如何应对Android面试官 -> WindowManagerService 启动流程分析

前言


image.png

本章主要从上面几个角度来讲解 WindowManagerService;

相关概念


介绍 WMS 之前,我们先来介绍几个相关的概念;

WMS 存在于 system_server 系统服务进程,view 存在于 app 进程,所有的窗口最终都是通过 wms 来进行管理,为了方便管理,app 和 wms 之间添加了 WindowManager,用来在应用与 wms 之间的管理接口,管理窗口顺序,消息等。

Activity 与 Window 相关概念

  • Activity 只负责生命周期和事件处理;
  • Window 只控制视图;
  • 一个 Activity 包含一个 Window,如果 Activity 没有 Window,那就相当于 Service;
  • AMS 统一调度所有应用程序的 Activity;
  • WMS 控制所有 Window 的显示与隐藏以及要显示的位置;

Window

『Window』表明它是和窗口相关的,“窗口”是一个抽象的概念,从用户的角度来讲,它是一个“界面”;从SurfaceFlinger 的角度来看,它是一个 Layer,承载着和界面有关的数据和属性;从 WMS 角度来看,它是一个WindowState,用于管理和界面有关的状态;添加一个 Window 的过程,就是分配一块 Surface 的过程;

  • 表示一个窗口的概念,是所有 View 的直接管理者,任何视图都通过 Window 呈现(点击事件由 Window->DecorView->View; Activity 的 setContentView 底层通过 Window 完成);
  • Window是一个抽象类,具体且唯一的实现是 PhoneWindow;
  • 创建 Window 需要通过 WindowManager 创建;
  • WindowManager 是外界访问 Window 的入口;
  • Window 具体实现位于 WindowManagerService 中;
  • WindowManager 和 WindowManagerService 的交互是通过 IPC 完成;
  • 定义窗口样式和行为的抽象基类,用于作为顶层的 view 加到 WindowManager 中,其实现类是 PhoneWindow
  • 每个 Window 都需要指定一个 Type(应用窗口、子窗口、系统窗口)。Activity 对应的窗口是应用窗口;PopupWindow,ContextMenu,OptionMenu 是常用的子窗口;像 Toast 和系统警告提示框(如ANR)就是系窗口,还有很多应用的悬浮框也属于系统窗口类型;

image.png

Android上对 Window 进行了弱化,主要是 View;

WindowManager

用来在应用与window之间的管理接口,管理窗口顺序,消息等;

WindowManagerService

简称 WMS,WindowManagerService 管理窗口的创建、更新和删除、显示顺序等,是 WindowManager 这个管理接口的真正的实现类。它运行在 system_server 进程,作为服务端,客户端(应用程序)通过 IPC 调用和它进行交互;

  • Z-ordered的维护函数;
  • 输入法管理;
  • AddWindew/RemoveWindow;
  • Layout;
  • Token管理 AppToken;
  • 活动窗口管理(FocusWindow);
  • 活动应用管理(FocusApp);
  • 转场动画;
  • 系统消息收集线程;
  • 系统消息分发线程;

image.png

image.png

WMS、WindowManager、Window 三者之间的一个关系;Window 是 App 这边用来管理 View 的一个概念,它是一个抽象的概念,我们真正看到的是 View 而不是 Window,View 最终如果要显示出来,需要交给 WMS,WMS会把 View 交给 SurfaceFlinger,而 SurfaceFlinger 最终会交给 OpenGL 进行真正的绘制,绘制完成后显示到屏幕上;

image.png

Token

这里提到的 Token 主是指窗口令牌(WindowToken),是一种特殊的 Binder 令牌,wms 用它唯一标识系统中的一个窗口;

Window 的 type

窗口类型;

  • 应用窗口;
  • 子窗口;
  • 系统窗口;

mTokenMap

保存所有显示令牌「类型为WindowToken」一个窗口必须隶属于某一个显示令牌;

mAppTokens,保存了所有属于 Activity 的显示令牌( WindowToken 的子类 AppWindowToken),mAppTokens 列表是有序的,它与 AMS 中的 mHistory 列表的顺序保持一致,反映了系统中 Activity 的顺序;

mExitingTokens,保存了正在退出过程中的显示令牌等;

WindowToken 用来表示一组 Window;

mWindowMap

保存所有的状态信息「类型为WindowState」;

mPendingRemove,保存了那些退出动画播放完成并即将被移除的窗口;

mLosingFocus,保存了那些失去了输入焦点的窗口;

在 DisplayContent 中,也有一个 windows 列表,这个列表存储了显示在此 DisplayContent 中的窗口,并且它是有序的。窗口在这个列表中的位置决定了其最终显示时的Z序;

mSessions

保存了所有想向 WMS 寻求窗口管理服务的客户端。注意 session 具有进程唯一性;App 进程通过建立 Session代理对象和 Session 对象通信,进而和WMS建立连接;

WindowState

在 Client 端用 Window 来表示,这个 Window 到了 WMS 这边换了一种表示方式,就是 WindowState;类似 Activity 在 App 侧是 Activity,在 AMS 侧就是 ActivityRecord;

AppTransition

App 启动的时候窗口动画使用;

启动流程

WMS 的启动也是通过 SystemServer 的 run 调用的 startOtherService 方法中启动的;

private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
    // 省略部分代码...
    
    wm = WindowManagerService.main(context, inputManager, !mFirstBoot, mOnlyCore,
            new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager);
    ServiceManager.addService(Context.WINDOW_SERVICE, wm, /* allowIsolated= */ false,
        DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PROTO);
}

这里直接调用了 WindowManagerService 的静态 main 方法;

public static WindowManagerService main(final Context context, final InputManagerService im,
        final boolean showBootMsgs, final boolean onlyCore, WindowManagerPolicy policy,
        ActivityTaskManagerService atm, DisplayWindowSettingsProvider
        displayWindowSettingsProvider, Supplier<SurfaceControl.Transaction> transactionFactory,
        Supplier<Surface> surfaceFactory,
        Function<SurfaceSession, SurfaceControl.Builder> surfaceControlFactory) {
    DisplayThread.getHandler().runWithScissors(() ->
            sInstance = new WindowManagerService(context, im, showBootMsgs, onlyCore, policy,
                    atm, displayWindowSettingsProvider, transactionFactory, surfaceFactory,
                    surfaceControlFactory), 0);
    return sInstance;
}

这里要注意的是 WMS 的初始化在 DisplayThread 一个单独的线程中,并没有在 SystemServer 的主线程中;我们先来看下这个 DisplayhThread 是什么

public final class DisplayThread extends ServiceThread {}
public class ServiceThread extends HandlerThread {}

本质上就是一个 HandlerThread,HandlerThread 我们在前面的 Handler 中有涉及,这里主要是拿到 Handler 之后调用了其 runWithScissors 方法,我们来看下这个 runWithScissors 方法;

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

这里使用了一个 BlockingRunnable,也就是说这里进行了阻塞,在 handler.post 中,让这个被post的消息执行之后再继续往下执行;

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

也就是说要等 WindowManagerService 创建完成之后才能继续往下执行,才能 return sInstance;

我们接着来看下 new WindowManagerService 做了什么

private WindowManagerService(Context context, InputManagerService inputManager,
        boolean showBootMsgs, boolean onlyCore, WindowManagerPolicy policy,
        ActivityTaskManagerService atm, DisplayWindowSettingsProvider
        displayWindowSettingsProvider, Supplier<SurfaceControl.Transaction> transactionFactory,
        Supplier<Surface> surfaceFactory,
        Function<SurfaceSession, SurfaceControl.Builder> surfaceControlFactory) {
    
    // 创建动画管家
    mAnimator = new WindowAnimator(this);
    // 获取 ActivityManagerService
    mActivityManager = ActivityManager.getService();
}

初始化了一些需要与 WMS 通信的服务;WMS 创建完成之后,会和 AMS 进行一个绑定;

wm = WindowManagerService.main(context, inputManager, !mFirstBoot, mOnlyCore,
        new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager);
ServiceManager.addService(Context.WINDOW_SERVICE, wm, /* allowIsolated= */ false,
        DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PROTO);
// 进行绑定        
mActivityManagerService.setWindowManager(wm);

绑定之后,会调用 wms 的 ready 逻辑;

// 相关 ready
wm.onInitReady();
// 相关 ready
try {
    wm.displayReady();
} catch (Throwable e) {
    reportWtf("making display ready", e);
}

// 相关 ready
try {
    wm.systemReady();
} catch (Throwable e) {
    reportWtf("making Window Manager Service ready", e);
}

总结一下,主要是下面两点:

  1. WMS 的启动主要涉及3个线程:system_server、android.display、android.ui;其中WMS.H.handleMessage 运行在 android.display 线程中;
  2. WMS 中3个关键步骤:创建 WMS 对象,初始化显示信息,处理 systemready 通知

窗口类型


应用窗口(Application Window)

包括所有应用程序自己创建的窗口,以及在应用起来之前系统负责显示的窗口,层级范围是1~99;

  • FIRST_APPLICATION_WINDOW=1;第一个应用窗口
  • TYPE_BASE_APPLICATION=1;所有程序窗口的base窗口,其他应用程序窗口都显示在它上面
  • TYPE_APPLICATION=2;所有Activity的窗口,只能配合Activity在当前APP使用
  • TYPE_APPLICATION_STARTING=3;目标应用窗口未启动之前的那个窗口
  • LAST_APPLICATION_WINDOW=99;最后一个应用窗口

子窗口

应用自定义的对话框,或者输入法窗口,子窗口必须依附于某个应用窗口(设置相同的token),层级范围是1000~1999;

  • FIRST_SUB_WINDOW=1000;第一个子窗口
  • TYPE_APPLICATION_PANEL=FIRST_SUB_WINDOW;面板窗口,显示于宿主窗口的上层,只能配合Activity在当前APP使用
  • TYPE_APPLICATION_MEDIA=FIRST_SUB_WINDOW+1;媒体窗口(例如视频),显示于宿主窗口下层
  • TYPE_APPLICATION_SUB_PANEL=FIRST_SUB_WINDOW+2;应用程序窗口的子面板,只能配合Activity在当前APP使用(PopupWindow默认就是这个Type)
  • TYPE_APPLICATION_ATTACHED_DIALOG=FIRST_SUB_WINDOW+3;对话框窗口,只能配合Activity在当前APP使用
  • TYPE_APPLICATION_MEDIA_OVERLAY=FIRST_SUB_WINDOW+4;TYPE_APPLICATION_MEDIA的重影窗口,显示TYPE_APPLICATION_MEDIA和应用窗口之间
  • LAST_SUB_WINDOW=1999;最后一个子窗口

系统窗口

系统设计,不依附于任何应用窗口,比如:状态栏(Status Bar)、导航栏(Navigation Bar)、壁纸(Wallpaper)、来电显示窗口(Phone)、锁屏窗口(KeyGuard)、信息提示窗口(Toast)、音量调整窗口、鼠标光标等等,层级范围是2000~2999;

  • FIRST_SYSTEM_WINDOW=2000;系统窗口,非应用程序创建
  • TYPE_STATUS_BAR;状态栏,只能有一个状态栏,位于屏幕顶端,其他窗口都位于它下方
  • TYPE_SEARCH_BAR;搜索栏,只能有一个搜索栏,位于屏幕上方
  • TYPE_PHONE;电话窗口,它用于电话交互(特别是呼入),置于所有应用程序之上,状态栏之下,属于悬浮窗(并且给一个Activity的话按下HOME键会出现看不到桌面上的图标异常情况)
  • TYPE_SYSTEM_ALERT;系统警告提示窗口,出现在应用程序窗口之上,属于悬浮窗, 但是会被禁止
  • TYPE_TOAST;信息窗口,用于显示Toast, 不属于悬浮窗, 但有悬浮窗的功能
  • TYPE_SYSTEM_OVERLAY;系统顶层窗口,显示在其他一切内容之上,此窗口不能获得输入焦点,否则影响锁屏
  • LAST_SYSTEM_WINDOW=2999;最后一个系统窗口

好了,今天的 WMS 就先讲解到这里吧

下一章预告


window 的显示次序,尺寸计算;

欢迎三连


来都来了,点个关注点个赞吧,你的支持是我最大的动力~

  • 24
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Android系统的启动流程可以简单分为以下几个步骤:\[1\] 1. 前期准备工作:包括系统服务的初始化、创建ActivityThread线程等。 2. 启动AMS:创建ActivityManagerService对象,并注册系统服务。 3. 启动Zygote进程:Zygote是Android系统的孵化器进程,负责创建新的应用进程。 4. 创建应用进程:Zygote根据应用的包名创建新的应用进程,并加载应用的代码和资源。 5. 启动应用:应用进程启动后,会创建Application对象,并执行Application的生命周期方法。 6. 创建Activity:应用启动后,根据启动模式和Intent创建相应的Activity,并进行Activity的生命周期管理。 7. 显示界面:Activity创建完成后,会通过WindowManagerService进行窗口管理,将界面显示到屏幕上。 在AMS加载Application的流程中,主要包括以下几个步骤:\[3\] 1. 前期准备工作:包括创建ActivityManagerService对象、注册系统服务等。 2. 创建Application对象:根据应用的包名和类名,通过反射创建Application对象。 3. 调用Application的生命周期方法:调用Application的attachBaseContext()、onCreate()等生命周期方法,完成应用的初始化工作。 在启动过程中,需要处理的问题包括:\[1\] 1. 冷启动时间过长:可以通过优化应用的启动流程、减少启动时的耗时操作等方式来缩短冷启动时间。 2. 黑白屏问题:可以通过在启动过程中显示一个启动界面,或者使用启动图等方式来解决黑白屏问题。 3. 启动优化:可以通过优化应用的启动流程、减少启动时的资源加载等方式来提升应用的启动速度和执行效率。 WMS(Window Manager Service)对启动优化的意义在于,它负责管理应用的窗口显示,包括界面的布局、绘制等。通过优化WMS的处理流程,可以提升应用的界面显示效果和响应速度,从而提升用户体验。\[2\] #### 引用[.reference_title] - *1* *2* [Android面试题——高级开发面试题一](https://blog.csdn.net/Calvin_zhou/article/details/128123302)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [Android系统服务 AMS 启动流程](https://blog.csdn.net/bugyinyin/article/details/126520417)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值