ActivityManagerService解读之Activity启动三探--Activity中Task与Stack
简介
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=0taskId=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=0taskId=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=trueisSleeping=falsemBounds=nullTask id #142mFullscreen=truemBounds=nullmMinWidth=-1mMinHeight=-1mLastNonFullscreenBounds=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.launcher3affinity=com.android.settingsintent={act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.android.settings/.Settings}origActivity=com.android.settings/.SettingsrealActivity=com.android.settings/.SettingsautoRemoveRecents=false isPersistable=true numFullscreen=1 taskType=0 mTaskToReturnTo=1rootWasReset=true mNeverRelinquishIdentity=true mReuseTask=false mLockTaskAuth=LOCK_TASK_AUTH_PINNABLEActivities=[ActivityRecord{f46fe89 u0 com.android.settings/.Settings t142}]askedCompatMode=false inRecents=true isAvailable=truelastThumbnail=null lastThumbnailFile=/data/system_ce/0/recent_images/142_task_thumbnail.pngstackId=1hasBeenVisible=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.settingslaunchedFromUid=10014 launchedFromPackage=com.android.launcher3 userId=0app=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.settingsrealActivity=com.android.settings/.SettingsbaseDir=/system/priv-app/Settings/Settings.apkdataDir=/data/user_de/0/com.android.settingsstateNotNeeded=false componentSpecified=true mActivityType=0compat={160dpi always-compat} labelRes=0x7f120b06 icon=0x7f0800df theme=0x7f1301c8mLastReportedConfigurations: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=fff5f5f5backgroundColor=fffafafastatusBarColor=ff757575navigationBarColor=ff000000launchFailed=false launchCount=1 lastLaunchTime=-3m44s281mshaveState=false icicle=nullstate=RESUMED stopped=false delayedResume=false finishing=falsekeysPaused=false inHistory=true visible=true sleeping=false idle=true mStartingWindowState=STARTING_WINDOW_SHOWNfullscreen=true noDisplay=false immersive=false launchMode=2frozenBeforeDestroy=false forceNewConfig=falsemActivityType=APPLICATION_ACTIVITY_TYPEwaitingVisible=false nowVisible=true lastVisibleTime=-3m40s512msresizeMode=RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSIONmLastReportedMultiWindowMode=false mLastReportedPictureInPictureMode=falseRunning 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=trueisSleeping=falsemBounds=nullTask id #139mFullscreen=truemBounds=nullmMinWidth=-1mMinHeight=-1mLastNonFullscreenBounds=null* TaskRecord{b1b0e06 #139 I=com.android.launcher3/.Launcher U=0 StackId=0 sz=1}userId=0 effectiveUid=u0a14 mCallingUid=1000 mUserSetupComplete=true mCallingPackage=nullintent={act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10000100 cmp=com.android.launcher3/.Launcher}realActivity=com.android.launcher3/.LauncherautoRemoveRecents=false isPersistable=true numFullscreen=1 taskType=1 mTaskToReturnTo=0rootWasReset=false mNeverRelinquishIdentity=true mReuseTask=false mLockTaskAuth=LOCK_TASK_AUTH_PINNABLEActivities=[ActivityRecord{1f09444 u0 com.android.launcher3/.Launcher t139}]askedCompatMode=false inRecents=true isAvailable=truelastThumbnail=null lastThumbnailFile=/data/system_ce/0/recent_images/139_task_thumbnail.pngstackId=0hasBeenVisible=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.launcher3launchedFromUid=0 launchedFromPackage=null userId=0app=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=nullrealActivity=com.android.launcher3/.LauncherbaseDir=/system/priv-app/Launcher3Go/Launcher3Go.apkdataDir=/data/user/0/com.android.launcher3stateNotNeeded=true componentSpecified=false mActivityType=1compat={160dpi always-compat} labelRes=0x7f0c000d icon=0x7f020021 theme=0x7f120002mLastReportedConfigurations: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=fff5f5f5backgroundColor=fffafafastatusBarColor=0navigationBarColor=0launchFailed=false launchCount=0 lastLaunchTime=-1h38m41s610mshaveState=true icicle=Bundle[mParcelledData.dataSize=4096]state=STOPPED stopped=true delayedResume=false finishing=falsekeysPaused=false inHistory=true visible=false sleeping=false idle=true mStartingWindowState=STARTING_WINDOW_NOT_SHOWNfullscreen=true noDisplay=false immersive=false launchMode=2frozenBeforeDestroy=false forceNewConfig=falsemActivityType=HOME_ACTIVITY_TYPEwaitingVisible=false nowVisible=false lastVisibleTime=-43m15s482msresizeMode=RESIZE_MODE_RESIZEABLEmLastReportedMultiWindowMode=false mLastReportedPictureInPictureMode=falseRunning 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=falsemKeyguardGoingAway=falsemOccluded=falsemDismissingKeyguardActivity=nullmDismissalRequested=falsemVisibilityTransactionDepth=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的启动流程,又比如优化应用的启动速度等等。
ActivityManagerService解读之Activity启动三探--Activity中Task与Stack相关推荐
- 【Android 插件化】Hook 插件化框架 ( 从 Hook 应用角度分析 Activity 启动流程 一 | Activity 进程相关源码 )
Android 插件化系列文章目录 [Android 插件化]插件化简介 ( 组件化与插件化 ) [Android 插件化]插件化原理 ( JVM 内存数据 | 类加载流程 ) [Android 插件 ...
- 深入理解Activity启动流程(二)–Activity启动相关类的类图
本文原创作者:Cloud Chou. 欢迎转载,请注明出处和本文链接 本系列博客将详细阐述Activity的启动流程,这些博客基于Cm 10.1源码研究. 在介绍Activity的详细启动流程之前,先 ...
- 重拾Activity(三)Activity知识
这篇文章是从安卓开发者文档找到的Activity资料进行整理的(篇幅较长,用于个人回顾) 目录 这篇文章是从安卓开发者文档找到的Activity资料进行整理的(篇幅较长,用于个人回顾) Activit ...
- Activity启动另一个Activity并返回的完整生命周期
Android的简单基本问题,这里记录一下 从一个Activity创建后启动另一个Activity并返回的完整log输出: 从log可以看出,当前Activity启动另一个Activity时,总是要等 ...
- Activity(三)—— Activity的启动模式
Activity的启动模式 1 Activity的LaunchMode Activity为什么需要启动模式?在默认情况下,当我们多次启动同一个Activity的时候,系统会创建多个实例并把它们一一放入 ...
- Activity启动另一个Activity的方式总结
下面两种方式均采用这个menifests.xml布局,且下面两种方式属于显性方式{即通过使用(MainActivity.this, xxxx.class)}: 一,用intent构造器进行启动: 二, ...
- ActivityManagerService解读之Activity启动时间闲聊--Android Framework层时间计算介绍
从ActivityManagerService解读之Activity启动初探,到ActivityManagerService解读之Activity启动再探,到ActivityManagerServic ...
- ActivityManagerService解读之Activity启动初探
Activity是Android四大组建之一,负责用户交互界面展示,其重要性不可言喻.Android系统由ActivityManagerService负责管理Activity.熟悉Activity的启 ...
- 深入理解Activity启动流程(三)–Activity启动的详细流程2
本文原创作者:Cloud Chou. 欢迎转载,请注明出处和本文链接 本系列博客将详细阐述Activity的启动流程,这些博客基于Cm 10.1源码研究. 深入理解Activity启动流程(一)--A ...
- Activity启动过程源码流程梳理和解读
篇章目标要点 AMS(全称ActivityManagerService)作为四大组件的管理者,在Android系统工作流程当中起着非常重要的角色,四大组件当中Activity使用则又最为广泛,因为了解 ...
最新文章
- 剑指offer面试题6:重建二叉树
- vsftpd服务安装与虚拟用户配置
- [CentOS7] systemd
- Android 6.0 7.0 8.0 一个简单的app内更新版本-okgo app版本更新
- C语言基础:C语言宏定义(4) - 多文件编译
- Postgresql的HashJoin状态机流程图整理
- docker容器内没有yum命令_为什么不建议把数据库部署在Docker容器内?
- css优雅降级和渐进增强
- ajax同步异步问题
- MATLAB每个字母等宽,等宽文本文件的导入选项对象
- SpringBoot根据包名进行区分使用多数据源
- 图解机器学习算法(9) | GBDT模型详解(机器学习通关指南·完结)
- 电信跨域跨系统业务实践
- Openwrt:创建编译IPK软件包
- Centos文件夹目录中文变英文
- python画五环图_对Python安装及绘制五环图的初步认识,初识,pythonpython,与
- npm ERR! fatal: unable to access ‘https://github.com/adobe-webplatform/eve.git/‘: OpenSSL SSL_read:
- 量子纠缠的机制是什么?一定要理解整体性概念
- 客制化键盘编程_基于3D打印的客制化机械键盘设计与实现
- npm run build appeared(出现) Cannot find module ‘webpack/lib/ModuleFilenameHelpers‘
热门文章
- 亚马逊防关联方法适合shopee平台吗?
- VSCode远程控制服务器
- matlab心理学函数包,心理学研究方法:基于MATLAB和PSYCHTOOLBOX
- 主流编程语言的特点以及优缺点(一)
- springboot项目启动后执行方法
- ros系列—解决文件改名导致节点无法启动问题及ros::NodeHandle nh与nh(“~“)的理解
- 连接共享打印机时,弹出无法安装打印机,打印处理器不存在!!
- 《#华为云#听从你心,无问西东》及网友跟帖
- oracle detele,Oracle中,一个Delete操作的流程
- 访黏度计算公式_调节阀流量系数Kv的计算公式