zoukankan      html  css  js  c++  java
  • WMS—启动过程

    基于Android 6.0源码, 分析WMS的启动过程。

    一. 概述

    • Surface:代表画布
    • WMS: 添加window的过程主要功能是添加Surface,管理所有的Surface布局,以及Z轴排序问题;
    • SurfaceFinger: 将Surface按次序混合并显示到物理屏幕上;

    1.1 WMS全貌

    wms_relation

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

    wms_startup

     

  • 相关阅读:
    leetcode 190 Reverse Bits
    vs2010 单文档MFC 通过加载位图文件作为客户区背景
    leetcode 198 House Robber
    记忆化搜索(DP+DFS) URAL 1183 Brackets Sequence
    逆序数2 HDOJ 1394 Minimum Inversion Number
    矩阵连乘积 ZOJ 1276 Optimal Array Multiplication Sequence
    递推DP URAL 1586 Threeprime Numbers
    递推DP URAL 1167 Bicolored Horses
    递推DP URAL 1017 Staircases
    01背包 URAL 1073 Square Country
  • 原文地址:https://www.cnblogs.com/ganchuanpu/p/8385124.html
Copyright © 2011-2022 走看看