Window, WindowManager, WindowManagerService 的簡單梳理(二)- Window 的添加過程
Window, WindowManager, WindowManagerService 的簡單梳理(三)- Activiy 的 Window 的創(chuàng)建過程
看完任玉剛的《Android 開發(fā)藝術(shù)探索》中關(guān)于Window 和 WindowManager 的章節(jié),想大致上把 Window, WindowManager, WindowManagerService 的關(guān)系梳理一下。
這本書上講的算是比較明白了,如果能夠硬著頭皮、逐字逐句、結(jié)合源碼看下來,應(yīng)該是可以看明白的。
不過看完以后,總少了一點(diǎn)通透的感覺,可能是因?yàn)檫@本書里對 WindowManagerService 本身的功能講的不多。并且,幾個概念繞來繞去,很容易互相混淆。
基本概念
-
Window : 在講 WindowManagerService 的時候,這里的 Window 都不是指 android.view.Window 類,也不是它的子類 PhoneWindow。甚至于說,WindowManager 名字中的“Window”的含義,與 WindowManagerService 名字中的“Window”的含義是否相同?我不確定。非要下定義的話,可能林學(xué)森的《深入理解 Android 內(nèi)核設(shè)計思想》一書中 WMS 部分的解釋更接近真相一點(diǎn)。
“Window” 表明它是與窗口相關(guān)的,“Manager”指出它具有管理者的身份。。。“窗口”是一個抽象的概念,從用戶的角度來講,它是一個“界面”,如撥號面板;從 SurfaceFlinger 的角度來看,它是一個 Layer,承載著和“界面”有關(guān)的數(shù)據(jù)和屬性;從 WMS 的角度來看,它是一個 WindowState,用于管理和“界面”有關(guān)的狀態(tài)。
所以,這里的 Window 通常不是指具體的某個類,更多的是指一個抽象概念。
-
WindowManager :這個是有具體類和接口的。WindowManager 是一個接口,繼承自 ViewManager 接口,具體實(shí)現(xiàn)是 WindowManagerImpl。WindowManager 并沒有給 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 也是有對應(yīng)的 WindowManagerService 類(/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java)的;繼承自 IWindowManager.Stub,當(dāng)然,這是一個 aidl (/frameworks/base/core/java/android/view/IWindowManager.aidl),有一個實(shí)現(xiàn) IWindowManagerImpl.java (/frameworks/base/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java),但是沒發(fā)現(xiàn)這個實(shí)現(xiàn)對我們的分析有什么作用。
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 是不同的兩個類和接口,職責(zé)也完全不一樣。
WindowManagerService 是非常重要的一個系統(tǒng)服務(wù),在SystemServer 中啟動和注冊,功能也復(fù)雜的多;WindowManager 則相對簡單了很多。也可以看出,我們 通過getSystemService 得到的是 WindowManager,并不是 WindowManagerService。
WindowManagerService 實(shí)現(xiàn)的是 IWindowManager,一個 aidl 接口。WindowManager 本身就是一個接口,繼承自 ViewManager。IWindowManager 接口本身也是巨復(fù)雜,跟 WindowManager 沒有一毛錢關(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();
...
}
可見,Activity 的 WindowManager 是來自 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);
}
可見,setWindowManager 中,Window 并沒有直接把入?yún)⒌?WindowManager wm 作為自己的 mWindowManager ,而是重新創(chuàng)建了一個 WindowManagerImpl 對象。
那么如果直接用 mContext.getSystemService(Context.WINDOW_SERVICE),得到的又是什么呢?
從上面代碼中的類型強(qiáng)轉(zhuǎn),已經(jīng)可以看出來,是 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 的具體實(shí)現(xiàn) WindowManagerImpl,不是 WindowManagerService。
因?yàn)檫@幾個方法的名字,讓我對 WindowManager 和 WindowManagerService 的關(guān)系糾結(jié)了很久。但是,他們倆真的就沒有什么關(guān)系,只是名字很像而已。
以上內(nèi)容參考了《Android 開發(fā)藝術(shù)探索》,也參考了《深入理解 Android 內(nèi)核設(shè)計思想》,也參考了 Android 源碼,如果有理解不對的地方,那一定是我學(xué)藝不精,與兩位作者無關(guān)。