基於Android 6.0源碼, 分析WMS的啟動過程。
一. 概述
- Surface:代表畫布
- WMS: 添加window的過程主要功能是添加Surface,管理所有的Surface布局,以及Z軸排序問題;
- SurfaceFinger: 將Surface按次序混合並顯示到物理屏幕上;
1.1 WMS全貌
- WMS繼承於
IWindowManager.Stub
, 作為Binder服務端; - WMS的成員變量mSessions保存着所有的Session對象,Session繼承於
IWindowSession.Stub
, 作為Binder服務端; - 成員變量mPolicy: 實例對象為PhoneWindowManager,用於實現各種窗口相關的策略;
- 成員變量mChoreographer: 用於控制窗口動畫,屏幕旋轉等操作;
- 成員變量mDisplayContents: 記錄一組DisplayContent對象,這個跟多屏輸出相關;
- 成員變量mTokenMap: 保存所有的WindowToken對象; 以IBinder為key,可以是IAppWindowToken或者其他Binder的Bp端;
- 另一端情況:ActivityRecord.Token extends IApplicationToken.Stub
- 成員變量mWindowMap: 保存所有的WindowState對象;以IBinder為key, 是IWindow的Bp端;
- 另一端情況: ViewRootImpl.W extends IWindow.Stub
- 一般地,每一個窗口都對應一個WindowState對象, 該對象的成員變量mClient用於跟應用端交互,成員變量mToken用於跟AMS交互.
二. 啟動過程
private void startOtherServices() { ... // [見小節2.1] WindowManagerService wm = WindowManagerService.main(context, inputManager, mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL, !mFirstBoot, mOnlyCore); wm.displayReady(); // [見小節2.5] ... wm.systemReady(); // [見小節2.6] }
2.1 WMS.main
[-> WindowManagerService.java]
public static WindowManagerService main(final Context context, final InputManagerService im, final boolean haveInputMethods, final boolean showBootMsgs, final boolean onlyCore) { final WindowManagerService[] holder = new WindowManagerService[1]; DisplayThread.getHandler().runWithScissors(new Runnable() { public void run() { //運行在"android.display"線程[見小節2.2] holder[0] = new WindowManagerService(context, im, haveInputMethods, showBootMsgs, onlyCore); } }, 0); return holder[0]; }
2.2 WindowManagerService
1 private WindowManagerService(Context context, InputManagerService inputManager, boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore) { 2 mContext = context; 3 mHaveInputMethods = haveInputMethods; 4 mAllowBootMessages = showBootMsgs; 5 mOnlyCore = onlyCore; 6 ... 7 mInputManager = inputManager; 8 mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class); 9 mDisplaySettings = new DisplaySettings(); 10 mDisplaySettings.readSettingsLocked(); 11 12 LocalServices.addService(WindowManagerPolicy.class, mPolicy); 13 mPointerEventDispatcher = new PointerEventDispatcher(mInputManager.monitorInput(TAG)); 14 15 mFxSession = new SurfaceSession(); 16 mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE); 17 mDisplays = mDisplayManager.getDisplays(); 18 19 for (Display display : mDisplays) { 20 //創建DisplayContent[見小節2.2.1] 21 createDisplayContentLocked(display); 22 } 23 24 mKeyguardDisableHandler = new KeyguardDisableHandler(mContext, mPolicy); 25 ... 26 27 mAppTransition = new AppTransition(context, mH); 28 mAppTransition.registerListenerLocked(mActivityManagerAppTransitionNotifier); 29 mActivityManager = ActivityManagerNative.getDefault(); 30 ... 31 mAnimator = new WindowAnimator(this); 32 33 34 LocalServices.addService(WindowManagerInternal.class, new LocalService()); 35 //初始化策略[見小節2.3] 36 initPolicy(); 37 38 Watchdog.getInstance().addMonitor(this); 39 40 SurfaceControl.openTransaction(); 41 try { 42 createWatermarkInTransaction(); 43 mFocusedStackFrame = new FocusedStackFrame( 44 getDefaultDisplayContentLocked().getDisplay(), mFxSession); 45 } finally { 46 SurfaceControl.closeTransaction(); 47 } 48 49 updateCircularDisplayMaskIfNeeded(); 50 showEmulatorDisplayOverlayIfNeeded(); 51 }
在“android.display”線程中執行WindowManagerService對象的初始化過程,其中final H mH = new H();
此處H繼承於Handler,無參初始化的過程,便會采用當前所在線程 的Looper。那就是說WindowManagerService.H.handleMessage()方法運行在“android.display”線程。
2.2.1 WMS.createDisplayContentLocked
public DisplayContent getDisplayContentLocked(final int displayId) { DisplayContent displayContent = mDisplayContents.get(displayId); if (displayContent == null) { final Display display = mDisplayManager.getDisplay(displayId); if (display != null) { displayContent = newDisplayContentLocked(display); } } return displayContent; }
創建DisplayContent,用於支持多屏幕的功能.比如目前除了本身真實的屏幕之外,還有Wifi display虛擬屏幕.
2.3 WMS.initPolicy
rivate void initPolicy() { //運行在"android.ui"線程 UiThread.getHandler().runWithScissors(new Runnable() { public void run() { WindowManagerPolicyThread.set(Thread.currentThread(), Looper.myLooper()); //此處mPolicy為PhoneWindowManager.[見小節2.4] mPolicy.init(mContext, WindowManagerService.this, WindowManagerService.this); } }, 0); }
2.3.1 Handler.runWithScissors
[-> Handler.java]
public final boolean runWithScissors(final Runnable r, long timeout) { //當前線程跟當前Handler都指向同一個Looper,則直接運行 if (Looper.myLooper() == mLooper) { r.run(); return true; } BlockingRunnable br = new BlockingRunnable(r); //[見小節2.3.2] return br.postAndWait(this, timeout); }
2.3.2 postAndWait
[-> Handler.java ::BlockingRunnable]
1 private static final class BlockingRunnable implements Runnable { 2 private final Runnable mTask; 3 private boolean mDone; 4 5 public BlockingRunnable(Runnable task) { 6 mTask = task; 7 } 8 9 public void run() { 10 try { 11 mTask.run(); 12 } finally { 13 synchronized (this) { 14 mDone = true; 15 notifyAll(); 16 } 17 } 18 } 19 20 public boolean postAndWait(Handler handler, long timeout) { 21 if (!handler.post(this)) { 22 return false; 23 } 24 25 synchronized (this) { 26 if (timeout > 0) { 27 final long expirationTime = SystemClock.uptimeMillis() + timeout; 28 while (!mDone) { 29 long delay = expirationTime - SystemClock.uptimeMillis(); 30 if (delay <= 0) { 31 return false; // timeout 32 } 33 try { 34 wait(delay); 35 } catch (InterruptedException ex) { 36 } 37 } 38 } else { 39 while (!mDone) { 40 try { 41 wait(); 42 } catch (InterruptedException ex) { 43 } 44 } 45 } 46 } 47 return true; 48 } 49 }
由此可見, BlockingRunnable.postAndWait()方法是阻塞操作,就是先將消息放入Handler所指向的線程, 此處是指”android.ui”線程, 由於該方法本身運行在”android.display”線程. 也就意味着”android.display”線程會進入等待狀態, 直到handler線程執行完成后再喚醒”android.display”線程. 那么PWM.init()便是運行在”android.ui”線程,屬於同步阻塞操作.
2.4 PWM.init
[-> PhoneWindowManager.java]
1 public void init(Context context, IWindowManager windowManager, WindowManagerFuncs windowManagerFuncs) { 2 mContext = context; 3 mWindowManager = windowManager; 4 mWindowManagerFuncs = windowManagerFuncs; 5 mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class); 6 mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class); 7 mDreamManagerInternal = LocalServices.getService(DreamManagerInternal.class); 8 mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class); 9 mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE); 10 ... 11 12 mHandler = new PolicyHandler(); //運行在"android.ui"線程 13 mWakeGestureListener = new MyWakeGestureListener(mContext, mHandler); 14 mOrientationListener = new MyOrientationListener(mContext, mHandler); 15 ... 16 17 mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE); 18 mBroadcastWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, 19 "PhoneWindowManager.mBroadcastWakeLock"); 20 mPowerKeyWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, 21 "PhoneWindowManager.mPowerKeyWakeLock"); 22 ... 23 24 mGlobalKeyManager = new GlobalKeyManager(mContext); 25 ... 26 27 if (!mPowerManager.isInteractive()) { 28 startedGoingToSleep(WindowManagerPolicy.OFF_BECAUSE_OF_USER); 29 finishedGoingToSleep(WindowManagerPolicy.OFF_BECAUSE_OF_USER); 30 } 31 32 mWindowManagerInternal.registerAppTransitionListener( 33 mStatusBarController.getAppTransitionListener()); 34 }
前面小節[2.1 ~ 2.4]介紹了WMS.main()方法, 接下來便是開始執行WMS.displayReady().
2.5 WMS.displayReady
1 public void displayReady() { 2 for (Display display : mDisplays) { 3 displayReady(display.getDisplayId()); 4 } 5 6 synchronized(mWindowMap) { 7 final DisplayContent displayContent = getDefaultDisplayContentLocked(); 8 readForcedDisplayPropertiesLocked(displayContent); 9 mDisplayReady = true; 10 } 11 12 mActivityManager.updateConfiguration(null); 13 14 synchronized(mWindowMap) { 15 mIsTouchDevice = mContext.getPackageManager().hasSystemFeature( 16 PackageManager.FEATURE_TOUCHSCREEN); 17 configureDisplayPolicyLocked(getDefaultDisplayContentLocked()); 18 } 19 20 mActivityManager.updateConfiguration(null); 21 }
2.6 WMS.systemReady
public void systemReady() { mPolicy.systemReady(); }
2.6.1 PWM.systemReady
[-> PhoneWindowManager.java]
1 public void systemReady() { 2 mKeyguardDelegate = new KeyguardServiceDelegate(mContext); 3 mKeyguardDelegate.onSystemReady(); 4 5 readCameraLensCoverState(); 6 updateUiMode(); 7 boolean bindKeyguardNow; 8 synchronized (mLock) { 9 updateOrientationListenerLp(); 10 mSystemReady = true; 11 12 mHandler.post(new Runnable() { 13 public void run() { 14 updateSettings(); 15 } 16 }); 17 18 bindKeyguardNow = mDeferBindKeyguard; 19 if (bindKeyguardNow) { 20 mDeferBindKeyguard = false; 21 } 22 } 23 24 if (bindKeyguardNow) { 25 mKeyguardDelegate.bindService(mContext); 26 mKeyguardDelegate.onBootCompleted(); 27 } 28 mSystemGestures.systemReady(); 29 }
三. 總結
整個啟動過程涉及3個線程: system_server主線程, “android.display”, “android.ui”, 整個過程是采用阻塞方式(利用Handler.runWithScissors)執行的. 其中WindowManagerService.mH的Looper運行在 “android.display”進程,也就意味着WMS.H.handleMessage()在該線程執行。 流程如下: