Android之AMS和WMS数据对应关系(基于Android9.0)

本文主要是讲述activity启动过程中ams和wms的数据是怎么关联起来的

ActivityStack和TaskStack

1:在Activity启动过程中,首先会创建ActivityRecord对象,在ActivityRecord的构造方法中会创建一个Token对象,Token继承于IApplicationToken.Stub,appToken会保存在app应用程序段,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:创建完ActivityRecord之后,会创建ActivityStack,在ActivityStack的构造方法中会创建StackWindowController,android是支持多屏显示的,ActivityStack是由ActivityDisplay负责创建,ActivityStack可以根据stackid来区分,DisplayContent表示的一块独立的显示屏幕,在StackWindowController的构造方法中会根据当前activity所属于的DisplayContent来创建一个TaskStack,TaskStack的stackId和前面的stackId是完全一致的
3:StackWindowController作为ActivityStack的成员变量mWindowContainerController,DisplayContent通过调用creatStack函数会将StackWindowController传递给TaskStack,TaskStack继承于WindowContainer,在TaskStack的构造方法中调用了父类的setController将传递过来的StackWindowController对象设置成自己的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关联起来
1:ActivityStackSuperVisor管理ActivityStack,ActivityStackSuperVisor的成员变量
private final SparseArray<ActivityDisplay> mActivityDisplays = new SparseArray<>();维护当前设备上的所有ActivityDisplay
2:ActivityDisplay的成员变量private final ArrayList<ActivityStack> mStacks = new ArrayList<>();管理着当前的ActivityStack
3:在wms端RootWindowContainer持有WindowList<Displaycontent>列表,维护着所有的DisplayContent,DisplayContent代表的是一块显示屏幕
4:DisplayContent的静态内部类TaskStackContainers持有WindowList<TaskStack>列表,维护着所有的TaskStack

TaskRecord和Task

1:创建完ActivityStack之后便需要创建一个TaskRecord,是否创建一个新的TaskRecord取决于应用设置的flag和taskAffnity,是否需要创建一个新的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负责创建Task并且管理task,task创建完毕之后会将其移到其所在Stack的栈顶,并且调用createWindowContainer创建一个TaskWindowContainerController,TaskRecord持有mWindowContainerController对象,在TaskWindowContainerController的构造方法中会创建一个Task对象,将创建好的Task至于之前创建的TaskStack的栈顶,同时将mWindowContainerController设置为task的windowContainer对象,这样TaskRecord和Task通过TaskWindowContainerController关联起来了

    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);----->创建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));--------------------->创建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内部有一个成员变量:final ArrayList<ActivityRecord> mActivities;来管理当前task的activity
2:一个Activity在ams中可能有多个ActivityRecord,但是是不同的对象
在wms端
1:Task持有WindowList<AppWindowToken>对象
2:AppWindowToken继承WindowContainer<WindowState>,AppWindowToken持有WindowList<WindowState>,表明AppWindowToken关联着一组WindowState

ActivityRecord和AppWindowToken(WindowState)

1:创建完成TaskRecord之后便为ActivityRecord创建一个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();------------------------>创建windowContainer
    }
    task.setFrontOfTask();--------------->将activityRecord所在task栈放在栈顶

2:创建AppWindowContainerController的过程
在AppWindowContainerController的构造方法中会创建一个AppWindowToken,AppWindowToken的数据类型是WindowToken,WindowToken的数据类型是WindowContainer<WindowState>,在WindowContainer中一个成员变量:
protected final WindowList<E> mChildren = new WindowList<E>();从上面我们可以看出AppWindowToken关联着一组WindowState,这样通过AppWindowContainerController将ActivityRecord和AppWindowToken关联在一起,在这个阶段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是在添加窗口的时候创建的,在Activity启动过程中appToken从ams传递到wms

AMS和WMS的各个对象的对应关系

test.jpg
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335

推荐阅读更多精彩内容