Android advanced decryption reading notes -- the startup process of four components

Keywords: Java Android Apache

Startup process of root Activity

There are two types of Activity startup: one is the startup process of root Activity, and the other is the startup process of ordinary Activity. Root Activity refers to the first Activity started by the application, so the startup process of root Activity can also be understood as the startup process of the application in general. Normal activities refer to activities other than the first Activity launched by the application. The starting process of the root Activity is divided into three parts: the Launcher requesting AMS process, the calling process from AMS to ApplicationThread, and the ActivityThread starting Activity

Launcher requests AMS process

After the Launcher is started, the shortcut icons of installed applications will be displayed on the desktop. The shortcut icons of these applications are the entry to start the root Activity. The whole sequence flow is as follows:

Launcher.startActivitySafely() -> Activity.startActivity() -> Activity.startActivityForResult() -> Instrumentation.execStartActivity() -> ActivityManager.startActivity() -> IActivityManager.startActivity() -> AMS

  1. Launcher.startActivitySafely()

    ( /packages/apps/Launcher3/src/com/android/launcher3/Launcher.java)

    1. intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK): set FLAG to intent.FLAG_ Activity_ NEW_ Task, so that the root Activity will be started in the new task stack

    2. startActivity(intent, opsBundle): call the startActivity method, which is implemented in the Activity

  2. Activity.startActivity()

    In the statrActivity() method, the startActivityForResult() method will be called, and its second parameter is - 1, which means that the Launcher does not need to know the result of Activity startup

  3. Activity.startActivityForResult()

    1. if(mParent == null){}: mParent is of type Activity and represents the parent class of the current Activity. Since the root Activity has not been created yet, mParent == null holds. Then call the execStartActivity method of Instrumentation, which is mainly used to monitor the interaction between the application and the system

  4. Instrumentation.execStartActivity()

    1. int result = ActivityManager.getService() / / get the proxy object of AMS

      .startActivity(....); // Call the startactivity method (the final call is the startactivity method of AMS)

  5. ActivityManager.getService() 

//The getServices method calls the get method of IActivityManagerSingleton
public static IActivityManager getService(){
  return IActivityManagerSingleton.get();
}

private static final Singleton<IActivityManager> IActivityManagerSingleton = new Singleton<IActivityManager>(){
     @Override
     protected IActivityManager create(){
         //Get the Service reference named "activity", that is, the reference of AMS of IBinder type
         final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
         //Convert it to an object of type IActivityManager (this code uses AIDL)
         final IActivityManager am = IActivityManager.Stub.asInterface(b);
         return am;
     }
}

The IActivityManager.java class is automatically generated by the AIDL tool at compile time (frameworks/base/cpre/java/android/app/IActivityManager.aidl). To realize inter process communication, AMS, that is, the server side, only needs to inherit the IActivityManager.Stub class and implement the corresponding methods

Calling procedure from AMS to ApplicationThread

ActivityManagerService.java

After the Launcher requests AMS, the code logic has entered AMS

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

public final int startActivity(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle bOptions){
    return startActivityAsUser(..., UserHandler.getCallingUserId());
}

//The startActivityAsUser() method has one more parameter UserHandler.getCallingUserId() than the startActivity method. This method will obtain the UserId of the caller, and AMS will determine the permissions of the caller according to this UserId
public final int startActivityAsUser(..., int userId){
    //Judge whether the caller is isolated. If it is isolated, a SecurityException exception will be thrown
    enforceNotIsolatedCaller("startActivity");
    //Check the caller's permission. If there is no permission, a SecurityException exception will be thrown
    userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId, false, ALLOW_FULL_ONLY, "startActivity", null);
    
    return mActivityStarter.startActivityMayWait(...,null, "startActivityAsUser");
}

ActivityStarter

Activity starter is a newly added class in Android 7.0. It is a control class for loading activities. It will collect all logic to decide how to convert Intent and Flags into activities, and associate activities with tasks and stacks

frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java

//inTask: it is a TaskRecord type and represents the stack of the started Activity
//Reason: it is a String type and represents the reason for starting
final int stratActivityMayWait(..., TaskRecord inTask, String reason){
    ...
    int res = startActivityLocked(...);
    ...
    return res;
}

int startActivityLocked(..., String reason){
    //The reason for judging startup is not empty
    if(TextUtils.isEmpty(reason)){
        throw new IllegalArgumentException("Need to specify a reason.");
    }
    
    ...
    mLastStartActivityResult = startActivity(...);
}

private int startActivity(IApplicationThread caller, ...){
    //The caller points to the ApplicationThread object of the application where the Launcher is located
    if(caller != null){
        //Get the Launcher process: call the getRecordForAppLocked method of AMS to get a callerApp object representing the Launcher process
        callerApp = mService.getRecordForAppLocked(caller);
    }
    
    //Create a description class ActivityRecord for the Activity to be started
    //ActivityRecord is used to describe an Activity and record all the information of an Activity
    ActivityRecord r = new ActivtiyRecord(...);
    if(outAcitivity != null){
        //Assign the created ActivityRecord to the outActivity of ActivityRecord [] type, and this outActivity will be passed as a parameter
        outActivity[0] = r;
    }
    ...
    return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true, options, inTask, outActivity);
}

private int startActivity(...){
    try{
        mService.mWindowManager.deferSurfaceLayout();
        result = startActivityUnchecked(...);
    }
    ...
    return result;
}

//It mainly deals with the logic related to stack management
private int startActivityUnchecked(...){
    ...
    //The mLauncher we set earlier is FLAG_ACTIVITY_NEW_TASK
    if(mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
          && (mLauncherFlags & FLAG_ACTIVITY_NEW_TASK) != 0){
        nweTask = true;
        //Create a new TaskRecord to describe an Activity task stack, that is, a new Activity task stack will be created inside the settaskfromreusorcreatewtask method
        result = setTaskFromReuseOrCreateNewTask(taskToAffiliate, preferredLaunchStackId, topStack);
    }
    ...
    //Call the resumeFocusedStackTopActivityLocked method of ActivityStackSupervisor
    mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity, mOptions);
}

ActivityStackSupervisor.java

frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java

boolean resumeFocusedStackTopActivityLocked(ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions){
    ...
    //Get the top of the stack where the Activity to be started is not the ActivityRecord in the stopped state
    final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
    
    //The ActivityRecord is not null, or the state of the Activity to be started is not the RESUMED state
    if(r == null || r.state != RESUMED){
        //Method calling ActivityStack
        mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
    }
}

ActivityStack.java
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options){
    ...
    result = resumeTopActivityInnerLocked(prev, options);
    ...
    return result;
}

//This method has a lot of code. We only need to pay attention to calling the startSpecificActivityLocked method of ActivityStackSupervisor
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options){
    ...
    mStackSupervisor.startSpecificActivityLocked(next, true, true);
}

ActivityStackSupervisor.java
void startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig){
    //Gets the application process of the Activity to be started
    ProcessRecord app = mService.getProcessRecordLocked(r.processName, r.info.applicationInfo.uid, true);
    
    //Determine whether the application process where the Activity to be started is already running
    if(app != null && app.thread != null){
        ...
        //The second parameter represents the ProcessRecord of the application process where the Activity to be started is located
        realStartActivityLocked(r, app, andResume, checkConfig);
    }
}

final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app, boolean andResume, boolean checkConfig) throws RemoteException{
    ...
    app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken, System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration), new Configuration(task.mOverrideConfig), r.compat, r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results, newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);
}

app.thread refers to iaapplicationthread. Its implementation is the internal class ApplicationThread of ActivityThread, where ApplicationThread inherits iaapplicationthread.stub. app refers to the application process of the incoming Activity to be started. Therefore, the code in realStartActivityLocked is to start the Activity in the target application process. The current code logic runs in the process where AMS is located (SystemServer process), and binders communicate with the application process through ApplicationThread. In other words, ApplicationThread is the communication bridge between the process where AMS is located (SystemServer process) and the application process

ActivityThread starts the process of activity

Start process

ActivityThread.java

scheduleLaunchActivity() -> sendMessage()

H.java

handleMessage() -> handleLaunchActivity()

ActivityThread.java

performLaunchActivity -> callActivityOnCreate()

Instrumentation.java

performCreate()

Activity.java

onCreate()

In the whole process, we mainly focus on the method performLauncherActivity(). For the specific implementation, you can read the source code

Posted by digitalflash on Wed, 27 Oct 2021 16:06:02 -0700