Wms 啟動流程分析和介紹
前言
客戶端開發(fā)中并不是直接和 WindowManagerService 交互,而是直接和本地對象 WindowManager 交互,然后由 WindowManager 完成和 WindowManagerService 的交互;
對于 Android 應(yīng)用來說這個交互是透明的,應(yīng)用感覺不到 WindowManagerService 的存在;
我們來介紹分析下窗口管理服務(wù) WindowManagerService 的啟動過程;
一、WindowManagerService的相關(guān)類
1、WindowManagerService概念
Framework層的窗口管理服務(wù),職責(zé)是管理Android系統(tǒng)中所有window;窗口管理服務(wù),繼承IWindowManager.Stub,Binder服務(wù)端,因此WM與WMS的交互也是一個IPC過程。WMS主要做的事情如下:
- Z-ordered的維護函數(shù)
- 輸入法管理
- AddWindow/RemoveWindow
- Layerout
- Token管理,AppToken
- 活動窗口管理(FocusWindow)
- 活動應(yīng)用管理(FocusApp)
- 轉(zhuǎn)場動畫
- 系統(tǒng)消息收集線程
- 系統(tǒng)消息分發(fā)線程
2、WindowManager
應(yīng)用與窗口管理服務(wù)WindowManagerService交互的接口
3、PhoneWindowManager
實現(xiàn)了窗口的各種策略,定義了窗口相關(guān)策略;
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
- 窗口Token,用來做Binder通信;同時也是一種標(biāo)識;
- 在進行窗口Zorder排序時,屬于同一個WindowToken的窗口會被安排在一起,而且在其中定義的一些屬性將會影響所有屬于此WindowToken的窗口,這些都表明了屬于同一個WindowToken的窗口之間的緊密聯(lián)系;
- 應(yīng)用組件在需要新的窗口時,必須提供WindowToken以表明自己的身份,并且窗口的類型必須與所持有的WindowToken的類型一致;
- 在創(chuàng)建系統(tǒng)類型的窗口時不需要提供一個有效的Token,WMS會隱式地為其聲明一個WindowToken,看起來誰都可以添加個系統(tǒng)級的窗口。難道Android為了內(nèi)部使用方便而置安全于不顧嗎?非也,addWindow()函數(shù)一開始的mPolicy.checkAddPermission()的目的就是如此。它要求客戶端必須擁有SYSTEM_ALERT_WINDOW或INTERNAL_SYSTEM_WINDOW權(quán)限才能創(chuàng)建系;
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
IMS實例。管理每個窗口的輸入事件通道(InputChannel)以及向通道上派發(fā)事件
11、Animator
所有窗口動畫的總管(WindowStateAnimator對象)。在Choreographer的驅(qū)動下,逐個渲染所有的動畫
二、WMS啟動流程
WMS的啟動,依然是由SystemServer進行啟動,在SystemServer的main函數(shù)中調(diào)用startOtherServices方法創(chuàng)建WMS;
1、SystemServer#startOtherServices
- private void startOtherServices() {
- ...
- try {
- ...
- // 創(chuàng)建WMS對象
- // 創(chuàng)建WMS對象需要依賴于InputManager、PhoneWindowManager、和AMS
- // IMS是用來管理每個窗口的輸入事件通道以及向通道上派發(fā)事件
- // PhoneWindowManager是實現(xiàn)了窗口的各種策略,定義了窗口相關(guān)策略
- // 比如:告訴WMS某一個類型Window的Z-Order的值是多少,幫助WMS矯正不合理的窗口屬性,
- // 為WMS監(jiān)聽屏幕旋轉(zhuǎn)的狀態(tài),預(yù)處理一些系統(tǒng)按鍵事件(例如HOME、BACK鍵等的默認(rèn)行為就是在這里實現(xiàn)的)等
- wm = WindowManagerService.main(context, inputManager, !mFirstBoot, mOnlyCore,
- new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager);
- 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);
- traceEnd();
- traceBeginAndSlog("SetWindowManagerService");
- // 將AMS與WMS做綁定
- mActivityManagerService.setWindowManager(wm);
- traceEnd();
- traceBeginAndSlog("WindowManagerServiceOnInitReady");
- // 這里主要是調(diào)用initPolicy用來初始化PhoneWindowManager
- wm.onInitReady();
- traceEnd();
- ...
- }
- ...
- traceBeginAndSlog("MakeDisplayReady");
- try {
- // 主要是初始化UI尺寸
- wm.displayReady();
- } catch (Throwable e) {
- reportWtf("making display ready", e);
- }
- traceEnd();
- ...
- traceBeginAndSlog("MakeWindowManagerServiceReady");
- try {
- // 準(zhǔn)備工作已經(jīng)完成
- wm.systemReady();
- } catch (Throwable e) {
- reportWtf("making Window Manager Service ready", e);
- }
- traceEnd();
- ...
- }
2、WindowManagerService#main
- WMS的main方法:是運行在SystemServer進程的主線程,但是WMS的初始化是在DisplayThread線程構(gòu)建的;
- DisplayThread其實就是一個HandlerThread;
- Handler中有一個runWithScissors方法:這個方法其實就是Handler.post消息執(zhí)行之后能夠再繼續(xù)往下執(zhí)行;
- 即runWithScissors后面的內(nèi)容,需要等待消息的處理完成之后才會繼續(xù)執(zhí)行。其實就是實現(xiàn)一個同步執(zhí)行的過程;
- DisplayThread其實是android.display線程,這是系統(tǒng)共享的單例前臺線程,在該線程內(nèi)部創(chuàng)建了WMS;
- 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);
- }
- WMS的main方法是在SystemServer進程的主線程調(diào)用的,然后在調(diào)用WMS的main方法的時候,通過DisplayThread這個HandlerThread,實現(xiàn)異步處理;
- 這里的異步處理,其實是通過跨線程的一個同步,即通過DisplayThread中的Handler對象,調(diào)用runWithScissors方法;
- 該方法其實是可以實現(xiàn)發(fā)送消息等待消息處理完成以后再繼續(xù)執(zhí)行runWithScissors方法調(diào)用位置之后的代碼,即等待消息處理完之后再進行return WMS對象的返回操作;
- @VisibleForTesting
- public static WindowManagerService main(final Context context, final InputManagerService im,
- final boolean showBootMsgs, final boolean onlyCore, WindowManagerPolicy policy,
- ActivityTaskManagerService atm, TransactionFactory transactionFactory) {
- // wms是運行在android.display線程
- DisplayThread.getHandler().runWithScissors(() ->
- sInstance = new WindowManagerService(context, im, showBootMsgs, onlyCore, policy,
- atm, transactionFactory), 0);
- return sInstance;
- }
3、Handler#runWithScissors
上面的runWithScissors傳入的就是一個Runnable實例,只不過是采用了lambda表達(dá)式的做法,所以Runnable的run()方法的方法體是就是:
- sInstance = new WindowManagerService(context, im, showBootMsgs, onlyCore, policy,
- atm, transactionFactory), 0);
- public final boolean runWithScissors(@NonNull Runnable r, long timeout) {
- if (r == null) {
- throw new IllegalArgumentException("runnable must not be null");
- }
- if (timeout < 0) {
- throw new IllegalArgumentException("timeout must be non-negative");
- }
- // 如果調(diào)用runWithScissors方法的線程是與消息處理線程在同一個線程
- // 則直接執(zhí)行Runnable的run方法。
- if (Looper.myLooper() == mLooper) {
- r.run();
- return true;
- }
- // 如果調(diào)用runWithScissors方法的線程與消息處理線程不是同一個,則創(chuàng)建一個BlockingRunnable
- BlockingRunnable br = new BlockingRunnable(r);
- return br.postAndWait(this, timeout);
- }
- 則創(chuàng)建一個BlockingRunnable;
- 調(diào)用BlockingRunnable.postAndWait方法;
- 這里的返回值會先等待,等待DisplayThread線程中的Handler處理完;
- 消息之后,然后喚醒BlockingRunnable;
- 該Handler處理消息是在DisplayThread線程,而BlockingRunnable;
- 而BlockingRunnable調(diào)用wait并不會讓DisplayThread線程中的;
- Handler等待,Handler依然會處理消息,處理消息其實就是調(diào)用了;
- BlockingRunnable.run()方法,當(dāng)BlockingRunnable.run()執(zhí)行完成;
- 就會調(diào)用notifyAll喚醒BlockingRunnable,執(zhí)行postAndWait的return;
4、BlockingRunnable方法介紹
- private static final class BlockingRunnable implements Runnable {
- private final Runnable mTask;
- private boolean mDone;
- public BlockingRunnable(Runnable task) {
- mTask = task;
- }
- @Override
- public void run() {
- try {
- mTask.run();
- } finally {
- synchronized (this) {
- mDone = true;
- notifyAll();
- }
- }
- }
- public boolean postAndWait(Handler handler, long timeout) {
- // 調(diào)用postAndWait的時候,先調(diào)用handler對象的post將消息發(fā)送出
- // 如果入隊成功,則為true,則開始阻塞
- if (!handler.post(this)) {
- return false;
- }
- // 在上面的方法調(diào)用中,timeout=0,則阻塞。
- synchronized (this) {
- if (timeout > 0) {
- final long expirationTime = SystemClock.uptimeMillis() + timeout;
- // 如果mDone為false的時候,則會等待,只有為true的時候,會執(zhí)行
- while (!mDone) {
- long delay = expirationTime - SystemClock.uptimeMillis();
- if (delay <= 0) {
- return false; // timeout
- }
- try {
- wait(delay);
- } catch (InterruptedException ex) {
- }
- }
- } else {
- while (!mDone) {
- try {
- wait();
- } catch (InterruptedException ex) {
- }
- }
- }
- }
- return true;
- }
- }
- mTask其實就是runWithScissors中傳入的Runnable對象;
- BlockingRunnable的run方法的執(zhí)行,其實就是需要Handler遍歷到消息處理的時候;
- 然后處理這個BlockingRunnable消息,在處理BlockingRunnable消息的時候;
- 就會處理runWithScissors的參數(shù)中的Runnable這個mTask;
- 處理完成之后,就會調(diào)用notifyAll喚醒等待線程,然后執(zhí)行postAndWait的return;
- 因為BlockingRunnable的run方法是由Handler處理消息;
- 這個消息的處理與BlockingRunnable是在不同的線程;
- 所以BlockingRunnable等待的時候,其run方法是可以由handler消息處理;
5、WindowManagerService構(gòu)造器
- private WindowManagerService(Context context, InputManagerService inputManager,
- boolean showBootMsgs, boolean onlyCore, WindowManagerPolicy policy,
- ActivityTaskManagerService atm, TransactionFactory transactionFactory) {
- installLock(this, INDEX_WINDOW);
- mGlobalLock = atm.getGlobalLock();
- mAtmService = atm;
- mContext = context;
- mAllowBootMessages = showBootMsgs;
- mOnlyCore = onlyCore;
- // 各種變量讀取
- mLimitedAlphaCompositing = context.getResources().getBoolean(
- com.android.internal.R.bool.config_sf_limitedAlpha);
- mHasPermanentDpad = context.getResources().getBoolean(
- com.android.internal.R.bool.config_hasPermanentDpad);
- mInTouchMode = context.getResources().getBoolean(
- com.android.internal.R.bool.config_defaultInTouchMode);
- ......
- mInputManager = inputManager;
- mDisplayManagerInternal =
- LocalServices.getService(DisplayManagerInternal.class);
- // Display設(shè)置
- mDisplayWindowSettings = new DisplayWindowSettings(this);
- mTransactionFactory = transactionFactory;
- mTransaction = mTransactionFactory.make();
- //PhoneWindowManager(繼承于WindowManagerPolicy, 用來提供UI相關(guān)的一些行為)
- mPolicy = policy;
- // 在一個單獨的task中執(zhí)行動畫和Surface操作的類
- mAnimator = new WindowAnimator(this);
- // 根Window容器
- mRoot = new RootWindowContainer(this);
- // 用來確定Window和Surface的位置
- mWindowPlacerLocked = new WindowSurfacePlacer(this);
- // 任務(wù)快照管理器(當(dāng)App不可見時, 會將Task的快照以Bitmap形式存在緩存中)
- mTaskSnapshotController = new TaskSnapshotController(this);
- LocalServices.addService(WindowManagerPolicy.class, mPolicy);
- mDisplayManager =
- (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
- // Keyguard處理器
- mKeyguardDisableHandler =
- KeyguardDisableHandler.create(mContext, mPolicy, mH);
- // PowerManager是控制設(shè)備電池狀態(tài)的管理器
- mPowerManager =
- (PowerManager)context.getSystemService(Context.POWER_SERVICE);
- // PowerManagerInternal是PowerMananger的本地服務(wù)
- mPowerManagerInternal =
- LocalServices.getService(PowerManagerInternal.class);
- if (mPowerManagerInternal != null) {
- mPowerManagerInternal.registerLowPowerModeObserver(
- new PowerManagerInternal.LowPowerModeListener() {
- @Override
- public int getServiceType() {
- return ServiceType.ANIMATION;
- }
- @Override
- public void onLowPowerModeChanged(PowerSaveState result) {
- synchronized (mGlobalLock) {
- // 低電量模式發(fā)生變化時, 需要調(diào)整對應(yīng)的動畫
- final boolean enabled = result.batterySaverEnabled;
- if (mAnimationsDisabled != enabled && !mAllowAnimationsInLowPowerMode) {
- mAnimationsDisabled = enabled;
- dispatchNewAnimatorScaleLocked(null);
- }
- }
- }
- });
- // 獲取是否允許動畫
- mAnimationsDisabled =
- mPowerManagerInternal.getLowPowerState(
- ServiceType.ANIMATION).batterySaverEnabled;
- }
- mScreenFrozenLock =
- mPowerManager.newWakeLock(
- PowerManager.PARTIAL_WAKE_LOCK, "SCREEN_FROZEN");
- mScreenFrozenLock.setReferenceCounted(false);
- // 獲取IActivity.Stub.Proxy(new BinderProxy())
- mActivityManager = ActivityManager.getService();
- // 獲取IActivityTaskManager.Stub.Proxy
- mActivityTaskManager = ActivityTaskManager.getService();
- // ActivityManagerInternal是ActivityManager的本地服務(wù)
- mAmInternal =
- LocalServices.getService(ActivityManagerInternal.class);
- // ActivityTaskManagerInternal是ActivityTaskManager的本地服務(wù)
- mAtmInternal =
- LocalServices.getService(ActivityTaskManagerInternal.class);
- mAppOps =
- (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
- AppOpsManager.OnOpChangedInternalListener opListener =
- new AppOpsManager.OnOpChangedInternalListener() {
- @Override
- public void onOpChanged(int op, String packageName) {
- updateAppOpsState();
- }
- };
- mAppOps.startWatchingMode(OP_SYSTEM_ALERT_WINDOW, null, opListener);
- mAppOps.startWatchingMode(AppOpsManager.OP_TOAST_WINDOW,
- null, opListener);
- // PackageManagerInternal是PackageManager的本地服務(wù)
- mPmInternal = LocalServices.getService(PackageManagerInternal.class);
- // 注冊Package suspend/unsuspend廣播
- final IntentFilter suspendPackagesFilter = new IntentFilter();
- suspendPackagesFilter.addAction(Intent.ACTION_PACKAGES_SUSPENDED);
- suspendPackagesFilter.addAction(Intent.ACTION_PACKAGES_UNSUSPENDED);
- context.registerReceiverAsUser(new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- final String[] affectedPackages =
- intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
- final boolean suspended =
- Intent.ACTION_PACKAGES_SUSPENDED.equals(intent.getAction());
- updateHiddenWhileSuspendedState(
- new ArraySet<>(Arrays.asList(affectedPackages)), suspended);
- }
- }, UserHandle.ALL, suspendPackagesFilter, null, null);
- // 獲取并設(shè)置window scale設(shè)置
- final ContentResolver resolver = context.getContentResolver();
- mWindowAnimationScaleSetting = Settings.Global.getFloat(resolver,
- Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScaleSetting);
- ......
- // 注冊廣播, 當(dāng)DevicePolicyManager狀態(tài)發(fā)生變化時設(shè)置keyguard屬性是否可用
- IntentFilter filter = new IntentFilter();
- filter.addAction(ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
- mContext.registerReceiverAsUser(mBroadcastReceiver,
- UserHandle.ALL, filter, null, null);
- mLatencyTracker = LatencyTracker.getInstance(context);
- mSettingsObserver = new SettingsObserver();
- ......
- mSurfaceAnimationRunner = new SurfaceAnimationRunner(mPowerManagerInternal);
- mAllowTheaterModeWakeFromLayout = context.getResources().getBoolean(
- com.android.internal.R.bool.config_allowTheaterModeWakeFromWindowLayout);
- // Task定位控制器
- mTaskPositioningController = new TaskPositioningController(this,
- mInputManager, mActivityTaskManager, mH.getLooper());
- // View的拖/拉操作控制器
- mDragDropController = new DragDropController(this, mH.getLooper());
- ......
- // 注冊WindowManager的本地服務(wù)WindowManagerInternal
- LocalServices.addService(WindowManagerInternal.class, new LocalService());
- }
LocalServices與ServiceManager類似,但是LocalServices只能是在同一個進程中使用;
并且LocalServices中注冊的并不是一個Binder對象,注冊進的都是對應(yīng)的Service的靜態(tài)內(nèi)部類;
也就是LocalService,比如WMS有一個WindowManagerInternal,LocalService就是其子類實現(xiàn);
6、onInitReady
- public void onInitReady() {
- // 初始化PhoneWindowManager
- initPolicy();
- // 添加Watchdog monitor
- Watchdog.getInstance().addMonitor(this);
- // 調(diào)用SurfaceControl.openTransaction(), 啟動一個事務(wù)
- openSurfaceTransaction();
- // 創(chuàng)建水印
- createWatermarkInTransaction();
- // 結(jié)束事務(wù)
- closeSurfaceTransaction("createWatermarkInTransaction");
- // 顯示模擬器顯示層
- showEmulatorDisplayOverlayIfNeeded();
- }
7、 initPolicy
- private void initPolicy() {
- UiThread.getHandler().runWithScissors(new Runnable() {
- @Override
- public void run() {
- WindowManagerPolicyThread.set(Thread.currentThread(),
- Looper.myLooper());
- mPolicy.init(mContext, WindowManagerService.this,
- WindowManagerService.this);
- }
- }, 0);
- }
PhoneWindowManager 的初始化運行在 “android.ui” 線程;
8、 displayReady
- public void displayReady() {
- synchronized (mGlobalLock) {
- // 設(shè)置RootWindowContainer的Window列表的最大寬度
- if (mMaxUiWidth > 0) {
- mRoot.forAllDisplays(
- displayContent -> displayContent.setMaxUiWidth(mMaxUiWidth));
- }
- final boolean changed = applyForcedPropertiesForDefaultDisplay();
- mAnimator.ready();
- mDisplayReady = true;
- if (changed) {
- // 重新配置DiaplayContent屬性
- reconfigureDisplayLocked(getDefaultDisplayContentLocked());
- }
- mIsTouchDevice = mContext.getPackageManager().hasSystemFeature(
- PackageManager.FEATURE_TOUCHSCREEN);
- }
- // 1.修改當(dāng)前configuration 2.確保當(dāng)前Activity正在運行當(dāng)前configuration
- mActivityTaskManager.updateConfiguration(null);
- // 更新CircularDisplayMask
- updateCircularDisplayMaskIfNeeded();
- }
9、systemReady
- public void systemReady() {
- mSystemReady = true;
- mPolicy.systemReady();
- mRoot.forAllDisplayPolicies(DisplayPolicy::systemReady);
- mTaskSnapshotController.systemReady();
- // 是否支持色域
- mHasWideColorGamutSupport = queryWideColorGamutSupport();
- // 是否支持HDR渲染
- mHasHdrSupport = queryHdrSupport();
- UiThread.getHandler().post(mSettingsObserver::updateSystemUiSettings);
- UiThread.getHandler().post(mSettingsObserver::updatePointerLocation);
- // 獲取IVrManager.Stub.Proxy, 并注冊狀態(tài)變化listener
- IVrManager vrManager = IVrManager.Stub.asInterface(
- ServiceManager.getService(Context.VR_SERVICE));
- if (vrManager != null) {
- final boolean vrModeEnabled = vrManager.getVrModeState();
- synchronized (mGlobalLock) {
- vrManager.registerListener(mVrStateCallbacks);
- if (vrModeEnabled) {
- mVrModeEnabled = vrModeEnabled;
- mVrStateCallbacks.onVrStateChanged(vrModeEnabled);
- }
- }
- }
- }
整個啟動過程涉及3個線程: system_server主線程, “android.display”, “android.ui”;
整個過程是采用阻塞方式(利用Handler.runWithScissors)執(zhí)行的;
其中WindowManagerService.mH的Looper運行在 “android.display”進程,也就意味著WMS.H.handleMessage()在該線程執(zhí)行;
WMS 主要用于窗口的添加和移除操作,其對應(yīng)的方法是 addWindow 和 removeWindow,關(guān)于窗口的添加和刪除過程
總結(jié)
快年底了,一起加油努力