0%

总结

第二章-系统启动过程

init 进程是用户空间第一个进程,进程号为 1

僵尸进程的危害主要是消耗进程表等资源,耗尽了就无法创建新的进程。

init 进程主要做了2件事:启动属性服务(类似Windows注册表,重启系统还能知道App以前的状态), 启动 Zygote 进程

因为会有系统支持 32 位,有的系统支持 64 位,所以 Zygote 有 32 位的,也有 64 位的。

Zygote 通过 JNI 调用 ZygoteInit 的 main 方法后,就进入了 Java 世界

Zygote 进程总共做了几件事情: 启动虚拟机为虚拟机注册JNI 方法通过JNI调用进入Java 代码执行注册 Server 类型的 Scoket(Java层)创建SystemServer 进程

SystemServer 进程做的事情:关闭fork过来的Server Socket、启动Binder线程池、启动各种系统服务AMS、WMS等

Launcher 请求 PackageManagerService 获取所有的安装 APK 的信息 。

Launcher 的启动是在 SystemServer 的 startOtherService 中调用了 AMS.systemReady() 实现的,也就是直接通过 AMS 来启动的

第三章-启动应用程序进程

如果要启动应用进程,会调用 AMS.startProcessLocked() 方法,在里面会获取到将要启动的进程的 uid (用户进程 id),最后,调用 Process.start() 启动进程,uid 也会传过去

之后,与 Zygote 通过 Socket 进行连接通信, Zygote 处于 ronSlectLoop() 循环中 (while(true) 实现的死循环)一直监听消息

在新创建的应用进程中,会创建 Binder 线程池,接下来Class.forName 获得 ActivityThread 的 Class 类,之后通过反射调用其 main 方法,到这里就完成了进程创建,并运行了主线程管理类 ActivityThread

在 ActivityThread 的 main 方法里面,会prepareMainLooder 创建主线程的 Looper,创建 ActivityThread 自己的对象 thread,创建 H 类的对象、最后,开始 Looper.loop 死循环

Binder 线程池会有 mThreadPoolStarted 变量,用于标记Binder 线程池是否已经启动过,默认 false ,确保 Binder 线程池只启动一次。

第四章-四大组件工作过程

根 Activity 的启动分为 3 个部分讲:Launcher 请求 AMS 、AMS 到 ApplicationThread 、ActivityThread 启动 Activity

Launcher 请求 AMS : (点击图标)Launcher.startActivitySafely -> Activity.startActivityForResult -> Instrumentation.execStartActivity -> IActivityManager.startActivity -> AMS.startActivity

由于是启动第一个Activity ,所以必须要有 NEW_TASK 标记分配一个新的任务栈

Instrumentation 是 应用程序和系统之间的一个边界,主要用来监控应用程序和系统的交互,在这里面会通过 ActivityManager.getService (8.0 以前是 ActivityManagerNative.getDefault)来获取 IActivityManager 接口去调用 startActivity ,getService 里面是通过 Singleton.get 返回的,意味着是个单例

在 Singleton 中,通过 IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE) 获取到 Binder 对象,后面再通过IActivityManager am = IActivityManager.Stub.asInterface(b) 将其转为 IActivityManager 类型

在 ActivityStarter 中决定 Activity 的 Task 和 Stack

调用到 ApplicationThread.scheduleLaunchActivity() 就准备启动Activity 了,在里面会执行 ActivityThread 的 sendMessage 方法切换到主线程,之后再 ActivityThread 里面执行 performLaunchActivity ,之后调用 Instrumentation.callActivityOnCreate ,在里面又会调用到 Activity 自己的 performCreate 之后 就是 onCreate

在 Activity 对象创建后,会调用 Activity 的 attach 方法,在里面创建PhoneWindow对象并关联,之后才调用 Instrumentation 的 callActivityOnCreate,在 attach 方法里面也会创建 ComtextImpl 赋值给 ContextWrapper 的 mBase 变量。

第五章-上下文Context

Application Context 是在什么时候创建的?应该是 第一次 (后面就不空了)在performActivity 创建 Activity 对象的时候。同样也会创建一个 ContextImpl 作为 application 的 mBase ,也会 ContextImpl 的 outerContext 设置为这个 application 对象。

Application 对象是通过 Instrumentation 的 newApplication 方法创建出来的,凑巧的是,Activity 的对象也是通过 Instrumentation 的 newActivity 创建出来的。

Application 对象最后也会赋值给 LoadedApk 中的 mApplication 对象。所以我们获取 ApplicationContext 基本上也是从 LoadedApk 中去获取,获取不到再从 ActivityThread 获取。(应用已经启动, LoadedApk 不空,所以基本上是从 LoadedApk 中获取

同理,Activity 也是一样,在创建的时候,也会创建一个 ContextImpl 在 attach 的时候作为 Activity 的 mBase ,然后这个 ContextImpl 的 outContext 就是 Activity

看起来,Activity 的创建(newActiity)和生命周期调用(onCreate 等)都会经过 Instrumentation ,难怪被定义为应用与系统的交互的桥梁

第六章-AMS

在 7.0 及以前,主要使用 AMP 和 AMN 来实现远程代理,AMP 是 AMN 的内部类,运行在不同进程,AMP 运行在客户端,AMN 运行在服务端。在 AMN 的 onTransact 方法中接受 AMP 发送过来的 Binder 数据,然后执行 startActivity 等操作

启动应用程序的时候,AMS 会检查应用进程是否存在,不存在就通过 Zygote 创建。

ActivityRecord 记录一个 Activity 的所有信息,TaskRecord 包含一个或者多个 ActivityRecord ,而 ActivityStack 又包含若干个 TaskRecord,如图所示:

Activity任务栈关系

假如社交应用和系统 E-mail 中的 Activity 是处于不同的应用进程的,有了栈管理,就可以把邮件界面放到社交应用中所在的栈栈顶。

在 ActivityStarter 中通过各种 Flag 计算出最终启动 Activity 的 FLAG

taskAffinity 与 allowTaskReparenting 配合使用,如果 allowTaskReparenting 为 true ,说明Activity 具有转移能力。 拿前面社交应用和 E-mail 应用的例子继续:如果邮件 Activity 的 allowTaskReparenting 为 true ,此后E-mail应用所在的栈卫浴前台时,发送邮件的 Activity 就会由社交应用的栈转移到与它更亲近的邮件应用(taskAffinity相同)所在栈中。

任务栈转移图

第7章-理解 WindowManager

WindowManager 提供了 API 给调用管理 Window ,但是实际的操作是 WMS 来做的。

Window 是在 Activity 实例创建出来后,attach 方法中创建的 PhoneWindow ,在 window 创建出来之后会 setWindowManager 来设置它的管理者。

Window 中与应用开发关系最密切的三个属性有:Type(Window类型)、Flag(Window的标志)、SoftInputMode (软键盘相关模式,如 ADJUST_RESIZE),软键盘相关的模式可以看如下表格:

软键盘相关模式

Window 分为三大类:Application Window(应用程序窗口,如 Activity)、Sub Window(子窗口,不能独立存在,如PopupWindow)、System Window(系统窗口)

WindowManagerGlobal 中维护了 window 操作相关的 3 个列表,分别是:View 列表ArrayList mViews、布局参数列表 ArrayList<WindowManager.LayoutParams> mParams 以及 ViewRootImpl列表ArrayList mRoots

ViewRootImpl 是 View 树的根,并且管理 View 树。 WindowManager 的 addView 操作,会交给 WindowManagerImpl,最终交给 WindowManagerGlobal ,并且只是记录到上述数组中,最终还是通过 ViewRootImpl 的 setView 真正实现,最后添加到 WMS

WindowManager ->WindowManagerImpl->WindowManagerGlobal->ViewRootImpl->WMS

StatusBar 也是个 Window。 Activity 调用 WindowManager.addView 实际上是 add 了 DecorView 进去

Window 更新调用 ViewManager.updateViewLayout 方法,具体在 WindowManagerImpl ,具体流程和 addView 操作是一样的,值得注意的是,window 的更新会触发 ViewRootImpl 的 scheduleTraversals 方法执行刷新

第八章-WMS

WMS 的职责:

  • Window管理:添加、启动、删除,大小和层级

  • window切换动画

  • Surface 管理,每个 Window 都有一个 Surface

  • 输入中转站:触摸 Window 产生事件, IMS 寻找合适的窗口来处理

因为 WMS 创建是 SystemServer 进程在 system_server 线程中执行的 startOtherServices 方法中进行的, 使用了 Handler 在 android.display 线程,而 SystemServer 中主线逻辑都是执行都是在 system_server 线程,由于是使用 Handler 的 runWithScissors 方法,所以 system_server 会等待 WMS 创建完成。

WindowToken 可以理解为窗口令牌,当应用程序向 WMS 申请创建新的 Window 时,必须出示有效的 WindowToken 。

谢谢你的鼓励