本文基于Android 11.0源码分析
前言
前边介绍了AMS和ATMS startService()的启动过程、setSystemProcess()阶段、installSystemProviders()阶段,本文介绍AMS.systemReady()的阶段,包含启动home activity的过程,home activity根据是否注册system uid来判断是启动Launch还是setup wizard。
AMS03.PNG1.startOtherService()
继续从SystemServer.java中的startOtherServices()方法开发分析:
// /frameworks/base/services/java/com/android/server/SystemServer.java
private void startOtherServices(TimingsTraceAndSlog t) {
//AMS.systemReady()
mActivityManagerService.systemReady(() -> {
//1\. 回调各个系统Service的onBootPhase(), AMS ready.
mSystemServiceManager.startBootPhase(t, SystemService.PHASE_ACTIVITY_MANAGER_READY);
...
//2\. 回调各个系统Service的onBootPhase(), 可以启动第三方应用
mSystemServiceManager.startBootPhase(t, SystemService.PHASE_THIRD_PARTY_APPS_CAN_START);
...
}, t);
}
2.AMS.systemReady()
它的第一个参数是Runnable,代码非常复杂,总结下主要工作:
- 调用ATMS.onSystemmReady(),他内部通知一些服务ready;
- AMS调用mUserController、mAppOpsService、 mProcessList,回调他们的onSystemReady();
- kill已经启动的app, persistent=true的app可能先于AMS启动完成就启动;
- 执行SystemServer.startOtherServices()中调用AMS.systemReady()传递的参数;
- 启动各种Apps,启动包括persistent=true的app,home activity等。
// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public void systemReady(final Runnable goingCallback, @NonNull TimingsTraceAndSlog t) {
...
//kill已经启动的app, persistent=true的app可能先于AMS启动完成就启动
//把这些应用kill
ArrayList<ProcessRecord> procsToKill = null;
synchronized(mPidsSelfLocked) {
for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
ProcessRecord proc = mPidsSelfLocked.valueAt(i);
if (!isAllowedWhileBooting(proc.info)){
if (procsToKill == null) {
procsToKill = new ArrayList<ProcessRecord>();
}
procsToKill.add(proc);
}
}
}
....
synchronized (this) {
// Only start up encryption-aware persistent apps; once user is
// unlocked we'll come back around and start unaware apps
t.traceBegin("startPersistentApps");
startPersistentApps(PackageManager.MATCH_DIRECT_BOOT_AWARE);
t.traceEnd();
// Start up initial activity.
mBooting = true;
// Enable home activity for system user, so that the system can always boot. We don't
// do this when the system user is not setup since the setup wizard should be the one
// to handle home activity in this case.
// 为system user启动home activity. 如果system user没有设置,由开机引导app来处理home activity.
if (UserManager.isSplitSystemUser() &&
Settings.Secure.getInt(mContext.getContentResolver(),
Settings.Secure.USER_SETUP_COMPLETE, 0) != 0
|| SystemProperties.getBoolean(SYSTEM_USER_HOME_NEEDED, false)) {
t.traceBegin("enableHomeActivity");
ComponentName cName = new ComponentName(mContext, SystemUserHomeActivity.class);
try {
AppGlobals.getPackageManager().setComponentEnabledSetting(cName,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0,
UserHandle.USER_SYSTEM);
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
}
t.traceEnd();
}
if (bootingSystemUser) {
t.traceBegin("startHomeOnAllDisplays");
// 启动Home Activity
mAtmInternal.startHomeOnAllDisplays(currentUserId, "systemReady");
t.traceEnd();
}
...
}
}
由于AMS.systemReady()启动的很复杂,目前没有要详细追踪的类,只会沿着启动Launcher或者开机引导程序的线进行分析。
3.Home Activity配置对象
Home activity根据是否注册system uid来判断是启动Launch还是setup wizard。
- Android 11中set wizard的App是Provision,路径在:/packages/apps/Provison;
- Launcher3和Provision的主Activity中的intent-filter,都包含action=MAIN,category=HOME and Default,这是AMS拉起Home activity的主要依据。
3.1 Provision的AndroidManifest.xml
下边是Provision的AndroidManifest.xml中Activity的intent,请于后边Launcher3的AndroidManifest.xml对比看。
<!-- packages/apps/Provision/AndroidManifest.xml -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.provision">
<original-package android:name="com.android.provision" />
<!-- For miscellaneous settings -->
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
<application>
<activity android:name="DefaultActivity"
android:excludeFromRecents="true">
<intent-filter android:priority="1">
<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.SETUP_WIZARD" />
</intent-filter>
</activity>
</application>
</manifest>
Provision模块的Android.bp文件如下:
// packages/apps/Provision/Android.bp
android_app {
name: "Provision",
srcs: ["**/*.java"],
platform_apis: true,
system_ext_specific: true,
certificate: "platform",
privileged: true,
required: ["privapp_whitelist_com.android.provision"],
optimize: {
proguard_flags_files: ["proguard.flags"],
},
}
Setup wizard app只有一个DefaultActivity,启动完成后会设置Provision state,而且还会把自己从package manger中remove并finish该Activity。
// packages/apps/Provision/src/com/android/provision/DefaultActivity.java
public class DefaultActivity extends Activity {
@Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
// Add a persistent setting to allow other apps to know the device has been provisioned.
Settings.Global.putInt(getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 1);
Settings.Secure.putInt(getContentResolver(), Settings.Secure.USER_SETUP_COMPLETE, 1);
// remove this activity from the package manager.
PackageManager pm = getPackageManager();
ComponentName name = new ComponentName(this, DefaultActivity.class);
pm.setComponentEnabledSetting(name, PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP);
// terminate the activity.
finish();
}
}
3.2 Launcher3的AndroidManifest.xml
<!-- packages/apps/Launcher3/AndroidManifest.xml -->
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.launcher3">
<uses-sdk android:targetSdkVersion="29" android:minSdkVersion="25"/>
<!--
Manifest entries specific to Launcher3\. This is merged with AndroidManifest-common.xml.
Refer comments around specific entries on how to extend individual components.
-->
<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/AppTheme"
android:largeHeap="@bool/config_largeHeap"
android:restoreAnyVersion="true"
android:supportsRtl="true" >
<!--
Main launcher activity. When extending only change the name, and keep all the
attributes and intent filters the same
-->
<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|uiMode"
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>
<meta-data
android:name="com.android.launcher3.grid.control"
android:value="${packageName}.grid_control" />
</activity>
</application>
</manifest>
4.startHomeOnAllDisplays()
回到《2.AMS.systemReady()》中,ActivityManagerService.systemReady()中启动Home Activity:
// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
if (bootingSystemUser) {
t.traceBegin("startHomeOnAllDisplays");
// 启动Home Activity
mAtmInternal.startHomeOnAllDisplays(currentUserId, "systemReady");
t.traceEnd();
}
其中mAtmInternal就是ActivityTaskManagerInternal,它就是ActivityTaskManagerService.java中内部类LocalService的对象。
4.1 LocalService.startHomeOnAllDisplays()
LocalService中的startHomeOnAllDisplays()方法如下:
// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public boolean startHomeOnAllDisplays(int userId, String reason) {
synchronized (mGlobalLock) {
// 调用RootWindowContainer的startHomeOnAllDisplays(),最终到startHomeOnDisplay()
return mRootWindowContainer.startHomeOnAllDisplays(userId, reason);
}
}
4.2 RootWindowContainer.startHomeOnAllDisplays()
// frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java
boolean startHomeOnAllDisplays(int userId, String reason) {
boolean homeStarted = false;
for (int i = getChildCount() - 1; i >= 0; i--) {
final int displayId = getChildAt(i).mDisplayId;
// 遍历所有child的display,对每一个displayId调用startHomeOnDisplay()
homeStarted |= startHomeOnDisplay(userId, reason, displayId);
}
return homeStarted;
}
//----------------------------------------
boolean startHomeOnDisplay(int userId, String reason, int displayId) {
return startHomeOnDisplay(userId, reason, displayId, false /* allowInstrumenting */,
false /* fromHomeKey */);
}
//----------------------------------------
boolean startHomeOnDisplay(int userId, String reason, int displayId, boolean allowInstrumenting,
boolean fromHomeKey) {
// Fallback to top focused display or default display if the displayId is invalid.
if (displayId == INVALID_DISPLAY) {
final ActivityStack stack = getTopDisplayFocusedStack();
displayId = stack != null ? stack.getDisplayId() : DEFAULT_DISPLAY;
}
final DisplayContent display = getDisplayContent(displayId);
boolean result = false;
for (int tcNdx = display.getTaskDisplayAreaCount() - 1; tcNdx >= 0; --tcNdx) {
final TaskDisplayArea taskDisplayArea = display.getTaskDisplayAreaAt(tcNdx);
result |= startHomeOnTaskDisplayArea(userId, reason, taskDisplayArea,
allowInstrumenting, fromHomeKey);
}
return result;
}
4.3 RootWindowContainer.startHomeOnTaskDisplayArea()
该方法主要工作:
- 调用AMS的getHomeIntent()获取action=MAIN and category=home的Intent;
- 接着调用本类的resolveHomeActivity(),该方法会通过PMS查询得到homeIntent对应的ActivityInfo和对应的applicationinfo,即得到Launcher3的信息;
- 调用ActivityStartController.startHomeActivity()。
// frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java
boolean startHomeOnTaskDisplayArea(int userId, String reason, TaskDisplayArea taskDisplayArea,
boolean allowInstrumenting, boolean fromHomeKey) {
// Fallback to top focused display area if the provided one is invalid.
// // AMS.systemReady()启动home activity时taskDisplayArea=null
if (taskDisplayArea == null) {
final ActivityStack stack = getTopDisplayFocusedStack();
taskDisplayArea = stack != null ? stack.getDisplayArea()
: getDefaultTaskDisplayArea();
}
Intent homeIntent = null;
ActivityInfo aInfo = null;
if (taskDisplayArea == getDefaultTaskDisplayArea()) {
// 1.调用ATMS的获取Category=HOME的Intent
homeIntent = mService.getHomeIntent();
// 2.解析homeIntent对应的ActivityInfo,包含applicationInfo,即得到Launcher3的信息
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) {//该fromHomeKey=false
homeIntent.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, true);
mWindowManager.cancelRecentsAnimation(REORDER_KEEP_IN_PLACE, "startHomeActivity");
}
// Update the reason for ANR debugging to verify if the user activity is the one that
// actually launched.
final String myReason = reason + ":" + userId + ":" + UserHandle.getUserId(
aInfo.applicationInfo.uid) + ":" + taskDisplayArea.getDisplayId();
//3.启动Home Activity--Luncher
mService.getActivityStartController().startHomeActivity(homeIntent, aInfo, myReason,
taskDisplayArea);
return true;
}
4.3.1 ATMS.getHomeIntent()
// frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
ComponentName mTopComponent;
String mTopAction = Intent.ACTION_MAIN;
String mTopData;
//返回的是action=MAIN and category=HOME的Intent。
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;
}
}
4.3.2 RootWindowContainer.resolveHomeActivity()
// frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java
ActivityInfo resolveHomeActivity(int userId, Intent homeIntent) {
final int flags = ActivityManagerService.STOCK_PM_FLAGS;
final ComponentName comp = homeIntent.getComponent();
ActivityInfo aInfo = null;
try {
if (comp != null) {
// Factory test.
aInfo = AppGlobals.getPackageManager().getActivityInfo(comp, flags, userId);
} else {
final String resolvedType =
homeIntent.resolveTypeIfNeeded(mService.mContext.getContentResolver());
//根据homeIntent在PMS中查找得到最优的activity
final ResolveInfo info = AppGlobals.getPackageManager()
.resolveIntent(homeIntent, resolvedType, flags, userId);
if (info != null) {
aInfo = info.activityInfo;
}
}
} catch (RemoteException e) {
// ignore
}
if (aInfo == null) {
Slog.wtf(TAG, "No home screen found for " + homeIntent, new Throwable());
return null;
}
aInfo = new ActivityInfo(aInfo);
aInfo.applicationInfo = mService.getAppInfoForUser(aInfo.applicationInfo, userId);
return aInfo;
}
4.4 ActivityStartController.startHomeActivity()
继续《4.3》中的流程:
//3.启动Home Activity--Luncher
mService.getActivityStartController().startHomeActivity(homeIntent, aInfo, myReason,
taskDisplayArea);
这里的mService就是ActivityTaskManagerService,通过getActivityStartController()获取到ActivityStartController对象,然后再调用该对象的startHomeActivity()方法:
// frameworks/base/services/core/java/com/android/server/wm/ActivityStartController.java
public class ActivityStartController {
private final ActivityStackSupervisor mSupervisor;
private int mLastHomeActivityStartResult;
ActivityStarter obtainStarter(Intent intent, String reason) {
return mFactory.obtain().setIntent(intent).setReason(reason);
}
void startHomeActivity(Intent intent, ActivityInfo aInfo, String reason,
TaskDisplayArea taskDisplayArea) {
final ActivityOptions options = ActivityOptions.makeBasic();
options.setLaunchWindowingMode(WINDOWING_MODE_FULLSCREEN);
if (!ActivityRecord.isResolverActivity(aInfo.name)) {
// The resolver activity shouldn't be put in home stack because when the foreground is
// standard type activity, the resolver activity should be put on the top of current
// foreground instead of bring home stack to front.
options.setLaunchActivityType(ACTIVITY_TYPE_HOME);
}
final int displayId = taskDisplayArea.getDisplayId();
options.setLaunchDisplayId(displayId);
options.setLaunchTaskDisplayArea(taskDisplayArea.mRemoteToken
.toWindowContainerToken());
// The home activity will be started later, defer resuming to avoid unneccerary operations
// (e.g. start home recursively) when creating home stack.
mSupervisor.beginDeferResume();
final ActivityStack homeStack;
try {
// Make sure home stack exists on display area.
homeStack = taskDisplayArea.getOrCreateRootHomeTask(ON_TOP);
} finally {
mSupervisor.endDeferResume();
}
//调用obtainStarter获取一个ActivityStarter对象,由它负责Activity的启动
//设置各种参数,最后执行excute()来启动Home Activity
mLastHomeActivityStartResult = obtainStarter(intent, "startHomeActivity: " + reason)
.setOutActivity(tmpOutRecord)
.setCallingUid(0)
.setActivityInfo(aInfo)
.setActivityOptions(options.toBundle())
.execute();
mLastHomeActivityStartRecord = tmpOutRecord[0];
if (homeStack.mInResumeTopActivity) {
// 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对象,由他负责activity的启动,通过设置各种参数,最后调用其excute()真正启动homeActivity。
4.5 ActivityStarter.execute()
// frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
class ActivityStarter {
int execute() {
...
int res;
res = executeRequest(mRequest);
...
}
}
4.6 ActivityStarter.executeRequset()
// frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
private int executeRequest(Request request) {
...
// 创建ActivityRecord
final ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
callingPackage, callingFeatureId, intent, resolvedType, aInfo,
mService.getGlobalConfiguration(), resultRecord, resultWho, requestCode,
request.componentSpecified, voiceSession != null, mSupervisor, checkedOptions,
sourceRecord);
mLastStartActivityRecord = r;
...
//调用startActivityUnchecked()启动activity
mLastStartActivityResult = startActivityUnchecked(r, sourceRecord, voiceSession,
request.voiceInteractor, startFlags, true /* doResume */, checkedOptions, inTask,
restrictedBgActivity, intentGrants);
if (request.outActivity != null) {
request.outActivity[0] = mLastStartActivityRecord;
}
return mLastStartActivityResult;
}
4.7 ActivityStarter.startActivityUnchecked()
// frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
int startFlags, boolean doResume, ActivityOptions options, Task inTask,
boolean restrictedBgActivity, NeededUriGrants intentGrants) {
int result = START_CANCELED;
final ActivityStack startedActivityStack;
try {
mService.deferWindowLayout();
Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "startActivityInner");
//调用startActivityInner()启动activity
result = startActivityInner(r, sourceRecord, voiceSession, voiceInteractor,
startFlags, doResume, options, inTask, restrictedBgActivity, intentGrants);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
startedActivityStack = handleStartResult(r, result);
mService.continueWindowLayout();
}
postStartActivityProcessing(r, result, startedActivityStack);
return result;
}
4.8 ActivityStarter.startActivityInner()
// frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
int startActivityInner(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
int startFlags, boolean doResume, ActivityOptions options, Task inTask,
boolean restrictedBgActivity, NeededUriGrants intentGrants) {
setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
voiceInteractor, restrictedBgActivity);
...
final ActivityRecord targetTaskTop = newTask
? null : targetTask.getTopNonFinishingActivity();
if (targetTaskTop != null) {
// Recycle the target task for this launch.
startResult = recycleTask(targetTask, targetTaskTop, reusedTask, intentGrants);
if (startResult != START_SUCCESS) {
return startResult;
}
} else {
mAddingToTask = true;
}
...
mRootWindowContainer.resumeFocusedStacksTopActivities(
mTargetStack, mStartActivity, mOptions);
...
}
4.9 RootWindowContainer.resumeFocusedStacksTopActivities()
// frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java
boolean resumeFocusedStacksTopActivities(
ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
if (!mStackSupervisor.readyToResume()) {
return false;
}
boolean result = false;
if (targetStack != null && (targetStack.isTopStackInDisplayArea()
|| getTopDisplayFocusedStack() == targetStack)) {
result = targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
}
...
}
4.10 ActivityStack.resumeTopActivityUncheckedLocked()
// frameworks/base/services/core/java/com/android/server/wm/ActivityStack.java
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
...
mInResumeTopActivity = true;
result = resumeTopActivityInnerLocked(prev, options);
...
}
4.11 ActivityStack.resumeTopActivityInnerLocked()
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
...
mStackSupervisor.startSpecificActivity(next, true, false);
...
}
4.12 ActivityStackSupervisor.startSpecificActivity()
该方法是判断要启动activity的进程是否已存在,存在的话调用自身的realStartActivityLocked(),不存在则最终会调用AMS.startProcessAsync()。
// frameworks/base/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
void startSpecificActivity(ActivityRecord r, boolean andResume, boolean checkConfig) {
// Is this activity's application already running?
//1\. 判断Launcher的进程是否运行
final WindowProcessController wpc =
mService.getProcessController(r.processName, r.info.applicationInfo.uid);
boolean knownToBeDead = false;
if (wpc != null && wpc.hasThread()) {
try {
//2.要启动的activity的进程已存在,则启动该activity
realStartActivityLocked(r, wpc, andResume, checkConfig);
return;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting activity "
+ r.intent.getComponent().flattenToShortString(), e);
}
// If a dead object exception was thrown -- fall through to
// restart the application.
knownToBeDead = true;
}
r.notifyUnknownVisibilityLaunchedForKeyguardTransition();
final boolean isTop = andResume && r.isTopRunningActivity();
//3.Launcher的进程不存在,则调用ATMS来启动进程
mService.startProcessAsync(r, knownToBeDead, isTop, isTop ? "top-activity" : "activity");
}
接下来就是AMS向Zygote进程请求fork一个launcher进程,就完成了Launcher应用的启动。
网友评论