Window, WindowManager, WindowManagerService 的简单梳理(一)

Window, WindowManager, WindowManagerService 的简单梳理(二)- Window 的添加过程

Window, WindowManager, WindowManagerService 的简单梳理(三)- Activiy 的 Window 的创建过程

看完任玉刚的《Android 开发艺术探索》中关于Window 和 WindowManager 的章节,想大致上把 Window, WindowManager, WindowManagerService 的关系梳理一下。
这本书上讲的算是比较明白了,如果能够硬着头皮、逐字逐句、结合源码看下来,应该是可以看明白的。
不过看完以后,总少了一点通透的感觉,可能是因为这本书里对 WindowManagerService 本身的功能讲的不多。并且,几个概念绕来绕去,很容易互相混淆。

基本概念

  • Window : 在讲 WindowManagerService 的时候,这里的 Window 都不是指 android.view.Window 类,也不是它的子类 PhoneWindow。甚至于说,WindowManager 名字中的“Window”的含义,与 WindowManagerService 名字中的“Window”的含义是否相同?我不确定。非要下定义的话,可能林学森的《深入理解 Android 内核设计思想》一书中 WMS 部分的解释更接近真相一点。

    “Window” 表明它是与窗口相关的,“Manager”指出它具有管理者的身份。。。“窗口”是一个抽象的概念,从用户的角度来讲,它是一个“界面”,如拨号面板;从 SurfaceFlinger 的角度来看,它是一个 Layer,承载着和“界面”有关的数据和属性;从 WMS 的角度来看,它是一个 WindowState,用于管理和“界面”有关的状态。

    所以,这里的 Window 通常不是指具体的某个类,更多的是指一个抽象概念。

  • WindowManager :这个是有具体类和接口的。WindowManager 是一个接口,继承自 ViewManager 接口,具体实现是 WindowManagerImpl。WindowManager 并没有给 ViewManager 扩展多少方法,更多的意义可能是定义了一些静态接口和静态类,如 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 也是有对应的 WindowManagerService 类(/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java)的;继承自 IWindowManager.Stub,当然,这是一个 aidl (/frameworks/base/core/java/android/view/IWindowManager.aidl),有一个实现 IWindowManagerImpl.java (/frameworks/base/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java),但是没发现这个实现对我们的分析有什么作用。
    WindowManagerService 由 SystemServer 启动,代码如下。

    // 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 的部分也截出来,就是想说明 WindowManager 和 WindowManagerService 是不同的两个类和接口,职责也完全不一样。

WindowManagerService 是非常重要的一个系统服务,在SystemServer 中启动和注册,功能也复杂的多;WindowManager 则相对简单了很多。也可以看出,我们 通过getSystemService 得到的是 WindowManager,并不是 WindowManagerService。
WindowManagerService 实现的是 IWindowManager,一个 aidl 接口。WindowManager 本身就是一个接口,继承自 ViewManager。IWindowManager 接口本身也是巨复杂,跟 WindowManager 没有一毛钱关系。

在 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();
        ...
    }

可见,Activity 的 WindowManager 是来自 mWindow。我们都知道,Activity 的 mWindow 其实就是 PhoneWindow;并且上面的代码中有 mWindow.setWindowManager() 的调用,那就看看 setWindowManager 是怎么实现的吧。

// 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);
    }

可见,setWindowManager 中,Window 并没有直接把入参的 WindowManager wm 作为自己的 mWindowManager ,而是重新创建了一个 WindowManagerImpl 对象。

那么如果直接用 mContext.getSystemService(Context.WINDOW_SERVICE),得到的又是什么呢?
从上面代码中的类型强转,已经可以看出来,是 WindowManager,不是 WindowManagerService。不过,我们还是看看代码吧。

// 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 的具体实现 WindowManagerImpl,不是 WindowManagerService。

因为这几个方法的名字,让我对 WindowManager 和 WindowManagerService 的关系纠结了很久。但是,他们俩真的就没有什么关系,只是名字很像而已。

以上内容参考了《Android 开发艺术探索》,也参考了《深入理解 Android 内核设计思想》,也参考了 Android 源码,如果有理解不对的地方,那一定是我学艺不精,与两位作者无关。

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

推荐阅读更多精彩内容