掃二維碼與項目經(jīng)理溝通
我們在微信上24小時期待你的聲音
解答本文疑問/技術(shù)咨詢/運營咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流
WindowManagerService是位于Framework層的窗口管理服務(wù),它的職責(zé)是管理系統(tǒng)中的所有窗口,也就是Window,關(guān)于Window的介紹,通俗來說,Window就是手機上一塊顯示區(qū)域,也就是Android中的繪制畫布Surface,添加一個Window的過程,也就是申請分配一塊Surface的過程,而整個流程的管理者正是WindowManagerService;

創(chuàng)新互聯(lián)建站專注于企業(yè)全網(wǎng)營銷推廣、網(wǎng)站重做改版、伊犁網(wǎng)站定制設(shè)計、自適應(yīng)品牌網(wǎng)站建設(shè)、H5場景定制、商城系統(tǒng)網(wǎng)站開發(fā)、集團公司官網(wǎng)建設(shè)、外貿(mào)網(wǎng)站建設(shè)、高端網(wǎng)站制作、響應(yīng)式網(wǎng)頁設(shè)計等建站業(yè)務(wù),價格優(yōu)惠性價比高,為伊犁等各大城市提供網(wǎng)站開發(fā)制作服務(wù)。
今天我們來分析下窗口WMS相關(guān)的知識點;
(1)WindowManagerService概念
Framework層的窗口管理服務(wù),職責(zé)是管理Android系統(tǒng)中所有window。窗口管理服務(wù),繼承IWindowManager.Stub,Binder服務(wù)端,因此WM與WMS的交互也是一個IPC過程。WMS主要做的事情如下:
(2)WindowManager
應(yīng)用與窗口管理服務(wù)WindowManagerService交互的接口;
(3)PhoneWindowManager
實現(xiàn)了窗口的各種策略,定義了窗口相關(guān)策略,比如:告訴WMS某一個類型Window的Z-Order的值是多少,幫助WMS矯正不合理的窗口屬性,為WMS監(jiān)聽屏幕旋轉(zhuǎn)的狀態(tài),預(yù)處理一些系統(tǒng)按鍵事件;
(4)Choreographer
用戶控制窗口動畫、屏幕選擇等操作,它擁有從顯示子系統(tǒng)獲取Vsync同步事件的能力,從而可以在合適的時機通知渲染動作,避免在渲染的過程中因為發(fā)生屏幕重繪而導(dǎo)致的畫面撕裂。WMS使用Choreographer負(fù)責(zé)驅(qū)動所有的窗口動畫、屏幕旋轉(zhuǎn)動畫、墻紙動畫的渲染;
(5)DisplayContent
用于描述多屏輸出相關(guān)信息;
根據(jù)窗口的顯示位置將其分組。隸屬于同一個DisplayContent的窗口將會被顯示在同一個屏幕中。每個DisplayContent都對應(yīng)著唯一ID,在添加窗口的時候可以通過指定這個ID決定其將顯示在哪個屏幕中;
DisplayContent是一個非常具有隔離性的一個概念。處于不同DisplayContent的兩個窗口在布局、顯示順序以及動畫處理上不會產(chǎn)生任何耦合;
(6)WindowState
描述窗口的狀態(tài)信息以及和WindowManagerService進行通信,一般一個窗口對應(yīng)一個WindowState。它用來表示一個窗口的所有屬性;
(7)WindowToken
(8)Session
App進程通過建立Session代理對象和Session對象通信,進而和WMS建立連接;
(9)SurfaceFlinger
SurfaceFlinger負(fù)責(zé)管理Android系統(tǒng)的幀緩沖區(qū)(Frame Buffer),Android設(shè)備的顯示屏被抽象為一個幀緩沖區(qū),而Android系統(tǒng)中的SurfaceFlinger服務(wù)就是通過向這個幀緩沖區(qū)寫入內(nèi)容來繪制應(yīng)用程序中的用戶界面的;
(10)InputManager
管理每個窗口的輸入事件通道(InputChannel)以及向通道上派發(fā)事件;
(11)Animator
所有窗口動畫的總管(WindowStateAnimator對象)。在Choreographer的驅(qū)動下,逐個渲染所有的動畫;
- // 窗口特征標(biāo)記
- public int flags;
- // 當(dāng)該window對用戶可見時,允許鎖屏
- public static final int FLAG_ALLOW_LOCK_WHILE_SCREEN_ON = 0x00000001;
- // 窗口后面的所有內(nèi)容都變暗
- public static final int FLAG_DIM_BEHIND = 0x00000002;
- // 窗口后面的所有內(nèi)容都變模糊
- public static final int FLAG_BLUR_BEHIND = 0x00000004;
- // 窗口不能獲得焦點
- public static final int FLAG_NOT_FOCUSABLE = 0x00000008;
- // 窗口不接受觸摸屏事件
- public static final int FLAG_NOT_TOUCHABLE = 0x00000010;
- // 即使在該window可獲得焦點情況下,允許該窗口之處的點擊事件傳遞到當(dāng)前窗口后面的窗口去
- public static final int FLAG_NOT_TOUCH_MODAL = 0x00000020;
- // 當(dāng)手機處于睡眠狀態(tài),如果屏幕被按下,那么該window將第一個收到觸摸事件
- public static final int FLAG_TOUCHABLE_WHEN_WAKING = 0x00000040;
- // 當(dāng)該window對用戶可見時,屏幕處于常亮狀態(tài)
- public static final int FLAG_KEEP_SCREEN_ON = 0x00000080;
- // 讓window占滿整個屏幕,不留任何邊界
- public static final int FLAG_LAYOUT_IN_SCREEN = 0x00000100;
- // 允許窗口超出整個手機屏幕
- public static final int FLAG_LAYOUT_NO_LIMITS = 0x00000200;
- // window全名顯示
- public static final int FLAG_FULLSCREEN = 0x00000400;
- // 恢復(fù)window非全屏顯示
- public static final int FLAG_FORCE_NOT_FULLSCREEN = 0x00000800;
- // 開啟窗口抖動
- public static final int FLAG_DITHER = 0x00001000;
- // 安全內(nèi)容窗口,該窗口顯示時不允許截屏
- public static final int FLAG_SECURE = 0x00002000;
- // 一種特殊模式,在該模式下,布局參數(shù)用于在將表面合成到屏幕時執(zhí)行縮放。
- public static final int FLAG_SCALED = 0x00004000;
- public static final int FLAG_IGNORE_CHEEK_PRESSES = 0x00008000;
- public static final int FLAG_LAYOUT_INSET_DECOR = 0x00010000;
- public static final int FLAG_ALT_FOCUSABLE_IM = 0x00020000;
- // 接收單個特殊的MotionEvent,以應(yīng)對窗口外發(fā)生的觸摸。
- // 不會收到完整的向下/向上/向上手勢,而只會收到第一次向下的位置作為ACTION_OUTSIDE。
- public static final int FLAG_WATCH_OUTSIDE_TOUCH = 0x00040000;
- // 鎖屏?xí)r顯示該窗口
- public static final int FLAG_SHOW_WHEN_LOCKED = 0x00080000;
- // 系統(tǒng)的墻紙顯示在該窗口之后
- public static final int FLAG_SHOW_WALLPAPER = 0x00100000;
- // 當(dāng)window被顯示的時候,系統(tǒng)將把它當(dāng)做一個用戶活動事件,以點亮手機屏幕
- public static final int FLAG_TURN_SCREEN_ON = 0x00200000;
- // 該窗口顯示,消失鍵盤
- public static final int FLAG_DISMISS_KEYGUARD = 0x00400000;
- // 當(dāng)window在可以接受觸摸屏情況下,讓因在該window之外,而發(fā)送到后面的window的
- // 觸摸屏可以支持split touch
- public static final int FLAG_SPLIT_TOUCH = 0x00800000;
- // 對該window進行硬件加速,該flag必須在activity或者dialog的content view之前進行設(shè)置
- public static final int FLAG_HARDWARE_ACCELERATED = 0x01000000;
- // 讓該window占滿整個手機屏幕,不留任何邊界
- public static final int FLAG_LAYOUT_IN_OVERSCAN = 0x02000000;
- // 透明狀態(tài)欄
- public static final int FLAG_TRANSLUCENT_STATUS = 0x04000000;
- // 透明導(dǎo)航欄
- public static final int FLAG_TRANSLUCENT_STATUS = 0x04000000;
- public final class WindowManagerGlobal {
- public void addView(View view, ViewGroup.LayoutParams params,
- Display display, Window parentWindow) {
- //校驗參數(shù)的合法性
- ...
- //ViewRootImpl封裝了View與WindowManager的交互力促
- ViewRootImpl root;
- View panelParentView = null;
- synchronized (mLock) {
- // Start watching for system property changes.
- if (mSystemPropertyUpdater == null) {
- mSystemPropertyUpdater = new Runnable() {
- @Override public void run() {
- synchronized (mLock) {
- for (int i = mRoots.size() - 1; i >= 0; --i) {
- mRoots.get(i).loadSystemProperties();
- }
- }
- }
- };
- SystemProperties.addChangeCallback(mSystemPropertyUpdater);
- }
- int index = findViewLocked(view, false);
- if (index >= 0) {
- if (mDyingViews.contains(view)) {
- // Don't wait for MSG_DIE to make it's way through root's queue.
- mRoots.get(index).doDie();
- } else {
- throw new IllegalStateException("View " + view
- + " has already been added to the window manager.");
- }
- // The previous removeView() had not completed executing. Now it has.
- }
- // If this is a panel window, then find the window it is being
- // attached to for future reference.
- if (wparams.type >= WindowManager.LayoutParams.FIRST_SUB_WINDOW &&
- wparams.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
- final int count = mViews.size();
- for (int i = 0; i < count; i++) {
- if (mRoots.get(i).mWindow.asBinder() == wparams.token) {
- panelParentView = mViews.get(i);
- }
- }
- }
- //通過上下文構(gòu)建ViewRootImpl
- root = new ViewRootImpl(view.getContext(), display);
- view.setLayoutParams(wparams);
- //mViews存儲著所有Window對應(yīng)的View對象
- mViews.add(view);
- //mRoots存儲著所有Window對應(yīng)的ViewRootImpl對象
- mRoots.add(root);
- //mParams存儲著所有Window對應(yīng)的WindowManager.LayoutParams對象
- mParams.add(wparams);
- }
- // do this last because it fires off messages to start doing things
- try {
- //調(diào)用ViewRootImpl.setView()方法完成Window的添加并更新界面
- root.setView(view, wparams, panelParentView);
- } catch (RuntimeException e) {
- // BadTokenException or InvalidDisplayException, clean up.
- synchronized (mLock) {
- final int index = findViewLocked(view, false);
- if (index >= 0) {
- removeViewLocked(index, true);
- }
- }
- throw e;
- }
- }
- }
在這個方法里有三個重要的成員變量:
我們來看看這個方法的實現(xiàn)
- public final class ViewRootImpl implements ViewParent,
- View.AttachInfo.Callbacks, ThreadedRenderer.HardwareDrawCallbacks {
- public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
- synchronized (this) {
- if (mView == null) {
- mView = view;
- //參數(shù)校驗與預(yù)處理
- ...
- // Schedule the first layout -before- adding to the window
- // manager, to make sure we do the relayout before receiving
- // any other events from the system.
- //1. 調(diào)用requestLayout()完成界面異步繪制的請求
- requestLayout();
- if ((mWindowAttributes.inputFeatures
- & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
- mInputChannel = new InputChannel();
- }
- mForceDecorViewVisibility = (mWindowAttributes.privateFlags
- & PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY) != 0;
- try {
- mOrigWindowType = mWindowAttributes.type;
- mAttachInfo.mRecomputeGlobalAttributes = true;
- collectViewAttributes();
- //2. 創(chuàng)建WindowSession并通過WindowSession請求WindowManagerService來完成Window添加的過程
- //這是一個IPC的過程。
- res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
- getHostVisibility(), mDisplay.getDisplayId(),
- mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
- mAttachInfo.mOutsets, mInputChannel);
- } catch (RemoteException e) {
- mAdded = false;
- mView = null;
- mAttachInfo.mRootView = null;
- mInputChannel = null;
- mFallbackEventHandler.setView(null);
- unscheduleTraversals();
- setAccessibilityFocus(null, null);
- throw new RuntimeException("Adding window failed", e);
- } finally {
- if (restore) {
- attrs.restore();
- }
- }
- ...
- }
- }
- }
performTraversals()方法的實現(xiàn):
WindowManager與WindowManagerService的跨進程通信。Android的各種服務(wù)都是基于C/S結(jié)構(gòu)來設(shè)計的,系統(tǒng)層提供服務(wù),應(yīng)用層使用服務(wù)。WindowManager也是一樣,它與
WindowManagerService的通信是通過WindowSession來完成的;
首先調(diào)用ServiceManager.getService("window")獲取WindowManagerService,該方法返回的是IBinder對象,然后調(diào)用IWindowManager.Stub.asInterface()方法將WindowManagerService轉(zhuǎn)換為一個IWindowManager對象;
然后調(diào)用openSession()方法與WindowManagerService建立一個通信會話,方便后續(xù)的跨進程通信。這個通信會話就是后面我們用到的WindowSession;
基本上所有的Android系統(tǒng)服務(wù)都是基于這種方式實現(xiàn)的,它是一種基于AIDL實現(xiàn)的IPC的過程;
- public final class WindowManagerGlobal {
- public static IWindowSession getWindowSession() {
- synchronized (WindowManagerGlobal.class) {
- if (sWindowSession == null) {
- try {
- InputMethodManager imm = InputMethodManager.getInstance();
- //獲取WindowManagerService對象,并將它轉(zhuǎn)換為IWindowManager類型
- IWindowManager windowManager = getWindowManagerService();
- //調(diào)用openSession()方法與WindowManagerService建立一個通信會話,方便后續(xù)的
- //跨進程通信。
- sWindowSession = windowManager.openSession(
- new IWindowSessionCallback.Stub() {
- @Override
- public void onAnimatorScaleChanged(float scale) {
- ValueAnimator.setDurationScale(scale);
- }
- },
- imm.getClient(), imm.getInputContext());
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
- return sWindowSession;
- }
- }
- public static IWindowManager getWindowManagerService() {
- synchronized (WindowManagerGlobal.class) {
- if (sWindowManagerService == null) {
- //調(diào)用ServiceManager.getService("window")獲取WindowManagerService,該方法返回的是IBinder對象
- //,然后調(diào)用IWindowManager.Stub.asInterface()方法將WindowManagerService轉(zhuǎn)換為一個IWindowManager對象
- sWindowManagerService = IWindowManager.Stub.asInterface(
- ServiceManager.getService("window"));
- try {
- if (sWindowManagerService != null) {
- ValueAnimator.setDurationScale(sWindowManagerService.getCurrentAnimatorScale());
- }
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
- return sWindowManagerService;
- }
- }
- }
Window的刪除流程也是在WindowManagerGlobal里完成
- public final class WindowManagerGlobal {
- public void removeView(View view, boolean immediate) {
- if (view == null) {
- throw new IllegalArgumentException("view must not be null");
- }
- synchronized (mLock) {
- //1. 查找待刪除View的索引
- int index = findViewLocked(view, true);
- View curView = mRoots.get(index).getView();
- //2. 調(diào)用removeViewLocked()完成View的刪除, removeViewLocked()方法
- //繼續(xù)調(diào)用ViewRootImpl.die()方法來完成View的刪除。
- removeViewLocked(index, immediate);
- if (curView == view) {
- return;
- }
- throw new IllegalStateException("Calling with view " + view
- + " but the ViewAncestor is attached to " + curView);
- }
- }
- private void removeViewLocked(int index, boolean immediate) {
- ViewRootImpl root = mRoots.get(index);
- View view = root.getView();
- if (view != null) {
- InputMethodManager imm = InputMethodManager.getInstance();
- if (imm != null) {
- imm.windowDismissed(mViews.get(index).getWindowToken());
- }
- }
- boolean deferred = root.die(immediate);
- if (view != null) {
- view.assignParent(null);
- if (deferred) {
- mDyingViews.add(view);
- }
- }
- }
- }
我們再來看看ViewRootImpl.die()方法的實現(xiàn);
- public final class ViewRootImpl implements ViewParent,
- View.AttachInfo.Callbacks, ThreadedRenderer.HardwareDrawCallbacks {
- boolean die(boolean immediate) {
- // Make sure we do execute immediately if we are in the middle of a traversal or the damage
- // done by dispatchDetachedFromWindow will cause havoc on return.
- //根據(jù)immediate參數(shù)來判斷是執(zhí)行異步刪除還是同步刪除
- if (immediate && !mIsInTraversal) {
- doDie();
- return false;
- }
- if (!mIsDrawing) {
- destroyHardwareRenderer();
- } else {
- Log.e(mTag, "Attempting to destroy the window while drawing!\n" +
- " window=" + this + ", title=" + mWindowAttributes.getTitle());
- }
- //如果是異步刪除,則發(fā)送一個刪除View的消息MSG_DIE就會直接返回
- mHandler.sendEmptyMessage(MSG_DIE);
- return true;
- }
- void doDie() {
- checkThread();
- if (LOCAL_LOGV) Log.v(mTag, "DIE in " + this + " of " + mSurface);
- synchronized (this) {
- if (mRemoved) {
- return;
- }
- mRemoved = true;
- if (mAdded) {
- //調(diào)用dispatchDetachedFromWindow()完成View的刪除
- dispatchDetachedFromWindow();
- }
- if (mAdded && !mFirst) {
- destroyHardwareRenderer();
- if (mView != null) {
- int viewVisibility = mView.getVisibility();
- boolean viewVisibilityChanged = mViewVisibility != viewVisibility;
本文名稱:Android進階:深入理解Android窗口管理框架機制
網(wǎng)址分享:http://uogjgqi.cn/article/ccopjeg.html

我們在微信上24小時期待你的聲音
解答本文疑問/技術(shù)咨詢/運營咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流