Android system startup
1, "Introduction to the Android System Startup Process"
2, "Android init process startup process"
3. "Android zygote process startup process"
4. "Android SystemServer Process Startup Process"
5. "Android launcher startup process"
6. "Detailed Explanation of Android Activity Startup Process"
Android System Development Preparation
1, "Android Source Code Download and Compilation"
2. "Android 11 source code compilation and pixel3 flashing"
3. "Android Framework Code IDE Loading and Debugging"
Android System Development Practice
1. "Android Setting Default Input Method"
2, "android framework prefabricated APK application"
3. "Detailed Explanation of Restricting Apps from Starting at the Android System Level"
4. "Android compiles the framework module separately and pushes it"
5. "Android Framework Development System Problem Analysis"
Android System Development Core Knowledge Reserve
1, "Android Compilation System - envsetup and lunch code articles"
2. "Android Compilation System - Concept"
3. "Detailed Explanation of Android Log System"
4. "Android System Handler Detailed Explanation"
5. "Android System Binder Detailed Explanation"
6. "Detailed Explanation of the Relationship between Activity, View and Window in Android"
7. "Detailed Explanation of the Android View Drawing Process"
8. "Detailed Explanation of Android Reading System Attributes"
9. "Detailed Explanation of Android Window Management Mechanism"
10. "Acquaintance with Android System"
11. "The communication method of AMS process in android notifying Zygote process fork new process"
Detailed explanation of Android core functions
1. "Android application market click to download APK installation details"
2, "Android gesture navigation (swipe from bottom to top to enter the multitasking page)"
4. "Detailed Explanation of Android Application Installation Process"
5, "android11 installation application triggers desktop icon refresh process"
6. "Detailed Explanation of Android System Multitasking Recents"
7. "Android System Navigation Bar View Analysis"
———————————————————————————————————————————
Table of contents
2.1.2 App icon entry on Launcher desktop
2.1.3 startActivitySafely() Method
2.1.4 execStartActivity() method
2.2 ATMS sends the process of creating an application process to AMS
2.2.2 ATMS(ActivityTaskManagerService)
2.3 AMS sends the process of creating the application process ActivityThread to the Zygote process
2.3.2 ActivityTaskManagerService starts the process
2.3.7 ZygoteProcess opens socket connection
2.3.8 ZygoteProcess sends request parameters
2.4 Zygote process fork and start the application process
2.4.2 Zygote process starts and parses the parameters passed in by Socket
2.4.3 ZygoteServer opens Loop to monitor Socket in a loop
2.4.5 Zygote creates child processes (native layer creation)
2.4.6 ZygoteConnection # handleChildProc() method
2.4.7 ZygoteInit # zygoteInit() method
2.4.8 RuntimeInit # applicationInit() method
2.4.9 RuntimeInit # MethodAndArgsCaller
2.5 The application process ActivityThread starts the Activity process
2.5.2 ActivityThread entry method
2.5.3 AMS binding ApplicationThread
2.5.4 ActivityThread creates and binds Application
2.5.5 ProcessRecord save ApplicationThread
2.5.6 ATMS binds WindowProcessController and starts root Activity
2.5.7 RootWindowContainer 绑定 WindowProcessController
2.5.8 Get ClientTransaction, add Callback, set LifecycleStateRequest
2.5.9 ClientTransaction get and add transaction callback
2.5.10 ClientLifecycleManager Client Lifecycle Transaction Transition Manager
2.5.11 ClientTransaction # schedule() scheduling transaction
2.5.12 ActivityThread Scheduling Transaction
2.5.13 TransactionExecutor transaction conversion executor
2.5.14 LaunchActivityItem request to start Activity
2.5.15 ActivityThread executes and starts the Activity transaction
2.5.16 ActivityThread executes lifecycle transactions
2.5.17 TransactionExecutor executes intermediate state life cycle request transactions
2.5.18 TransactionExecutorHelper obtains the status sequence of the life cycle to be executed
2.5.19 TransactionExecutor executes the final conversion of lifecycle transactions
1. Background introduction
There are two types of Activity startup processes: one is to start an Activity through the startActivity (Intent intent) method in the activity; the other is to start an App by clicking the application icon on the desktop and then display the Activity; the second method is compared with the first method. It is more comprehensive and complex, so this article will use the second process to analyze and explain.
The start-up process is roughly divided into the following five stages:
1. The Launcher process requests to call the ATMS system process process.
2. ATMS sends the process of creating the application process to AMS.
3. AMS sends the process of creating the application process ActivityThread to the Zygote process.
4. The Zygote process receives the request to fork and starts the process of the application process ActivityThread
. 5. The process of starting the Activity by the application process ActivityThread
Two, Activity startup process
Click an application icon in the Launcher to display the first Activity of the application. When the system is turned on, the Launcher will be started by AMS, and then the installed application icon will be displayed on the desktop. So when we click an application icon, it is actually It is equivalent to clicking a Button in the Activity, and the corresponding event is that the Launcher process requests ATMS to start the application.
2.1 Call ATMS system process
2.1.1 Timing diagram
2.1.2 App icon entry on Launcher desktop
The manifest.xml definition of Launcher3, the path packages/apps/Launcher3/AndroidManifest.xml
<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>
<meta-data
android:name="com.android.launcher3.grid.control"
android:value="${packageName}.grid_control" />
</activity>
From the above definition, we can see that the com.android.launcher3.Launcher.java file is the desktop home page, and the source code is as follows:
public class Launcher extends StatefulActivity<LauncherState> implements LauncherExterns,Callbacks, InvariantDeviceProfile.OnIDPChangeListener, PluginListener<OverlayPlugin>,LauncherOverlayCallbacks {
@Override
@TargetApi(Build.VERSION_CODES.S)
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
......
// 分析1 -- 加载、展示布局文件
inflateRootView(R.layout.launcher);
}
}
The layout file R.layout.launcher is as follows,
<!-- R.layout.launcher -->
<?xml version="1.0" encoding="utf-8"?>
<com.android.launcher3.LauncherRootView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:launcher="http://schemas.android.com/apk/res-auto"
android:id="@+id/launcher"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<com.android.launcher3.dragndrop.DragLayer
android:id="@+id/drag_layer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipChildren="false"
android:clipToPadding="false"
android:importantForAccessibility="no">
<!-- 这里是展示所有 App 图标的布局,我们只看相关代码 -->
<include
android:id="@+id/apps_view"
layout="@layout/all_apps"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</com.android.launcher3.dragndrop.DragLayer>
</com.android.launcher3.LauncherRootView>
<!-- R.layout.apps_view -->
<?xml version="1.0" encoding="utf-8"?>
<com.android.launcher3.allapps.LauncherAllAppsContainerView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/apps_view"
android:theme="?attr/allAppsTheme"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipChildren="true"
android:clipToPadding="false"
android:focusable="false"
android:saveEnabled="false">
<!-- 展示所有已安装 app 的 AllAppsRecyclerView 继承自 RecyclerView -->
<include
layout="@layout/all_apps_rv_layout"
android:visibility="gone" />
</com.android.launcher3.allapps.LauncherAllAppsContainerView>
<!-- R.layout.all_apps_rv_layout -->
<?xml version="1.0" encoding="utf-8"?>
<com.android.launcher3.allapps.AllAppsRecyclerView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/apps_list_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/search_container_all_apps"
android:clipToPadding="false"
android:descendantFocusability="afterDescendants"
android:focusable="true" />
The outer layer of AllAppsRecyclerView is LauncherAllAppsContainerView, which is a subclass of AllAppsContainerView. The Adapter set for AllAppsRecyclerView is encapsulated into AllAppsContainerView, take a look at the code:
/**
* The all apps view container.
*/
public class AllAppsContainerView extends SpringRelativeLayout implements DragSource,
Insettable, OnDeviceProfileChangeListener, OnActivePageChangedListener,
ScrimView.ScrimDrawingController {
protected void rebindAdapters(boolean force) {
......
if (mUsingTabs) {
......
// 这里只分析不使用 Tabs 的情况,感兴趣的童鞋可以继续追源码
} else {
// AllAppsRecyclerView 设置 Adapter 等信息
mAH[AdapterHolder.MAIN].setup(findViewById(R.id.apps_list_view), null);
mAH[AdapterHolder.WORK].recyclerView = null;
}
......
}
public class AdapterHolder {
public static final int MAIN = 0;
public static final int WORK = 1;
public final AllAppsGridAdapter adapter;
final LinearLayoutManager layoutManager;
final AlphabeticalAppsList appsList;
AllAppsRecyclerView recyclerView;
AdapterHolder(boolean isWork) {
mIsWork = isWork;
appsList = new AlphabeticalAppsList(mLauncher, mAllAppsStore,
isWork ? mWorkManager.getAdapterProvider() : null);
BaseAdapterProvider[] adapterProviders =
isWork ? new BaseAdapterProvider[]{mSearchAdapterProvider,
mWorkManager.getAdapterProvider()}
: new BaseAdapterProvider[]{mSearchAdapterProvider};
adapter = new AllAppsGridAdapter(mLauncher, getLayoutInflater(), appsList,
adapterProviders);
appsList.setAdapter(adapter);
layoutManager = adapter.getLayoutManager();
}
void setup(@NonNull View rv, @Nullable ItemInfoMatcher matcher) {
appsList.updateItemFilter(matcher);
recyclerView = (AllAppsRecyclerView) rv;
recyclerView.setEdgeEffectFactory(createEdgeEffectFactory());
recyclerView.setApps(appsList);
recyclerView.setLayoutManager(layoutManager);
// AllAppsRecyclerView 设置 AllAppsGridAdapter
recyclerView.setAdapter(adapter);
}
}
}
In the source code, AllAppsGridAdapter is set for AllAppsRecyclerView in AllAppsContainerView, and then click event ItemClickHandler.INSTANCE is set for subitem itemView in AllAppsGridAdapter # onCreateViewHolder() method, and the click event is obtained by launcher.getItemOnClickListener() method. Take a look at how ItemClickHandler handles click events, the code is as follows:
/**
* Class for handling clicks on workspace and all-apps items
*/
public class ItemClickHandler {
private static final String TAG = ItemClickHandler.class.getSimpleName();
/**
* Instance used for click handling on items
* 单例方式获取点击事件
*/
public static final OnClickListener INSTANCE = ItemClickHandler::onClick;
private static void onClick(View v) {
if (v.getWindowToken() == null) return;
Launcher launcher = Launcher.getLauncher(v.getContext());
if (!launcher.getWorkspace().isFinishedSwitchingState()) return;
Object tag = v.getTag();
if (tag instanceof WorkspaceItemInfo) {
onClickAppShortcut(v, (WorkspaceItemInfo) tag, launcher);
} else if (tag instanceof FolderInfo) {
if (v instanceof FolderIcon) {
onClickFolderIcon(v);
}
} else if (tag instanceof AppInfo) {
// 点击 App 图标
startAppShortcutOrInfoActivity(v, (AppInfo) tag, launcher
);
} else if (tag instanceof LauncherAppWidgetInfo) {
if (v instanceof PendingAppWidgetHostView) {
onClickPendingWidget((PendingAppWidgetHostView) v, launcher);
}
} else if (tag instanceof SearchActionItemInfo) {
onClickSearchAction(launcher, (SearchActionItemInfo) tag);
}
}
private static void startAppShortcutOrInfoActivity(View v, ItemInfo item, Launcher launcher) {
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 (intent == null) {
throw new IllegalArgumentException("Input must have a valid intent");
}
if (item instanceof WorkspaceItemInfo) {
WorkspaceItemInfo si = (WorkspaceItemInfo) item;
if (si.hasStatusFlag(WorkspaceItemInfo.FLAG_SUPPORTS_WEB_UI)
&& Intent.ACTION_VIEW.equals(intent.getAction())) {
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;
}
}
if (v != null && launcher.supportsAdaptiveIconAnimation(v)) {
// Preload the icon to reduce latency b/w swapping the floating view with the original.
FloatingIconView.fetchIcon(launcher, v, item, true /* isOpening */);
}
// 调用 Launcher # startActivitySafely() 启动 Activity
launcher.startActivitySafely(v, intent, item);
}
}
To answer the above question, AllAppsRecyclerView has set AllAppsGridAdapter in AllAppsContainerView, and set click event ItemClickHandler.INSTANCE for child itemView in AllAppsGridAdapter # onCreateViewHolder() method.
2.1.3 startActivitySafely() Method
/**
* Default launcher application.
*/
public class Launcher extends StatefulActivity<LauncherState> implements LauncherExterns,
Callbacks, InvariantDeviceProfile.OnIDPChangeListener, PluginListener<OverlayPlugin>,
LauncherOverlayCallbacks {
@Override
public boolean startActivitySafely(View v, Intent intent, ItemInfo item) {
if (!hasBeenResumed()) {
addOnResumeCallback(() -> startActivitySafely(v, intent, item));
if (mOnDeferredActivityLaunchCallback != null) {
mOnDeferredActivityLaunchCallback.run();
mOnDeferredActivityLaunchCallback = null;
}
return true;
}
boolean success = super.startActivitySafely(v, intent, item);
if (success && v instanceof BubbleTextView) {
BubbleTextView btv = (BubbleTextView) v;
btv.setStayPressed(true);
addOnResumeCallback(() -> btv.setStayPressed(false));
}
return success;
}
}
/**
* Extension of BaseActivity allowing support for drag-n-drop
*/
@SuppressWarnings("NewApi")
public abstract class BaseDraggingActivity extends BaseActivity
implements OnColorsChangedListener, DisplayInfoChangeListener {
public boolean startActivitySafely(View v, Intent intent, @Nullable ItemInfo item) {
......
Bundle optsBundle = (v != null) ? getActivityLaunchOptions(v, item).toBundle() : null;
UserHandle user = item == null ? null : item.user;
// Prepare intent
// 添加 FLAG_ACTIVITY_NEW_TASK,即在新的 Task 中启动 Activity
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (v != null) {
intent.setSourceBounds(Utilities.getViewBounds(v));
}
try {
boolean isShortcut = (item instanceof WorkspaceItemInfo)
&& (item.itemType == Favorites.ITEM_TYPE_SHORTCUT
|| item.itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT)
&& !((WorkspaceItemInfo) item).isPromise();
if (isShortcut) {
// Shortcuts need some special checks due to legacy reasons.
startShortcutIntentSafely(intent, optsBundle, item);
} else if (user == null || user.equals(Process.myUserHandle())) {
// Could be launching some bookkeeping activity
// 点击 App 图标 启动 App
startActivity(intent, optsBundle);
} else {
getSystemService(LauncherApps.class).startMainActivity(
intent.getComponent(), user, intent.getSourceBounds(), optsBundle);
}
if (item != null) {
InstanceId instanceId = new InstanceIdSequence().newInstanceId();
logAppLaunch(getStatsLogManager(), item, instanceId);
}
return true;
} catch (NullPointerException | ActivityNotFoundException | SecurityException e) {
......
}
return false;
}
}
When the root Activity starts, add FLAG_ACTIVITY_NEW_TASK , that is, start the Activity in a new task stack Task, and then call the Activity # startActivity() method, and the incoming parameters are intent and Bundle. code show as below:
public class Activity extends ContextThemeWrapper
implements ... {
@Override
public void startActivity(Intent intent, @Nullable Bundle options) {
if (options != null) {
// 通过 startActivityForResult 启动 Activity
startActivityForResult(intent, -1, options);
} else {
startActivityForResult(intent, -1);
}
}
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
@Nullable Bundle options) {
// mParent 表示当前 Activity 的父 Activity,一般情况下 mParent 为空
if (mParent == null) {
options = transferSpringboardActivityOptions(options);
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);
if (ar != null) {
mMainThread.sendActivityResult(
mToken, mEmbeddedID, requestCode, ar.getResultCode(),
ar.getResultData());
}
if (requestCode >= 0) {
mStartedActivity = true;
}
cancelInputsAndStartExitTransition(options);
} else {
if (options != null) {
mParent.startActivityFromChild(this, intent, requestCode, options);
} else {
mParent.startActivityFromChild(this, intent, requestCode);
}
}
}
}
The Activity # startActivity() method calls the Activity # startActivityForResult() method, and the second parameter of Activity # startActivity() is -1 to indicate that the Launcher does not need to know the startup result of the root Activity. Since mParent=null (mParent represents the parent Activity of the current Activity, and mParent is generally empty), we only need to pay attention to the case of mParent=null, and the Instrumentation # execStartActivity() method will be called at this time.
2.1.4 execStartActivity() method
Instrumentation is responsible for invoking the life cycle of Activity and Application. Each Activity holds a reference to the Instrumentation object, but there will only be one Instrumentation object in the entire process. Follow up and take a look at the Instrumentation # execStartActivity () method, the code is as follows:
@UnsupportedAppUsage
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
......
try {
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess(who);
// 获取 ActivityTaskManagerService 的代理对象
int result = ActivityTaskManager.getService()
.startActivity(whoThread, who.getBasePackageName(), 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;
}
Instrumentation # execStartActivity() method will call ActivityTaskManager # getService() method to get the proxy object of ActivityTaskManagerService, and then call the startActivity() method of this proxy object.
public static IActivityTaskManager getService() {
return IActivityTaskManagerSingleton.get();
}
@UnsupportedAppUsage(trackingBug = 129726065)
private static final Singleton<IActivityTaskManager> IActivityTaskManagerSingleton =
new Singleton<IActivityTaskManager>() {
@Override
protected IActivityTaskManager create() {
final IBinder b = ServiceManager.getService(Context.ACTIVITY_TASK_SERVICE);
return IActivityTaskManager.Stub.asInterface(b);
}
};
In the create() method of Singleton, obtain the reference of ActivityTaskManagerService, which is a reference of IBinder type, and ActivityTaskManagerService is in the system_server process as the server, and is not in the same process as the current Launcher process as the client. So the method here returns the proxy object of IActivityTaskManager.Stub, and ActivityTaskManagerService is the corresponding implementation class, which inherits IActivityTaskManager.Stub and implements the corresponding methods. The method of the server-side ActivityTaskManagerService can be called across processes through the proxy object.
2.2 ATMS sends the process of creating an application process to AMS
The startBootstrapServices() method in the system_server process starts the system bootstrap service. ATMS (ActivityTaskManagerServici), AMS and other services are started in the bootstrap service. ATMS is a new addition in Android 10. It was originally managed by AMS. Google considers that AMS has too many responsibilities , The code is too huge, so ATMS is separated out to manage Activity and its container classes, such as Task, Stack, Display, etc., to share part of the responsibilities of AMS.
2.2.1 Timing diagram
2.2.2 ATMS(ActivityTaskManagerService)
Through the above analysis, the startup process has come to ATMS, calling the ATMS # startActivity() method, the code is as follows:
@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) {
// UserHandle.getCallingUserId() 方法会获取调用者的 UserId
return startActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType,
resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions,
UserHandle.getCallingUserId());
}
@Override
public int startActivityAsUser(IApplicationThread caller, String callingPackage,
String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo,
String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo,
Bundle bOptions, int userId) {
return startActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType,
resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions, userId,
true /*validateIncomingUser*/);
}
private 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) {
assertPackageMatchesCallingUid(callingPackage);
// 检查调用者的进程是否隔离,如果 isIsolated 则抛出 SecurityException 异常
enforceNotIsolatedCaller("startActivityAsUser");
// 检查调用者权限,ATMS 根据传入的 UserId 来确定调用者的权限
userId = getActivityStartController().checkTargetUser(userId, validateIncomingUser,
Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");
// TODO: Switch to user app stacks here.
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();
}
// 获取 ActivityStartController
ActivityStartController getActivityStartController() {
return mActivityStartController;
}
2.2.3 ActivityStartController
/**
* @return A starter to configure and execute starting an activity. It is valid until after
* {@link ActivityStarter#execute} is invoked. At that point, the starter should be
* considered invalid and no longer modified or used.
*/
ActivityStarter obtainStarter(Intent intent, String reason) {
return mFactory.obtain().setIntent(intent).setReason(reason);
}
After obtaining the ActivityStarter object, set various parameter values required for starting through the Builder mode, and then execute and start the Activity. ActivityStarter is added in Android 7.0 and is used to load the control class that starts the Activity.
2.2.4 ActivityStarter
class ActivityStarter {
@VisibleForTesting
interface Factory {
// Sets the {@link ActivityStartController} to be passed to {@link ActivityStarter}.
void setController(ActivityStartController controller);
// 生成一个准备处理新启动请求的 ActivityStarter,ActivityStartController 持有这个实例对象
ActivityStarter obtain();
// Recycles a starter for reuse.
void recycle(ActivityStarter starter);
}
// Default implementation of {@link StarterFactory}.
static class DefaultFactory implements Factory {
// 被激活的启动器的最大数
private final int MAX_STARTER_COUNT = 3;
private ActivityStartController mController;
private ActivityTaskManagerService mService;
private ActivityStackSupervisor mSupervisor;
private ActivityStartInterceptor mInterceptor;
private SynchronizedPool<ActivityStarter> mStarterPool =
new SynchronizedPool<>(MAX_STARTER_COUNT);
DefaultFactory(ActivityTaskManagerService service,
ActivityStackSupervisor supervisor, ActivityStartInterceptor interceptor) {
mService = service;
mSupervisor = supervisor;
mInterceptor = interceptor;
}
@Override
public void setController(ActivityStartController controller) {
mController = controller;
}
@Override
public ActivityStarter obtain() {
ActivityStarter starter = mStarterPool.acquire();
if (starter == null) {
starter = new ActivityStarter(mController, mService, mSupervisor, mInterceptor);
}
return starter;
}
@Override
public void recycle(ActivityStarter starter) {
starter.reset(true /* clearRequest*/);
mStarterPool.release(starter);
}
}
/**
* Resolve necessary information according the request parameters provided earlier, and execute
* the request which begin the journey of starting an activity.
* @return The starter result.
*/
int execute() {
try {
int res;
synchronized (mService.mGlobalLock) {
final boolean globalConfigWillChange = mRequest.globalConfig != null
&& mService.getGlobalConfiguration().diff(mRequest.globalConfig) != 0;
final ActivityStack stack = mRootWindowContainer.getTopDisplayFocusedStack();
if (stack != null) {
stack.mConfigWillChange = globalConfigWillChange;
}
final long origId = Binder.clearCallingIdentity();
res = resolveToHeavyWeightSwitcherIfNeeded();
if (res != START_SUCCESS) {
return res;
}
// 继续调用 executeRequest() 方法
res = executeRequest(mRequest);
Binder.restoreCallingIdentity(origId);
if (globalConfigWillChange) {
......
mService.updateConfigurationLocked(mRequest.globalConfig, null, false);
}
// Notify ActivityMetricsLogger that the activity has launched.
// ActivityMetricsLogger will then wait for the windows to be drawn and populate
// WaitResult.
mSupervisor.getActivityMetricsLogger().notifyActivityLaunched(launchingState, res,
mLastStartActivityRecord);
return getExternalResult(mRequest.waitResult == null ? res
: waitForResult(res, mLastStartActivityRecord));
}
} finally {
onExecutionComplete();
}
}
private int executeRequest(Request request) {
......
// 创建 ActivityRecord,保存 Activity 的所有信息
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;
......
final ActivityStack stack = mRootWindowContainer.getTopDisplayFocusedStack();
mLastStartActivityResult = startActivityUnchecked(r, sourceRecord, voiceSession,
request.voiceInteractor, startFlags, true /* doResume */, checkedOptions, inTask,
restrictedBgActivity, intentGrants);
......
return mLastStartActivityResult;
}
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;
try {
mService.deferWindowLayout();
result = startActivityInner(r, sourceRecord, voiceSession, voiceInteractor,
startFlags, doResume, options, inTask, restrictedBgActivity, intentGrants);
}
......
return result;
}
@VisibleForTesting
int startActivityInner(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
int startFlags, boolean doResume, ActivityOptions options, Task inTask,
boolean restrictedBgActivity, NeededUriGrants intentGrants) {
......
if (mDoResume) {
final ActivityRecord topTaskActivity =
mStartActivity.getTask().topRunningActivityLocked();
if (!mTargetStack.isTopActivityFocusable()
|| (topTaskActivity != null && topTaskActivity.isTaskOverlay()
&& mStartActivity != topTaskActivity)) {
......
mTargetStack.ensureActivitiesVisible(null /* starting */,
0 /* configChanges */, !PRESERVE_WINDOWS);
// Go ahead and tell window manager to execute app transition for this activity
// since the app transition will not be triggered through the resume channel.
mTargetStack.getDisplay().mDisplayContent.executeAppTransition();
} else {
......
mRootWindowContainer.resumeFocusedStacksTopActivities(
mTargetStack, mStartActivity, mOptions);
}
}
}
}
Obtain ActivityStartController in the first step above, call its obtainStarter() method, and obtain ActivityStarter through the internally implemented DefaultFactory. If it is not obtained in mStarterPool, create a new one.
The above mentioned that the ActivityStarter class is the control class used to load and start the Activity. In the ActivityStarter # execute() method, the ActivityStarter # executeRequest() method will continue to be called. Here, the request to start the Activity will be processed and an Activity startup process will be started.
The ActivityStarter # executeRequest() method will conduct a preliminary check and confirm the permissions, and assemble the ActivityRecord corresponding to the Activity here, which contains all the information of the corresponding Activity and store it in the task stack TaskRecord. During the startup process of the Activity, the Activity is represented by the ActivityRecord. Then continue to call the ActivityStarter # startActivityUnchecked() method, and then the ActivityStarter # startActivityUnchecked() method will call the ActivityStarter # startActivityInner() method.
In the ActivityStarter # startActivityInner() method, it mainly deals with the logic related to the startup mode of the Activity, and handles the related matters of the corresponding Activity in the task stack in the ActivityStack, including but not limited to adding the corresponding ActivityRecord to the TaskRecord stack, adding The corresponding ActivityRecord is mentioned at the top of the TaskRecord stack.
Finally, call the RootWindowContainer # resumeFocusedStacksTopActivities() method to hand over the startup process to RootWindowContainer.
2.2.5 RootWindowContainer
boolean resumeFocusedStacksTopActivities(
ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
......
boolean result = false;
if (targetStack != null && (targetStack.isTopStackInDisplayArea()
|| getTopDisplayFocusedStack() == targetStack)) {
result = targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
}
for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
boolean resumedOnDisplay = false;
......
if (!resumedOnDisplay) {
// In cases when there are no valid activities (e.g. device just booted or launcher
// crashed) it's possible that nothing was resumed on a display. Requesting resume
// of top activity in focused stack explicitly will make sure that at least home
// activity is started and resumed, and no recursion occurs.
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;
}
RootWindowContainer is the root container of the window container (WindowContainer), manages all window containers, and all windows (Window) and displays (Display) on the device are managed by it.
The RootWindowContainer # resumeFocusedStacksTopActivities() method will resume the activity at the top of the corresponding task stack. Some visibility-related properties will be checked in the method, and then handed over to the ActivityStack # resumeTopActivityUncheckedLocked() method to continue the startup process.
2.2.6 ActivityStack
@GuardedBy("mService")
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
if (mInResumeTopActivity) {
// Don't even start recursing.
return false;
}
boolean result = false;
try {
// Protect against recursion.
mInResumeTopActivity = 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 = topRunningActivity(true /* focusableOnly */);
if (next == null || !next.canTurnScreenOn()) {
checkReadyForSleep();
}
} finally {
mInResumeTopActivity = false;
}
return result;
}
@GuardedBy("mService")
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
if (next.attachedToProcess()) {
......
ActivityRecord lastResumedActivity =
lastFocusedStack == null ? null : lastFocusedStack.mResumedActivity;
final ActivityState lastState = next.getState();
next.setState(RESUMED, "resumeTopActivityInnerLocked");
next.app.updateProcessInfo(false /* updateServiceConnectionActivities */,
true /* activityChange */, true /* updateOomAdj */,
true /* addPendingTopUid */);
// From this point on, if something goes wrong there is no way
// to recover the activity.
try {
next.completeResumeLocked();
} catch (Exception e) {
......
mStackSupervisor.startSpecificActivity(next, true, false);
return true;
}
} else {
// Whoops, need to restart this activity!
......
}
return true;
}
ActivityStack is a management class, which is used to manage various states of all activities in the system. It maintains a list of TaskRecords inside. Each TaskRecord contains several ActivityRecords, and each ActivityRecord corresponds to an Activity. Here TaskRecord is equivalent to the "task stack" in the startup mode. Depending on the startup mode, different operations will be performed on TaskRecord when the Activity is started.
Since the ActivityRecord corresponding to the Activity has been added to the top of the stack in the previous step, the ActivityStack # resumeTopActivityUncheckedLocked() method restores the top Activity of the stack that will be started, and then continues to call the ActivityStack # resumeTopActivityInnerLocked() method to continue the startup process. A series of judgments to ensure the visibility of the Activity to be started, to schedule the switching animation of the Activity, etc. Then transfer to ActivityStackSupervisor # startSpecificActivity() method to start the specific Activity at the top of the stack.
2.2.7 ActivityStackSupervisor
void startSpecificActivity(ActivityRecord r, boolean andResume, boolean checkConfig) {
// Is this activity's application already running?
// 获取即将要启动的 Activity 的所在的应用程序进程已经运行了吗?
final WindowProcessController wpc =
mService.getProcessController(r.processName, r.info.applicationInfo.uid);
boolean knownToBeDead = false;
// wpc.hasThread() 内部通过判断 IApplicationThread 是否被赋值,如果已赋值,即应用进程已运行
// 启动 Activity 的应用程序进程已经创建运行则走 Activity 的生命周期
// 即普通 Activity 的启动走 realStartActivityLocked() 方法继续 Activity 的创建
if (wpc != null && wpc.hasThread()) {
try {
realStartActivityLocked(r, wpc, andResume, checkConfig);
return;
} catch (RemoteException e) {
......
}
// If a dead object exception was thrown -- fall through to
// restart the application.
knownToBeDead = true;
}
r.notifyUnknownVisibilityLaunchedForKeyguardTransition();
final boolean isTop = andResume && r.isTopRunningActivity();
// 如果未赋值,即应用进程还不存在,则需要创建应用进程,由于是根 Activity 的启动所以应用进程还未被创建并启动
mService.startProcessAsync(r, knownToBeDead, isTop, isTop ? "top-activity" : "activity");
}
ActivityStackSupervisor is used to assist ATMS to manage Activity and Task, among which ActivityStackSupervisor manages ActivityStack, and uses ActivityStack to manage the state of Acitivity.
ActivityStackSupervisor internally manages three ActivityStacks: mHomeStack, mFocusedStack and mLastFocusedStack:
1. mHomeStack manages the Activity stack related to the Launcher, and the stackId is 0.
2. mFocusedStack manages the activity stack of the activity currently displayed in the foreground.
3. mLastFocusedStack manages the Activity stack of the last Activity displayed in the foreground.
ActivityStackSupervisor # startSpecificActivity() method to get WindowProcessController, use wpc # hasThread() method to judge whether the application process has been created and running, internally it is judged by whether IApplicationThread has been assigned, if it has been assigned, it means that the application process has been created And it is running, enter the judgment body at this time, go to the ActivityStackSupervisor # realStartActivityLocked() method to continue the startup process of the Activity, that is, the startup process of a normal Activity. If it is not assigned, the application process needs to be created. Here, the application process has not been created and started because it is the start of the root Activity.
2.3 AMS sends the process of creating the application process ActivityThread to the Zygote process
2.3.1 Timing diagram
![](https://img-blog.csdnimg.cn/81d430d28d724c71a147f1f3bc7f9bf3.png)
2.3.2 ActivityTaskManagerService starts the process
void startProcessAsync(ActivityRecord activity, boolean knownToBeDead, boolean isTop,
String hostingType) {
try {
if (Trace.isTagEnabled(TRACE_TAG_WINDOW_MANAGER)) {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "dispatchingStartProcess:"
+ activity.processName);
}
// Post message to start process to avoid possible deadlock of calling into AMS with the
// ATMS lock held.
// 发送 Handler 消息来启动进程,以避免在持有 ATMS 锁的情况下调用 AMS 时可能发生的死锁
final Message m = PooledLambda.obtainMessage(ActivityManagerInternal::startProcess,
mAmInternal, activity.processName, activity.info.applicationInfo, knownToBeDead,
isTop, hostingType, activity.intent.getComponent());
mH.sendMessage(m);
} finally {
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
}
In the method, a Handler message needs to be sent to start the process. When obtaining the Message object, it is different from our usual usage. Here, the PooledLambda # obtainMessage() function is used, and the code is as follows:
static <A, B, C, D, E, F> Message obtainMessage(
HexConsumer<? super A, ? super B, ? super C, ? super D, ? super E, ? super F> function,
A arg1, B arg2, C arg3, D arg4, E arg5, F arg6) {
synchronized (Message.sPoolSync) {
PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
function, 6, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, null, null,
null, null, null);
return Message.obtain().setCallback(callback.recycleOnUse());
}
}
It can be seen that this is a static function that can be called directly outside the interface. This is a new feature of Java 1.8. Interface methods modified by static or default can have default implementations. Interested children's shoes can check it out by themselves. The interface uses the classic lambda definition method. This generic definition cleverly connects our function and the parameter types that need to be passed in. The first lambda interface passed in is closely related to the subsequent parameter types. Call this function Directly pass in the parameters that need to be passed in together. What needs to be mentioned here is that the intermediate interface in lambda is a hidden existence. We can directly ignore it anonymously during the calling process. This is the case with the above calling example, which directly uses the :: symbol to directly link to the target function startProcess ().
So the grammatical meaning is to call the startProcess() method of the ActivityManagerInternal class, and the following variables are the input parameters passed to the startProcess() method. To be more specific, it is off-topic. If you are interested, you can check it yourself. The brief description is that a PooledRunnable instance is obtained through the acquire() function, and an instance of PooledLambdaImpl (which implements the PooledLambda interface) is obtained through its recycleOnUse() function. So when we call sendMessage() later, the run() method of this PooledRunnable will be executed, that is, the ActivityManagerInternal # startProcess() method.
ActivityManagerInternal is an abstract class, which is the interface for Activity to manage local services. Its implementation is the internal class LocalService of AMS. During the process of AMS startup, it is registered to LocalServices through LocalServices # addService(). The usage of this class is similar to that of ServiceManager. The difference is that the services registered here are not Binder objects and can only be used in the same process (system_server process). That is to say, the LocalService implementation class of ActivityManagerInternal is the local service Service of the system_server process, which is registered to LocalServices through the local service, and AMS is also running in the system_server process, so LocalService can be used directly.
LocalServices can be understood as an open cache pool, internally using ArrayMap to store local service objects. Each service in the system_server process can be registered in LocalServices through LocalServices # addService(), and the registered local service can be obtained through LocalServices # getService() when the stored LocalService needs to be used.
2.3.3 ActivityManagerService
public class ActivityManagerService extends IActivityManager.Stub
implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
@VisibleForTesting
public final class LocalService extends ActivityManagerInternal {
......
@Override
public void startProcess(String processName, ApplicationInfo info, boolean knownToBeDead,
boolean isTop, String hostingType, ComponentName hostingName) {
try {
if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "startProcess:"
+ processName);
}
synchronized (ActivityManagerService.this) {
// If the process is known as top app, set a hint so when the process is
// started, the top priority can be applied immediately to avoid cpu being
// preempted by other processes before attaching the process of top app.
startProcessLocked(processName, info, knownToBeDead, 0 /* intentFlags */,
new HostingRecord(hostingType, hostingName, isTop),
ZYGOTE_POLICY_FLAG_LATENCY_SENSITIVE, false /* allowWhileBooting */,
false /* isolated */, true /* keepIfLarge */);
}
} finally {
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
}
......
}
@GuardedBy("this")
final ProcessRecord startProcessLocked(String processName,
ApplicationInfo info, boolean knownToBeDead, int intentFlags,
HostingRecord hostingRecord, int zygotePolicyFlags, boolean allowWhileBooting,
boolean isolated, boolean keepIfLarge) {
return mProcessList.startProcessLocked(processName, info, knownToBeDead, intentFlags,
hostingRecord, zygotePolicyFlags, allowWhileBooting, isolated, 0 /* isolatedUid */,
keepIfLarge, null /* ABI override */, null /* entryPoint */,
null /* entryPointArgs */, null /* crashHandler */);
}
}
The startProcess() method calls the AMS # startProcessLocked() method and returns a ProcessRecord instance to record the information that manages the started process.
2.3.4 ProcessList
@GuardedBy("mService")
final ProcessRecord startProcessLocked(String processName, ApplicationInfo info,
boolean knownToBeDead, int intentFlags, HostingRecord hostingRecord,
int zygotePolicyFlags, boolean allowWhileBooting, boolean isolated, int isolatedUid,
boolean keepIfLarge, String abiOverride, String entryPoint, String[] entryPointArgs,
Runnable crashHandler) {
......
// ProcessRecord 记录每个进程的信息,进程名、uid 等
ProcessRecord app = getProcessRecordLocked(processName, info.uid, keepIfLarge);
checkSlow(startTime, "startProcess: stepping in to startProcess");
final boolean success =
startProcessLocked(app, hostingRecord, zygotePolicyFlags, abiOverride);
checkSlow(startTime, "startProcess: done starting proc!");
return success ? app : null;
}
@GuardedBy("mService")
final boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord,
int zygotePolicyFlags, String abiOverride) {
return startProcessLocked(app, hostingRecord, zygotePolicyFlags,
false /* disableHiddenApiChecks */, false /* disableTestApiChecks */,
false /* mountExtStorageFull */, abiOverride);
}
/**
* @return {@code true} if process start is successful, false otherwise.
*/
@GuardedBy("mService")
boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord,
int zygotePolicyFlags, boolean disableHiddenApiChecks, boolean disableTestApiChecks,
boolean mountExtStorageFull, String abiOverride) {
......
try {
app.gids = gids;
app.setRequiredAbi(requiredAbi);
app.instructionSet = instructionSet;
// Start the process. It will either succeed and return a result containing
// the PID of the new process, or else throw a RuntimeException.
// 配置新创建进程的启动文件:ActivityThread,经过层层封装后经 Socket 传输到 Zygote 进程
// Zygote 进程 fork 出新进程后要加载启动的类文件名
final String entryPoint = "android.app.ActivityThread";
return startProcessLocked(hostingRecord, entryPoint, app, uid, gids,
runtimeFlags, zygotePolicyFlags, mountExternal, seInfo, requiredAbi,
instructionSet, invokeWith, startTime);
}
......
}
@GuardedBy("mService")
boolean startProcessLocked(HostingRecord hostingRecord, String entryPoint, ProcessRecord app,
int uid, int[] gids, int runtimeFlags, int zygotePolicyFlags, int mountExternal,
String seInfo, String requiredAbi, String instructionSet, String invokeWith,
long startTime) {
......
if (mService.mConstants.FLAG_PROCESS_START_ASYNC) {
......
} else {
try {
final Process.ProcessStartResult startResult = startProcess(hostingRecord,
entryPoint, app,
uid, gids, runtimeFlags, zygotePolicyFlags, mountExternal, seInfo,
requiredAbi, instructionSet, invokeWith, startTime);
handleProcessStartedLocked(app, startResult.pid, startResult.usingWrapper,
startSeq, false);
}
......
return app.pid > 0;
}
}
private Process.ProcessStartResult startProcess(HostingRecord hostingRecord, String entryPoint,
ProcessRecord app, int uid, int[] gids, int runtimeFlags, int zygotePolicyFlags,
int mountExternal, String seInfo, String requiredAbi, String instructionSet,
String invokeWith, long startTime) {
try {
......
final Process.ProcessStartResult startResult;
if (hostingRecord.usesWebviewZygote()) {
startResult = startWebView(entryPoint,
app.processName, uid, uid, gids, runtimeFlags, mountExternal,
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, null, app.info.packageName, app.mDisabledCompatChanges,
new String[]{PROC_START_SEQ_IDENT + app.startSeq});
} else if (hostingRecord.usesAppZygote()) {
final AppZygote appZygote = createAppZygoteForProcessIfNeeded(app);
// We can't isolate app data and storage data as parent zygote already did that.
startResult = appZygote.getProcess().start(entryPoint,
app.processName, uid, uid, gids, runtimeFlags, mountExternal,
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, null, app.info.packageName,
/*zygotePolicyFlags=*/ ZYGOTE_POLICY_FLAG_EMPTY, isTopApp,
app.mDisabledCompatChanges, pkgDataInfoMap, whitelistedAppDataInfoMap,
false, false,
new String[]{PROC_START_SEQ_IDENT + app.startSeq});
} else {
startResult = Process.start(entryPoint,
app.processName, uid, uid, gids, runtimeFlags, mountExternal,
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, invokeWith, app.info.packageName, zygotePolicyFlags,
isTopApp, app.mDisabledCompatChanges, pkgDataInfoMap,
whitelistedAppDataInfoMap, bindMountAppsData, bindMountAppStorageDirs,
new String[]{PROC_START_SEQ_IDENT + app.startSeq});
}
return startResult;
} finally {
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
}
After calling 4 startProcessLocked() methods, the startProcess() method is called, and then a judgment is made in the startProcess() method, and different methods are called to start the process according to different parameters. Follow up Process here # start() to continue tracking source code.
2.3.5 Process
/**
* State associated with the zygote process.
* @hide
*/
public static final ZygoteProcess ZYGOTE_PROCESS = new ZygoteProcess();
public static ProcessStartResult start(@NonNull final String processClass,
@Nullable final String niceName,
int uid, int gid, @Nullable int[] gids,
int runtimeFlags,
int mountExternal,
int targetSdkVersion,
@Nullable String seInfo,
@NonNull String abi,
@Nullable String instructionSet,
@Nullable String appDataDir,
@Nullable String invokeWith,
@Nullable String packageName,
int zygotePolicyFlags,
boolean isTopApp,
@Nullable long[] disabledCompatChanges,
@Nullable Map<String, Pair<String, Long>>
pkgDataInfoMap,
@Nullable Map<String, Pair<String, Long>>
whitelistedDataInfoMap,
boolean bindMountAppsData,
boolean bindMountAppStorageDirs,
@Nullable String[] zygoteArgs) {
return ZYGOTE_PROCESS.start(processClass, niceName, uid, gid, gids,
runtimeFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, invokeWith, packageName,
zygotePolicyFlags, isTopApp, disabledCompatChanges,
pkgDataInfoMap, whitelistedDataInfoMap, bindMountAppsData,
bindMountAppStorageDirs, zygoteArgs);
}
ZYGOTE_PROCESS is a static instance of ZygoteProcess in the Process class, so the process call goes to the Process # start() method to continue the process of starting the process.
2.3.6 ZygoteProcess
public final Process.ProcessStartResult start(@NonNull final String processClass,
final String niceName,
int uid, int gid, @Nullable int[] gids,
int runtimeFlags, int mountExternal,
int targetSdkVersion,
@Nullable String seInfo,
@NonNull String abi,
@Nullable String instructionSet,
@Nullable String appDataDir,
@Nullable String invokeWith,
@Nullable String packageName,
int zygotePolicyFlags,
boolean isTopApp,
@Nullable long[] disabledCompatChanges,
@Nullable Map<String, Pair<String, Long>>
pkgDataInfoMap,
@Nullable Map<String, Pair<String, Long>>
whitelistedDataInfoMap,
boolean bindMountAppsData,
boolean bindMountAppStorageDirs,
@Nullable String[] zygoteArgs) {
// TODO (chriswailes): Is there a better place to check this value?
if (fetchUsapPoolEnabledPropWithMinInterval()) {
informZygotesOfUsapPoolStatus();
}
try {
// 继续调用 startViaZygote,即通过 Zygote 来启动进程
return startViaZygote(processClass, niceName, uid, gid, gids,
runtimeFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, invokeWith, /*startChildZygote=*/ false,
packageName, zygotePolicyFlags, isTopApp, disabledCompatChanges,
pkgDataInfoMap, whitelistedDataInfoMap, bindMountAppsData,
bindMountAppStorageDirs, zygoteArgs);
}
......
}
private Process.ProcessStartResult startViaZygote(@NonNull final String processClass,
@Nullable final String niceName,
final int uid, final int gid,
@Nullable final int[] gids,
int runtimeFlags, int mountExternal,
int targetSdkVersion,
@Nullable String seInfo,
@NonNull String abi,
@Nullable String instructionSet,
@Nullable String appDataDir,
@Nullable String invokeWith,
boolean startChildZygote,
@Nullable String packageName,
int zygotePolicyFlags,
boolean isTopApp,
@Nullable long[] disabledCompatChanges,
@Nullable Map<String, Pair<String, Long>>
pkgDataInfoMap,
@Nullable Map<String, Pair<String, Long>>
whitelistedDataInfoMap,
boolean bindMountAppsData,
boolean bindMountAppStorageDirs,
@Nullable String[] extraArgs)
throws ZygoteStartFailedEx {
// 创建字符串列表 argsForZygote,将应用进程的启动参数保存在 argsForZygote 中
// 包括 uid、gid、targetSdkVersion、应用程序进程启动文件:android.app.ActivityThread 等参数
ArrayList<String> argsForZygote = new ArrayList<>();
...... // 添加各种参数值
argsForZygote.add(processClass);
......
synchronized(mLock) {
// The USAP pool can not be used if the application will not use the systems graphics
// driver. If that driver is requested use the Zygote application start path.
// 调用 zygoteSendArgsAndGetResult(),将传入的应用进程的启动参数 argsForZygote 写入到 ZygoteState 中
return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi),
zygotePolicyFlags, argsForZygote);
}
}
In the ZygoteProcess # start() method, continue to call the ZygoteProcess # startViaZygote() method, that is, start the process through Zygote. The method flow is as follows:
Create a string list argsForZygote, save the startup parameters of the application process in the argsForZygote list, including uid, gid, targetSdkVersion, startup file of the application process: android.app.ActivityThread and other parameters.
Call the ZygoteProcess # openZygoteSocketIfNeeded() method, if the socket connection with the Zygote process is not opened, try to open it, which may cause blocking and retrying. The connection calls the ZygoteState # connect() method, and ZygoteState is the internal class of ZygoteProcess.
Call the ZygoteProcess # zygoteSendArgsAndGetResult() method to send the parameter list to the Zygote process, start a new child process and return the pid of the child process. Note: The current implementation replaces newlines in the argument list with spaces.
2.3.7 ZygoteProcess opens socket connection
@GuardedBy("mLock")
private ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {
try {
// 与 Zygote 进程建立 Socket 连接
attemptConnectionToPrimaryZygote();
if (primaryZygoteState.matches(abi)) {
return primaryZygoteState;
}
if (mZygoteSecondarySocketAddress != null) {
// The primary zygote didn't match. Try the secondary.
attemptConnectionToSecondaryZygote();
if (secondaryZygoteState.matches(abi)) {
return secondaryZygoteState;
}
}
} catch (IOException ioe) {
throw new ZygoteStartFailedEx("Error connecting to zygote", ioe);
}
throw new ZygoteStartFailedEx("Unsupported zygote ABI: " + abi);
}
private static class ZygoteState implements AutoCloseable {
......
// 上面 Primary、Secondary 都是调用 ZygoteState.connect() 方法来创建一个使用给定 Zygote socket 地址的 Socket 连接
static ZygoteState connect(@NonNull LocalSocketAddress zygoteSocketAddress,
@Nullable LocalSocketAddress usapSocketAddress)
throws IOException {
DataInputStream zygoteInputStream;
BufferedWriter zygoteOutputWriter;
final LocalSocket zygoteSessionSocket = new LocalSocket();
if (zygoteSocketAddress == null) {
throw new IllegalArgumentException("zygoteSocketAddress can't be null");
}
try {
zygoteSessionSocket.connect(zygoteSocketAddress);
zygoteInputStream = new DataInputStream(zygoteSessionSocket.getInputStream());
zygoteOutputWriter =
new BufferedWriter(
new OutputStreamWriter(zygoteSessionSocket.getOutputStream()),
Zygote.SOCKET_BUFFER_SIZE);
} catch (IOException ex) {
try {
zygoteSessionSocket.close();
} catch (IOException ignore) { }
throw ex;
}
// socket、DataInputStream、BufferedWriter 封装成 ZygoteState 对象供外部调用
return new ZygoteState(zygoteSocketAddress, usapSocketAddress,
zygoteSessionSocket, zygoteInputStream, zygoteOutputWriter,
getAbiList(zygoteOutputWriter, zygoteInputStream));
}
}
ZygoteProcess # openZygoteSocketIfNeeded() method, open the socket connection with the Zygote process, if the connection is not established, try to call the ZygoteState # connect() method to create a Socket connection using the given Zygote socket address, and then connect to the remote server of Zygote, At the same time, create BufferedWriter and DataInputStream to transmit and read parameter data, and finally encapsulate socket, DataInputStream, BufferedWriter, etc. into ZygoteState objects for external calls.
2.3.8 ZygoteProcess sends request parameters
@GuardedBy("mLock")
private Process.ProcessStartResult zygoteSendArgsAndGetResult(
ZygoteState zygoteState, int zygotePolicyFlags, @NonNull ArrayList<String> args)
throws ZygoteStartFailedEx {
......
if (shouldAttemptUsapLaunch(zygotePolicyFlags, args)) {
try {
return attemptUsapSendArgsAndGetResult(zygoteState, msgStr);
} catch (IOException ex) {
// If there was an IOException using the USAP pool we will log the error and
// attempt to start the process through the Zygote.
Log.e(LOG_TAG, "IO Exception while communicating with USAP pool - "
+ ex.getMessage());
}
}
return attemptZygoteSendArgsAndGetResult(zygoteState, msgStr);
}
// 用来 fork 出一个新的 Launcher 进程
private Process.ProcessStartResult attemptZygoteSendArgsAndGetResult(
ZygoteState zygoteState, String msgStr) throws ZygoteStartFailedEx {
try {
final BufferedWriter zygoteWriter = zygoteState.mZygoteOutputWriter;
final DataInputStream zygoteInputStream = zygoteState.mZygoteInputStream;
zygoteWriter.write(msgStr);
zygoteWriter.flush();
// Always read the entire result from the input stream to avoid leaving
// bytes in the stream for future process starts to accidentally stumble
// upon.
Process.ProcessStartResult result = new Process.ProcessStartResult();
result.pid = zygoteInputStream.readInt();
result.usingWrapper = zygoteInputStream.readBoolean();
if (result.pid < 0) {
// 进程创建失败
throw new ZygoteStartFailedEx("fork() failed");
}
return result;
} catch (IOException ex) {
zygoteState.close();
Log.e(LOG_TAG, "IO Exception while communicating with Zygote - "
+ ex.toString());
throw new ZygoteStartFailedEx(ex);
}
}
ZygoteProcess #attemptZygoteSendArgsAndGetResult() method uses the BufferedWriter and DataInputStream saved in the created ZygoteState to carry out Socket communication, through which the data flow transmission and reading operations are performed. The system_server process writes the parameters to the server side of the socket of the Zygote process through BufferedWriter, and then blocks and waits for the socket of the Zygote process to return the pid and usingWrapper and then encapsulates it into ProcessStartResult.
2.4 Zygote process fork and start the application process
2.4.1 Timing diagram
2.4.2 Zygote process starts and parses the parameters passed in by Socket
The bottom layer of the Android system is based on Linux. Like Linux, the init process is the first process of the Linux system user process. It is started by the Linux kernel (kenerl) to start the attribute service (similar to the registry in Windows), Start the process. All other user processes are subprocesses of the init process. The Zygote process we analyze next is also created by the init process. How to start Zygote will not be discussed here. After Zygote starts, it will call the ZygoteInit # main() method, so we First look at socket creation and message reading from the main() method. code show as below:
public static void main(String argv[]) {
ZygoteServer zygoteServer = null;
......
Runnable caller;
try {
......
// 解析参数
boolean startSystemServer = false;
String zygoteSocketName = "zygote";
String abiList = null;
boolean enableLazyPreload = false;
for (int i = 1; i < argv.length; i++) {
if ("start-system-server".equals(argv[i])) {
startSystemServer = true;
} else if ("--enable-lazy-preload".equals(argv[i])) {
enableLazyPreload = true;
} else if (argv[i].startsWith(ABI_LIST_ARG)) {
abiList = argv[i].substring(ABI_LIST_ARG.length());
} else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
zygoteSocketName = argv[i].substring(SOCKET_NAME_ARG.length());
} else {
throw new RuntimeException("Unknown command line argument: " + argv[i]);
}
}
......
zygoteServer = new ZygoteServer(isPrimaryZygote);
......
// 调用 runSelectLoop() 开启 Loop 循环来监听 client socket 发来的消息
caller = zygoteServer.runSelectLoop(abiList);
} catch (Throwable ex) {
Log.e(TAG, "System zygote died with exception", ex);
throw ex;
} finally {
if (zygoteServer != null) {
zygoteServer.closeServerSocket();
}
}
// We're in the child process and have exited the select loop. Proceed to execute the command.
// 子进程的启动
if (caller != null) {
caller.run();
}
}
Create a new ZygoteServer instance object in the method, call the ZygoteServer # runSelectLoop() method to start an infinite loop loop to monitor the messages sent by the client socket, and when a request to create a new process is received, it will immediately wake up and perform corresponding work. If the system process is forked, it will be added to the list, and then continue to block and wait; if the fork is a child process, it will exit the loop cycle, return to the created application child process, and execute the start of the child process.
2.4.3 ZygoteServer opens Loop to monitor Socket in a loop
ZygoteServer(boolean isPrimaryZygote) {
mUsapPoolEventFD = Zygote.getUsapPoolEventFD();
if (isPrimaryZygote) {
mZygoteSocket = Zygote.createManagedSocketFromInitSocket(Zygote.PRIMARY_SOCKET_NAME);
mUsapPoolSocket =
Zygote.createManagedSocketFromInitSocket(
Zygote.USAP_POOL_PRIMARY_SOCKET_NAME);
} else {
mZygoteSocket = Zygote.createManagedSocketFromInitSocket(Zygote.SECONDARY_SOCKET_NAME);
mUsapPoolSocket =
Zygote.createManagedSocketFromInitSocket(
Zygote.USAP_POOL_SECONDARY_SOCKET_NAME);
}
mUsapPoolSupported = true;
fetchUsapPoolPolicyProps();
}
/**
* Runs the zygote process's select loop. Accepts new connections as
* they happen, and reads commands from connections one spawn-request's
* worth at a time.
*/
Runnable runSelectLoop(String abiList) {
ArrayList<FileDescriptor> socketFDs = new ArrayList<>();
ArrayList<ZygoteConnection> peers = new ArrayList<>();
// mZygoteSocket 是服务端的 socket 对象,也就是 Zygote 进程所在 socket 放在 fds[0] 位置
socketFDs.add(mZygoteSocket.getFileDescriptor());
// 刚开始默认 peers[0] = null
peers.add(null);
mUsapPoolRefillTriggerTimestamp = INVALID_TIMESTAMP;
// 开启轮询等待
while (true) {
fetchUsapPoolPolicyPropsWithMinInterval();
mUsapPoolRefillAction = UsapPoolRefillAction.NONE;
int[] usapPipeFDs = null;
StructPollfd[] pollFDs;
if (mUsapPoolEnabled) {
usapPipeFDs = Zygote.getUsapPipeFDs();
pollFDs = new StructPollfd[socketFDs.size() + 1 + usapPipeFDs.length];
} else {
pollFDs = new StructPollfd[socketFDs.size()];
}
int pollIndex = 0;
......
int pollTimeoutMs;
if (mUsapPoolRefillTriggerTimestamp == INVALID_TIMESTAMP) {
pollTimeoutMs = -1;
} else {
long elapsedTimeMs = System.currentTimeMillis() - mUsapPoolRefillTriggerTimestamp;
if (elapsedTimeMs >= mUsapPoolRefillDelayMs) {
pollTimeoutMs = -1;
} else if (elapsedTimeMs <= 0) {
pollTimeoutMs = mUsapPoolRefillDelayMs;
} else {
pollTimeoutMs = (int) (mUsapPoolRefillDelayMs - elapsedTimeMs);
}
}
int pollReturnValue;
try {
// 处理轮询状态,当 pollFds 有事件到来则往下执行,否则阻塞在这里
pollReturnValue = Os.poll(pollFDs, pollTimeoutMs);
} catch (ErrnoException ex) {
throw new RuntimeException("poll failed", ex);
}
if (pollReturnValue == 0) {
mUsapPoolRefillTriggerTimestamp = INVALID_TIMESTAMP;
mUsapPoolRefillAction = UsapPoolRefillAction.DELAYED;
} else {
boolean usapPoolFDRead = false;
// 倒序处理,即优先处理已建立连接的信息,后处理新建连接的请求
while (--pollIndex >= 0) {
// 采用I/O多路复用 epoll 机制,当接收到客户端请求到来,则往下执行;否则跳出本次循环
if ((pollFDs[pollIndex].revents & POLLIN) == 0) {
continue;
}
if (pollIndex == 0) {
// Zygote server socket
// pollIndex==0 表示有新的客户端请求连接到来,调用server socket端的 accpet 函数建立通信连接
// zygote 进程与 system server 进程建立了连接
ZygoteConnection newPeer = acceptCommandPeer(abiList);
// 加入到 peers 和 fds, 即开始下一次监听
peers.add(newPeer);
socketFDs.add(newPeer.getFileDescriptor());
} else if (pollIndex < usapPoolEventFDIndex) {
// Session socket accepted from the Zygote server socket
// socket 连接成功之后从 Zygote 服务器的 socket 接受到的 Session socket
try {
ZygoteConnection connection = peers.get(pollIndex);
final Runnable command = connection.processOneCommand(this);
// TODO (chriswailes): Is this extra check necessary?
if (mIsForkChild) {
......
return command;
} else {
// 如果不是 fork 子进程则关闭连接,删除当前 fd 消息
if (connection.isClosedByPeer()) {
connection.closeSocket();
peers.remove(pollIndex);
socketFDs.remove(pollIndex);
}
}
} catch (Exception e) {
......
} finally {
......
mIsForkChild = false;
}
}
}
......
}
......
}
}
The runSelectLoop() method obtains the startup parameters of the application process transmitted in the zygoteSendArgsAndGetResult() method, that is, establishes a connection with the Zygote process. The method flow is as follows:
Open Loop to listen to socket events in an infinite loop. When there is no connection, it will be blocked there. When a connection arrives, it will wake up and continue to execute.
When pollIndex==0, it means that the connection request event is received, the request establishes a socket connection with Zygote, calls the acceptCommandPeer() method to create a ZygoteConnection object, and calls the mZygoteSocket # accept() method to establish a socket connection, and then adds it to the listening list peers, Wait for the arrival of the command related to this socket.
When pollIndex < usapPoolEventFDIndex, it means that the command on the connected socket arrives. At this time, call the ZygoteConnection # processOneCommand() method to receive the startup parameters of the application process transmitted by the client, and execute the process creation work. After processing, it will Disconnect from the client and remove the socket used for connection from the listening list peers.
2.4.4 ZygoteConnection
Runnable processOneCommand(ZygoteServer zygoteServer) {
String[] args;
try {
// 逐行读取 client 端通过 socket write 过来的启动参数(字符串数组)
args = Zygote.readArgumentList(mSocketReader);
} catch (IOException ex) {
throw new IllegalStateException("IOException on command socket", ex);
}
......
int pid;
FileDescriptor childPipeFd = null;
FileDescriptor serverPipeFd = null;
// 将数据解析成 ZygoteArguments 格式
ZygoteArguments parsedArgs = new ZygoteArguments(args);
......
int[][] rlimits = null;
if (parsedArgs.mRLimits != null) {
rlimits = parsedArgs.mRLimits.toArray(Zygote.INT_ARRAY_2D);
}
int[] fdsToIgnore = null;
if (parsedArgs.mInvokeWith != null) {
try {
FileDescriptor[] pipeFds = Os.pipe2(O_CLOEXEC);
childPipeFd = pipeFds[1];
serverPipeFd = pipeFds[0];
Os.fcntlInt(childPipeFd, F_SETFD, 0);
fdsToIgnore = new int[]{childPipeFd.getInt$(), serverPipeFd.getInt$()};
} catch (ErrnoException errnoEx) {
throw new IllegalStateException("Unable to set up pipe for invoke-with", errnoEx);
}
}
// 将 client 端 fd 和 server 端 fd 存入 fdsToClose 数组中,然后 fd 置位 null
int [] fdsToClose = { -1, -1 };
FileDescriptor fd = mSocket.getFileDescriptor();
if (fd != null) {
fdsToClose[0] = fd.getInt$();
}
fd = zygoteServer.getZygoteSocketFileDescriptor();
if (fd != null) {
fdsToClose[1] = fd.getInt$();
}
// 调用 forkAndSpecialize() 方法来 fork 子进程
pid = Zygote.forkAndSpecialize(parsedArgs.mUid, parsedArgs.mGid, parsedArgs.mGids,
parsedArgs.mRuntimeFlags, rlimits, parsedArgs.mMountExternal, parsedArgs.mSeInfo,
parsedArgs.mNiceName, fdsToClose, fdsToIgnore, parsedArgs.mStartChildZygote,
parsedArgs.mInstructionSet, parsedArgs.mAppDataDir, parsedArgs.mIsTopApp,
parsedArgs.mPkgDataInfoList, parsedArgs.mWhitelistedDataInfoList,
parsedArgs.mBindMountAppDataDirs, parsedArgs.mBindMountAppStorageDirs);
try {
if (pid == 0) {
// in child
// pid = 0 表示创建成功,则进入子进程中,即应用程序进程
zygoteServer.setForkChild();
// 关闭 socket 连接
zygoteServer.closeServerSocket();
IoUtils.closeQuietly(serverPipeFd);
serverPipeFd = null;
// 进入子进程执行相关操作
return handleChildProc(parsedArgs, childPipeFd, parsedArgs.mStartChildZygote);
} else {
// In the parent. A pid < 0 indicates a failure and will be handled in handleParentProc.
// pid < 0表示创建失败,则进入父进程返回消息给 client socket 表示启动失败
IoUtils.closeQuietly(childPipeFd);
childPipeFd = null;
// 进入父进程执行相关操作
handleParentProc(pid, serverPipeFd);
return null;
}
} finally {
IoUtils.closeQuietly(childPipeFd);
IoUtils.closeQuietly(serverPipeFd);
}
}
The main functions of this method are as follows:
Read the data written by the socket on the system_server side, and encapsulate the data stored in the string array into the ZygoteArguments format.
Call the Zygote # forkAndSpecialize() method to fork the child process and return the pid. The pid here is not the process id, but the result value. 0 means the creation is successful, and -1 means it failed.
After the child process is successfully created, it enters the child process for execution.
2.4.5 Zygote creates child processes (native layer creation)
static int forkAndSpecialize(int uid, int gid, int[] gids, int runtimeFlags,
int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir,
boolean isTopApp, String[] pkgDataInfoList, String[] whitelistedDataInfoList,
boolean bindMountAppDataDirs, boolean bindMountAppStorageDirs) {
ZygoteHooks.preFork();
// 通过 JNI 调用 native 层方法
int pid = nativeForkAndSpecialize(
uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
fdsToIgnore, startChildZygote, instructionSet, appDataDir, isTopApp,
pkgDataInfoList, whitelistedDataInfoList, bindMountAppDataDirs,
bindMountAppStorageDirs);
if (pid == 0) {
// Note that this event ends at the end of handleChildProc,
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork");
// If no GIDs were specified, don't make any permissions changes based on groups.
if (gids != null && gids.length > 0) {
NetworkUtils.setAllowNetworkingForProcess(containsInetGid(gids));
}
}
// Set the Java Language thread priority to the default value for new apps.
Thread.currentThread().setPriority(Thread.NORM_PRIORITY);
ZygoteHooks.postForkCommon();
return pid;
}
In the method, call the nativeForkAndSpecialize() method of the native layer to create a process, and then return the pid of the process (in the parent process, return the pid of the newly created child process, in the child process, return 0, and return a negative number when an error occurs), and the specific native layer I don’t follow the source code, but I took a look at the process:
Call the fork() method of Linux to create a process, and set the name of the main thread of the process. If it is null or system_server, it is system_server.
Call the CallStaticVoidMethod() method to return to Zygote # The callPostForkChildHooks() method handles gc/thread pool management and other operations after the fork child thread.
2.4.6 ZygoteConnection # handleChildProc() method
private Runnable handleChildProc(ZygoteArguments parsedArgs,
FileDescriptor pipeFd, boolean isZygote) {
// 关闭 socket 连接
closeSocket();
// 设置应用进程的 name 名
Zygote.setAppProcessName(parsedArgs, TAG);
// End of the postFork event.
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
if (parsedArgs.mInvokeWith != null) {
WrapperInit.execApplication(parsedArgs.mInvokeWith,
parsedArgs.mNiceName, parsedArgs.mTargetSdkVersion,
VMRuntime.getCurrentInstructionSet(),
pipeFd, parsedArgs.mRemainingArgs);
// Should not get here.
throw new IllegalStateException("WrapperInit.execApplication unexpectedly returned");
} else {
if (!isZygote) {
return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
parsedArgs.mDisabledCompatChanges,
parsedArgs.mRemainingArgs, null /* classLoader */);
} else {
return ZygoteInit.childZygoteInit(parsedArgs.mTargetSdkVersion,
parsedArgs.mRemainingArgs, null /* classLoader */);
}
}
}
This method is to enter the child process to perform different initialization operations, because the fork() has been successful, close the socket connection and release resources, set the name of the application process, and finally call ZygoteInit # zygoteInit() method to initialize Zygote.
2.4.7 ZygoteInit # zygoteInit() method
public static final Runnable zygoteInit(int targetSdkVersion, long[] disabledCompatChanges,
String[] argv, ClassLoader classLoader) {
......
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");
RuntimeInit.redirectLogStreams();
// 进程初始化配置,如设置异常捕获 Handler、时区、重置 LogManager 等等
RuntimeInit.commonInit();
// native 层初始化 -- 打开/dev/binder 驱动,映射内核的地址空间,创建 binder 线程用于 IPC 通信
ZygoteInit.nativeZygoteInit();
return RuntimeInit.applicationInit(targetSdkVersion, disabledCompatChanges, argv,
classLoader);
}
The method flow is as follows:
Log stream redirection, redirects system output and system errors to the Android log.
Process initialization configuration, such as setting exception capture Handler, time zone, resetting LogManager, etc.
Initialize the native layer, open the /dev/binder driver, map the address space of the kernel, and create a binder thread for IPC communication.
Call the RuntimeInit # applicationInit() method to return the created Runnable object.
2.4.8 RuntimeInit # applicationInit() method
protected static Runnable applicationInit(int targetSdkVersion, long[] disabledCompatChanges,
String[] argv, ClassLoader classLoader) {
// 如果应用程序调用了 System.exit() 方法立即终止进程,可能会导致剩余的运行线程在进程实际退出之前崩溃
nativeSetExitWithoutCleanup(true);
VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
VMRuntime.getRuntime().setDisabledCompatChanges(disabledCompatChanges);
final Arguments args = new Arguments(argv);
// The end of of the RuntimeInit event (see #zygoteInit).
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
// Remaining arguments are passed to the start class's static main
return findStaticMain(args.startClass, args.startArgs, classLoader);
}
protected static Runnable findStaticMain(String className, String[] argv,
ClassLoader classLoader) {
// 待加载的类、这里是指 ActivityThread,也就是我们第三节中在 ProcessList 中指明的 entryPoint
Class<?> cl;
try {
// 加载 android.app.ActivityThread 类
cl = Class.forName(className, true, classLoader);
} catch (ClassNotFoundException ex) {
throw new RuntimeException(
"Missing class when invoking static main " + className, ex);
}
// 获取 main 方法
Method m;
try {
// 获取 ActivityThread # main() 函数
m = cl.getMethod("main", new Class[] { String[].class });
} catch (NoSuchMethodException ex) {
throw new RuntimeException("Missing static main on " + className, ex);
} catch (SecurityException ex) {
throw new RuntimeException("Problem getting static main on " + className, ex);
}
// 判断 main 方法是不是 public 并且 static 类型
int modifiers = m.getModifiers();
if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
throw new RuntimeException("Main method is not public and static on " + className);
}
// 返回 Caller,即本小节第一部分的 ZygoteInit.main() 中的 caller
return new MethodAndArgsCaller(m, argv);
}
In the applicationInit() method, a System.exit() protection is first made to prevent crashes when exiting the process, setting parameters such as targetSDKVersion, and finally calling the findStaticMain() method to load the ActivityThread class and methods.
In the findStaticMain() method, the target class ActivityThread is loaded through ClassLoader, and then its static main method is obtained, and then encapsulated into a MethodAndArgsCaller object to return. MethodAndArgsCaller implements the Runnable interface. That is, return to the caller of the ZygoteInit # main() method in the section 2. Zygote process startup and analysis of parameters passed in by Socket, if the caller! =null will call the Runnable's run() method.
2.4.9 RuntimeInit # MethodAndArgsCaller
static class MethodAndArgsCaller implements Runnable {
/** method to call */
private final Method mMethod;
/** argument array */
private final String[] mArgs;
public MethodAndArgsCaller(Method method, String[] args) {
mMethod = method;
mArgs = args;
}
public void run() {
try {
mMethod.invoke(null, new Object[] { mArgs });
} catch (IllegalAccessException ex) {
throw new RuntimeException(ex);
} catch (InvocationTargetException ex) {
......
}
}
}
MethodAndArgsCaller # The invoke reflective call is used in the run() method. So far, the main() method of the ActivityThread is executed, and the application process starts the ActivityThread successfully.
2.4.10. Summary
Zygote process startup process:
The init process is the first process in the user space (relative to the kernel space), and starts the Zygote process according to init.rc.
Zygote process startup steps: create virtual machine, register JNI, execute ZygoteInit # main() method.
The Zygote process starts the system_server process (the first process started by Zygote), which is not specifically analyzed in this section.
Zygote creates a socket connection channel, blocks and waits for the instruction to create a new process, and creates a new user process through fork.
Zygote has added a new mechanism for optimizing process creation, UsapPool - pooling mechanism, I followed the source code, and several processes are pre-cached.
2.5 The application process ActivityThread starts the Activity process
The ActivityThread class is an application initialization class, and its main() method is the entry method of the application. It is also what we call the "main thread", but the ActivityThread itself is not a thread. The reason why it is called the "main thread" is because it runs in the main thread. So ActivityThread is part of the main thread, but it does not represent the main thread.
1. ActivityThread is responsible for creating the Application object and managing its life cycle method calls.
2. ActivityThread manages the life cycle method calls of the four major components.
2.5.1 Timing Diagram
2.5.2 ActivityThread entry method
public final class ActivityThread extends ClientTransactionHandler {
// 初始化 ApplicationThread
final ApplicationThread mAppThread = new ApplicationThread();
// 初始化 Handler,ApplicationThread 和 ActivityThread 通信使用
final H mH = new H();
public static void main(String[] args) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
......
// Call per-process mainline module initialization.
initializeMainlineModules();
Process.setArgV0("<pre-initialized>");
// 初始化主线程的 Looper
Looper.prepareMainLooper();
...... // 获取 startSeq
// 实例化 ActivityThread
ActivityThread thread = new ActivityThread();
//
thread.attach(false, startSeq);
if (sMainThreadHandler == null) {
// sMainThreadHandler = mH
sMainThreadHandler = thread.getHandler();
}
// End of event ActivityThreadMain.
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
// 开启 Looper 循环,等待接收消息
Looper.loop();
// 正常不会走到这里,除非是非正常退出了 looper 循环
throw new RuntimeException("Main thread loop unexpectedly exited");
}
private void attach(boolean system, long startSeq) {
sCurrentActivityThread = this;
mSystemThread = system;
if (!system) {
android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
UserHandle.myUserId());
RuntimeInit.setApplicationObject(mAppThread.asBinder());
final IActivityManager mgr = ActivityManager.getService();
try {
mgr.attachApplication(mAppThread, startSeq);
}
......
} else {
android.ddm.DdmHandleAppName.setAppName("system_process",
UserHandle.myUserId());
try {
mInstrumentation = new Instrumentation();
mInstrumentation.basicInit(this);
ContextImpl context = ContextImpl.createAppContext(
this, getSystemContext().mPackageInfo);
mInitialApplication = context.mPackageInfo.makeApplication(true, null);
mInitialApplication.onCreate();
}
......
}
......
}
}
In the ActivityThread # attach() method, use Binder communication to call the attachApplication() method of AMS in the system_server process across processes, and pass ApplicationThread as a parameter.
2.5.3 AMS binding ApplicationThread
// ActivityTaskManagerInternal 是一个抽象类,实现类是 ATMS 的内部类 LocalService
// ATMS 启动的时候,通过 LocalServices # addService() 注册到 LocalServices
public ActivityTaskManagerInternal mAtmInternal;
public ActivityManagerService(Context systemContext, ActivityTaskManagerService atm) {
......
mAtmInternal = LocalServices.getService(ActivityTaskManagerInternal.class);
......
}
@Override
public final void attachApplication(IApplicationThread thread, long startSeq) {
if (thread == null) {
throw new SecurityException("Invalid application interface");
}
synchronized (this) {
int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
attachApplicationLocked(thread, callingPid, callingUid, startSeq);
Binder.restoreCallingIdentity(origId);
}
}
@GuardedBy("this")
private boolean attachApplicationLocked(@NonNull IApplicationThread thread,
int pid, int callingUid, long startSeq) {
......
// 保存当前正在运行的进程的所有信息
ProcessRecord app;
......
try {
......
// 跨进程调用应用进程 ApplicationThread # bindApplication()创建绑定 Application
thread.bindApplication(processName, appInfo, providerList, null, profilerInfo,
null, null, null, testMode,
mBinderTransactionTrackingEnabled, enableTrackAllocation,
isRestrictedBackupMode || !normalMode, app.isPersistent(),
new Configuration(app.getWindowProcessController().getConfiguration()),
app.compat, getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked(),
buildSerial, autofillOptions, contentCaptureOptions,
app.mDisabledCompatChanges);
// Make app active after binding application or client may be running requests (e.g
// starting activities) before it is ready.
// 保存 应用进程 IApplicationThread
app.makeActive(thread, mProcessStats);
......
}
......
boolean didSomething = false;
// See if the top visible activity is waiting to run in this process...
if (normalMode) {
try {
// 通过 ATMS 启动根 Activity
didSomething = mAtmInternal.attachApplication(app.getWindowProcessController());
}
......
}
return true;
}
AMS # attachApplication() method, continue to call AMS # attachApplicationLocked() method after getting the pid and uid.
AMS # attachApplicationLocked() method focuses on the following processes:
Create and bind Application by calling ApplicationThread # bindApplication() in the application process through cross-process communication.
ProcessRecord calls the makeActive() method to save the application process IApplicationThread. Transition to ATMS starts the root Activity through the ActivityTaskManagerInternal local service.
2.5.4 ActivityThread creates and binds Application
The IApplicationThread # bindApplication() method calls the implementation class ApplicationThread # bindApplication() method in the application process. In the method, the Handler message is sent through the internal class H, and then the ActivityThread # handleBindApplication() method is called. The code is as follows:
@UnsupportedAppUsage
private void handleBindApplication(AppBindData data) {
......
final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
updateLocaleListFromAppContext(appContext,
mResourcesManager.getConfiguration().getLocales());
......
if (ii != null) {
......
final LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
appContext.getClassLoader(), false, true, false);
final ContextImpl instrContext = ContextImpl.createAppContext(this, pi,
appContext.getOpPackageName());
try {
// 获取 ClassLoader 加载类文件
final ClassLoader cl = instrContext.getClassLoader();
// 获取 Instrumentation 类并构建实例对象
mInstrumentation = (Instrumentation)
cl.loadClass(data.instrumentationName.getClassName()).newInstance();
}
......
final ComponentName component = new ComponentName(ii.packageName, ii.name);
mInstrumentation.init(this, instrContext, appContext, component,
data.instrumentationWatcher, data.instrumentationUiAutomationConnection);
......
}
......
Application app;
......
try {
// 创建 Application
app = data.info.makeApplication(data.restrictedBackupMode, null);
......
mInitialApplication = app;
......
try {
mInstrumentation.onCreate(data.instrumentationArgs);
}
......
try {
// 内部调用 Application # onCreate() 的方法
// 故 Application # onCreate() 比 ActivityThread 的 main() 方法慢执行
// 但是会比所有该应用 Activity 的生命周期先调用,因为此时的 Activity 还没启动
mInstrumentation.callApplicationOnCreate(app);
}
......
}
......
}
2.5.5 ProcessRecord save ApplicationThread
public void makeActive(IApplicationThread _thread, ProcessStatsService tracker) {
......
thread = _thread;
mWindowProcessController.setThread(thread);
}
In the method, the process is handed over to WindowProcessController and its setThread() method is called to store IApplicationThread. The code is as follows:
public class WindowProcessController extends ConfigurationContainer<ConfigurationContainer>
implements ConfigurationContainerListener {
private IApplicationThread mThread;
@HotPath(caller = HotPath.PROCESS_CHANGE)
public void setThread(IApplicationThread thread) {
synchronized (mAtm.mGlobalLockWithoutBoost) {
mThread = thread;
if (thread != null) {
setLastReportedConfiguration(getConfiguration());
}
}
}
IApplicationThread getThread() {
return mThread;
}
boolean hasThread() {
return mThread != null;
}
}
WindowProcessController # setThread() method assigns the incoming IApplicationThread to mThread and saves it. At this time, the IApplicationThread in WindowProcessController has a value, and it also explains the question raised at the end of the second part. And when we start the root Activity, we can't get IApplicationThread through wpc. IApplicationThread assignment in WindowProcessController.
2.5.6 ATMS binds WindowProcessController and starts root Activity
public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
// 启动的时候注册到 LocalServices 中
private void start() {
LocalServices.addService(ActivityTaskManagerInternal.class, mInternal);
}
final class LocalService extends ActivityTaskManagerInternal {
......
@HotPath(caller = HotPath.PROCESS_CHANGE)
@Override
public boolean attachApplication(WindowProcessController wpc) throws RemoteException {
synchronized (mGlobalLockWithoutBoost) {
if (Trace.isTagEnabled(TRACE_TAG_WINDOW_MANAGER)) {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "attachApplication:" + wpc.mName);
}
try {
// 调用 RootWindowContainer # attachApplication()
return mRootWindowContainer.attachApplication(wpc);
} finally {
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
}
}
......
}
}
ActivityTaskManagerInternal is an abstract class, and its implementation class is the internal class LocalService of ATMS. This is a local service. When ATMS starts, it is registered in LocalServices through LocalServices # addService(). In the construction method of AMS, the registered local service is obtained through the LocalServices # getService() method. Therefore, the method of calling ActivityTaskManagerInternal in AMS actually calls the method of the implementation class LocalService in ATMS. This method continues to call the RootWindowContainer # attachApplication() method, and the startup process is handed over to RootWindowContainer.
2.5.7 RootWindowContainer 绑定 WindowProcessController
boolean attachApplication(WindowProcessController app) throws RemoteException {
final String processName = app.mName;
boolean didSomething = false;
for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
final DisplayContent display = getChildAt(displayNdx);
final ActivityStack stack = display.getFocusedStack();
if (stack == null) {
continue;
}
mTmpRemoteException = null;
mTmpBoolean = false; // Set to true if an activity was started.
final PooledFunction c = PooledLambda.obtainFunction(
RootWindowContainer::startActivityForAttachedApplicationIfNeeded, this,
PooledLambda.__(ActivityRecord.class), app, stack.topRunningActivity());
stack.forAllActivities(c);
c.recycle();
if (mTmpRemoteException != null) {
throw mTmpRemoteException;
}
didSomething |= mTmpBoolean;
}
if (!didSomething) {
ensureActivitiesVisible(null, 0, false /* preserve_windows */);
}
return didSomething;
}
private boolean startActivityForAttachedApplicationIfNeeded(ActivityRecord r,
WindowProcessController app, ActivityRecord top) {
if (r.finishing || !r.okToShowLocked() || !r.visibleIgnoringKeyguard || r.app != null
|| app.mUid != r.info.applicationInfo.uid || !app.mName.equals(r.processName)) {
return false;
}
try {
if (mStackSupervisor.realStartActivityLocked(r, app, top == r /*andResume*/,
true /*checkConfig*/)) {
mTmpBoolean = true;
}
} catch (RemoteException e) {
.....
return true;
}
return false;
}
In the RootWindowContainer # attachApplication() method, the RootWindowContainer # startActivityForAttachedApplicationIfNeeded() method is called. For how to call this method, please refer to the third part 2. ActivityTaskManagerService starts the process. In the RootWindowContainer # startActivityForAttachedApplicationIfNeeded() method, continue to call the ActivityStackSupervisor # realStartActivityLocked() method to actually start the Activity.
2.5.8 Get ClientTransaction, add Callback, set LifecycleStateRequest
boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,
boolean andResume, boolean checkConfig) throws RemoteException {
final Task task = r.getTask();
final ActivityStack stack = task.getStack();
beginDeferResume();
try {
r.startFreezingScreenLocked(proc, 0);
......
try {
......
// Create activity launch transaction.
// 获取 ClientTransaction 实例
final ClientTransaction clientTransaction = ClientTransaction.obtain(
proc.getThread(), r.appToken);
final DisplayContent dc = r.getDisplay().mDisplayContent;
// ClientTransaction 实例添加 ClientTransactionItem 类型的回调消息
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.launchedFromPackage, task.voiceInteractor, proc.getReportedProcState(),
r.getSavedState(), r.getPersistentSavedState(), results, newIntents,
dc.isNextTransitionForward(), proc.createProfilerInfoIfNeeded(),
r.assistToken, r.createFixedRotationAdjustmentsIfNeeded()));
// 所需的最终生命周期状态请求
final ActivityLifecycleItem lifecycleItem;
// 判断此时的生命周期状态是走 onResume 还是 onPause
if (andResume) {
// 由于此时 ActivityStack 栈中只有一个 Activity,所以 top == r 为 true,因此应赋值为 ResumeActivityItem
lifecycleItem = ResumeActivityItem.obtain(dc.isNextTransitionForward());
} else {
lifecycleItem = PauseActivityItem.obtain();
}
// 设置执行 transaction 后的最终的生命周期状态请求
clientTransaction.setLifecycleStateRequest(lifecycleItem);
// ClientLifecycleManager 调度 ClientTransaction
mService.getLifecycleManager().scheduleTransaction(clientTransaction);
......
} catch (RemoteException e) {
// 启动失败,移除 ActivityRecord
r.launchFailed = true;
proc.removeActivity(r);
throw e;
}
} finally {
endDeferResume();
}
return true;
}
The execution flow of this method is as follows:
Create an instance of ClientTransaction, where the parameter proc.getThread() is of type IApplicationThread, and mActivityToken is of type IBinder.
The ClientTransaction instance adds the ClientTransactionItem type callback message. Note: What is added here is the LaunchActivityItem instance, which inherits from the ClientTransactionItem abstract class and implements the methods in it.
Get the ClientLifecycleManager instance, call its scheduleTransaction() method to schedule the execution of the conversion transaction Transaction.
2.5.9 ClientTransaction get and add transaction callback
// 客户端的单个回调列表
@UnsupportedAppUsage
private List<ClientTransactionItem> mActivityCallbacks;
// 执行事务后客户端活动应处于的最终生命周期状态
private ActivityLifecycleItem mLifecycleStateRequest;
/** Target client. */
private IApplicationThread mClient;
/** Target client activity. Might be null if the entire transaction is targeting an app. */
private IBinder mActivityToken;
/** Obtain an instance initialized with provided params. */
// 获取 ClientTransaction 实例
public static ClientTransaction obtain(IApplicationThread client, IBinder activityToken) {
ClientTransaction instance = ObjectPool.obtain(ClientTransaction.class);
if (instance == null) {
instance = new ClientTransaction();
}
instance.mClient = client;
instance.mActivityToken = activityToken;
return instance;
}
/**
* 在 ClientTransaction 的 callbacks 列表尾部添加 ClientTransactionItem 类型的消息
* 参数:包含生命周期请求或回调的单个消息
* @param activityCallback A single message that can contain a lifecycle request/callback.
*/
public void addCallback(ClientTransactionItem activityCallback) {
if (mActivityCallbacks == null) {
mActivityCallbacks = new ArrayList<>();
}
mActivityCallbacks.add(activityCallback);
}
/**
* Set the lifecycle state in which the client should be after executing the transaction.
* 设置客户端在执行事务后应处于的生命周期状态
* @param stateRequest A lifecycle request initialized with right parameters.
*/
public void setLifecycleStateRequest(ActivityLifecycleItem stateRequest) {
mLifecycleStateRequest = stateRequest;
}
ClientTransaction is a container that saves a series of transaction messages to be sent to the client for processing, including a Callback list and a final lifecycle state.
2.5.10 ClientLifecycleManager Client Lifecycle Transaction Transition Manager
/**
* Schedule a transaction, which may consist of multiple callbacks and a lifecycle request.
* 安排调度一个事务(启动、暂停等 Activity 事务),可能包含多个回调和一个生命周期请求
* @param transaction A sequence of client transaction items.
* @throws RemoteException
*
* @see ClientTransaction
*/
void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
final IApplicationThread client = transaction.getClient();
transaction.schedule();
if (!(client instanceof Binder)) {
// If client is not an instance of Binder - it's a remote call and at this point it is
// safe to recycle the object. All objects used for local calls will be recycled after
// the transaction is executed on client in ActivityThread.
transaction.recycle();
}
}
ClientLifecycleManager is capable of combining multiple client lifecycle transition requests and callbacks and scheduling them as a single transaction.
2.5.11 ClientTransaction # schedule() scheduling transaction
/**
* Schedule the transaction after it was initialized. It will be send to client and all its
* individual parts will be applied in the following sequence:
* 1. The client calls {@link #preExecute(ClientTransactionHandler)}, which triggers all work
* that needs to be done before actually scheduling the transaction for callbacks and
* lifecycle state request.
* 2. The transaction message is scheduled.
* 3. The client calls {@link TransactionExecutor#execute(ClientTransaction)}, which executes
* all callbacks and necessary lifecycle transitions.
*/
public void schedule() throws RemoteException {
mClient.scheduleTransaction(this);
}
Looking at the comments of the method, it probably means that the transaction is scheduled after the transaction is initialized, and all its individual parts will be sent to the client in the following order:
The client calls the preExecute() method to trigger any tasks that need to be completed before actually dispatching the transaction's callback and lifecycle status requests.
A transactional message has been dispatched.
The client calls the TransactionExecutor # execute() method to execute all callbacks and necessary lifecycle transitions.
From the source code analysis in Sections 8 and 9 above, it can be seen that mClient is an IApplicationThread type, which is an extremely important Binder interface that maintains the IPC communication between the application process and AMS in the system_server process. mClient is the application process in the system The proxy object in the process, AMS communicates with the application process as the server through mClient. The implementation class ApplicationThread in the application process is an internal class of ActivityThread, inherited from IApplicationThread.Stub, and implements the Binder interface. At this time, as a server, it accepts and executes the request sent by AMS in the system_server process, that is, the process switches to the application process to continue execution .
2.5.12 ActivityThread Scheduling Transaction
public abstract class ClientTransactionHandler {
/** Prepare and schedule transaction for execution. */
void scheduleTransaction(ClientTransaction transaction) {
transaction.preExecute(this);
// 发送 Handler 消息到 ActivityThread.H 中
sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
}
/**
* Get the {@link TransactionExecutor} that will be performing lifecycle transitions and
* callbacks for activities.
*/
abstract TransactionExecutor getTransactionExecutor();
// ActivityThread 实现该抽象方法,然后调用其内部的 mH 发送消息并处理
abstract void sendMessage(int what, Object obj);
}
public final class ActivityThread extends ClientTransactionHandler {
final H mH = new H();
// An executor that performs multi-step transactions.
private final TransactionExecutor mTransactionExecutor = new TransactionExecutor(this);
// 应用进程中 IApplicationThread 的实现类,继续调用 ActivityThread 的方法
private class ApplicationThread extends IApplicationThread.Stub {
@Override
public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
// 执行父类 ClientTransactionHandler # scheduleTransaction()
ActivityThread.this.scheduleTransaction(transaction);
}
}
class H extends Handler {
......
public static final int EXECUTE_TRANSACTION = 159; // 执行事务
public void handleMessage(Message msg) {
......
switch (msg.what) {
......
case EXECUTE_TRANSACTION:
// 获取传递过来的 ClientTransaction
final ClientTransaction transaction = (ClientTransaction) msg.obj;
// TransactionExecutor
mTransactionExecutor.execute(transaction);
if (isSystem()) {
// Client transactions inside system process are recycled on the client side
// instead of ClientLifecycleManager to avoid being cleared before this
// message is handled.
transaction.recycle();
}
// TODO(lifecycler): Recycle locally scheduled transactions.
break;
......
}
......
}
}
void sendMessage(int what, Object obj) {
sendMessage(what, obj, 0, 0, false);
}
......
private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
......
Message msg = Message.obtain();
msg.what = what;
msg.obj = obj;
msg.arg1 = arg1;
msg.arg2 = arg2;
if (async) {
msg.setAsynchronous(true);
}
mH.sendMessage(msg);
}
}
The execution process is as follows:
The ApplicationThread # scheduleTransaction() method continues to call the ActivityThread # scheduleTransaction() method, but the ActivityThread itself does not have this method, so the parent class ClientTransactionHandler # scheduleTransaction() method is executed.
ClientTransactionHandler # scheduleTransaction() method sends messages to ActivityThread through the implementation class H inherited from Handler, and rewrites its handleMessage() method.
H # handleMessage() method gets the passed ClientTransaction, and TransactionExecutor # execute() executes the conversion of the ClientTransaction.
2.5.13 TransactionExecutor transaction conversion executor
public void execute(ClientTransaction transaction) {
final IBinder token = transaction.getActivityToken();
if (token != null) {
final Map<IBinder, ClientTransactionItem> activitiesToBeDestroyed =
mTransactionHandler.getActivitiesToBeDestroyed();
final ClientTransactionItem destroyItem = activitiesToBeDestroyed.get(token);
if (destroyItem != null) {
if (transaction.getLifecycleStateRequest() == destroyItem) {
// 执行销毁与该 token 有关的 Activity 的事务,然后与此有关的记录将被移除
activitiesToBeDestroyed.remove(token);
}
if (mTransactionHandler.getActivityClient(token) == null) {
// Activity 还未完成创建就请求销毁,所以与这个 token 有关的事务都要取消
Slog.w(TAG, tId(transaction) + "Skip pre-destroyed transaction:\n"
+ transactionToString(transaction, mTransactionHandler));
return;
}
}
}
// 执行事务的回调 -- 第 8 小节中添加到 ClientTransaction 中的回调 -- LaunchActivityItem
executeCallbacks(transaction);
// 执行生命周期状态
executeLifecycleState(transaction);
mPendingActions.clear();
}
/**
* Cycle through all states requested by callbacks and execute them at proper times.
* 循环遍历回调列表中的所有状态请求,在适当的时间执行它们
*/
@VisibleForTesting
public void executeCallbacks(ClientTransaction transaction) {
final List<ClientTransactionItem> callbacks = transaction.getCallbacks();
if (callbacks == null || callbacks.isEmpty()) {
return;
}
final IBinder token = transaction.getActivityToken();
ActivityClientRecord r = mTransactionHandler.getActivityClient(token);
final ActivityLifecycleItem finalStateRequest = transaction.getLifecycleStateRequest();
final int finalState = finalStateRequest != null ? finalStateRequest.getTargetState()
: UNDEFINED;
// Index of the last callback that requests some post-execution state.
final int lastCallbackRequestingState = lastCallbackRequestingState(transaction);
final int size = callbacks.size();
for (int i = 0; i < size; ++i) {
final ClientTransactionItem item = callbacks.get(i);
......// 执行回调并输出日志
final int postExecutionState = item.getPostExecutionState();
final int closestPreExecutionState = mHelper.getClosestPreExecutionState(r,
item.getPostExecutionState());
if (closestPreExecutionState != UNDEFINED) {
cycleToPath(r, closestPreExecutionState, transaction);
}
// 获取到 LaunchActivityItem 并调用其 execute() 方法
item.execute(mTransactionHandler, token, mPendingActions);
item.postExecute(mTransactionHandler, token, mPendingActions);
if (r == null) {
// 启动活动请求将创建一个活动记录
r = mTransactionHandler.getActivityClient(token);
}
if (postExecutionState != UNDEFINED && r != null) {
final boolean shouldExcludeLastTransition =
i == lastCallbackRequestingState && finalState == postExecutionState;
cycleToPath(r, postExecutionState, shouldExcludeLastTransition, transaction);
}
}
}
In the TransactionExecutor # executeCallbacks() method, loop through all status requests in the callback list, and execute the added status requests at an appropriate time, here is 8. Get ClientTransaction, add Callback, and set the LaunchActivityItem added to ClientTransaction in LifecycleStateRequest.
2.5.14 LaunchActivityItem request to start Activity
/**
1. Request to launch an activity.
2. 请求启动 Activity
3. @hide
*/
public class LaunchActivityItem extends ClientTransactionItem {
@Override
public void execute(ClientTransactionHandler client, IBinder token,
PendingTransactionActions pendingActions) {
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,
mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,
mPendingResults, mPendingNewIntents, mIsForward,
mProfilerInfo, client, mAssistToken, mFixedRotationAdjustments);
client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
}
ClientTransactionHandler is an abstract class. ActivityThread inherits from ClientTransactionHandler and implements its abstract method, so here we return to the ActivityThread class and call its handleLaunchActivity() method to start the Activity.
2.5.15 ActivityThread executes and starts the Activity transaction
@Override
public Activity handleLaunchActivity(ActivityClientRecord r,
PendingTransactionActions pendingActions, Intent customIntent) {
......
WindowManagerGlobal.initialize();
// Hint the GraphicsEnvironment that an activity is launching on the process.
GraphicsEnvironment.hintActivityLaunch();
final Activity a = performLaunchActivity(r, customIntent);
if (a != null) {
r.createdConfig = new Configuration(mConfiguration);
reportSizeConfigurations(r);
if (!r.activity.mFinished && pendingActions != null) {
pendingActions.setOldState(r.state);
pendingActions.setRestoreInstanceState(true);
pendingActions.setCallOnPostCreate(true);
}
} else {
// 启动 Activity 发生异常,不论是什么原因,通知 ATMS 终止此 Activity
try {
ActivityTaskManager.getService()
.finishActivity(r.token, Activity.RESULT_CANCELED, null,
Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
return a;
}
/** Core implementation of activity launch. */
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);
}
......
// 创建 Activity 的 Context
ContextImpl appContext = createBaseContextForActivity(r);
Activity activity = null;
try {
// 通过 ClassLoader 反射获取 Activity 的实例
java.lang.ClassLoader cl = appContext.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
r.intent.prepareToEnterProcess();
if (r.state != null) {
r.state.setClassLoader(cl);
}
} catch (Exception e) {
......
}
try {
// 创建 Application
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
......
if (activity != null) {
......
appContext.getResources().addLoaders(
app.getResources().getLoaders().toArray(new ResourcesLoader[0]));
appContext.setOuterContext(activity);
// 执行 Activity 的 attach、初始化 Window 等
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.configCallback,
r.assistToken);
......
activity.mCalled = false;
// 执行 Activity 的 onCreate
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
......
r.activity = activity;
mLastReportedWindowingMode.put(activity.getActivityToken(),
config.windowConfiguration.getWindowingMode());
}
// 设置生命周期的状态为 ON_CREATE
r.setState(ON_CREATE);
synchronized (mResourcesManager) {
mActivities.put(r.token, r);
}
}
......
return activity;
}
performLaunchActivity() method execution flow:
Call the createBaseContextForActivity() method to create a ContextImpl object. In this method, call the ContextImpl # createActivityContext() method to create a ContextImpl object.
Call the Instrumentation # newActivity() method to load and create a new Activity, which calls the AppComponentFactory # instantiateActivity() method, and then loads the new Activity class through the newly created ClassLoader in the performLaunchActivity() method.
Create an Application object through the LoadApk # makeApplication() method, the process is similar to loading a new Activity, using ClassLoader.
Execute the Activity # attach() method, ContextImpl uses this method to establish an association with the Activity. In addition, the method also completes the creation of the Window instance and establishes its own association with the Window, so that when the Window receives an external input event, it will Events can be passed to the Activity.
Execute the Instrumentation # callActivityOnCreate() method, which calls the Activity # performCreate() method, and the Activity # performCreate() method calls the Activity # onCreate() method.
The process comes here. Activity # onCreate() method is executed, and the state of the life cycle is set to ON_CREATE. What about life cycle methods such as onStart and onResume?
2.5.16 ActivityThread executes lifecycle transactions
Looking back at 13. TransactionExecutor transaction conversion executor, before we only analyzed the process related to TransactionExecutor # executeCallbacks(transaction) execution callback, now let's look at the TransactionExecutor # executeLifecycleState(transaction) method.
/** Transition to the final state if requested by the transaction. */
private void executeLifecycleState(ClientTransaction transaction) {
// 获取之前设置的生命周期状态请求
final ActivityLifecycleItem lifecycleItem = transaction.getLifecycleStateRequest();
if (lifecycleItem == null) {
// No lifecycle request, return early.
return;
}
final IBinder token = transaction.getActivityToken();
// 获取 ActivityClientRecord,该对象保存 Activity 的启动信息
final ActivityClientRecord r = mTransactionHandler.getActivityClient(token);
......
if (r == null) {
// Ignore requests for non-existent client records for now.
return;
}
// Cycle to the state right before the final requested state.
// 执行当前已设置的生命周期请求最终状态之前的状态
cycleToPath(r, lifecycleItem.getTargetState(), true /* excludeLastState */, transaction);
// Execute the final transition with proper parameters.
// 执行设置的生命周期事务的最终转换
lifecycleItem.execute(mTransactionHandler, token, mPendingActions);
lifecycleItem.postExecute(mTransactionHandler, token, mPendingActions);
}
TransactionExecutor # executeLifecycleState(transaction) The method is mainly used to convert the lifecycle state of the Activity to the final state and execute it. The process is as follows:
Acquisition 8. Obtain ClientTransaction, add Callback, and set the final lifecycle state request after executing the transaction set in LifecycleStateRequest, which is the set ResumeActivityItem.
Obtain the ActivityRecord object that saves the startup information of the Activity, and call the cycleToPath() method to obtain and execute the state before the final state of the set life cycle request.
Call the ActivityLifecycleItem # execute() method to execute the final conversion of the set life cycle transaction, and the ResumeActivityItem # execute() method is actually called here.
2.5.17 TransactionExecutor executes intermediate state life cycle request transactions
What is an intermediate life cycle request transaction? The Android system defines corresponding XXXActivityItem classes for the life cycle of the Activity, such as StartActivityItem, PauseActivityItem, etc., which are life cycle request transactions in the intermediate state.
When will these intermediate life cycle request transactions be executed? For example, when is the lifecycle request onStart of the Activity corresponding to StartActivityItem triggered?
private void cycleToPath(ActivityClientRecord r, int finish, boolean excludeLastState,
ClientTransaction transaction) {
final int start = r.getLifecycleState();
......
final IntArray path = mHelper.getLifecyclePath(start, finish, excludeLastState);
performLifecycleSequence(r, path, transaction);
}
/** Transition the client through previously initialized state sequence. */
private void performLifecycleSequence(ActivityClientRecord r, IntArray path,
ClientTransaction transaction) {
final int size = path.size();
for (int i = 0, state; i < size; i++) {
state = path.get(i);
.......
switch (state) {
case ON_CREATE:
mTransactionHandler.handleLaunchActivity(r, mPendingActions,
null /* customIntent */);
break;
case ON_START:
mTransactionHandler.handleStartActivity(r.token, mPendingActions);
break;
......
}
}
}
The execution flow of the method is as follows:
Get the current life cycle status of the Activity to be started. Since the Activity # onCreate() method is executed and the life cycle status is set to ON_CREATE, start is ON_CREATE. In the previous section, we know that the final life cycle state request set is ResumeActivityItem, and its getTargetState() method returns ON_RESUME.
Call its getLifecyclePath() method through the TransactionExecutorHelper object to obtain the path of the secondary execution life cycle. In the method, a state array of IntArray type is constructed according to the start and finish states.
In calling the TransactionExecutor # performLifecycleSequence() method, traverse the constructed state sequence and execute the corresponding ActivityThread # handleXXXActivity() method in the application process to complete the transition of the lifecycle state.
Seeing this, it is still unclear when and where the onStart of the Activity life cycle is executed? But the auxiliary class TransactionExecutorHelper is worthy of attention. Use the TransactionExecutorHelper # getLifecyclePath() method to get the path of the main execution life cycle. See how this method works?
2.5.18 TransactionExecutorHelper obtains the status sequence of the life cycle to be executed
Let's first look at the definitions of life cycle states such as ON_START, ON_RESUME, etc., so that we can understand the follow-up process.
/**
* 请求 Activity 应该达到的生命周期状态
*/
public abstract class ActivityLifecycleItem extends ClientTransactionItem {
......
@Retention(RetentionPolicy.SOURCE)
public @interface LifecycleState{}
public static final int UNDEFINED = -1;
public static final int PRE_ON_CREATE = 0;
public static final int ON_CREATE = 1;
public static final int ON_START = 2;
public static final int ON_RESUME = 3;
public static final int ON_PAUSE = 4;
public static final int ON_STOP = 5;
public static final int ON_DESTROY = 6;
public static final int ON_RESTART = 7;
/** A final lifecycle state that an activity should reach. */
@LifecycleState
public abstract int getTargetState();
}
StartActivityItem, ResumeActivityItem, etc. related to the Activity life cycle inherit from this abstract class and implement its abstract method getTargetState(), which returns the corresponding life cycle. Note: LaunchActivityItem directly inherits from ClientTransactionItem.
Combine the above abstract class to analyze the TransactionExecutorHelper # getLifecyclePath() method, the code is as follows:
@VisibleForTesting
public IntArray getLifecyclePath(int start, int finish, boolean excludeLastState) {
......
// 清空生命周期状态序列
mLifecycleSequence.clear();
if (finish >= start) {
if (start == ON_START && finish == ON_STOP) {
// 如果很快从 ON_START 转换到 ON_STOP 状态,此时不需要经历恢复、暂停状态
mLifecycleSequence.add(ON_STOP);
} else {
// 添加 start 到 finish 之间的生命周期状态
for (int i = start + 1; i <= finish; i++) {
mLifecycleSequence.add(i);
}
}
}
......
// 根据条件判断移除最后的生命周期状态
if (excludeLastState && mLifecycleSequence.size() != 0) {
mLifecycleSequence.remove(mLifecycleSequence.size() - 1);
}
return mLifecycleSequence;
}
After the previous analysis, it can be seen that the start passed in the TransactionExecutorHelper # getLifecyclePath() method is ON_CREATE, finish is ON_RESUME, and excludeLastState is true. It can be seen from the definition of the ActivityLifecycleItem abstract class that finish >= start, so the method can only focus on the logic processing of this part. Through comparison, it can be found that there is an intermediate state of ON_START between ON_CREATE and ON_RESUME, so the ON_START and ON_RESUME states will be added to the mLifecycleSequence state sequence , at this time, because excludeLastState is true, the ON_RESUME state will be removed at the end, so the returned state sequence only contains the ON_START state, that is, the path obtained in the cycleToPath() method only contains the ON_START state.
So at this point, go back to 17. TransactionExecutor executes the intermediate state life cycle request transaction analysis performLifecycleSequence() method. At this time, there is only ON_START state value in the state sequence built by traversal, so execute the corresponding ActivityThread # handleStartActivity() method in the application process to complete the life For periodic state transitions, the method call flow is as follows:
In the ActivityThread # handleStartActivity() method, the activity # performStart() method is called to set the state of the life cycle to ON_START.
The Instrumentation # callActivityOnStart() method is called in the Activity # performStart() method, and the Activity # onStart() method is called in the Instrumentation # callActivityOnStart() method.
The process comes here Activity # onStart() method is executed, and the state of the life cycle is set to ON_START, continue to analyze the calling process of the onResume life cycle method?
2.5.19 TransactionExecutor executes the final conversion of lifecycle transactions
Looking back at the ActivityThread executing lifecycle transactions, the final conversion of the set lifecycle transactions will be executed at the end. Through the previous analysis, the ResumeActivityItem # execute() method is executed here, and the code is as follows:
@Override
public void execute(ClientTransactionHandler client, IBinder token,
PendingTransactionActions pendingActions) {
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityResume");
client.handleResumeActivity(token, true /* finalStateRequest */, mIsForward,
"RESUME_ACTIVITY");
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
As analyzed above, ClientTransactionHandler is an abstract class. ActivityThread inherits from ClientTransactionHandler and implements its abstract method, so the method called ActivityThread # handleResumeActivity() is not posted here. The method call process is as follows:
The ActivityThread # handleResumeActivity() method calls the ActivityThread # performResumeActivity() method to set the state of the life cycle to ON_RESUME.
The ActivityThread # performResumeActivity() method calls the Activity # performResume() method. The Instrumentation # callActivityOnResume() method is called in the Activity # performResume() method, and the Activity # onResume() method is called in the Instrumentation # callActivityOnResume() method.
After the breakpoint, you can view the calling relationship as follows,
Three, summary
So far, based on Android R (11.0), we have finally analyzed the startup process of the Activity. This article mainly analyzes the startup process of clicking the application ICON from the desktop to start the Activity, and removes the pages related to the startup process Launcher and the incubation process Zygote in this article. That is, the startup process of ordinary Activity, which will not be analyzed separately here.
In addition, the ClientTransaction part is worth studying in depth, which was added by Android P (9.0), and its functions are as follows:
Reduce the number of communications: AMS in the system process to the application process, one communication, including various communication events and content.
Coordinating message domains: classifying and coordinating life cycle changes and event updates, and processing them separately.
Reduce the coupling at both ends: AMS’s requirements for sending the life cycle in the system process are not equal to the processing requirements of the application process for the life cycle, so the application process will assemble a complete life cycle callback by itself, and the processing logic is more cohesive.
—————————————————
Reference: Original article by CSDN blogger "neuHenry", following the CC 4.0 BY-SA copyright agreement
Original text link: https://blog.csdn.net/u010347226 /article/details/124890884