Android10 WMS启动过程分析

WindowManagerService作为Android系统中重要的服务,管理所有的窗口和输入事件的中转站

发布日期 2020-12-08

一、概述

WindowManagerService作为Android系统中重要的服务,管理所有的窗口和输入事件的中转站,其相关类如下。

1.1 WMS类族

WMS

WMS继承于IWindowManager.Stub,作为Binder服务端

成员变量mSessions保存所有的Session对象,Session继承于IWindowSession.Stub,作为Binder服务端

成员变量mPolicy,实例是PhoneWindowManager,用于实现各种窗口相关的策略

成员变量mWindowMap,保存所有的WindowState对象;以IBinder为key, 是IWindow的Bp端;

每个窗口都对应一个WindowState对象, 该对象的成员变量mClient用于跟应用端交互,成员变量mToken用于跟AMS交互,WindowState的attach方法与SurfaceFlinger通信。

WindowManager与WindowManagerService通过Session进行通信,具体的实现由WMS处理。

WindowManager实现类是WindowManagerImpl ;

WindowManagerImpl 中成员变量 mParentWindow (Window),mGlobal (WindowManagerGlobal)

1.2 图形框架

Android系统图形系统复杂,包括WindowManager,SurfaceFlinger,Open GL,GPU等模块,其中SurfaceFlinger作为绘制应用UI的核心。Surface代表BufferQueue的生产者端,并由SurfaceFlinger消费。

Image Stream Producter(生产者):可产生graphic buffers的生产者,例如:OpenGL ES,Canvas 2D,mediaserver的视频编码器

Image Stream Consumers(消费者):使用Open GL和Hardware Composer来组合一组surfaces

Window Manager:用于管理window,这是一组view容器,WM将window元数据信息发送给SurfaceFlinger,因此SurfaceFlinger能将这些信息来合成surfaces,并输出到显示设备。

Hardware Composer(硬件合成器):显示子系统的硬件抽象层,SurfaceFlinger能将一些合成工作给Hardware Composer,从而降低OpenGL和GPU的负载。

Gralloc:全程graphics memory allocator,图像内存分配器,用于图形生产请求分配内存。

二、启动过程

WMS在SystemServer中的startOtherServices方法启动,和其启动相关的主要操作如下:

[->SystemServer.java]

private void startOtherServices() {
      wm = WindowManagerService.main(context, inputManager,
                   mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
                   !mFirstBoot, mOnlyCore, new PhoneWindowManager());
      ...
      //见2.1节
      mActivityManagerService.setWindowManager(wm);
      ...   
      wm.onInitReady();
      ...   
      wm.displayReady();
      ...     
      wm.systemReady();

}

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,
           WindowManagerPolicy policy) {
       DisplayThread.getHandler().runWithScissors(() ->
               //运行在android.display线程
               sInstance = new WindowManagerService(context, im, haveInputMethods, showBootMsgs,
                       onlyCore, policy), 0);
       return sInstance;
   }

2.2 WindowManagerService

[->WindowManagerService.java]

private WindowManagerService(Context context, InputManagerService inputManager,
           boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore,
           WindowManagerPolicy policy) {
       //初始化锁
       installLock(this, INDEX_WINDOW);
       mContext = context;
       mHaveInputMethods = haveInputMethods;
       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);
       mDrawLockTimeoutMillis = context.getResources().getInteger(
               com.android.internal.R.integer.config_drawLockTimeoutMillis);
       mAllowAnimationsInLowPowerMode = context.getResources().getBoolean(
               com.android.internal.R.bool.config_allowAnimationsInLowPowerMode);
       mMaxUiWidth = context.getResources().getInteger(
               com.android.internal.R.integer.config_maxUiWidth);
       mDisableTransitionAnimation = context.getResources().getBoolean(
               com.android.internal.R.bool.config_disableTransitionAnimation);
       mInputManager = inputManager; // Must be before createDisplayContentLocked.
       mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
       mDisplaySettings = new DisplaySettings();
       mDisplaySettings.readSettingsLocked();

       mPolicy = policy;
       mAnimator = new WindowAnimator(this);
       //创建根Window,用于支持多屏幕的功能
       mRoot = new RootWindowContainer(this);

       mWindowPlacerLocked = new WindowSurfacePlacer(this);
       mTaskSnapshotController = new TaskSnapshotController(this);

       mWindowTracing = WindowTracing.createDefaultAndStartLooper(context);

       LocalServices.addService(WindowManagerPolicy.class, mPolicy);

       if(mInputManager != null) {
           final InputChannel inputChannel = mInputManager.monitorInput(TAG_WM);
           mPointerEventDispatcher = inputChannel != null
                   ? new PointerEventDispatcher(inputChannel) : null;
       } else {
           mPointerEventDispatcher = null;
       }

       mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);

       mKeyguardDisableHandler = new KeyguardDisableHandler(mContext, mPolicy);

       mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
       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 (mWindowMap) {
                       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);

       mAppTransition = new AppTransition(context, this);
       mAppTransition.registerListenerLocked(mActivityManagerAppTransitionNotifier);

       final AnimationHandler animationHandler = new AnimationHandler();
       mBoundsAnimationController = new BoundsAnimationController(context, mAppTransition,
               AnimationThread.getHandler(), animationHandler);

       mActivityManager = ActivityManager.getService();
       mAmInternal = LocalServices.getService(ActivityManagerInternal.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);

       mPmInternal = LocalServices.getService(PackageManagerInternal.class);
       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);

       // Get persisted window scale setting
       mWindowAnimationScaleSetting = Settings.Global.getFloat(context.getContentResolver(),
               Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScaleSetting);
       mTransitionAnimationScaleSetting = Settings.Global.getFloat(context.getContentResolver(),
               Settings.Global.TRANSITION_ANIMATION_SCALE,
               context.getResources().getFloat(
                       R.dimen.config_appTransitionAnimationDurationScaleDefault));

       setAnimatorDurationScale(Settings.Global.getFloat(context.getContentResolver(),
               Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScaleSetting));

       IntentFilter filter = new IntentFilter();
       // Track changes to DevicePolicyManager state so we can enable/disable keyguard.
       filter.addAction(ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
       mContext.registerReceiver(mBroadcastReceiver, filter);

       mLatencyTracker = LatencyTracker.getInstance(context);

       mSettingsObserver = new SettingsObserver();

       mHoldingScreenWakeLock = mPowerManager.newWakeLock(
               PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, TAG_WM);
       mHoldingScreenWakeLock.setReferenceCounted(false);

       mSurfaceAnimationRunner = new SurfaceAnimationRunner(mPowerManagerInternal);

       mAllowTheaterModeWakeFromLayout = context.getResources().getBoolean(
               com.android.internal.R.bool.config_allowTheaterModeWakeFromWindowLayout);

       mTaskPositioningController = new TaskPositioningController(
               this, mInputManager, mInputMonitor, mActivityManager, mH.getLooper());
       mDragDropController = new DragDropController(this, mH.getLooper());

       LocalServices.addService(WindowManagerInternal.class, new LocalService());
   }

WMS的初始化在“android.display”线程中执行,mH继承于Handler,采用的是当前线程的Looper, mH.sendMessage方法也运行在android.display”线程

2.3 WMS.onInitReady

[->WindowManagerService.java]

public void onInitReady() {
       initPolicy();

       // Add ourself to the Watchdog monitors.
       Watchdog.getInstance().addMonitor(this);

       openSurfaceTransaction();
       try {
           createWatermarkInTransaction();
       } finally {
           closeSurfaceTransaction("createWatermarkInTransaction");
       }

       showEmulatorDisplayOverlayIfNeeded();
   }

2.3.1 initPolicy

[->WindowManagerService.java]

private void initPolicy() {
      //运行在Ui线程
       UiThread.getHandler().runWithScissors(new Runnable() {
           @Override
           public void run() {
               WindowManagerPolicyThread.set(Thread.currentThread(), Looper.myLooper());
               //此处为PhoneWindowManager
               mPolicy.init(mContext, WindowManagerService.this, WindowManagerService.this);
           }
       }, 0);
   }

2.3.2 runWithScissors

[->Handler.java]

public final boolean runWithScissors(final 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");
       }

       if (Looper.myLooper() == mLooper) {
           r.run();
           return true;
       }

       BlockingRunnable br = new BlockingRunnable(r);
       return br.postAndWait(this, timeout);
   }

2.3.3 postAndWait

[->Handler.java::BlockingRunnable]

public boolean postAndWait(Handler handler, long timeout) {
           if (!handler.post(this)) {
               return false;
           }

           synchronized (this) {
               if (timeout > 0) {
                   final long expirationTime = SystemClock.uptimeMillis() + timeout;
                   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;
       }

postAndWait是阻塞操作,把消息放在Handler所指向的线程,此处是android.ui线程,由于该方法运行在android.display线程,从而会进入等待状态,直到执行完成,再唤醒android.display线程,PWM.init运行在android.ui线程,属于同步阻塞。

2.4 PWM.init

[->PhoneWindowManager.java]

public void init(Context context, IWindowManager windowManager,
            WindowManagerFuncs windowManagerFuncs) {
        mContext = context;
        mWindowManager = windowManager;
        mWindowManagerFuncs = windowManagerFuncs;
        mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
        mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
        mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
        mDreamManagerInternal = LocalServices.getService(DreamManagerInternal.class);
        mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
        mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
        mHasFeatureWatch = mContext.getPackageManager().hasSystemFeature(FEATURE_WATCH);
        mHasFeatureLeanback = mContext.getPackageManager().hasSystemFeature(FEATURE_LEANBACK);
        mAccessibilityShortcutController =
                new AccessibilityShortcutController(mContext, new Handler(), mCurrentUserId);
        mLogger = new MetricsLogger();
        // Init display burn-in protection
        boolean burnInProtectionEnabled = context.getResources().getBoolean(
                com.android.internal.R.bool.config_enableBurnInProtection);
        // Allow a system property to override this. Used by developer settings.
        boolean burnInProtectionDevMode =
                SystemProperties.getBoolean("persist.debug.force_burn_in", false);
        if (burnInProtectionEnabled || burnInProtectionDevMode) {
            final int minHorizontal;
            final int maxHorizontal;
            final int minVertical;
            final int maxVertical;
            final int maxRadius;
            if (burnInProtectionDevMode) {
                minHorizontal = -8;
                maxHorizontal = 8;
                minVertical = -8;
                maxVertical = -4;
                maxRadius = (isRoundWindow()) ? 6 : -1;
            } else {
                Resources resources = context.getResources();
                minHorizontal = resources.getInteger(
                        com.android.internal.R.integer.config_burnInProtectionMinHorizontalOffset);
                maxHorizontal = resources.getInteger(
                        com.android.internal.R.integer.config_burnInProtectionMaxHorizontalOffset);
                minVertical = resources.getInteger(
                        com.android.internal.R.integer.config_burnInProtectionMinVerticalOffset);
                maxVertical = resources.getInteger(
                        com.android.internal.R.integer.config_burnInProtectionMaxVerticalOffset);
                maxRadius = resources.getInteger(
                        com.android.internal.R.integer.config_burnInProtectionMaxRadius);
            }
            mBurnInProtectionHelper = new BurnInProtectionHelper(
                    context, minHorizontal, maxHorizontal, minVertical, maxVertical, maxRadius);
        }
        //运行在ui线程
        mHandler = new PolicyHandler(); 
        mWakeGestureListener = new MyWakeGestureListener(mContext, mHandler);
        mOrientationListener = new MyOrientationListener(mContext, mHandler);
        try {
            mOrientationListener.setCurrentRotation(windowManager.getDefaultDisplayRotation());
        } catch (RemoteException ex) { }
        mSettingsObserver = new SettingsObserver(mHandler);
        mSettingsObserver.observe();
        mShortcutManager = new ShortcutManager(context);
        mUiMode = context.getResources().getInteger(
                com.android.internal.R.integer.config_defaultUiModeType);
        mHomeIntent =  new Intent(Intent.ACTION_MAIN, null);
        mHomeIntent.addCategory(Intent.CATEGORY_HOME);
        mHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
        mEnableCarDockHomeCapture = context.getResources().getBoolean(
                com.android.internal.R.bool.config_enableCarDockHomeLaunch);
        mCarDockIntent =  new Intent(Intent.ACTION_MAIN, null);
        mCarDockIntent.addCategory(Intent.CATEGORY_CAR_DOCK);
        mCarDockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
        mDeskDockIntent =  new Intent(Intent.ACTION_MAIN, null);
        mDeskDockIntent.addCategory(Intent.CATEGORY_DESK_DOCK);
        mDeskDockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
        mVrHeadsetHomeIntent =  new Intent(Intent.ACTION_MAIN, null);
        mVrHeadsetHomeIntent.addCategory(Intent.CATEGORY_VR_HOME);
        mVrHeadsetHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);

        mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
        mBroadcastWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
                "PhoneWindowManager.mBroadcastWakeLock");
        mPowerKeyWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
                "PhoneWindowManager.mPowerKeyWakeLock");
        mEnableShiftMenuBugReports = "1".equals(SystemProperties.get("ro.debuggable"));
        mSupportAutoRotation = mContext.getResources().getBoolean(
                com.android.internal.R.bool.config_supportAutoRotation);
        mLidOpenRotation = readRotation(
                com.android.internal.R.integer.config_lidOpenRotation);
        mCarDockRotation = readRotation(
                com.android.internal.R.integer.config_carDockRotation);
        mDeskDockRotation = readRotation(
                com.android.internal.R.integer.config_deskDockRotation);
        mUndockedHdmiRotation = readRotation(
                com.android.internal.R.integer.config_undockedHdmiRotation);
        mCarDockEnablesAccelerometer = mContext.getResources().getBoolean(
                com.android.internal.R.bool.config_carDockEnablesAccelerometer);
        mDeskDockEnablesAccelerometer = mContext.getResources().getBoolean(
                com.android.internal.R.bool.config_deskDockEnablesAccelerometer);
        mLidKeyboardAccessibility = mContext.getResources().getInteger(
                com.android.internal.R.integer.config_lidKeyboardAccessibility);
        mLidNavigationAccessibility = mContext.getResources().getInteger(
                com.android.internal.R.integer.config_lidNavigationAccessibility);
        mLidControlsScreenLock = mContext.getResources().getBoolean(
                com.android.internal.R.bool.config_lidControlsScreenLock);
        mLidControlsSleep = mContext.getResources().getBoolean(
                com.android.internal.R.bool.config_lidControlsSleep);
        mTranslucentDecorEnabled = mContext.getResources().getBoolean(
                com.android.internal.R.bool.config_enableTranslucentDecor);

        mAllowTheaterModeWakeFromKey = mContext.getResources().getBoolean(
                com.android.internal.R.bool.config_allowTheaterModeWakeFromKey);
        mAllowTheaterModeWakeFromPowerKey = mAllowTheaterModeWakeFromKey
                || mContext.getResources().getBoolean(
                    com.android.internal.R.bool.config_allowTheaterModeWakeFromPowerKey);
        mAllowTheaterModeWakeFromMotion = mContext.getResources().getBoolean(
                com.android.internal.R.bool.config_allowTheaterModeWakeFromMotion);
        mAllowTheaterModeWakeFromMotionWhenNotDreaming = mContext.getResources().getBoolean(
                com.android.internal.R.bool.config_allowTheaterModeWakeFromMotionWhenNotDreaming);
        mAllowTheaterModeWakeFromCameraLens = mContext.getResources().getBoolean(
                com.android.internal.R.bool.config_allowTheaterModeWakeFromCameraLens);
        mAllowTheaterModeWakeFromLidSwitch = mContext.getResources().getBoolean(
                com.android.internal.R.bool.config_allowTheaterModeWakeFromLidSwitch);
        mAllowTheaterModeWakeFromWakeGesture = mContext.getResources().getBoolean(
                com.android.internal.R.bool.config_allowTheaterModeWakeFromGesture);

        mGoToSleepOnButtonPressTheaterMode = mContext.getResources().getBoolean(
                com.android.internal.R.bool.config_goToSleepOnButtonPressTheaterMode);

        mSupportLongPressPowerWhenNonInteractive = mContext.getResources().getBoolean(
                com.android.internal.R.bool.config_supportLongPressPowerWhenNonInteractive);

        mLongPressOnBackBehavior = mContext.getResources().getInteger(
                com.android.internal.R.integer.config_longPressOnBackBehavior);

        mShortPressOnPowerBehavior = mContext.getResources().getInteger(
                com.android.internal.R.integer.config_shortPressOnPowerBehavior);
        mLongPressOnPowerBehavior = mContext.getResources().getInteger(
                com.android.internal.R.integer.config_longPressOnPowerBehavior);
        mVeryLongPressOnPowerBehavior = mContext.getResources().getInteger(
                com.android.internal.R.integer.config_veryLongPressOnPowerBehavior);
        mDoublePressOnPowerBehavior = mContext.getResources().getInteger(
                com.android.internal.R.integer.config_doublePressOnPowerBehavior);
        mTriplePressOnPowerBehavior = mContext.getResources().getInteger(
                com.android.internal.R.integer.config_triplePressOnPowerBehavior);
        mShortPressOnSleepBehavior = mContext.getResources().getInteger(
                com.android.internal.R.integer.config_shortPressOnSleepBehavior);
        mVeryLongPressTimeout = mContext.getResources().getInteger(
                com.android.internal.R.integer.config_veryLongPressTimeout);
        mAllowStartActivityForLongPressOnPowerDuringSetup = mContext.getResources().getBoolean(
                com.android.internal.R.bool.config_allowStartActivityForLongPressOnPowerInSetup);

        mUseTvRouting = AudioSystem.getPlatformType(mContext) == AudioSystem.PLATFORM_TELEVISION;

        mHandleVolumeKeysInWM = mContext.getResources().getBoolean(
                com.android.internal.R.bool.config_handleVolumeKeysInWindowManager);

        readConfigurationDependentBehaviors();

        mAccessibilityManager = (AccessibilityManager) context.getSystemService(
                Context.ACCESSIBILITY_SERVICE);

        // register for dock events
        IntentFilter filter = new IntentFilter();
        filter.addAction(UiModeManager.ACTION_ENTER_CAR_MODE);
        filter.addAction(UiModeManager.ACTION_EXIT_CAR_MODE);
        filter.addAction(UiModeManager.ACTION_ENTER_DESK_MODE);
        filter.addAction(UiModeManager.ACTION_EXIT_DESK_MODE);
        filter.addAction(Intent.ACTION_DOCK_EVENT);
        Intent intent = context.registerReceiver(mDockReceiver, filter);
        if (intent != null) {
            // Retrieve current sticky dock event broadcast.
            mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
                    Intent.EXTRA_DOCK_STATE_UNDOCKED);
        }

        // register for dream-related broadcasts
        filter = new IntentFilter();
        filter.addAction(Intent.ACTION_DREAMING_STARTED);
        filter.addAction(Intent.ACTION_DREAMING_STOPPED);
        context.registerReceiver(mDreamReceiver, filter);

        // register for multiuser-relevant broadcasts
        filter = new IntentFilter(Intent.ACTION_USER_SWITCHED);
        context.registerReceiver(mMultiuserReceiver, filter);

        // monitor for system gestures
        // TODO(multi-display): Needs to be display specific.
        mSystemGestures = new SystemGesturesPointerEventListener(context,
                new SystemGesturesPointerEventListener.Callbacks() {
                    @Override
                    public void onSwipeFromTop() {
                        if (mStatusBar != null) {
                            requestTransientBars(mStatusBar);
                        }
                    }
                    @Override
                    public void onSwipeFromBottom() {
                        if (mNavigationBar != null && mNavigationBarPosition == NAV_BAR_BOTTOM) {
                            requestTransientBars(mNavigationBar);
                        }
                    }
                    @Override
                    public void onSwipeFromRight() {
                        if (mNavigationBar != null && mNavigationBarPosition == NAV_BAR_RIGHT) {
                            requestTransientBars(mNavigationBar);
                        }
                    }
                    @Override
                    public void onSwipeFromLeft() {
                        if (mNavigationBar != null && mNavigationBarPosition == NAV_BAR_LEFT) {
                            requestTransientBars(mNavigationBar);
                        }
                    }
                    @Override
                    public void onFling(int duration) {
                        if (mPowerManagerInternal != null) {
                            mPowerManagerInternal.powerHint(
                                    PowerHint.INTERACTION, duration);
                        }
                    }
                    @Override
                    public void onDebug() {
                        // no-op
                    }
                    @Override
                    public void onDown() {
                        mOrientationListener.onTouchStart();
                    }
                    @Override
                    public void onUpOrCancel() {
                        mOrientationListener.onTouchEnd();
                    }
                    @Override
                    public void onMouseHoverAtTop() {
                        mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS);
                        Message msg = mHandler.obtainMessage(MSG_REQUEST_TRANSIENT_BARS);
                        msg.arg1 = MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS;
                        mHandler.sendMessageDelayed(msg, 500);
                    }
                    @Override
                    public void onMouseHoverAtBottom() {
                        mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS);
                        Message msg = mHandler.obtainMessage(MSG_REQUEST_TRANSIENT_BARS);
                        msg.arg1 = MSG_REQUEST_TRANSIENT_BARS_ARG_NAVIGATION;
                        mHandler.sendMessageDelayed(msg, 500);
                    }
                    @Override
                    public void onMouseLeaveFromEdge() {
                        mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS);
                    }
                });
        mImmersiveModeConfirmation = new ImmersiveModeConfirmation(mContext);
        mWindowManagerFuncs.registerPointerEventListener(mSystemGestures);

        mVibrator = (Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE);
        mLongPressVibePattern = getLongIntArray(mContext.getResources(),
                com.android.internal.R.array.config_longPressVibePattern);
        mCalendarDateVibePattern = getLongIntArray(mContext.getResources(),
                com.android.internal.R.array.config_calendarDateVibePattern);
        mSafeModeEnabledVibePattern = getLongIntArray(mContext.getResources(),
                com.android.internal.R.array.config_safeModeEnabledVibePattern);

        mScreenshotChordEnabled = mContext.getResources().getBoolean(
                com.android.internal.R.bool.config_enableScreenshotChord);

        mGlobalKeyManager = new GlobalKeyManager(mContext);

        // Controls rotation and the like.
        initializeHdmiState();

        // Match current screen state.
        if (!mPowerManager.isInteractive()) {
            startedGoingToSleep(WindowManagerPolicy.OFF_BECAUSE_OF_USER);
            finishedGoingToSleep(WindowManagerPolicy.OFF_BECAUSE_OF_USER);
        }

        mWindowManagerInternal.registerAppTransitionListener(
                mStatusBarController.getAppTransitionListener());
        mWindowManagerInternal.registerAppTransitionListener(new AppTransitionListener() {
            @Override
            public int onAppTransitionStartingLocked(int transit, IBinder openToken,
                    IBinder closeToken, long duration, long statusBarAnimationStartTime,
                    long statusBarAnimationDuration) {
                return handleStartTransitionForKeyguardLw(transit, duration);
            }

            @Override
            public void onAppTransitionCancelledLocked(int transit) {
                handleStartTransitionForKeyguardLw(transit, 0 /* duration */);
            }
        });
        mKeyguardDelegate = new KeyguardServiceDelegate(mContext,
                new StateCallback() {
                    @Override
                    public void onTrustedChanged() {
                        mWindowManagerFuncs.notifyKeyguardTrustedChanged();
                    }

                    @Override
                    public void onShowingChanged() {
                        mWindowManagerFuncs.onKeyguardShowingAndNotOccludedChanged();
                    }
                });
        mScreenshotHelper = new ScreenshotHelper(mContext);
    }

2.5 WMS.displayReady

private void displayReady(int displayId) {
      synchronized(mWindowMap) {
          //得到显示的displayid
          final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
          if (displayContent != null) {
              mAnimator.addDisplayLocked(displayId);
              displayContent.initializeDisplayBaseInfo();
              reconfigureDisplayLocked(displayContent);
          }
      }
  }

2.6 WMS.systemReady

[->WindowManagerService.java]

public void systemReady() {
      mPolicy.systemReady();
      //截屏systemReady
      mTaskSnapshotController.systemReady();
      mHasWideColorGamutSupport = queryWideColorGamutSupport();
  }

2.6.1 PWM.systemReady

[->PhoneWindowManager]

public void systemReady() {
       // In normal flow, systemReady is called before other system services are ready.
       // So it is better not to bind keyguard here.
       mKeyguardDelegate.onSystemReady();

       mVrManagerInternal = LocalServices.getService(VrManagerInternal.class);
       if (mVrManagerInternal != null) {
           mVrManagerInternal.addPersistentVrModeStateListener(mPersistentVrModeListener);
       }

       readCameraLensCoverState();
       updateUiMode();
       synchronized (mLock) {
           updateOrientationListenerLp();
           mSystemReady = true;
           mHandler.post(new Runnable() {
               @Override
               public void run() {
                   updateSettings();
               }
           });
           // If this happens, for whatever reason, systemReady came later than systemBooted.
           // And keyguard should be already bound from systemBooted
           if (mSystemBooted) {
               mKeyguardDelegate.onBootCompleted();
           }
       }

       mSystemGestures.systemReady();
       mImmersiveModeConfirmation.systemReady();

       mAutofillManagerInternal = LocalServices.getService(AutofillManagerInternal.class);
   }

三、总结

整个启动过程有3个线程,systemserver主线程,”android.display”,”android.ui”,整个过程采用阻塞的方式(利用runWithScissors)执行,WMS.mH的Looper运行在”android.display”进程。流程如下:

附录

源码路径

frameworks/base/services/java/com/android/server/SystemServer.java
frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
frameworks/base/services/core/java/com/android/server/UiThread.java
frameworks/base/core/java/android/os/Handler.java
frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java