android WMS--WindowContainer和WindowContainerController

1:WindowContainer

系統(tǒng)中的窗口window是放在一個容器中進行管理的险绘,它的名字就是WindowContainer,用來管理添加進來的子WindowContainer,在android系統(tǒng)中有下來的幾種WindowContainer


EB8A91CC-88FA-4912-8108-037AA2F3CCA2.png

WindowContainer有一個成員變量:WindowList<E> mChildren,用來保存添加進來的子容器宦棺,添加的流程大概是

protected void addChild(E child, Comparator<E> comparator) {
        if (child.getParent() != null) {
            throw new IllegalArgumentException("addChild: container=" + child.getName()
                    + " is already a child of container=" + child.getParent().getName()
                    + " can't add to container=" + getName());
        }
        int positionToAdd = -1;
        if (comparator != null) {
            final int count = mChildren.size();
            for (int i = 0; i < count; i++) {
                if (comparator.compare(child, mChildren.get(i)) < 0) {
                    positionToAdd = i;
                    break;
                }
            }
        }
        if (positionToAdd == -1) {
            mChildren.add(child);
        } else {
            mChildren.add(positionToAdd, child);
        }
        onChildAdded(child);
        // Set the parent after we've actually added a child in case a subclass depends on this.
        child.setParent(this);
    }

addChild這個方法主要是根據(jù)comparator來確定其具體的位置代咸,然后插入到合適的位置上呐芥,child.setParent(this);設(shè)置其父容器贩耐,這樣就能直接找到它的父容器

1.1:DisplayContent

DisplayContent對應(yīng)的是一塊顯示屏幕厦取,那么其不可能存在子屏幕的,也就是說它沒有addChild方法铡买,不過在其內(nèi)部有四個默認的container奇钞,分別用來存儲不同類型的窗口漂坏,還有一個HashMap<IBinder, WindowToken> mTokenMap用來保存當前顯示屏幕上的所有的窗口

/** The containers below are the only child containers the display can have. */
    // Contains all window containers that are related to apps (Activities)
    private final TaskStackContainers mTaskStackContainers = new TaskStackContainers(mService);
    // Contains all non-app window containers that should be displayed above the app containers
    // (e.g. Status bar)
    private final AboveAppWindowContainers mAboveAppWindowsContainers =
            new AboveAppWindowContainers("mAboveAppWindowsContainers", mService);
    // Contains all non-app window containers that should be displayed below the app containers
    // (e.g. Wallpaper).
    private final NonAppWindowContainers mBelowAppWindowsContainers =
            new NonAppWindowContainers("mBelowAppWindowsContainers", mService);
    // Contains all IME window containers. Note that the z-ordering of the IME windows will depend
    // on the IME target. We mainly have this container grouping so we can keep track of all the IME
    // window containers together and move them in-sync if/when needed. We use a subclass of
    // WindowContainer which is omitted from screen magnification, as the IME is never magnified.
    private final NonMagnifiableWindowContainers mImeWindowsContainers =
            new NonMagnifiableWindowContainers("mImeWindowsContainers", mService);
    private final HashMap<IBinder, WindowToken> mTokenMap = new HashMap();
1.2:TaskStack

TaskStack用來管理WMS端的棧谷徙,和AMS的ActivityStack是一一對應(yīng)的,并且id也是一樣的谋旦,TaskStack存儲的是Task

1.3:Task

Task類似于任務(wù)棧屈尼,用來管理WindowToken/AppWindowToken的,和AMS端的TaskRecord是一一對應(yīng)的,并且id也是相同的

1.4:AppWindowToken/WindowToken

WindowToken關(guān)聯(lián)著一組token相同的WindowState,用來管理WindowState的

1.5:WindoState

WindowState是一個窗口單元甲捏,對應(yīng)于wms的一個窗口摊鸡,但是窗口有不同的類型蚕冬,有子窗口囤热,普通應(yīng)用程序窗口旁蔼,系統(tǒng)窗口疙教,子窗口和父窗口是共token的,因此WindowState有addChild的功能

2:WindowContainerController

我們都知道AMS和WMS兩者之間的數(shù)據(jù)都是一一對應(yīng)的限佩,那么它們之間是怎么建立連接的呢祟同,就是通過WindowContainerController建立它們之間的聯(lián)系的


windowController.png
2.1:DisplayWindowController

每創(chuàng)建一個ActivityDisplay的時候都會創(chuàng)建一個DisplayWindowController

   ActivityDisplay(ActivityStackSupervisor supervisor, int displayId) {
        this(supervisor, supervisor.mDisplayManager.getDisplay(displayId));
    }
    ActivityDisplay(ActivityStackSupervisor supervisor, Display display) {
        mSupervisor = supervisor;
        mDisplayId = display.getDisplayId();
        mDisplay = display;
        mWindowContainerController = createWindowContainerController();
        updateBounds();
    }
   public DisplayWindowController(Display display, WindowContainerListener listener) {
        super(listener, WindowManagerService.getInstance());
        mDisplayId = display.getDisplayId();
        synchronized (mWindowMap) {
            final long callingIdentity = Binder.clearCallingIdentity();
            try {
                mRoot.createDisplayContent(display, this /* controller */);
            } finally {
                Binder.restoreCallingIdentity(callingIdentity);
            }
            if (mContainer == null) {
                throw new IllegalArgumentException("Trying to add display=" + display
                        + " dc=" + mRoot.getDisplayContent(mDisplayId));
            }
        }
    }

在DisplayWIndowController的構(gòu)造方法中會創(chuàng)建一個DisplayContent

2:2:StackWindowController
 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);
            getRawBounds(outBounds);
        }
    }

在其構(gòu)造方法中創(chuàng)建一個TaskStack

2:3: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 */);
        }
    }
    @VisibleForTesting
    Task createTask(int taskId, TaskStack stack, int userId, int resizeMode,
            boolean supportsPictureInPicture, TaskDescription taskDescription) {
        return new Task(taskId, stack, userId, mService, resizeMode, supportsPictureInPicture,
                taskDescription, this);
    }

在其構(gòu)造方法中創(chuàng)建Task

2:4:AppWindowContainerController
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);
        }
    }

在其構(gòu)造方法中會創(chuàng)建一個AppWindowToken

3:AMS和WMS數(shù)據(jù)結(jié)構(gòu)對應(yīng)關(guān)系
Controller.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市滤蝠,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌房轿,老刑警劉巖所森,帶你破解...
    沈念sama閱讀 216,651評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件焕济,死亡現(xiàn)場離奇詭異,居然都是意外死亡掩幢,警方通過查閱死者的電腦和手機上鞠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,468評論 3 392
  • 文/潘曉璐 我一進店門芍阎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人轮听,你說我怎么就攤上這事岭佳。” “怎么了述寡?”我有些...
    開封第一講書人閱讀 162,931評論 0 353
  • 文/不壞的土叔 我叫張陵辨赐,是天一觀的道長京办。 經(jīng)常有香客問我,道長不恭,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,218評論 1 292
  • 正文 為了忘掉前任折晦,我火速辦了婚禮沾瓦,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘风喇。我一直安慰自己缕探,他們只是感情好,可當我...
    茶點故事閱讀 67,234評論 6 388
  • 文/花漫 我一把揭開白布耙考。 她就那樣靜靜地躺著倦始,像睡著了一般。 火紅的嫁衣襯著肌膚如雪鞋邑。 梳的紋絲不亂的頭發(fā)上怒坯,一...
    開封第一講書人閱讀 51,198評論 1 299
  • 那天剔猿,我揣著相機與錄音嬉荆,去河邊找鬼。 笑死鄙早,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的舱污。 我是一名探鬼主播弥虐,決...
    沈念sama閱讀 40,084評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼媚赖,長吁一口氣:“原來是場噩夢啊……” “哼惧磺!你這毒婦竟也來了捻撑?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,926評論 0 274
  • 序言:老撾萬榮一對情侶失蹤番捂,失蹤者是張志新(化名)和其女友劉穎描验,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體膘流,經(jīng)...
    沈念sama閱讀 45,341評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡呼股,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,563評論 2 333
  • 正文 我和宋清朗相戀三年彭谁,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片缠局。...
    茶點故事閱讀 39,731評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡狭园,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出罚舱,到底是詐尸還是另有隱情绎谦,我是刑警寧澤,帶...
    沈念sama閱讀 35,430評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站恩掷,受9級特大地震影響赃蛛,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜破托,卻給世界環(huán)境...
    茶點故事閱讀 41,036評論 3 326
  • 文/蒙蒙 一歧蒋、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧萝映,春花似錦阐虚、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,676評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至避矢,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間亥宿,已是汗流浹背砂沛。 一陣腳步聲響...
    開封第一講書人閱讀 32,829評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留材蛛,地道東北人怎抛。 一個月前我還...
    沈念sama閱讀 47,743評論 2 368
  • 正文 我出身青樓芽淡,卻偏偏與公主長得像,于是被迫代替她去往敵國和親挣菲。 傳聞我的和親對象是個殘疾皇子掷邦,可洞房花燭夜當晚...
    茶點故事閱讀 44,629評論 2 354