Android系统Launcher启动流程学习(三)Launcher启动流程
Launcher 启动
系统启动的最后一步是启动一个应用程序用来显示系统中已经安装的应用程序,并作为这些安装程序的启动入口,这个应用程序就是Launcher。Launcher就是Android的桌面,主要作用就两点:
- 作为Android系统的启动器,用于启动应用程序
- 作为为Android的桌面,用于显示和管理应用程序的快捷图标或者其他桌面组件。
上面得知SystemServer 进程启动中会启动很多其他的服务,其中一个就是 ActivityManagerService,在 startOtherServices 中会调用 AMS 的 systemReady() 方法将 Lanuncher 启动起来
位置:frameworks/base/services/java/com/android/server/SystemServer.java
private void startOtherServices() {
//...
mActivityManagerService.systemReady(() -> { //在startOtherService()方法中
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);
}
traceEnd();
//...
}, BOOT_TIMINGS_TRACE_LOG);
位置:frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public void systemReady(final Runnable goingCallback, TimingsTraceLog traceLog) {
traceLog.traceBegin("PhaseActivityManagerReady");
//...
synchronized (this) {
//...
startHomeActivityLocked(currentUserId, "systemReady");
//...
//调用了ActivityStackSupervisor的resumeFocusedStackTopActivityLock方法
mStackSupervisor.resumeFocusedStackTopActivityLocked();
mUserController.sendUserSwitchBroadcasts(-1, currentUserId);
//...
}
}
resumeFocusedStackTopActivityLocked
位置:frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java
boolean resumeFocusedStackTopActivityLocked() {
return resumeFocusedStackTopActivityLocked(null, null, null);
}
boolean resumeFocusedStackTopActivityLocked(
ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
if (!readyToResume()) {
return false;
}
if (targetStack != null && isFocusedStack(targetStack)) {
return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions); //从这里调用ActivityStack.java的函数
}
final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
if (r == null || !r.isState(RESUMED)) {
mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
} else if (r.isState(RESUMED)) {
// Kick off any lingering app transitions form the MoveTaskToFront operation.
mFocusedStack.executeAppTransition(targetOptions);
}
return false;
}
位置:frameworks/base/services/core/java/com/android/server/am/ActivityStack.java
@GuardedBy("mService")
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
if (mStackSupervisor.inResumeTopActivity) {
// Don't even start recursing.
return false;
}
boolean result = false;
try {
// Protect against recursion.
mStackSupervisor.inResumeTopActivity = true;
result = resumeTopActivityInnerLocked(prev, options); //使用函数
// When resuming the top activity, it may be necessary to pause the top activity (for
// example, returning to the lock screen. We suppress the normal pause logic in
// {@link #resumeTopActivityUncheckedLocked}, since the top activity is resumed at the
// end. We call the {@link ActivityStackSupervisor#checkReadyForSleepLocked} again here
// to ensure any necessary pause logic occurs. In the case where the Activity will be
// shown regardless of the lock screen, the call to
// {@link ActivityStackSupervisor#checkReadyForSleepLocked} is skipped.
final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);
if (next == null || !next.canTurnScreenOn()) {
checkReadyForSleep();
}
} finally {
mStackSupervisor.inResumeTopActivity = false;
}
return result;
}
@GuardedBy("mService")
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
if (!mService.mBooting && !mService.mBooted) {
// Not ready yet!
return false;
}
// Find the next top-most activity to resume in this stack that is not finishing and is
// focusable. If it is not focusable, we will fall into the case below to resume the
// top activity in the next focusable task.
final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);
final boolean hasRunningActivity = next != null;
// TODO: Maybe this entire condition can get removed?
if (hasRunningActivity && !isAttached()) {
return false;
}
mStackSupervisor.cancelInitializingActivities();
// Remember how we'll process this pause/resume situation, and ensure
// that the state is reset however we wind up proceeding.
boolean userLeaving = mStackSupervisor.mUserLeaving;
mStackSupervisor.mUserLeaving = false;
if (!hasRunningActivity) {
// There are no activities left in the stack, let's look somewhere else. 如果没有TopActivity运行
return resumeTopActivityInNextFocusableStack(prev, options, "noMoreActivities");
}
//...
}
private boolean resumeTopActivityInNextFocusableStack(ActivityRecord prev,
ActivityOptions options, String reason) {
if (adjustFocusToNextFocusableStack(reason)) {
// Try to move focus to the next visible stack with a running activity if this
// stack is not covering the entire screen or is on a secondary display (with no home
// stack).
return mStackSupervisor.resumeFocusedStackTopActivityLocked(
mStackSupervisor.getFocusedStack(), prev, null);
}
// Let's just start up the Launcher...
ActivityOptions.abort(options);
if (DEBUG_STATES) Slog.d(TAG_STATES,
"resumeTopActivityInNextFocusableStack: " + reason + ", go home");
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
// Only resume home if on home display
return isOnHomeDisplay() &&
mStackSupervisor.resumeHomeStackTask(prev, reason);
}
位置:frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java
boolean resumeHomeStackTask(ActivityRecord prev, String reason) {
if (!mService.mBooting && !mService.mBooted) {
// Not ready yet!
return false;
}
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); //这里调用了AMS的startHomeActivityLocked
}
startHomeActivityLocked
在 AMS 中的 systemReady() 方法中执行 startHomeActivityLocked()方法,传入当前用户ID
boolean startHomeActivityLocked(int userId, String reason) {
if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL
&& mTopAction == null) {
// mFactoryTest为FactoryTest.FACTORY_TEST_LOW_LEVEL(低工厂模式)并且mTopAction等于null时,直接返回null
// We are running in factory test mode, but unable to find
// the factory test app, so just sit around displaying the
// error message and don't try to start anything.
return false;
}
Intent intent = getHomeIntent(); //获取到要启动的HomeActivity的intent对象
//通过PackageManager去获取对应符合的Activity
ActivityInfo aInfo = resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);
if (aInfo != null) {
intent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name));
// Don't do this if the home app is currently being
// instrumented.
aInfo = new ActivityInfo(aInfo);
aInfo.applicationInfo = getAppInfoForUser(aInfo.applicationInfo, userId);
ProcessRecord app = getProcessRecordLocked(aInfo.processName,
aInfo.applicationInfo.uid, true);
if (app == null || app.instr == null) {
//添加FLAG_ACTIVITY_NEW_TASK启动参数,开启新栈
intent.setFlags(intent.getFlags() | FLAG_ACTIVITY_NEW_TASK);
final int resolvedUserId = UserHandle.getUserId(aInfo.applicationInfo.uid);
// For ANR debugging to verify if the user activity is the one that actually
// launched.
final String myReason = reason + ":" + userId + ":" + resolvedUserId;
mActivityStartController.startHomeActivity(intent, aInfo, myReason);
}
} else {
Slog.wtf(TAG, "No home screen found for " + intent, new Throwable());
}
return true;
}
Intent getHomeIntent() {
Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null);
intent.setComponent(mTopComponent); //mTopAction默认为INTENT.ACTION_MAIN
intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
intent.addCategory(Intent.CATEGORY_HOME); //添加CATEGORY_HOME的category标志
}
return intent;
}
private ActivityInfo resolveActivityInfo(Intent intent, int flags, int userId) {
ActivityInfo ai = null;
ComponentName comp = intent.getComponent();
try {
if (comp != null) {
// Factory test.
ai = AppGlobals.getPackageManager().getActivityInfo(comp, flags, userId);
} else {
ResolveInfo info = AppGlobals.getPackageManager().resolveIntent(
intent,
intent.resolveTypeIfNeeded(mContext.getContentResolver()),
flags, userId);
if (info != null) {
ai = info.activityInfo;
}
}
} catch (RemoteException e) {
// ignore
}
return ai;
}
//位置:"./frameworks/base/services/core/java/com/android/server/am/ActivityStartController.java"
void startHomeActivity(Intent intent, ActivityInfo aInfo, String reason) {
mSupervisor.moveHomeStackTaskToTop(reason);
//调用obtainStarter()方法获取到一个ActivityStarter对象
mLastHomeActivityStartResult = obtainStarter(intent, "startHomeActivity: " + reason)
.setOutActivity(tmpOutRecord)
.setCallingUid(0)
.setActivityInfo(aInfo)
.execute();
mLastHomeActivityStartRecord = tmpOutRecord[0];
if (mSupervisor.inResumeTopActivity) {
// If we are in resume section already, home activity will be initialized, but not
// resumed (to avoid recursive resume) and will stay that way until something pokes it
// again. We need to schedule another resume.
mSupervisor.scheduleResumeTopActivities();
}
}
ActivityStarter obtainStarter(Intent intent, String reason) {
return mFactory.obtain().setIntent(intent).setReason(reason); //工厂模式创建ActivityStarter对象
}
//位置"frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java"
int execute() {
try {
// TODO(b/64750076): Look into passing request directly to these methods to allow
// for transactional diffs and preprocessing.
if (mRequest.mayWait) { //mayWait默认为false
return startActivityMayWait(mRequest.caller, mRequest.callingUid,
mRequest.callingPackage, mRequest.intent, mRequest.resolvedType,
mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,
mRequest.resultWho, mRequest.requestCode, mRequest.startFlags,
mRequest.profilerInfo, mRequest.waitResult, mRequest.globalConfig,
mRequest.activityOptions, mRequest.ignoreTargetSecurity, mRequest.userId,
mRequest.inTask, mRequest.reason,
mRequest.allowPendingRemoteAnimationRegistryLookup,
mRequest.originatingPendingIntent);
} else {
//执行startActivity()进入Activity的启动流程
return startActivity(mRequest.caller, mRequest.intent, mRequest.ephemeralIntent,
mRequest.resolvedType, mRequest.activityInfo, mRequest.resolveInfo,
mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,
mRequest.resultWho, mRequest.requestCode, mRequest.callingPid,
mRequest.callingUid, mRequest.callingPackage, mRequest.realCallingPid,
mRequest.realCallingUid, mRequest.startFlags, mRequest.activityOptions,
mRequest.ignoreTargetSecurity, mRequest.componentSpecified,
mRequest.outActivity, mRequest.inTask, mRequest.reason,
mRequest.allowPendingRemoteAnimationRegistryLookup,
mRequest.originatingPendingIntent);
}
} finally {
onExecutionComplete();
}
}
Launcher本身就是一个系统APP,用于显示桌面等,LauncherApp启动之后会执行其生命周期方法初始化桌面布局,至此,Launcher就启动完成了,用户进入到界面,整个Android系统也启动起来
Laucher应用程序图标显示过程
Launcher是一个桌面应用程序,先从Launcher的onCreate方法入手:
位置:packages/apps/Launcher3/src/com/android/launcher3/Launcher.java
@Override
protected void onCreate(Bundle savedInstanceState) {
//...
LauncherAppState app = LauncherAppState.getInstance(this); //“获取LauncherAppState的实例”
mOldConfig = new Configuration(getResources().getConfiguration());
mModel = app.setLauncher(this); //将Launcher对象传入
initDeviceProfile(app.getInvariantDeviceProfile());
//...
if (!mModel.startLoader(currentScreen)) { //调用LauncherModel的startLoader
if (!internalStateHandled) {
// If we are not binding synchronously, show a fade in animation when
// the first page bind completes.
mDragLayer.getAlphaProperty(ALPHA_INDEX_LAUNCHER_LOAD).setValue(0);
}
} else {
// Pages bound synchronously.
mWorkspace.setCurrentPage(currentScreen);
setWorkspaceLoading(true);
}
//...
}
位置: packages/apps/Launcher3/src/com/android/launcher3/LauncherAppState.java
LauncherModel setLauncher(Launcher launcher) {
getLocalProvider(mContext).setLauncherProviderChangeListener(launcher);
mModel.initialize(launcher); //调用LauncherModel的initialize方法
return mModel;
}
位置:packages/apps/Launcher3/src/com/android/launcher3/LauncherModel.java
public void initialize(Callbacks callbacks) {
synchronized (mLock) {
Preconditions.assertUIThread();
mCallbacks = new WeakReference<>(callbacks); //封装成了弱引用对象
}
}
//创建了具有消息循环的线程HandlerThread对象
@Thunk static final HandlerThread sWorkerThread = new HandlerThread("launcher-loader");
static {
sWorkerThread.start();
}
//创建了Handler,并且传入HadlerThread的Looper,作用是向HandlerThread发送消息
@Thunk static final Handler sWorker = new Handler(sWorkerThread.getLooper());
public boolean startLoader(int synchronousBindPage) {
// Enable queue before starting loader. It will get disabled in Launcher#finishBindingItems
InstallShortcutReceiver.enableInstallQueue(InstallShortcutReceiver.FLAG_LOADER_RUNNING);
synchronized (mLock) {
// Don't bother to start the thread if we know it's not going to do anything
if (mCallbacks != null && mCallbacks.get() != null) {
final Callbacks oldCallbacks = mCallbacks.get();
// Clear any pending bind-runnables from the synchronized load process.
mUiExecutor.execute(oldCallbacks::clearPendingBinds);
// If there is already one running, tell it to stop.
stopLoader();
//这里初始化会post一下
LoaderResults loaderResults = new LoaderResults(mApp, sBgDataModel,
mBgAllAppsList, synchronousBindPage, mCallbacks);
if (mModelLoaded && !mIsLoaderTaskRunning) {
// 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();
// 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 {
startLoaderForResults(loaderResults);
}
}
}
return false;
}
位置:packages/apps/Launcher3/src/com/android/launcher3/model/LoaderResults.java
public void bindAllApps() {
// shallow copy
@SuppressWarnings("unchecked")
final ArrayList<AppInfo> list = (ArrayList<AppInfo>) mBgAllAppsList.data.clone();
Runnable r = new Runnable() {
public void run() {
Callbacks callbacks = mCallbacks.get(); //这个mCallbacks是指向Launcher的
if (callbacks != null) {
callbacks.bindAllApplications(list); //调用bindAllApplications
}
}
};
mUiExecutor.execute(r);
}
位置: packages/apps/Launcher3/src/com/android/launcher3/Launcher.java
public void bindAllApplications(ArrayList<AppInfo> apps) {
mAppsView.getAppsStore().setApps(apps); //调用mAppsView对象的setApps方法,并将包含应用信息的列表apps传进去
if (mLauncherCallbacks != null) {
mLauncherCallbacks.bindAllApplications(apps);
}
}
位置:packages/apps/Launcher3/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
public void setApps(AlphabeticalAppsList apps, boolean usingTabs) {
mApps = apps; //将包含应用信息的列表apps设置给mApps,这个mApps是AlphabeticalAppsList类型的对象
mFastScrollHelper = new AllAppsFastScrollHelper(this, apps);
}
接着查看AllAppsContainerView的onFinishInflate方法如下所示:
位置:packages/apps/Launcher3/src/com/android/launcher3/allapps/AllAppsContainerView.java
@Override
protected void onFinishInflate() {
super.onFinishInflate();
// This is a focus listener that proxies focus from a view into the list view. This is to
// work around the search box from getting first focus and showing the cursor.
setOnFocusChangeListener((v, hasFocus) -> {
if (hasFocus && getActiveRecyclerView() != null) {
getActiveRecyclerView().requestFocus();
}
});
mHeader = findViewById(R.id.all_apps_header);
rebindAdapters(mUsingTabs, true /* force */);
mSearchContainer = findViewById(R.id.search_container_all_apps);
mSearchUiManager = (SearchUiManager) mSearchContainer;
mSearchUiManager.initialize(this); //这里更新adapater
}
位置:packages/apps/Launcher3/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java
@Override
public void initialize(AllAppsContainerView appsView) {
mApps = appsView.getApps();
mAppsView = appsView;
mSearchBarController.initialize(
new DefaultAppSearchAlgorithm(mApps.getApps()), this, mLauncher, this);
}