above
- Android System Revealed (1) -Activity startup process (1)
- Android System Revealed (1) -Activity startup process (1)
- Android System Disclosure (2) -Service startup process
- Android System Revealed (3) – Overview of Android system startup
preface
The last step in starting the Android system is to start the Launcher
What is the Launcher
If you don’t know what a Launcher is, look at this page and you’ll know it. A Launcher is a desktop.
The ICONS on the desktop are the launcher, and we can start the corresponding application with these ICONS.
The Launcher to start
Because each version of the difference is relatively large, so separate several versions of the analysis, do not want to see the source code students can directly see the end of the summary
Android 8 or 9
Let’s start with the overall sequence diagram:
The Zygote process starts the SystemServer process, and the entry to start the Launcher is the AMS systemReady method, which is called in the SystemServer startOtherServices method
As follows:
frameworks/base/services/java/com/android/server/SystemServer.java
public final class SystemServer {
private void run(a) {...// Start services.
try {
t.traceBegin("StartServices");
startBootstrapServices(t);
startCoreServices(t);
startOtherServices(t);
} catch (Throwable ex) {
Slog.e("System"."* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *");
Slog.e("System"."************ Failure starting system services", ex);
throw ex;
} finally {
t.traceEnd(); // StartServices}... }private void startOtherServices(@NonNull TimingsTraceAndSlog t) {... mActivityManagerService.systemReady(() -> { Slog.i(TAG,"Making services ready");
t.traceBegin("StartActivityManagerReadyPhase"); mSystemServiceManager.startBootPhase(t, SystemService.PHASE_ACTIVITY_MANAGER_READY); . }... }}Copy the code
Take a look at the systemReady implementation
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public void systemReady(final Runnable goingCallback, TimingsTraceLog traceLog) {
...
mStackSupervisor.resumeFocusedStackTopActivityLocked();
mUserController.sendUserSwitchBroadcastsLocked(-1, currentUserId);
traceLog.traceEnd(); // ActivityManagerStartApps
traceLog.traceEnd(); // PhaseActivityManagerReady
}
Copy the code
You can see that this is the ActivityStackSupervisor
frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java
boolean resumeFocusedStackTopActivityLocked( ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) { if (! readyToResume()) { return false; } if (targetStack ! = null && isFocusedStack(targetStack)) { return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions); }... return false; }Copy the code
The back is called ActivityStack resumeTopActivityUncheckedLocked method
frameworks/base/services/core/java/com/android/server/am/ActivityStack.java
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); } finally { mStackSupervisor.inResumeTopActivity = false; }... return result; } private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) { ... return isOnHomeDisplay() && mStackSupervisor.resumeHomeStackTask(prev, "prevFinished"); . }Copy the code
ActivityStack eventually calls the ActivityStackSupervisor’s resumeHomeStackTask method
frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java
boolean resumeHomeStackTask(ActivityRecord prev, String reason) { ... 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); }Copy the code
Finally, back to AMS, call AMS’s startHomeActivityLocked method
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
boolean startHomeActivityLocked(int userId, FactoryTest == factorytest.factory_test_low_level && mTopAction == 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(); 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) { intent.setFlags(intent.getFlags() | Intent.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; mActivityStarter.startHomeActivityLocked(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); intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING); if (mFactoryTest ! = FactoryTest.FACTORY_TEST_LOW_LEVEL) { intent.addCategory(Intent.CATEGORY_HOME); } return intent; }Copy the code
Here an Intent is launched, and you can see the list configuration of the Launcher from the source code
packages/apps/Launcher3/AndroidManifest.xml
<? The XML version = "1.0" encoding = "utf-8"? > <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.launcher3"> <application android:backupAgent="com.android.launcher3.LauncherBackupAgent" android:fullBackupOnly="true" android:fullBackupContent="@xml/backupscheme" android:hardwareAccelerated="true" android:icon="@drawable/ic_launcher_home" android:label="@string/derived_app_name" android:theme="@style/LauncherTheme" android:largeHeap="@bool/config_largeHeap" android:restoreAnyVersion="true" android:supportsRtl="true" > <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> </application> </manifest>Copy the code
Finally, use ActivityStarter to start the Launcher. For details, see Starting an Activity
frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java
void startHomeActivityLocked(Intent intent, ActivityInfo aInfo, String reason) { mSupervisor.moveHomeStackTaskToTop(reason); mLastHomeActivityStartResult = startActivityLocked(null /*caller*/, intent, null /*ephemeralIntent*/, null /*resolvedType*/, aInfo, null /*rInfo*/, null /*voiceSession*/, null /*voiceInteractor*/, null /*resultTo*/, null /*resultWho*/, 0 /*requestCode*/, 0 /*callingPid*/, 0 /*callingUid*/, null /*callingPackage*/, 0 /*realCallingPid*/, 0 /*realCallingUid*/, 0 /*startFlags*/, null /*options*/, false /*ignoreTargetSecurity*/, false /*componentSpecified*/, mLastHomeActivityStartRecord /*outActivity*/, null /*inTask*/, "startHomeActivity: " + reason); . }Copy the code
summary
- Use AMS to start the Launcher in SystemServer
- AMS call ActivityStackSupervisor resumeFocusedStackTopActivityLocked method
- I went through the ActivityStackSupervisor -> ActivityStack -> ActivityStackSupervisor ->AMS process, did some stack-related work in between, and finally came back to AMS
- AMS calls ActivityStarter to start the Launcher Activity
It is recommended to look back at the sequence diagram after reading the source code, which will be more clear
Android 10
Sequence diagram:
Like Android 8, it starts from AMS, Different android to a 10 ActivityTaskManagerInternal mAtmInternal type of service frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
@VisibleForTesting public ActivityTaskManagerInternal mAtmInternal; public ActivityManagerService(Context systemContext, ActivityTaskManagerService atm) { ... mAtmInternal = LocalServices.getService(ActivityTaskManagerInternal.class); } public void systemReady(final Runnable goingCallback, TimingsTraceLog traceLog) { ... t.traceBegin("resumeTopActivities"); mAtmInternal.resumeTopActivities(false /* scheduleIdle */); t.traceEnd(); . }Copy the code
Where we see mAtmInternal, LocalServices class is a class and object of key/value pairs, and ActivityTaskManagerInternal is an abstract class, We find it only derived class ActivityTaskManagerService. LocalService
frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
RootActivityContainer mRootActivityContainer;
final class LocalService extends ActivityTaskManagerInternal {
@Override
public void resumeTopActivities(boolean scheduleIdle) {
synchronized(mGlobalLock) { mRootActivityContainer.resumeFocusedStacksTopActivities(); . }}}}Copy the code
Call the RootActivityContainer resumeFocusedStacksTopActivities method here
frameworks/base/services/core/java/com/android/server/wm/RootActivityContainer.java
boolean resumeFocusedStacksTopActivities() { return resumeFocusedStacksTopActivities(null, null, null); } boolean resumeFocusedStacksTopActivities( ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) { ... for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) { ... if (! resumedOnDisplay) { final ActivityStack focusedStack = display.getFocusedStack(); if (focusedStack ! = null) { focusedStack.resumeTopActivityUncheckedLocked(target, targetOptions); } } } return result; }Copy the code
Next came ActivityStack
frameworks/base/services/core/java/com/android/server/wm/ActivityStack.java
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) { ... result = resumeTopActivityInnerLocked(prev, options); . } private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) { .... if (! hasRunningActivity) { // There are no activities left in the stack, let's look somewhere else. return resumeNextFocusableActivityWhenStackIsEmpty(prev, options); }... }Copy the code
private boolean resumeNextFocusableActivityWhenStackIsEmpty(ActivityRecord prev,
ActivityOptions options) {
...
return mRootActivityContainer.resumeHomeActivity(prev, reason, mDisplayId);
}
Copy the code
And call the RootActivityContainer resumeHomeActivity resumeNextFocusableActivityWhenStackIsEmpty method
frameworks/base/services/core/java/com/android/server/wm/RootActivityContainer.java
boolean resumeHomeActivity(ActivityRecord prev, String reason, int displayId) {
...
return startHomeOnDisplay(mCurrentUser, myReason, displayId);
}
Copy the code
boolean startHomeOnDisplay(int userId, String reason, int displayId) {
return startHomeOnDisplay(userId, reason, displayId, false /* allowInstrumenting */,
false /* fromHomeKey */);
}
Copy the code
So in startHomeOnDisplay, we get homeIntent, and then we go to the last line:
boolean startHomeOnDisplay(int userId, String reason, int displayId, boolean allowInstrumenting, boolean fromHomeKey) { ... Intent homeIntent = null; ActivityInfo aInfo = null; if (displayId == DEFAULT_DISPLAY) { homeIntent = mService.getHomeIntent(); aInfo = resolveHomeActivity(userId, homeIntent); } else if (shouldPlaceSecondaryHomeOnDisplay(displayId)) { Pair<ActivityInfo, Intent> info = resolveSecondaryHomeActivity(userId, displayId); aInfo = info.first; homeIntent = info.second; }... / / start HomeActivity mService is ActivityTaskManagerService mService.getActivityStartController().startHomeActivity(homeIntent, aInfo, myReason, displayId); return true; }Copy the code
MService. GetActivityStartController () get ActivityStartController
frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
private ActivityStartController mActivityStartController; ActivityStartController getActivityStartController() { return mActivityStartController; } public void initialize(IntentFirewall intentFirewall, PendingIntentController intentController, Looper looper) { ... mActivityStartController = new ActivityStartController(this); . }Copy the code
Finally, use the ActivityStartController to start the Launcher
frameworks/base/services/core/java/com/android/server/wm/ActivityStartController.java
void startHomeActivity(Intent intent, ActivityInfo aInfo, String reason, TaskDisplayArea taskDisplayArea) { ... mLastHomeActivityStartResult = obtainStarter(intent, "startHomeActivity: " + reason) .setOutActivity(tmpOutRecord) .setCallingUid(0) .setActivityInfo(aInfo) .setActivityOptions(options.toBundle()) .execute(); mLastHomeActivityStartRecord = tmpOutRecord[0]; . if (homeStack.mInResumeTopActivity) { mSupervisor.scheduleResumeTopActivities(); }}Copy the code
ActivityStarter obtainStarter(Intent intent, String reason) {
return mFactory.obtain().setIntent(intent).setReason(reason);
}
Copy the code
The resulting process can be referenced to the start of the Activity
summary
- Use AMS to start the Launcher in SystemServer
- AMS call ActivityTaskManagerInternal resumeTopActivities method
- Display the relevant things in RootActivityContainer, then use ActivityStack to do some stack-related work, and then go back to RootActivityContainer
- Start the LauncherActivity with ActivityStartController
It is recommended to look back at the sequence diagram after reading the source code, which will be more clear
Android 11
Sequence diagram:
The Launcher for Android 11 is similar to Android 10
Call resumeTopActivities in AMS just like Android 10
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
@VisibleForTesting public ActivityTaskManagerInternal mAtmInternal; public ActivityManagerService(Context systemContext, ActivityTaskManagerService atm) { ... mAtmInternal = LocalServices.getService(ActivityTaskManagerInternal.class); } public void systemReady(final Runnable goingCallback, TimingsTraceLog traceLog) { ... t.traceBegin("resumeTopActivities"); mAtmInternal.resumeTopActivities(false /* scheduleIdle */); t.traceEnd(); . }Copy the code
The difference is that Android11 uses RootWindowContainer instead of RootActivityContainer to start the Launcher
frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
RootWindowContainer mRootWindowContainer;
final class LocalService extends ActivityTaskManagerInternal {
@Override
public void resumeTopActivities(boolean scheduleIdle) {
synchronized (mGlobalLock) {
10 for mRootActivityContainer / /
mRootWindowContainer.resumeFocusedStacksTopActivities();
if (scheduleIdle) {
mStackSupervisor.scheduleIdle();
}
}
}
}
}
Copy the code
The following code is a bit different. When ActivityStack is not present in ActivityDisplay, focusedStack == null, Android 11 starts the resumeHomeActivity method directly
frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java
boolean resumeFocusedStacksTopActivities() { return resumeFocusedStacksTopActivities(null, null, null); } boolean resumeFocusedStacksTopActivities( ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) { ... for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) { ... if (! resumedOnDisplay) { final ActivityStack focusedStack = display.getFocusedStack(); if (focusedStack ! = null) { result |= focusedStack.resumeTopActivityUncheckedLocked(target, targetOptions); } else if (targetStack == null) { result |= resumeHomeActivity(null /* prev */, "no-focusable-task", display.getDefaultTaskDisplayArea()); } } } return result; }Copy the code
This process is similar to Android 10 and is handled using ActivityStack
frameworks/base/services/core/java/com/android/server/wm/ActivityStack.java
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) { ... result = resumeTopActivityInnerLocked(prev, options); . } private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) { .... if (! hasRunningActivity) { // There are no activities left in the stack, let's look somewhere else. return resumeNextFocusableActivityWhenStackIsEmpty(prev, options); }... }Copy the code
private boolean resumeNextFocusableActivityWhenStackIsEmpty(ActivityRecord prev,
ActivityOptions options) {
...
return mRootActivityContainer.resumeHomeActivity(prev, reason, mDisplayId);
}
Copy the code
You end up back in RootWindowContainer’s resumeHomeActivity method
frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java
boolean resumeHomeActivity(ActivityRecord prev, String reason, TaskDisplayArea taskDisplayArea) { if (! mService.isBooting() && ! mService.isBooted()) { // Not ready yet! return false; } if (taskDisplayArea == null) { taskDisplayArea = getDefaultTaskDisplayArea(); } final ActivityRecord r = taskDisplayArea.getHomeActivity(); final String myReason = reason + " resumeHomeActivity"; // Only resume home activity if isn't finishing. if (r ! = null && ! r.finishing) { r.moveFocusableActivityToTop(myReason); return resumeFocusedStacksTopActivities(r.getRootTask(), prev, null); } return startHomeOnTaskDisplayArea(mCurrentUser, myReason, taskDisplayArea, false /* allowInstrumenting */, false /* fromHomeKey */); }Copy the code
Go to startHomeOnTaskDisplayArea methods (the method name is not the same as before)
boolean startHomeOnTaskDisplayArea(int userId, String reason, TaskDisplayArea taskDisplayArea, boolean allowInstrumenting, boolean fromHomeKey) { ... Intent homeIntent = null; ActivityInfo aInfo = null; if (taskDisplayArea == getDefaultTaskDisplayArea()) { homeIntent = mService.getHomeIntent(); aInfo = resolveHomeActivity(userId, homeIntent); } else if (shouldPlaceSecondaryHomeOnDisplayArea(taskDisplayArea)) { Pair<ActivityInfo, Intent> info = resolveSecondaryHomeActivity(userId, taskDisplayArea); aInfo = info.first; homeIntent = info.second; } if (aInfo == null || homeIntent == null) { return false; } if (! canStartHomeOnDisplayArea(aInfo, taskDisplayArea, allowInstrumenting)) { return false; } // Updates the home component of the intent. homeIntent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name)); homeIntent.setFlags(homeIntent.getFlags() | FLAG_ACTIVITY_NEW_TASK); // Updates the extra information of the intent. if (fromHomeKey) { homeIntent.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, true); mWindowManager.cancelRecentsAnimation(REORDER_KEEP_IN_PLACE, "startHomeActivity"); } final String myReason = reason + ":" + userId + ":" + UserHandle.getUserId( aInfo.applicationInfo.uid) + ":" + taskDisplayArea.getDisplayId(); / / start HomeActivity mService is ActivityTaskManagerService mService.getActivityStartController().startHomeActivity(homeIntent, aInfo, myReason, taskDisplayArea); return true; }Copy the code
RootWindowContainer starts with ActivityStartControlle. This process is similar to that of Android 10.
frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
private ActivityStartController mActivityStartController; ActivityStartController getActivityStartController() { return mActivityStartController; } public void initialize(IntentFirewall intentFirewall, PendingIntentController intentController, Looper looper) { ... mActivityStartController = new ActivityStartController(this); . }Copy the code
frameworks/base/services/core/java/com/android/server/wm/ActivityStartController.java
void startHomeActivity(Intent intent, ActivityInfo aInfo, String reason, TaskDisplayArea taskDisplayArea) { ... mSupervisor.beginDeferResume(); final ActivityStack homeStack; try { // Make sure home stack exists on display area. homeStack = taskDisplayArea.getOrCreateRootHomeTask(ON_TOP); } finally { mSupervisor.endDeferResume(); } mLastHomeActivityStartResult = obtainStarter(intent, "startHomeActivity: " + reason) .setOutActivity(tmpOutRecord) .setCallingUid(0) .setActivityInfo(aInfo) .setActivityOptions(options.toBundle()) .execute(); mLastHomeActivityStartRecord = tmpOutRecord[0]; if (homeStack.mInResumeTopActivity) { mSupervisor.scheduleResumeTopActivities(); }}Copy the code
ActivityStarter obtainStarter(Intent intent, String reason) {
return mFactory.obtain().setIntent(intent).setReason(reason);
}
Copy the code
summary
- Other than the RootActivityContainer job being replaced by RootWindowContainer, the rest of the process doesn’t change much from Android 10
The Launcher to start the Activity
The Launcher startActivitySafely way start Activity packages/apps/Launcher3 / SRC/com/android/Launcher3 / Launcher. Java
public boolean startActivitySafely(View v, Intent intent, ItemInfo item) { ... Intent.addflags (intent.flag_activity_new_task); . try { ... startActivity(intent, optsBundle); . } catch (ActivityNotFoundException|SecurityException e) { Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show(); Log.e(TAG, "Unable to launch. tag=" + item + " intent=" + intent, e); } return false; }Copy the code
conclusion
Compare the sequence diagrams for several versions
- Android 8 or 9
- Android 10
- Android 11
Android 10 changes a lot
It can be summarized as follows
- First use AMS in SystemServer to start the Launcher
- If Android 8-9
- AMS call ActivityStackSupervisor resumeFocusedStackTopActivityLocked method
- I went through the ActivityStackSupervisor -> ActivityStack -> ActivityStackSupervisor ->AMS process, did some stack-related work in between, and finally came back to AMS
- AMS calls ActivityStarter to start the Launcher Activity
- If Android is 10-11
-
AMS call ActivityTaskManagerInternal resumeTopActivities method
-
Display the relevant things in RootActivityContainer (Android11 for RootWindowContainer), then use ActivityStack to handle some stack-related work, Call the resumeHomeActivity method of RootActivityContainer. (In Android11, if ActivityStack is not found, call resumeHomeActivity directly.)
-
Use ActivityStartController to start the Launcher Activity
-