1. Start the Activity
//startActivity
Intent intent = newIntent(ActivityA instance, activityb.class); startActivity(intent);//startActivityForResult
startActivityForResult(intent,REQUEST_CODE);
Copy the code
2. Analyze the Activity startup process
Assume ActivityA starts ActivityB
1, ` Activity# startActivityForResult ` :2, ` Instrumentation# execStartActivity ` :3, ` ActivityTaskManagerService# startActivity ` :4, ` ActivityTaskManagerService# startActivityAsUser ` :5, ` ActivityStarter# execute ` :6, ` ActivityStarter# startActivityInner ` :7, ` RootWindowContainer# resumeFocusedStacksTopActivities ` :8, ` ActivityStack# resumeTopActivityUncheckedLocked ` :9, ` ActivityStack# resumeTopActivityInnerLocked ` :9.1, 'ActivityStack#startPausingLocked' : handles ActivityA onPause9.2, 'activitystackcontainer #startSpecificActivity' : handles ActivityB startupCopy the code
Activity# startActivity method
public void startActivity(Intent intent) {
this.startActivity(intent, null);
}
public void startActivity(Intent intent, @Nullable Bundle options) {
if(options ! =null) {
startActivityForResult(intent, -1, options);
} else {
//options = null so this will be executed,requestCode = -1
startActivityForResult(intent, -1); }}Copy the code
RequestCode <0 indicates that the Activity starts normally, but the requestCode is not called back in onActivityResult(). All startActivities end up calling the startActivityForResult(@requiresperMission Intent Intent, int requestCode, Bundle options) method
//Activity.java
//requestCode= -1 ,options = null
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
@Nullable Bundle options) {
if (mParent == null) {
options = transferSpringboardActivityOptions(options);
/ / mParent = null, invoked mInstrumentation. ExecStartActivity start-up Activity
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this, intent, requestCode, options); }}Copy the code
Instrumentation is responsible for starting activities and calling related lifecycle methods
Instrumentation#execStartActivity( Context who, IBinder contextThread, IBinder token, Activity target, Intent intent, int requestCode, Bundle options)
//framework\base\core\java\android\app\Instrumentation.java
/ / who is ActivityA
/ / token for ActivityA token to find ActivityA ActivityRecord ActivityClientRecord
//contextThread =ApplicationThread inherits from IApplicationThread.Stub, which is the bridge for AMS to call App
/ / target for ActivityA
//requestCode = -1
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
IApplicationThread whoThread = (IApplicationThread) contextThread;
try {
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess(who);
// Call the AMS startActivity method
intresult = 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;
}
Copy the code
Client side through ActivityTaskManager. GetService () to the Server side Binder proxy objects, to communicate across processes, then call ActivityManagerService# startActivity method
//framework\base\services\core\java\com\android\server\am\ActivityManagerService.java
ResultTo is the ActivityA token
ResultWho is ActivityA's mEmbeddedID. MEmbeddedID is assigned to attach in the Activity
//requestCode =-1
//startFlags = 0
//profilerInfo = null
//callingPackage is the ActivityA package name
public int startActivity(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
return mActivityTaskManager.startActivity(caller, callingPackage, null, intent,
resolvedType, resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions);
}
Copy the code
Will call ActivityTaskManagerService# startActivityAsUser
//framework\base\services\core\java\com\android\server\wm\ActivityTaskManagerService.java
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);
enforceNotIsolatedCaller("startActivityAsUser");
userId = getActivityStartController().checkTargetUser(userId, validateIncomingUser,
Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");
// call the ActivityStarter#execute method
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();
}
Copy the code
The ActivityStarter#execute method calls executeRequest to execute the Request
//framework\base\services\core\java\com\android\server\wm\ActivityStarter.java
int execute(a) {
try {
// Result returns a value
int res;
synchronized (mService.mGlobalLock) {
res = resolveToHeavyWeightSwitcherIfNeeded();
if(res ! = START_SUCCESS) {return res;
}
// Call the executeRequest methodres = executeRequest(mRequest); }}}Copy the code
ActivityStarter# executeRequest method
//framework\base\services\core\java\com\android\server\wm\ActivityStarter.java
private int executeRequest(Request request) {
/ / call startActivityUnchecked
mLastStartActivityResult = startActivityUnchecked(r, sourceRecord, voiceSession,
request.voiceInteractor, startFlags, true /* doResume */, checkedOptions, inTask,
restrictedBgActivity, intentGrants);
return mLastStartActivityResult;
}
Copy the code
StartActivityInner is called in the startActivityUnchecked method
////framework\base\services\core\java\com\android\server\wm\ActivityStarter.java
int startActivityInner(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
int startFlags, boolean doResume, ActivityOptions options, Task inTask,
boolean restrictedBgActivity, NeededUriGrants intentGrants) {
if (mDoResume) {
final ActivityRecord topTaskActivity =
mStartActivity.getTask().topRunningActivityLocked();
if(! mTargetStack.isTopActivityFocusable() || (topTaskActivity ! =null&& topTaskActivity.isTaskOverlay() && mStartActivity ! = topTaskActivity)) { mTargetStack.getDisplay().mDisplayContent.executeAppTransition(); }else {
/ / call RootWindowContainer resumeFocusedStacksTopActivities methodmRootWindowContainer.resumeFocusedStacksTopActivities( mTargetStack, mStartActivity, mOptions); }}return START_SUCCESS;
}
Copy the code
RootWindowContainer#resumeFocusedStacksTopActivities
//framework\base\services\core\java\com\android\server\wm\RootWindowContainer.java
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) {
if(! resumedOnDisplay) {final ActivityStack focusedStack = display.getFocusedStack();
if(focusedStack ! =null) {
/ / call ActivityStack resumeTopActivityUncheckedLockedresult |= focusedStack.resumeTopActivityUncheckedLocked(target, targetOptions); }}}return result;
}
Copy the code
ActivityStack# resumeTopActivityInnerLocked method, prev ActivityA ActivityRecord
//framework\base\services\core\java\com\android\server\wm\ActivityStack.java
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
if(mResumedActivity ! =null) {
// Call startPausingLocked to execute ActivityA's onPause method
pausing |= startPausingLocked(userLeaving, false /* uiSleeping */, next);
}
if (prev.attachedToProcess()) {
try {
/ / to mobilize StackSupervisor startSpecificActivity
/ / start ActivityB
mStackSupervisor.startSpecificActivity(next, true.false);
return true;
}
return true;
}
Copy the code
2.1 Handling ActivityA onPause
ActivityStack#startPausingLocked pauses ActivityA
//framework\base\services\core\java\com\android\server\wm\ActivityStack.java
final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping,
ActivityRecord resuming) {
if (prev.attachedToProcess()) {
try {
//prev gets ActivityRecord from ActivityA
// Get ActivityA from ActivityRecord
Prev.app.getthread () is an ApplicationThread Binder agent object that performs scheduleTransactionmAtmService.getLifecycleManager().scheduleTransaction(prev.app.getThread(), prev.appToken, PauseActivityItem.obtain(prev.finishing, userLeaving, prev.configChangeFlags, pauseImmediately)); }}}Copy the code
The ApplicationThread#scheduleTransaction method is eventually called
public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
ActivityThread.this.scheduleTransaction(transaction);
}
void scheduleTransaction(ClientTransaction transaction) {
transaction.preExecute(this);
sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
}
// Execute to this point
case EXECUTE_TRANSACTION:
final ClientTransaction transaction = (ClientTransaction) msg.obj;
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();
}
Copy the code
Transactionor #execute Executes transactions
public void execute(ClientTransaction transaction) {
if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) + "Start resolving transaction");
final IBinder token = transaction.getActivityToken();
executeCallbacks(transaction);
executeLifecycleState(transaction);
}
public void executeCallbacks(ClientTransaction transaction) {
final List<ClientTransactionItem> callbacks = transaction.getCallbacks();
final IBinder token = transaction.getActivityToken();
ActivityClientRecord r = mTransactionHandler.getActivityClient(token);
final ActivityLifecycleItem finalStateRequest = transaction.getLifecycleStateRequest();
final intfinalState = finalStateRequest ! =null ? finalStateRequest.getTargetState()
: UNDEFINED;
final int lastCallbackRequestingState = lastCallbackRequestingState(transaction);
final int size = callbacks.size();
for (int i = 0; i < size; ++i) {
final ClientTransactionItem item = callbacks.get(i);
// Execute the execute methoditem.execute(mTransactionHandler, token, mPendingActions); }}Copy the code
PauseActivityItem#execute
public void execute(ClientTransactionHandler client, IBinder token, PendingTransactionActions pendingActions) {
/ / client for ActivityThread
client.handlePauseActivity(token, mFinished, mUserLeaving, mConfigChanges,
}
Copy the code
2.2 start ActivityB
Back to ActivityStack# resumeTopActivityInnerLocked method, ActivityStackSupervisor# startSpecificActivity, start ActivityB
//framework\base\services\core\java\com\android\server\wm\ActivityStackSupervisor.java
void startSpecificActivity(ActivityRecord r, boolean andResume, boolean checkConfig) {
// Is this activity's application already running?
final WindowProcessController wpc =
mService.getProcessController(r.processName, r.info.applicationInfo.uid);
if(wpc ! =null && wpc.hasThread()) {
try {
realStartActivityLocked(r, wpc, andResume, checkConfig);
return;
} catch (RemoteException e) {
}
}
}
Copy the code
realStartActivityLocked
//framework\base\services\core\java\com\android\server\wm\ActivityStackSupervisor.java
boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,
boolean andResume, boolean checkConfig) throws RemoteException {
final Task task = r.getTask();
final ActivityStack stack = task.getStack();
try {
// Create activity launch transaction.
final ClientTransaction clientTransaction = ClientTransaction.obtain(
proc.getThread(), r.appToken);
final DisplayContent dc = r.getDisplay().mDisplayContent;
// Add the LaunchActivityItem transaction callback
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()));
// Set desired final state.
final ActivityLifecycleItem lifecycleItem;
if (andResume) {
//andResume = true
lifecycleItem = ResumeActivityItem.obtain(dc.isNextTransitionForward());
} else {
lifecycleItem = PauseActivityItem.obtain();
}
clientTransaction.setLifecycleStateRequest(lifecycleItem);
// Schedule transactions
// Bind the scheduleTransaction method of ApplicationThread with binder
// Start ActivityB and execute the relevant lifecycle methods
mService.getLifecycleManager().scheduleTransaction(clientTransaction);
}
return true;
}
Copy the code
LaunchActivityItem#execute
//framework\base\core\java\android\app\servertransaction\LaunchActivityItem.java
public void execute(ClientTransactionHandler client, IBinder token, PendingTransactionActions pendingActions) {
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 */);
}
Copy the code
The ActivityThread#handleLaunchActivity reflection creates the Activity and executes the onCreate method
public Activity handleLaunchActivity(ActivityClientRecord r, PendingTransactionActions pendingActions, Intent customIntent) {
final Activity a = performLaunchActivity(r, customIntent);
return a;
}
Copy the code
ActivityThread#performLaunchActivity reflection create Activity call attach set theme call onCreate
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);
}
ComponentName component = r.intent.getComponent();
if (component == null) {
component = r.intent.resolveActivity(
mInitialApplication.getPackageManager());
r.intent.setComponent(component);
}
if(r.activityInfo.targetActivity ! =null) {
component = new ComponentName(r.activityInfo.packageName,
r.activityInfo.targetActivity);
}
ContextImpl appContext = createBaseContextForActivity(r);
Activity activity = null;
try {
java.lang.ClassLoader cl = appContext.getClassLoader();
// Reflection creates Activity
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); }}try {
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
if(activity ! =null) {
CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
Configuration config = new Configuration(mCompatConfiguration);
if(r.overrideConfig ! =null) {
config.updateFrom(r.overrideConfig);
}
Window window = null;
if(r.mPendingRemoveWindow ! =null && r.mPreserveWindow) {
window = r.mPendingRemoveWindow;
r.mPendingRemoveWindow = null;
r.mPendingRemoveWindowManager = null;
}
appContext.setOuterContext(activity);
// Call attach
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(customIntent ! =null) {
activity.mIntent = customIntent;
}
r.lastNonConfigurationInstances = null;
checkAndBlockForNetworkAccess();
activity.mStartedActivity = false;
int theme = r.activityInfo.getThemeResource();
if(theme ! =0) {
// Set the theme
activity.setTheme(theme);
}
activity.mCalled = false;
// Call onCreate
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
r.activity = activity;
}
// Set the state to ON_CREATE
r.setState(ON_CREATE);
synchronized (mResourcesManager) {
// Save to mActivitiesmActivities.put(r.token, r); }}return activity;
}
Copy the code
Back to the TransactionorExecute #execute method, the executeCallbacks handles the creation of the Activity and calls the onCreate method, OnStart and onResume are then handled with the executeLifecycleState call
public void execute(ClientTransaction transaction) {
if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) + "Start resolving transaction");
final IBinder token = transaction.getActivityToken();
// The onCreate method is done here
executeCallbacks(transaction);
// Proceed with onStart and onResume
executeLifecycleState(transaction);
}
Copy the code
TransactionExecutor#executeLifecycleState
private void executeLifecycleState(ClientTransaction transaction) {
final ActivityLifecycleItem lifecycleItem = transaction.getLifecycleStateRequest();
if (lifecycleItem == null) {
// No lifecycle request, return early.
return;
}
final IBinder token = transaction.getActivityToken();
final ActivityClientRecord r = mTransactionHandler.getActivityClient(token);
if (DEBUG_RESOLVER) {
Slog.d(TAG, tId(transaction) + "Resolving lifecycle state: "
+ lifecycleItem + " for activity: "
+ getShortActivityName(token, mTransactionHandler));
}
if (r == null) {
// Ignore requests for non-existent client records for now.
return;
}
// loop through path
/ / lifecycleItem getTargetState at this time for the onCreate ()
cycleToPath(r, lifecycleItem.getTargetState(), true /* excludeLastState */, transaction);
}
private void cycleToPath(ActivityClientRecord r, int finish, boolean excludeLastState,
ClientTransaction transaction) {
final int start = r.getLifecycleState();
/ / path = [2, 3]
final IntArray path = mHelper.getLifecyclePath(start, finish, excludeLastState);
performLifecycleSequence(r, path, transaction);
}
Copy the code
The getLifecyclePath method returns an array of execution lifecycles to be traversed, returning [2,3]
//framework\base\core\java\android\app\servertransaction\TransactionExecutorHelper.java
// 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;
// start = ON_CREATE =1 , finish = ON_RESUME =3
public IntArray getLifecyclePath(int start, int finish, boolean excludeLastState) {
mLifecycleSequence.clear();
if (finish >= start) {
if (start == ON_START && finish == ON_STOP) {
// A case when we from start to stop state soon, we don't need to go
// through the resumed, paused state.
mLifecycleSequence.add(ON_STOP);
} else {
// Add 2 and 3 onStart and onResume
for (int i = start + 1; i <= finish; i++) { mLifecycleSequence.add(i); }}}return mLifecycleSequence;
}
Copy the code
TransactionExecutor#performLifecycleSequence
private void performLifecycleSequence(ActivityClientRecord r, IntArray path, ClientTransaction transaction) {
final int size = path.size();
/ / path for ON_START ON_RESUME
for (int i = 0, state; i < size; i++) {
state = path.get(i);
switch (state) {
case ON_START:
/ / call ActivityThread# handleStartActivity
mTransactionHandler.handleStartActivity(r.token, mPendingActions);
break;
case ON_RESUME:
/ / call ActivityThread# handleResumeActivity
mTransactionHandler.handleResumeActivity(r.token, false /* finalStateRequest */,
r.isForward, "LIFECYCLER_RESUME_ACTIVITY");
break; }}}Copy the code
ActivityThread#handleStartActivity calls onStart and OnRestoreInstanceState
public void handleStartActivity(ActivityClientRecord r, PendingTransactionActions pendingActions) {
final Activity activity = r.activity;
/ / call the onStart
activity.performStart("handleStartActivity");
r.setState(ON_START);
/ / calls OnRestoreInstanceState
if (pendingActions.shouldRestoreInstanceState()) {
if (r.isPersistable()) {
if(r.state ! =null|| r.persistentState ! =null) { mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state, r.persistentState); }}else if(r.state ! =null) { mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state); }}/ / call postOnCreate ()
if (pendingActions.shouldCallOnPostCreate()) {
activity.mCalled = false;
if (r.isPersistable()) {
mInstrumentation.callActivityOnPostCreate(activity, r.state,
r.persistentState);
} else{ mInstrumentation.callActivityOnPostCreate(activity, r.state); }}}Copy the code
ActivityThread#handleResumeActivity, calls the onResume method and then addView to start drawing the view
public void handleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward,
String reason) {
// Execute onResume
final ActivityClientRecord r = performResumeActivity(token, finalStateRequest, reason);
final Activity a = r.activity;
booleanwillBeVisible = ! a.mStartedActivity;if(! willBeVisible) {try {
willBeVisible = ActivityTaskManager.getService().willActivityBeVisible(
a.getActivityToken());
} catch (RemoteException e) {
throwe.rethrowFromSystemServer(); }}if (r.window == null && !a.mFinished && willBeVisible) {
r.window = r.activity.getWindow();
View decor = r.window.getDecorView();
decor.setVisibility(View.INVISIBLE);
ViewManager wm = a.getWindowManager();
WindowManager.LayoutParams l = r.window.getAttributes();
a.mDecor = decor;
l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
l.softInputMode |= forwardBit;
if (r.mPreserveWindow) {
a.mWindowAdded = true;
r.mPreserveWindow = false;
ViewRootImpl impl = decor.getViewRootImpl();
if(impl ! =null) { impl.notifyChildRebuilt(); }}if (a.mVisibleFromClient) {
if(! a.mWindowAdded) { a.mWindowAdded =true;
// Perform the View drawing
wm.addView(decor, l);
} else {
a.onWindowAttributesChanged(l);
}
}
}
Looper.myQueue().addIdleHandler(new Idler());
}
Copy the code