惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Hugging Face - Blog
Hugging Face - Blog
Recent Announcements
Recent Announcements
V
Visual Studio Blog
博客园 - 叶小钗
H
Help Net Security
aimingoo的专栏
aimingoo的专栏
宝玉的分享
宝玉的分享
U
Unit 42
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
F
Fortinet All Blogs
V
V2EX
Stack Overflow Blog
Stack Overflow Blog
WordPress大学
WordPress大学
D
DataBreaches.Net
J
Java Code Geeks
H
Hackread – Cybersecurity News, Data Breaches, AI and More
A
About on SuperTechFans
酷 壳 – CoolShell
酷 壳 – CoolShell
量子位
C
Check Point Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
小众软件
小众软件
Microsoft Azure Blog
Microsoft Azure Blog
M
MIT News - Artificial intelligence

音视频开发进阶

音视频教程-第三节 音视频教程-第二节 真的,AI 可能就是新时代的信息差 充值 Cursor 之后,工作有了哪些变化?🤔 个人'蒸馏'大模型能做哪些有意思的事情 DeepSeek 大模型在 Mac 上的部署和运行 音视频教程-第一节 【WebRTC 专栏】-- Android 开发集成 WebRTC 库的几种方式 【WebRTC 专栏】-- 在 Mac M1 等系列芯片编译和开发 WebRTC-Android 库 Meta Llama3 大模型在 Mac 上的部署和运行 iOS VideoToolBox 解码 HEVC Open-GOP 视频的问题排查 Flutter 状态管理之 InheritedWidget 使用和分析 用 ChatGPT 回答技术问题怎么样 ? 音视频开发系统入门大致路线 UE 4.27 添加自定义 ShadingModel 用 UE4 虚幻引擎做个捏脸小功能~~ UE4 材质练习 之 凹凸贴图偏移的使用 UE4 材质练习系列基础 OpenGL上下文创建以及共享机制 007 | 播放器系列专栏-解析 MP4 文件读取信息 006 | 播放器系列专栏-在 Mac 上查看 MP4 格式信息 干货 | 快速抽取缩略图是怎么练成的? 关于直播、WebRTC、FFmpeg 的那些事 005 | 播放器系列专栏-在 Windows 上查看 MP4 格式信息 将音视频中的花屏、绿屏、黑屏问题一网打尽 关于音视频里面的解码帧率和渲染帧率 004 | 播放器系列专栏-认识MP4视频(下) 003 | 播放器系列专栏-认识MP4视频(上) 入门或者转行音视频,应该要怎么做? H264视频文件如何缩放分辨率
Android 6.0 Launcher 启动 Activity 过程分析小结(四)
音视频开发进阶 · 2017-12-22 · via 音视频开发进阶

一个专注音视频领域的小圈子

在如下三篇文章中过了一遍 Launcher 启动 Activity 的代码流程。

在 Launcher 进程内执行函数:

  • Launcher . startActivitySafely(View v, Intent intent, Object tag)

  • Launcher . startActivity(View v, Intent intent, Object tag)

  • Activity . startActivity(Intent intent, @Nullable Bundle options)

  • Activity . startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options)

  • Instrumentation . execStartActivity( Context who, IBinder contextThread, IBinder token, Activity target, Intent intent, int requestCode, Bundle options)

  • ActivityManagerProxy . startActivity(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle options)

Launcher 进程这部分执行的操作主要就是 委托ActivityManagerService 去启动一个 Activity 组件,把这个 Activity 组件的 Intent信息传递过去,把自己的包名信息传递过去,还把自己的本地 Binder 对象 ApplicationThread传递过去,以便 ActivityManagerService 可以通过它来联系到 Launcher 组件。

毕竟,当 ActivityManagerService 要去创建新的 Activity 组件时,首先得让之前的 Activity 组件进入 Paused状态。

Launcher 组件的运行流程从startActivitySafelystartActivity,再从 Activity 类的startActivitystartActivityForResult,最后通过 Instrumentation类的execStartActivity方法得到 ActivityManagerService 的代理对象 ActivityManagerProxy来执行startActivity。成功地把 Activity 组件启动的任务交给了 ActivityManagerService 去完成。

ActivityManagerService 进程

在 Launcher 进程内执行函数:

  • ActivityManagerService . startActivity(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle options)

  • ActivityManagerService . startActivityAsUser(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle options, int userId)

  • ActivityStackSupervisor . startActivityMayWait(…)

  • ActivityStackSupervisor . startActivityLocked( …)

  • ActivityStackSupervisor . startActivityUncheckedLocked( …)

  • ActivityStack . startActivityLocked(ActivityRecord r, boolean newTask, boolean doResume, boolean keepCurTransition, Bundle options)

  • ActivityStackSupervisor . resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target, Bundle targetOptions)

  • ActivityStack . resumeTopActivityLocked(ActivityRecord prev, Bundle options)

  • ActivityStack . resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options)

  • ActivityStackSupervisor . startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig)

ActivityManagerService 响应跨进程调用执行startActivity方法,方法内执行startActivityAsUser方法。

接着执行startActivityMayWait方法,首先通过 PackageManager解析待启动 Activity 的 Intent 信息,得到了包含更多信息的 ActivityInfo对象。

接着开始执行startActivityLocked方法,创建一个待启动的 Activity 组件的 ActivityRecord对象,里面包含了相关信息。在接下来的方法startActivityUncheckedLocked中为待启动的 Activity 组件找到它的 Task 任务,由于是新建的 Activity,则直接创建了一个新的 Task。而这个 Task也是 ActivityRecord的成员变量task。由这个 TaskRecord得到它的成员变量ActivityStack ,管理 Activity 的堆栈。

接下来便执行 ActivityStack类的startActivityLocked方法, 首先将待启动的 ActivityRecord 位于栈顶,然后执行 resumeTopActivitiesLocked方法,将所有 ActivityStack 栈顶的 ActivityRecord 运行至 Resumed 状态,其中都是调用的resumeTopActivityLocked方法,而该方法内部又是调用的resumeTopActivityInnerLocked方法,该方法会做一系列的判断,判断当年能够将 ActivityStack 栈顶的 Activity 运行至 Resumed状态,比如:当有 Activity 没有进入 Paused 状态时,便会通过跨进程通信来通知它进入 Paused 状态。当所有的状态都满足了,准备就绪了,就会去检查应用程序进程是否启动了,如果没有则去创建进程,否则让 Activity 组件运行至 Resumed 状态。

ActivityManagerService 创建应用程序进程

  • ActivityStackSupervisor . startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig)

  • ActivityManagerService . startProcessLocked(…)

  • ActivityManagerService . newProcessRecordLocked(ApplicationInfo info, String customProcess, boolean isolated, int isolatedUid)

  • ActivityManagerService . startProcessLocked(…)

startSpecificActivityLocked方法会创建应用程序进程,在 startProcessLocked方法内部根据进程名称和用户 ID 检查应用程序是否存在,不存在,则调用了newProcessRecordLocked方法创建了一个ProcessRecord对象,它包含了进程的基本信息,根据这个 ProcessRecord对象,在startProcessLocked函数的另一形式中去创建了应用程序进程。

当应用程序进程创建成功后,会得到一个大于 0 的进程 ID ,而 ActivityManagerService 就以这个 ID 为关键字将这个进程对应的 ProcessRecord 保存在变量mPidsSelfLocked中,以便 ActivityManagerService 可以根据这个 ID 找到该进程的记录信息。

当进程创建成功后,便会开始运行了,而 Java 程序的入口就是 main函数了。

Activity 应用程序进程启动

  • ActivityThread . main(…)

  • ActivityThread . attach(boolean system)

  • ActivityManagerService . attachApplication(IApplicationThread thread)

  • ActivityManagerService . attachApplicationLocked(IApplicationThread thread, int pid)

  • ApplicationThread . bindApplication(…)

  • ActivityThread . handleBindApplication(AppBindData data)

  • StackSupervisor . attachApplicationLocked(ProcessRecord app)

  • StackSupervisor . realStartActivityLocked(ActivityRecord r, ProcessRecord app, boolean andResume, boolean checkConfig)

  • ApplicationThread . scheduleLaunchActivity(…)

  • ActivityThread . handleLaunchActivity(ActivityClientRecord r, Intent customIntent)

  • ActivityThread . performLaunchActivity(ActivityClientRecord r, Intent customIntent)

  • ActivityThread . handleResumeActivity(IBinder token, boolean clearHide, boolean isForward, boolean reallyResume)

  • ActivityThread . performResumeActivity(IBinder token, boolean clearHide)

由于 Process 类的 start 方法指定了 ActivityThread 类的 main 方法作为一个进程的开始点,跟进 main 方法,初始化线程消息循环,并且在 attach方法中向 ActivityManagerService 跨进程发送请求,要求 ActivityManagerService 将当前进程添加 Application ,毕竟这还是个单纯的进程,并不是 Android 进程。

于是 ActivityManagerService 执行了 attachApplication方法响应这个跨进程请求,接着又继续调用了 attachApplicationLocked方法,从mPidsSelfLocked变量中根据 PID 找到 Activity 应用程序进程对应的 ProcessRecord 。然后将ProcessRecord绑定到应用进程,将ApplicationThread赋值给ProcessRecord的成员变量thread,这样就能 ActivityManagerService 就能通过它来和 Activity 通信了。

接下来 ActivityManagerService 又发起跨进程调用,通过 ApplicationThreadbindApplication方法。ActivityThread 主线程消息循环收到 Handler 发送的消息,响应方法为handleBindApplication。在此方法内,创建了Application 运行环境上下文Context、监控程序与系统交互的Instrumentation、应用程序的Application、并且调用了Application的 onCreate 方法。

当 ActivityManagerService 将 Activity 的 Application 创建完成后,又开始调度 Activity 的生命周期了。通过 StackSupervisor 类的 attachApplicationLocked方法,找到位于栈顶的 ActivityRecord对象,检查这个 Activity 组件的用户 ID 和进程名是否与 ProcessRecord 对象所描述的一致,如果一致,则调用realStartActivityLocked真正的开启一个 Activity 组件了。

开启一个 Activity 组件的生命周期当然是在应用程序进程内了,此时又是 ActivityManagerService 的跨进程通信,执行 ApplicationThread 的 scheduleLaunchActivity,ActivityThread 的消息循环响应方法为 handleLaunchActivity。在该方法内又继续执行 performLaunchActivity将 Activity 组件启动起来。通过反射创建了一个 Activity 对象,并且创建了 Activity 的运行环境上下文,通过 Instrumentation 执行了 Activity 的 onCreate 方法、onStart 方法。接着又执行了handleResumeActivity方法让 Activity 运行到 Resumed状态,真正执行操作的是performResumeActivity方法,而最终还是调用 Instrumentation类的callActivityOnResume方法。

至此,一个 Activity 组件就已经创建成功了,里面具体的代码细节暂不深入讨论了,比如 Activity 的加载之类的。

原创文章,转载请注明来源:    Android 6.0 Launcher 启动 Activity 过程分析小结(四)