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

     

  • 相关阅读:
    面向过程--面向对象
    shiro有哪些组件?
    Redis的特点什么是?
    Spring Boot 有哪些优点?
    什么是 JavaConfig?
    HashMap和Hashtable的区别
    深入理解SQL的四种连接-左外连接、右外连接、内连接、全连接
    Linux指令--tar,gzip
    JQuery 学习总结及实例
    $(this) 和 this 关键字在 jQuery 中有何不同?
  • 原文地址:https://www.cnblogs.com/ganchuanpu/p/8385124.html
Copyright © 2011-2022 走看看