简介

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”。

标记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,关于这两个方法这里不关注,在后续类似事件传递时应该会再触及。

Android10_原理机制系列_Window介绍及WMS的启动过程的更多相关文章

  1. Android10_原理机制系列_事件传递机制

    前言和概述 Android的输入设备,最常用的就是 触摸屏和按键 了.当然还有其他方式,比如游戏手柄,比如支持OTG设备,则可以链接鼠标.键盘等. 那么这些设备的操作 是如何传递到系统 并 控制界面的 ...

  2. Android10_原理机制系列_Activity窗口添加到WMS过程

    前言 首先看一个Android界面的布局层次结构,最直观的看一下: 我们能清晰看到,这个界面分成了3部分:顶部状态栏(statusbar).底部导航栏(navigationbar).应用界面. 题外话 ...

  3. Android10_原理机制系列_AMS(ATMS)之应用的第一次启动的过程

    概述 该篇基于Android 10的代码.在 AMS之AMS的启动---Android Framework(Android 10) 中已经介绍了,在Android 10中,activity的调度和管理 ...

  4. Android10_原理机制系列_AMS之AMS的启动

    概述 该篇基于AndroidQ,主要介绍系统启动中的 AMS(ActivityManagerService)的启动过程. AMS对四大组件(AndroidQ将activity移到了ActivityTa ...

  5. Android10_原理机制系列_PMS的启动及应用的安装过程

    概述 这里主要介绍 PackageManagerService(简称PMS)的启动 和 一个应用的安装过程.这里只是大致总结,供参考,不少地方同样需要进一步深入了解学习的. 该篇相关代码也是基于And ...

  6. Android10_原理机制系列_Binder机制

    前言 Binder 从java到c++到kernel,涉及的内容很多,很难在一篇文章中说清楚.这篇主要是自我记录,方便后续查询并拆分总结的. 因为涉及的的确非常多,不能面面俱到,所以可能一些地方感觉比 ...

  7. Android10_原理机制系列_Android消息机制(Handler)详述

    概述 在Android中的多进程.多线程中提过,只有主线程(UI线程)可以更新UI,其他线程不可以,所以一般耗时操作放到子线程.子线程可以通过Handler将相关信息通知到主线程. Android的消 ...

  8. 【原创】源码角度分析Android的消息机制系列(二)——ThreadLocal的工作过程

    ι 版权声明:本文为博主原创文章,未经博主允许不得转载. 在上一篇文章中,我们已经提到了ThreadLocal,它并非线程,而是在线程中存储数据用的.数据存储以后,只能在指定的线程中获取到数据,对于其 ...

  9. Storm系列(五)架构分析之Nimbus启动过程

    启动流程图   mk-assignments 功能:对当前集群中所有Topology进行新一轮的任务调度. 实现源码路径: \apache-storm-0.9.4\storm-core\src\clj ...

随机推荐

  1. spring mvc 基础知识

    spring mvc 在web.xml中的配置: 例子: <?xml version="1.0" encoding="UTF-8"?> <we ...

  2. linux云服务搭建七日杀服务器

    目录 准备工作 1.设置swap 2.安装screen 3.安装SteamCmd运行所需环境 4.创建一个用户 steamCMD与七日杀服务器端 1.下载并安装SteamCMD 2.登录steam账号 ...

  3. Python 单表查询数据

    import pymssql #引入pymssql模块# -----------------------------------------------------import pymssql #引入 ...

  4. 13.java设计模式之模板模式

    基本需求: 制作豆浆的流程 选材--->添加配料--->浸泡--->放到豆浆机打碎 通过添加不同的配料,可以制作出不同口味的豆浆 选材.浸泡和放到豆浆机打碎这几个步骤对于制作每种口味 ...

  5. 回收站都找不到的文件,EasyRecovery帮你找

    "有人相爱,有人看海,有人深夜两点还在找文件."没错,有人正是不才本人. 细数下来,这已经是本人第五六七八次丢文件了,每次丢的原因很奇怪:删错了.保存完找不到了.或者没有原因就那样 ...

  6. 思维导图iMindMap能够对逻辑思维有什么帮助

    思维就像人的身体一样,只有更多的锻炼才能更加灵活,思维导图可以很好的锻炼我们的思维,包括发散思维.图像思维.系统思维.条理性思维.主次思维和空间思维等.快给你的的思维报一个思维导图强化班吧. 为什么导 ...

  7. 系统兼容软件CrossOver和虚拟机软件,哪个好用?

    想要在Mac上运行Windows软件的方法有很多种,比较常见的有安装双系统以及虚拟机.但是安装双系统会导致一个很大的问题,就是占用了过多的硬盘空间,这样一来会导致可使用的空间减少. 目前来说,大家都不 ...

  8. Vim注释行的方法

    目录 一.Visual block 加注释 去注释 二.正则表达式 加注释 去注释 一.Visual block 加注释 1.首先按键盘上的ESC进入命令行模式 2.再按Ctrl+V进入VISUAL ...

  9. [C#.NET 拾遗补漏]13:动态构建LINQ查询表达式

    最近工作中遇到一个这样的需求:在某个列表查询功能中,可以选择某个数字列(如商品单价.当天销售额.当月销售额等),再选择 小于或等于 和 大于或等于 ,再填写一个待比较的数值,对数据进行查询过滤. 如果 ...

  10. QQ账号测试用例