android R版本应用程序启动过程源码分析

本文详细分析了Android R版本下应用程序启动过程,包括冷启动和热启动两种情况。冷启动涉及ActivityRecord、ActivityStack的创建,以及进程启动、暂停、恢复等步骤。热启动时,系统会查找复用栈并将其移到栈顶,然后恢复Activity。整个启动过程中,系统通过异步消息调度Activity的生命周期,并通过日志跟踪分析启动流程。
摘要由CSDN通过智能技术生成

        应用启动方式包括四种:Activity、Broadcast、Service、Provider四种安卓组件被唤醒和拉起时都可以造成进程启动。下面先主要以Activity启动为例来做个简要分析。

一、冷启动跳转新应用

1、 startActivity阶段       

        常见的Activity启动一般由startActivity发起,以桌面点击图库冷起为例,startActivity函数执行过程如下(冷启动执行reusedTask为空分支): 

08-24 20:58:18.744  1982  7944 I ActivityTaskManager: START u0 {act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.wtf.gallery3d/.app.MainActivity bnds=[48,1681][294,1992] (has extras)} from uid 10100

startActivity执行到系统侧时一般第一行日志输出的关键字是“START u”,u0代表要启动的页面是主用户0的,子用户就是u10、u11这种(子用户从10开始计算),该行日志还会打印发起请求的intent信息,表明所启动的组件目标,from uid代表发起startActivity的发起者的uid,可以根据命令adb shell ps -A|findstr u0_a100查询到uid是10100的进程是哪个,10100要转成u0_a100,a代表10000,如果是子用户进程就是u10_a100这种一次类推。如果该关键字日志不存在,则查看android源码对照Instrumentation.checkStartActivityResult函数中抛出的错误信息搜索判别是组件找不到、没权限启动、组件是应用私有未对外exported等具体原因,一般没有START u关键字就要从发起方和目标应用去排查。

在打印START u日志之后,ATMS这块会查找复用栈,由于冷起,所以没有复用栈,此时会新建ActivityRecord、ActivityStack(R版本开始全屏、悬浮窗等非分屏场景的ActivityStack就是作为Task在使用,二者是同一个对象,ActivityStack继承Task),这一点从以下dump信息也可以看出来:

创建完ActivityStack对象后会打印以下events日志,该日志表面栈id是3405:

08-24 20:58:18.759  1982  7944 I wm_stack_created: 3405

一个ActivityStack在构造时就会加到栈顶,此时并没有wm_focused_stack的events日志打印,因为创建完成后加到栈顶时传入的updateLastFocusedStackReason是null,不会造成events日志输出,而且即便紧接着还有一次moveToFront但由于栈顶对象还是刚才新创建的stack,所以也不会打印该events日志。

在将ActivityStack作为一个Task对象后,会打印以下events日志:

08-24 20:58:18.763  1982  7944 I wm_create_task: [0,3405]

注意,虽然前面很早就新建了ActivityRecord,但是wm_create_activity这个events日志并不是构造ActivityRecord时打印的,而是在wm_create_task之后才打印出来:

08-24 20:58:18.763  1982  7944 I wm_create_activity: [0,14228247,3405,com.wtf.gallery3d/.app.MainActivity,android.intent.action.MAIN,NULL,NULL,270532608]

在创建好各级数据结构并关联好上下级关系之后,才会真正去尝试resumeTopActivity去resume栈顶的ActivityRecord(此时栈顶就是要启动的图库应用),注意这个地方是尝试去resume,不代表真正能去resume成功,因为此时会判断是否有需要执行不可见的ActivityRecord要被pause,从桌面点击启动图库,显然需要把桌面pause掉,此时逻辑代码如下:

该处有两个pause尝试,pauseBackStacks代表要去把display上的其他栈尝试计算可见性判别是否需要pause,比如桌面点击图库跳转不同栈时,就需要执行这一步把桌面栈pause掉;而紧接着的startPausingLocked判断条件要求当前要resume的stack具有mResumedActivity,也就是说当前栈在前台可见了,只是栈内部有activity跳转,也就是说应用内部进行跳转执行这个pause。这两个pause动作无论执行哪一个都会有以下日志输出,当然这个仅仅是系统侧的分发pause的日志,还没到app侧执行onPause:

08-24 20:58:18.765  1982  7944 I wm_pause_activity: [0,225436362,com.wtf.launcher/.Launcher,userLeaving=true]

在发起对上一个应用也就是桌面的pause操作时,判断要resume的next也就是图库页面是没有进程存在的,需要新启动一下进程,此时会异步执行图库的进程拉起,至此startActivity函数就执行完毕了,其实可以看出来,startActivity此时执行了个寂寞,仅仅发起了对上一个应用的pause(异步,所有的生命周期调度到应用侧的都是oneway异步不等待的,参见IApplicationThread类带有oneway标记)和启动要拉起的页面的进程(异步),除此之外,别无他物。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值