The startup process of Android root Activity

The content of this article is mostly from the book "Android Advanced Decryption". Therefore, I may not provide much help to you. The purpose of writing this article is just to have an impression and provide a convenience for myself when I study again.

Now begin to record the startup process of the root Activity. The process is very complicated. It is about the process of clicking the App icon on the screen after the phone is turned on and entering the desktop, until the first application Activity is displayed after the App is started. It can be divided into three parts, namely the process of Launcher requesting AMS, the process of calling AMS to ApplicationThread and the process of starting Activity by ActivityThread.

1. The process of Launcher requesting AMS

1. Clicking on the application icon will call the startActivitySafely method of Launcher3. There are two points to note in this method

1) intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); This code will make the Activity start in the new task stack

2) The startActivity(intent.optsBundle) method will be called in the startActivitySafely method; this startActivity method will be implemented in the Activity.

2. The source code of the startActivity method in the Activity class is as follows:

@Override
public void startActivity(Intent intent, @Nullable Bundle options) {
    if (options != null) {
    startActivityForResult(intent, -1, options);
    } else {
    // Note we want to go through this call for compatibility with
    // applications that may have overridden the method.
    startActivityForResult(intent, -1);
    }
}

This method calls the startActivityForResult(intent,-1,options); method. The second parameter -1 means that the Launcher does not need to know the start result of the Activity. Let's take a look at the source code of the startActivityForResult method:

public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
            @Nullable Bundle options) {
        if (mParent == null) {
            options = transferSpringboardActivityOptions(options);
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);   
            // 代码省略         
        } 

        // 代码省略

}

The execStartActivity method of Instrumentation is called in the source code. Instrumentation is mainly used to monitor the interaction between the application and the system. The execStartActivity method has a lot of code, but we only need to analyze the most important part. code show as below:

public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
        // 代码省略
        try {
            // .......
            // 主要代码
            int result = ActivityManager.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;
    }

The ActivityManager.getService() method calls IActivityManagerSingleTon.get(), and IActivityManagerSingleTon is a Singleton class. Its onCreate method code is as follows:

@Override
protected IActivityManager create() {

    // 注释1
    final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);

    // 注释2
    final IActivityManager am = IActivityManager.Stub.asInterface(b);
    return am;
}

At Note 1, you get a Service type object named "activity", which is actually an AMS reference of the IBinder type. Note 2 is to convert the IBinder type AMS reference obtained in the previous step into an object of type IActivityManager. This code uses AIDL, and the IActivityManager.java class is automatically generated by the AIDL tool at compile time. Therefore, the execStartActivity method finally calls the startActivity method of AMS.

At this point, the analysis of the process from Launcher to ActivityManagerService is complete. Attach a timing diagram, from which you can see the general process:

Second, the call process from AMS to ApplicationThread

1. In AMS, the code will first call the startActivity method of AMS, which returns the startActivityAsUser method. This method has one more parameter UserHandle.getCallingUserId() than the startActivity method. This method will obtain the userId of the caller, and AMS will follow This UserId determines the permissions of the caller. The source code of the startActivityAsUser method is as follows:

@Override
    public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {
        // 注释1
        enforceNotIsolatedCaller("startActivity");
        // 注释2
        userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
                userId, false, ALLOW_FULL_ONLY, "startActivity", null);
        // TODO: Switch to user app stacks here.
        // 注释3
        return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
                resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
                profilerInfo, null, null, bOptions, false, userId, null, null,
                "startActivityAsUser");
    }

1) At Note 1, it is judged whether the caller process is isolated. If it is isolated, a SecurityException will be thrown.

2) At Note 2, check the caller's permission, if there is no permission, a SecurityException will be thrown.

3) In Note 3, the ActivityStarter.startActivityMayWait method is called. The penultimate parameter type of the startActivityMayWait method is TaskRecord, which represents the stack where the started Activity is located. The last parameter "startActivityAsUser" represents the reason for starting.

2. The startActivityMayWait method of ActivityStarter, which returns the startActivityLocked method. The reason is judged in the startActivityLocked method. If it is empty, an IllegalArgumentException is thrown, and then the startActivity method is called. Let's take a look at what is done in this startActivity method. The source code is as follows:

/** DO NOT call this method directly. Use {@link #startActivityLocked} instead. */
    private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
            String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
            String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
            ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
            ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,
            TaskRecord inTask) {
        
        // 。。。。。。

        ProcessRecord callerApp = null;
        // 注释1
        if (caller != null) {
            callerApp = mService.getRecordForAppLocked(caller);
            if (callerApp != null) {
                callingPid = callerApp.pid;
                callingUid = callerApp.info.uid;
            } else {
                Slog.w(TAG, "Unable to find app for caller " + caller
                        + " (pid=" + callingPid + ") when starting: "
                        + intent.toString());
                err = ActivityManager.START_PERMISSION_DENIED;
            }
        }

        
        // 代码省略。。。
        
        // 注释2 创建ActivityRecord
        ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
                callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
                resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
                mSupervisor, container, options, sourceRecord);
        if (outActivity != null) {
            outActivity[0] = r;
        }

       
        // 代码省略
        
        // 注释3
        return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true,
                options, inTask, outActivity);
    }

There is a lot of code, even if part of it is omitted. In Note 1, caller is passed down from the method call, pointing to the ApplicationThread object of the application process where the Launcher is located, callerApp is an object representing the Launcher process, it is of the ProcessRecord type, and ProcessRecord is used to describe an application process. Similarly, ActivityRecord is used to describe an Activity and to record all the information of an Activity. Next, create an ActivityRecord, and assign its object r to outActivity[0], and finally outActivity is used as a parameter of the startActivity method in Note 3. The startActivityUnChecked method is called in this startActivity method. The code of the startActivityUnChecked method is as follows:

// Note: This method should only be called from {@link startActivity}.
    private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
            ActivityRecord[] outActivity) {
        
        // 代码省略。。。。
       

        // Should this be considered a new task?
        int result = START_SUCCESS;
        // 注释1
        if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
                && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
            newTask = true;
            // 注释2。。。。
            result = setTaskFromReuseOrCreateNewTask(
                    taskToAffiliate, preferredLaunchStackId, topStack);
        } 

        if (mDoResume) {
            final ActivityRecord topTaskActivity =
                    mStartActivity.getTask().topRunningActivityLocked();
            if (!mTargetStack.isFocusable()
                    || (topTaskActivity != null && topTaskActivity.mTaskOverlay
                    && mStartActivity != topTaskActivity)) {
                
                mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
                
                mWindowManager.executeAppTransition();
            } else {
                
                if (mTargetStack.isFocusable() && !mSupervisor.isFocusedStack(mTargetStack)) {
                    mTargetStack.moveToFront("startActivityUnchecked");
                }
                // 注释3。。。
                mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
                        mOptions);
            }
        } else {
            mTargetStack.addRecentActivityLocked(mStartActivity);
        }
        // 。。。。。
    }

The startActivityUnchecked method mainly deals with logic related to stack management. When starting the root Activity, set the Intent's Flag to FLAG_ACTIVITY_NEW_TASK in the launcher's startActivitySafely method. So you can execute the setTaskFromReuseOrCreateNewTask method, which will create a new Activity task stack inside this method, and then the code will execute the resumeFocusedStackTopActivityLocked method of ActivityStackSupervisor. In this method:

final ActivityRecord r = mFocusedStack.topRunningActivityLocked();

It is to get the ActivityRecord that is not in the stopped state on the top of the stack where the Activity to be started is located. Judgment of the Activity condition that is about to be started

if(r == null || r.state != RESUMED)

Is established, so the code will execute:

mFocusedStack.resumeTopActivityUnCheckedLocked(null,null);

The code of the resumeTopActivityUnCheckedLocked method of ActivityStack is as follows:

boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
        
        boolean result = false;
        try {
            // Protect against recursion.
            mStackSupervisor.inResumeTopActivity = true;
            // 注释1。。。
            result = resumeTopActivityInnerLocked(prev, options);
        } finally {
            mStackSupervisor.inResumeTopActivity = false;
        }
        
        return result;
    }

Note 1 calls the resumeTopActivityInnerLocked method, the code is as follows:

private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
        
            // 代码省略。。。。

            if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Restarting " + next);

            // 关键代码

            mStackSupervisor.startSpecificActivityLocked(next, true, true);
        }

        if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
        return true;
    }

In this method, the startSpecificActivityLocked method of ActivityStackSupervisor is called. code show as below:

void startSpecificActivityLocked(ActivityRecord r,
            boolean andResume, boolean checkConfig) {
        // Is this activity's application already running?
        // 获取即将启动的Activity的所在应用程序进程
        ProcessRecord app = mService.getProcessRecordLocked(r.processName,
                r.info.applicationInfo.uid, true);

        r.getStack().setLaunchTime(r);
        // 判断要启动的Activity所在的应用程序进程是否已经运行
        if (app != null && app.thread != null) {
            try {
                
                // 真正的启动Activity,参数二代表要启动的Activity所在的应用程序进程的ProcessRecord
                realStartActivityLocked(r, app, andResume, checkConfig);
                return;
            } catch (RemoteException e) {
                Slog.w(TAG, "Exception when starting activity "
                        + r.intent.getComponent().flattenToShortString(), e);
            }

            
        }

        // 代码省略。。。。
       
    }

The realStartActivityLocked method is called after judging that the application process where the Activity to be started is already running. The method code is as follows:

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,
                    // TODO: Have this take the merged configuration instead of separate global and
                    // override configs.
                    mergedConfiguration.getGlobalConfiguration(),
                    mergedConfiguration.getOverrideConfiguration(), r.compat,
                    r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
                    r.persistentState, results, newIntents, !andResume,
                    mService.isNextTransitionForward(), profilerInfo);

           // 代码省略。。。

        return true;
    }

There are a lot of codes in this method, but the most important thing is to call the app.thread.scheduleLaunchActivity method. Here app.thread refers to IApplicationThread, and its implementation is the internal class ApplicationThread of ActivityThread, where ApplicationThread inherits IApplicationThread.Stub. app refers to the application process where the incoming Activity to be started is located. So this code refers to starting the Activity in the target application process. The current code logic runs in the process (SystemServer) where the AMS is located, and communicates with the application process through the ApplicationThread Binder. Therefore, ApplicationThread is the communication bridge between the AMS process (SystemServer process) and the application process. At this point, the process from AMS to ApplicationThread is also analyzed. The simple sequence diagram of this process is as follows:

Three, the process of ActivityThread starting Activity

The previous process code is executed to the scheduleLaunchActivity method of ApplicationThread, where ApplicationThread is an internal class of ActivityThread. The scheduleLaunchActivity method encapsulates the parameters for starting the Activity into ActivityClientRecord, and finally calls sendMessage(H.LAUNCH_ACTIVITY,r); the method sends a message of type LAUNCH_ACTIVITY to class H and passes ActivityClientRecord over. The processing of LAUNCH_ACTIVITY in the handleMessage method of H is as follows:

public void handleMessage(Message msg) {
    if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
        switch (msg.what) {
            case LAUNCH_ACTIVITY: {
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
                final ActivityClientRecord r = (ActivityClientRecord) msg.obj;

                r.packageInfo = getPackageInfoNoCheck(
                    r.activityInfo.applicationInfo, r.compatInfo);
                // 调用了handleLaunchActivity方法
                handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            } break;
                
    }

In the processing of LAUNCH_ACTIVITY, the most important thing is to call the handleLaunchActivity method. The source code is as follows:

private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
        
        // 注释1

        Activity a = performLaunchActivity(r, customIntent);

        if (a != null) {
            r.createdConfig = new Configuration(mConfiguration);
            reportSizeConfigurations(r);
            Bundle oldState = r.state;
            // 注释2。。。
            handleResumeActivity(r.token, false, r.isForward,
                    !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);

            if (!r.activity.mFinished && r.startsNotResumed) {
                

                // 代码省略。。。。

        } else {
            // If there was an error, for any reason, tell the activity manager to stop us.
            try {
                
                // 注释3。。。
                ActivityManager.getService()
                    .finishActivity(r.token, Activity.RESULT_CANCELED, null,
                            Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
        }
    }

Note 1, call the performLaunchActivity method to start the Activity; Note 2, use to set the status of the Activity to Resume; Note 3, if the Activity is null, it will notify AMS to stop starting the Activity. The code of performLaunchActivity method is as follows:

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        // System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");

        // 注释1:获取ActivityInfo

        ActivityInfo aInfo = r.activityInfo;
        if (r.packageInfo == null) {
            // 注释2:获取APK文件的描述类LoadedApk
            r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
                    Context.CONTEXT_INCLUDE_CODE);
        }

        // ComponentName类中保存了该Activity的包名和类名
        ComponentName component = r.intent.getComponent();
        
        // 代码省略。。。

        // 注释3:创建要启动的Activity的上下文环境

        ContextImpl appContext = createBaseContextForActivity(r);
        Activity activity = null;
        try {
            java.lang.ClassLoader cl = appContext.getClassLoader();
            // 注释4:用类加载器来创建该Activity的实例
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
           
        } catch (Exception e) {
            //。。。
        }

        try {
            // 注释5:创建Application,makeApplication方法内部会调用Application的onCreate方法
            Application app = r.packageInfo.makeApplication(false, mInstrumentation);

            // 。。。。            

            if (activity != null) {

                // 。。。。               
                //注释6:初始化Activity,attach方法中会创建Window对象并与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);

                // 。。。。               

                if (r.isPersistable()) {
                    // 注释7:启动Activity
                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                } else {
                    mInstrumentation.callActivityOnCreate(activity, r.state);
                }
                
                // .....
           

        } catch (SuperNotCalledException e) {
            throw e;

        } catch (Exception e) {
            //....
        }

        return activity;
    }

In note 7 the callActivityOnCreate method of the Instrumentation class is called to start the Activity. code show as below:

/**
  * Perform calling of an activity's {@link Activity#onCreate}
  * method.  The default implementation simply calls through to that method.
  *  @param activity The activity being created.
  * @param icicle The previously frozen state (or null) to pass through to
  * @param persistentState The previously persisted state (or null)
  */
public void callActivityOnCreate(Activity activity, Bundle icicle,
        PersistableBundle persistentState) {
    prePerformCreate(activity);
    // 调用了Activity的performCreate方法
    activity.performCreate(icicle, persistentState);
    postPerformCreate(activity);
}

This method calls the performCreate method of Activity, and the code is as follows:

final void performCreate(Bundle icicle, PersistableBundle persistentState) {
    restoreHasCurrentPermissionRequest(icicle);
    // 调用到了Activity的声明周期方法
    onCreate(icicle, persistentState);
    mActivityTransitionState.readState(icicle);
    performCreateCommon();
}

In the performCreate method of the Activity, the life cycle method of onCreate of the specific Activity is called. At this point, the analysis of the startup process of the root Activity is complete, and the application is started at this time. The sequence diagram of this process is as follows:

Well, this article ends here. I also said at the beginning of the article. The content is basically from the book "Android Advanced Decryption", just for the convenience of learning again. I would like to express my gratitude to the author of this book.

Guess you like

Origin blog.csdn.net/zhourui_1021/article/details/105590528