本文主要是講述activity啟動過程中ams和wms的數(shù)據(jù)是怎么關(guān)聯(lián)起來的
ActivityStack和TaskStack
1:在Activity啟動過程中瓶盛,首先會創(chuàng)建ActivityRecord對象,在ActivityRecord的構(gòu)造方法中會創(chuàng)建一個Token對象,Token繼承于IApplicationToken.Stub秦叛,appToken會保存在app應(yīng)用程序段篡撵,ams和wms端在
ActivityStarter::startActivity
ActivityRecord(ActivityManagerService _service, ProcessRecord _caller, int _launchedFromPid,
int _launchedFromUid, String _launchedFromPackage, Intent _intent, String _resolvedType,
ActivityInfo aInfo, Configuration _configuration,
ActivityRecord _resultTo, String _resultWho, int _reqCode,
boolean _componentSpecified, boolean _rootVoiceInteraction,
ActivityStackSupervisor supervisor, ActivityOptions options,
ActivityRecord sourceRecord) {
service = _service;
appToken = new Token(this, _intent);
setState(INITIALIZING, "ActivityRecord ctor");
}
2:創(chuàng)建完ActivityRecord之后迷殿,會創(chuàng)建ActivityStack,在ActivityStack的構(gòu)造方法中會創(chuàng)建StackWindowController,android是支持多屏顯示的乱顾,ActivityStack是由ActivityDisplay負(fù)責(zé)創(chuàng)建,ActivityStack可以根據(jù)stackid來區(qū)分绪妹,DisplayContent表示的一塊獨立的顯示屏幕甥桂,在StackWindowController的構(gòu)造方法中會根據(jù)當(dāng)前activity所屬于的DisplayContent來創(chuàng)建一個TaskStack,TaskStack的stackId和前面的stackId是完全一致的
3:StackWindowController作為ActivityStack的成員變量mWindowContainerController邮旷,DisplayContent通過調(diào)用creatStack函數(shù)會將StackWindowController傳遞給TaskStack,TaskStack繼承于WindowContainer,在TaskStack的構(gòu)造方法中調(diào)用了父類的setController將傳遞過來的StackWindowController對象設(shè)置成自己的StackWindowController
@VisibleForTesting
public StackWindowController(int stackId, StackWindowListener listener,
int displayId, boolean onTop, Rect outBounds, WindowManagerService service) {
super(listener, service);
mStackId = stackId;
mHandler = new H(new WeakReference<>(this), service.mH.getLooper());
synchronized (mWindowMap) {
final DisplayContent dc = mRoot.getDisplayContent(displayId);
if (dc == null) {
throw new IllegalArgumentException("Trying to add stackId=" + stackId
+ " to unknown displayId=" + displayId);
}
dc.createStack(stackId, onTop, this);------------->this表示的就是StackWindowController
getRawBounds(outBounds);
}
}
TaskStack createStack(int stackId, boolean onTop, StackWindowController controller) {
if (DEBUG_STACK) Slog.d(TAG_WM, "Create new stackId=" + stackId + " on displayId="
+ mDisplayId);
final TaskStack stack = new TaskStack(mService, stackId, controller);
mTaskStackContainers.addStackToDisplay(stack, onTop);
return stack;
}
TaskStack(WindowManagerService service, int stackId, StackWindowController controller) {
super(service);
mStackId = stackId;
setController(controller);
mDockedStackMinimizeThickness = service.mContext.getResources().getDimensionPixelSize(
com.android.internal.R.dimen.docked_stack_minimize_thickness);
EventLog.writeEvent(EventLogTags.WM_STACK_CREATED, stackId);
}
這樣ActivityStack便通過StatckWindowController和TaskStack關(guān)聯(lián)起來
1:ActivityStackSuperVisor管理ActivityStack黄选,ActivityStackSuperVisor的成員變量
private final SparseArray<ActivityDisplay> mActivityDisplays = new SparseArray<>();維護(hù)當(dāng)前設(shè)備上的所有ActivityDisplay
2:ActivityDisplay的成員變量private final ArrayList<ActivityStack> mStacks = new ArrayList<>();管理著當(dāng)前的ActivityStack
3:在wms端RootWindowContainer持有WindowList<Displaycontent>列表,維護(hù)著所有的DisplayContent,DisplayContent代表的是一塊顯示屏幕
4:DisplayContent的靜態(tài)內(nèi)部類TaskStackContainers持有WindowList<TaskStack>列表婶肩,維護(hù)著所有的TaskStack
TaskRecord和Task
1:創(chuàng)建完ActivityStack之后便需要創(chuàng)建一個TaskRecord办陷,是否創(chuàng)建一個新的TaskRecord取決于應(yīng)用設(shè)置的flag和taskAffnity,是否需要創(chuàng)建一個新的task是在startActivityUnchecked方法中
boolean newTask = false;
final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
? mSourceRecord.getTask() : null;
// Should this be considered a new task?
int result = START_SUCCESS;
if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
&& (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
newTask = true;
result = setTaskFromReuseOrCreateNewTask(taskToAffiliate, topStack);--->新建一個task
} else if (mSourceRecord != null) {
result = setTaskFromSourceRecord();
} else if (mInTask != null) {
result = setTaskFromInTask();
} else {
// This not being started from an existing activity, and not part of a new task...
// just put it in the top task, though these days this case should never happen.
setTaskToCurrentTopOrCreateNewTask();
}
if (result != START_SUCCESS) {
return result;
}
private int setTaskFromReuseOrCreateNewTask(
TaskRecord taskToAffiliate, ActivityStack topStack) {
mTargetStack = computeStackFocus(mStartActivity, true, mLaunchFlags, mOptions);
// Do no move the target stack to front yet, as we might bail if
// isLockTaskModeViolation fails below.
if (mReuseTask == null) {
final TaskRecord task = mTargetStack.createTaskRecord(
mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
mNewTaskIntent != null ? mNewTaskIntent : mIntent, mVoiceSession,
mVoiceInteractor, !mLaunchTaskBehind /* toTop */, mStartActivity, mSourceRecord,
mOptions);
addOrReparentStartingActivity(task, "setTaskFromReuseOrCreateNewTask - mReuseTask");
updateBounds(mStartActivity.getTask(), mLaunchParams.mBounds);
if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
+ " in new task " + mStartActivity.getTask());
} else {
...........................................
return START_SUCCESS;
2:ActivityStack負(fù)責(zé)創(chuàng)建Task并且管理task律歼,task創(chuàng)建完畢之后會將其移到其所在Stack的棧頂民镜,并且調(diào)用createWindowContainer創(chuàng)建一個TaskWindowContainerController,TaskRecord持有mWindowContainerController對象,在TaskWindowContainerController的構(gòu)造方法中會創(chuàng)建一個Task對象险毁,將創(chuàng)建好的Task至于之前創(chuàng)建的TaskStack的棧頂制圈,同時將mWindowContainerController設(shè)置為task的windowContainer對象,這樣TaskRecord和Task通過TaskWindowContainerController關(guān)聯(lián)起來了
TaskRecord createTaskRecord(int taskId, ActivityInfo info, Intent intent,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
boolean toTop, ActivityRecord activity, ActivityRecord source,
ActivityOptions options) {
final TaskRecord task = TaskRecord.create(
mService, taskId, info, intent, voiceSession, voiceInteractor);
// add the task to stack first, mTaskPositioner might need the stack association
addTask(task, toTop, "createTaskRecord");------------->至于stack的棧頂
final int displayId = mDisplayId != INVALID_DISPLAY ? mDisplayId : DEFAULT_DISPLAY;
final boolean isLockscreenShown = mService.mStackSupervisor.getKeyguardController()
.isKeyguardOrAodShowing(displayId);
if (!mStackSupervisor.getLaunchParamsController()
.layoutTask(task, info.windowLayout, activity, source, options)
&& !matchParentBounds() && task.isResizeable() && !isLockscreenShown) {
task.updateOverrideConfiguration(getOverrideBounds());
}
task.createWindowContainer(toTop, (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0);----->創(chuàng)建WindowContainer
return task;
}
void createWindowContainer(boolean onTop, boolean showForAllUsers) {
if (mWindowContainerController != null) {
throw new IllegalArgumentException("Window container=" + mWindowContainerController
+ " already created for task=" + this);
}
final Rect bounds = updateOverrideConfigurationFromLaunchBounds();
setWindowContainerController(new TaskWindowContainerController(taskId, this,
getStack().getWindowContainerController(), userId, bounds,
mResizeMode, mSupportsPictureInPicture, onTop,
showForAllUsers, lastTaskDescription));--------------------->創(chuàng)建TaskWindowContainerController
}
public TaskWindowContainerController(int taskId, TaskWindowContainerListener listener,
StackWindowController stackController, int userId, Rect bounds, int resizeMode,
boolean supportsPictureInPicture, boolean toTop, boolean showForAllUsers,
TaskDescription taskDescription, WindowManagerService service) {
super(listener, service);
mTaskId = taskId;
mHandler = new H(new WeakReference<>(this), service.mH.getLooper());
synchronized(mWindowMap) {
if (DEBUG_STACK) Slog.i(TAG_WM, "TaskWindowContainerController: taskId=" + taskId
+ " stack=" + stackController + " bounds=" + bounds);
final TaskStack stack = stackController.mContainer;
if (stack == null) {
throw new IllegalArgumentException("TaskWindowContainerController: invalid stack="
+ stackController);
}
EventLog.writeEvent(WM_TASK_CREATED, taskId, stack.mStackId);
final Task task = createTask(taskId, stack, userId, resizeMode,
supportsPictureInPicture, taskDescription);
final int position = toTop ? POSITION_TOP : POSITION_BOTTOM;
// We only want to move the parents to the parents if we are creating this task at the
// top of its stack.
stack.addTask(task, position, showForAllUsers, toTop /* moveParents */);
}
Task(int taskId, TaskStack stack, int userId, WindowManagerService service, int resizeMode,
boolean supportsPictureInPicture, TaskDescription taskDescription,
TaskWindowContainerController controller) {
super(service);
mTaskId = taskId;
mStack = stack;
mUserId = userId;
mResizeMode = resizeMode;
mSupportsPictureInPicture = supportsPictureInPicture;
setController(controller);
setBounds(getOverrideBounds());
mTaskDescription = taskDescription;
// Tasks have no set orientation value (including SCREEN_ORIENTATION_UNSPECIFIED).
setOrientation(SCREEN_ORIENTATION_UNSET);
}
1:TaskRecord內(nèi)部有一個成員變量:final ArrayList<ActivityRecord> mActivities;來管理當(dāng)前task的activity
2:一個Activity在ams中可能有多個ActivityRecord畔况,但是是不同的對象
在wms端
1:Task持有WindowList<AppWindowToken>對象
2:AppWindowToken繼承WindowContainer<WindowState>,AppWindowToken持有WindowList<WindowState>,表明AppWindowToken關(guān)聯(lián)著一組WindowState
ActivityRecord和AppWindowToken(WindowState)
1:創(chuàng)建完成TaskRecord之后便為ActivityRecord創(chuàng)建一個windowController鲸鹦,這塊的邏輯在startActivityLocked中
// If we are not placing the new activity frontmost, we do not want to deliver the
// onUserLeaving callback to the actual frontmost activity
final TaskRecord activityTask = r.getTask();
if (task == activityTask && mTaskHistory.indexOf(task) != (mTaskHistory.size() - 1)) {
mStackSupervisor.mUserLeaving = false;
if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
"startActivity() behind front, mUserLeaving=false");
}
task = activityTask;
// Slot the activity into the history stack and proceed
if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to stack to task " + task,
new RuntimeException("here").fillInStackTrace());
// TODO: Need to investigate if it is okay for the controller to already be created by the
// time we get to this point. I think it is, but need to double check.
// Use test in b/34179495 to trace the call path.
if (r.getWindowContainerController() == null) {
r.createWindowContainer();------------------------>創(chuàng)建windowContainer
}
task.setFrontOfTask();--------------->將activityRecord所在task棧放在棧頂
2:創(chuàng)建AppWindowContainerController的過程
在AppWindowContainerController的構(gòu)造方法中會創(chuàng)建一個AppWindowToken,AppWindowToken的數(shù)據(jù)類型是WindowToken跷跪,WindowToken的數(shù)據(jù)類型是WindowContainer<WindowState>馋嗜,在WindowContainer中一個成員變量:
protected final WindowList<E> mChildren = new WindowList<E>();從上面我們可以看出AppWindowToken關(guān)聯(lián)著一組WindowState,這樣通過AppWindowContainerController將ActivityRecord和AppWindowToken關(guān)聯(lián)在一起,在這個階段appToken會傳遞給wms
void createWindowContainer() {
inHistory = true;
final TaskWindowContainerController taskController = task.getWindowContainerController();
// TODO(b/36505427): Maybe this call should be moved inside updateOverrideConfiguration()
task.updateOverrideConfigurationFromLaunchBounds();
// Make sure override configuration is up-to-date before using to create window controller.
updateOverrideConfiguration();
mWindowContainerController = new AppWindowContainerController(taskController, appToken,
this, Integer.MAX_VALUE /* add on top */, info.screenOrientation, fullscreen,
(info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0, info.configChanges,
task.voiceSession != null, mLaunchTaskBehind, isAlwaysFocusable(),
appInfo.targetSdkVersion, mRotationAnimationHint,
ActivityManagerService.getInputDispatchingTimeoutLocked(this) * 1000000L);
task.addActivityToTop(this);---------------->將activityRecord放在所在Task的棧頂
// When an activity is started directly into a split-screen fullscreen stack, we need to
// update the initial multi-window modes so that the callbacks are scheduled correctly when
// the user leaves that mode.
mLastReportedMultiWindowMode = inMultiWindowMode();
mLastReportedPictureInPictureMode = inPinnedWindowingMode();
}
public AppWindowContainerController(TaskWindowContainerController taskController,
IApplicationToken token, AppWindowContainerListener listener, int index,
int requestedOrientation, boolean fullscreen, boolean showForAllUsers, int configChanges,
boolean voiceInteraction, boolean launchTaskBehind, boolean alwaysFocusable,
int targetSdkVersion, int rotationAnimationHint, long inputDispatchingTimeoutNanos,
WindowManagerService service) {
super(listener, service);
mHandler = new H(service.mH.getLooper());
mToken = token;
synchronized(mWindowMap) {
AppWindowToken atoken = mRoot.getAppWindowToken(mToken.asBinder());
if (atoken != null) {
// TODO: Should this throw an exception instead?
Slog.w(TAG_WM, "Attempted to add existing app token: " + mToken);
return;
}
final Task task = taskController.mContainer;
if (task == null) {
throw new IllegalArgumentException("AppWindowContainerController: invalid "
+ " controller=" + taskController);
}
atoken = createAppWindow(mService, token, voiceInteraction, task.getDisplayContent(),
inputDispatchingTimeoutNanos, fullscreen, showForAllUsers, targetSdkVersion,
requestedOrientation, rotationAnimationHint, configChanges, launchTaskBehind,
alwaysFocusable, this);
if (DEBUG_TOKEN_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "addAppToken: " + atoken
+ " controller=" + taskController + " at " + index);
task.addChild(atoken, index);
}
}
1:ActivityRecord是ams端的一個真實的activity對象
2:在wms端WindowState是一個真正意義上的窗口吵瞻,WindowState是在添加窗口的時候創(chuàng)建的葛菇,在Activity啟動過程中appToken從ams傳遞到wms