当前位置: 首页 > news >正文

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

 

 

相关文章:

  • linux文件压缩解压命令
  • iOS无限滑动轮播图可竖着滑动
  • Java递归拷贝文件夹
  • SSH.ASDM:远程管理
  • Adapter.notifyDataSetChanged与ListView.Post()刷新问题
  • SpringBoot几种定时任务的实现方式
  • Linux文件权限命令及配置
  • java判断集合list是为空
  • 升级的Electric Cloud平台增添了大型机和微服务功能
  • day16-示例:表单验证
  • c语言程序设计第6周编程作业一(分解质因数)
  • 将任意程序添加进右键菜单方法
  • 技术分享连载(二十四)
  • 序列化Serializable和Parcelable的理解和区别
  • vue-router的history模式发布配置
  • 网络传输文件的问题
  • 【347天】每日项目总结系列085(2018.01.18)
  • Git的一些常用操作
  • JavaScript学习总结——原型
  • jdbc就是这么简单
  • JS+CSS实现数字滚动
  • Linux gpio口使用方法
  • spring-boot List转Page
  • Vue2.x学习三:事件处理生命周期钩子
  • 技术胖1-4季视频复习— (看视频笔记)
  • 项目管理碎碎念系列之一:干系人管理
  • 小程序滚动组件,左边导航栏与右边内容联动效果实现
  • 一个6年java程序员的工作感悟,写给还在迷茫的你
  • 责任链模式的两种实现
  • 正则与JS中的正则
  • 3月27日云栖精选夜读 | 从 “城市大脑”实践,瞭望未来城市源起 ...
  • 如何用纯 CSS 创作一个货车 loader
  • 智能情侣枕Pillow Talk,倾听彼此的心跳
  • ​iOS实时查看App运行日志
  • ​力扣解法汇总946-验证栈序列
  • #define,static,const,三种常量的区别
  • (175)FPGA门控时钟技术
  • (阿里云万网)-域名注册购买实名流程
  • (附源码)计算机毕业设计SSM在线影视购票系统
  • (剑指Offer)面试题34:丑数
  • (免费领源码)python#django#mysql公交线路查询系统85021- 计算机毕业设计项目选题推荐
  • (十)DDRC架构组成、效率Efficiency及功能实现
  • (实战篇)如何缓存数据
  • (原創) 如何使用ISO C++讀寫BMP圖檔? (C/C++) (Image Processing)
  • .halo勒索病毒解密方法|勒索病毒解决|勒索病毒恢复|数据库修复
  • .java 指数平滑_转载:二次指数平滑法求预测值的Java代码
  • .NET Standard / dotnet-core / net472 —— .NET 究竟应该如何大小写?
  • .NET/C# 的字符串暂存池
  • .net打印*三角形
  • .NET中的Exception处理(C#)
  • .php文件都打不开,打不开php文件怎么办
  • // an array of int
  • @ResponseBody
  • @staticmethod和@classmethod的作用与区别
  • @Transactional 详解