Android10_原理机制系列_Window介绍及WMS的启动过程
简介
Window简介
Android中,Window是一个重要部分,用户看到的界面、触摸显示界面进行一系列操作都涉及到Window。但实际上,Window本身并不具备绘制功能。
该篇简单介绍下Window的一点内容,同时总结下WMS的启动过程。在下篇会逐步介绍一个Activity是如何创建出窗口 并 添加到WMS中的。
该篇基于Andorid10的代码。
窗口涉及到一下几个功能:
窗口管理-WMS
WMS管理窗口的创建、添加、删除、大小、层级等等。输入中转-IMS(InputManagerService)
触摸窗口产生触摸事件,IMS对触摸事件进行处理,最后寻找一个最合适窗口进行反馈处理。窗口动画 ---WindowAnimator
窗口间进行切换时,使用窗口动画可以实现更好的效果,窗口动画主要由WindowAnimator管理。可以在开发者模式菜单找到相应设置。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()这里几个地方记录下,个人觉得比较值得注意的:
initPolicy()中,mPolicy即PhoneWindowManager对象,从开始处startOtherServices()中可以看到。startOtherServices()创建了PhoneWindowManager,这里完成了PhoneWindowManager的init()操作。
initPolicy()中,是运行在UiThread,也是继承的ServiceThread。执行mPolicy.init()。
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的启动过程的更多相关文章
- Android10_原理机制系列_事件传递机制
前言和概述 Android的输入设备,最常用的就是 触摸屏和按键 了.当然还有其他方式,比如游戏手柄,比如支持OTG设备,则可以链接鼠标.键盘等. 那么这些设备的操作 是如何传递到系统 并 控制界面的 ...
- Android10_原理机制系列_Activity窗口添加到WMS过程
前言 首先看一个Android界面的布局层次结构,最直观的看一下: 我们能清晰看到,这个界面分成了3部分:顶部状态栏(statusbar).底部导航栏(navigationbar).应用界面. 题外话 ...
- Android10_原理机制系列_AMS(ATMS)之应用的第一次启动的过程
概述 该篇基于Android 10的代码.在 AMS之AMS的启动---Android Framework(Android 10) 中已经介绍了,在Android 10中,activity的调度和管理 ...
- Android10_原理机制系列_AMS之AMS的启动
概述 该篇基于AndroidQ,主要介绍系统启动中的 AMS(ActivityManagerService)的启动过程. AMS对四大组件(AndroidQ将activity移到了ActivityTa ...
- Android10_原理机制系列_PMS的启动及应用的安装过程
概述 这里主要介绍 PackageManagerService(简称PMS)的启动 和 一个应用的安装过程.这里只是大致总结,供参考,不少地方同样需要进一步深入了解学习的. 该篇相关代码也是基于And ...
- Android10_原理机制系列_Binder机制
前言 Binder 从java到c++到kernel,涉及的内容很多,很难在一篇文章中说清楚.这篇主要是自我记录,方便后续查询并拆分总结的. 因为涉及的的确非常多,不能面面俱到,所以可能一些地方感觉比 ...
- Android10_原理机制系列_Android消息机制(Handler)详述
概述 在Android中的多进程.多线程中提过,只有主线程(UI线程)可以更新UI,其他线程不可以,所以一般耗时操作放到子线程.子线程可以通过Handler将相关信息通知到主线程. Android的消 ...
- 【原创】源码角度分析Android的消息机制系列(二)——ThreadLocal的工作过程
ι 版权声明:本文为博主原创文章,未经博主允许不得转载. 在上一篇文章中,我们已经提到了ThreadLocal,它并非线程,而是在线程中存储数据用的.数据存储以后,只能在指定的线程中获取到数据,对于其 ...
- Storm系列(五)架构分析之Nimbus启动过程
启动流程图 mk-assignments 功能:对当前集群中所有Topology进行新一轮的任务调度. 实现源码路径: \apache-storm-0.9.4\storm-core\src\clj ...
随机推荐
- spring mvc 基础知识
spring mvc 在web.xml中的配置: 例子: <?xml version="1.0" encoding="UTF-8"?> <we ...
- linux云服务搭建七日杀服务器
目录 准备工作 1.设置swap 2.安装screen 3.安装SteamCmd运行所需环境 4.创建一个用户 steamCMD与七日杀服务器端 1.下载并安装SteamCMD 2.登录steam账号 ...
- Python 单表查询数据
import pymssql #引入pymssql模块# -----------------------------------------------------import pymssql #引入 ...
- 13.java设计模式之模板模式
基本需求: 制作豆浆的流程 选材--->添加配料--->浸泡--->放到豆浆机打碎 通过添加不同的配料,可以制作出不同口味的豆浆 选材.浸泡和放到豆浆机打碎这几个步骤对于制作每种口味 ...
- 回收站都找不到的文件,EasyRecovery帮你找
"有人相爱,有人看海,有人深夜两点还在找文件."没错,有人正是不才本人. 细数下来,这已经是本人第五六七八次丢文件了,每次丢的原因很奇怪:删错了.保存完找不到了.或者没有原因就那样 ...
- 思维导图iMindMap能够对逻辑思维有什么帮助
思维就像人的身体一样,只有更多的锻炼才能更加灵活,思维导图可以很好的锻炼我们的思维,包括发散思维.图像思维.系统思维.条理性思维.主次思维和空间思维等.快给你的的思维报一个思维导图强化班吧. 为什么导 ...
- 系统兼容软件CrossOver和虚拟机软件,哪个好用?
想要在Mac上运行Windows软件的方法有很多种,比较常见的有安装双系统以及虚拟机.但是安装双系统会导致一个很大的问题,就是占用了过多的硬盘空间,这样一来会导致可使用的空间减少. 目前来说,大家都不 ...
- Vim注释行的方法
目录 一.Visual block 加注释 去注释 二.正则表达式 加注释 去注释 一.Visual block 加注释 1.首先按键盘上的ESC进入命令行模式 2.再按Ctrl+V进入VISUAL ...
- [C#.NET 拾遗补漏]13:动态构建LINQ查询表达式
最近工作中遇到一个这样的需求:在某个列表查询功能中,可以选择某个数字列(如商品单价.当天销售额.当月销售额等),再选择 小于或等于 和 大于或等于 ,再填写一个待比较的数值,对数据进行查询过滤. 如果 ...
- QQ账号测试用例