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)谆趾。