Android中,Window是一个重要部分,用户看到的界面、触摸显示界面进行一系列操做都涉及到Window。但实际上,Window自己并不具有绘制功能。
该篇简单介绍下Window的一点内容,同时总结下WMS的启动过程。在下篇会逐步介绍一个Activity是如何建立出窗口 并 添加到WMS中的。
该篇基于Andorid10的代码。html
窗口涉及到一下几个功能:java
窗口管理-WMS
WMS管理窗口的建立、添加、删除、大小、层级等等。android
输入中转-IMS(InputManagerService)
触摸窗口产生触摸事件,IMS对触摸事件进行处理,最后寻找一个最合适窗口进行反馈处理。app
窗口动画 ---WindowAnimator
窗口间进行切换时,使用窗口动画能够实现更好的效果,窗口动画主要由WindowAnimator管理。能够在开发者模式菜单找到相应设置。ide
Surface管理 ---SurfaceFlinger
窗口不具有有绘制的功能,所以每一个窗口都须要有一块Surface来供本身绘制。为每一个窗口分配Surface是由WMS来完成的。
Surface就像画布,而后经过Canvas或OpenGL绘制。
SurfaceFlinger的做用主要是merge Surface,它接受多个来源的Surface图形显示数据(全部Surface:全部Window的Surface,特殊状况 有些Surface跟Window无关,如StrictMode),而后将他们合并(根据特定顺序Z-order),而后发送到显示设备。如最多见的界面是3层,顶部的statusbar,底部的导航栏,应用界面。
oop
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");
动画
以前总结了 AMS的启动 、AMS之应用的第一次启动过程、PMS的启动及应用的安装过程。 这里WMS的启动相似,下面会简单介绍下。ui
WMS是在system server启动后的startOtherServices()中启动。下面截取了其中关于WMS相关的代码。this
//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)。
//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);
这个很简单,wm被设置的到AMS和ATMS中。
//ActivityManagerService.java public void setWindowManager(WindowManagerService wm) { synchronized (this) { mWindowManager = wm; mActivityTaskManager.setWindowManager(wm); } }
//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”。
//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更新。
//WindowManagerService.java public void systemReady() { mSystemReady = true; mPolicy.systemReady(); ... }
系统初始化完成,通知WMS系统准备好了。这里主要完成:mPolicy.systemReady()
。
在标记3 时,有在android.ui线程执行的mPolicy.init()
,这里有mPolicy.systemReady()
。 mPolicy是PhoneWindowManager,关于这两个方法这里不关注,在后续相似事件传递时应该会再触及。