侧边栏壁纸
博主头像
慢行的骑兵博主等级

贪多嚼不烂,欲速则不达

  • 累计撰写 29 篇文章
  • 累计创建 27 个标签
  • 累计收到 1 条评论

目 录CONTENT

文章目录

AMS服务执行流程

慢行的骑兵
2021-09-24 / 0 评论 / 0 点赞 / 476 阅读 / 2,647 字
  • 理解AMS的前提
    • Android的体系结构
    • 系统的启动流程
    • 什么是Binder
    • AIDL
  • 准备知识学习好之后,从二个方面来学习AMS
    • Activity的启动过程(其它组件的启动类似)—>体现AMS的作用
      • 这一部分不做具体的源码分析(具体的源码分析之前有总结过笔记),只总结大体的流程
    • Hook AMS—> 查看启动Activity会启动哪些AMS的方法

一.Android的体系结构

  • Android的体系结构

06.Android的体系结构

  • 底层是基于Linux,第三成包含大量的库和android运行时,这两层通过系统调用进行调用;

  • 做应用层一般熟悉1.2层即可,若想成为资深级的专家。可以看一下Linux相关的书籍(如:Linux内核设计与实现、深入理解Linux);主要看的是文件管理、进程管理、进程调度、系统调用、数据结构、终端管理、内存管理、io(如epoll,android底层的很多读写是用这个);

二.Android的启动过程

1.大体流程

  • Android系统的启动流程是比较复杂的,这里只梳理大体流程;
  • Android系统的启动流程主要有以下几步(先实现了解,后续有精力再去深入)
    • 1.启动电源,加载引导程序BootLoader(理解成一个小程序,将系统os拉起来)到RAM,然后执行;
    • 2.当内核启动后,会做一些初始化工作,并在系统文件中找到init.rc,并启动init进程
    • 3.init进程启动:初始化和启动属性服务,并且启动Zygote进程
    • 4.Zygote进程启动:创建Java虚拟机并为Java虚拟机注册JNI方法,创建服务器端Socket,启动SystemServer进程
    • 5.SystemServer进程启动:启动Binder线程池和SystemServiceManager,并且启动各种系统服务;
    • 6.Launcher启动:被SystemServer进程启动的AMS会启动Launcher;

07.Android的系统启动简图

  • SysCall属于系统调用(关于这些概念,可以通过《操作系统的哲学》一书来学习,在这里明白用户空间,内核空间,系统调用即可);

  • 引导服务中最终要的服务就是AMS,需要第一时间运行起来;

  • Zygote进程优先于SystemServer进程启动,通信方式有两种,接着换一个角度看一下App启动的大体流程;

05.App启动的大体流程

  • 既然应用程序启动activity需要AMS的调控,那么接下来我们就来看看activity的启动过程以及过程中,AMS如何对应用程序加以调度,并且和应用程序之间进行交互的。Activity的启动入口是startActivityForResult(),startActivity()其实也是调用了startActivityForResult(),那么就从这个入口去看看具体的启动流程吧;

三.什么是Binder

1.什么是Binder

08.什么是Binder

2.Binder是如何启动的

  • 这部分先了解即可

09.Binder是如何启动的

  • Binder神图:深入理解了Binder之后,可以再看下图

10.Binder神图

3.Aidl

  • 使用到了动态代理
    • 共同实现业务接口
    • 代理对象包含实际对象
stub继承binder,实现了定义的接口
proxy实现了定义的接口,持有一个remote(是stub实体)

4.Binder通信的原理

  • 非常重要,必须要明白;另外,Android为什么要采用Binder作为IPC机制,也非常重要;
  • 面试题

11.AIDL通信原理

  • 当bindService的时候,会调到远端服务的onBind中去,通过AMS最终是调用客户端中定义的ServiceConnection的onServiceConnected回调,在会调用会得到服务端的IBinder对象,通过asInterface方法将IBinder转换成定义的接口(此时,该接口的实体是Proxy类),接着通过该接口引用调用接口中定义的方法,就会指定proxy中的方法,调用transact方法(然后客户端线程挂起,等待服务端数据返回[关于挂起和继续执行底层都是binder去实现]继续运行),触发调用服务端onTransact方法;
  • 关于bindService的细节补充,在android L之后,intent不能隐式调用,需要转成显示调用;

5.Android为什么要采用Binder作为IPC机制

  • Android系统是基于Linux内核的,Linux已经提供了管道、消息队列、共享内存和Socket等 IPC 机制。那为什么Android还要提供Binder来实现IPC呢?主要是基于性能、稳定性和安全性几方面的原因。

5.1.性能

  • Socket 作为一款通用接口,其传输效率低,开销大,主要用在跨网络的进程间通信和本机上进程间的低速通信;
  • 消息队列和管道采用存储-转发方式,即数据先从发送方缓存区拷贝到内核开辟的缓存区中,然后再从内核缓存区拷贝到接收方缓存区,至少有两次拷贝过程;
  • 共享内存虽然无需拷贝,但控制复杂,难以使用;
  • Binder 只需要一次数据拷贝,性能上仅次于共享内存;

30.ipc_vs

5.2.稳定性

  • Binder 基于 C/S 架构,客户端(Client)有什么需求就丢给服务端(Server)去完成,架构清晰、职责明确又相互独立,自然稳定性更好。共享内存虽然无需拷贝,但是控制负责,难以使用。从稳定性的角度讲,Binder 机制是优于内存共享的;

5.3.安全性

  • Android 作为一个开放性的平台,市场上有各类海量的应用供用户选择安装,因此安全性对于 Android 平台而言极其重要。作为用户当然不希望我们下载的 APP 偷偷读取我的通信录,上传我的隐私数据,后台偷跑流量、消耗手机电量。传统的 IPC 没有任何安全措施,完全依赖上层协议来确保。首先传统的 IPC 接收方无法获得对方可靠的进程用户ID/进程ID(UID/PID),从而无法鉴别对方身份。Android 为每个安装好的 APP 分配了自己的 UID,故而进程的 UID 是鉴别进程身份的重要标志。传统的 IPC 只能由用户在数据包中填入 UID/PID,但这样不可靠,容易被恶意程序利用。可靠的身份标识只有由 IPC 机制在内核中添加。其次传统的 IPC 访问接入点是开放的,只要知道这些接入点的程序都可以和对端建立连接,不管怎样都无法阻止恶意程序通过猜测接收方地址获得连接。同时 Binder 既支持实名 Binder,又支持匿名 Binder,安全性高。

5.4.总结

  • 基于上述原因,Android 需要建立一套新的 IPC 机制来满足系统对稳定性、传输性能和安全性方面的要求,这就是 Binder。

  • 最后用一张表格来总结下 Binder 的优势:

31.binder_youshi

6.系统使用服务大致流程分析

12.系统使用服务大致流程分析

  • ServiceManager是先启动的,其它服务会先注册到ServiceManager中,服务端需要使用服务的时候,通过ServiceManager拿到服务(代理),客户端就可以使用该服务;

7.Binder–AIDL通信细节

13.Binder-AIDL的通信细节

  • 这部分的细节,我们暂时不去深究,但大概的流程需要有所了解。

四.应用进程的启动

1.相关的类

  • 系统中的所有应用进程都是由Zygote进程fork出来的;
  • SystemServer进程是系统进程,很多系统服务,例如ActivityManagerService、PackageManagerService、WindowManagerService…都是存在该进程被创建后启动;
  • ActivityManagerServices(AMS):是一个服务端对象,负责所有的Activity的生命周期,AMS通过Binder与Activity通信,而AMS与Zygote之间是通过Socket通信;
  • ActivityThread主角,UI线程/主线程,它的main()方法是APP的真正入口;
  • ApplicationThread:一个实现了IBinder接口的ActivityThread内部类,用于ActivityThread和AMS的所在进程间通信;
  • Instrumentation:可以理解为ActivityThread的一个工具类,在ActivityThread中初始化,一个进程只存在一个Instrumentation对象,在每个Activity初始化时,会通过Activity的Attach方法,将该引用传递Activity。Activity所有生命周期的方法都有该类来执行;
  • 关于AMS源码部分,这里就略过,之前总结的App启动和Activity的启动流程分析的过程中都涉及有AMS,建议先看,然后再下方内容。以下,分别对每个步骤的流程进行一个大体的梳理,不同版本在细节上会存在差异。

2.点击应用图标(所干的事情)

14.应用进程启动分析1

  • Lanucher进程跟AMS通信(Binder),告诉AMS需要启动的目标app;
  • AMS创建进程(并非自己创建):通过socket通信通知Zygote去fork(涉及到Linux进程的创建过程知识)一个进程;
  • 应用进程创建好之后,应用进程跟AMS是通过Binder进行通信;

3.根Activity启动过程涉及的进程之间的关系

  • 换个角度看Lanuncher的启动

15.应用进程启动分析2

4.应用程序进程启动过程分析-时序图

16.应用程序进程启动过程分析-时序图

5.AMS请求Zygote过程分析

17.AMS请求Zygote过程分析

6.Zygote进程fork进程分析

18.Zygote进程fork进程分析

7.应用程序创建后细节一

19.应用程序创建后细节一

8.应用进程Crash处理

20.应用进程Crash处理

9.Launcher请求AMS启动Activity

21.Launcher请求AMS启动Activity

10.AMS到ApplicationThread的调用过程

22.AMS到ApplicationThread的调用过程

11.ActivityThread启动Activity

23.ActivityThread启动Activity

12.IActivity接口分析

24.IActivity接口分析

13.IApplicationThead接口分析

25.IApplicationThead接口分析

14.Activity通信模型

26.Activity通信模型

15.AMS家族介绍

27.AMS家族介绍

16.AMS Android O–AIDL模型

28.AMS_Android_O_AIDL模型

17.Android P利用状态模式重构了部分代码

  • 重构之后,阅读代码的难度有所增加(状态模式封装了请求)

29.Activity_HandlerActivity的改变

五.Hook技术

  • 插件化、微信分身
  • hook没有注册的activity的启动
0

评论区