简介
ActivityManagerService中对Activity的管理都是以Task的形式,任务Task是指在执行特定作业时与用户交互的一系列 Activity, 这些 Activity 按照各自的打开顺序排列在堆栈Stack中,AMS中分别以TaskRecord和ActivityStack表示,Activity则用ActivityRecord表示。因此我们也可以这么认为ActivityManagerService对Activity的管理,其实真正实现上来说是对ActivityStack,TaskRecord和ActivityRecord这三个数据结构的管理。更多详细的Task,Stack信息我们可以参考Google官网中Understand Tasks and Back Stack。
通常我们可以通过如下命令获取Android系统中Stack和Task的一些基本信息:
adb shell am stack list
Stack id=1 bounds=[0,0][240,320] displayId=0 userId=0
taskId=142: com.android.settings/com.android.settings.Settings bounds=[0,0][240,320] userId=0 visible=true topActivity=ComponentInfo{com.android.settings/com.android.settings.Settings}
Stack id=0 bounds=[0,0][240,320] displayId=0 userId=0
taskId=139: com.android.launcher3/com.android.launcher3.Launcher bounds=[0,0][240,320] userId=0 visible=false topActivity=ComponentInfo{com.android.launcher3/com.android.launcher3.Launcher}
如果我们想要获取对应Stack中Task以及Task中Activity的详细信息,比如Task中Activity的数量,Activity的启动Intent,Activity的启动模式等等,我们可以通过如下命令:
ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)
Display #0 (activities from top to bottom):
Stack #1:
mFullscreen=true
isSleeping=false
mBounds=null
Task id #142
mFullscreen=true
mBounds=null
mMinWidth=-1
mMinHeight=-1
mLastNonFullscreenBounds=null
* TaskRecord{32da96f #142 A=com.android.settings U=0 StackId=1 sz=1}
userId=0 effectiveUid=1000 mCallingUid=u0a14 mUserSetupComplete=true mCallingPackage=com.android.launcher3
affinity=com.android.settings
intent={act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.android.settings/.Settings}
origActivity=com.android.settings/.Settings
realActivity=com.android.settings/.Settings
autoRemoveRecents=false isPersistable=true numFullscreen=1 taskType=0 mTaskToReturnTo=1
rootWasReset=true mNeverRelinquishIdentity=true mReuseTask=false mLockTaskAuth=LOCK_TASK_AUTH_PINNABLE
Activities=[ActivityRecord{f46fe89 u0 com.android.settings/.Settings t142}]
askedCompatMode=false inRecents=true isAvailable=true
lastThumbnail=null lastThumbnailFile=/data/system_ce/0/recent_images/142_task_thumbnail.png
stackId=1
hasBeenVisible=true mResizeMode=RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION mSupportsPictureInPicture=false isResizeable=true firstActiveTime=1672808557 lastActiveTime=1672809402 (inactive for 223s)
* Hist #0: ActivityRecord{f46fe89 u0 com.android.settings/.Settings t142}
packageName=com.android.settings processName=com.android.settings
launchedFromUid=10014 launchedFromPackage=com.android.launcher3 userId=0
app=ProcessRecord{218dd1e 2581:com.android.settings/1000}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.android.settings/.Settings bnds=[159,155][237,242] }
frontOfTask=true task=TaskRecord{32da96f #142 A=com.android.settings U=0 StackId=1 sz=1}
taskAffinity=com.android.settings
realActivity=com.android.settings/.Settings
baseDir=/system/priv-app/Settings/Settings.apk
dataDir=/data/user_de/0/com.android.settings
stateNotNeeded=false componentSpecified=true mActivityType=0
compat={160dpi always-compat} labelRes=0x7f120b06 icon=0x7f0800df theme=0x7f1301c8
mLastReportedConfigurations:
mGlobalConfig={1.0 ?mcc?mnc [en_US] ldltr sw240dp w240dp h248dp 160dpi smll port -touch -keyb/v/h -nav/h appBounds=Rect(0, 0 - 240, 272) s.4}
mOverrideConfig={1.0 ?mcc?mnc [en_US] ldltr sw240dp w240dp h248dp 160dpi smll port -touch -keyb/v/h -nav/h appBounds=Rect(0, 0 - 240, 272) s.4}
CurrentConfiguration={1.0 ?mcc?mnc [en_US] ldltr sw240dp w240dp h248dp 160dpi smll port -touch -keyb/v/h -nav/h appBounds=Rect(0, 0 - 240, 272) s.4}
taskDescription: iconFilename=/data/system_ce/0/recent_images/142_activity_icon_1672808529.png label="null" primaryColor=fff5f5f5
backgroundColor=fffafafa
statusBarColor=ff757575
navigationBarColor=ff000000
launchFailed=false launchCount=1 lastLaunchTime=-3m44s281ms
haveState=false icicle=null
state=RESUMED stopped=false delayedResume=false finishing=false
keysPaused=false inHistory=true visible=true sleeping=false idle=true mStartingWindowState=STARTING_WINDOW_SHOWN
fullscreen=true noDisplay=false immersive=false launchMode=2
frozenBeforeDestroy=false forceNewConfig=false
mActivityType=APPLICATION_ACTIVITY_TYPE
waitingVisible=false nowVisible=true lastVisibleTime=-3m40s512ms
resizeMode=RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION
mLastReportedMultiWindowMode=false mLastReportedPictureInPictureMode=false
Running activities (most recent first):
TaskRecord{32da96f #142 A=com.android.settings U=0 StackId=1 sz=1}
Run #0: ActivityRecord{f46fe89 u0 com.android.settings/.Settings t142}
mResumedActivity: ActivityRecord{f46fe89 u0 com.android.settings/.Settings t142}
Stack #0:
mFullscreen=true
isSleeping=false
mBounds=null
Task id #139
mFullscreen=true
mBounds=null
mMinWidth=-1
mMinHeight=-1
mLastNonFullscreenBounds=null
* TaskRecord{b1b0e06 #139 I=com.android.launcher3/.Launcher U=0 StackId=0 sz=1}
userId=0 effectiveUid=u0a14 mCallingUid=1000 mUserSetupComplete=true mCallingPackage=null
intent={act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10000100 cmp=com.android.launcher3/.Launcher}
realActivity=com.android.launcher3/.Launcher
autoRemoveRecents=false isPersistable=true numFullscreen=1 taskType=1 mTaskToReturnTo=0
rootWasReset=false mNeverRelinquishIdentity=true mReuseTask=false mLockTaskAuth=LOCK_TASK_AUTH_PINNABLE
Activities=[ActivityRecord{1f09444 u0 com.android.launcher3/.Launcher t139}]
askedCompatMode=false inRecents=true isAvailable=true
lastThumbnail=null lastThumbnailFile=/data/system_ce/0/recent_images/139_task_thumbnail.png
stackId=0
hasBeenVisible=true mResizeMode=RESIZE_MODE_RESIZEABLE mSupportsPictureInPicture=false isResizeable=true firstActiveTime=1667109722 lastActiveTime=1672808679 (inactive for 224s)
* Hist #0: ActivityRecord{1f09444 u0 com.android.launcher3/.Launcher t139}
packageName=com.android.launcher3 processName=com.android.launcher3
launchedFromUid=0 launchedFromPackage=null userId=0
app=ProcessRecord{31ae0ef 3012:com.android.launcher3/u0a14}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10000100 cmp=com.android.launcher3/.Launcher }
frontOfTask=true task=TaskRecord{b1b0e06 #139 I=com.android.launcher3/.Launcher U=0 StackId=0 sz=1}
taskAffinity=null
realActivity=com.android.launcher3/.Launcher
baseDir=/system/priv-app/Launcher3Go/Launcher3Go.apk
dataDir=/data/user/0/com.android.launcher3
stateNotNeeded=true componentSpecified=false mActivityType=1
compat={160dpi always-compat} labelRes=0x7f0c000d icon=0x7f020021 theme=0x7f120002
mLastReportedConfigurations:
mGlobalConfig={1.0 ?mcc?mnc [en_US] ldltr sw240dp w240dp h248dp 160dpi smll port -touch -keyb/v/h -nav/h appBounds=Rect(0, 0 - 240, 272) s.4}
mOverrideConfig={1.0 ?mcc?mnc [en_US] ldltr sw240dp w240dp h248dp 160dpi smll port -touch -keyb/v/h -nav/h appBounds=Rect(0, 0 - 240, 272) s.4}
CurrentConfiguration={1.0 ?mcc?mnc [en_US] ldltr sw240dp w240dp h248dp 160dpi smll port -touch -keyb/v/h -nav/h appBounds=Rect(0, 0 - 240, 272) s.4}
taskDescription: iconFilename=null label="null" primaryColor=fff5f5f5
backgroundColor=fffafafa
statusBarColor=0
navigationBarColor=0
launchFailed=false launchCount=0 lastLaunchTime=-1h38m41s610ms
haveState=true icicle=Bundle[mParcelledData.dataSize=4096]
state=STOPPED stopped=true delayedResume=false finishing=false
keysPaused=false inHistory=true visible=false sleeping=false idle=true mStartingWindowState=STARTING_WINDOW_NOT_SHOWN
fullscreen=true noDisplay=false immersive=false launchMode=2
frozenBeforeDestroy=false forceNewConfig=false
mActivityType=HOME_ACTIVITY_TYPE
waitingVisible=false nowVisible=false lastVisibleTime=-43m15s482ms
resizeMode=RESIZE_MODE_RESIZEABLE
mLastReportedMultiWindowMode=false mLastReportedPictureInPictureMode=false
Running activities (most recent first):
TaskRecord{b1b0e06 #139 I=com.android.launcher3/.Launcher U=0 StackId=0 sz=1}
Run #0: ActivityRecord{1f09444 u0 com.android.launcher3/.Launcher t139}
mLastPausedActivity: ActivityRecord{1f09444 u0 com.android.launcher3/.Launcher t139}
Display #1 (activities from top to bottom):
ResumedActivity: ActivityRecord{f46fe89 u0 com.android.settings/.Settings t142}
mFocusedStack=ActivityStack{4f3c6a8 stackId=1, 1 tasks} mLastFocusedStack=ActivityStack{4f3c6a8 stackId=1, 1 tasks}
mCurTaskIdForUser={0=142}
mUserStackInFront={}
mStacks={0=ActivityStack{7020d13 stackId=0, 1 tasks}, 1=ActivityStack{4f3c6a8 stackId=1, 1 tasks}}
mLockTaskModeState=NONE mLockTaskPackages (userId:packages)=
0:[]
mLockTaskModeTasks[]
KeyguardController:
mKeyguardShowing=false
mKeyguardGoingAway=false
mOccluded=false
mDismissingKeyguardActivity=null
mDismissalRequested=false
mVisibilityTransactionDepth=0
至于为什么使用如上命令就能获取这么多的信息,建议还是去多多的阅读系统源码,或许我们可以找到我们想要的答案。
ActivityManagerService中的Stack
Android系统中一些常用的Stack
Name | Value | Description |
HOME_STACK_ID | 0 | 一般HomeActivity所在的Stack,就是Launcher所在的Stack |
FULLSCREEN_WORKSPACE_STACK_ID | 1 | 正常情况下,我们启动的Activity都在这个Stack |
FREEFORM_WORKSPACE_STACK_ID | 2 | 自由模式下,一般平板中会使用 |
DOCKED_STACK_ID | 3 | 进入分屏模式后,新创建的便是该类型的Stack |
PINNED_STACK_ID | 4 | 画中画模式下,处于画中画Activity所在的Stack |
RECENTS_STACK_ID | 5 | SystemUI的RecentActivity所在的Stack |
ASSISTANT_STACK_ID | 6 | 有Android assistant启动的Activity都在此Stack,国内手机貌似很少使用该Stack |
从这些常用的Stack的作用上来看,我们可以简单的理解Android更多的会根据各种不同的行为和场景来区分不同的ActivityStack。从之前的dump信息我们便可以断定ActivityStack中主要存放的就是各种Task,对应的便是TaskRecord,实际Android代码中也确实如此。对于ActivityStack的各种管理,Android又抽象出ActivityStackSupervisor类,我们从命名中也可以看出该类专门负责ActivityStack的管理。后续Activity的启动流程分析中,我们将更多的接触并分析该类。一般Android系统启动时,开机启动到Launcher界面,便会创建HOME_STACK_ID Stack(下面便是开机的Trace Log,可以结合Trace和代码具体理一下这个创建的过程,这里就不再细述了)专门用于存放Home Activity。
01-20 23:40:35.110 1964 1964 D ABM_TRACE_MAIN: java.lang.Throwable
01-20 23:40:35.110 1964 1964 D ABM_TRACE_MAIN: at com.android.server.am.ActivityStack.<init>(ActivityStack.java:458)
01-20 23:40:35.110 1964 1964 D ABM_TRACE_MAIN: at com.android.server.am.ActivityStackSupervisor.createStack(ActivityStackSupervisor.java:2657)
01-20 23:40:35.110 1964 1964 D ABM_TRACE_MAIN: at com.android.server.am.ActivityStackSupervisor.createStackOnDisplay(ActivityStackSupervisor.java:2648)
01-20 23:40:35.110 1964 1964 D ABM_TRACE_MAIN: at com.android.server.am.ActivityStackSupervisor.getStack(ActivityStackSupervisor.java:2251)
01-20 23:40:35.110 1964 1964 D ABM_TRACE_MAIN: at com.android.server.am.ActivityStackSupervisor.setWindowManager(ActivityStackSupervisor.java:689)
01-20 23:40:35.110 1964 1964 D ABM_TRACE_MAIN: at com.android.server.am.ActivityManagerService.setWindowManager(ActivityManagerService.java:2629)
01-20 23:40:35.110 1964 1964 D ABM_TRACE_MAIN: at com.android.server.SystemServer.startOtherServices(SystemServer.java:861)
01-20 23:40:35.110 1964 1964 D ABM_TRACE_MAIN: at com.android.server.SystemServer.run(SystemServer.java:398)
01-20 23:40:35.110 1964 1964 D ABM_TRACE_MAIN: at com.android.server.SystemServer.main(SystemServer.java:274)
01-20 23:40:35.110 1964 1964 D ABM_TRACE_MAIN: at java.lang.reflect.Method.invoke(Native Method)
01-20 23:40:35.110 1964 1964 D ABM_TRACE_MAIN: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
01-20 23:40:35.110 1964 1964 D ABM_TRACE_MAIN: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:787)
01-20 23:40:35.129 1964 1964 I wm_stack_created: 0
01-20 23:40:35.140 1964 1964 D ABM_TRACE_MAIN: java.lang.Throwable
01-20 23:40:35.140 1964 1964 D ABM_TRACE_MAIN: at com.android.server.am.ActivityStackSupervisor$ActivityDisplay.attachStack(ActivityStackSupervisor.java:4749)
01-20 23:40:35.140 1964 1964 D ABM_TRACE_MAIN: at com.android.server.am.ActivityStack.postAddToDisplay(ActivityStack.java:514)
01-20 23:40:35.140 1964 1964 D ABM_TRACE_MAIN: at com.android.server.am.ActivityStack.<init>(ActivityStack.java:472)
01-20 23:40:35.140 1964 1964 D ABM_TRACE_MAIN: at com.android.server.am.ActivityStackSupervisor.createStack(ActivityStackSupervisor.java:2657)
01-20 23:40:35.140 1964 1964 D ABM_TRACE_MAIN: at com.android.server.am.ActivityStackSupervisor.createStackOnDisplay(ActivityStackSupervisor.java:2648)
01-20 23:40:35.140 1964 1964 D ABM_TRACE_MAIN: at com.android.server.am.ActivityStackSupervisor.getStack(ActivityStackSupervisor.java:2251)
01-20 23:40:35.140 1964 1964 D ABM_TRACE_MAIN: at com.android.server.am.ActivityStackSupervisor.setWindowManager(ActivityStackSupervisor.java:689)
01-20 23:40:35.140 1964 1964 D ABM_TRACE_MAIN: at com.android.server.am.ActivityManagerService.setWindowManager(ActivityManagerService.java:2629)
01-20 23:40:35.140 1964 1964 D ABM_TRACE_MAIN: at com.android.server.SystemServer.startOtherServices(SystemServer.java:861)
01-20 23:40:35.140 1964 1964 D ABM_TRACE_MAIN: at com.android.server.SystemServer.run(SystemServer.java:398)
01-20 23:40:35.140 1964 1964 D ABM_TRACE_MAIN: at com.android.server.SystemServer.main(SystemServer.java:274)
01-20 23:40:35.140 1964 1964 D ABM_TRACE_MAIN: at java.lang.reflect.Method.invoke(Native Method)
01-20 23:40:35.140 1964 1964 D ABM_TRACE_MAIN: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
01-20 23:40:35.140 1964 1964 D ABM_TRACE_MAIN: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:787)
01-20 23:40:35.141 1964 1964 V ABM_Log : attachStack: attaching ActivityStack{abbc88a stackId=0, 0 tasks} to displayId=0 position=0
一般我们可以通过event log可以获取ActivityStack的创建与销毁
wm_stack_created (StackId|1|5)
wm_task_removed (TaskId|1|5),(Reason|3)
虽然这是WindowManagerService相关的Log,但是Window在组织和管理各种窗口时ActivityManagerService管理Activity一样都是通过各种堆栈形式的,并且WindowManagerService里面对应的堆栈顺序都是和ActivityManagerService中保持一致的,他们在Activity启动时创建的顺序也是一前一后的,其中相关的数据结构的对应关系如下:
ActivityStack TaskStack
TaskRecord Task
ActivityRecord APPWindowToken
一般我们在创建Activity时,根据不同功能的需要,创建对应或使用不同的ActivityStack,一般使用ActivityStackSupervisor.getStack去获取,如果不存在便创建新的。对应的当我们Activity销毁的时候,Android系统会从该Activity所在的Task中移除该Activity,如果该Activity是lastActivity,系统还会从ActivityStack中移除该Task,如果从ActivityStack移除完该Task之后,ActivityStack中不存在任何Task,系统还会将该ActivityStack销毁回收。
ActivityManagerService中的Task
Activity启动过程中,对于ActivityStack应用开发者很少接触, 我们也可以不去关注它的创建与销毁,更多的这都是系统完成的。通过前文ActivityManagerService解读之Activity启动再探所述,我们知道可以更多的使用不同的启动模式,外加各种Task属性和设置不同的Intent flag来影响Activity Task的创建管理行为。比如每次需要Activity创建单独的Task时您可以使用singleInstance模式,等等(更多关于启动模式和Task属性以及不同intent flag请参阅ActivityManagerService解读之Activity启动再探一文)。当我们启动Activity或者销毁Activity时,系统为该Activity创建Task或者销毁Task时候,我们一般会看见如下Log:
wm_task_created (TaskId|1|5),(StackId|1|5)
am_create_task (User|1|5),(Task ID|1|5)
wm_task_removed (TaskId|1|5),(Reason|3)
Task是从用户角度来管理Activity的,Android系统更多的是根据用户的操作来将一系列Activity按启动顺序放于同一个Task中,这些Activity可以来自不同的应用,因为从用户角度来说,这些操作只是为自己服务而已,用户并不知道他们来自不同的应用。
写在最后
ActivityStack和TaskRecord是ActivityManagerService管理Activity的两个相当重要的数据,了解他们的作用对分析Activity启动大有作用,懂得Activity启动流程,在日常项目开发中才能应对各种需求,实施各种不同的应对方案,比如最近很火的插件技术,想要插件话Activity,必须得了解Activity的启动流程,又比如优化应用的启动速度等等。