明修"栈"道——越过Android启动栈陷阱( 四 )


Activity类::startActivity() 
→ startActivityForResult() 
→ Instrumentation类::execStartActivity() , 
返回值result则是ATMS
(ActivityTaskManagerService)执行的结果 。
 

明修"栈"道——越过Android启动栈陷阱

文章插图
 
如上图(标记2)标注 , ATMS类::startActivity()方法 , 返回了result=3 。
在system_process进程中 , 我们看一下这个result=3是怎样被赋值的 。略去详细断点步骤 , 实际堆栈如下图(标注1)所示:
ATMS类::startActivity() → startActivityAsUser() 
→ ActivityStarter类::execute() 
→ executeRequest() 
→ startActivityUnchecked() 
→ startActivityInner() 
→ recycleTask() , 在recycleTask()中返回了结果 。
 
明修"栈"道——越过Android启动栈陷阱

文章插图
 
如上图(标注2)所示 , result在mMovedToFrnotallow=false时被赋值 , 即result=START_DELIVERED_TO_TOP=3 , 而START_SUCCESS=0才代表创建成功 。
看一下源码中对START_DELIVERED_TO_TOP的说明 , 如下图:
 
明修"栈"道——越过Android启动栈陷阱

文章插图
 
Result for IActivityManaqer.startActivity: activity wasn't really started, but the given Intent was given to the existing top activity.
(IActivityManaqer.startActivityActivity的结果:Activity并未真正启动 , 但给定的Intent已提供给现有的顶层Activity 。)
“Activity并未真正启动”——是的 , 因为可以复用
“给定的Intent已提供给现有的顶层Activity”——实际没有 , 顶层Activity3并没有收到任何回调 , onNewIntent()未执行 , 甚至尝试通过Intent::putExtra()传入新的参数 , Activity3也没有收到 。官方文档又带给了我们一个疑问点?我们把这个问题记录下来 , 在后面分析 。
满足什么条件 , 才会造成
START_DELIVERED_TO_TOP的结果呢?笔者的思路是 , 通过与正常启动流程对比 , 找出差异点 。
3.3 过程断点 , 探索启动流程一般来说 , 在定位问题时 , 我们习惯通过结果反推原因 , 但反推的过程只能关注到与问题强关联的代码分支 , 并不能能使我们很好地了解全貌 。
所以 , 本节内容我们通过顺序阅读的方法 , 正向介绍startActivity过程中与上述【场景01234】强相关的逻辑 。再次简述一下:
  1. 【场景0】同一个Task内 , 从顶部B-3跳转B-2——停留在B-3
  2. 【场景1】从另一个Task内的C-4 , 跳转B-2——跳转到B-3
  3. 【场景2】把场景1中 , C-4跳转B-2的方式改为setClassName()——创建新B-2实例
  4. 【场景3】把场景1中 , C-4跳转B-2改为跳转B-3——创建新B-3实例
  5. 【场景4】给场景3中的B-3 , 指定taskAffinity——创建新Task和新B-3实例
3.3.1 流程源码概览
源码中 , 整个启动流程很长 , 涉及的方法和逻辑也很多 , 为了便于大家理清方法调用顺序 , 方便后续内容的阅读 , 笔者将本文涉及到的关键类及方法调用关系整理如下 。
后续阅读中如果不清楚调用关系 , 可以返回这里查看:
// ActivityStarter.JAVAActivityStarter::execute() {executeRequest(intent) {startActivityUnchecked() {startActivityInner();}}ActivityStarter::startActivityInner() {setInitialState();computeLaunchingTaskFlags();Task targetTask = getReusableTask(){findTask();}ActivityRecord targetTaskTop = targetTask.getTopNonFinishingActivity();if (targetTaskTop != null) {startResult = recycleTask() {setTargetRootTaskIfNeeded();complyActivityFlags();if (mAddingToTask) {return START_SUCCESS; //【场景2】【场景3】从recycleTask()返回}resumeFocusedTasksTopActivities()return mMovedToFront ? START_TASK_TO_FRONT : START_DELIVERED_TO_TOP;//【场景1】【场景0】从recycleTask()返回}} else {mAddingToTask = true;}if (startResult != START_SUCCESS) {return startResult;//【场景1】【场景0】从startActivityInner()返回}deliverToCurrentTopIfNeeded();resumeFocusedTasksTopActivities();return startResult;}


推荐阅读