Android之AMS和WMS數(shù)據(jù)對應(yīng)關(guān)系(基于Android9.0)

本文主要是講述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

AMS和WMS的各個對象的對應(yīng)關(guān)系

test.jpg
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末甘磨,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子眯停,更是在濱河造成了極大的恐慌宽档,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,843評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件庵朝,死亡現(xiàn)場離奇詭異,居然都是意外死亡又厉,警方通過查閱死者的電腦和手機(jī)九府,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,538評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來覆致,“玉大人侄旬,你說我怎么就攤上這事』吐瑁” “怎么了儡羔?”我有些...
    開封第一講書人閱讀 163,187評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長璧诵。 經(jīng)常有香客問我汰蜘,道長,這世上最難降的妖魔是什么之宿? 我笑而不...
    開封第一講書人閱讀 58,264評論 1 292
  • 正文 為了忘掉前任族操,我火速辦了婚禮,結(jié)果婚禮上比被,老公的妹妹穿的比我還像新娘色难。我一直安慰自己,他們只是感情好等缀,可當(dāng)我...
    茶點故事閱讀 67,289評論 6 390
  • 文/花漫 我一把揭開白布枷莉。 她就那樣靜靜地躺著,像睡著了一般尺迂。 火紅的嫁衣襯著肌膚如雪笤妙。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,231評論 1 299
  • 那天噪裕,我揣著相機(jī)與錄音危喉,去河邊找鬼。 笑死州疾,一個胖子當(dāng)著我的面吹牛辜限,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播严蓖,決...
    沈念sama閱讀 40,116評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼薄嫡,長吁一口氣:“原來是場噩夢啊……” “哼氧急!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起毫深,我...
    開封第一講書人閱讀 38,945評論 0 275
  • 序言:老撾萬榮一對情侶失蹤吩坝,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后哑蔫,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體钉寝,經(jīng)...
    沈念sama閱讀 45,367評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,581評論 2 333
  • 正文 我和宋清朗相戀三年闸迷,在試婚紗的時候發(fā)現(xiàn)自己被綠了嵌纲。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,754評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡腥沽,死狀恐怖逮走,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情今阳,我是刑警寧澤师溅,帶...
    沈念sama閱讀 35,458評論 5 344
  • 正文 年R本政府宣布,位于F島的核電站盾舌,受9級特大地震影響墓臭,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜妖谴,卻給世界環(huán)境...
    茶點故事閱讀 41,068評論 3 327
  • 文/蒙蒙 一起便、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧窖维,春花似錦榆综、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,692評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至琳轿,卻和暖如春判沟,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背崭篡。 一陣腳步聲響...
    開封第一講書人閱讀 32,842評論 1 269
  • 我被黑心中介騙來泰國打工挪哄, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人琉闪。 一個月前我還...
    沈念sama閱讀 47,797評論 2 369
  • 正文 我出身青樓迹炼,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子斯入,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,654評論 2 354

推薦閱讀更多精彩內(nèi)容