目录
一、TaskDisplayArea、ActivityStack、TaskRecord以及ActivityRecord关系图
二、TaskDisplayArea、ActivityStack、Task以及ActivityRecord相关代码
前言:对TaskDisplayArea、ActivityStack、TaskRecord以及ActivityRecord这几个类,搞应用开发的同学可能会觉得既熟悉又陌生,有接触但是对他们之间具体的关系只是一知半解,所以我这里整理了一下,方便自己回顾以及同学们的学习。以下基于Android 11讲解,不同Android版本会有差异。
一、TaskDisplayArea、ActivityStack、TaskRecord以及ActivityRecord关系图
先通过框架图直观的画出他们的关系:
我们使用dumpsys activity activities命令查看 activity 相关信息:
ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)
Display #0 (activities from top to bottom): //(1)
Stack #33: type=standard mode=fullscreen //(2)
isSleeping=false
mBounds=Rect(0, 0 - 0, 0)
mResumedActivity: ActivityRecord{42c5293 u0 com.google.android.youtube.tv/com.google.android.apps.youtube.tv.activity.MainActivity t33}
* Task{abc62c9 #33 visible=true type=standard mode=fullscreen //(3)
translucent=false A=10045:com.google.android.youtube.tv.main U=0 StackId=33 sz=1}
mBounds=Rect(0, 0 - 0, 0)
mMinWidth=-1 mMinHeight=-1
userId=0 effectiveUid=u0a45 mCallingUid=u0a45 mUserSetupComplete=true mCallingPackage=com.google.android.youtube.tv mCallingFeatureId=null
affinity=10045:com.google.android.youtube.tv.main
intent={act=android.intent.action.MAIN cat=[android.intent.category.LEANBACK_LAUNCHER] flg=0x15000000 pkg=com.google.android.youtube.tv cmp=com.google.android.yout
ube.tv/com.google.android.apps.youtube.tv.activity.MainActivity}
mActivityComponent=com.google.android.youtube.tv/com.google.android.apps.youtube.tv.activity.MainActivity
autoRemoveRecents=false isPersistable=true activityType=1
rootWasReset=false mNeverRelinquishIdentity=true mReuseTask=false mLockTaskAuth=LOCK_TASK_AUTH_PINNABLE
Activities=[ActivityRecord{42c5293 u0 com.google.android.youtube.tv/com.google.android.apps.youtube.tv.activity.MainActivity t33}]
askedCompatMode=false inRecents=true isAvailable=true
mRootProcess=ProcessRecord{3b66003 2276:com.google.android.youtube.tv/u0a45}
taskId=33 stackId=33
mHasBeenVisible=true
mResizeMode=RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION mSupportsPictureInPicture=false isResizeable=true
lastActiveTime=936386 (inactive for 56s)
* Hist #0: ActivityRecord{42c5293 u0 com.google.android.youtube.tv/com.google.android.apps.youtube.tv.activity.MainActivity t33}
packageName=com.google.android.youtube.tv processName=com.google.android.youtube.tv
launchedFromUid=10045 launchedFromPackage=com.google.android.youtube.tv launchedFromFeature=null userId=0
app=ProcessRecord{3b66003 2276:com.google.android.youtube.tv/u0a45}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.LEANBACK_LAUNCHER] flg=0x15000000 pkg=com.google.android.youtube.tv cmp=com.google.android
.youtube.tv/com.google.android.apps.youtube.tv.activity.MainActivity bnds=[1536,405][1744,554] }
rootOfTask=true task=Task{abc62c9 #33 visible=true type=standard mode=fullscreen translucent=false A=10045:com.google.android.youtube.tv.main U=0 StackId=33 sz
=1}
taskAffinity=10045:com.google.android.youtube.tv.main
mActivityComponent=com.google.android.youtube.tv/com.google.android.apps.youtube.tv.activity.MainActivity
baseDir=/product/app/YouTubeLeanback/YouTubeLeanback.apk
dataDir=/data/user/0/com.google.android.youtube.tv
stateNotNeeded=false componentSpecified=false mActivityType=standard
compat={320dpi always-compat} labelRes=0x7f12002d icon=0x7f0f0000 theme=0x7f1300de
mLastReportedConfigurations:
mGlobalConfig={1.0 ?mcc?mnc [en_US] ldltr sw540dp w960dp h540dp 320dpi lrg long land television finger qwerty/v/v dpad/v winConfig={ mBounds=Rect(0, 0 - 1920
, 1080) mAppBounds=Rect(0, 0 - 1920, 1080) mWindowingMode=fullscreen mDisplayWindowingMode=fullscreen mActivityType=undefined mAlwaysOnTop=undefined mRotation=ROTATION_0
} s.6}
mOverrideConfig={1.0 ?mcc?mnc [en_US] ldltr sw540dp w960dp h540dp 320dpi lrg long land television finger qwerty/v/v dpad/v winConfig={ mBounds=Rect(0, 0 - 19
20, 1080) mAppBounds=Rect(0, 0 - 1920, 1080) mWindowingMode=fullscreen mDisplayWindowingMode=fullscreen mActivityType=standard mAlwaysOnTop=undefined mRotation=ROTATION_
0} s.2}
CurrentConfiguration={1.0 ?mcc?mnc [en_US] ldltr sw540dp w960dp h540dp 320dpi lrg long land television finger qwerty/v/v dpad/v winConfig={ mBounds=Rect(0, 0 -
1920, 1080) mAppBounds=Rect(0, 0 - 1920, 1080) mWindowingMode=fullscreen mDisplayWindowingMode=fullscreen mActivityType=standard mAlwaysOnTop=undefined mRotation=ROTATI
ON_0} s.2}
taskDescription: label="null" icon=null iconResource=/0 iconFilename=null primaryColor=ff282828
backgroundColor=ff303030 statusBarColor=ff000000 navigationBarColor=ff000000
launchFailed=false launchCount=1 lastLaunchTime=-56s888ms
mHaveState=false mIcicle=null
state=RESUMED stopped=false delayedResume=false finishing=false
keysPaused=false inHistory=true setToSleep=false idle=true mStartingWindowState=STARTING_WINDOW_SHOWN
occludesParent=true noDisplay=false immersive=false launchMode=2
frozenBeforeDestroy=false forceNewConfig=false
mActivityType=standard
windows=[Window{287fb2e u0 com.google.android.youtube.tv/com.google.android.apps.youtube.tv.activity.MainActivity}, Window{694a88e u0 com.google.android.youtub
e.tv/com.google.android.apps.youtube.tv.activity.MainActivity}]
windowType=2 hasVisible=true
mOccludesParent=true mOrientation=6
mVisibleRequested=true mVisible=true mClientVisible=true reportedDrawn=true reportedVisible=true
mNumInterestingWindows=2 mNumDrawnWindows=2 allDrawn=true lastAllDrawn=true)
startingData=null firstWindowDrawn=true mIsExiting=false
nowVisible=true lastVisibleTime=-56s184ms
resizeMode=RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION
mLastReportedMultiWindowMode=false mLastReportedPictureInPictureMode=false
Stack #1: type=home mode=fullscreen //(4)
isSleeping=false
mBounds=Rect(0, 0 - 0, 0)
mLastPausedActivity: ActivityRecord{5965cc0 u0 com.google.android.tvlauncher/.MainActivity t30}
* Task{3d3a13e #30 visible=false type=home mode=fullscreen //(5)
translucent=true A=10036:.TvLauncher U=0 StackId=1 sz=1}
mBounds=Rect(0, 0 - 0, 0)
mMinWidth=-1 mMinHeight=-1
userId=0 effectiveUid=u0a36 mCallingUid=0 mUserSetupComplete=true mCallingPackage=null mCallingFeatureId=null
affinity=10036:.TvLauncher
intent={act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10800100 cmp=com.google.android.tvlauncher/.MainActivity}
mActivityComponent=com.google.android.tvlauncher/.MainActivity
autoRemoveRecents=false isPersistable=false activityType=2
rootWasReset=false mNeverRelinquishIdentity=true mReuseTask=false mLockTaskAuth=LOCK_TASK_AUTH_PINNABLE
Activities=[ActivityRecord{5965cc0 u0 com.google.android.tvlauncher/.MainActivity t30}]
askedCompatMode=false inRecents=true isAvailable=true
taskId=30 stackId=1
mHasBeenVisible=true
mResizeMode=RESIZE_MODE_UNRESIZEABLE mSupportsPictureInPicture=false isResizeable=false
lastActiveTime=931857 (inactive for 61s)
* Hist #0: ActivityRecord{5965cc0 u0 com.google.android.tvlauncher/.MainActivity t30}
packageName=com.google.android.tvlauncher processName=com.google.android.tvlauncher
launchedFromUid=0 launchedFromPackage=null launchedFromFeature=null userId=0
app=ProcessRecord{14710bd 1297:com.google.android.tvlauncher/u0a36}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10800100 cmp=com.google.android.tvlauncher/.MainActivity (has extras) }
rootOfTask=true task=Task{3d3a13e #30 visible=false type=home mode=fullscreen translucent=true A=10036:.TvLauncher U=0 StackId=1 sz=1}
taskAffinity=10036:.TvLauncher
mActivityComponent=com.google.android.tvlauncher/.MainActivity
baseDir=/product/priv-app/TVLauncher/TVLauncher.apk
dataDir=/data/user/0/com.google.android.tvlauncher
stateNotNeeded=true componentSpecified=false mActivityType=home
compat={320dpi always-compat} labelRes=0x7f12002b icon=0x7f0f0000 theme=0x7f130007
mLastReportedConfigurations:
mGlobalConfig={1.0 ?mcc?mnc [en_US] ldltr sw540dp w960dp h540dp 320dpi lrg long land television finger qwerty/v/v dpad/v winConfig={ mBounds=Rect(0, 0 - 1920
, 1080) mAppBounds=Rect(0, 0 - 1920, 1080) mWindowingMode=fullscreen mDisplayWindowingMode=fullscreen mActivityType=home mAlwaysOnTop=undefined mRotation=ROTATION_0} s.8
}
mOverrideConfig={1.0 ?mcc?mnc [en_US] ldltr sw540dp w960dp h540dp 320dpi lrg long land television finger qwerty/v/v dpad/v winConfig={ mBounds=Rect(0, 0 - 19
20, 1080) mAppBounds=Rect(0, 0 - 1920, 1080) mWindowingMode=fullscreen mDisplayWindowingMode=fullscreen mActivityType=home mAlwaysOnTop=undefined mRotation=ROTATION_0} s
.3}
CurrentConfiguration={1.0 ?mcc?mnc [en_US] ldltr sw540dp w960dp h540dp 320dpi lrg long land television finger qwerty/v/v dpad/v winConfig={ mBounds=Rect(0, 0 -
1920, 1080) mAppBounds=Rect(0, 0 - 1920, 1080) mWindowingMode=fullscreen mDisplayWindowingMode=fullscreen mActivityType=home mAlwaysOnTop=undefined mRotation=ROTATION_0
} s.4}
RequestedOverrideConfiguration={0.0 ?mcc?mnc ?localeList ?layoutDir ?swdp ?wdp ?hdp ?density ?lsize ?long ?ldr ?wideColorGamut ?orien ?uimode ?night ?touch ?ke
yb/?/? ?nav/? winConfig={ mBounds=Rect(0, 0 - 0, 0) mAppBounds=null mWindowingMode=undefined mDisplayWindowingMode=undefined mActivityType=home mAlwaysOnTop=undefined mR
otation=undefined}}
taskDescription: label="null" icon=null iconResource=/0 iconFilename=null primaryColor=ff37474f
backgroundColor=ff303030 statusBarColor=ff263238 navigationBarColor=ff000000
launchFailed=false launchCount=0 lastLaunchTime=-16m8s532ms
mHaveState=true mIcicle=Bundle[mParcelledData.dataSize=1272]
state=STOPPED stopped=true delayedResume=false finishing=false
keysPaused=false inHistory=true setToSleep=false idle=true mStartingWindowState=STARTING_WINDOW_REMOVED
occludesParent=true noDisplay=false immersive=false launchMode=2
frozenBeforeDestroy=false forceNewConfig=false
mActivityType=home
windows=[Window{eccb3b1 u0 com.google.android.tvlauncher/com.google.android.tvlauncher.MainActivity}]
windowType=2 hasVisible=true
mOccludesParent=true mOrientation=0
mVisibleRequested=false mVisible=false mClientVisible=false reportedDrawn=false reportedVisible=false
mAppStopped=true
mNumInterestingWindows=1 mNumDrawnWindows=1 allDrawn=true lastAllDrawn=true)
startingData=null firstWindowDrawn=true mIsExiting=false
nowVisible=false lastVisibleTime=-7m58s405ms
resizeMode=RESIZE_MODE_UNRESIZEABLE
mLastReportedMultiWindowMode=false mLastReportedPictureInPictureMode=false
根据以上显示的信息,注释(1)中的Display #0 为ActivityDisplay,id为0,注释(2)中的Stack #33 为 ActivityStack,id为33,注释(4)中的Stack #1为ActivityStack,id为1,注释(3)和注释(5)TaskRecord的 id分别为33和30.
关系图如下:
二、TaskDisplayArea、ActivityStack、Task以及ActivityRecord相关代码
1、ActivityRecord
\frameworks\base\services\core\java\com\android\server\wm\ActivityRecord.java
final class ActivityRecord {
...............
final ActivityRecord.Token appToken;
final ActivityTaskManagerService mAtmService;
final ComponentName realActivity; // the intent component, or target of an alias.
final String shortComponentName; // the short component name of the intent
final String packageName; // the package implementing intent's component
final String processName; // process where this component wants to run
final String taskAffinity; // as per ActivityInfo.taskAffinity
boolean fullscreen; // covers the full screen?
...............
}
ActivityRecord记录着Activity的信息,与Activity一一对应,可能大家对ActivityRecord与Activity搞不太清楚,实际上ActivityRecord就是Activity对应的服务端,Activity为客户端。
2、Task
\frameworks\base\services\core\java\com\android\server\wm\Task.java
class Task extends WindowContainer<WindowContainer> {
................
final ActivityTaskManagerService mAtmService;
final ActivityStackSupervisor mStackSupervisor;
final RootWindowContainer mRootWindowContainer;
/* Unique identifier for this task. */
final int mTaskId;
/* User for which this task was created. */
// TODO: Make final
int mUserId;
................
}
3、ActivityStack
\frameworks\base\services\core\java\com\android\server\wm\ActivityStack.java
class ActivityStack extends Task {
}
我们可以看到,在Android 11中ActivityStack是继承于task的,因此持有相对应Task中的mAtmService、mStackSupervisor、mRootWindowContainer、mTaskId等变量。通常开启一个新的应用,就会新建一个ActivityStack。但在同一个应用中如果通过singleInstance启动activity,那么也会新建一个ActivityStack。
4、TaskDisplayArea
\frameworks\base\services\core\java\com\android\server\wm\TaskDisplayArea.java
final class TaskDisplayArea extends DisplayArea<ActivityStack> {
.....................
// Cached reference to some special tasks we tend to get a lot so we don't need to loop
// through the list to find them.
private ActivityStack mRootHomeTask;
private ActivityStack mRootPinnedTask;
private ActivityStack mRootSplitScreenPrimaryTask;
// TODO(b/159029784): Remove when getStack() behavior is cleaned-up
private ActivityStack mRootRecentsTask;
.....................
}
我们可以看到这里有很多个ActivityStack 的全局变量,mRootHomeTask使用来存储launcher的ActivityStack,其type为home。
\frameworks\base\services\core\java\com\android\server\wm\TaskDisplayArea.java
ActivityStack getStack(int windowingMode, int activityType) {
.........
if (activityType == ACTIVITY_TYPE_HOME) { //(6)
return mRootHomeTask;
} else if (activityType == ACTIVITY_TYPE_RECENTS) {
return mRootRecentsTask;
}
.........
}
public static String activityTypeToString(@ActivityType int applicationType) {
switch (applicationType) {
case ACTIVITY_TYPE_UNDEFINED: return "undefined";
case ACTIVITY_TYPE_STANDARD: return "standard";
case ACTIVITY_TYPE_HOME: return "home"; //(7)
case ACTIVITY_TYPE_RECENTS: return "recents";
case ACTIVITY_TYPE_ASSISTANT: return "assistant";
case ACTIVITY_TYPE_DREAM: return "dream";
}
return String.valueOf(applicationType);
}
以上代码我们可以看到通过TaskDisplayArea获取ACTIVITY_TYPE_HOME的时候即返回mRootHomeTask,在注释(7)这里看到其实际type为字符“home”,那么我们回过头看看dumpsys activity activities中launcher相关信息:
Stack #1: type=home mode=fullscreen //(8)
isSleeping=false
mBounds=Rect(0, 0 - 0, 0)
mLastPausedActivity: ActivityRecord{5965cc0 u0 com.google.android.tvlauncher/.MainActivity t30}
* Task{3d3a13e #30 visible=false type=home mode=fullscreen
translucent=true A=10036:.TvLauncher U=0 StackId=1 sz=1}
mBounds=Rect(0, 0 - 0, 0)
mMinWidth=-1 mMinHeight=-1
userId=0 effectiveUid=u0a36 mCallingUid=0 mUserSetupComplete=true mCallingPackage=null mCallingFeatureId=null
affinity=10036:.TvLauncher
intent={act=android.intent.action.MAIN cat=[android.intent.category.HOME]
在注释(8)中我们看到其type为home。