Activity启动过程详解(转发)

自己新浪博客转移

前面发了blog分析了ActivityManager框架的大体结构,主要就是一个进程通信机制,今天我通过深入Activity的启动过程再次深入到ActivityManager框架,对其进行一个更深入的了解

    以桌面启动一个应用Activity为例,onClick事件后,会调用startActivityForResult(Intent, int)

        public void startActivityForResult(Intent intent, int requestCode) {
       if (mParent == null) {
                       //Activity启动执行交由Instrumentation对象去处理
           Instrumentation.ActivityResult ar =
               mInstrumentation.execStartActivity(
                   this, mMainThread.getApplicationThread(), mToken, this,
                   intent, requestCode);
              //mMainThread 在attach方法中被设置,当ActivityThread PerformLauchActivity,调用attach把ActivityThread.this传送过来
              //mMainThread.getApplicationThread()它是一个进程通信服务端存根对象,提供了很多操作ActivityThread的方法,它继承了ApplicationThreadNative              
           if (ar != null) {
               mMainThread.sendActivityResult(
                   mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                   ar.getResultData());
           }
           if (requestCode >= 0) {
               // If this start is requesting a result, we can avoid making
               // the activity visible until the result is received.  Setting
               // this code during onCreate(Bundle savedInstanceState) or onResume() will keep the
               // activity hidden during this time, to avoid flickering.
               // This can only be done when a result is requested because
               // that guarantees we will get information back when the
               // activity is finished, no matter what happens to it.
               mStartedActivity = true;
           }
       } else {
           mParent.startActivityFromChild(this, intent, requestCode);
       }
    }
Instrumentation.execStartActivity
    public ActivityResult execStartActivity(
       Context who, IBinder contextThread, IBinder token, Activity target,
       Intent intent, int requestCode) {
                               ......
       try {
       //ActivityManagerNative.getDefault()实际返回的是一个ActivityManagerProxy对象
           int result = ActivityManagerNative.getDefault()
               .startActivity(whoThread, intent,
                       intent.resolveTypeIfNeeded(who.getContentResolver()),
                       null, 0, token, target != null ? target.mEmbeddedID : null,
                       requestCode, false, false);
           checkStartActivityResult(result, intent);
       } catch (RemoteException e) {
       }
       return null;
    }

    ActivityManagerProxy是实现IActivityManager接口的一个进程通信代理对象,在该方法ActivityManagerProxy.startActivity中,它只负责
准备相关的数据发送到system_process进程去处理startActivity:

   public int startActivity(IApplicationThread caller, Intent intent,
           String resolvedType, Uri[] grantedUriPermissions, int grantedMode,
           IBinder resultTo, String resultWho,
           int requestCode, boolean onlyIfNeeded,
           boolean debug) throws RemoteException {
       Parcel data = Parcel.obtain();
       Parcel reply = Parcel.obtain();
       data.writeInterfaceToken(IActivityManager.descriptor);
       data.writeStrongBinder(caller != null ? caller.asBinder() : null);
       intent.writeToParcel(data, 0);
       data.writeString(resolvedType);
       data.writeTypedArray(grantedUriPermissions, 0);
       data.writeInt(grantedMode);
       data.writeStrongBinder(resultTo);
       data.writeString(resultWho);
       data.writeInt(requestCode);
       data.writeInt(onlyIfNeeded ? 1 : 0);
       data.writeInt(debug ? 1 : 0);
       //mRemote是一个BinderProxy对象,transact方法本地化实现
       mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
       reply.readException();
       int result = reply.readInt();
       reply.recycle();
       data.recycle();
       return result;
    }

    到此前面3步都是在Laucher2进程中执行,调用mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);后,系统转到
system_process进程中执行,根据我前面讲的进程通信机制,入口函数是ActivityManagerNative.onTransact方法,在system_process进程中
ActivityManagerNative被继承,实际执行的是ActivityManagerService.onTransact方法,调用堆栈如下:

ActivityManagerService(ActivityManagerNative).onTransact(int, Parcel, Parcel, int) line: 129       
ActivityManagerService.onTransact(int, Parcel, Parcel, int) line: 1481       
ActivityManagerService(Binder).execTransact(int, int, int, int) line: 288       
NativeStart.run() line: not available [native method]

    在ActivityManagerService(ActivityManagerNative).onTransact中根据前面的参数START_ACTIVITY_TRANSACTION,执行对应的case代码:

       case START_ACTIVITY_TRANSACTION:
       {
           data.enforceInterface(IActivityManager.descriptor);
           IBinder b = data.readStrongBinder();
           IApplicationThread app = ApplicationThreadNative.asInterface(b);
           Intent intent = Intent.CREATOR.createFromParcel(data);
           String resolvedType = data.readString();
           Uri[] grantedUriPermissions = data.createTypedArray(Uri.CREATOR);
           int grantedMode = data.readInt();
           IBinder resultTo = data.readStrongBinder();
           String resultWho = data.readString();   
           int requestCode = data.readInt();
           boolean onlyIfNeeded = data.readInt() != 0;
           boolean debug = data.readInt() != 0;
           //执行对应Stub的IActivityManager接口方法
           int result = startActivity(app, intent, resolvedType,
                   grantedUriPermissions, grantedMode, resultTo, resultWho,
                   requestCode, onlyIfNeeded, debug);
           reply.writeNoException();
           reply.writeInt(result);
           return true;
       }

前面红色的startActivity方法实际是执行的ActivityManagerService中的startActivity,接下来的执行很复杂,要想搞清楚这些细节还需要一些时间,我我们跳过这些,继续沿着主干道前行:

ActivityManagerService.startProcessLocked(ProcessRecord, String, String) line: 2043       
ActivityManagerService.startProcessLocked(String, ApplicationInfo, boolean, int, String, ComponentName, boolean) line: 1982       
ActivityManagerService.startSpecificActivityLocked(HistoryRecord, boolean, boolean) line: 1908       
ActivityManagerService.resumeTopActivityLocked(HistoryRecord) line: 2855       
ActivityManagerService.completePauseLocked() line: 2237       
ActivityManagerService.activityPaused(IBinder, Bundle, boolean) line: 5963       
ActivityManagerService.activityPaused(IBinder, Bundle) line: 5941       
ActivityManagerService(ActivityManagerNative).onTransact(int, Parcel, Parcel, int) line: 387       
ActivityManagerService.onTransact(int, Parcel, Parcel, int) line: 1481       
ActivityManagerService(Binder).execTransact(int, int, int, int) line: 288       
SystemServer.init1(String[]) line: not available [native method]       
SystemServer.main(String[]) line: 582       
Method.invokeNative(Object, Object[], Class, Class[], Class, int, boolean) line: not available [native method]       
Method.invoke(Object, Object...) line: 521       
ZygoteInit$MethodAndArgsCaller.run() line: 868       
ZygoteInit.main(String[]) line: 626       
NativeStart.main(String[]) line: not available [native method]

在用例进程onPause后,通过ActivityManagerProxy.activityPaused执行相关操作,这也是一个用例进程到system_process进程的远程调用,原来的用例进程需要进栈,并启动一个新的Activity在屏幕最前端,我们只关注新Activity的启动,首先关注新Activity应用进程的创建,看上面的调用堆栈,在函数startProcessLocked:

//app记录的是一个要启动ActivityThread进程的信息,hostingType=activity,hostingNameStr="com.iaiai.activity/.IaiaiActivity"
    private final void startProcessLocked(ProcessRecord app,
           String hostingType, String hostingNameStr) {
           ......
           //Process.start是一个静态方法,它将启动一个新的进程,新进程的的入口main方法为android.app.ActivityThread.main
           int pid = Process.start("android.app.ActivityThread",
                   mSimpleProcessManagement ? app.processName : null, uid, uid,
                   gids, debugFlags, null);  
           ......


 

     现在,我们终于看到了一个新的应用进程的创建,别急,在启动主Activity我们还有很多工作要做,我我们可以想象到得,一个新的应用肯定要建立闭环的消息循环,然后它要把的一个ApplicationThreadProxy代理对象传递给system_process进程,这样system_process进程就可以通过ApplicationThreadProxy代理对象来控制我们的应用进程了,比如它把广播消息转给应用进程,关闭应用进程等

    先看新进程的main函数:

   public static final void main(String[] args) {
    SamplingProfilerIntegration.start();

       Process.setArgV0("<pre-initialized>");
       //建立looper消息循环队列
       Looper.prepareMainLooper();

       ActivityThread thread = new ActivityThread();
       thread.attach(false);
       //开始主线程消息循环
       Looper.loop();

       if (Process.supportsProcesses()) {
           throw new RuntimeException("Main thread loop unexpectedly exited");
       }

       thread.detach();
       String name = (thread.mInitialApplication != null)
           ? thread.mInitialApplication.getPackageName()
           : "<unknown>";
       Slog.i(TAG, "Main thread of " + name + " is now exiting");
    }

      在main函数中建立了闭环的消息循环,这个是一般ui程序做法,很容易理解,但是后续应用的启动工作是如何进程的,关注我上面标注的红色代码,这里创建了一个ActivityThread对象,ActivityThread构造时初始化了该应用进程的一些基本成员,最重要的我们关注

   final Looper mLooper = Looper.myLooper();
    final H mH = new H();//消息处理handler
在这里,我们建立了消息处理器,它将负责处理main线程中Looper消息循环中的消息。

    还用一个成员对象值得我们关注,那就是ApplicationThread对象,在ActivityThread对象被创建时,它也被构造了,我前面已经提到过了,它继承了ApplicationThreadNative类,熟悉进程通信代理机制的朋友就清楚了,ApplicationThread就是一个通信代理存根实现类,我们可以看它的实现方法,都是调用queueOrSendMessage方法,派发消息交给ActivityThread的mH去处理,那么我们很清楚了,ActivityThread代理存根对象,它负责执行来自远程的调用,这些远程的调用大部分来自system_process,所以,system_process很容易通过ApplicationThread的客户端代理对象控制ActivityThread,事实就是如此,后面我们可以很好地看到这一点,

    继续看thread.attach(false)函数,参数标识是否系统进程,系统进程的入口函数是systemMain,而不是main方法,

  private final void attach(boolean system) {//system==false
       sThreadLocal.set(this);//ActivityThread对象关联到主线程
       mSystemThread = system;
       if (!system) {//是非系统进程
           ...
           IActivityManager mgr = ActivityManagerNative.getDefault();
           try {
             //把ApplicationThread mAppThread attach到系统进程system_process,以便system_process控制当前应用的ActivityThread
               mgr.attachApplication(mAppThread);
           } catch (RemoteException ex) {
           }
       } else {
           //系统进程要作的处理
           ...
       }
       //接收来自ViewRoot的ConfigurationChanged消息,派发给mH处理(H.CONFIGURATION_CHANGED),
       //一旦配置发生变更,mH将执行H.CONFIGURATION_CHANGED
       ViewRoot.addConfigCallback(new ComponentCallbacks() {
           public void onConfigurationChanged(Configuration newConfig) {
               synchronized (mPackages) {
                   // We need to apply this change to the resources
                   // immediately, because upon returning the view
                   // hierarchy will be informed about it.
                   if (applyConfigurationToResourcesLocked(newConfig)) {
                       // This actually changed the resources! Tell
                       // everyone about it.
                       if (mPendingConfiguration == null ||
                               mPendingConfiguration.isOtherSeqNewer(newConfig)) {
                           mPendingConfiguration = newConfig;
                           
                           queueOrSendMessage(H.CONFIGURATION_CHANGED, newConfig);
                       }
                   }
               }
           }
           public void onLowMemory() {
           }
       });
    }
    再来看一下attach方法的调用堆栈:

ActivityManagerProxy.attachApplication(IApplicationThread) line: 1542       
ActivityThread.attach(boolean) line: 4555       
ActivityThread.main(String[]) line: 4632       
Method.invokeNative(Object, Object[], Class, Class[], Class, int, boolean) line: not available [native method]       
Method.invoke(Object, Object...) line: 521       
ZygoteInit$MethodAndArgsCaller.run() line: 868       
ZygoteInit.main(String[]) line: 626       
NativeStart.main(String[]) line: not available [native method]

这里你又会看到一个熟悉的身影,ActivityManagerProxy,是的,这里又使用了进程通信,通知ActivityManagerService执行attachApplication
看一下ActivityManagerProxy.attachApplication方法的代码:

   public void attachApplication(IApplicationThread app) throws RemoteException
    {
       Parcel data = Parcel.obtain();
       Parcel reply = Parcel.obtain();
       data.writeInterfaceToken(IActivityManager.descriptor);
       //参数IApplicationThread app通过进程通信传送到system_process进程,而app是一个ApplicationThread对象,不要被它的名称所迷惑
       //这里它只是一个对象,它继承了ApplicationThreadNative,而ApplicationThreadNative是实现IApplicationThread接口的一个进程通信接口存根类,当它到达system_process,system_process得到的是它的一个代理类ActivityManagerProxy
       data.writeStrongBinder(app.asBinder());
       mRemote.transact(ATTACH_APPLICATION_TRANSACTION, data, reply, 0);
       reply.readException();
       data.recycle();
       reply.recycle();
    }
     再次回到了system_process进程,先看一下system接收到来自新的Activity的远程调用堆栈:

ActivityManagerService.attachApplicationLocked(IApplicationThread, int) line: 5591       
ActivityManagerService.attachApplication(IApplicationThread) line: 5677       
ActivityManagerService(ActivityManagerNative).onTransact(int, Parcel, Parcel, int) line: 363       
ActivityManagerService.onTransact(int, Parcel, Parcel, int) line: 1481       
ActivityManagerService(Binder).execTransact(int, int, int, int) line: 288       
NativeStart.run() line: not available [native method]    

我们看attachApplicationLocked的实现,由于函数比较长,而且我也没有深入仔细看,所以我只列出我理解的关键部分代码

   //thread来用户进程的ApplicationThread代理对象,pid是用户进程的pid
    private final boolean attachApplicationLocked(IApplicationThread thread,
           int pid) {
    ......
    ProcessRecord app;
       if (pid != MY_PID && pid >= 0) {
           synchronized (mPidsSelfLocked) {
           //当用户进程创建时有一个标识用户进程的pid,它关联了ProcessRecord记录,现在根据pid或者该记录
               app = mPidsSelfLocked.get(pid);
           }
       } else if (mStartingProcesses.size() > 0) {
           app = mStartingProcesses.remove(0);
           app.setPid(pid);
       } else {
           app = null;
       }
       ......
       //设置app相关参数
       app.thread = thread;//设置app的thread为用户进程代理对象ActivityManagerProxy
       app.curAdj = app.setAdj = -100;
       app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
       app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
       app.forcingToForeground = null;
       app.foregroundServices = false;
       app.debugging = false;

    ......
           thread.bindApplication(processName, app.instrumentationInfo != null
                   ? app.instrumentationInfo : app.info, providers,
                   app.instrumentationClass, app.instrumentationProfileFile,
                   app.instrumentationArguments, app.instrumentationWatcher, testMode,
                   isRestrictedBackupMode || !normalMode,
                   mConfiguration, getCommonServicesLocked());
           updateLruProcessLocked(app, false, true);
           app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
      ......
              HistoryRecord hr = topRunningActivityLocked(null);
       if (hr != null && normalMode) {
           if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
                   && processName.equals(hr.processName)) {
               try {
                   //realStartActivityLocked会调用thread.scheduleLaunchActivity
                   if (realStartActivityLocked(hr, app, true, true)) {
                       didSomething = true;
                   }
}

这里通过远程调用后thread并不是一个ApplicationThread对象,而是其一个远程代理对象ApplicationThreadProxy,通过thread,可以操作ApplicationThread对象调用bindApplication和scheduleLaunchActivity:

先看bindApplication:

ActivityThread$ApplicationThread.bindApplication(String, ApplicationInfo, List, ComponentName, String, Bundle, IInstrumentationWatcher, int, boolean, Configuration, Map) line: 1655       
ActivityThread$ApplicationThread(ApplicationThreadNative).onTransact(int, Parcel, Parcel, int) line: 251       
ActivityThread$ApplicationThread(Binder).execTransact(int, int, int, int) line: 288       
NativeStart.run() line: not available [native method]

       public final void bindApplication(String processName,
               ApplicationInfo appInfo, List<ProviderInfo> providers,
               ComponentName instrumentationName, String profileFile,
               Bundle instrumentationArgs, IInstrumentationWatcher instrumentationWatcher,
               int debugMode, boolean isRestrictedBackupMode, Configuration config,
               Map<String, IBinder> services) {
           //获取来自system_process远程调用传递过来的相关参数
           if (services != null) {
               // Setup the service cache in the ServiceManager
               ServiceManager.initServiceCache(services);
           }

           AppBindData data = new AppBindData();
           data.processName = processName;
           data.appInfo = appInfo;
           data.providers = providers;
           data.instrumentationName = instrumentationName;
           data.profileFile = profileFile;
           data.instrumentationArgs = instrumentationArgs;
           data.instrumentationWatcher = instrumentationWatcher;
           data.debugMode = debugMode;
           data.restrictedBackupMode = isRestrictedBackupMode;
           data.config = config;
           //派发给ActivityThread.mH去处理执行H.BIND_APPLICATION
           queueOrSendMessage(H.BIND_APPLICATION, data);
       }

我们看mH是如何处理的,mH接收到H.BIND_APPLICATION消息执行的对应是handleBindApplication函数,handleBindApplication函数中做了大量初始化ActivityThread的操作:

 初始化mConfiguration

 设置进程名

 本地语言设置

 设置包名称

 设置应用程序根路径

 设置应用程序data路径

 设置activity的context

等等,我没有详细看,有不正之处希望高手指正,小弟不胜感激

     接着是第二步,scheduleLaunchActivity,先看调用堆栈:
ActivityThread$ApplicationThread.scheduleLaunchActivity(Intent, IBinder, int, ActivityInfo, Bundle, List, List, boolean, boolean) line: 1526       
ActivityThread$ApplicationThread(ApplicationThreadNative).onTransact(int, Parcel, Parcel, int) line: 130       
ActivityThread$ApplicationThread(Binder).execTransact(int, int, int, int) line: 288       
NativeStart.run() line: not available [native method]

同样,该函数操作也是交给ActivityThread.mH来处理,对应case消息为:H.LAUNCH_ACTIVITY

交由函数handleLaunchActivity处理,在这个函数中,根据ActivityRecord对像,获取要启动的Activity类信息,然后创建一个Activity,执行Activity的生命周期函数:onCreate,onResume,至此ActivitThread的handleBindApplication和handleLaunchActivity完成Activity的启动操作。

    最后,我再总结一下从桌面启动一个应用Activity的启动过程,画了一个时序图,有助于理解,希望走过路过的朋友别忘了留个脚印,或者留个砖板,这个blog花费了我不少时间:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值