Launcher启动流程
1.SystemServer.java
在SystemServer会调用startOtherService():
private void startOtherServices() { …… mActivityManagerService.systemReady(() -> { Slog.i(TAG, "Making services ready"); traceBeginAndSlog("StartActivityManagerReadyPhase"); mSystemServiceManager.startBootPhase( SystemService.PHASE_ACTIVITY_MANAGER_READY); traceEnd(); traceBeginAndSlog("StartObservingNativeCrashes"); try { mActivityManagerService.startObservingNativeCrashes(); } catch (Throwable e) { reportWtf("observing native crashes", e); } …… }, BOOT_TIMINGS_TRACE_LOG); }
这中间用了Lambda表达式,我理解就是表达式中执行的过程作为调用systemReady的第一个参数,BOOT_TIMINGS_TRACE_LOG作为第二个参数。这个里面可以看到执行了一堆后执行了ActivityManagerService的systemReady方法
2.ActivityManagerService.java
看一下ActivityManagerService里的systemReady方法:
public void systemReady(final Runnable goingCallback, BootTimingsTraceLog traceLog) { traceLog.traceBegin("PhaseActivityManagerReady"); …… synchronized (this) { …… mStackSupervisor.resumeFocusedStackTopActivityLocked(); mUserController.sendUserSwitchBroadcastsLocked(-1, currentUserId); …… } }
这里面调用了resumeFocusedStackTopActivityLocked方法
3.ActivityStackSupervisor.java
这个类主要管理ActivityStack:
boolean resumeFocusedStackTopActivityLocked() { return resumeFocusedStackTopActivityLocked(null, null, null); } boolean resumeFocusedStackTopActivityLocked( ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) { if (targetStack != null && isFocusedStack(targetStack)) { return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions); } final ActivityRecord r = mFocusedStack.topRunningActivityLocked(); if (r == null || r.state != RESUMED) { mFocusedStack.resumeTopActivityUncheckedLocked(null, null); } else if (r.state == RESUMED) { // Kick off any lingering app transitions form the MoveTaskToFront operation. mFocusedStack.executeAppTransition(targetOptions); } return false; }
在没有参数的resumeFocusedStackTopActivityLocked直接return了有参数的resumeFocusedStackTopActivityLocked,参数传入三个null
在resumeFocusedStackTopActivityLocked里面看出调用了resumeTopActivityUncheckedLocked方法。
4.ActivityStack.java
看下ActivityStack的resumeTopActivityUncheckedLocked方法:
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) { …… boolean result = false; try { mStackSupervisor.inResumeTopActivity = true; result = resumeTopActivityInnerLocked(prev, options); } finally { mStackSupervisor.inResumeTopActivity = false; } mStackSupervisor.checkReadyForSleepLocked(); return result; }
在这里面直接调用了resumeTopActivityInnerLocked方法:
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) { …… return isOnHomeDisplay() && mStackSupervisor.resumeHomeStackTask(prev, "prevFinished"); …… }
这里又回到了ActivityStackSupervisor的resumeHomeStackTask方法:
5.ActivityStackSupervisor.java
boolean resumeHomeStackTask(ActivityRecord prev, String reason) { if (!mService.mBooting && !mService.mBooted) { // Not ready yet! return false; } if (prev != null) { prev.getTask().setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE); } mHomeStack.moveHomeStackTaskToTop(); ActivityRecord r = getHomeActivity(); final String myReason = reason + " resumeHomeStackTask"; // Only resume home activity if isn't finishing. if (r != null && !r.finishing) { moveFocusableActivityStackToFrontLocked(r, myReason); return resumeFocusedStackTopActivityLocked(mHomeStack, prev, null); } return mService.startHomeActivityLocked(mCurrentUser, myReason); }
函数最后会调到mService的startHomeActivityLocked函数,这个mService就是ActivityManagerService
6.ActivityManagerService.java
boolean startHomeActivityLocked(int userId, String reason) { // 判断是否是工厂模式和mTopAction是否存在 if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL && mTopAction == null) { return false; } // 获取home intent(launcher) Intent intent = getHomeIntent(); ActivityInfo aInfo = resolveActivityInfo(intent, STOCK_PM_FLAGS, userId); if (aInfo != null) { intent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name)); aInfo = new ActivityInfo(aInfo); aInfo.applicationInfo = getAppInfoForUser(aInfo.applicationInfo, userId); ProcessRecord app = getProcessRecordLocked(aInfo.processName, aInfo.applicationInfo.uid, true); // 如果当前launcher还没有启动就开始启动 if (app == null || app.instr == null) { intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK); final int resolvedUserId = UserHandle.getUserId(aInfo.applicationInfo.uid); final String myReason = reason + ":" + userId + ":" + resolvedUserId; // 启动launcher mActivityStarter.startHomeActivityLocked(intent, aInfo, myReason); } } else { Slog.wtf(TAG, "No home screen found for " + intent, new Throwable()); } return true; }
mFactoryTest代表系统的运行模式,系统的运行模式分为三种,分别是非工厂模式、低级工厂模式和高级工厂模式,mTopAction则用来描述第一个被启动Activity组件的Action,它的值为Intent.ACTION_MAIN。因此上面的代码意思就是mFactoryTest为FactoryTest.FACTORY_TEST_LOW_LEVEL(低级工厂模式)并且mTopAction=null时,直接返回false
getHomeIntent函数:
Intent getHomeIntent() { // 根据传入的mTopAction数据生成intent Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null); intent.setComponent(mTopComponent); intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING); if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) { // 添加匹配为CATEGORY_HOME intent.addCategory(Intent.CATEGORY_HOME); } return intent; }
最后确定Launcher是通过Intent.CATEGORY_HOME来匹配的
AndroidManifest.xml:
<activity android:name="com.android.launcher3.Launcher" android:launchMode="singleTask" android:clearTaskOnLaunch="true" android:stateNotNeeded="true" android:windowSoftInputMode="adjustPan|stateUnchanged" android:screenOrientation="nosensor" android:configChanges="keyboard|keyboardHidden|navigation" android:resizeableActivity="true" android:resumeWhilePausing="true" android:taskAffinity="" android:enabled="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.HOME" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.MONKEY"/> </intent-filter> </activity>
这样就启动Launcher
因此,如果要开机启动一个替换Launcher的程序,只要在程序<intent-filter>里面加入action.MAIN 、category.HOME、category.DEFAULT就可以。如果出现多个程序都加入这种intent,系统会弹出让你选择哪个作为启动器
Launcher2和Launcher3区别,Launcher3是从android 4.几开始的,现在默认都是加载Launcher3:
<activity android:name="com.android.launcher3.Launcher" android:launchMode="singleTask" android:clearTaskOnLaunch="true" android:stateNotNeeded="true" android:windowSoftInputMode="adjustPan" android:screenOrientation="unspecified" android:configChanges="keyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenSize|screenLayout|smallestScreenSize" android:resizeableActivity="true" android:resumeWhilePausing="true" android:taskAffinity="" android:enabled="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.HOME" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.MONKEY"/> <category android:name="android.intent.category.LAUNCHER_APP" /> </intent-filter> </activity>
Launcher2 :
<application android:name="com.android.launcher2.LauncherApplication" android:label="@string/application_name" android:icon="@mipmap/ic_launcher_home" android:hardwareAccelerated="true" android:largeHeap="@bool/config_largeHeap" android:supportsRtl="true"> <activity android:name="com.android.launcher2.Launcher" android:launchMode="singleTask" android:clearTaskOnLaunch="true" android:stateNotNeeded="true" android:resumeWhilePausing="true" android:theme="@style/Theme" android:windowSoftInputMode="adjustPan" android:screenOrientation="nosensor"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.HOME" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.MONKEY"/> </intent-filter> </activity>
Launcher生命周期执行过程
1.Launcher.java
protected void onCreate(Bundle savedInstanceState) { …… super.onCreate(savedInstanceState); // 调用LauncherAppState实例 LauncherAppState app = LauncherAppState.getInstance(this); mDeviceProfile = app.getInvariantDeviceProfile().getDeviceProfile(this); if (isInMultiWindowModeCompat()) { Display display = getWindowManager().getDefaultDisplay(); Point mwSize = new Point(); display.getSize(mwSize); mDeviceProfile = mDeviceProfile.getMultiWindowProfile(this, mwSize); } mSharedPrefs = Utilities.getPrefs(this); mIsSafeModeEnabled = getPackageManager().isSafeMode(); // 将Launcher传入LauncherAppState实例 mModel = app.setLauncher(this); mModelWriter = mModel.getWriter(mDeviceProfile.isVerticalBarLayout()); mIconCache = app.getIconCache(); mAccessibilityDelegate = new LauncherAccessibilityDelegate(this); …… }
2.LauncherAppState
从上面看第一步调用了LauncherAppState的getInstance方法,下面是对应的方法和构造方法:
public static LauncherAppState getInstance(final Context context) { if (INSTANCE == null) { if (Looper.myLooper() == Looper.getMainLooper()) { // 创建实例 INSTANCE = new LauncherAppState(context.getApplicationContext()); } else { try { return new MainThreadExecutor().submit(new Callable<LauncherAppState>() { @Override public LauncherAppState call() throws Exception { return LauncherAppState.getInstance(context); } }).get(); } catch (InterruptedException|ExecutionException e) { throw new RuntimeException(e); } } } return INSTANCE; } private LauncherAppState(Context context) { …… mInvariantDeviceProfile = new InvariantDeviceProfile(mContext); mIconCache = new IconCache(mContext, mInvariantDeviceProfile); mWidgetCache = new WidgetPreviewLoader(mContext, mIconCache); // 创建LauncherModel对象 mModel = new LauncherModel(this, mIconCache, Utilities.getOverrideObject(AppFilter.class, mContext, R.string.app_filter_class)); LauncherAppsCompat.getInstance(mContext).addOnAppsChangedCallback(mModel); …… }
setLauncher函数:
LauncherModel setLauncher(Launcher launcher) { getLocalProvider(mContext).setLauncherProviderChangeListener(launcher); mModel.initialize(launcher); return mModel; }
setLauncher里面调用了LauncherModel对象的initialize方法,传入变量就是launcher对象
3.LaunerModel.java
下面是mModel的initialize方法:
public void initialize(Callbacks callbacks) { synchronized (mLock) { Preconditions.assertUIThread(); // Remove any queued UI runnables mHandler.cancelAll(); mCallbacks = new WeakReference<>(callbacks); } }
由于Launcher实现了Callback,所以这里把它封装成了弱引用对象
继续分析Launcher的onCreate函数
4.Launcher.java
protected void onCreate(Bundle savedInstanceState) { …… super.onCreate(savedInstanceState); // 将Launcher传入LauncherAppState实例 mModel = app.setLauncher(this); mModelWriter = mModel.getWriter(mDeviceProfile.isVerticalBarLayout()); …… if (!mModel.startLoader(currentScreen)) { mDragLayer.setAlpha(0); } else { mWorkspace.setCurrentPage(currentScreen); setWorkspaceLoading(true); } }
获取到mModel之后会调用startLoader方法
public boolean startLoader(int synchronousBindPage) { InstallShortcutReceiver.enableInstallQueue(); synchronized (mLock) { if (mCallbacks != null && mCallbacks.get() != null) { final Callbacks oldCallbacks = mCallbacks.get(); runOnMainThread(new Runnable() { public void run() { oldCallbacks.clearPendingBinds(); } }); stopLoaderLocked(); // 执行LoaderTask函数 mLoaderTask = new LoaderTask(mApp.getContext(), synchronousBindPage); if (synchronousBindPage != PagedView.INVALID_RESTORE_PAGE && mModelLoaded && !mIsLoaderTaskRunning) { mLoaderTask.runBindSynchronousPage(synchronousBindPage); return true; } else { sWorkerThread.setPriority(Thread.NORM_PRIORITY); // 将mLoaderTask传入到消息线程中处理 sWorker.post(mLoaderTask); } } } return false; }
5.LoaderTask.java
LoaderTask类实现了Runnable接口,当消息被执行的时候会调用LoaderTask的run函数:
private class LoaderTask implements Runnable { …… public void run() { synchronized (mLock) { if (mStopped) { return; } mIsLoaderTaskRunning = true; } try { if (DEBUG_LOADERS) Log.d(TAG, "step 1.1: loading workspace"); // Set to false in bindWorkspace() mIsLoadingAndBindingWorkspace = true; // 加载桌面 loadWorkspace(); verifyNotStopped(); if (DEBUG_LOADERS) Log.d(TAG, "step 1.2: bind workspace workspace"); // 绑定桌面 bindWorkspace(mPageToBindFirst); if (DEBUG_LOADERS) Log.d(TAG, "step 1 completed, wait for idle"); waitForIdle(); verifyNotStopped(); if (DEBUG_LOADERS) Log.d(TAG, "step 2.1: loading all apps"); // 加载所有的app loadAllApps(); verifyNotStopped(); if (DEBUG_LOADERS) Log.d(TAG, "step 2.2: Update icon cache"); updateIconCache(); if (DEBUG_LOADERS) Log.d(TAG, "step 2 completed, wait for idle"); waitForIdle(); verifyNotStopped(); if (DEBUG_LOADERS) Log.d(TAG, "step 3.1: loading deep shortcuts"); loadDeepShortcuts(); verifyNotStopped(); if (DEBUG_LOADERS) Log.d(TAG, "step 3.2: bind deep shortcuts"); bindDeepShortcuts(); if (DEBUG_LOADERS) Log.d(TAG, "step 3 completed, wait for idle"); waitForIdle(); verifyNotStopped(); if (DEBUG_LOADERS) Log.d(TAG, "step 4.1: loading widgets"); refreshAndBindWidgetsAndShortcuts(getCallback(), false /* bindFirst */, null /* packageUser */); synchronized (mLock) { mModelLoaded = true; mHasLoaderCompletedOnce = true; } } catch (CancellationException e) { // Loader stopped, ignore } finally { mContext = null; synchronized (mLock) { if (mLoaderTask == this) { mLoaderTask = null; } mIsLoaderTaskRunning = false; } } } …… }
在loadAllApps会去加载所有的app,对应方法如下:
private void loadAllApps() { …… mHandler.post(new Runnable() { public void run() { final long bindTime = SystemClock.uptimeMillis(); final Callbacks callbacks = tryGetCallbacks(oldCallbacks); if (callbacks != null) { // 绑定apps callbacks.bindAllApplications(added); if (DEBUG_LOADERS) { Log.d(TAG, "bound " + added.size() + " apps in " + (SystemClock.uptimeMillis() - bindTime) + "ms"); } } else { Log.i(TAG, "not binding apps: no Launcher activity"); } } }); …… }
因为callbacks就是之前传进来的Launcher对象,所以这里就将app传给了Launcher对象
6.Launcher.java
public void bindAllApplications(final ArrayList<AppInfo> apps) { if (waitUntilResume(mBindAllApplicationsRunnable, true)) { mTmpAppsList = apps; return; } if (mAppsView != null) { mAppsView.setApps(apps); } if (mLauncherCallbacks != null) { mLauncherCallbacks.bindAllApplications(apps); } }
这里就将app信息传递给了mAppsView界面。这样基本就将app显示出来了。