Android ActivityManager

这篇文章记录下自己在解决ActivityManager相关bug过程的一些心得。

1. Activity管理

ActivityManagerService以task stack的概念来管理着Activity。每一个Activity都属于一个task,一个task可以看成是一系列Activity的集合。task内部使用stack的概念进行管理。每次切换到新的Activity的时候,都会将Activity所属的task切换到前台,并将Activity置于栈顶,之后才会进行resume过程。

所有的task共同存在于一个ArrayList中,每当发生task切换的时候,都需要执行ArrayList的删除和移动工作。 task与Activity之间的关系见下图:

在上图中,A,B,C,D,E,F代表着四个Activity。颜色相同的Activity属于一个task。F位于栈顶,表示用于当前交互的Activity,F所属的task也称之为前台task。所以从图中也可以看出,task只是一个概念上的划分,并没有额外的数据结构单独来实现。stack是以ArrayList的方式实现,index 为0的Activty A位于栈底,index为5的Activity位于栈顶。

当在F中startActivity A的时候会发生什么场景了?栈的情况又会发生什么变化?这就设计到Activity的launchMode和Intent中的启动flag取值了。关于这一部分的介绍可以参考:Tasks and Back Stack

下面以一张图来对Tasks and Back Stack这篇文章作一点补充:

上图中,启动Activity的Intent flag都采取默认值。 站在ActivityManagerService的角度来说,启动一个Activity的就是根据发起startActivity调用的Activity的属性,目标Activity的属性,以及Intent的flag标记来决定目标Activity在task stack中的位置。关于这一部分的源码在:ActivityStack.java的startActivityUncheckedLocked方法中完成。

一个Activity启动另外一个Activity的简图大致如下:

2. dumpsys Activity的分析

使用dumpsys activity activities命令可以dump出当前系统中Activity的stack情况。一个典型的输出信息如下:

ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)
  Main stack:
  * TaskRecord{410ff038 #2 A com.android.launcher U 0}
    numActivities=1 rootWasReset=true userId=0
    affinity=com.android.launcher
    intent={act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10600000 cmp=com.android.launcher/com.android.launcher2.Launcher}
    realActivity=com.android.launcher/com.android.launcher2.Launcher
    askedCompatMode=false
    lastThumbnail=null lastDescription=null
    lastActiveTime=12791687 (inactive for 4s)
    * Hist #2: ActivityRecord{410f8738 u0 com.android.launcher/com.android.launcher2.Launcher}
        packageName=com.android.launcher processName=com.android.launcher
        launchedFromUid=0 userId=0
        app=ProcessRecord{410ffa10 418:com.android.launcher/u0a10020}
        Intent { act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10000000 cmp=com.android.launcher/com.android.launcher2.Launcher }
        frontOfTask=true task=TaskRecord{410ff038 #2 A com.android.launcher U 0}
        taskAffinity=com.android.launcher
        realActivity=com.android.launcher/com.android.launcher2.Launcher
        baseDir=/system/app/Launcher2.apk
        dataDir=/data/user/0/com.android.launcher
        stateNotNeeded=true componentSpecified=false isHomeActivity=true
        compat={160dpi always-compat} labelRes=0x7f0d0000 icon=0x7f030001 theme=0x7f0e0001
        config={1.0 310mcc260mnc en_US ldltr sw320dp w320dp h455dp 160dpi nrml port -touch -keyb/v/h tball/v s.6}
        launchFailed=false haveState=false icicle=null
        state=RESUMED stopped=false delayedResume=false finishing=false
        keysPaused=false inHistory=true visible=true sleeping=false idle=true
        fullscreen=true noDisplay=false immersive=false launchMode=2
        frozenBeforeDestroy=false thumbnailNeeded=false forceNewConfig=false
        thumbHolder: 410ff038 bm=null desc=null
        waitingVisible=false nowVisible=true lastVisibleTime=-3s487ms
  * TaskRecord{4120ab18 #8 A com.android.providers.downloads.ui U 0}
    numActivities=1 rootWasReset=true userId=0
    affinity=com.android.providers.downloads.ui
    intent={act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.android.providers.downloads.ui/.DownloadList bnds=[240,187][314,269]}
    realActivity=com.android.providers.downloads.ui/.DownloadList
    askedCompatMode=false
    lastThumbnail=null lastDescription=null
    lastActiveTime=12791673 (inactive for 4s)
    * Hist #1: ActivityRecord{41210098 u0 com.android.providers.downloads.ui/.DownloadList}
        packageName=com.android.providers.downloads.ui processName=android.process.media
        launchedFromUid=10020 userId=0
        app=ProcessRecord{4116a5d8 4349:android.process.media/u0a10023}
        Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.android.providers.downloads.ui/.DownloadList bnds=[240,187][314,269] }
        frontOfTask=true task=TaskRecord{4120ab18 #8 A com.android.providers.downloads.ui U 0}
        taskAffinity=com.android.providers.downloads.ui
        realActivity=com.android.providers.downloads.ui/.DownloadList
        baseDir=/system/app/DownloadProviderUi.apk
        dataDir=/data/data/com.android.providers.downloads.ui
        stateNotNeeded=false componentSpecified=true isHomeActivity=false
        compat={160dpi always-compat} labelRes=0x7f070000 icon=0x7f030000 theme=0x1030077
        config={1.0 310mcc260mnc en_US ldltr sw320dp w320dp h455dp 160dpi nrml port -touch -keyb/v/h tball/v s.6}
        launchFailed=false haveState=true icicle=Bundle[mParcelledData.dataSize=1740]
        state=STOPPED stopped=true delayedResume=false finishing=false
        keysPaused=false inHistory=true visible=false sleeping=false idle=true
        fullscreen=true noDisplay=false immersive=false launchMode=1
        frozenBeforeDestroy=false thumbnailNeeded=false forceNewConfig=false
        thumbHolder: 4120ab18 bm=null desc=null
        waitingVisible=false nowVisible=false lastVisibleTime=-5s589ms
  * TaskRecord{41138f80 #7 A android.task.contacts U 0}
    numActivities=1 rootWasReset=true userId=0
    affinity=android.task.contacts
    intent={act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.android.contacts/.activities.PeopleActivity bnds=[84,387][158,469]}
    realActivity=com.android.contacts/.activities.PeopleActivity
    askedCompatMode=false
    lastThumbnail=null lastDescription=null
    lastActiveTime=12785119 (inactive for 10s)
    * Hist #0: ActivityRecord{40fedda0 u0 com.android.contacts/.activities.PeopleActivity}
        packageName=com.android.contacts processName=com.android.contacts
        launchedFromUid=10020 userId=0
        app=ProcessRecord{4104ceb0 4288:com.android.contacts/u0a10009}
        Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.android.contacts/.activities.PeopleActivity bnds=[84,387][158,469] }
        frontOfTask=true task=TaskRecord{41138f80 #7 A android.task.contacts U 0}
        taskAffinity=android.task.contacts
        realActivity=com.android.contacts/.activities.PeopleActivity
        baseDir=/system/app/Contacts.apk
        dataDir=/data/data/com.android.contacts
        stateNotNeeded=false componentSpecified=true isHomeActivity=false
        compat={160dpi always-compat} labelRes=0x7f0b000b icon=0x7f030000 theme=0x7f0f0007
        config={1.0 310mcc260mnc en_US ldltr sw320dp w320dp h455dp 160dpi nrml port -touch -keyb/v/h tball/v s.6}
        launchFailed=false haveState=true icicle=Bundle[mParcelledData.dataSize=5608]
        state=STOPPED stopped=true delayedResume=false finishing=false
        keysPaused=false inHistory=true visible=false sleeping=false idle=true
        fullscreen=true noDisplay=false immersive=false launchMode=1
        frozenBeforeDestroy=false thumbnailNeeded=false forceNewConfig=false
        thumbHolder: 41138f80 bm=null desc=null
        waitingVisible=false nowVisible=false lastVisibleTime=-12s455ms

  Running activities (most recent first):
    TaskRecord{410ff038 #2 A com.android.launcher U 0}
      Run #2: ActivityRecord{410f8738 u0 com.android.launcher/com.android.launcher2.Launcher}
    TaskRecord{4120ab18 #8 A com.android.providers.downloads.ui U 0}
      Run #1: ActivityRecord{41210098 u0 com.android.providers.downloads.ui/.DownloadList}
    TaskRecord{41138f80 #7 A android.task.contacts U 0}
      Run #0: ActivityRecord{40fedda0 u0 com.android.contacts/.activities.PeopleActivity}

  mResumedActivity: ActivityRecord{410f8738 u0 com.android.launcher/com.android.launcher2.Launcher}
  mFocusedActivity: ActivityRecord{410f8738 u0 com.android.launcher/com.android.launcher2.Launcher}
  mLastPausedActivity: ActivityRecord{41210098 u0 com.android.providers.downloads.ui/.DownloadList}
  mSleepTimeout: false
  mDismissKeyguardOnNextActivity: false

  Recent tasks:
  * Recent #0: TaskRecord{410ff038 #2 A com.android.launcher U 0}
    numActivities=1 rootWasReset=true userId=0
    affinity=com.android.launcher
    intent={act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10600000 cmp=com.android.launcher/com.android.launcher2.Launcher}
    realActivity=com.android.launcher/com.android.launcher2.Launcher
    askedCompatMode=false
    lastThumbnail=null lastDescription=null
    lastActiveTime=12791687 (inactive for 4s)
  * Recent #1: TaskRecord{4120ab18 #8 A com.android.providers.downloads.ui U 0}
    numActivities=1 rootWasReset=true userId=0
    affinity=com.android.providers.downloads.ui
    intent={act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.android.providers.downloads.ui/.DownloadList bnds=[240,187][314,269]}
    realActivity=com.android.providers.downloads.ui/.DownloadList
    askedCompatMode=false
    lastThumbnail=null lastDescription=null
    lastActiveTime=12791673 (inactive for 4s)
  * Recent #2: TaskRecord{41138f80 #7 A android.task.contacts U 0}
    numActivities=1 rootWasReset=true userId=0
    affinity=android.task.contacts
    intent={act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.android.contacts/.activities.PeopleActivity bnds=[84,387][158,469]}
    realActivity=com.android.contacts/.activities.PeopleActivity
    askedCompatMode=false
    lastThumbnail=null lastDescription=null
    lastActiveTime=12785119 (inactive for 10s)
  * Recent #3: TaskRecord{41230588 #6 A com.android.systemui U 0}
    affinity=com.android.systemui
    intent={act=com.android.systemui.recent.action.TOGGLE_RECENTS flg=0x10800000 cmp=com.android.systemui/.recent.RecentsActivity}
    realActivity=com.android.systemui/.recent.RecentsActivity
    askedCompatMode=false
    lastThumbnail=null lastDescription=null
    lastActiveTime=12774793 (inactive for 21s)

  mCurTask: 8
  • Main stack,dump了Activity的排列顺序和相关信息

  • TaskRecord表示Activity所属的task,一条TaskRecord记录表示了TaskRecord的id,名字,以及所属的用户。比如TaskRecord{410ff038 #2 A com.android.launcher U 0}表示此TaskRecord的hashcode为410ff038,它的id为2,它的名字为com.android.launcher,它所属的用户id为0.

  • Hist #N 表示Activity位于history stack中N的位置。N越大表示越靠近栈顶

  • ActivityRecord对应着一个Activity的记录,其中Intent描述了启动这个Activity的Intent信息。如果调用了startActivity,但是由于某种原因,此时这个Activity还不适宜在前台显示,那么就会有一个pending intent的记录

  • Running activities中列出了最近使用的Activity的记录,这个按照最most recent的顺序排列

  • Recent tasks中列出了most recent的task的信息

results matching ""

    No results matching ""