1 Launcher
overview
The last step in system startup is to start an application to display the applications already installed in the system, this application is called Launcher
. Launcher
During the startup process, it will be requested PackageManagerService
to return the installed application program information in the system, and the information will be packaged into a shortcut icon list and displayed on the system screen, so that the user can start the corresponding application program by clicking these shortcut icons.
In layman's terms, Launcher
it is Android
the desktop of the system, and its functions mainly include the following two points:
- As
Android
the launcher of the system, it is used to start the application program; - As
Android
the desktop of the system, it is used to display and manage shortcut icons of applications or other desktop components;
2 Launcher
start process
SystemServer
The process will be started during the startup process PackageManagerService
, and PackageManagerService
the application programs in the system will be installed after startup, and the ones that have been started before ActivityManagerService
will be Launcher
started.
Launcher
The startup is divided into three parts:
SystemServer
Complete the relevant configurationLauncher
of the startupActivity
;Zygote
processfork
out processLauncher
;- Enter
ActivityThread.main
the function, and finally complete the operationLauncher
ofActivity.onCreate
;
Launcher
The relevant configuration completed in the first stage
SystemServer.startOtherServices
Call the method in the method , ActivityManagerService.systemReady
the Launcher
start of the process starts from here, the following is the relevant source code:
// /frameworks/base/services/java/com/android/server/SystemServer.java
private void startOtherServices() {
...
mActivityManagerService.systemReady(() -> {
// 1
Slog.i(TAG, "Making services ready");
traceBeginAndSlog("StartActivityManagerReadyPhase");
mSystemServiceManager.startBootPhase(
SystemService.PHASE_ACTIVITY_MANAGER_READY);
traceEnd();
}
...
)
}
The following is ActivityManagerService.systemReady
the source code of the method:
// /frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public ActivityTaskManagerInternal mAtmInternal;
public void systemReady(final Runnable goingCallback, TimingsTraceLog traceLog) {
...
// 启动 Home Activity,即 Launcher 应用的入口 Activity,这里指的是,在所有屏幕上启动 Launcher。因为 Android 10 开始支持多屏幕,比如手机屏幕、虚拟投屏、外接屏幕
mAtmInternal.startHomeOnAllDisplays(currentUserId, "systemReady"); // 1
...
}
Here mAtmInternal
is ActivityTaskManagerInternal
an instance of , ActivityTaskManagerInternal
which is an abstract class. ActivityManagerService
The inner class in LocalService
implements ActivityTaskManagerInternal
:
// /frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
final class LocalService extends ActivityTaskManagerInternal {
...
@Override
public boolean startHomeOnAllDisplays(int userId, String reason) {
synchronized (mGlobalLock) {
return mRootActivityContainer.startHomeOnAllDisplays(userId, reason);
}
}
...
}
LocalService.startHomeOnAllDisplays
The method was called in the method RootActivityContainer.startHomeOnAllDisplays
. RootActivityContainer
The role of is to call PackageManagerService
to query which of the installed applications in the mobile phone system meets Launcher
the standard, and return a Intent
object, and give it toActivityStarter
:
// /frameworks/base/services/core/java/com/android/server/wm/RootActivityContainer.java
boolean startHomeOnAllDisplays(int userId, String reason) {
boolean homeStarted = false;
for (int i = mActivityDisplays.size() - 1; i >= 0; i--) {
final int displayId = mActivityDisplays.get(i).mDisplayId;
homeStarted |= startHomeOnDisplay(userId, reason, displayId); // 1
}
return homeStarted;
}
boolean startHomeOnDisplay(int userId, String reason, int displayId) {
return startHomeOnDisplay(userId, reason, displayId, false /* allowInstrumenting */,false /* fromHomeKey */);
}
boolean startHomeOnDisplay(int userId, String reason, int displayId,
boolean allowInstrumenting, boolean fromHomeKey) {
...
Intent homeIntent = null;
ActivityInfo aInfo = null;
if (displayId == DEFAULT_DISPLAY) {
// 构建一个 category 为 CATEGORY_HOME 的 Intent,表明是 HomeActivity
homeIntent = mService.getHomeIntent(); // 2
// 通过 PMS 从系统所有已安装的引用中找到一个符合 homeIntent 的 Activity
aInfo = resolveHomeActivity(userId, homeIntent); // 3
} else if (shouldPlaceSecondaryHomeOnDisplay(displayId)) {
...
}
...
// 启动 Launcher
mService.getActivityStartController().startHomeActivity(homeIntent, aInfo,
myReason, displayId); // 4
return true;
}
2
The method is called at the comment ActivityTaskManagerService.getHomeIntent()
to build a for category
, indicating that it is a conforming application . Parse the information that needs to be started by calling the method at the comment . Call Get at the comment . The function of this class is to do various checks before startup, such as whether there is a list file registered, whether the file exists, etc., and then start .CATEGORY_HOME
Intent
Launcher
Intent
3
resolveHomeActivity
Activity
4
ActivityTaskManagerService.getActivityStartController()
ActivityStartController
Activity
Class
Activity
The following is the relevant timing diagram:
First, take a look at ActivityTaskManagerService.getHomeIntent()
the method, which is mainly to build a conforming Launcher
application Intent
:
// frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
Intent getHomeIntent() {
Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null);
intent.setComponent(mTopComponent);
intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
intent.addCategory(Intent.CATEGORY_HOME); // 1
}
return intent;
}
The comment 1
represents Activity
the intention to start. Generally speaking, there is only one application configured in the manifest file for the entire system CATEGORY_HOME
. If multiple applications are configured, the system will require the user to manually select which application to use when starting. Start the application. If it is configured in the system settings application, the configured application will be selected.
Then look at RootActivityContainer.resolveIntentInternal
the method:
// /frameworks/base/services/core/java/com/android/server/wm/RootActivityContainer.java
private ResolveInfo resolveIntentInternal(Intent intent, String resolvedType,
int flags, int userId,
boolean resolveForStart,
int filterCallingUid) {
try {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "resolveIntent");
if (!sUserManager.exists(userId)) return null;
final int callingUid = Binder.getCallingUid();
flags = updateFlagsForResolve(flags, userId, intent, filterCallingUid, resolveForStart);
mPermissionManager.enforceCrossUserPermission(callingUid, userId,
false /*requireFullPermission*/, false /*checkShell*/, "resolve intent");
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "queryIntentActivities");
final List<ResolveInfo> query = queryIntentActivitiesInternal(intent, resolvedType,
flags, filterCallingUid, userId, resolveForStart, true /*allowDynamicSplits*/);
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
final ResolveInfo bestChoice =
chooseBestActivity(intent, resolvedType, flags, query, userId);
return bestChoice;
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
}
Find a matching application from all installed applications in the system through Binder
cross-process communication notification .PackageManagerService
homeInent
Activity
Look at the code of again ActivityStartController.startHomeActivity
:
// /frameworks/base/services/core/java/com/android/server/wm/ActivityStartController.java
void startHomeActivity(Intent intent, ActivityInfo aInfo, String reason,
int displayId) {
final ActivityOptions options = ActivityOptions.makeBasic();
options.setLaunchWindowingMode(WINDOWING_MODE_FULLSCREEN);
if (!ActivityRecord.isResolverActivity(aInfo.name)) {
options.setLaunchActivityType(ACTIVITY_TYPE_HOME);
}
options.setLaunchDisplayId(displayId);
mLastHomeActivityStartResult =
obtainStarter(intent, "startHomeActivity: " + reason) // 1
.setOutActivity(tmpOutRecord)
.setCallingUid(0)
.setActivityInfo(aInfo)
.setActivityOptions(options.toBundle())
.execute(); // 2
mLastHomeActivityStartRecord = tmpOutRecord[0];
final ActivityDisplay display =
mService.mRootActivityContainer.getActivityDisplay(displayId);
final ActivityStack homeStack = display != null ? display.getHomeStack() : null;
if (homeStack != null && homeStack.mInResumeTopActivity) {
mSupervisor.scheduleResumeTopActivities();
}
}
ActivityStarter obtainStarter(Intent intent, String reason) {
// 3
return mFactory.obtain().setIntent(intent).setReason(reason);
}
1
First get one at the comment ActivityStarter
, which is mainly used for startup Activity
, then set the required parameters, and finally call its execute()
method:
// /frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
int execute() {
try {
if (mRequest.mayWait) {
...
} else {
return startActivity(...);
}
} finally {
onExecutionComplete();
}
}
The following is ActivityStarter.startActivity
the relevant source code of , this method is mainly used for Activity
security verification before startup:
// /frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
private int startActivity(...) {
mSupervisor.getActivityMetricsLogger().notifyActivityLaunching(intent);
int err = ActivityManager.START_SUCCESS;
// Pull the optional Ephemeral Installer-only bundle out of the options early.
final Bundle verificationBundle
= options != null ? options.popAppVerificationBundle() : null;
WindowProcessController callerApp = null;
if (caller != null) {
callerApp = mService.getProcessController(caller);
if (callerApp != null) {
callingPid = callerApp.getPid();
callingUid = callerApp.mInfo.uid;
} else {
Slog.w(TAG, "Unable to find app for caller " + caller
+ " (pid=" + callingPid + ") when starting: "
+ intent.toString());
err = ActivityManager.START_PERMISSION_DENIED;
}
}
...
final int res = startActivity(r, sourceRecord, voiceSession, voiceInteractor,
startFlags, true /* doResume */, checkedOptions,
inTask, outActivity, restrictedBgActivity);
...
}
private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession,
IVoiceInteractor voiceInteractor, int startFlags,
boolean doResume, ActivityOptions options,
TaskRecord inTask, ActivityRecord[] outActivity,
boolean restrictedBgActivity) {
...
result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
startFlags, doResume, options, inTask,
outActivity, restrictedBgActivity); // 1
...
}
Code 1
called at comment :ActivityStarter.startActivityUnchecked
// /frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
private int startActivityUnchecked(final ActivityRecord r,
ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession,
IVoiceInteractor voiceInteractor, int startFlags,
boolean doResume, ActivityOptions options,
TaskRecord inTask, ActivityRecord[] outActivity,
boolean restrictedBgActivity) {
...
final int preferredWindowingMode = mLaunchParams.mWindowingMode;
computeLaunchingTaskFlags(); // 1
computeSourceStack(); // 2
mIntent.setFlags(mLaunchFlags);
ActivityRecord reusedActivity = getReusableIntentActivity();
...
mRootActivityContainer.resumeFocusedStacksTopActivities(); // 3
...
}
1
The method at the comment ActivityStarter.computeLaunchingTaskFlags()
is the stacking method calculated based Activity
on the launcher mode
and of . The calculation at the comment starts from which stack . The method is called at the comment :intent.flag
Activity
2
ActivityStarter.computeSourceStack()
Activity
3
RootActivityContainer.resumeFocusedStacksTopActivities
// /frameworks/base/services/core/java/com/android/server/wm/RootActivityContainer.java
boolean resumeFocusedStacksTopActivities() {
return resumeFocusedStacksTopActivities(null, null, null);
}
boolean resumeFocusedStacksTopActivities(
ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
...
if (targetStack != null && (targetStack.isTopStackOnDisplay()
|| getTopDisplayFocusedStack() == targetStack)) {
result = targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
}
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
...
if (!resumedOnDisplay) {
final ActivityStack focusedStack = display.getFocusedStack();
if (focusedStack != null) {
focusedStack.resumeTopActivityUncheckedLocked(target, targetOptions); // 1
}
}
}
return result;
}
1
Call the method at the comment ActivityStack.resumeTopActivityUncheckedLocked
:
// /frameworks/base/services/core/java/com/android/server/wm/ActivityStack.java
@GuardedBy("mService")
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
...
result = resumeTopActivityInnerLocked(prev, options);
...
}
@GuardedBy("mService")
private boolean resumeTopActivityInnerLocked(ActivityRecord prev,
ActivityOptions options) {
...
if (anim) {
next.applyOptionsLocked();
} else {
next.clearOptionsLocked();
}
mStackSupervisor.mNoAnimActivities.clear();
if (next.attachedToProcess()) {
// 待启动的进程是否创建完成,如果没有就会到 else 中
...
} else {
mStackSupervisor.startSpecificActivityLocked(next, true, true); // 1
}
...
}
1
Called at comment ActivityStackSupervisor.startSpecificActivityLocked
:
// /frameworks/base/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
void startSpecificActivityLocked(ActivityRecord r, boolean andResume,
boolean checkConfig) {
...
try {
...
final Message msg = PooledLambda.obtainMessage(
ActivityManagerInternal::startProcess, // 1
mService.mAmInternal, r.processName, r.info.applicationInfo,
knownToBeDead, "activity", r.intent.getComponent());
mService.mH.sendMessage(msg);
} finally {
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
}
Note 1
that the call is actually ActivityManagerService.startProcess
the method, which starts to create a process:
// /frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public final class LocalService extends ActivityManagerInternal {
@Override
public void startProcess(String processName, ApplicationInfo info,
boolean knownToBeDead, 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) {
startProcessLocked(processName, info, knownToBeDead,
0 /* intentFlags */,
new HostingRecord(hostingType, hostingName),
false /* allowWhileBooting */,
false /* isolated */,
true /* keepIfLarge */); // 1
}
} finally {
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
}
@GuardedBy("this")
final ProcessRecord startProcessLocked(String processName,
ApplicationInfo info,
boolean knownToBeDead, int intentFlags,
HostingRecord hostingRecord,
boolean allowWhileBooting,
boolean isolated, boolean keepIfLarge) {
return mProcessList.startProcessLocked(processName, info, knownToBeDead,
intentFlags,
hostingRecord, allowWhileBooting,
isolated, 0 /* isolatedUid */,
keepIfLarge,
null /* ABI override */,
null /* entryPoint */,
null /* entryPointArgs */,
null /* crashHandler */); // 2
}
}
1
Call the method at the comment LocalService.startProcessLocked
. In LocalService.startProcessLocked
the method, the work of process creation is delegated to ProcessList
. Then look at ProcessList.startProcessLocked
the method:
// /frameworks/base/services/core/java/com/android/server/am/ProcessList.java
@GuardedBy("mService")
final void startProcessLocked(ProcessRecord app, HostingRecord hostingRecord) {
startProcessLocked(app, hostingRecord, null /* abiOverride */);
}
@GuardedBy("mService")
final boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord,
String abiOverride) {
return startProcessLocked(app, hostingRecord, false /* disableHiddenApiChecks */,
false /* mountExtStorageFull */, abiOverride);
}
@GuardedBy("mService")
boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord,
boolean disableHiddenApiChecks,
boolean mountExtStorageFull,
String abiOverride) {
...
final String entryPoint = "android.app.ActivityThread"; // 1
return startProcessLocked(hostingRecord, entryPoint, app, uid, gids,
runtimeFlags, mountExternal, seInfo, requiredAbi,
instructionSet, invokeWith, startTime);
}
@GuardedBy("mService")
final ProcessRecord startProcessLocked(String processName, ApplicationInfo info,
boolean knownToBeDead, int intentFlags,
HostingRecord hostingRecord,
boolean allowWhileBooting, boolean isolated,
int isolatedUid, boolean keepIfLarge,
String abiOverride, String entryPoint,
String[] entryPointArgs, Runnable crashHandler) {
if (!isolated) {
app = getProcessRecordLocked(processName, info.uid, keepIfLarge);
checkSlow(startTime, "startProcess: after getProcessRecord");
...
}
final String entryPoint = "android.app.ActivityThread";
...
}
The function of these methods is to configure some necessary parameters before the process is created, such as version number and other parameters. In the comment 1
is a very important parameter, entryPoint
which is the entry point of the new process. So, Android
the program entry of the application is ActivityThread
.
After the configuration of the parameters required to create a process is completed, it will eventually go to ZygoteProcess
the class:
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,
boolean useUsapPool,
@Nullable String[] extraArgs)
throws ZygoteStartFailedEx {
synchronized (mLock) {
return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi),
useUsapPool, argsForZygote);
}
}
At this time, it is still in system_server
the process. The purpose of this class is to create a local Socket
connection object, connect to the method Zygote
of the process Socket
, and then send the parameters needed to create the process through the character input stream.
Phase 2: Zygote
The process receives the request and creates Launcher
a process
Refer to the application process startup process
Phase Three: Entry ActivityThread.main
, Final Completion Launcher.onCreate
Operations
Zygote
fork
Exit Launcher
the process, and hand over the next Launcher
startup task ActivityThread
to , and then analyze the creation process from ActivityThread.main
the method . Launcher
The following is the timing diagram for ActivityThread
startup Activity
:
ActivityThread.main
The method is the program entry, the following is the relevant code:
// /frameworks/base/core/java/android/app/ActivityThread.java
public static void main(String[] args) {
...
Looper.prepareMainLooper();
...
ActivityThread thread = new ActivityThread();
thread.attach(false, startSeq); // 1
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
...
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
1
Call the method at the comment ActivityThread.attach
, the following is the relevant source code:
// /frameworks/base/core/java/android/app/ActivityThread.java
@UnsupportedAppUsage
private void attach(boolean system, long startSeq) {
sCurrentActivityThread = this;
mSystemThread = system;
if (!system) {
...
final IActivityManager mgr = ActivityManager.getService(); // 1
try {
mgr.attachApplication(mAppThread, startSeq); // 2
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
...
} else {
...
}
...
}
1
Get ActivityManagerService
an instance of at the annotation and 2
call ActivityManagerService.attachApplication
the method at the annotation:
// /frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
@Override
public final void attachApplication(IApplicationThread thread, long startSeq) {
if (thread == null) {
throw new SecurityException("Invalid application interface");
}
synchronized (this) {
// 通过 Binder 获取传入的 pid 信息
int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
attachApplicationLocked(thread, callingPid, callingUid, startSeq); // 1
Binder.restoreCallingIdentity(origId);
}
}
public ActivityTaskManagerInternal mAtmInternal;
@GuardedBy("this")
private boolean attachApplicationLocked(@NonNull IApplicationThread thread,
int pid, int callingUid, long startSeq) {
...
didSomething = mAtmInternal.attachApplication(app.getWindowProcessController()); // 2
...
}
1
The method is called at the annotation ActivityManagerService.attachApplicationLocked
. 2
The at the comment mAtmInternal
is ActivityTaskManagerInternal
a variable of type, ActivityTaskManagerService
the internal class LocalService
in inherits from ActivityTaskManagerInternal
, the following is the relevant source code:
// /frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
final class LocalService extends ActivityTaskManagerInternal {
@HotPath(caller = HotPath.PROCESS_CHANGE)
@Override
public boolean attachApplication(WindowProcessController wpc) throws RemoteException {
synchronized (mGlobalLockWithoutBoost) {
return mRootActivityContainer.attachApplication(wpc); // 1
}
}
}
1
The method is called at the comment RootActivityContainer.attachApplication
:
// frameworks/base/services/core/java/com/android/server/wm/RootActivityContainer.java
boolean attachApplication(WindowProcessController app) throws RemoteException {
final String processName = app.mName;
boolean didSomething = false;
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
final ActivityDisplay display = mActivityDisplays.get(displayNdx);
final ActivityStack stack = display.getFocusedStack();
if (stack != null) {
stack.getAllRunningVisibleActivitiesLocked(mTmpActivityList);
final ActivityRecord top = stack.topRunningActivityLocked();
final int size = mTmpActivityList.size();
for (int i = 0; i < size; i++) {
final ActivityRecord activity = mTmpActivityList.get(i);
if (activity.app == null && app.mUid == activity.info.applicationInfo.uid
&& processName.equals(activity.processName)) {
try {
// 1
if (mStackSupervisor.realStartActivityLocked(activity, app,
top == activity /* andResume */,
true /* checkConfig */)) {
didSomething = true;
}
} catch (RemoteException e) {
Slog.w(TAG, "Exception in new application when starting activity "
+ top.intent.getComponent().flattenToShortString(), e);
throw e;
}
}
}
}
}
if (!didSomething) {
ensureActivitiesVisible(null, 0, false /* preserve_windows */);
}
return didSomething;
}
1
Call the method at the comment ActivityStackSupervisor.realStartActivityLocked
:
// /frameworks/base/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,
boolean andResume, boolean checkConfig) throws RemoteException {
...
clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),
System.identityHashCode(r), r.info,
mergedConfiguration.getGlobalConfiguration(),
mergedConfiguration.getOverrideConfiguration(), r.compat,
r.launchedFromPackage, task.voiceInteractor,
proc.getReportedProcState(), r.icicle, r.persistentState, results,
newIntents, dc.isNextTransitionForward(),
proc.createProfilerInfoIfNeeded(), r.assistToken)); // 1
...
// Schedule transaction.
mService.getLifecycleManager().scheduleTransaction(clientTransaction); // 2
...
}
2
The method at comment ActivityTaskManagerService.getLifecycleManager
returns ClientLifecycleManager
the instance. The following is ClientLifecycleManager.scheduleTransaction
the relevant source code:
// /frameworks/base/services/core/java/com/android/server/wm/ClientLifecycleManager.java
void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
final IApplicationThread client = transaction.getClient();
transaction.schedule(); // 1
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();
}
}
1
The method is called at the comment ClientTransaction.schedule
:
// /frameworks/base/core/java/android/app/servertransaction/ClientTransaction.java
private IApplicationThread mClient;
public void schedule() throws RemoteException {
mClient.scheduleTransaction(this); // 1
}
1
The in the comment mClient
is IApplicationThread
an instance, here is ApplicationThread
the internal class of , the following is the relevant source code ApplicationThread
:ActivityThread
// /frameworks/base/core/java/android/app/ActivityThread.java
private class ApplicationThread extends IApplicationThread.Stub {
@Override
public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
ActivityThread.this.scheduleTransaction(transaction); // 1
}
}
1
The method is called in the comment ActivityThread.this.scheduleTransaction
, ActivityThread
which is inherited from ClientTransactionHandler
, so the method is called here ClientTransactionHandler.scheduleTransaction
. The following is the relevant source code:
// /frameworks/base/core/java/android/app/ClientTransactionHandler.java
void scheduleTransaction(ClientTransaction transaction) {
transaction.preExecute(this);
sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction); // 1
}
1
The in the comment ActivityThread.H
is Handler
a subclass of , the following is ActivityThread.sendMessage
the source code of the method and ActivityThread.H.EXECUTE_TRANSACTION
related processing about :
// /frameworks/base/core/java/android/app/ActivityThread.java
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) {
if (DEBUG_MESSAGES) {
Slog.v(TAG,
"SCHEDULE " + what + " " + mH.codeToString(what) + ": " + arg1 + " / " + obj);
}
Message msg = Message.obtain();
msg.what = what;
msg.obj = obj;
msg.arg1 = arg1;
msg.arg2 = arg2;
if (async) {
msg.setAsynchronous(true);
}
mH.sendMessage(msg);
}
class H extends Handler {
...
public static final int EXECUTE_TRANSACTION = 159;
...
public void handleMessage(Message msg) {
if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
switch (msg.what) {
...
case EXECUTE_TRANSACTION:
final ClientTransaction transaction = (ClientTransaction) msg.obj;
mTransactionExecutor.execute(transaction); // 1
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;
...
}
}
}
method 1
called at annotationTransactionExecutor.execute
// /frameworks/base/core/java/android/app/servertransaction/TransactionExecutor.java
public void execute(ClientTransaction transaction) {
...
executeCallbacks(transaction); // 1
executeLifecycleState(transaction);
mPendingActions.clear();
if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) + "End resolving transaction");
}
@VisibleForTesting
public void executeCallbacks(ClientTransaction transaction) {
...
final int size = callbacks.size();
for (int i = 0; i < size; ++i) {
final ClientTransactionItem item = callbacks.get(i);
...
item.execute(mTransactionHandler, token, mPendingActions); // 2
..
}
}
2
The method is called at the comment , which is implemented ClientTransactionItem.execute
in its subclass , the following is the method:LaunchActivityItem
LaunchActivityItem.execute
// /frameworks/base/core/java/android/app/servertransaction/LaunchActivityItem.java)
@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);
client.handleLaunchActivity(r, pendingActions, null /* customIntent */); // 1
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
1
The in the comment client
is ClientTransactionHandler
a subclass of ActivityThread
, view ActivityThread.handleLauncherActivity
the source code of , mainly calling ActivityThread.performLaunchActivity
the method:
// /frameworks/base/core/java/android/app/ActivityThread.java
@Override
public Activity handleLaunchActivity(ActivityClientRecord r,
PendingTransactionActions pendingActions,
Intent customIntent) {
...
WindowManagerGlobal.initialize();
// 1 启动 Activity
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 {
// If there was an error, for any reason, tell the activity manager to stop us.
try {
// 停止 Activity 的启动
ActivityTaskManager.getService()
.finishActivity(r.token, Activity.RESULT_CANCELED, null,
Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
return a;
}
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
ActivityInfo aInfo = r.activityInfo; // 2 获取 ActivityInfo 类
if (r.packageInfo == null) {
// 3 获取 APK 文件描述类 LoadApk
r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
Context.CONTEXT_INCLUDE_CODE);
}
ComponentName component = r.intent.getComponent(); // 4
...
// 5 创建要启动的 Activity 的上下文环境
ContextImpl appContext = createBaseContextForActivity(r);
Activity activity = null;
try {
java.lang.ClassLoader cl = appContext.getClassLoader();
// 6 用类加载器创建该 Activity 的实例
activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);
...
} catch (Exception e) {
...
}
try {
// 7 创建 Application
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
...
if (activity != null) {
...
// 8 初始化 Activity
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);
...
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState); // 9
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
...
}
...
} catch (SuperNotCalledException e) {
throw e;
} catch (Exception e) {
....
}
return activity;
}
The comment 1
calls ActivityThread.performLaunchActivity
the method to start Activity
. Comments are used to 2
obtain ActivityInfo
and store code and AndroidManifest
set Activity
and Receiver
node information, for example, Activity
and . Get the description class of the file at the comment . Obtain the class of the to be started at the comment , and save the package name and class name of the class in the class. Used at comments to create the context in which to start . According to the class name stored in the comment , use the class loader to create the instance of the . The comment is used to create , and the method will be called inside the method. Call the method initialization at the annotation , and the object ( ) will be created in the method and associated with itself. Call the method at the comment to start :theme
launchMode
3
APK
LoadedApk
4
Activity
ComponentName
ComponentName
Activity
5
Activity
6
ComponentName
Activity
Activity
7
Application
LoadedApk.makeApplication
Application.onCreate
8
Activity.attach
Activity
Activity.attach
Window
PhoneWindow
Activity
9
Instrumentation.callActivityOnCreate
Activity
// /frameworks/base/core/java/android/app/Instrumentation.java
public void callActivityOnCreate(Activity activity, Bundle icicle,
PersistableBundle persistentState) {
prePerformCreate(activity);
activity.performCreate(icicle, persistentState); // 1
postPerformCreate(activity);
}
1
The method is called at the comment Activity.performCreate
, Activity.performCreate
and the method is called in the method Activity.onCreate
. At this point, the root Activity
is started. The following is the relevant source code:
// /frameworks/base/core/java/android/app/Activity.java
@UnsupportedAppUsage
final void performCreate(Bundle icicle, PersistableBundle persistentState) {
dispatchActivityPreCreated(icicle);
mCanEnterPictureInPicture = true;
restoreHasCurrentPermissionRequest(icicle);
// 1
if (persistentState != null) {
onCreate(icicle, persistentState);
} else {
onCreate(icicle);
}
writeEventLog(LOG_AM_ON_CREATE_CALLED, "performCreate");
mActivityTransitionState.readState(icicle);
mVisibleFromClient = !mWindow.getWindowStyle().getBoolean(
com.android.internal.R.styleable.Window_windowNoDisplay, false);
mFragments.dispatchActivityCreated();
mActivityTransitionState.setEnterActivityOptions(this, getActivityOptions());
dispatchActivityPostCreated(icicle);
}
@MainThread
@CallSuper
protected void onCreate(@Nullable Bundle savedInstanceState) {
if (DEBUG_LIFECYCLE) Slog.v(TAG, "onCreate " + this + ": " + savedInstanceState);
if (mLastNonConfigurationInstances != null) {
mFragments.restoreLoaderNonConfig(mLastNonConfigurationInstances.loaders);
}
if (mActivityInfo.parentActivityName != null) {
if (mActionBar == null) {
mEnableDefaultActionBarUp = true;
} else {
mActionBar.setDefaultDisplayHomeAsUpEnabled(true);
}
}
if (savedInstanceState != null) {
mAutoFillResetNeeded = savedInstanceState.getBoolean(AUTOFILL_RESET_NEEDED, false);
mLastAutofillId = savedInstanceState.getInt(LAST_AUTOFILL_ID,
View.LAST_APP_AUTOFILL_ID);
if (mAutoFillResetNeeded) {
getAutofillManager().onCreate(savedInstanceState);
}
Parcelable p = savedInstanceState.getParcelable(FRAGMENTS_TAG);
mFragments.restoreAllState(p, mLastNonConfigurationInstances != null
? mLastNonConfigurationInstances.fragments : null);
}
mFragments.dispatchCreate();
dispatchActivityCreated(savedInstanceState);
if (mVoiceInteractor != null) {
mVoiceInteractor.attachActivity(this);
}
mRestoredFromBundle = savedInstanceState != null;
mCalled = true;
}
public void onCreate(@Nullable Bundle savedInstanceState,
@Nullable PersistableBundle persistentState) {
onCreate(savedInstanceState);
}