Android中,Window是一個重要部分,用戶看到的界面、觸摸顯示界面進行一系列操做都涉及到Window。但實際上,Window自己並不具有繪製功能。
該篇簡單介紹下Window的一點內容,同時總結下WMS的啓動過程。在下篇會逐步介紹一個Activity是如何建立出窗口 並 添加到WMS中的。
該篇基於Andorid10的代碼。html
窗口涉及到一下幾個功能:java
窗口管理-WMS
WMS管理窗口的建立、添加、刪除、大小、層級等等。android
輸入中轉-IMS(InputManagerService)
觸摸窗口產生觸摸事件,IMS對觸摸事件進行處理,最後尋找一個最合適窗口進行反饋處理。app
窗口動畫 ---WindowAnimator
窗口間進行切換時,使用窗口動畫能夠實現更好的效果,窗口動畫主要由WindowAnimator管理。能夠在開發者模式菜單找到相應設置。ide
Surface管理 ---SurfaceFlinger
窗口不具有有繪製的功能,所以每一個窗口都須要有一塊Surface來供本身繪製。爲每一個窗口分配Surface是由WMS來完成的。
Surface就像畫布,而後經過Canvas或OpenGL繪製。
SurfaceFlinger的做用主要是merge Surface,它接受多個來源的Surface圖形顯示數據(全部Surface:全部Window的Surface,特殊狀況 有些Surface跟Window無關,如StrictMode),而後將他們合併(根據特定順序Z-order),而後發送到顯示設備。如最多見的界面是3層,頂部的statusbar,底部的導航欄,應用界面。
oop
WMS同以前總結過的AMS、PMS同樣(連接:AMS的啓動 、AMS之應用的第一次啓動過程、PMS的啓動及應用的安裝過程),是系統服務,做爲Binder的服務端。 下表簡單對比列出下:字體
系統服務 | binder服務端 | binder客戶端 | 服務名 |
---|---|---|---|
AMS | ActivityManagerService(extends IActivityManager.Stub) | ActivityManager | activity(Context.ACTIVITY_SERVICE) |
PMS | PackageManagerService(extends IPackageManager.Stub) | PackageManager | package |
WMS | WindowManagerService(extends IWindowManager.Stub) | WindowManager | window(Context.WINDOW_SERVICE) |
通常獲取方法:
獲取binder客戶端,與服務通訊,相似:
ActivityManager am = (ActivityManager) context.getSystemService("activity");
ActivityManager am = context.getSystemService(ActivityManager.class);
從ServiceManager獲取服務的Binder,相似:
IBinder binder = ServiceManager.getService(Context.ACTIVITY_SERVICE);
下面兩個也是用的ServiceManager.getService():
IActivityManager mgr = ActivityManager.getService();
PackageManagerService pm = (PackageManagerService) ServiceManager.getService("package");
動畫
以前總結了 AMS的啓動 、AMS之應用的第一次啓動過程、PMS的啓動及應用的安裝過程。 這裏WMS的啓動相似,下面會簡單介紹下。ui
WMS是在system server啓動後的startOtherServices()中啓動。下面截取了其中關於WMS相關的代碼。this
//SystemServer.java private void startOtherServices() { final Context context = mSystemContext; WindowManagerService wm = null; try { // WMS 依賴 sensor service ConcurrentUtils.waitForFutureNoInterrupt(mSensorServiceStart, START_SENSOR_SERVICE); //標記1:StartWindowManagerService //建立WMS實例 wm = WindowManagerService.main(context, inputManager, !mFirstBoot, mOnlyCore, new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager); //註冊WINDOW_SERVICE 服務到 ServiceManager。 ServiceManager.addService(Context.WINDOW_SERVICE, wm, /* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PROTO); ServiceManager.addService(Context.INPUT_SERVICE, inputManager, /* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL); //標記2:SetWindowManagerService //WMS設置到AMS/ATMS中。 mActivityManagerService.setWindowManager(wm); //標記3:WindowManagerServiceOnInitReady //WMS初始化完成。 wm.onInitReady(); inputManager.setWindowManagerCallbacks(wm.getInputManagerCallback()); inputManager.start(); mDisplayManagerService.windowManagerAndInputReady(); } // Before things start rolling, be sure we have decided whether // we are in safe mode. final boolean safeMode = wm.detectSafeMode(); try { //標記4:MakeDisplayReady //初始化顯示信息 wm.displayReady(); } if (mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL) { if (!isWatch) { try { statusBar = new StatusBarManagerService(context, wm); ServiceManager.addService(Context.STATUS_BAR_SERVICE, statusBar); } } } try { //標記5:MakeWindowManagerServiceReady //通知WMS系統準備好了,初始化完成了。 wm.systemReady(); } final Configuration config = wm.computeNewConfiguration(DEFAULT_DISPLAY); DisplayMetrics metrics = new DisplayMetrics(); WindowManager w = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); w.getDefaultDisplay().getMetrics(metrics); context.getResources().updateConfiguration(config, metrics); final WindowManagerService windowManagerF = wm; mActivityManagerService.systemReady(() -> { try { startSystemUi(context, windowManagerF); } }, BOOT_TIMINGS_TRACE_LOG); }
startOtherServices()中,建立了WindowManagerService對象 並 註冊了服務Context.WINDOW_SERVICE。而後進行了各類初始化等操做。
注意上面的註釋,下面主要看下其中的5行代碼(標記1-標記5)。
//public class WindowManagerService extends IWindowManager.Stub implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs { //WindowManagerService.java private static WindowManagerService sInstance; static WindowManagerService getInstance() { return sInstance; } public static WindowManagerService main(final Context context, final InputManagerService im, final boolean showBootMsgs, final boolean onlyCore, WindowManagerPolicy policy, ActivityTaskManagerService atm) { return main(context, im, showBootMsgs, onlyCore, policy, atm, SurfaceControl.Transaction::new); } @VisibleForTesting public static WindowManagerService main(final Context context, final InputManagerService im, final boolean showBootMsgs, final boolean onlyCore, WindowManagerPolicy policy, ActivityTaskManagerService atm, TransactionFactory transactionFactory) { //android.display線程中執行 DisplayThread.getHandler().runWithScissors(() -> sInstance = new WindowManagerService(context, im, showBootMsgs, onlyCore, policy, atm, transactionFactory), 0); return sInstance; } private WindowManagerService(Context context, InputManagerService inputManager, boolean showBootMsgs, boolean onlyCore, WindowManagerPolicy policy, ActivityTaskManagerService atm, TransactionFactory transactionFactory) { ...... //ActivityTaskManagerService mAtmService = atm; //context是mSystemContext system server進程上下文 mContext = context; mOnlyCore = onlyCore; mInTouchMode = context.getResources().getBoolean( com.android.internal.R.bool.config_defaultInTouchMode); mMaxUiWidth = context.getResources().getInteger( com.android.internal.R.integer.config_maxUiWidth); mLowRamTaskSnapshotsAndRecents = context.getResources().getBoolean( com.android.internal.R.bool.config_lowRamTaskSnapshotsAndRecents); //輸入法管理 mInputManager = inputManager; // Must be before createDisplayContentLocked. mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class); mDisplayWindowSettings = new DisplayWindowSettings(this); mPolicy = policy; //管理窗口動畫 mAnimator = new WindowAnimator(this); mRoot = new RootWindowContainer(this); mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE); mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE); mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class); mActivityManager = ActivityManager.getService(); mActivityTaskManager = ActivityTaskManager.getService(); mAmInternal = LocalServices.getService(ActivityManagerInternal.class); mAtmInternal = LocalServices.getService(ActivityTaskManagerInternal.class); mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE); ...... }
WindowManagerService.main()主要就是建立了WindowManagerService對象。
WindowManagerService的構造方法沒有完整附上了,沒什麼特別的,基本是初始化並保存 WMS中須要用到的各類對象等數據。上面列出了幾個常見的。
DisplayThread.getHandler().runWithScissors()
,注意這裏是DisplayThread(繼承ServiceThread),是在android.display線程上執行。
題外話 :DisplayThread.getHandler().runWithScissors(() -> sInstance = new WindowManagerService(...),0);
是 lambda表達式 ,這裏至關於:
DisplayThread.getHandler().runWithScissors( new Runnable() { @Override public void run() { sInstance = new WindowManagerService(context, im, showBootMsgs, onlyCore, policy, atm, transactionFactory) } }, 0);
這個很簡單,wm被設置的到AMS和ATMS中。
//ActivityManagerService.java public void setWindowManager(WindowManagerService wm) { synchronized (this) { mWindowManager = wm; mActivityTaskManager.setWindowManager(wm); } }
//WindowManagerService.java public void onInitReady() { //初始化PhoneWindowManager (PhoneWindowManager implements WindowManagerPolicy) initPolicy(); // Add ourself to the Watchdog monitors. Watchdog.getInstance().addMonitor(this); //SurfaceControl.openTransaction(); openSurfaceTransaction(); try { //水印,這裏瞭解了下 createWatermarkInTransaction(); } finally { closeSurfaceTransaction("createWatermarkInTransaction"); } showEmulatorDisplayOverlayIfNeeded(); } private void initPolicy() { //android.ui線程上執行 UiThread.getHandler().runWithScissors(new Runnable() { @Override public void run() { WindowManagerPolicyThread.set(Thread.currentThread(), Looper.myLooper()); mPolicy.init(mContext, WindowManagerService.this, WindowManagerService.this); } }, 0); } void createWatermarkInTransaction() { ... File file = new File("/system/etc/setup.conf"); ... try { ... if (line != null) { String[] toks = line.split("%"); if (toks != null && toks.length > 0) { // TODO(multi-display): Show watermarks on secondary displays. final DisplayContent displayContent = getDefaultDisplayContentLocked(); mWatermark = new Watermark(displayContent, displayContent.mRealDisplayMetrics, toks); } } } ... }
onInitReady()這裏幾個地方記錄下,我的以爲比較值得注意的:
initPolicy()中,mPolicy即PhoneWindowManager對象,從開始處startOtherServices()中能夠看到。startOtherServices()建立了PhoneWindowManager,這裏完成了PhoneWindowManager的init()操做。
initPolicy()中,是運行在UiThread,也是繼承的ServiceThread。執行mPolicy.init()。
createWatermarkInTransaction():這個能夠看一下。這是在window manager的窗口上添加水印。這個功能幾乎沒有用過,嘗試了下,效果以下圖。
日後跟蹤,能夠看到:顯示的字符配置到/system/etc/setup.conf裏的,Watermark有個解析過程(相似解密),詳細的能夠本身看下Watermark的構造方法。以下圖中顯示的字符串「WMS」,我在setup.conf配置的是「A8B2A<%30」,%後面是字體大小。「A8B2A<」即「WMS」。
//WindowManagerService.java public void displayReady() { synchronized (mGlobalLock) { if (mMaxUiWidth > 0) { mRoot.forAllDisplays(displayContent -> displayContent.setMaxUiWidth(mMaxUiWidth)); } //全局設置僅適用於默認顯示。設置Display size、Display density、Display scaling mode。 //getDefaultDisplayContentLocked()。 final boolean changed = applyForcedPropertiesForDefaultDisplay(); mAnimator.ready(); mDisplayReady = true; if (changed) { reconfigureDisplayLocked(getDefaultDisplayContentLocked()); } mIsTouchDevice = mContext.getPackageManager().hasSystemFeature( PackageManager.FEATURE_TOUCHSCREEN); } try { //初始化配置完成,ATMS完成第一次Configuration更新 mActivityTaskManager.updateConfiguration(null); } catch (RemoteException e) { } updateCircularDisplayMaskIfNeeded(); }
看下注釋。這裏主要是初始化顯示信息。初始化配置完成,ATMS完成第一次Configuration更新。
//WindowManagerService.java public void systemReady() { mSystemReady = true; mPolicy.systemReady(); ... }
系統初始化完成,通知WMS系統準備好了。這裏主要完成:mPolicy.systemReady()
。
在標記3 時,有在android.ui線程執行的mPolicy.init()
,這裏有mPolicy.systemReady()
。 mPolicy是PhoneWindowManager,關於這兩個方法這裏不關注,在後續相似事件傳遞時應該會再觸及。