美文网首页Android技术知识Android开发Android开发经验谈
Android 操作系统之 Activity 的启动过程

Android 操作系统之 Activity 的启动过程

作者: 程序老秃子 | 来源:发表于2022-08-08 14:37 被阅读0次

    前言

    上篇文章写到 Service 的启动过程; 相对来说Activity的启动过程比Service的启动过程更为复杂,其一Activity的生命周期方法比Service多,其二Activity具有启动模式和返回栈; 写本文的目的在于更清晰的梳理Activity的启动过程,加强自己的内功修炼,博客粉丝日益增多,力在以最简单的方式让大家理解,跟大家一起学习

    一、Binder的基本理解

    Activity的启动有多次IPC过程,所以Binder属于预备知识,帮助我们更好理解系统的C/S的这种架构模式

    二、Activity启动的双向IPC过程

    一般Android各个应用进程的启动都以这样一条路线,init进程 –> Zygote进程 –> SystemServer进程 –>各种应用进程

    • Init进程:Linux的根进程,Android系统是基于Linux系统的,因此可以算作是整个android操作系统的第一个进程;

    • Zygote进程是所有应用进程的父进程,所有的应用进程都是它孵化出来的;

    • SystemServer进程含有一些核心的服务,比如ActivityManagerService,PackageManagerService,WindowManagerService等;

    • 各种应用进程:启动自己编写的客户端应用时,有自己的虚拟机与运行环境。

    由此可知应用的第一个Activity的启动是多个进程相互配合的结果,多个进程相互配合就少不了使用Binder进行IPC了,现在看一次IPC调用的过程是怎样的。

    上图大概说明了一次IPC的过程,或许你现在对里面各个类还不是很清楚,没关系,大致了解一下

    ActivityManagerService (下文简称AMS),AMS是Android中最核心的服务,实现了ActivityManager,主要负责系统中四大组件的启动、切换、调度及应用进程的管理和调度等工作,AMS提供了一个ArrayList mHistory来管理所有的Activity,Activity在AMS中的形式是ActivityRecord,Task在AMS中的形式为TaskRecord,进程在AMS中的管理形式为ProcessRecord,它在Android中特别重要

    ActivityManagerNative (下文简称AMN):由于AMS是系统核心服务在SystemServer进程里面,很多API不能直接开放供客户端使用,所以需要通过IPC的方式,具体是这样的,ActivityManager类内部调用AMN的getDefault函数得到一个ActivityManagerProxy对象,通过它可与AMS通信

    ActivityManagerProxy (下文简称AMP):AMP是AMS在客户端进程的一个代理,通过AMP里面的方法请求AMS

    Instrumentation: Instrumentaion是一个工具类,一个大管家。当它被启用时,系统先创建它,再通过它来创建其他组件;另外,系统和组件之间的交互也将通过Instrumentation来传递,这样,Instrumentation就能监测系统和这些组件的交互情况了。在实际使用中,我们可以创建Instrumentation的派生类来进行相应的处理。Android中Junit的使用到了Intrstrumentation

    OK,现在我们知道,Activity是如何向AMS发出startActivity这个请求了,这意味着Activity可以与AMS进行通信,但是AMS却不能与Activity通信,Binder是单向的,所以在Activity发出请求之后,AMS需要通知Activity发生状态改变,要做到这一点,自然就在AMS到Activity这个过程建立一个Binder,如下:

    大致过程就是,SystemServer进程在收到请求后,再通过IPC向应用进程发送scheduleLaunchActivity请求,应用进程的binder线程(ApplicationThread)在收到请求后,通过handler向主线程发送LAUNCH_ACTIVITY消息,主线程在收到Message后,创建目标Activity,并回调Activity.onCreate()等方法

    对上面的理解不是太明白,在看下面这张图,简单多了;AMS到Activity这个过程建立了一个Binder,Activity到AMS这个过程也建立了一个Binder,这就能相互通信了

    上图就是Activity与AMS之间的双向Binder连接, (备注:这个就是理解Activity启动流程的指南针,不记住这个,复杂的启动流程会让你晕头转向);Activity用IActivityManager提供的API向AMS提出执行某个动作的请求(本例中是启动RemoteService),AMS通过IApplicationThread提供的API来控制Activity所在的应用程序,这些API包括schedulePauseActivity()、scheduleStopActivity()等

    IActivityManager接口定义的API,启动四大组件的等多种请求都在里面

    IApplicationThread接口定义的API,一看就比IActivityManager高逼格一点,IActivityManager好多方法是start开头,表示去AMS请求,IApplicationThread以schedule开头,表示对Activity进行调度

    分析到这里,我们不知不觉间忽略了两个问题,那就是启动Activity至少需要两个前提

    第一是,应用进程存在,第二AMS已经初始化完毕; 在调用startActivity方法时候,如果我们的应用进程不存在,Activity能启动吗,当然是不能的,比如点击桌面图标的时候,这个时候需要先创建进程。关于Zygote孵化应用进程,这个暂时不说,先看看AMS服务注册

    三、AMS服务注册

    先忽略 Activity调用ActivityManagerService启动应用,直接从SystemServer的main方法说起

     /**
        * The main entry point from zygote.
        */
       public static void main(String[] args) {
           new SystemServer().run();
       }
    

    run方法中,调用了startBootstrapServices

     private void startBootstrapServices() {
          
           ......
           //启动AMS服务
           Installer installer = mSystemServiceManager.startService(Installer.class);
    
           //请注意这里参数是Lifecycle,因为AMS是在Lifecycle里面new出来的
           mActivityManagerService = mSystemServiceManager.startService(
                   ActivityManagerService.Lifecycle.class).getService();
           mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
           mActivityManagerService.setInstaller(installer);
    
           mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);
    
           mActivityManagerService.initPowerManagement();
    
            ......
           mActivityManagerService.setSystemProcess();
         ......
    }
    
     public SystemService startService(String className) {
           final Class<SystemService> serviceClass;
           try {
               serviceClass = (Class<SystemService>)Class.forName(className);
           } catch (ClassNotFoundException ex) {
               Slog.i(TAG, "Starting " + className);
           }
           return startService(serviceClass);
       }
    

    继续

    public <T extends SystemService> T startService(Class<T> serviceClass) {
           try {
               final String name = serviceClass.getName();
               // 1、创建服务
               final T service;
               try {
                   Constructor<T> constructor = serviceClass.getConstructor(Context.class);
                 // 如果传进来的是ActivityManagerService.Lifecycle对象,那么ActivityManagerService就能被创建
                   service = constructor.newInstance(mContext);
               } catch (InstantiationException ex) {
                   throw new RuntimeException("Failed to create service " + name
                           + ": service could not be instantiated", ex);
               }
               // 2、注册服务
               mServices.add(service);
    
               // 3、启动服务
               try {
                   service.onStart();
               } catch (RuntimeException ex) {
                   throw new RuntimeException("Failed to start service " + name
                           + ": onStart threw an exception", ex);
               }
               return service;
           } finally {
               Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
           }
       }
    
    ActivityManagerService.java
    
      public static final class Lifecycle extends SystemService {
           private final ActivityManagerService mService;
    
           public Lifecycle(Context context) {
               super(context);
             //ActivityManagerService被new出来了
               mService = new ActivityManagerService(context);
           }
    
           @Override
           public void onStart() {
             //  启动
               mService.start();
           }
    
           public ActivityManagerService getService() {
               return mService;
           }
       }
    
     private void start() {
           Process.removeAllProcessGroups();
           mProcessCpuThread.start();
    
           mBatteryStatsService.publish(mContext);
           mAppOpsService.publish(mContext);
           Slog.d("AppOps", "AppOpsService published");
           LocalServices.addService(ActivityManagerInternal.class, new LocalService());
       }
    

    回到 startBootstrapServices里面调用的 mActivityManagerService.setSystemProcess();

    public void setSystemProcess() {
           try {
               ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);
               ServiceManager.addService(ProcessStats.SERVICE_NAME, mProcessStats);
               ServiceManager.addService("meminfo", new MemBinder(this));
               ServiceManager.addService("gfxinfo", new GraphicsBinder(this));
               ServiceManager.addService("dbinfo", new DbBinder(this));
               ......
    
    
          // 设置application info LoadedApkinfo 有关 framework-res.apk
           ApplicationInfo info = mContext.getPackageManager().getApplicationInfo( "android", STOCK_PM_FLAGS);
           mSystemThread.installSystemApplicationInfo(info, getClass().getClassLoader());
           
           //给SystemServer进程创建ProcessRecord,adj值,就是将SystemServer进程加入到AMS进程管理机制中,跟应用进程一致
           synchronized (this) {
               ProcessRecord app = newProcessRecordLocked(info, info.processName, false, 0);
               app.persistent = true;
               app.pid = MY_PID;
               app.maxAdj = ProcessList.SYSTEM_ADJ;
               app.makeActive(mSystemThread.getApplicationThread(), mProcessStats);
               synchronized (mPidsSelfLocked) {
                   mPidsSelfLocked.put(app.pid, app);
               }
               updateLruProcessLocked(app, false, null);
               updateOomAdjLocked();
     }
    

    ServiceManager这里面注册了很多的服务,可通过dumpsys <服务名>命令查看。比如查看CPU信息命令dumpsys cpuinfo,查看graphics信息命令dumpsys gfxinfo

    在Android中所有的核心服务,并不是直接给上层使用,都先交给ServiceManager管理,上层使用的时候可以从ServiceManager获取,ServiceManager相当于一个路由作用。现在来看一张经典的图。其中注册服务,获取服务以及使用服务,每一次都是一个完整的Binder IPC过程,可见理解Binder是多么的重要啊。关于AMS启动得深入了解

    • 注册服务:首先AMS注册到ServiceManager。AMS所在进程(SystemServer)是客户端,ServiceManager是服务端

    • 获取服务:Client进程使用AMS前,须先向ServiceManager中获取AMS的代理类AMP。该过程。AMP所在进程(应用进程)是客户端,ServiceManager是服务端

    • 使用服务: app进程根据得到的代理类AMP,便可以直接与AMS所在进程交互。该过程,AMP所在进程(应用进程)是客户端,AMS所在进程(SystemServer)是服务端

    有需要文章中完整代码的同学 现在点击此处传送门 即可免费获取

    现在点击链接还可以获取《更多 Android 源码解析+核心笔记+面试真题》

    最后我想说:

    学习没有捷径可言,我们要注意记学习,不仅要记,还要写心得体会,文字笔记、画图、总结等,方式很多,但是一定要自己认真去做,不要太相信自己的记忆,只有反复记忆,加深理解才行

    同时,对于程序员而言,不单单是死记硬背,我们有更好的方式去学习,比如写demo去验证。复习知识点时,要及时跟你做过的项目结合起来,这样在面试时就知道怎么聊了,由项目讲到知识点,由一个知识点串联到另一个知识点。复习到一定阶段,可以尝试着去把这些东西串联起来,由点及面,形成知识体系

    对于程序员来说,要学习的知识内容、技术有太多太多,要想不被环境淘汰就只有不断提升自己,从来都是我们去适应环境,而不是环境来适应我们

    技术是无止境的,你需要对自己提交的每一行代码、使用的每一个工具负责,不断挖掘其底层原理,才能使自己的技术升华到更高的层面

    Android 架构师之路还很漫长,与君共勉

    相关文章

      网友评论

        本文标题:Android 操作系统之 Activity 的启动过程

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