Android随笔随想-GUI-事件分发先导篇

Android随笔随想-GUI-事件分发先导篇

为了了解Android的事件分发,我们先需要了解一下GUI的上下文涉及的内容,这篇只是做简单的介绍,在分析完事件后,会详细的分析总结这些内容

基于Android 2.3源码的分析总结

1. GUI系统结构图

GUI其实是为了做了几件事情:

  1. 将Android进行绘制
  2. 对于用户的按键操作,触摸操作进行响应,并且交给对应的内容进行处理

是否还有其他???

涉及到的相关内容

  • Ams(ActivityManagerService(以下简称Ams))
  • Wms(WindowManagerService(以下简称Wms))
  • SurfaceFlinger

因为需要找到一个突破口,如果但从SurfaceFlinger或者Wms入口的话,很难看到具体的调用的地方,于是还是从Ams入手是最好的

  1. 能够知道整体的流转,整体的数据和逻辑控制的序列
  2. 因为Ams是与开发者,直接能够接触和使用的,了解了之后会更加轻车熟路的来了解其他

GUI系统结构图

Android随笔随想-GUI-事件分发先导篇_第1张图片

2. Ams的介绍

2.1 Ams是什么

Ams: ActivityManagerService, 这个名字感觉还是不够明确的,这个并不单单做这个事情,ActivityManagerService 是作为server端,管理系统中的四大组件的

  • Activity
  • Service
  • BroadcastReceiver
  • ContentProvider

2.2 Ams用来做什么用

控制管理四大基本组件

2.3 Ams的相关图示

2.3.1 Ams相关类图

Android随笔随想-GUI-事件分发先导篇_第2张图片

这里也只是将Activity相关的部分,进行了一些类图的汇总

总结如下:

Client

  1. Activity通过Instrumentation来调用服务端的Ams相关动作,比如说我们常见的从Launcher启动一个应用,Activity来启动另外一个Activity,Instrumentation起到了和Ams通讯的中间桥梁
  2. Instrumentation在和Ams进行主动通讯时,是跨进程的,跨进程通讯使用的是IPC,而IPC的套路是,Client和Server共同实现相同的接口,然后通过Binder来调用,这里也是符合Android自己定义的Binder的流程的

    • Instrumentation使用的是ActivityManagerNative.gDefault(),通过查看源码得知,这里使用的是一个Ams的代理: ActivityManagerProxy, 在调用ActivityManagerProxy的方法时,便是通过Binder来调用ActivityManagerService

Server

  1. ActivityManagerService在收到了客户端的请求操作后,会做一些逻辑的处理,以通过Launcher来启动一个应用为例

    • 会通知原来的Launcher的activity做对应状态的更改,比如说,Activity应该做onPause,onStop的操作
    • 启动一个新的进程,会调用ActivityThread的main()函数

Client

  1. ActivityThread在收到这个请求后,会做初始化,将初始化的ApplicationThread通知给Ams

Server

  1. Ams在收到这个请求后,会保存ApplicationThread的一个代理
  2. bind对应的application,即Application的初始化

    • 将Application初始化,由于已经建立了callback的通道,即ApplicationThreadProxy,便直接通过这个来通知Client进行启动绑定
  3. 将要启动的Activity来继续操作,通过ApplicationThreadProxy通知启动Activity,activity便进行了launch

  4. 端上在launch时,会通过Instrument来通知Activity进行attach,onCreate以及生命周期相关方法onStart(), onResume()的调用

2.3.2 内容总结

  1. Ams只是控制Activity的堆栈以及应用之间应该如何操作,自己并不做Activity的启动以及销毁等操作,因为这个是具体应用来控制的,即Client的事情

  2. 数据的通道: 这个与我们常见写的callback的方式其实没有太大的差异,只不过涉及的类以及内容复杂了些,Activity通过Ams的proxy来请求服务端,我想做什么,服务端在处理了之后,通过ApplicationThread的Proxy来通知端上,你应该做什么.

2.3.3 相关资料

Ams相关讲解

老罗的Android之旅 activity相关

2.4 随想

2.4.1 360的DroidPlugin

DroidPlugin github地址

个人之前也在之前公司的app中集成过360的DroidPlugin,这个插件实现的挺巧妙的,而且各种hook,也看出了360的hook与hack的精神,插科打诨一下~

个人之前的DroidPluigin的随笔,写的很散,而且条理性不是很清晰,但是是个人学习的踪迹,现在来看,还是别有一番趣味的

2.4.1.1 Ams超级简化

在说360的这个插件框架之前,再来简化的说一下Ams相关的流程图

图示如下:

Android随笔随想-GUI-事件分发先导篇_第3张图片

根据这个图,我们再来梳理一下:

  1. Activity通过Instrumentation来向ActivityManager的Proxy来和ActivityManagerService来请求通讯,类似于request
  2. ActivityManagerService收到请求后,做出对应的响应,不同应用或者相同应用之间,进程,ActivityRecord,ProcessRecord等的控制,在处理完成后,通过客户端给自己的ApplicationThread的代理,发送响应消息
  3. ApplicationThread将对应的响应在Handler中做顺序排队,然后取出给ActivityThread,ActivityThread再通过Instrumentation来和Activity来交互

这个图只是以Activity的启动为例,其实Service,ContentProvider,BroadcastReceiver等组件均由ActivitiyManagerService来控制,Client均是通过ActivityManagerProxy来做这些请求操作,然后ActivityManagerService来通过ApplicationThreadProxy来通知客户端应该做如何的响应的.

2.4.1.2 DroidPlugin的举例分析

DroidPlugin的偷梁换柱

我们知道,Android的四大组件,除了广播,其他的组件,Activity,Service,ContentProvider都是需要在资源清单文件中注册的,那么对于动态加载,肯定是这些资源清单文件中,没有的这几个组件,通过查看上节中的分析,得知这四大组件的通讯模型,是否能够做些手脚,便可以实现这些,360的DroidPlugin便实现了这些.

上图中,我已经标注了Client和Server的分界线,而且进出口都是明确的,进入ActivityManagerService的入口是ActivityManagerProxy,查看ActivityManagerProxy的源码,看到了我们垂涎欲滴的方法,startActivity, startService,那么更改下这个代理,把我们要启动的Activity换位已有的Activity,这样系统就认为我们启动的Activity是合法的了.参数如何处理呢?直接将参数以其他的方式存入到Intent中即可

这个只是启动合法了,那么Activity在通过ApplicationThreadProxy时通知我们启动Activity时,这个Acitivy是我们欺骗系统用的Activity,这时,通过Instrumentation是要启动我们想要的Activity的,那么我们再将Instrumentation中的要启动的Activity我们自己加载,便可以Activity的动态加载了.

如下图:

Android随笔随想-GUI-事件分发先导篇_第4张图片

2.4.2 设计模式

这个后续再分享吧,todo一下

2.4.3 程序设计时的逻辑流向要明确

其实包括我们接下来要说的View的事件分发,其实能看出来,单方向的数据流设计是最简单的,而且是最不容易出问题的.

A 请求B,我要做什么,B经过处理后,通知A,你可以做什么,其实Ams的模型就是这个的复杂化.
A想要请求B,但是A摸不到B,A只能通过B的代理来请求B,B经过自己的N多处理流程,最终通过其他方式来通知A,你可以做什么.
其实说白了,这个就是请求响应的复杂化,
A request B, B response A

我们最常见的写代码的逻辑,举例如下:

A是UI的控件,B是处理逻辑的控制器,A点击后,调用B的方法,告诉B我想做什么
B在收到这个事件后,经过自己的处理逻辑,告诉A处理的结果.

以上内容部分参考老罗的android之旅以及柯元旦的源码分析

相关图位于个人的github上

你可能感兴趣的:(Android)