Activity的工作过程(一)

一. Activity调用ActivityManagerService启动应用

image

  1. 用户在Launcher程序里点击应用图标时,会通知ActivityManagerService启动应用的入口Activity
  2. ActivityManagerService发现这个应用还未启动,则会通知Zygote进程孵化出应用进程,然后在这个dalvik应用进程里执行ActivityThread的main方法。
  3. 应用进程接下来通知ActivityManagerService应用进程已启动,ActivityManagerService保存应用进程的一个代理对象,这样ActivityManagerService可以通过这个代理对象控制应用进程
  4. 最后ActivityManagerService通知应用进程创建入口Activity的实例,并执行它的生命周期方法。

二. Activity启动相关类的类图

1. IActivityManager相关类

image

  1. Activity的管理采用binder机制,管理Activity的接口是IActivityManager.
  2. ActivityManagerService实现了Activity管理功能,位于system_server进程,
  3. ActivityManagerProxy对象是ActivityManagerService在普通应用进程的一个代理对象,应用进程通过ActivityManagerProxy对象调用ActivityManagerService提供的功能。
  4. 应用进程并不会直接创建ActivityManagerProxy对象,而是通过调用ActiviyManagerNative类的工具方法getDefault方法得到ActivityManagerProxy对象。
  5. 应用进程里通常这样启动Activty:
ActivityManagerNative.getDefault().startActivity();
2. IApplicationThread相关类

image

  1. ApplicationThreadProxy对象是ApplicationThread对象在ActivityManagerService线程内的代理对象.
  2. 应用进程需要调用ActivityManagerService提供的功能,而ActivityManagerService也需要主动调用应用进程以控制应用进程并完成指定操作。
  3. 这样ActivityManagerService也需要应用进程的一个Binder代理对象,而这个代理对象就是ApplicationThreadProxy对象。
  4. ActivityManagerService通过IApplicationThread接口管理应用进程,ApplicationThread类实现了IApplicationThread接口,实现了管理应用的操作。
3. ActivityManagerService相关类

image

ActivityManagerService管理Activity时,主要涉及以下几个类:

  1. ActivityManagerService,它是管理activity的入口类,聚合了ProcessRecord对象和ActivityStack对象
    • ProcessRecord,表示应用进程记录,每个应用进程都有对应的ProcessRecord对象
    • ActivityStack,该类主要管理回退栈
  2. ActivityRecord,每次启动一个Actvity会有一个对应的ActivityRecord对象,表示Activity的一个记录
  3. ActivityInfo: Activity的信息,比如启动模式,taskAffinity,flag信息(这些信息在AndroidManifest.xml里声明Activity时填写)
  4. TaskRecord: Task记录信息,一个Task可能有多个ActivityRecord,但是一个ActivityRecord只能属于一个TaskRecord

三. Activity启动详细流程(上)

1. Activity调用ActivityManagerService启动应用

image

  1. 启动Activity后,Activity最终调用Instrumentation的execStartActivity来启动应用:
//Activity类
public void startActivityForResult(Intent intent, int requestCode, Bundle options) {
    if (mParent == null) {
        Instrumentation.ActivityResult ar =
                    mInstrumentation.execStartActivity(
                        this, mMainThread.getApplicationThread(), mToken, this,
                        intent, requestCode, options);
        if (ar != null) {
                    mMainThread.sendActivityResult(
                        mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                        ar.getResultData());
        } 
        //...   
    }else{
        //...
    }
}
  1. Instrumentation调用ActivityManagerProxy对象的startActivity方法启动Activity

    • ActivityManagerProxy只是ActivityManagerService对象在应用进程的一个代理对象,
    • ActivityManagerProxy最终调用ActivityManagerService的startActvity方法启动Activity。
    //Instrumentation类
    public ActivityResult execStartActivity(
              Context who, IBinder contextThread, IBinder token, Activity target,
              Intent intent, int requestCode, Bundle options) {
    //...
     try{          
       //...
       int result = ActivityManagerNative.getDefault()
                    .startActivity(whoThread, intent,
                            intent.resolveTypeIfNeeded(who.getContentResolver()),
                            token, target != null ? target.mEmbeddedID : null,
                            requestCode, 0, null, null, options);
       } catch (RemoteException e) {
       }   
    //...   
    }
2. ActivityManagerService调用Zygote孵化应用进程

image

  1. ActivityManagerProxy对象调用ActivityManagerService对象(运行在system_server进程)的startActivity方法以启动应用,startActivity方法接下来调用startActivityAsUser方法以启动应用。
  2. 在startActivityAsUser方法里会调用ActivityStack的startActivityMayWait方法以启动应用,startActivityMayWait方法里启动应用时,需先根据intent在系统中找到合适的应用的activity,如果有多个activity可选择,则会弹出ResolverActivity让用户选择合适的应用。

    //ActivityStack类
    final int startActivityMayWait(IApplicationThread caller, int callingUid,
                Intent intent, String resolvedType, IBinder resultTo,
                String resultWho, int requestCode, int startFlags, String profileFile,
                ParcelFileDescriptor profileFd, WaitResult outResult, Configuration config,
                Bundle options, int userId) {
    //…
    //根据intent在系统中找到合适的应用的activity,如果有多个activity可选择,
    //则会弹出ResolverActivity让用户选择合适的应用。
      ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags,
                    profileFile, profileFd, userId);
    //…
    int res = startActivityLocked(caller, intent, resolvedType,
                        aInfo, resultTo, resultWho, requestCode, callingPid, callingUid,
                        startFlags, options, componentSpecified, null);
    //…
  3. 在startActivityLocked方法里,对传过来的参数做一些校验,然后创建ActivityRecord对象,再调用startActivityUncheckedLocked方法启动Activity。
  4. startActivityUncheckedLocked方法调度task的算法非常复杂,和当前回退栈,要启动的acitivity的启动模式以及taskAffinity属性,启动activity时设置的intent的flag等诸多要素相关,intent的flag就有很多种情况,故此算法非常复杂,需要阅读源码并结合特定启动情况才能理解。
  5. 接下来调用startActivityLocked将ActivityRecord加入到回退栈里:

    //ActivityStack类
    final int startActivityUncheckedLocked(ActivityRecord r,
              ActivityRecord sourceRecord, int startFlags, boolean doResume,
              Bundle options) {
    //...          
    startActivityLocked(r, newTask, doResume, keepCurTransition, options);
    //...
    }
  6. 在startActivityLocked里调用resumeTopActivityLocked显示栈顶Activity:

    //ActivityStack类
    private final void startActivityLocked(ActivityRecord r, boolean newTask,
            boolean doResume, boolean keepCurTransition, Bundle options) {
     //...        
     if (doResume) {
       resumeTopActivityLocked(null);
     }  
    }
  7. resumeTopActivityLocked(null)会调用另一个resumeTopActivityLocked方法显示栈顶的acitivity:

    //ActivityStack类
    final boolean resumeTopActivityLocked(ActivityRecord prev) {
        return resumeTopActivityLocked(prev, null);
    }
  8. 因为应用还未启动过,所以调用startSpecificActivityLocked启动应用,执行逻辑如下:

    //ActivityStack类
    final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
      //...
      if (next.app != null && next.app.thread != null) {
        //…
      }else{
        //…
       startSpecificActivityLocked(next, true, true);
      }
     //...
  9. 在startSpecificActivityLocked里调用mService.startProcessLocked启动应用:

    //ActivityStack类
    private final void startSpecificActivityLocked(ActivityRecord r,
                boolean andResume, boolean checkConfig) {
       ProcessRecord app = mService.getProcessRecordLocked(r.processName,
                  r.info.applicationInfo.uid);
       //...
       mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
            "activity", r.intent.getComponent(), false, false);
    }
  10. 在ActivityManagerService的startProcessLocked方法里:

    //ActivityManagerService类
    final ProcessRecord startProcessLocked(String processName,
              ApplicationInfo info, boolean knownToBeDead, int intentFlags,
              String hostingType, ComponentName hostingName, boolean allowWhileBooting,
              boolean isolated) {
     ProcessRecord app;
     if (!isolated) {
         app = getProcessRecordLocked(processName, info.uid);
     } else {
         //...
     }
     //...
     if (app == null) {
        app = newProcessRecordLocked(null, info, processName, isolated);
        if (app == null) {
            Slog.w(TAG, "Failed making new process record for "
                    + processName + "/" + info.uid + " isolated=" + isolated);
            return null;
        }
        mProcessNames.put(processName, app.uid, app);
        if (isolated) {
            mIsolatedProcesses.put(app.uid, app);
        }
      } else {
       //..
     }
     //...
     startProcessLocked(app, hostingType, hostingNameStr);
     //...
    }
  11. 在startProcessLocked方法里:

    //ActivityManagerService类
    private final void startProcessLocked(ProcessRecord app,
            String hostingType, String hostingNameStr) {
      //...
      try {
          //...
          // Start the process.  It will either succeed and return a result containing
      // the PID of the new process, or else throw a RuntimeException.
      //Zygote孵化dalvik应用进程后,会执行android.app.ActivityThread类的main方法
          Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread",
                  app.processName, uid, uid, gids, debugFlags, mountExternal,
                  app.info.targetSdkVersion, app.info.seinfo, null);
          //...    
      } catch (RuntimeException e) {
          //...
      }
    }
  12. 在Process类的start方法里:

    //Process类
    public static final ProcessStartResult start(final String processClass,
                                  final String niceName,
                                  int uid, int gid, int[] gids,
                                  int debugFlags, int mountExternal,
                                  int targetSdkVersion,
                                  String seInfo,
                                  String[] zygoteArgs) {
     try{                              
      startViaZygote(processClass, niceName, uid, gid, gids,
                        debugFlags, mountExternal, targetSdkVersion, seInfo, zygoteArgs);
      }catch (ZygoteStartFailedEx ex) {
        //...
      }                    
    }
3. zygote孵化应用进程

image

  1. zygote进程将ZygoteInit作为启动类,会执行它的main方法,先注册ZygoteSocket,然后调用runSelectLoop方法。
  2. runSelectLoop方法会调用方法在ZygoteSocket上监听请求,如果别的进程通过ZygoteSocket请求孵化进程,则孵化进程。

  3. runSelectLoop方法的主要代码:

    //ZygoteInit类
    private static void runSelectLoopMode() throws MethodAndArgsCaller {
      //...
      while (true) {
         //...
          try {
              fdArray = fds.toArray(fdArray);
              index = selectReadable(fdArray);
          } catch (IOException ex) {
              throw new RuntimeException("Error in select()", ex);
          }
          if (index < 0) {
              throw new RuntimeException("Error in select()");
          } else if (index == 0) {
              //监听客户连接请求
              ZygoteConnection newPeer = acceptCommandPeer();
              peers.add(newPeer);
              fds.add(newPeer.getFileDesciptor());
          } else {
             //若客户发送孵化进程的请求过来,
             //此时便需要调用ZygoteConnection的runOnce方法孵化进程
              boolean done;
              done = peers.get(index).runOnce();
              if (done) {
                  peers.remove(index);
                  fds.remove(index);
              }
          }
      }
    }
  4. 在runOnce方法里调用Zygote.forkAndSpecialize方法孵化进程,如果返回值为0表示是在孵化出来的应用进程里,此时会调用handleChildProc进行一些处理,并使用异常机制进行逃逸,会直接逃逸至ZygoteInit的main方法。

    //ZygoteConnection类
    boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {
      //...
      try {
      //...
          pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
                  parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
                  parsedArgs.niceName);
      } 
      //...
      try {
          if (pid == 0) {
              // in child
              IoUtils.closeQuietly(serverPipeFd);
              serverPipeFd = null;
              //handleChildProc是一个很重要的函数,在该函数里使用了异常进行逃逸
              handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
              //...  
          } else {
             //... 
          }
      } finally {
           //...
      }
    }
  5. Zygote.forkAndSpecialize

    • Zygote的forkAndSpecialize方法会调用nativeForkAndSpecialize方法孵化进程,
    • nativeForkAndSpecialize是一个本地方法,它的实现在dalvik/vm/native/dalvik_system_Zygote.cpp里,在该cpp文件里与nativeForkAndSpecialize对应的C++方法是Dalvik_dalvik_system_Zygote_forkAndSpecialize
    • 在该方法里会调用forkAndSpecializeCommon孵化进程,在forkAndSpecializeCommon方法里会调用fork系统调用创建进程,因为使用的是fork机制所以创建进程的效率比较高。
  6. handleChildProc

    //ZygoteConnection类
    private void handleChildProc(Arguments parsedArgs,
                FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr)
                throws ZygoteInit.MethodAndArgsCaller {
      //...
      if (parsedArgs.runtimeInit) {
      //...
      } else {
          String className;
          try {
              //这里得到的classname实际是android.app.ActivityThread
              className = parsedArgs.remainingArgs[0];
          } catch (ArrayIndexOutOfBoundsException ex) {
              logAndPrintError(newStderr,
                      "Missing required class name argument", null);
              return;
          }
          //...
          if (parsedArgs.invokeWith != null) {
          //...
          } else {
              ClassLoader cloader;
              if (parsedArgs.classpath != null) {
                  cloader = new PathClassLoader(parsedArgs.classpath,
                          ClassLoader.getSystemClassLoader());
              } else {
                  cloader = ClassLoader.getSystemClassLoader();
              }
              //调用ZygoteInit.invokeStaticMain执行android.app.ActivityThread的main方法        
              try {
                  ZygoteInit.invokeStaticMain(cloader, className, mainArgs);
              } catch (RuntimeException ex) {
                  logAndPrintError(newStderr, "Error starting.", ex);
              }
          }
      }
    }
    1. ZygoteInit的invokeStaticMain方法并不会直接执行className的main方法,而是会构造一个 ZygoteInit.MethodAndArgsCaller异常,然后抛出来,通过异常机制会直接跳转到ZygoteInit的main方法.
    2. ZygoteInit.MethodAndArgsCaller类实现了Runnable方法,在run方法里会执行要求执行的main方法,故此跳转到ZygoteInitmain方法后,异常会被捕获,然后执行方法caller.run(),这样便会执行android.app.ActivityThreadmain方法。
    3. ZygoteInitinvokeStaticMain方法主要代码:

      //ZygoteInit类
      static void invokeStaticMain(ClassLoader loader,
              String className, String[] argv)
              throws ZygoteInit.MethodAndArgsCaller {
        //...        
        Method m;
        try {
            m = cl.getMethod("main", new Class[] { String[].class });
        } catch(//...){
        }
        //...
        throw new ZygoteInit.MethodAndArgsCaller(m, argv);
      }
    4. ZygoteInit.MethodAndArgsCaller主要代码:

      public static class MethodAndArgsCaller extends Exception
              implements Runnable {
          //...
          public void run() {
              try {
                  mMethod.invoke(null, new Object[] { mArgs });
              }//...
          }
      }
    5. ZygoteInit的main方法相关代码:

      //ZygoteInit类
      public static void main(String argv[]) {
        try {
            //...
        } catch (MethodAndArgsCaller caller) {
            caller.run();
        } catch (RuntimeException ex) {
            //...
        }
      }
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值