美文网首页
Android中根Activity的启动过程

Android中根Activity的启动过程

作者: MadnessXiong | 来源:发表于2020-04-02 00:24 被阅读0次

    Activity的启动过程分为2种,一种是根Activity的启动过程,另一种是普通Activity的启动过程。根Activity指的是应用程序启动的第一个Activity。因此根Activity的启动过程一般情况下,也可以理解为应用程序的启动过程。普通Activity指的是除应用程序启动的第一个Activity之外的其他Activity。

    1. 根Activity的启动过程

    根Activity的启动过程分为3个部分:

    1. Launcher请求AMS过程
    2. AMS到ApplicationThread的调用过程
    3. ActivityThread启动Activity过程
    • Launcher请求AMS过程:

      Launcher启动后,会将已安装应用程序的快捷图标显示到桌面上,这些应用程序的快捷图标就是启动根Activity的入口,当点击某个应用程序的快捷图标时,就会通过Launcher请求AMS来启动该应用程序,调用的第一个方法为Launcher的startActivitySafely(),看代码:

             public boolean startActivitySafely(View v, Intent intent, ItemInfo item) {
                 if (mIsSafeModeEnabled && !Utilities.isSystemApp(this, intent)) {
                  //设置FLAG
                 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                  //调用Activity的startActivity()
                 startActivity(intent, optsBundle);
                 return false;
             }
      

      可以看到,先是设置了FLAG,因为这是第一个启动的Activity,所以要给它一个新的任务栈。

      然后调用了Activity的startActivity(),继续看代码:

             @Override
             public void startActivity(Intent intent, @Nullable Bundle options) {
                //参数-1代表Launcher不需要知道启动结果
                 if (options != null) {
                     startActivityForResult(intent, -1, options);
                 } else {
                     startActivityForResult(intent, -1);
                 }
             }
      

      这里调用了startActivityForResult():

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

      由于这是第一个Activity,所以父类mParent肯定是null,所以这里调用了Instrumentation.execStartActivity():

             public ActivityResult execStartActivity(
                 Context who, IBinder contextThread, IBinder token, String target,
                 Intent intent, int requestCode, Bundle options) {
                                 //获取AMS代理对象
                     int result = ActivityManager.getService()
                         .startActivity(whoThread, who.getBasePackageName(), intent,
                                 intent.resolveTypeIfNeeded(who.getContentResolver()),
                                 token, target, requestCode, 0, null, options);
                     checkStartActivityResult(result, intent);
      
                 return null;
             }
      

      首先获取了AMS的代理对象,然后调用了它的startActivity()。这里采用了AIDL的方式进行进程间通讯,关于AIDL参考:Binder深入理解及与AIDL的使用和理解

      总结:可以看到,第一步主要是通知AMS,代码从这里就进入了AMS里。

    • AMS到ApplicationThread的调用过程:

      接上面,来到AMS的startActivity():

             @Override
             public final int startActivity(IApplicationThread caller, String callingPackage,
                     Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
                     int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
                    //调用startActivityAsUser,这里多传了一个getCallingUserId()
                 return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
                         resultWho, requestCode, startFlags, profilerInfo, bOptions,
                         UserHandle.getCallingUserId());
             }
      

      再看startActivityAsUser():

             @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) {
                         //判断调用者进程是否被隔离
                 enforceNotIsolatedCaller("startActivity");
                         //根据传入的UserID来确定调用者权限
                 userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
                         userId, false, ALLOW_FULL_ONLY, "startActivity", null);
                 return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
                         resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
                         profilerInfo, null, null, bOptions, false, userId, null, null,
                         "startActivityAsUser");
             }
      

      这里确定了调用者权限,然后调用了ActivityStarter.startActivityMayWait(),其中倒数第二个参数为TaskRecord,最后一个参数代表启动的理由,继续看代码:

             final int startActivityMayWait() {
                     int res = startActivityLocked();
                     return res;
                 }
             }
      

      ActivityStarter主要是对Intent和Flags进行处理,然后又调用了startActivityLocked():

             int startActivityLocked() { 
                 if (TextUtils.isEmpty(reason)) {
                     throw new IllegalArgumentException("Need to specify a reason.");
                 }
         
                 mLastStartActivityResult = startActivity();
                 return mLastStartActivityResult;
             }
      

      这里先判断了启动理由,如果不为空,则继续调用ActivityStarter的startActivity():

             private int startActivity() {
                        //ProcessRecord用于描述一个应用程序进程
                 ProcessRecord callerApp = null;
                            //判断caller是否为null,这个caller实际是ApplicationThread对象,是从startActivityForResult()里传递过来的
                 if (caller != null) {
                    //调用AMS的getRecordForAppLocked(),获取Launcher进程
                     callerApp = mService.getRecordForAppLocked(caller);
                     if (callerApp != null) {
                       //获取Launcher的pid和uid
                         callingPid = callerApp.pid;
                         callingUid = callerApp.info.uid;
                     } 
                 }
                        //创建即将要启动的activity的描述类ActivityRecord,ActivityRecord记录了一个activity的所有信息
                 ActivityRecord r = new ActivityRecord());
                 if (outActivity != null) {
                     outActivity[0] = r;
                 }
                 return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags,true,
                         options, inTask, outActivity);
             }
      

      可以看到,这里通过AMS获取了Launcher进程,同时创建了ActivityRecord,然后将ActivityRecord赋值给了outActivity,然后将outActivity作为参数,继续调用startActivity():

             private int startActivity() {
                     result = startActivityUnchecked()
                 return result;
             }
      

      这里又调用了startActivityUnchecked():

             private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
                     IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
                     int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
                     ActivityRecord[] outActivity) {
                                //创建新的TaskRecord
                     result = setTaskFromReuseOrCreateNewTask(
                             taskToAffiliate, preferredLaunchStackId, topStack);
                                    
                         mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
                                 mOptions);
                 return START_SUCCESS;
             }
      

      前面说过,这时第一个Activity,所以要创建一个新的栈,所以这里创建了新的TaskRecord,然后进入了ActivityStackSupervisor.resumeFocusedStackTopActivityLocked():

             boolean resumeFocusedStackTopActivityLocked(
                     ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
                                //获取要启动的Activity所在的栈的栈顶不是处于停止状态的ActivityRecord
                 final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
                 if (r == null || r.state != RESUMED) {
                     mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
                 } 
                 return false;
             }
      

      这里会调用ctivityStack.resumeTopActivityUncheckedLocked():

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

      调用了resumeTopActivityInnerLocked():

             private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
                     mStackSupervisor.startSpecificActivityLocked(next, true, false);
               return true;
             }
      

      这里调用了ActivityStackSupervisor.startSpecificActivityLocked():

             void startSpecificActivityLocked(ActivityRecord r,
                     boolean andResume, boolean checkConfig) {
                            //获取即将启动的Activity的所在的应用程序进程
                 ProcessRecord app = mService.getProcessRecordLocked(r.processName,
                         r.info.applicationInfo.uid, true);
                          //判断应用程序进程是否已经运行
                 if (app != null && app.thread != null) {
                  //应用程序进程已经运行      
                  realStartActivityLocked(r, app, andResume, checkConfig);
      
                 }
             }
      

      这里可以看到,先去获取了应用程序进程ProcessRecord,如果不为null,则代表应用程序进程已经启动,这里是分析Activity的启动过程,默认应用程序进程已经启动,所以会来到realStartActivityLocked():

             final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
                     boolean andResume, boolean checkConfig) throws RemoteException {
                                //调用ApplicationThread的scheduleLaunchActivity启动Activity
                     app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                             System.identityHashCode(r), r.info,
                             mergedConfiguration.getGlobalConfiguration(),
                             mergedConfiguration.getOverrideConfiguration(), r.compat,
                             r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
                             r.persistentState, results, newIntents, !andResume,
                             mService.isNextTransitionForward(), profilerInfo);
         
                 return true;
             }
      

      这里的app是要启动的activity所在应用程序的进程,app.thread其实是ApplicationThread,它是ActivityThread的内部类,它继承了IApplication.Stub。那么这个ApplicationThread就具备了进程间通讯的能力。参考Binder深入理解及与AIDL的使用和理解,可知这个app.thread其实就是ApplicationThread的代理对象,负责AMS进程(SystemServer进程)与应用程序进程间的通讯。

      总结:可以看到,第二步主要是对要启动的Activity的进程一些权限检查,创建ActivityRecord,它里面记录了Activity所有信息以及创建堆栈信息等操作,最后判断应用程序进程是否已经运行,如果没运行则去创建应用程序进程,如果已运行则通过Binder代理对象,通知ApplicationThread,执行它的scheduleLaunchActivity()

    • ActivityThread启动Activity过程:

      接上面,代码来到了ApplicationThread.scheduleLaunchActivity():

                 public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
                         ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
                         CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
                         int procState, Bundle state, PersistableBundle persistentState,
                         List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
                         boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {
                                //创建一个ActivityClientRecord,用于封装启动Activity的参数
                     ActivityClientRecord r = new ActivityClientRecord();
         
                     r.token = token;
                     r.ident = ident;
                     r.intent = intent;
                     r.referrer = referrer;
                     r.voiceInteractor = voiceInteractor;
                     r.activityInfo = info;
                     r.compatInfo = compatInfo;
                     r.state = state;
                     r.persistentState = persistentState;
                     r.pendingResults = pendingResults;
                     r.pendingIntents = pendingNewIntents;  
                     r.startsNotResumed = notResumed;
                     r.isForward = isForward; 
                     r.profilerInfo = profilerInfo;  
                     r.overrideConfig = overrideConfig;
                     updatePendingConfiguration(curConfig);  
                    //发送消息
                     sendMessage(H.LAUNCH_ACTIVITY, r);
                 }
      

      这里将Activity启动的参数封装成了一个ActivityClientRecord,然后通过sendMessage(),发送了出去,再看代码:

             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);
             }
      

      这里调用mH.sendMessage(msg)发送消息,这个H是ActivityThread的内部类并继承自Handler,是应用程序进程中主线程的消息管理类,因为ApplicationThread是一个Binder,它的调用逻辑运行在Binder线程池中,所以这里需要用Handler将代码逻辑切换到主线程中。

      Android应用程序进程启动过程中,最后建立了一个消息循环。就是这个Handler。

      Handler处理消息会来到它的HandleMessage(),看代码:

                 public void handleMessage(Message msg) {
                     if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
                     switch (msg.what) {
                         case LAUNCH_ACTIVITY: {
                             final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
                                                //获取LoadedAPK类型对象,并存入r.packageInfo中。
                             r.packageInfo = getPackageInfoNoCheck(
                                     r.activityInfo.applicationInfo, r.compatInfo);
                             handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
                         } break;
                 }
      

      这里先获得了LoadedAPK,然后存入ActivityClientRecord.packageInfo中。

      应用程序进程要启动Activity时需要将该Activity所属的APK加载进来,LoadedAPK就是描述已加载的APK文件的。

      最后调用handleLaunchActivity(),看代码:

             private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
                            //启动Activity
                 Activity a = performLaunchActivity(r, customIntent);
                  //将Activity的状态设置为resume
                         handleResumeActivity(r.token, false, r.isForward,
                             !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
      
             }
      

      可以看到,这里调用了performLaunchActivity()启动Activity,再看代码:

             private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
                    //这获取ActivityInfo,用于存储代码以及AndroidManifest设置的activity和receiver节点信息,如activity的theme和launchMode。
                 ActivityInfo aInfo = r.activityInfo;
                    //获取描述文件LoadAPK
                 if (r.packageInfo == null) {
                     r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
                             Context.CONTEXT_INCLUDE_CODE);
                 }
                 //获取要启动的Activity的ComponentName,它保存了该Activity的包名和类名
                 ComponentName component = r.intent.getComponent();
                         //创建要启动activity的上下文环境
                 ContextImpl appContext = createBaseContextForActivity(r);
                 Activity activity = null;
                                
                     java.lang.ClassLoader cl = appContext.getClassLoader();
                        //在newActivity()中用类加载器创建activity的实例,
                     activity = mInstrumentation.newActivity(
                             cl, component.getClassName(), r.intent);
                                //创建Application
                     Application app = r.packageInfo.makeApplication(false, mInstrumentation);
                                //初始化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);
                             //调用onCreate()
                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
      
                 return activity;
             }
      

      可以看到,这里首先获取了各种信息,然后在Instrumentation.newActivity()里通过classLoader创建了Activity实例,然后又创建了Application,然后调用activity.attach(),初始化activity,最后调用Instrumentation.callActivityOnCreate()去调用Activity的onCreate,这里先看attach():

             final void attach() {、
                 //初始化PhoneWindow
                 mWindow = new PhoneWindow(this, window, activityConfigCallback);
                 //将PhoneWindow和当前activity关联
                 mWindow.setCallback(this);
                         //初始化UI线程
                 mUiThread = Thread.currentThread();
                 //初始化主线程
                 mMainThread = aThread;
                        //设置WindowManager
                 mWindow.setWindowManager(
                         (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
                         mToken, mComponent.flattenToString(),
                         (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
      
             }
      

      可以看到在attach()里初始化了PhoneWindow,并和activity关联了起来,然后初始化了Ui线程和主线程,这2个线程在这里基本是一回事,除非执行attach()时当前线程不是主线程。最后设置了WindowManager。

      然后再来看Instrumentation.callActivityOnCreate():

             public void callActivityOnCreate(Activity activity, Bundle icicle) {
                 activity.performCreate(icicle);
             }
      

      可以看到,这里调用了Activity的performCreate(),继续看代码:

             final void performCreate(Bundle icicle) {
                 onCreate(icicle);
             }
      

      可以看到,最终调用了Activity的Create()。到这里,根Activity就被启动了。

    2. 根Activity启动过程中涉及到的进程

    Launcher进程首先向AMS请求创建根Activity,AMS会判断根Activity所需要的应用程序进程是否存在并启动,如果不存在就会请求Zygote进程创建应用程序进程(这一步是通过Socket通信)。如果存在或者应用程序进程启动后,AMS会请求创建根Activity。

    根Activity启动过程中涉及以下几个进程:Launcher进程,AMS所在的SystemServer进程,Zygote进程,应用程序进程

    普通Activity启动过程中设计2个进程:AMS所在的SystemServer进程,应用程序进程。

    相关文章

      网友评论

          本文标题:Android中根Activity的启动过程

          本文链接:https://www.haomeiwen.com/subject/ugftphtx.html