问题:Android开机之后,很快就去启动应用播放视频,长按power key进入关机,但是有时候关机会花很长时间。
疑点:关机广播发送到接收时间较长;activity stack shutdown(activities finish)花费时间较长。
分析:关机flow主要集中在shutdownThread,加打印trace长按power键,Android关机flow。
背景:原生的shutdown关机分为high level(Android系统)和low level(kernel/driver),这里主要分析high level。
知识点:broadcast的发送和接收;activity进栈和退栈及启动模式的了解。
正常和异常打印时间戳:
一、BroadcastReceiver
- Broadcast的种类
- 并发和有序
- 前台和后台
- 系统和自定义
- BroadcastReceiver的注册方式
- 静态
- 动态
- Broadcast的发送:
- Broadcast的接收:
- BroadcastReceiver注册时序
原图链接:https://blog.csdn.net/u011733869/article/details/83796225
- Broadcast发送到接收的时序
原图链接:https://blog.csdn.net/u011733869/article/details/83834656
原图链接:https://blog.csdn.net/sinat_29255093/article/details/51817760
- shutdownBroadcast的时序 --待补
二、Activity
- activity的启动模式:standard、singleTop、singleTask、singleInstance
- ActivityStack、TaskStack、ActivityRecord
- 理清这三者之间的关系
原图链接:https://www.jianshu.com/p/94816e52cd77
原图链接:https://www.jianshu.com/p/94816e52cd77
dumpsys activity activities的抽取关键info如下:可以看到,
有三个stack,对应三个ActivityStack,StackId 0、1、2
ActivityStackId 2 ->TaskRecord Id 41->ActivityRecord:com.netflix.ninja/.MainActivity
ActivityStackId 0 ->TaskRecord Id 40->ActivityRecord:com.google.android.tvlauncher/.MainActivity
ActivityStackId 1 ->TaskRecord Id 39->ActivityRecord:com.google.com.customer.tv/.TVActivity
Stack #2: type=standard mode=fullscreen
.....
.....//此处省略
Running activities (most recent first):
TaskRecord{8329e0f #41 A=com.netflix.ninja U=0 StackId=2 sz=1}
Run #0: ActivityRecord{b66c2d7 u0 com.netflix.ninja/.MainActivity t41}
mResumedActivity: ActivityRecord{b66c2d7 u0 com.netflix.ninja/.MainActivity t41}
Stack #0: type=home mode=fullscreen
......
.....//此处省略
Running activities (most recent first):
TaskRecord{8500e9c #40 A=.TvLauncher U=0 StackId=0 sz=1}
Run #0: ActivityRecord{e12b727 u0 com.google.android.tvlauncher/.MainActivity t40}
mLastPausedActivity: ActivityRecord{e12b727 u0 com.google.android.tvlauncher/.MainActivity t40}
Stack #1: type=standard mode=fullscreen
......
......//此处省略
Running activities (most recent first):
TaskRecord{731f0a5 #39 A=com.customer.tv U=0 StackId=1 sz=1}
Run #0: ActivityRecord{7cf3c8e u0 com.customer.tv/.TVActivity t39}
mLastPausedActivity: ActivityRecord{7cf3c8e u0 com.customer.tv/.TVActivity t39}
ResumedActivity: ActivityRecord{b66c2d7 u0 com.netflix.ninja/.MainActivity t41}
mFocusedStack=ActivityStack{c33ec7a stackId=2 type=standard mode=fullscreen visible=true translucent=false, 1 tasks} mLastFocusedStack=ActivityStack{c33ec7a stackId=2 type=standard mode=fullscreen visible=true translucent=false, 1 tasks}
mCurTaskIdForUser={0=41}
mUserStackInFront={}
displayId=0 stacks=3
mHomeStack=ActivityStack{4850c2b stackId=0 type=home mode=fullscreen visible=false translucent=true, 1 tasks}
isHomeRecentsComponent=false KeyguardController:
mKeyguardShowing=false
mAodShowing=false
mKeyguardGoingAway=false
mOccluded=false
mDismissingKeyguardActivity=null
mDismissalRequested=false
mVisibilityTransactionDepth=0
LockTaskController
mLockTaskModeState=NONE
mLockTaskModeTasks=
mLockTaskPackages (userId:packages)=
u0:[]
- AMS shutdown耗时分析
- trace ams.shutdown源码可以看到分为四个部分做shutdown,打印时间戳,正常与异常log
三、小结
- 开机系统起来会有很多的后台广播:比如开机广播、网络变化广播、Timetick广播等。有些是并发广播,有些是有序广播。开机之后PKMS扫描清单文件里注册的Receiver(静态注册receiver,pkms先扫到的先接收到广播),AMS会将广播发送给相应的receiver处理,比如开机广播,有的要实现app自启动,这个会耗时,如果这个时候关机发送有序的关机广播,那就要等前一个receiver甚至前几个receiver接收处理完之后 才能轮到shutdownThread receiver接收处理关机广播(而且还要考虑priority),这样就会有概率性超时,如果开机之后等几分钟在去关机就不会出现关机广播超时的情况,因为那个时候基本上所有的开机广播都处理完了。
- 一方面shutdownThread的Broadcast推迟接收处理,另一方面开机自启动的应用很多,直观地dumpsys activity activities 也可以看到stackID=0,1,2;分别是tvlauncher、Netflix、TvActivity,那ActivityStackSupervisor作为ActivityStack的管理者,shutdown的时候需要分别将对应的stack做shutdown。耗时的部分还有ProcessStats.shutdown,包括后台进程,在shutdown之前都需要写进程状态,进程越多,花费的时候越多。
四、感悟
- 四大组件是基础,还是要夯实基础
- 学的知识点还是要记下来,多debug、多总结