以下分析基于Android S.
简述
上文中我们知道Activity的Window被添加至WMS其实就是该Activity的ViewRootImpl中的W作为IWindow、存储该Activity窗口属性信息的LayoutParams以及InputChannel被传入WMS,然后生成WindowToken, 当然之后WindowToken自然是保存在DisplayContent.mTokenMap中,该map的key即对应Activity中的mToken(LocalActivityRecord)。
在Activity的Window被添加至WMS中,我们仅仅分析了一半,然后重点区分析了DisplayContent的构建,了解了其层次结构器的创建过程以及layer的个数和Window类型对应的layer。现在我们接着看WindowToken的创建,上文中留有一个疑问:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 
 | DisplayArea.Tokens findAreaForToken(int windowType, boolean ownerCanManageAppTokens,boolean roundedCornerOverlay) {
 
 
 
 int windowLayerFromType = mWmService.mPolicy.getWindowLayerFromTypeLw(windowType,
 ownerCanManageAppTokens, roundedCornerOverlay);
 
 if (windowLayerFromType == APPLICATION_LAYER) {
 throw new IllegalArgumentException(
 "There shouldn't be WindowToken on APPLICATION_LAYER");
 }
 return mAreaForLayer[windowLayerFromType];
 }
 
 | 
因为Activity对应的windowType是TYPE_BASE_APPLICATION,所以拿到的windowLayerFromType就是APPLICATION_LAYER,那么这里必然会抛出异常!
当然按照正常理解来说,必然不会发生异常才对,所以是我们流程分析哪里有问题? 是也不是,这里就要留意到应用启动过程了,回到Activity的启动过程,我们先看ActivityRecord的创建过程。
一. ActivityRecord的创建
ActivityRecord类是WindowToken子类:

而且从名字中也可以看出,这个类应该是和Activity一一对应的,那么应该在Activity启动流程中哪个步骤创建其对象呢?不难理解,肯定是在startActivity的过程中。
Activity的启动流程这里就不展开了,直接看关键代码.
1.1 ActivityTaskManagerService.startActivity
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 
 | private int startActivityAsUser(IApplicationThread caller, String callingPackage,@Nullable String callingFeatureId, Intent intent, String resolvedType,
 IBinder resultTo, String resultWho, int requestCode, int startFlags,
 ProfilerInfo profilerInfo, Bundle bOptions, int userId, boolean validateIncomingUser) {
 ......
 
 return getActivityStartController().obtainStarter(intent, "startActivityAsUser")
 .setCaller(caller)
 .setCallingPackage(callingPackage)
 .setCallingFeatureId(callingFeatureId)
 .setResolvedType(resolvedType)
 .setResultTo(resultTo)
 .setResultWho(resultWho)
 .setRequestCode(requestCode)
 .setStartFlags(startFlags)
 .setProfilerInfo(profilerInfo)
 .setActivityOptions(bOptions)
 .setUserId(userId)
 .execute();
 }
 
 | 
将Activity的启动委托给ActivityStarter执行。
1.2 ActivityStarter.execute
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 
 | int execute() {try {
 ......
 synchronized (mService.mGlobalLock) {
 ......
 res = executeRequest(mRequest);
 ......
 }
 
 private int executeRequest(Request request) {
 ......
 
 Task inTask = request.inTask;
 ......
 
 final ActivityRecord r = new ActivityRecord.Builder(mService)
 .setCaller(callerApp)
 .setLaunchedFromPid(callingPid)
 .setLaunchedFromUid(callingUid)
 .setLaunchedFromPackage(callingPackage)
 .setLaunchedFromFeature(callingFeatureId)
 .setIntent(intent)
 .setResolvedType(resolvedType)
 .setActivityInfo(aInfo)
 .setConfiguration(mService.getGlobalConfiguration())
 .setResultTo(resultRecord)
 .setResultWho(resultWho)
 .setRequestCode(requestCode)
 .setComponentSpecified(request.componentSpecified)
 .setRootVoiceInteraction(voiceSession != null)
 .setActivityOptions(checkedOptions)
 .setSourceRecord(sourceRecord)
 .build();
 ......
 
 mLastStartActivityResult = startActivityUnchecked(r, sourceRecord, voiceSession,
 request.voiceInteractor, startFlags, true , checkedOptions, inTask,
 restrictedBgActivity, intentGrants);
 ......
 }
 
 | 
ActivityRecord的初始化是采用了Build模式.
1.2.1 ActivityRecord的初始化
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 
 | private ActivityRecord(ActivityTaskManagerService _service, WindowProcessController _caller,int _launchedFromPid, int _launchedFromUid, String _launchedFromPackage,
 @Nullable String _launchedFromFeature, Intent _intent, String _resolvedType,
 ActivityInfo aInfo, Configuration _configuration, ActivityRecord _resultTo,
 String _resultWho, int _reqCode, boolean _componentSpecified,
 boolean _rootVoiceInteraction, ActivityTaskSupervisor supervisor,
 ActivityOptions options, ActivityRecord sourceRecord, PersistableBundle persistentState,
 TaskDescription _taskDescription, long _createTime) {
 
 
 super(_service.mWindowManager, new Token(_intent).asBinder(), TYPE_APPLICATION, true,
 null , false );
 
 mAtmService = _service;
 appToken = (Token) token;
 info = aInfo;
 ......
 appToken.attach(this);
 ......
 }
 
 static class Token extends IApplicationToken.Stub {
 ......
 private void attach(ActivityRecord activity) {
 if (weakActivity != null) {
 throw new IllegalStateException("Already attached..." + this);
 }
 
 weakActivity = new WeakReference<>(activity);
 }
 ......
 
 | 
所以ActivityRecord里的appToken其实是ActivityRecord初始化时创建的Token(为IApplicationToken.Stub的子类),里面保存了该Activity的Intent信息。
1.3 ActivityStarter.startActivityUnchecked
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 
 | private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
 int startFlags, boolean doResume, ActivityOptions options, Task inTask,
 boolean restrictedBgActivity, NeededUriGrants intentGrants) {
 ......
 result = startActivityInner(r, sourceRecord, voiceSession, voiceInteractor,
 startFlags, doResume, options, inTask, restrictedBgActivity, intentGrants);
 ......
 }
 
 int startActivityInner(final ActivityRecord r, ActivityRecord sourceRecord,
 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
 int startFlags, boolean doResume, ActivityOptions options, Task inTask,
 boolean restrictedBgActivity, NeededUriGrants intentGrants) {
 
 setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
 voiceInteractor, restrictedBgActivity);
 ......
 
 final Task reusedTask = getReusableTask();
 ......
 
 final Task targetTask = reusedTask != null ? reusedTask : computeTargetTask();
 final boolean newTask = targetTask == null;
 mTargetTask = targetTask;
 ......
 
 final ActivityRecord targetTaskTop = newTask
 ? null : targetTask.getTopNonFinishingActivity();
 if (targetTaskTop != null) {
 
 startResult = recycleTask(targetTask, targetTaskTop, reusedTask, intentGrants);
 if (startResult != START_SUCCESS) {
 return startResult;
 }
 } else {
 mAddingToTask = true;
 }
 ......
 
 final Task topRootTask = mPreferredTaskDisplayArea.getFocusedRootTask();
 if (topRootTask != null) {
 
 startResult = deliverToCurrentTopIfNeeded(topRootTask, intentGrants);
 if (startResult != START_SUCCESS) {
 return startResult;
 }
 }
 if (mTargetRootTask == null) {
 
 mTargetRootTask = getLaunchRootTask(mStartActivity, mLaunchFlags, targetTask, mOptions);
 }
 
 if (newTask) {
 final Task taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
 ? mSourceRecord.getTask() : null;
 
 setNewTask(taskToAffiliate);
 } else if (mAddingToTask) {
 addOrReparentStartingActivity(targetTask, "adding to task");
 }
 ......
 
 mTargetRootTask.startActivityLocked(mStartActivity,
 topRootTask != null ? topRootTask.getTopNonFinishingActivity() : null, newTask,
 mKeepCurTransition, mOptions, startFromSamePackage);
 ......
 }
 
 private void setNewTask(Task taskToAffiliate) {
 final boolean toTop = !mLaunchTaskBehind && !mAvoidMoveToFront;
 
 final Task task = mTargetRootTask.reuseOrCreateTask(
 mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
 mNewTaskIntent != null ? mNewTaskIntent : mIntent, mVoiceSession,
 mVoiceInteractor, toTop, mStartActivity, mSourceRecord, mOptions);
 mService.getTransitionController().collectExistenceChange(task);
 
 addOrReparentStartingActivity(task, "setTaskFromReuseOrCreateNewTask - mReuseTask");
 
 ......
 }
 
 | 
这里我们假设启动的Activity是应用的首个Activity,而且也没有设置affinity,这样在启动该Activity时,会创建新的Task, 并在该Task中保存ActivityRecord!
1.3.1 ActivityStarter.setInitialState - 设置初始化状态
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 
 | private void setInitialState(ActivityRecord r, ActivityOptions options, Task inTask,boolean doResume, int startFlags, ActivityRecord sourceRecord,
 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
 boolean restrictedBgActivity) {
 reset(false );
 
 mStartActivity = r;
 ......
 mLaunchParams.reset();
 ......
 
 
 mPreferredTaskDisplayArea = mLaunchParams.hasPreferredTaskDisplayArea()
 ? mLaunchParams.mPreferredTaskDisplayArea
 : mRootWindowContainer.getDefaultTaskDisplayArea();
 }
 
 | 
这里首先先清理ActivityStarter内部成员,然后依次赋值。
1.4 ActivityStarter.addOrReparentStartingActivity
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 
 | private void addOrReparentStartingActivity(Task parent, String reason) {
 
 if (mStartActivity.getTask() == null || mStartActivity.getTask() == parent) {
 
 parent.addChild(mStartActivity);
 } else {
 mStartActivity.reparent(parent, parent.getChildCount() , reason);
 }
 }
 
 | 
1.5 Task.addChild
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 
 | void addChild(ActivityRecord r) {
 addChild(r, Integer.MAX_VALUE );
 }
 
 @Override
 void addChild(WindowContainer child, int index) {
 
 boolean hadChild = hasChild();
 
 final int activityType = getActivityType();
 
 index = getAdjustedChildPosition(child, index);
 
 super.addChild(child, index);
 ......
 }
 
 | 
1.5.1 Task.getActivityType
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 
 | @Overridepublic int getActivityType() {
 
 final int applicationType = super.getActivityType();
 if (applicationType != ACTIVITY_TYPE_UNDEFINED || !hasChild()) {
 return applicationType;
 }
 return getTopChild().getActivityType();
 }
 
 
 public int getActivityType() {
 
 return mFullConfiguration.windowConfiguration.getActivityType();
 }
 
 
 @ActivityType
 public int getActivityType() {
 return mActivityType;
 }
 
 | 
ActivityType有如下取值:
| 名称 | 值 | 含义 | 
| ACTIVITY_TYPE_UNDEFINED | 0 | Activity类型尚未定义 | 
| ACTIVITY_TYPE_STANDARD | 1 | 标准Activity类型 | 
| ACTIVITY_TYPE_HOME | 2 | Home或Launcher的Activity类型 | 
| ACTIVITY_TYPE_RECENTS | 3 | Recents或者Overview的Activity类型,系统中只有一个具有此类型的Activity | 
| ACTIVITY_TYPE_ASSISTANT | 4 | Assistant Activity类型 | 
| ACTIVITY_TYPE_DREAM | 5 | Dream Activity类型 | 
一般情况都是ACTIVITY_TYPE_STANDARD或者ACTIVITY_TYPE_HOME类型。当前Task获取的值应该是初始化的默认值:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 
 | private Configuration mFullConfiguration = new Configuration();
 
 
 public final WindowConfiguration windowConfiguration = new WindowConfiguration();
 
 
 public WindowConfiguration() {
 unset();
 }
 
 public void unset() {
 setToDefaults();
 }
 
 
 public void setToDefaults() {
 setAppBounds(null);
 setBounds(null);
 setMaxBounds(null);
 setWindowingMode(WINDOWING_MODE_UNDEFINED);
 setActivityType(ACTIVITY_TYPE_UNDEFINED);
 setAlwaysOnTop(ALWAYS_ON_TOP_UNDEFINED);
 setRotation(ROTATION_UNDEFINED);
 setDisplayWindowingMode(WINDOWING_MODE_UNDEFINED);
 }
 
 | 
可以看到,ActivityType是被设置成:ACTIVITY_TYPE_UNDEFINED,也即未定义类型!
1.5.2 Task.getAdjustedChildPosition
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 
 | private int getAdjustedChildPosition(WindowContainer wc, int suggestedPosition) {
 
 final boolean canShowChild = wc.showToCurrentUser();
 
 final int size = mChildren.size();
 
 
 int minPosition = (canShowChild) ? computeMinUserPosition(0, size) : 0;
 int maxPosition = (canShowChild) ? size : computeMaxUserPosition(size - 1);
 
 
 if (!wc.isAlwaysOnTop()) {
 
 
 while (maxPosition > minPosition) {
 if (!mChildren.get(maxPosition - 1).isAlwaysOnTop()) break;
 --maxPosition;
 }
 }
 
 
 
 if (suggestedPosition == POSITION_BOTTOM && minPosition == 0) {
 return POSITION_BOTTOM;
 } else if (suggestedPosition == POSITION_TOP && maxPosition >= (size - 1)) {
 return POSITION_TOP;
 }
 
 return Math.min(Math.max(suggestedPosition, minPosition), maxPosition);
 }
 
 | 
这里是通过检查WindowContainer是否可见的属性以及是否应该永远处于最上层来调整该WC应该被插入Task的哪个位置。
当我们ActivityRecord被添加入一个新建的Task时,毫无疑问应该是处于最上层即返回POSITION_TOP。
1.5.2.1 WindowContainer.isAlwaysOnTop
| 12
 3
 4
 5
 6
 7
 
 | public boolean isAlwaysOnTop() {if (mWindowingMode == WINDOWING_MODE_PINNED) return true;
 if (mActivityType == ACTIVITY_TYPE_DREAM) return true;
 if (mAlwaysOnTop != ALWAYS_ON_TOP_ON) return false;
 return mWindowingMode == WINDOWING_MODE_FREEFORM
 || mWindowingMode == WINDOWING_MODE_MULTI_WINDOW;
 }
 
 | 
说明如下情况,该WindowContainer应该始终处于所在Task的最上层:
- window模式为WINDOWING_MODE_PINNED
- Activity类型是ACTIVITY_TYPE_DREAM
- 当mAlwaysOnTop为ALWAYS_ON_TOP_ON,window模式为WINDOWING_MODE_FREEFORM或WINDOWING_MODE_MULTI_WINDOW
1.6 WindowContainer.addChild
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 
 | @CallSupervoid addChild(E child, int index) {
 ......
 
 if (index == POSITION_TOP) {
 index = mChildren.size();
 } else if (index == POSITION_BOTTOM) {
 index = 0;
 }
 
 
 mChildren.add(index, child);
 
 
 child.setParent(this);
 }
 
 | 
@CallSuper: 是Android中特有的注解,如果子类覆盖了同名方法而没有显示调用父类的该方法时就会报错!
这个也挺简单的,首先最后调整一下index:
- 如果传入的index为POSITION_TOP,则将index设置为当前mChildren的size值,意为将待存入的child保存在mChildren中最后一位(上面)
- 如果传入的index为POSITION_BOTTOM, 则将index设置为0,意为将待存入的child保存在mChildren中第一位(下面)
然后让child(ActivityRecord)保存该WC(即Task)。
1.7 WindowContainer.setParent
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 
 | final protected void setParent(WindowContainer<WindowContainer> parent) {final WindowContainer oldParent = mParent;
 mParent = parent;
 
 if (mParent != null) {
 mParent.onChildAdded(this);
 }
 
 if (!mReparenting) {
 onSyncReparent(oldParent, mParent);
 
 if (mParent != null && mParent.mDisplayContent != null
 && mDisplayContent != mParent.mDisplayContent) {
 
 onDisplayChanged(mParent.mDisplayContent);
 }
 
 onParentChanged(mParent, oldParent);
 }
 }
 
 | 
设置WC(ActivityRecord)的父集(mParent, 即保存该WC的Task), 如有必要同步Task中DisplayContent至该WC中。
1.7.1 ActivityRecord.onParentChanged
| 12
 3
 4
 5
 6
 7
 8
 
 | @Overridevoid onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent) {
 final Task oldTask = oldParent != null ? (Task) oldParent : null;
 final Task newTask = newParent != null ? (Task) newParent : null;
 
 this.task = newTask;
 ......
 }
 
 | 
将传入的ConfigurationContainer作为Task,存入ActivityRecord.task中,其余部分暂时先不研究。
1.8 ActivityRecord.onDisplayChanged
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 
 | @Overridevoid onDisplayChanged(DisplayContent dc) {
 DisplayContent prevDc = mDisplayContent;
 
 super.onDisplayChanged(dc);
 ......
 }
 
 
 @Override
 void onDisplayChanged(DisplayContent dc) {
 
 dc.reParentWindowToken(this);
 
 
 super.onDisplayChanged(dc);
 }
 
 
 void onDisplayChanged(DisplayContent dc) {
 if (mDisplayContent != null && mDisplayContent.mChangingContainers.remove(this)) {
 
 mSurfaceFreezer.unfreeze(getPendingTransaction());
 }
 mDisplayContent = dc;
 if (dc != null && dc != this) {
 dc.getPendingTransaction().merge(mPendingTransaction);
 }
 
 for (int i = mChildren.size() - 1; i >= 0; --i) {
 final WindowContainer child = mChildren.get(i);
 child.onDisplayChanged(dc);
 }
 for (int i = mListeners.size() - 1; i >= 0; --i) {
 mListeners.get(i).onDisplayChanged(dc);
 }
 }
 
 | 
这里最主要的是理清ActivityRecord、WindowToken、Task和WindowContainer之间的继承关系:

1.9 DisplayContent.reParentWindowToken
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 
 | void reParentWindowToken(WindowToken token) {
 final DisplayContent prevDc = token.getDisplayContent();
 if (prevDc == this) {
 return;
 }
 if (prevDc != null) {
 ......
 }
 
 
 addWindowToken(token.token, token);
 ......
 }
 
 | 
由于此时还处于ActivityRecord刚被创建,正在第一次被设置DisplayContent时,所以其DisplayContent此时还是null的。那么就直接将该WindowToken(即ActivityRecord)保存在此DisplayContent中,注意token.token其实是WindowToken.token, 这个值我们之前分析过,是attrs.token,也就是从App进程传入的LocalActivityRecord.
1.10 DisplayContent.addWindowToken
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 
 | void addWindowToken(IBinder binder, WindowToken token) {final DisplayContent dc = mWmService.mRoot.getWindowTokenDisplay(token);
 ......
 
 mTokenMap.put(binder, token);
 
 if (token.asActivityRecord() == null) {
 ......
 }
 }
 
 | 
好了,我们终于明白了一个ActivityRecord是如何被添加进DisplayContent中了,看到这里是不是似曾相识呢?Bingo, 之前我们的windowToken创建时会抛出一个异常,就是因为这个WindowToken.asActivityRecord返回值为null, 导致DisplayContent中添加该WindowToken时找不到合适layer!
| 12
 3
 4
 5
 6
 7
 
 | int windowLayerFromType = mWmService.mPolicy.getWindowLayerFromTypeLw(windowType,ownerCanManageAppTokens, roundedCornerOverlay);
 
 if (windowLayerFromType == APPLICATION_LAYER) {
 throw new IllegalArgumentException(
 "There shouldn't be WindowToken on APPLICATION_LAYER");
 }
 
 | 
现在我们知道了,在app的Activity被resume时,早就已经有了其WindowToken(ActivityRecord)被保存在DisplayContent的mTokenMap中。所以回过头我们看WMS.addWindow方法:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 
 | public int addWindow(Session session, IWindow client, LayoutParams attrs, int viewVisibility,int displayId, int requestUserId, InsetsState requestedVisibility,
 InputChannel outInputChannel, InsetsState outInsetsState,
 InsetsSourceControl[] outActiveControls) {
 ......
 
 final int type = attrs.type;
 synchronized (mGlobalLock) {
 ......
 
 WindowToken token = displayContent.getWindowToken(
 hasParent ? parentWindow.mAttrs.token : attrs.token);
 ......
 
 if (token == null) {
 .....
 }
 ...
 
 final WindowState win = new WindowState(this, session, client, token, parentWindow,
 appOp[0], attrs, viewVisibility, session.mUid, userId,
 session.mCanAddInternalSystemWindow);
 ......
 
 win.attach();
 
 mWindowMap.put(client.asBinder(), win);
 ......
 win.mToken.addWindow(win);
 ......
 ......
 }
 
 | 
啊哈,异常解除,因为Activity需要resume必须先start, 而start过程中就会创建其对应ActivityRecord并保存在对应DisplayContent的mTokenMap中!
最后附上一张时序图以备忘:

接下来,我们继续看WMS.addWindow的流程:WindowState的创建及其管理。