One, the introduction

Based on the Activity startup mode introduced in the previous part, the related process of starting an Activity in the application process, and the related process of starting an Activity in the Android FrameWork introduced in the middle part, With Binder, you can call the application process to start the Activity on Android Q. Of course, another purpose of writing this blog is to better understand how to implement Android plug-in on Android Q, after all, Android plug-in is based on the application process level of the Android Framework Hook.

In addition, it should be noted that although the previous and midarticles are based on the relevant source code of Android P, but in this piece of code logic on Android P and Android Q does not change too much, so do not worry about this blog and the previous blog discontinuity.

Second, the source

1. The Android Framework layer communicates with the Binder of application processes

In the Android Framework, the Activity startup process ends up in realStartActivityLocked methods of the ActivityStackSupervisor class, Binder objects in ActivityThread implement communication between the Android Framework layer and the application process. The core code is as follows:

. // Generate ClientTransaction by passing in the Binder object of the application process in which the Activity is started. ClientTransaction ClientTransaction = clientTransaction.obtain (proc.getThread(), r.appToken); final DisplayContent dc = r.getDisplay().mDisplayContent; 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)); // Set the final state of the Activity to enter. Final ActivityLifecycleItem lifecycleItem; if (andResume) { lifecycleItem = ResumeActivityItem.obtain(dc.isNextTransitionForward()); } else { lifecycleItem = PauseActivityItem.obtain(); } clientTransaction.setLifecycleStateRequest(lifecycleItem); // Call the Schedule method of ClientTransaction in the class ClientLifecycleManager mService.getLifecycleManager().scheduleTransaction(clientTransaction); .Copy the code

After a series of transitions, it is called into the ClientTransaction Schedule method, which is easily implemented by Binder directly into the application process. The code is as follows:

// This is a serialized object that implements the Parcelable interface. Can be passed between process public void the schedule () throws RemoteException {mClient. ScheduleTransaction (this); }Copy the code

The mClient object is the ApplicationThread, the Binder object of the application processes passed in to realStartActivityLocked. Both the Binder object definition and the instance object are in the ActivityThread of the application process, so we jump directly to the ActivityThread for the rest of the process.

2. Access the application process

In the Android Instead of calling the scheduleLaunchActivity directly and then calling the handleLaunchActivity method to start the Activity in ActivityThread or above; Instead, it swings back and forth between classes and starts the Activity in the handleLaunchActivity method of the ActivityThread.

2.1 Starting point of ActivityThread

Starting an Activity from the Android FrameWork to the application layer starts with scheduleTransaction, the Binder class in ActivityThread, which does nothing. It simply calls the scheduleTransaction method that ActivityThread inherits from its parent class.

public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
      ActivityThread.this.scheduleTransaction(transaction);
}
Copy the code

So go straight to the Activity implementation class ClientTransactionHandler to see how it works:

Void scheduleTransaction(ClientTransaction Transaction) {// Do some initialization work before starting the Activity. SendMessage (ActivityThread.h.execute_TRANSACTION, transaction); }Copy the code

Skip the unnecessary code here for the moment:

 case EXECUTE_TRANSACTION:
      final ClientTransaction transaction = (ClientTransaction) msg.obj;
      mTransactionExecutor.execute(transaction);
      if (isSystem()) {
          transaction.recycle();
      }
 break;
Copy the code

2.2 TransactionExecutor

It then continues to call the Execute method of the TransactionExecutor class

Public void execute(ClientTransaction Transaction) {// Get windowManager Token, in ActivityRecord instance object generated by the current ActivityRecord and Intent final IBinder token = transaction. GetActivityToken (); if (token ! Final Map<IBinder, ClientTransactionItem> activitiesToBeDestroyed = mTransactionHandler.getActivitiesToBeDestroyed(); final ClientTransactionItem destroyItem = activitiesToBeDestroyed.get(token); if (destroyItem ! = null) {// If the next action to execute is to destroy the Activity, Is removed from the list that need to be really destroyed the Activity relative to the corresponding information if (transaction. GetLifecycleStateRequest () = = destroyItem) { activitiesToBeDestroyed.remove(token); } // The Activity is never actually started, Is don't do anything if (mTransactionHandler getActivityClient (token) = = null) {Slog w. (TAG, tId(transaction) + "Skip pre-destroyed transaction:\n" + transactionToString(transaction, mTransactionHandler)); return; }}} // This function will actually call the handleLaunchActivity method in the ActivityThread to start executing onCreate executeCallbacks(transaction); ExecuteLifecycleState (transaction); // Execute subsequent onStart and onResume methods; mPendingActions.clear(); }Copy the code

This omits the parts of the code that are not cared for in the executeCallbacks method:

. for (int i = 0; i < size; ++i) { ...... // This calls the callBack set above in ActivityStackSupervisor's realStartActivityLocked method. Item. execute(mTransactionHandler, Token, mPendingActions); // Add 1 item.postExecute(mTransactionHandler, Token, mPendingActions); . }...Copy the code

Let’s take a look at what’s going on in the core execute method.

public void execute(ClientTransactionHandler client, IBinder token, PendingTransactionActions pendingActions) {/ / first generate corresponding ActivityClientRecord object, ActivityClientRecord r = New ActivityClientRecord(Token, mIntent, mIdent, mInfo, mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState, mPendingResults, mPendingNewIntents, mIsForward, mProfilerInfo, client, mAssistToken); / / and then began to create and start the Activity, the subsequent client are introduced. The handleLaunchActivity (r, pendingActions, null customIntent / * * /); }Copy the code

We continued to look at the TransactionExecutor’s executelifeccleState method, In this method, the handleStartActivity method of ActivityThread and the handleResumeActivity method are executed.

private void executeLifecycleState(ClientTransaction transaction) { final ActivityLifecycleItem lifecycleItem = transaction.getLifecycleStateRequest(); . / / calculate the initial state of the Activity to reach the final state of needed through the middle of the cycleToPath (r, lifecycleItem getTargetState (), true excludeLastState / * * /, transaction); Lifecycleitem. execute(mTransactionHandler, token, mPendingActions); lifecycleItem.postExecute(mTransactionHandler, token, mPendingActions); }Copy the code

2.2 ActivityThread Executes the Activity lifecycle

2.2.1 handleLaunchActivity

This method doesn’t do much else. It does some initialization, such as initializing the hardware-accelerated renderer, initializing the WindowManager instance, etc. Then it calls the performLaunchActivity method because the code is relatively simple. So skip to the performLaunchActivity method;

2.2.2 performLaunchActivity
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) { ActivityInfo aInfo = r.activityInfo; LoadedApk = LoadedApk = LoadedApk = LoadedApk = LoadedApk; If (r.packageInfo == null) {r.packageInfo == LoadedApk; if (r.packageInfo == null) {r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo, Context.CONTEXT_INCLUDE_CODE); ComponentName Component = r.i.nten.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); } // Get the Classloader object generated in LoadedApk. If did not generate a default to this object / / generated object corresponding to the ContextImpl ContextImpl appContext = createBaseContextForActivity (r); Activity activity = null; Try {/ / this generated by these objects to load corresponding to the Activity and generate Java instance objects. Lang. This 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) { if (! mInstrumentation.onException(activity, e)) { throw new RuntimeException( "Unable to instantiate activity " + component + ": " + e.toString(), e); }} try {// Generate the aplication instance object (if no Application is used, use the default Application) and call the onCreate method. So I know why the Application object will invoke the Application before the Activity app = r.p ackageInfo. MakeApplication (false, mInstrumentation); . if (activity ! = null) { appContext.setOuterContext(activity); Attach (appContext, this, getInstrumentation(), r.toy, R.I.dent, app, R.I.ntent, 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) { activity.setTheme(theme); } activity.mCalled = false; / / call the current Activity onCreate method if (r.i sPersistable ()) {mInstrumentation. CallActivityOnCreate (Activity, r.s Tate, r.persistentState); } else { mInstrumentation.callActivityOnCreate(activity, r.state); } // Custom to the Activity without calling the super method if (! activity.mCalled) { throw new SuperNotCalledException( "Activity " + r.intent.getComponent().toShortString() + " did not  call through to super.onCreate()"); } r.activity = activity; } // Set the life cycle of the current Activity. // Save running in the current process to Activity synchronized (mResourcesManager) {mactivities. put(r.token, r); } } catch (SuperNotCalledException e) { throw e; } catch (Exception e) { if (! mInstrumentation.onException(activity, e)) { throw new RuntimeException( "Unable to start activity " + component + ": " + e.toString(), e); } } return activity; }Copy the code

Next comes the onStart and onResume life cycles of the Activity. Remember the performLifecycleSequence method of the TransactionExecutor class mentioned earlier? This is where you start calling the Activity’s onStart method step by step. So the next step is the method handleStartActivity

2.2.3 handleStartActivity
public void handleStartActivity(ActivityClientRecord r, PendingTransactionActions pendingActions) {/ / the Activity is in the method of the object generated by performLaunchActivit final Activity Activity = r.activity; if (r.activity == null) { return; } // Set the current Activity state to onCreate to true if (! r.stopped) { throw new IllegalStateException("Can't start activity that is not stopped."); If (r.activity. MFinished) {return; if (r.activity. } // In this method, call activity.performStart("handleStartActivity") into the onCreate method of the Activity with Instrumentation. // Set the current Activity state to onStart r.setState(ON_START); if (pendingActions == null) { // No more work to do. return; }... }Copy the code

Take a quick look at the performStart method.

2.2.4 handleStartActivity
final void performStart(String reason) { ..... mCalled = false; / / in the call to the Activity of the onStart method mInstrumentation. CallActivityOnStart (this); if (! mCalled) { throw new SuperNotCalledException( "Activity " + mComponent.toShortString() + " did not call through to super.onStart()"); }... }Copy the code

Here is the basic flow of calling the onResume method.

2.2.5 performResumeActivity
public ActivityClientRecord performResumeActivity(IBinder token, boolean finalStateRequest, String reason) { final ActivityClientRecord r = mActivities.get(token); if (localLOGV) { Slog.v(TAG, "Performing resume of " + r + " finished=" + r.activity.mFinished); } / / whether the Activity that needs to be finish, if you need, don't do anything if (r = = null | | state Richard armitage ctivity. MFinished) {return null; If (r.getlifecycleState () == ON_RESUME) {if (! finalStateRequest) { final RuntimeException e = new IllegalStateException( "Trying to resume activity which is already resumed"); Slog.e(TAG, e.getMessage(), e); Slog.e(TAG, r.getStateString()); } return null; If (finalStateRequest) {r.ideforNow = false; if (finalStateRequest) {r.ideForNow = false; r.activity.mStartedActivity = false; } try { r.activity.onStateNotSaved(); r.activity.mFragments.noteStateNotSaved(); checkAndBlockForNetworkAccess(); If (r.peningIntents!); // If (r.peningIntents! = null) { deliverNewIntents(r, r.pendingIntents); r.pendingIntents = null; } // The onActivityFotResult function exists waiting to be called if (r.pendingResults! = null) { deliverResults(r, r.pendingResults, reason); r.pendingResults = null; } // Call Activity onResume method r.activity. PerformResume (r.tartsnotresumed, reason); r.state = null; r.persistentState = null; // Set the current Activity state to onResume r.setState(ON_RESUME); reportTopResumedActivityChanged(r, r.isTopResumedActivity, "topWhenResuming"); } catch (Exception e) { if (! mInstrumentation.onException(r.activity, e)) { throw new RuntimeException("Unable to resume activity " + r.intent.getComponent().toShortString() + ": " + e.toString(), e); } } return r; }Copy the code

Third, summary

This is the outline of the Activity life cycle from onCreate->onResume in the Android application layer.

Android source code check address:

(1) www.androidos.net.cn/

(2) androidxref.com/