Window, WindowManager, WindowManagerService 的簡(jiǎn)單梳理(一)

Window, WindowManager, WindowManagerService 的簡(jiǎn)單梳理(二)- Window 的添加過(guò)程

Window, WindowManager, WindowManagerService 的簡(jiǎn)單梳理(三)- Activiy 的 Window 的創(chuàng)建過(guò)程

看完任玉剛的《Android 開(kāi)發(fā)藝術(shù)探索》中關(guān)于Window 和 WindowManager 的章節(jié)颅拦,想大致上把 Window, WindowManager, WindowManagerService 的關(guān)系梳理一下。
這本書(shū)上講的算是比較明白了察绷,如果能夠硬著頭皮、逐字逐句、結(jié)合源碼看下來(lái),應(yīng)該是可以看明白的挣输。
不過(guò)看完以后齐饮,總少了一點(diǎn)通透的感覺(jué)捐寥,可能是因?yàn)檫@本書(shū)里對(duì) WindowManagerService 本身的功能講的不多。并且祖驱,幾個(gè)概念繞來(lái)繞去握恳,很容易互相混淆。

基本概念

  • Window : 在講 WindowManagerService 的時(shí)候捺僻,這里的 Window 都不是指 android.view.Window 類乡洼,也不是它的子類 PhoneWindow。甚至于說(shuō)匕坯,WindowManager 名字中的“Window”的含義束昵,與 WindowManagerService 名字中的“Window”的含義是否相同?我不確定葛峻。非要下定義的話锹雏,可能林學(xué)森的《深入理解 Android 內(nèi)核設(shè)計(jì)思想》一書(shū)中 WMS 部分的解釋更接近真相一點(diǎn)。

    “Window” 表明它是與窗口相關(guān)的术奖,“Manager”指出它具有管理者的身份礁遵。。采记∮赌停“窗口”是一個(gè)抽象的概念,從用戶的角度來(lái)講挺庞,它是一個(gè)“界面”晰赞,如撥號(hào)面板;從 SurfaceFlinger 的角度來(lái)看,它是一個(gè) Layer掖鱼,承載著和“界面”有關(guān)的數(shù)據(jù)和屬性然走;從 WMS 的角度來(lái)看,它是一個(gè) WindowState戏挡,用于管理和“界面”有關(guān)的狀態(tài)芍瑞。

    所以,這里的 Window 通常不是指具體的某個(gè)類褐墅,更多的是指一個(gè)抽象概念拆檬。

  • WindowManager :這個(gè)是有具體類和接口的。WindowManager 是一個(gè)接口妥凳,繼承自 ViewManager 接口竟贯,具體實(shí)現(xiàn)是 WindowManagerImpl。WindowManager 并沒(méi)有給 ViewManager 擴(kuò)展多少方法逝钥,更多的意義可能是定義了一些靜態(tài)接口和靜態(tài)類屑那,如 WindowManager.LayoutParams。所以我們有必要知道 ViewManager 的主要方法艘款。

    // ViewManager
    public interface ViewManager
    {
        /**
         * Assign the passed LayoutParams to the passed View and add the view to the window.
         * <p>Throws {@link android.view.WindowManager.BadTokenException} for certain programming
         * errors, such as adding a second view to a window without removing the first view.
         * <p>Throws {@link android.view.WindowManager.InvalidDisplayException} if the window is on a
         * secondary {@link Display} and the specified display can't be found
         * (see {@link android.app.Presentation}).
         * @param view The view to be added to this window.
         * @param params The LayoutParams to assign to view.
         */
        public void addView(View view, ViewGroup.LayoutParams params);
        public void updateViewLayout(View view, ViewGroup.LayoutParams params);
        public void removeView(View view);
    }
    

    以及 WindowManager.LayoutParams 的聲明持际。

    // WindowManager
    public static class LayoutParams extends ViewGroup.LayoutParams 
                                             implements Parcelable {
        ...
        public int type;
        ...
        public int flags;
        ...
    }
    
  • WindowManagerService : 真正的 WindowManagerService 也是有對(duì)應(yīng)的 WindowManagerService 類(/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java)的;繼承自 IWindowManager.Stub哗咆,當(dāng)然蜘欲,這是一個(gè) aidl (/frameworks/base/core/java/android/view/IWindowManager.aidl),有一個(gè)實(shí)現(xiàn) IWindowManagerImpl.java (/frameworks/base/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java)晌柬,但是沒(méi)發(fā)現(xiàn)這個(gè)實(shí)現(xiàn)對(duì)我們的分析有什么作用姥份。
    WindowManagerService 由 SystemServer 啟動(dòng),代碼如下空繁。

    // SystemServe
     /**
      * Starts a miscellaneous grab bag of stuff that has yet to be refactored
      * and organized.
      */
     private void startOtherServices() {
         ...
         WindowManagerService wm = null;
         ...
             //注意殿衰,這是 WindowManagerService
             wm = WindowManagerService.main(context, inputManager,
                     mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
                     !mFirstBoot, mOnlyCore);
             ServiceManager.addService(Context.WINDOW_SERVICE, wm);
         ...
         // Update the configuration for this context by hand, because we're going
         // to start using it before the config change done in wm.systemReady() will
         // propagate to it.
         Configuration config = wm.computeNewConfiguration();
         DisplayMetrics metrics = new DisplayMetrics();
         //注意,這是 WindowManager
         WindowManager w = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
         w.getDefaultDisplay().getMetrics(metrics);
         context.getResources().updateConfiguration(config, metrics);
         ...
     }
    

    特意把 WindowManager 的部分也截出來(lái)盛泡,就是想說(shuō)明 WindowManager 和 WindowManagerService 是不同的兩個(gè)類和接口,職責(zé)也完全不一樣娱颊。

WindowManagerService 是非常重要的一個(gè)系統(tǒng)服務(wù)傲诵,在SystemServer 中啟動(dòng)和注冊(cè),功能也復(fù)雜的多箱硕;WindowManager 則相對(duì)簡(jiǎn)單了很多拴竹。也可以看出,我們 通過(guò)getSystemService 得到的是 WindowManager剧罩,并不是 WindowManagerService栓拜。
WindowManagerService 實(shí)現(xiàn)的是 IWindowManager,一個(gè) aidl 接口。WindowManager 本身就是一個(gè)接口幕与,繼承自 ViewManager挑势。IWindowManager 接口本身也是巨復(fù)雜,跟 WindowManager 沒(méi)有一毛錢關(guān)系啦鸣。

在 Activity 中獲取 WindowManager

我看的代碼是 API 25潮饱。Activity 中提供了2種方法獲取 WindowManager。

// Activity

    /** Retrieve the window manager for showing custom windows. */
    public WindowManager getWindowManager() {
        return mWindowManager;
    }

    @Override
    public Object getSystemService(@ServiceName @NonNull String name) {
        if (getBaseContext() == null) {
            throw new IllegalStateException(
                    "System services not available to Activities before onCreate()");
        }

        if (WINDOW_SERVICE.equals(name)) {
            return mWindowManager;
        } else if (SEARCH_SERVICE.equals(name)) {
            ensureSearchManager();
            return mSearchManager;
        }
        return super.getSystemService(name);
    }

    final void attach(Context context, ActivityThread aThread,
            Instrumentation instr, IBinder token, int ident,
            Application application, Intent intent, ActivityInfo info,
            CharSequence title, Activity parent, String id,
            NonConfigurationInstances lastNonConfigurationInstances,
            Configuration config, String referrer, IVoiceInteractor voiceInteractor,
            Window window) {
        ...
        mWindow = new PhoneWindow(this, window);
        mWindow.setWindowControllerCallback(this);
        mWindow.setCallback(this);
        ...
        mWindow.setWindowManager(
                (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
                mToken, mComponent.flattenToString(),
                (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
        if (mParent != null) {
            mWindow.setContainer(mParent.getWindow());
        }
        mWindowManager = mWindow.getWindowManager();
        ...
    }

可見(jiàn)诫给,Activity 的 WindowManager 是來(lái)自 mWindow香拉。我們都知道,Activity 的 mWindow 其實(shí)就是 PhoneWindow中狂;并且上面的代碼中有 mWindow.setWindowManager() 的調(diào)用凫碌,那就看看 setWindowManager 是怎么實(shí)現(xiàn)的吧。

// android.view.Window
    /**
     * Set the window manager for use by this Window to, for example,
     * display panels.  This is <em>not</em> used for displaying the
     * Window itself -- that must be done by the client.
     *
     * @param wm The window manager for adding new windows.
     */
    public void setWindowManager(WindowManager wm, IBinder appToken, String appName,
            boolean hardwareAccelerated) {
        mAppToken = appToken;
        mAppName = appName;
        mHardwareAccelerated = hardwareAccelerated
                || SystemProperties.getBoolean(PROPERTY_HARDWARE_UI, false);
        if (wm == null) {
            wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
        }
        mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);
    }

可見(jiàn)胃榕,setWindowManager 中证鸥,Window 并沒(méi)有直接把入?yún)⒌?WindowManager wm 作為自己的 mWindowManager ,而是重新創(chuàng)建了一個(gè) WindowManagerImpl 對(duì)象勤晚。

那么如果直接用 mContext.getSystemService(Context.WINDOW_SERVICE)枉层,得到的又是什么呢?
從上面代碼中的類型強(qiáng)轉(zhuǎn)赐写,已經(jīng)可以看出來(lái)鸟蜡,是 WindowManager,不是 WindowManagerService挺邀。不過(guò)揉忘,我們還是看看代碼吧。

// ContextImpl
    @Override
    public Object getSystemService(String name) {
        return SystemServiceRegistry.getSystemService(this, name);
    }

// SystemServiceRegistry
    public static Object getSystemService(ContextImpl ctx, String name) {
        ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
        return fetcher != null ? fetcher.getService(ctx) : null;
    }

    private static <T> void registerService(String serviceName, Class<T> serviceClass,
            ServiceFetcher<T> serviceFetcher) {
        SYSTEM_SERVICE_NAMES.put(serviceClass, serviceName);
        SYSTEM_SERVICE_FETCHERS.put(serviceName, serviceFetcher);
    }

    static {
        ...
        registerService(Context.WINDOW_SERVICE, WindowManager.class,
                new CachedServiceFetcher<WindowManager>() {
            @Override
            public WindowManager createService(ContextImpl ctx) {
                return new WindowManagerImpl(ctx);
            }});
        ...
    }

總之端铛,我們能夠從 Activity 或者 Context 拿到的泣矛,就是 WindowManager 的具體實(shí)現(xiàn) WindowManagerImpl,不是 WindowManagerService禾蚕。

因?yàn)檫@幾個(gè)方法的名字您朽,讓我對(duì) WindowManager 和 WindowManagerService 的關(guān)系糾結(jié)了很久。但是换淆,他們倆真的就沒(méi)有什么關(guān)系哗总,只是名字很像而已。

以上內(nèi)容參考了《Android 開(kāi)發(fā)藝術(shù)探索》倍试,也參考了《深入理解 Android 內(nèi)核設(shè)計(jì)思想》讯屈,也參考了 Android 源碼,如果有理解不對(duì)的地方县习,那一定是我學(xué)藝不精涮母,與兩位作者無(wú)關(guān)谆趾。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市叛本,隨后出現(xiàn)的幾起案子沪蓬,更是在濱河造成了極大的恐慌,老刑警劉巖炮赦,帶你破解...
    沈念sama閱讀 216,651評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件怜跑,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡吠勘,警方通過(guò)查閱死者的電腦和手機(jī)性芬,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,468評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)剧防,“玉大人植锉,你說(shuō)我怎么就攤上這事∏途校” “怎么了俊庇?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,931評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)鸡挠。 經(jīng)常有香客問(wèn)我辉饱,道長(zhǎng),這世上最難降的妖魔是什么拣展? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,218評(píng)論 1 292
  • 正文 為了忘掉前任彭沼,我火速辦了婚禮,結(jié)果婚禮上备埃,老公的妹妹穿的比我還像新娘姓惑。我一直安慰自己,他們只是感情好按脚,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,234評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布于毙。 她就那樣靜靜地躺著,像睡著了一般辅搬。 火紅的嫁衣襯著肌膚如雪唯沮。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,198評(píng)論 1 299
  • 那天伞辛,我揣著相機(jī)與錄音烂翰,去河邊找鬼。 笑死蚤氏,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的踊兜。 我是一名探鬼主播竿滨,決...
    沈念sama閱讀 40,084評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了于游?” 一聲冷哼從身側(cè)響起毁葱,我...
    開(kāi)封第一講書(shū)人閱讀 38,926評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎贰剥,沒(méi)想到半個(gè)月后倾剿,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,341評(píng)論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蚌成,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,563評(píng)論 2 333
  • 正文 我和宋清朗相戀三年前痘,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片担忧。...
    茶點(diǎn)故事閱讀 39,731評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡芹缔,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出瓶盛,到底是詐尸還是另有隱情最欠,我是刑警寧澤,帶...
    沈念sama閱讀 35,430評(píng)論 5 343
  • 正文 年R本政府宣布惩猫,位于F島的核電站芝硬,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏轧房。R本人自食惡果不足惜拌阴,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,036評(píng)論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望锯厢。 院中可真熱鬧皮官,春花似錦、人聲如沸实辑。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,676評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)剪撬。三九已至摄乒,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間残黑,已是汗流浹背馍佑。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,829評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留梨水,地道東北人拭荤。 一個(gè)月前我還...
    沈念sama閱讀 47,743評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像疫诽,于是被迫代替她去往敵國(guó)和親舅世。 傳聞我的和親對(duì)象是個(gè)殘疾皇子旦委,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,629評(píng)論 2 354

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