本文基于android13-release源码浏览整顿
零碎源码地址:init.h - Android Code Search
1.前言
紧接上篇[Android零碎Launcher启动流程)]咱们持续看看Launcher是如何运行并加载所有桌面利用,继而探索用户在launcher桌面点击App图标启动利用整体流程
2.Launcher运行及生命周期办法
相熟Android开发的同学在启动模拟器显示桌面后,咱们能够直观看到模拟器顶部搜寻框,工夫日历小部件,可拖拽利用区域,底部导航批示条以及快捷启动图标,利用文件夹等,基于零碎UI层级展现形式,咱们通过源码逐渐探寻其工作形式.上面咱们从onCreate()函数开始
源码地位:packages/apps/Launcher3/src/com/android/launcher3/Launcher.java
2.1 Launcher.onCreate
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //获取LauncherAppState实例,次要解决IconCache,IconCacheProvider、LauncherModel对象初始化及凋谢对外调用办法 LauncherAppState app = LauncherAppState.getInstance(this); mOldConfig = new Configuration(getResources().getConfiguration()); //LauncherAppState中定义对外调用办法 mModel = app.getModel(); mRotationHelper = new RotationHelper(this); //依据屏幕宽高读取最靠近设施文件信息,用于桌面图标大小,行列数配置 InvariantDeviceProfile idp = app.getInvariantDeviceProfile(); initDeviceProfile(idp); idp.addOnChangeListener(this); //存储库SharePreferences mSharedPrefs = Utilities.getPrefs(this); mIconCache = app.getIconCache(); mAccessibilityDelegate = createAccessibilityDelegate(); //初始化拖拽布局控制器 mDragController = new LauncherDragController(this); //解决所有app在桌面拖拽图标时的动画 mAllAppsController = new AllAppsTransitionController(this); mStateManager = new StateManager < >(this, NORMAL); //关联存储库SharePreferences mOnboardingPrefs = createOnboardingPrefs(mSharedPrefs); //小部件治理helper mAppWidgetManager = new WidgetManagerHelper(this); mAppWidgetHost = createAppWidgetHost(); mAppWidgetHost.startListening(); //加载launcher xml inflateRootView(R.layout.launcher); //设置所有apps view,放在上面大节独自剖析 setupViews(); //淡入淡出动画 crossFadeWithPreviousAppearance(); //设置监听NotificationListener,PopupDataProvider次要解决长按app图标显示内容 mPopupDataProvider = new PopupDataProvider(this: :updateNotificationDots); //状态解决相干 boolean internalStateHandled = ACTIVITY_TRACKER.handleCreate(this); if (internalStateHandled) { if (savedInstanceState != null) { // InternalStateHandler has already set the appropriate state. // We dont need to do anything. savedInstanceState.remove(RUNTIME_STATE); } } restoreState(savedInstanceState); mStateManager.reapplyState(); if (savedInstanceState != null) { int[] pageIds = savedInstanceState.getIntArray(RUNTIME_STATE_CURRENT_SCREEN_IDS); if (pageIds != null) { mPagesToBindSynchronously = IntSet.wrap(pageIds); } } //LoaderTask相干操作,放在上面大节独自剖析 if (!mModel.addCallbacksAndLoad(this)) { if (!internalStateHandled) { Log.d(BAD_STATE, "Launcher onCreate not binding sync, prevent drawing"); // If we are not binding synchronously, pause drawing until initial bind complete, // so that the system could continue to show the device loading prompt mOnInitialBindListener = Boolean.FALSE: :booleanValue; } } // For handling default keys setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL); //设置页面布局 setContentView(getRootView()); if (mOnInitialBindListener != null) { getRootView().getViewTreeObserver().addOnPreDrawListener(mOnInitialBindListener); } getRootView().dispatchInsets(); //注册屏幕敞开播送监听 registerReceiver(mScreenOffReceiver, new IntentFilter(Intent.ACTION_SCREEN_OFF)); //更新UiState、Theme(Dark/Light) getSystemUiController().updateUiState(SystemUiController.UI_STATE_BASE_WINDOW, Themes.getAttrBoolean(this, R.attr.isWorkspaceDarkText)); //hook生命周期办法 if (mLauncherCallbacks != null) { mLauncherCallbacks.onCreate(savedInstanceState); } mOverlayManager = getDefaultOverlay(); PluginManagerWrapper.INSTANCE.get(this).addPluginListener(this, LauncherOverlayPlugin.class, false /* allowedMultiple */ ); //屏幕旋转切换配置初始化 mRotationHelper.initialize(); TraceHelper.INSTANCE.endSection(traceToken); mUserChangedCallbackCloseable = UserCache.INSTANCE.get(this).addUserChangeListener(() - >getStateManager().goToState(NORMAL)); if (Utilities.ATLEAST_R) { getWindow().setSoftInputMode(LayoutParams.SOFT_INPUT_ADJUST_NOTHING); } setTitle(R.string.home_screen);}
launcher类中onCreate()会初始化LauncherAppState实例,用于获取Icon/LauncherModel对象,读取设施文件信息以匹配桌面图标及行列数,初始化SharedPreferences,布局拖拽控制器,设置布局xml,apps view,以及LoaderTask相干操作,设置页面布局及其它配置信息,上面咱们来看看源码中setupViews()办法
2.2 Launcher.setupViews()
protected void setupViews() { //加载根布局 inflateRootView(R.layout.launcher); mDragLayer = findViewById(R.id.drag_layer); mFocusHandler = mDragLayer.getFocusIndicatorHelper(); mWorkspace = mDragLayer.findViewById(R.id.workspace); //初始化PageIndicator mWorkspace.initParentViews(mDragLayer); mOverviewPanel = findViewById(R.id.overview_panel); mHotseat = findViewById(R.id.hotseat); //设置快捷启动图标工作区 mHotseat.setWorkspace(mWorkspace); // Setup the drag layer mDragLayer.setup(mDragController, mWorkspace); //初始化DragController,更新layer type属性 mWorkspace.setup(mDragController); //绑定工作区之前锁定壁纸默认状态 mWorkspace.lockWallpaperToDefaultPage(); //初始化第一页并绑定,此处会以CellLayout承载页面,其自身继承于ViewGroup,反对对item拖入拖出操作 mWorkspace.bindAndInitFirstWorkspaceScreen(); //拖拽监听 mDragController.addDragListener(mWorkspace); // Get the search/delete/uninstall bar mDropTargetBar = mDragLayer.findViewById(R.id.drop_target_bar); // Setup Apps mAppsView = findViewById(R.id.apps_view); // Setup Scrim mScrimView = findViewById(R.id.scrim_view); // Setup the drag controller (drop targets have to be added in reverse order in priority) mDropTargetBar.setup(mDragController); //mAppsView设置mScrimView mAllAppsController.setupViews(mScrimView, mAppsView);}
以上办法初始化相干views并设置监听,上面咱们再看LoaderTask数据加载是如何进行的
源码门路:packages/apps/Launcher3/src/com/android/launcher3/LauncherModel.java
2.3 LoaderTask
public boolean addCallbacksAndLoad(@NonNull final Callbacks callbacks) { synchronized(mLock) { addCallbacks(callbacks); return startLoader(new Callbacks[] { callbacks }); }}private boolean startLoader(@NonNull final Callbacks[] newCallbacks) { // Enable queue before starting loader. It will get disabled in Launcher#finishBindingItems ItemInstallQueue.INSTANCE.get(mApp.getContext()).pauseModelPush(ItemInstallQueue.FLAG_LOADER_RUNNING); synchronized(mLock) { //进行LoaderTask工作线程 boolean wasRunning = stopLoader(); //设置相干标记 boolean bindDirectly = mModelLoaded && !mIsLoaderTaskRunning; boolean bindAllCallbacks = wasRunning || !bindDirectly || newCallbacks.length == 0; final Callbacks[] callbacksList = bindAllCallbacks ? getCallbacks() : newCallbacks; if (callbacksList.length > 0) { //同步工作执行时革除任意挂起绑定操作 for (Callbacks cb: callbacksList) { MAIN_EXECUTOR.execute(cb: :clearPendingBinds); } //构建loaderResults LoaderResults loaderResults = new LoaderResults(mApp, mBgDataModel, mBgAllAppsList, callbacksList); if (bindDirectly) { // Divide the set of loaded items into those that we are binding synchronously, // and everything else that is to be bound normally (asynchronously). loaderResults.bindWorkspace(bindAllCallbacks); // For now, continue posting the binding of AllApps as there are other // issues that arise from that. loaderResults.bindAllApps(); loaderResults.bindDeepShortcuts(); loaderResults.bindWidgets(); return true; } else { stopLoader(); //构建LoaderTask工作并筹备执行 mLoaderTask = new LoaderTask(mApp, mBgAllAppsList, mBgDataModel, mModelDelegate, loaderResults); // Always post the loader task, instead of running directly // (even on same thread) so that we exit any nested synchronized blocks //通过handler公布mLoaderTask,但不以內联形式运行 MODEL_EXECUTOR.post(mLoaderTask); } } } return false;}
通过下面代码调用链,此时mLoaderTask曾经公布,咱们看下LoaderTask.run()具体执行内容有哪些
public void run() { ... ... LoaderMemoryLogger memoryLogger = new LoaderMemoryLogger(); try (LauncherModel.LoaderTransaction transaction = mApp.getModel().beginLoader(this)) { List < ShortcutInfo > allShortcuts = new ArrayList < >(); try { //加载工作区 loadWorkspace(allShortcuts, memoryLogger); } finally { Trace.endSection(); } ... //绑定工作区 mResults.bindWorkspace(true /* incrementBindId */); mModelDelegate.workspaceLoadComplete(); //发送首屏播送告诉,告诉软件安装包在首屏无效装置 sendFirstScreenActiveInstallsBroadcast(); //期待workspace加载实现 waitForIdle(); ... List < LauncherActivityInfo > allActivityList; try { //加载所有apps,从缓存读取user profiles,清空利用列表,依据profile读取所有LauncherActivityInfo,最终增加进缓存汇合 allActivityList = loadAllApps(); } finally { Trace.endSection(); } ... //绑定所有apps mResults.bindAllApps(); ... //获取解决图标缓存更新handler IconCacheUpdateHandler updateHandler = mIconCache.getUpdateHandler(); setIgnorePackages(updateHandler); updateHandler.updateIcons(allActivityList, LauncherActivityCachingLogic.newInstance(mApp.getContext()), mApp.getModel() : :onPackageIconsUpdated); ... //缓存allShortcuts updateHandler.updateIcons(allShortcuts, new ShortcutCachingLogic(), mApp.getModel() : :onPackageIconsUpdated); //期待上述步骤操作实现 waitForIdle(); ... //加载应用程序快捷方式 List < ShortcutInfo > allDeepShortcuts = loadDeepShortcuts(); ... //绑定利用快捷启动形式 mResults.bindDeepShortcuts(); ... //缓存allDeepShortcuts updateHandler.updateIcons(allDeepShortcuts, new ShortcutCachingLogic(), (pkgs, user) - >{}); //期待上述步骤操作实现 waitForIdle(); ... //加载桌面小部件allWidgetsList List < ComponentWithLabelAndIcon > allWidgetsList = mBgDataModel.widgetsModel.update(mApp, null); ... //绑定桌面小部件 mResults.bindWidgets(); ... //缓存小部件图标 updateHandler.updateIcons(allWidgetsList, new ComponentWithIconCachingLogic(mApp.getContext(), true), mApp.getModel() : :onWidgetLabelsUpdated); ... //加载桌面文件夹名称 loadFolderNames(); ... //解决实现 updateHandler.finish(); mModelDelegate.modelLoadComplete(); transaction.commit(); memoryLogger.clearLogs(); } catch(CancellationException e) { // Loader stopped, ignore logASplit(logger, "Cancelled"); } catch(Exception e) { memoryLogger.printLogs(); throw e; } finally { logger.dumpToLog(); } TraceHelper.INSTANCE.endSection(traceToken);}
在LoaderTask.run()中能够清晰看到加载数据的每一步操作,基于此launcher桌面利用相干信息根本加载实现,Launcher类自身继承于StatefulActivity,其生命周期办法与惯例Activity基本一致,感兴趣的可持续在源码外面查看相干办法具体解决内容
3.点击桌面图标启动App
3.1 bindWorkspace与createShortcut
上述步骤中在loadWorkspace()之后紧接着调用bindWorkpsace(),用于将所有加载数据绑定到主线程上的理论视图
public void bindWorkspace(boolean incrementBindId) { ... ... for (Callbacks cb: mCallbacksList) { new WorkspaceBinder(cb, mUiExecutor, mApp, mBgDataModel, mMyBindingId, workspaceItems, appWidgets, extraItems, orderedScreenIds).bind(); }}
次要看下bind()办法,会持续调用bindWorkspaceItems(),用于最终callback调用bindItems,此处callback对象为launcher实例,Launcher中定义了bindItems()
//该办法中会循环调用view = createShortcut(info)创立view,createShortcut()也同样定义在Launcher类中,
private void bindWorkspaceItems(final ArrayList < ItemInfo > workspaceItems, final Executor executor) { // Bind the workspace items int count = workspaceItems.size(); for (int i = 0; i < count; i += ITEMS_CHUNK) { final int start = i; final int chunkSize = (i + ITEMS_CHUNK <= count) ? ITEMS_CHUNK: (count - i); executeCallbacksTask(c - >c.bindItems(workspaceItems.subList(start, start + chunkSize), false), executor); }}//创立shortcutpublic View createShortcut(ViewGroup parent, WorkspaceItemInfo info) { BubbleTextView favorite = (BubbleTextView) LayoutInflater.from(parent.getContext()).inflate(R.layout.app_icon, parent, false); favorite.applyFromWorkspaceItem(info); //设置图标点击事件,ItemClickHandler用于解决对工作区和所有利用点击响应 favorite.setOnClickListener(ItemClickHandler.INSTANCE); favorite.setOnFocusChangeListener(mFocusHandler); return favorite;}//点击事件响应private static void onClick(View v) { ... ... Object tag = v.getTag(); //起源来为WorkspaceItemInfo, if (tag instanceof WorkspaceItemInfo) { //持续调用startAppShortcutOrInfoActivity(v, shortcut, launcher)用于启动activity onClickAppShortcut(v, (WorkspaceItemInfo) tag, launcher); } ... ...}//启动activityprivate static void startAppShortcutOrInfoActivity(View v, ItemInfo item, Launcher launcher) { //构建intent Intent intent; if (item instanceof ItemInfoWithIcon && (((ItemInfoWithIcon) item).runtimeStatusFlags & ItemInfoWithIcon.FLAG_INSTALL_SESSION_ACTIVE) != 0) { ItemInfoWithIcon appInfo = (ItemInfoWithIcon) item; intent = new PackageManagerHelper(launcher) .getMarketIntent(appInfo.getTargetComponent().getPackageName()); } else { intent = item.getIntent(); } ... if (item instanceof WorkspaceItemInfo) { WorkspaceItemInfo si = (WorkspaceItemInfo) item; if (si.hasStatusFlag(WorkspaceItemInfo.FLAG_SUPPORTS_WEB_UI) && Intent.ACTION_VIEW.equals(intent.getAction())) {the // web ui. This only works though if the package isn't set intent = new Intent(intent); intent.setPackage(null); } if ((si.options & WorkspaceItemInfo.FLAG_START_FOR_RESULT) != 0) { launcher.startActivityForResult(item.getIntent(), 0); InstanceId instanceId = new InstanceIdSequence().newInstanceId(); launcher.logAppLaunch(launcher.getStatsLogManager(), item, instanceId); return; } } ... //启动activity launcher.startActivitySafely(v, intent, item); }}
通过startActivitySafely启动activity,咱们须要看下Launcher继承关系,
Launcher->StatefulActivity->BaseDraggingActivity->BaseActivity implements AppLauncher,
所以launcher.startActivitySafely最终是调用AppLauncher接口中的同名办法,该办法会构建利用启动须要的显示
的宽高参数、animation、displayId,封装到Bundle对象中,最初调用startShortcut(),办法源码如下:
3.2 startShortcut
default void startShortcut(String packageName, String id, Rect sourceBounds, Bundle startActivityOptions, UserHandle user) { if (GO_DISABLE_WIDGETS) { return; } try { ((Context) this).getSystemService(LauncherApps.class).startShortcut(packageName, id, sourceBounds, startActivityOptions, user); } catch(SecurityException | IllegalStateException e) { Log.e(TAG, "Failed to start shortcut", e); }}//通过一系列参数解决最终走到LauncherApps.java中,源码地位:frameworks/base/core/java/android/content/pm/LauncherApps.java@UnsupportedAppUsage private void startShortcut(@NonNull String packageName, @NonNull String shortcutId, @Nullable Rect sourceBounds, @Nullable Bundle startActivityOptions, int userId) { try { //此处mService对应LauncherAppsImpl实现类,通过aidl定义实现用于跨过程通信 final boolean success = mService.startShortcut(mContext.getPackageName(), packageName, null /* default featureId */ , shortcutId, sourceBounds, startActivityOptions, userId); if (!success) { throw new ActivityNotFoundException("Shortcut could not be started"); } } catch(RemoteException e) { throw e.rethrowFromSystemServer(); }}
@SystemService(Context.LAUNCHER_APPS_SERVICE)通过注解标记零碎服务,当作用于类是可便捷获取其服务实例,此处LAUNCHER_APPS_SERVICE对应实例类LauncherAppService.java类
在被注解的LauncherApps类可通过context.getSystemService获取,具体代码位于该类构造函数中;LauncherAppsService构造函数初始化了LauncherAppsImpl实例,在onStart启动服务办法中公布了LAUNCHER_APPS_SERVICE标记服务
LauncherAppsImpl实例中定义了startShortcut()办法,最终调用startShortcutInner()验证调用包,用户是否有权限拜访配置文件以及异步创立快捷方式启动intent,并配置intent启动标记,源边界及Splash theme,最初调用startShortcutIntentsAsPublisher()启动activity,
3.3 startShortcutInner
其源码如下
//源码地位:/frameworks/base/services/core/java/com/android/server/pm/LauncherAppsService.javaprivate boolean startShortcutInner(int callerUid, int callerPid, int callingUserId, String callingPackage, String packageName, String featureId, String shortcutId, Rect sourceBounds, Bundle startActivityOptions, int targetUserId) { verifyCallingPackage(callingPackage, callerUid); if (!canAccessProfile(targetUserId, "Cannot start activity")) { return false; } if (!mShortcutServiceInternal.isPinnedByCaller(callingUserId, callingPackage, packageName, shortcutId, targetUserId)) { ensureShortcutPermission(callerUid, callerPid, callingPackage); } final AndroidFuture < Intent[] > ret = new AndroidFuture < >(); Intent[] intents; mShortcutServiceInternal.createShortcutIntentsAsync(getCallingUserId(), callingPackage, packageName, shortcutId, targetUserId, injectBinderCallingPid(), injectBinderCallingUid(), ret); try { intents = ret.get(); } catch(InterruptedException | ExecutionException e) { return false; } if (intents == null || intents.length == 0) { return false; } ActivityOptions options = ActivityOptions.fromBundle(startActivityOptions); if (options != null && options.isApplyActivityFlagsForBubbles()) { // Flag for bubble to make behaviour match documentLaunchMode=always. intents[0].addFlags(FLAG_ACTIVITY_NEW_DOCUMENT); intents[0].addFlags(FLAG_ACTIVITY_MULTIPLE_TASK); } intents[0].addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intents[0].setSourceBounds(sourceBounds); final String splashScreenThemeResName = mShortcutServiceInternal.getShortcutStartingThemeResName(callingUserId, callingPackage, packageName, shortcutId, targetUserId); if (splashScreenThemeResName != null && !splashScreenThemeResName.isEmpty()) { if (startActivityOptions == null) { startActivityOptions = new Bundle(); } startActivityOptions.putString(KEY_SPLASH_SCREEN_THEME, splashScreenThemeResName); } return startShortcutIntentsAsPublisher(intents, packageName, featureId, startActivityOptions, targetUserId);}private boolean startShortcutIntentsAsPublisher(@NonNull Intent[] intents, @NonNull String publisherPackage, @Nullable String publishedFeatureId, Bundle startActivityOptions, int userId) { final int code; try { //mActivityTaskManagerInternal - ActivityTaskManagerService的外部抽象类 code = mActivityTaskManagerInternal.startActivitiesAsPackage(publisherPackage, publishedFeatureId, userId, intents, startActivityOptions); if (ActivityManager.isStartResultSuccessful(code)) { return true; // Success } else { Log.e(TAG, "Couldn't start activity, code=" + code); } return false; } catch(SecurityException e) { if (DEBUG) { Slog.d(TAG, "SecurityException while launching intent", e); } return false; }}
在LauncherAppsImpl构造函数中,会通过LocalServices.getService(ActivityTaskManagerInternal.class)获取ActivityTaskManagerInternal实例
那该实例何时被增加进去的呢,这个就须要看ActivityTaskManagerService中的start()办法,其中定义了外部类LocalService继承于ActivityTaskManagerInternal抽象类,最终调用
startActivitiesAsPackage()
//源码地位:/frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java@Override public int startActivitiesAsPackage(String packageName, @Nullable String featureId, int userId, Intent[] intents, Bundle bOptions) { Objects.requireNonNull(intents, "intents"); final String[] resolvedTypes = new String[intents.length]; // UID of the package on user userId. // "= 0" is needed because otherwise catch(RemoteException) would make it look like // packageUid may not be initialized. int packageUid = 0; final long ident = Binder.clearCallingIdentity(); try { for (int i = 0; i < intents.length; i++) { resolvedTypes[i] = intents[i].resolveTypeIfNeeded(mContext.getContentResolver()); } packageUid = AppGlobals.getPackageManager().getPackageUid(packageName, PackageManager.MATCH_DEBUG_TRIAGED_MISSING, userId); } catch(RemoteException e) { // Shouldn't happen. } finally { Binder.restoreCallingIdentity(ident); } return getActivityStartController().startActivitiesInPackage(packageUid, packageName, featureId, intents, resolvedTypes, null /* resultTo */ , SafeActivityOptions.fromBundle(bOptions), userId, false /* validateIncomingUser */ , null /* originatingPendingIntent */ , false /* allowBackgroundActivityStart */ );}
能够看到最重要的一行:getActivityStartController().startActivitiesInPackage()交由ActivityStartController治理启动activity相干操作,在上一篇博文中
7.AMS.systemReady办法启动Launcher也会波及ActivityStartController执行executeRequest,
3.4 startActivitiesInPackage
咱们持续看下调用办法源码,
//源码地位:/frameworks/base/services/core/java/com/android/server/wm/ActivityStartController.javafinal int startActivitiesInPackage(int uid, int realCallingPid, int realCallingUid, String callingPackage, @Nullable String callingFeatureId, Intent[] intents, String[] resolvedTypes, IBinder resultTo, SafeActivityOptions options, int userId, boolean validateIncomingUser, PendingIntentRecord originatingPendingIntent, boolean allowBackgroundActivityStart) { final String reason = "startActivityInPackage"; //校验指标用户id,并保障不是非凡用户 userId = checkTargetUser(userId, validateIncomingUser, Binder.getCallingPid(), Binder.getCallingUid(), reason); //筹备启动 return startActivities(null, uid, realCallingPid, realCallingUid, callingPackage, callingFeatureId, intents, resolvedTypes, resultTo, options, userId, reason, originatingPendingIntent, allowBackgroundActivityStart);}//最终调用启动办法int startActivities(IApplicationThread caller, int callingUid, int incomingRealCallingPid, int incomingRealCallingUid, String callingPackage, @Nullable String callingFeatureId, Intent[] intents, String[] resolvedTypes, IBinder resultTo, SafeActivityOptions options, int userId, String reason, PendingIntentRecord originatingPendingIntent, boolean allowBackgroundActivityStart) { ... ... try { intents = ArrayUtils.filterNotNull(intents, Intent[] : :new); ... ... final IBinder sourceResultTo = resultTo; final ActivityRecord[] outActivity = new ActivityRecord[1]; // Lock the loop to ensure the activities launched in a sequence. synchronized(mService.mGlobalLock) { mService.deferWindowLayout(); // To avoid creating multiple starting window when creating starting multiples // activities, we defer the creation of the starting window once all start request // are processed mService.mWindowManager.mStartingSurfaceController.beginDeferAddStartingWindow(); try { for (int i = 0; i < starters.length; i++) { final int startResult = starters[i].setResultTo(resultTo).setOutActivity(outActivity).execute(); if (startResult < START_SUCCESS) { // Abort by error result and recycle unused starters. for (int j = i + 1; j < starters.length; j++) { mFactory.recycle(starters[j]); } return startResult; } final ActivityRecord started = outActivity[0]; if (started != null && started.getUid() == filterCallingUid) { // Only the started activity which has the same uid as the source caller // can be the caller of next activity. resultTo = started.token; } else { resultTo = sourceResultTo; // Different apps not adjacent to the caller are forced to be new task. if (i < starters.length - 1) { starters[i + 1].getIntent().addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); } } } } finally { mService.mWindowManager.mStartingSurfaceController.endDeferAddStartingWindow(options != null ? options.getOriginalOptions() : null); mService.continueWindowLayout(); } } } finally { Binder.restoreCallingIdentity(origId); } return START_SUCCESS;}
在下面办法中通过对ActivityStarter数组循环执行启动activity申请,execute()最终调用该类int execute()办法,后续调用流程就跟startHomeActivity()统一,具体阐明参见上一篇博文中
7.AMS.systemReady办法以及后续章节源码阐明
4.利用内启动startActivity()
以Activity.startActivity()为例,
//启动activitypublic void startActivity(Intent intent, @Nullable Bundle options) { if (mIntent != null && mIntent.hasExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN) && mIntent.hasExtra(AutofillManager.EXTRA_RESTORE_CROSS_ACTIVITY)) { if (TextUtils.equals(getPackageName(), intent.resolveActivity(getPackageManager()).getPackageName())) { // Apply Autofill restore mechanism on the started activity by startActivity() final IBinder token = mIntent.getIBinderExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN); // Remove restore ability from current activity mIntent.removeExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN); mIntent.removeExtra(AutofillManager.EXTRA_RESTORE_CROSS_ACTIVITY); // Put restore token intent.putExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN, token); intent.putExtra(AutofillManager.EXTRA_RESTORE_CROSS_ACTIVITY, true); } } if (options != null) { startActivityForResult(intent, -1, options); } else { // Note we want to go through this call for compatibility with // applications that may have overridden the method. startActivityForResult(intent, -1); }}//startActivityForResultpublic void startActivityForResult(@RequiresPermission Intent intent, int requestCode, @Nullable Bundle options) { if (mParent == null) { options = transferSpringboardActivityOptions(options); //Instrumentation.execStartActivity Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity(this, mMainThread.getApplicationThread(), mToken, this, intent, requestCode, options); ... ... } else { ... ... }}//Instrumentation.execStartActivitypublic ActivityResult execStartActivity(Context who, IBinder contextThread, IBinder token, Activity target, Intent intent, int requestCode, Bundle options) { ... //参数及监控相干解决 ... try { ... //此处getService 返回IActivityTaskManager抽象类,理论被ActivityTaskManagerService实现 int result = ActivityTaskManager.getService().startActivity(whoThread, who.getBasePackageName(), who.getAttributionTag(), intent, intent.resolveTypeIfNeeded(who.getContentResolver()), token, target != null ? target.mEmbeddedID: null, requestCode, 0, null, options); //校验启动后果是否胜利 checkStartActivityResult(result, intent); } catch(RemoteException e) { throw new RuntimeException("Failure from system", e); } return null;}//ActivityTaskManagerService.startActivity//源码地位:/frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java@Override public final int startActivity(IApplicationThread caller, String callingPackage, String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) { return startActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType, resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions, UserHandle.getCallingUserId());}//startActivityAsUserprivate int startActivityAsUser(IApplicationThread caller, String callingPackage, @Nullable String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId, boolean validateIncomingUser) { ... ... //此处getActivityStartController()返回ActivityStartController对象,调用obtainStarter理论调用ActivityStarter,通过execute()执行启动申请 return getActivityStartController().obtainStarter(intent, "startActivityAsUser").setCaller(caller).setCallingPackage(callingPackage).setCallingFeatureId(callingFeatureId).setResolvedType(resolvedType).setResultTo(resultTo).setResultWho(resultWho).setRequestCode(requestCode).setStartFlags(startFlags).setProfilerInfo(profilerInfo).setActivityOptions(bOptions).setUserId(userId).execute();}//调用execute()最终执行executeRequest()启动,源码门路:/frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
- execute()办法解决Activity启动申请,进入到
- executeRequest(mRequest);执行执行一系列权限查看,进入到
- startActivityUnchecked()校验初步权限查看是否实现,进入到
- startActivityInner()启动 Activity,并确定是否将activity增加到栈顶,进入到
- startActivityLocked()判断以后activity是否可见以及是否须要为其新建Task,并将ActivityRecord退出到Task栈顶中,进入到
- resumeFocusedTasksTopActivities() - RootWindowContainer.java ,次要判断targetRootTask是否处于栈顶,同时判断task是否处于暂停状态,进入到
- resumeTopActivityUncheckedLocked() - Task.java,递归调用该办法并查找栈顶可显示activity以及状态是否暂停,进入到
- resumeTopActivityInnerLocked() - Task.java,该办法次要解决ActivityRecord、设置resume状态、筹备启动activity,进入到
- resumeTopActivity() - TaskFragment.java,查找栈顶activity是否处于running,查看所有暂停操作是否实现,进入到
- startSpecificActivity() - ActivityTaskSupervisor.java,如果activity已运行则间接启动,未运行则启动指标Activity,开启启动新过程,进入到
realStartActivityLocked() - ActivityTaskManagerService.java,因为Activity.startActivity()在调用前过程已创立,所以分支走到这里
boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc, boolean andResume, boolean checkConfig) throws RemoteException { ... try { ... try { ... //创立activity启动事务 final ClientTransaction clientTransaction = ClientTransaction.obtain(proc.getThread(), r.token); //判断activity是否是前向转换,即从一个Activity转换到另一个Activity,后者在工作栈中的地位比前者更靠前 final boolean isTransitionForward = r.isTransitionForward(); //获取IBinder对象 final IBinder fragmentToken = r.getTaskFragment().getFragmentToken(); //将蕴含activity回调(蕴含生命周期申请/回调)增加到音讯汇合开端 clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent), System.identityHashCode(r), r.info, // TODO: Have this take the merged configuration instead of separate global // and override configs. mergedConfiguration.getGlobalConfiguration(), mergedConfiguration.getOverrideConfiguration(), r.compat, r.getFilteredReferrer(r.launchedFromPackage), task.voiceInteractor, proc.getReportedProcState(), r.getSavedState(), r.getPersistentSavedState(), results, newIntents, r.takeOptions(), isTransitionForward, proc.createProfilerInfoIfNeeded(), r.assistToken, activityClientController, r.shareableActivityToken, r.getLaunchedFromBubble(), fragmentToken)); //设置生命周期状态申请 final ActivityLifecycleItem lifecycleItem; if (andResume) { lifecycleItem = ResumeActivityItem.obtain(isTransitionForward); } else { lifecycleItem = PauseActivityItem.obtain(); } clientTransaction.setLifecycleStateRequest(lifecycleItem); //获取ClientLifecycleManager对象,执行事务 mService.getLifecycleManager().scheduleTransaction(clientTransaction); } ... } ...}
ClientLifecycleManager.scheduleTransaction()最终调用ClientTransaction.java中的shedule()办法
该办法将客户端事务退出到零碎事务队列中,并按程序执行preExecute实现前置工作,发送事务message,调用TransactionExecutor.execute()执行所有回调及生命周期转换
mClient对象为IApplicationThread,这是aidl接口,其理论执行对象为ActivityThread,继承于ClientTransactionHandler,外部也实例化TransactionExecutor对象,
public void schedule() throws RemoteException { mClient.scheduleTransaction(this);}//最终调用ActivityThread.scheduleTransaction(),重写了父类ClientTransactionHandler.scheduleTransaction(),执行transaction操作@Override public void scheduleTransaction(ClientTransaction transaction) throws RemoteException { ActivityThread.this.scheduleTransaction(transaction);}void scheduleTransaction(ClientTransaction transaction) { transaction.preExecute(this); //发送handle message sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);}
咱们接着看下ActivityThread handleMessage() - case EXECUTE_TRANSACTION
case EXECUTE_TRANSACTION: //获取message final ClientTransaction transaction = (ClientTransaction) msg.obj; //执行 mTransactionExecutor.execute(transaction); if (isSystem()) { //零碎过程內的事务在客户端回收掉 transaction.recycle(); } // TODO(lifecycler): Recycle locally scheduled transactions. break;//TransactionExecutor.execute()public void execute(ClientTransaction transaction) { ... //循环执行回调申请 executeCallbacks(transaction); //执行生命周期回调 executeLifecycleState(transaction); ...}
- executeLifecycleState()会调用cycleToPath()用于在状态之间转换客户端, 进入到
- performLifecycleSequence() ,通过之前初始化的状态转换客户端,此时状态走到ON_CREATE,进入到
- handleLaunchActivity() - ClientTransactionHandler.java,该类为抽象类,具体实现在ActivityThread中,
- ActivityThread.handleLaunchActivity() ,筹备执行启动,进入到
performLaunchActivity() , 启动activity的外围实现办法,次要解决查看包信息,组件名称,Context,组装classLoader,调用mInstrumentation.newActivity()
//启动activity外围实现办法private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) { ActivityInfo aInfo = r.activityInfo; //校验包信息 if (r.packageInfo == null) { r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo, Context.CONTEXT_INCLUDE_CODE); } //校验启动组件信息 ComponentName component = r.intent.getComponent(); if (component == null) { component = r.intent.resolveActivity(mInitialApplication.getPackageManager()); r.intent.setComponent(component); } if (r.activityInfo.targetActivity != null) { component = new ComponentName(r.activityInfo.packageName, r.activityInfo.targetActivity); } //创立context ContextImpl appContext = createBaseContextForActivity(r); Activity activity = null; try { //获取ClassLoader - /frameworks/base/core/java/android/app/ContextImpl.java java.lang.ClassLoader cl = appContext.getClassLoader(); //实例化activity,反射生成 activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent); StrictMode.incrementExpectedActivityCount(activity.getClass()); r.intent.setExtrasClassLoader(cl); r.intent.prepareToEnterProcess(isProtectedComponent(r.activityInfo), appContext.getAttributionSource()); if (r.state != null) { r.state.setClassLoader(cl); } } catch(Exception e) { if (!mInstrumentation.onException(activity, e)) { throw new RuntimeException("Unable to instantiate activity " + component + ": " + e.toString(), e); } } try { //获取Application,默认从缓存获取,不存在通过Instrumentation.newApplication()创立新的返回,同时回调Application.onCreate() Application app = r.packageInfo.makeApplicationInner(false, mInstrumentation); if (localLOGV) Slog.v(TAG, "Performing launch of " + r); if (localLOGV) Slog.v(TAG, r + ": app=" + app + ", appName=" + app.getPackageName() + ", pkg=" + r.packageInfo.getPackageName() + ", comp=" + r.intent.getComponent().toShortString() + ", dir=" + r.packageInfo.getAppDir()); // updatePendingActivityConfiguration() reads from mActivities to update // ActivityClientRecord which runs in a different thread. Protect modifications to // mActivities to avoid race. synchronized(mResourcesManager) { mActivities.put(r.token, r); } if (activity != null) { CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager()); Configuration config = new Configuration(mConfigurationController.getCompatConfiguration()); if (r.overrideConfig != null) { config.updateFrom(r.overrideConfig); } if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity " + r.activityInfo.name + " with config " + config); //设置Window Window window = null; if (r.mPendingRemoveWindow != null && r.mPreserveWindow) { window = r.mPendingRemoveWindow; r.mPendingRemoveWindow = null; r.mPendingRemoveWindowManager = null; } //初始化Activity resources // Activity resources must be initialized with the same loaders as the // application context. appContext.getResources().addLoaders(app.getResources().getLoaders().toArray(new ResourcesLoader[0])); //设置以后context appContext.setOuterContext(activity); //调用activity attach办法 activity.attach(appContext, this, getInstrumentation(), r.token, r.ident, app, r.intent, r.activityInfo, title, r.parent, r.embeddedID, r.lastNonConfigurationInstances, config, r.referrer, r.voiceInteractor, window, r.activityConfigCallback, r.assistToken, r.shareableActivityToken); //设置activity intent if (customIntent != null) { activity.mIntent = customIntent; } r.lastNonConfigurationInstances = null; //期待网络规定更新 - ActivityManagerService.waitForNetworkStateUpdate() checkAndBlockForNetworkAccess(); activity.mStartedActivity = false; //设置主题theme int theme = r.activityInfo.getThemeResource(); if (theme != 0) { activity.setTheme(theme); } if (r.mActivityOptions != null) { activity.mPendingOptions = r.mActivityOptions; r.mActivityOptions = null; } activity.mLaunchedFromBubble = r.mLaunchedFromBubble; activity.mCalled = false; // Assigning the activity to the record before calling onCreate() allows // ActivityThread#getActivity() lookup for the callbacks triggered from // ActivityLifecycleCallbacks#onActivityCreated() or // ActivityLifecycleCallback#onActivityPostCreated(). r.activity = activity; //开始回调activity.onCreate() if (r.isPersistable()) { mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState); } else { mInstrumentation.callActivityOnCreate(activity, r.state); } if (!activity.mCalled) { throw new SuperNotCalledException("Activity " + r.intent.getComponent().toShortString() + " did not call through to super.onCreate()"); } mLastReportedWindowingMode.put(activity.getActivityToken(), config.windowConfiguration.getWindowingMode()); } r.setState(ON_CREATE); } catch(SuperNotCalledException e) { throw e; } catch(Exception e) { if (!mInstrumentation.onException(activity, e)) { throw new RuntimeException("Unable to start activity " + component + ": " + e.toString(), e); } } //返回activity实例 return activity;}
5.小结
在startActivity()调用启动中,Instrumentation类表演非常重要的角色,该类中定义了一系列call办法,监控着activity生命周期办法以及application.onCreate()、execStartActivity()等,用来解决利用和零碎过程所有交互,在Android插件化相干解决中,也能够看到hook instrumentation相干操作,理解源码调用流程也能帮忙咱们找到适合的切入点
6.文档阐明
因为源码流程较长,整体调用链十分繁冗,可能存在错漏的中央,欢送在浏览时提出问题和有余
参考文档:
Android Code Search
/ - OpenGrok cross reference for / (aospxref.com)