一、点击桌面App图标事件分发
- systemserver进程启动时,会启动 inputflinger 服务: native层的 InputManager
- InputManager 启动时,启动 InputDispatcher 线程和 InputReader 线程
- InputReader 线程循环调用 EventHub 的 getEvents 方法,linux设备节点/dev/input文件夹下的event读取事件
- InputReader 读取到事件后,放到 InputDispatcher.mInboundQueue 队列中,并通知 InputDispatcher 线程读取数据
- InputDispatcher 线程唤醒后,从 mInboundQueue 队列中取出事件,按事件类型进行分发。
- 对于触屏事件,会寻找屏幕触控事件的焦点窗口,找到后把事件放入 Connection.outboundQueue 队列中
- Connection是在窗口添加时在 WindowState.openInputChannel 调用过程中创建的,
- 一个 Connection有一个服务端的InputChannel,一个InputChannel有一个socketpair服务端socket的fd,
- 同时 socketpair客户端的fd会被发送到App进程,并加入epoll监听
- 因此Connection就代表同App端的socket连接(或者说是管道)
- 最后通过 Connection 中的 socket 把事件发送到 App
InputDispatcher分发流程
1 | c复制代码InputDispatcher::start();// 这个start是SystemServer进程启动过程调用的 |
App进程事件分发
looper epoll监听
SocketPair
的fd 【这个fd的来源见:addToDisplayAsUser 章节】socket来数据后,回调 NativeInputEventReceiver::handleEvent
android::NativeInputEventReceiver.consumeEvent
native 反射调用Java层 InputEventReceiver.deliverInputEvent
WindowInputEventReceiver.onInputEvent
ViewRootImpl.enqueueInputEvent//执行入队操作—PendingInputEventQueue
doProcessInputEvents()
deliverInputEvent(q);//这里会在systrace显示 deliverInputEvent块
经过若干步骤后
mView.dispatchPointerEvent(event);//进入view的事件分发流程
然后 view 再处理各自的touch事件。
比如ScrollView,在touch事件中,会调整view的坐标,然后调用 invalidate 函数,函数最终会调用 requestNextVsync 触发 vsync ,vsync 回调doframe中绘制流程中,ScrollView根据新的坐标绘制界面,然后就看到了界面滚动。
事件分发到桌面图标的view后,view自身的点击事件中调用 startActivity 启动App。
二、APP创建进程
App到systemserver进程
Activity 的 startActivity 函数会调用到 ActivityTaskManagerService 的 startActivityAsUser 或者其他几个 start 方法
ActivityTaskManagerService.startActivityAsUser
—>ActivityStarter.execute
—>ActivityStarter.executeRequest
- 内部创建ActivityRecord : ActivityRecord r = new ActivityRecord.Builder(mService)
- ActivityRecord 继承 WindowToken
- Android 12 构造函数中 appToken = new Token
- Token extends IApplicationToken.Stub
- token,这个东西Android 11,Android12,Android13 这里的代码都不一样。
- Android 13 Token extends Binder
- ActivityRecord 没有 appToken 变量了,也是new Token,然后传递到 父类 WindowToken 中
- 由于构造函数中传递的DisplayContent为null,新创建的 ActivityRecord 还不会加入 DisplayContent 的HashMap对象 mTokenMap
- 内部创建ActivityRecord : ActivityRecord r = new ActivityRecord.Builder(mService)
—>ActivityStarter.startActivityUnchecked
—>ActivityStarter.startActivityInner
setNewTask
–>addOrReparentStartingActivity(task, “setTaskFromReuseOrCreateNewTask”); 把 ActivityRecord 添加到任务栈
- 给 ActivityRecord 添加 parent : parent.addChild(mStartActivity); ActivityRecord.getTask 返回的就是这个 targetTask
- addOrReparentStartingActivity 最终会把 ActivityRecord 加入到 DisplayContent .mTokenMap
mTargetRootTask.startActivityLocked
- 判断当前 activity 是否需要为其新建 Task,将 ActivityRecord 加入到对应的 Task 栈顶中
- ActivityRecord.showStartingWindow 启动过度界面
mTargetRootTask.moveToFront
RootWindowContainer.resumeFocusedTasksTopActivities===>转Task.resumeFocusedTasksTopActivities
mSupervisor.mRecentTasks.add(mStartActivity.getTask())
其他任务栈相关的处理
—> Task.resumeFocusedTasksTopActivities
—> Task.resumeTopActivityUncheckedLocked
—> Task.resumeTopActivityInnerLocked // 这里写是的Android12的流程,Android 13 这里不一样了
- ActivityRecord next = topRunningActivity(true /* focusableOnly */);
- —>如果有关联的进程,则直接调度生命周期:mAtmService.getLifecycleManager().scheduleTransaction(transaction);
- —>如果是新的activity【mTaskSupervisor.startSpecificActivity(next, true, true)】,事务添加 LaunchActivityItem Callback,用于app进程创建activity。如果没有进程还会创建进程
—>ActivityTaskSupervisor.startSpecificActivity
- —> 如果已有进程调用 realStartActivityLocked
- —>没有进程,创建进程流程:mService.startProcessAsync(r, knownToBeDead, isTop, isTop ? “top-activity” : “activity”);
–>ATMS.startProcessAsync
- startProcessAsync 只是把任务post给AMS,调用 AMS.startProcess
–>ActivityManagerInternal.startProcess
- ActivityManagerInternal.startProcess 是个抽象方法,实现是 ActivityManagerService.LocalService.startProcess
–>ActivityManagerService.LocalService.startProcessLocked
- 创建 HostingRecord ,并作为参数传给下一步
- HostingRecord .mHostingZygote 属性用于选择 zygote 类型
- HostingRecord 构造函数未传入 hostingZygote 参数,使用默认的 REGULAR_ZYGOTE ,即常规孵化器
ActivityManagerService.startProcessLocked 没啥内容,直接调用 ProcessList.startProcessLocked
–>16参数的ProcessList.startProcessLocked
- 处理 badProcess,连续崩溃超过2次会变成badProcess,后台禁止启动badProcess
- 处理隔离进程
- 处理不同App在同一个进程情况,App正在启动情况
- 正在启动的话,直接返回
- 处理App已经死亡,但是死亡通知还未到来的情况
- 处理系统还未启动完成情况,先把App存起来,之后处理
–>4参数的ProcessList.startProcessLocked 直接转发到6参数的 startProcessLocked
–>6参数的ProcessList.startProcessLocked 代码很多主要是设置启动参数
- 进程正在启动中,返回
- 记录启动开始的时间
- 清理参与的 死亡通知信息
- 清理mProcessesOnHold用于保存那些在系统还没有准备好就提前请求启动的ProcessRecord
- 更新 Profiler 信息
- 设置外存储挂载模式、设置App权限:gids
- 处理 manifest中设置了android:debuggable 信息,添加debug启动参数
- 设置 ABI、设置指令集、设置 selinux
- 设置App进程的启动入口为 “android.app.ActivityThread“
–>ProcessList.startProcess
- 启动准备
- 设置一些正在启动的标志
- 异步启动和同步启动,默认使用异步启动
–>ProcessList.handleProcessStart 异步启动
- 如果上一个App还没有死亡通知,则延迟启动,延迟时间最长默认 10 秒
- 正常情况直接调用 ProcessList.startProcess
–>ProcessList.startProcess
- 处理存储目录
- 选择创建App进程的孵化器,由于HostingRecord .mHostingZygote 为 REGULAR_ZYGOTE ,因此调用 Process.start
–>Process.start 没啥内容,直接调用 ZygoteProcess.start
–>ZygoteProcess.start
- 处理usap,usap启用的话,预创建APP进程,最大创建10个线程
- Android 13 由属性 dalvik.vm.usap_pool_enabled 决定是否启用usap,这个属性默认为false
- 之后调用 ZygoteProcess.startViaZygote
–>ZygoteProcess.startViaZygote 把参数封装成字符串
–>ZygoteProcess.zygoteSendArgsAndGetResult 处理一些字符串异常,并加入数据大小
- 调用 openZygoteSocketIfNeeded(abi) 连接 ZygoteServer ,根据ABI确定连接 zygote(zygote64) 还是 zygote_secondary(zygote32)
–>ZygoteProcess.attemptZygoteSendArgsAndGetResult 写完socket,接着后读socket –>zygoteWriter.write(msgStr);
–>使用socket 数据传输到 ZygoteServer
ZygoteServer进程
从Zygote启动讲起
ZygoteInit.main // Zygote 有两种启动方式,一种是启动system_server 一种启动App
- main函数
- 1、非懒加载情况下,预加载资源:jar,图形库,drawable、字体
- 2、创建zygote进程的socket server服务端对象 ZygoteServer
- 3、调用 ZygoteServer.runSelectLoop 进入死循环,等待 AMS 创建进程的socket消息(也会处理其他消息)
- 4、调用 runSelectLoop 返回的 Runnable.run 方法
- ZygoteServer.runSelectLoop
- ZygoteServer.acceptCommandPeer // 得到一个请求连接封装对象ZygoteConnection
- ZygoteConnection.processCommand //处理AMS客户端请求
- Zygote.forkSimpleApps // fork创建应用子进程,
- ZygoteCommandBuffer.forkRepeatedly // 进入native层后,调用 fork()
- Zygote.childMain
- ZygoteInit.zygoteInit // 开启 binder 消息监听 ,设置异常处理函数
- RuntimeInit.applicationInit
- RuntimeInit.findStaticMain
- return new MethodAndArgsCaller(m, argv);
MethodAndArgsCaller 对象不再继承Exception,仅仅继承Runnable,
MethodAndArgsCaller经过层层 return 后,返回 ZygoteInit.main ,
最后调用 MethodAndArgsCaller.run 方法 通过反射创建ActivityThread
对象并调用其“main
”入口方法。
ZygoteInit.main
1 | java复制代码ZygoteInit.main(String[] argv); |
ZygoteServer.runSelectLoop
1 | java复制代码Runnable runSelectLoop(String abiList); |
ZygoteConnection.processCommand
1 | java复制代码Runnable processCommand(ZygoteServer zygoteServer, boolean multipleOK); |
子进程调用 Zygote.childMain
1 | java复制代码// frameworks/base/core/java/com/android/internal/os/Zygote.java |
三、android.app.ActivityThread.main
1、ActivityThread.main 到 AMS 流程
1 | java复制代码ActivityThread.main |
2、scheduleTransaction 跨进程调用,把事务传递到 APP进程
1 | java复制代码ClientLifecycleManager.scheduleTransaction(ClientTransaction transaction); |
ActivityClientRecord.token = ClientTransaction.mActivityToken = ActivityRecord.token
经过一系列的 事务,生命周期管理相关的代码后 调用 handleLaunchActivity 和 handleResumeActivity
3、handleLaunchActivity
- 执行 Launch 生命周期
1 | java复制代码// frameworks/base/core/java/android/app/servertransaction/LaunchActivityItem.java |
4、handleResumeActivity
- 执行Resume生命周期
1 | java复制代码// frameworks/base/core/java/android/app/servertransaction/ResumeActivityItem.java |
setview之后看surface创建流程
四、ViewRootImpl 注册vsync回调
注册vsync回调流程:Choreographer
1 | java复制代码WindowManagerGlobal:: mGlobal.addView |
注册vsync回调流程:EventThread
Choreographer 构造函数创建 FrameDisplayEventReceiver 时,会创建同SurfaceFlinger的EventThread线程通信的 IDisplayEventConnection
IDisplayEventConnection定义了以下接口:
- void stealReceiveChannel(out BitTube outChannel);获取socket通信管道
- void setVsyncRate(in int count); 设置vsync分发速率。0,不调用requestNextVsync不分发;1,每次vsync事件都分发;其他,每N个vsync事件分发一次
- 系统默认为 0 ,不调用requestNextVsync不分发
- oneway void requestNextVsync(); 请求vsync
- ParcelableVsyncEventData getLatestVsyncEventData(); 获取最新的
获取到 IDisplayEventConnection 后,会立刻调用 stealReceiveChannel 获取socket通信管道
从 FrameDisplayEventReceiver 构造函数开始:
注册vsync回调流程:APP进程端
1 | c++复制代码Choreographer choreographer = new Choreographer(Looper.myLooper(), VSYNC_SOURCE_APP); |
注册vsync回调流程:SurfaceFlinger 进程端
BpSurfaceComposer.createDisplayEventConnection 跨进程进入 SurfaceFlinger 端
1 | c++复制代码// frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp |
五、ViewRootImpl.setView
注册 vsync 回调 IDisplayEventConnection
ViewRootImpl.setView 函数中调用 requestLayout 请求vsync流程
ViewRootImpl.setView 函数中调用 WindowSession.
addToDisplayAsUser
**创建 ISurfaceComposerClient **
- addToDisplayAsUser 还有个功能是 创建 InputChannel
传入一个null的 inputChannel 对象到 addToDisplayAsUser,这个 inputChannel ,在wms端创建,并赋值到inputChannel ,实际就是 socketpair
- vsync回调回来后 调用ViewRootImpl.**relayoutWindow 创建 Surface **
ViewRootImpl.requestLayout 请求vsync流程
衔接第三章的 setView
1 | java复制代码// frameworks/base/core/java/android/view/WindowManagerGlobal.java |
IWindowSession.addToDisplayAsUser–>WMS.addWindow
- 1、创建 WindowState
- 2、创建 InputChannel
- 3、创建同 SurfaceFlinger 的连接 ISurfaceComposerClient
- 4、更新焦点
1 | java复制代码root.setView(view, wparams, panelParentView, userId); |
六、vsync 回调
1、SurfaceFlinger进程端: vsync 事件分发
这里简单写写吧
1 | c++复制代码EventThread::onVSyncEvent(nsecs_t timestamp, VSyncSource::VSyncData vsyncData) |
2、APP进程端:接收vsync回调
1 | java复制代码epoll回调 |
3、ViewRootImpl.relayoutWindow 创建 Surface
1 | java复制代码ViewRootImpl.mTraversalRunnable.run() |
创建Surface:useBLAST (BBQ)
接续上一章节“useBLAST 的情况”
1 | java复制代码// frameworks/base/core/java/android/view/ViewRootImpl.java |
4、BLASTBufferQueue::createBufferQueue 生产者-消费者-BufferQueueCore
1 | c++复制代码// frameworks/native/libs/gui/BLASTBufferQueue.cpp |
七、SurfaceFlinger创建layer
Android 11 以及以前的版本简述:
1 | c++复制代码SurfaceFlinger::createLayer |
SurfaceFlinger::createLayer Android 13
- Android 12 以后因为BBQ都在APP进程,所以 createLayer 大大简化了,内容不多。
1 | c++复制代码【接续“ViewRootImpl.relayoutWindow 创建 Surface” 章节中的 “SurfaceComposerClient.createSurfaceChecked”】 |