zoukankan      html  css  js  c++  java
  • Android10_原理机制系列_Window介绍及WMS的启动过程

    简介

    Window简介

    Android中,Window是一个重要部分,用户看到的界面、触摸显示界面进行一系列操作都涉及到Window。但实际上,Window本身并不具备绘制功能。
    该篇简单介绍下Window的一点内容,同时总结下WMS的启动过程。在下篇会逐步介绍一个Activity是如何创建出窗口 并 添加到WMS中的。
    该篇基于Andorid10的代码。

    窗口涉及到一下几个功能:

    1. 窗口管理-WMS
      WMS管理窗口的创建、添加、删除、大小、层级等等。

    2. 输入中转-IMS(InputManagerService)
      触摸窗口产生触摸事件,IMS对触摸事件进行处理,最后寻找一个最合适窗口进行反馈处理。

    3. 窗口动画 ---WindowAnimator
      窗口间进行切换时,使用窗口动画可以实现更好的效果,窗口动画主要由WindowAnimator管理。可以在开发者模式菜单找到相应设置。

    4. Surface管理 ---SurfaceFlinger
      窗口不具备有绘制的功能,因此每个窗口都需要有一块Surface来供自己绘制。为每个窗口分配Surface是由WMS来完成的。
      Surface就像画布,然后通过Canvas或OpenGL绘制。
      SurfaceFlinger的作用主要是merge Surface,它接受多个来源的Surface图形显示数据(所有Surface:所有Window的Surface,特殊情况 有些Surface跟Window无关,如StrictMode),然后将他们合并(根据特定顺序Z-order),然后发送到显示设备。如最常见的界面是3层,顶部的statusbar,底部的导航栏,应用界面。

    WMS简介

    WMS同之前总结过的AMS、PMS一样(链接:AMS的启动AMS之应用的第一次启动过程PMS的启动及应用的安装过程),是系统服务,作为Binder的服务端。 下表简单对比列出下:

    系统服务 binder服务端 binder客户端 服务名
    AMS ActivityManagerService(extends IActivityManager.Stub) ActivityManager activity(Context.ACTIVITY_SERVICE)
    PMS PackageManagerService(extends IPackageManager.Stub) PackageManager package
    WMS WindowManagerService(extends IWindowManager.Stub) WindowManager window(Context.WINDOW_SERVICE)

    一般获取方法:
    获取binder客户端,与服务通信,类似:
    ActivityManager am = (ActivityManager) context.getSystemService("activity");
    ActivityManager am = context.getSystemService(ActivityManager.class);
    从ServiceManager获取服务的Binder,类似:
    IBinder binder = ServiceManager.getService(Context.ACTIVITY_SERVICE);
    下面两个也是用的ServiceManager.getService():
    IActivityManager mgr = ActivityManager.getService();
    PackageManagerService pm = (PackageManagerService) ServiceManager.getService("package");

    WMS的启动过程

    之前总结了 AMS的启动AMS之应用的第一次启动过程PMS的启动及应用的安装过程。 这里WMS的启动类似,下面会简单介绍下。

    WMS是在system server启动后的startOtherServices()中启动。下面截取了其中关于WMS相关的代码。

    //SystemServer.java
    private void startOtherServices() {
        final Context context = mSystemContext;
        WindowManagerService wm = null;
       
        try {
            // WMS 依赖 sensor service
            ConcurrentUtils.waitForFutureNoInterrupt(mSensorServiceStart, START_SENSOR_SERVICE);
            //标记1:StartWindowManagerService
            //创建WMS实例
            wm = WindowManagerService.main(context, inputManager, !mFirstBoot, mOnlyCore,
                    new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager);
            //注册WINDOW_SERVICE 服务到 ServiceManager。 
            ServiceManager.addService(Context.WINDOW_SERVICE, wm, /* allowIsolated= */ false,
                    DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PROTO);
            ServiceManager.addService(Context.INPUT_SERVICE, inputManager,
                    /* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL);
    
            //标记2:SetWindowManagerService
            //WMS设置到AMS/ATMS中。     
            mActivityManagerService.setWindowManager(wm);
            
            //标记3:WindowManagerServiceOnInitReady
            //WMS初始化完成。 
            wm.onInitReady();
    
            inputManager.setWindowManagerCallbacks(wm.getInputManagerCallback());
            inputManager.start();
    
            mDisplayManagerService.windowManagerAndInputReady();
        }
    
        // Before things start rolling, be sure we have decided whether
        // we are in safe mode.
        final boolean safeMode = wm.detectSafeMode();
        try {
            //标记4:MakeDisplayReady
            //初始化显示信息
            wm.displayReady();
        } 
    
        if (mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
            if (!isWatch) {
                try {
                    statusBar = new StatusBarManagerService(context, wm);
                    ServiceManager.addService(Context.STATUS_BAR_SERVICE, statusBar);
                } 
            }
        }
    
        try {
            //标记5:MakeWindowManagerServiceReady
            //通知WMS系统准备好了,初始化完成了。    
            wm.systemReady();
        } 
    
        final Configuration config = wm.computeNewConfiguration(DEFAULT_DISPLAY);
        DisplayMetrics metrics = new DisplayMetrics();
        WindowManager w = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        w.getDefaultDisplay().getMetrics(metrics);
        context.getResources().updateConfiguration(config, metrics);
    
        final WindowManagerService windowManagerF = wm;
    
        mActivityManagerService.systemReady(() -> {      
            try {
                startSystemUi(context, windowManagerF);
            } 
        }, BOOT_TIMINGS_TRACE_LOG);
    }
    

    startOtherServices()中,创建了WindowManagerService对象 并 注册了服务Context.WINDOW_SERVICE。然后进行了各种初始化等操作。
    注意上面的注释,下面主要看下其中的5行代码(标记1-标记5)。

    标记1:wm = WindowManagerService.main(...)

    //public class WindowManagerService extends IWindowManager.Stub implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
    //WindowManagerService.java
    private static WindowManagerService sInstance;
    static WindowManagerService getInstance() {
        return sInstance;
    }
    
    public static WindowManagerService main(final Context context, final InputManagerService im,
            final boolean showBootMsgs, final boolean onlyCore, WindowManagerPolicy policy,
            ActivityTaskManagerService atm) {
        return main(context, im, showBootMsgs, onlyCore, policy, atm,
                SurfaceControl.Transaction::new);
    }
    
    @VisibleForTesting
    public static WindowManagerService main(final Context context, final InputManagerService im,
            final boolean showBootMsgs, final boolean onlyCore, WindowManagerPolicy policy,
            ActivityTaskManagerService atm, TransactionFactory transactionFactory) {
        //android.display线程中执行
        DisplayThread.getHandler().runWithScissors(() ->
                sInstance = new WindowManagerService(context, im, showBootMsgs, onlyCore, policy,
                        atm, transactionFactory), 0);
        return sInstance;
    }
    
    
    private WindowManagerService(Context context, InputManagerService inputManager,
            boolean showBootMsgs, boolean onlyCore, WindowManagerPolicy policy,
            ActivityTaskManagerService atm, TransactionFactory transactionFactory) {
        ......
        //ActivityTaskManagerService
        mAtmService = atm;
        //context是mSystemContext   system server进程上下文
        mContext = context;
        mOnlyCore = onlyCore;
        mInTouchMode = context.getResources().getBoolean(
                com.android.internal.R.bool.config_defaultInTouchMode);
        mMaxUiWidth = context.getResources().getInteger(
                com.android.internal.R.integer.config_maxUiWidth);
        mLowRamTaskSnapshotsAndRecents = context.getResources().getBoolean(
                com.android.internal.R.bool.config_lowRamTaskSnapshotsAndRecents);
        //输入法管理
        mInputManager = inputManager; // Must be before createDisplayContentLocked.
        mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
        mDisplayWindowSettings = new DisplayWindowSettings(this);
        mPolicy = policy;
        //管理窗口动画
        mAnimator = new WindowAnimator(this);
        mRoot = new RootWindowContainer(this);
        mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
        mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
        mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
        mActivityManager = ActivityManager.getService();
        mActivityTaskManager = ActivityTaskManager.getService();
        mAmInternal = LocalServices.getService(ActivityManagerInternal.class);
        mAtmInternal = LocalServices.getService(ActivityTaskManagerInternal.class);
        mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
        ......
    }
    

    WindowManagerService.main()主要就是创建了WindowManagerService对象。
    WindowManagerService的构造方法没有完整附上了,没什么特别的,基本是初始化并保存 WMS中需要用到的各种对象等数据。上面列出了几个常见的。
    DisplayThread.getHandler().runWithScissors(),注意这里是DisplayThread(继承ServiceThread),是在android.display线程上执行。

    题外话DisplayThread.getHandler().runWithScissors(() -> sInstance = new WindowManagerService(...),0);lambda表达式 ,这里相当于:

    DisplayThread.getHandler().runWithScissors(
        new Runnable() {
            @Override
            public void run() {
                sInstance = new WindowManagerService(context, im, showBootMsgs, onlyCore, policy,
                        atm, transactionFactory)
            }
        }, 0);
    

    标记2:mActivityManagerService.setWindowManager(wm)

    这个很简单,wm被设置的到AMS和ATMS中。

    //ActivityManagerService.java
    public void setWindowManager(WindowManagerService wm) {
        synchronized (this) {
            mWindowManager = wm;
            mActivityTaskManager.setWindowManager(wm);
        }
    }
    

    标记3:wm.onInitReady()

    //WindowManagerService.java
    public void onInitReady() {
        //初始化PhoneWindowManager (PhoneWindowManager implements WindowManagerPolicy)
        initPolicy();
    
        // Add ourself to the Watchdog monitors.
        Watchdog.getInstance().addMonitor(this);
        //SurfaceControl.openTransaction();
        openSurfaceTransaction();
        try {
            //水印,这里了解了下
            createWatermarkInTransaction();
        } finally {
            closeSurfaceTransaction("createWatermarkInTransaction");
        }
    
        showEmulatorDisplayOverlayIfNeeded();
    }
    
    private void initPolicy() {
        //android.ui线程上执行
        UiThread.getHandler().runWithScissors(new Runnable() {
            @Override
            public void run() {
                WindowManagerPolicyThread.set(Thread.currentThread(), Looper.myLooper());
                mPolicy.init(mContext, WindowManagerService.this, WindowManagerService.this);
            }
        }, 0);
    }
    
    void createWatermarkInTransaction() {
        ...
        File file = new File("/system/etc/setup.conf");
        ...
        try {
            ...
            if (line != null) {
                String[] toks = line.split("%");
                if (toks != null && toks.length > 0) {
                    // TODO(multi-display): Show watermarks on secondary displays.
                    final DisplayContent displayContent = getDefaultDisplayContentLocked();
                    mWatermark = new Watermark(displayContent, displayContent.mRealDisplayMetrics,
                            toks);
                }
            }
        }
        ...
    }
    

    onInitReady()这里几个地方记录下,个人觉得比较值得注意的:

    1. initPolicy()中,mPolicy即PhoneWindowManager对象,从开始处startOtherServices()中可以看到。startOtherServices()创建了PhoneWindowManager,这里完成了PhoneWindowManager的init()操作。

    2. initPolicy()中,是运行在UiThread,也是继承的ServiceThread。执行mPolicy.init()。

    3. createWatermarkInTransaction():这个可以看一下。这是在window manager的窗口上添加水印。这个功能几乎没有用过,尝试了下,效果如下图。

    往后跟踪,可以看到:显示的字符配置到/system/etc/setup.conf里的,Watermark有个解析过程(类似解密),详细的可以自己看下Watermark的构造方法。如下图中显示的字符串“WMS”,我在setup.conf配置的是“A8B2A<%30”,%后面是字体大小。“A8B2A<”即“WMS”。

    wms_watermark

    标记4:wm.displayReady()

    //WindowManagerService.java
    public void displayReady() {
        synchronized (mGlobalLock) {
            if (mMaxUiWidth > 0) {
                mRoot.forAllDisplays(displayContent -> displayContent.setMaxUiWidth(mMaxUiWidth));
            }
            //全局设置仅适用于默认显示。设置Display size、Display density、Display scaling mode。
            //getDefaultDisplayContentLocked()。
            final boolean changed = applyForcedPropertiesForDefaultDisplay();
            mAnimator.ready();
            mDisplayReady = true;
            if (changed) {
                reconfigureDisplayLocked(getDefaultDisplayContentLocked());
            }
            mIsTouchDevice = mContext.getPackageManager().hasSystemFeature(
                    PackageManager.FEATURE_TOUCHSCREEN);
        }
    
        try {
            //初始化配置完成,ATMS完成第一次Configuration更新
            mActivityTaskManager.updateConfiguration(null);
        } catch (RemoteException e) {
        }
    
        updateCircularDisplayMaskIfNeeded();
    }
    

    看下注释。这里主要是初始化显示信息。初始化配置完成,ATMS完成第一次Configuration更新。

    标记5:wm.systemReady()

    //WindowManagerService.java
    public void systemReady() {
        mSystemReady = true;
        mPolicy.systemReady();
        ...
    }
    

    系统初始化完成,通知WMS系统准备好了。这里主要完成:mPolicy.systemReady()

    在标记3 时,有在android.ui线程执行的mPolicy.init(),这里有mPolicy.systemReady()
    mPolicy是PhoneWindowManager,关于这两个方法这里不关注,在后续类似事件传递时应该会再触及。

  • 相关阅读:
    react路由组件&&非路由组件
    react函数式组件(非路由组件)实现路由跳转
    react使用antd组件递归实现左侧菜单导航树
    【LeetCode】65. Valid Number
    【LeetCode】66. Plus One (2 solutions)
    【LeetCode】68. Text Justification
    【LeetCode】69. Sqrt(x) (2 solutions)
    【LeetCode】72. Edit Distance
    【LeetCode】73. Set Matrix Zeroes (2 solutions)
    【LeetCode】76. Minimum Window Substring
  • 原文地址:https://www.cnblogs.com/fanglongxiang/p/13951212.html
Copyright © 2011-2022 走看看