基于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()在该线程执行。 流程如下: