解释网站为什么这样做,php 快速网站开发,wordpress主题导出,手机网站建设电话咨询一 概述
今天#xff0c;我们介绍 WindowManagerService#xff08;后续简称 WMS#xff09;的启动流程#xff0c;WMS 是 Android 系统中#xff0c;负责窗口显示的的服务。在 Android 中它也起着承上启下的作用。
如下图#xff0c;就是《深入理解 Android》书籍中的…一 概述
今天我们介绍 WindowManagerService后续简称 WMS的启动流程WMS 是 Android 系统中负责窗口显示的的服务。在 Android 中它也起着承上启下的作用。
如下图就是《深入理解 Android》书籍中的一张图。 图中展示了WMS 在 Android 系统的地位它作为中间层连接了上层的 View 框架和下层的 SurfaceFingler。了解了 WMS 的工作机制我们就彻底打通了上层 VIew 到底层 Surface甚至到显示器如何显示的逻辑。
接下来我们依旧从 WMS 的启动开始来看 WMS 是如何启动的。
二 从 SystemServer 开始
2.1 startOtherServices
[frameworks/base/services/java/com/android/server/SystemServer.java]
private void startOtherServices(NonNull TimingsTraceAndSlog t) {WindowManagerService wm null;// 这里传入的 PhoneWindowManager 就是 WMS 中的 WindowManagerPolicywm 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);// 将 WMS 设置到 AMS 中mActivityManagerService.setWindowManager(wm);wm.onInitReady();...try {wm.displayReady();} catch (Throwable e) {reportWtf(making display ready, e);}...try {wm.systemReady();} catch (Throwable e) {reportWtf(making Window Manager Service ready, e);}...// 更新上下文中关于显示窗口相关的属性final Configuration config wm.computeNewConfiguration(DEFAULT_DISPLAY);DisplayMetrics metrics new DisplayMetrics();context.getDisplay().getMetrics(metrics);context.getResources().updateConfiguration(config, metrics);}和 AMS 不同的是WMS 的启动是在 SystemServer 的 startOtherServices 中启动过程依旧是我们之前提过的构造、注册只是少了 onStart 这个步骤。
并且在 WMS 启动之后还会陆续调用一些其他的函数
onInitReadydisplayReadysystemReadyupdateConfiguration
接下来我们会根据 WMS 启动过程中调用的函数以此查看它们具体的实现原理。
从 AMS 和 WMS 的启动我们可以看出来它们都是隶属于 SystemServer 进程的根据之前我们对应用和 AMS 的了解也经常看到它们交互的流程中有 WMS 的身影所以虽然说是应用和 AMSWMS 的通信实际上就是应用和 SystemServer 进程的通信。
2.2 main
[frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java]
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,new DisplayWindowSettingsProvider(), SurfaceControl.Transaction::new, Surface::new,SurfaceControl.Builder::new);
}public static WindowManagerService main(final Context context, final InputManagerService im,final boolean showBootMsgs, final boolean onlyCore, WindowManagerPolicy policy,ActivityTaskManagerService atm, DisplayWindowSettingsProviderdisplayWindowSettingsProvider, SupplierSurfaceControl.Transaction transactionFactory,SupplierSurface surfaceFactory,FunctionSurfaceSession, SurfaceControl.Builder surfaceControlFactory) {DisplayThread.getHandler().runWithScissors(() -sInstance new WindowManagerService(context, im, showBootMsgs, onlyCore, policy,atm, displayWindowSettingsProvider, transactionFactory, surfaceFactory,surfaceControlFactory), 0);return sInstance;
}在 WMS 的 main 函数中主要做了两件事
创建了一个 WMS 对象将这个 WMS 对象传递给了 DisplayThread
我们首先看这个 WMS 对象的构造函数
三 WindowManagerService
3.1 WMS 的构造函数
private WindowManagerService(Context context, InputManagerService inputManager,boolean showBootMsgs, boolean onlyCore, WindowManagerPolicy policy,ActivityTaskManagerService atm, DisplayWindowSettingsProviderdisplayWindowSettingsProvider, SupplierSurfaceControl.Transaction transactionFactory,SupplierSurface surfaceFactory,FunctionSurfaceSession, SurfaceControl.Builder surfaceControlFactory) {installLock(this, INDEX_WINDOW);// ActivityTaskManagerServicemGlobalLock atm.getGlobalLock();mAtmService atm;mContext context;mIsPc mContext.getPackageManager().hasSystemFeature(FEATURE_PC);mAllowBootMessages showBootMsgs;...// 输入法管理mInputManager inputManager; // Must be before createDisplayContentLocked.// 显示管理mDisplayManagerInternal LocalServices.getService(DisplayManagerInternal.class);// Surface 图像相关mSurfaceControlFactory surfaceControlFactory;mTransactionFactory transactionFactory;mSurfaceFactory surfaceFactory;mTransaction mTransactionFactory.get();mPolicy policy;// 窗口动画mAnimator new WindowAnimator(this);// 根窗口容器mRoot new RootWindowContainer(this);final ContentResolver resolver context.getContentResolver();mUseBLAST Settings.Global.getInt(resolver,Settings.Global.DEVELOPMENT_USE_BLAST_ADAPTER_VR, 1) 1;mSyncEngine new BLASTSyncEngine(this);mWindowPlacerLocked new WindowSurfacePlacer(this);mTaskSnapshotController new TaskSnapshotController(this);mWindowTracing WindowTracing.createDefaultAndStartLooper(this,Choreographer.getInstance());LocalServices.addService(WindowManagerPolicy.class, mPolicy);mDisplayManager (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);mKeyguardDisableHandler KeyguardDisableHandler.create(mContext, mPolicy, mH);mPowerManager (PowerManager)context.getSystemService(Context.POWER_SERVICE);mPowerManagerInternal LocalServices.getService(PowerManagerInternal.class);if (mPowerManagerInternal ! null) {mPowerManagerInternal.registerLowPowerModeObserver(new PowerManagerInternal.LowPowerModeListener() {Overridepublic int getServiceType() {return ServiceType.ANIMATION;}Overridepublic void onLowPowerModeChanged(PowerSaveState result) {synchronized (mGlobalLock) {final boolean enabled result.batterySaverEnabled;if (mAnimationsDisabled ! enabled !mAllowAnimationsInLowPowerMode) {mAnimationsDisabled enabled;dispatchNewAnimatorScaleLocked(null);}}}});mAnimationsDisabled mPowerManagerInternal.getLowPowerState(ServiceType.ANIMATION).batterySaverEnabled;}mScreenFrozenLock mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, SCREEN_FROZEN);mScreenFrozenLock.setReferenceCounted(false);mDisplayNotificationController new DisplayWindowListenerController(this);// AMS 相关mActivityManager ActivityManager.getService();mActivityTaskManager ActivityTaskManager.getService();mAmInternal LocalServices.getService(ActivityManagerInternal.class);mAtmInternal LocalServices.getService(ActivityTaskManagerInternal.class);...
}WMS 的构造函数的代码非常长其中有包含各种服务我们这里只关注和我们应用 Activity 相关的还有和显示相关的窗口容器 RootWindowContainer还有和刷新相关的 Surface。
3.2 runWithScissors
另外在 main 函数中还调用了一个 runWithScissors这个函数是 Handler 中定义的函数这里我们简单看一下。
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);
}runWithScissors 是 Handler 中的函数用一句话概括就是如果发送消息的线程与 Handler 处理的线程相同就直接调用。如果不同就阻塞调用。
3.3 onInitReady
public void onInitReady() {initPolicy();// Add ourself to the Watchdog monitors.Watchdog.getInstance().addMonitor(this);createWatermark();showEmulatorDisplayOverlayIfNeeded();
}3.4 initPolicy
private void initPolicy() {UiThread.getHandler().runWithScissors(new Runnable() {Overridepublic void run() {WindowManagerPolicyThread.set(Thread.currentThread(), Looper.myLooper());// mPolicy 其实就是 PhoneWindowManager【5.1】mPolicy.init(mContext, WindowManagerService.this, WindowManagerService.this);}}, 0);
}mPolicy 其实是 PhoneWindowManagerrunWithScissors 前面介绍过了如果是当前线程就直接运行如果不是当前线程就阻塞运行。
所以这里是在 android.ui 线程中运行 mPolicy 的初始化逻辑。
3.5 createWatermark
void createWatermark() {if (mWatermark ! null) {return;}File file new File(/system/etc/setup.conf);FileInputStream in null;DataInputStream ind null;try {in new FileInputStream(file);ind new DataInputStream(in);String line ind.readLine();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, mTransaction);mTransaction.apply();}}} ...
}createWatermark 创建系统水印只能显示文字。
3.6 displayReady
[frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java]
public void displayReady() {synchronized (mGlobalLock) {if (mMaxUiWidth 0) {mRoot.forAllDisplays(displayContent - displayContent.setMaxUiWidth(mMaxUiWidth));}applyForcedPropertiesForDefaultDisplay();mAnimator.ready();mDisplayReady true;// createWatermark重新配置所有显示器大小mRoot.forAllDisplays(DisplayContent::reconfigureDisplayLocked);// 是否触屏mIsTouchDevice mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN);mIsFakeTouchDevice mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FAKETOUCH);}try {// ATMSmActivityTaskManager.updateConfiguration(null);} catch (RemoteException e) {}
}displayReady 就是初始化显示器大小。
3.7 systemReady
[frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java]
public void systemReady() {mSystemReady true;// 调用 PhoneWindowManager 的 systemReadymPolicy.systemReady();// 调用 DisplayPolicy 的 systemReadymRoot.forAllDisplayPolicies(DisplayPolicy::systemReady);// 调用 TaskSnapshotController 的 systemReadymTaskSnapshotController.systemReady();mHasWideColorGamutSupport queryWideColorGamutSupport();mHasHdrSupport queryHdrSupport();// 加载系统设置UiThread.getHandler().post(mSettingsObserver::loadSettings);// VRIVrManager vrManager IVrManager.Stub.asInterface(ServiceManager.getService(Context.VR_SERVICE));if (vrManager ! null) {try {final boolean vrModeEnabled vrManager.getVrModeState();synchronized (mGlobalLock) {vrManager.registerListener(mVrStateCallbacks);if (vrModeEnabled) {mVrModeEnabled vrModeEnabled;mVrStateCallbacks.onVrStateChanged(vrModeEnabled);}}} catch (RemoteException e) {// Ignore, we cannot do anything if we failed to register VR mode listener}}
}3.8 computeNewConfiguration
public Configuration computeNewConfiguration(int displayId) {synchronized (mGlobalLock) {return computeNewConfigurationLocked(displayId);}
}3.9 computeNewConfigurationLocked
private Configuration computeNewConfigurationLocked(int displayId) {if (!mDisplayReady) {return null;}final Configuration config new Configuration();final DisplayContent displayContent mRoot.getDisplayContent(displayId);displayContent.computeScreenConfiguration(config);return config;
}displayId 表示的是显示设备的 id这两段代码就是通过 mRootRootWindowContainer获取显示指定设备的 DisplayContent。说人话就是通过显示器的 id获取显示器对应的实例类 DisplayContent。
四 DisplayThread
[frameworks/base/services/core/java/com/android/server/DisplayThread.java]
public final class DisplayThread extends ServiceThread {private static DisplayThread sInstance;private static Handler sHandler;private DisplayThread() {// DisplayThread 运行重要的东西但 AnimationThread 更重要。因此优先级设置为 THREAD_PRIORITY_DISPLAY 1// THREAD_PRIORITY_DISPLAY 的值为 -4super(android.display, Process.THREAD_PRIORITY_DISPLAY 1, false /*allowIo*/);}DisplayThread 就是 Android 中的 android.display 线程它的优先级为 THREAD_PRIORITY_DISPLAY 1THREAD_PRIORITY_DISPLAY 值为 -4所以 android.display 线程的优先级是 -3。
再回到 【2.2】中WMS 的 main 函数是通过 android.display 线程完成的并且在 android.display 线程中对 android.ui 线程进行了初始化。
五 UIThread
public final class UiThread extends ServiceThread {private static final long SLOW_DISPATCH_THRESHOLD_MS 100;private static final long SLOW_DELIVERY_THRESHOLD_MS 200;private static UiThread sInstance;private static Handler sHandler;private UiThread() {super(android.ui, Process.THREAD_PRIORITY_FOREGROUND, false /*allowIo*/);}Overridepublic void run() {// Make sure UiThread is in the fg stune boost groupProcess.setThreadGroup(Process.myTid(), Process.THREAD_GROUP_TOP_APP);super.run();}UiThread 和 DisplayThread 一样也是继承自 ServiceThread它的线程名是 android.ui优先级是 THREAD_PRIORITY_FOREGROUND值为-2,所以 android.ui 线程的优先级是 -2。
六 PhoneWindowManager
PhoneWindowManager 是 WindowManagerPolicy 的实现类它定义了手机窗口、处理输入事件以及与系统 UI 交互的策略和行为。
PhoneWindowManager 中的函数有很多这里我们列举一个其中的按键分发的函数 interceptKeyBeforeQueueing。
6.1 interceptKeyBeforeQueueing
[frameworks\base\services\core\java\com\android\server\policy\PhoneWindowManager.java]
public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {final int keyCode event.getKeyCode();final boolean down event.getAction() KeyEvent.ACTION_DOWN;boolean isWakeKey (policyFlags WindowManagerPolicy.FLAG_WAKE) ! 0|| event.isWakeKey();if (!mSystemBooted) {// 系统启动前只监听电源按键if (down (keyCode KeyEvent.KEYCODE_POWER|| keyCode KeyEvent.KEYCODE_TV_POWER)) {wakeUpFromPowerKey(event.getDownTime());} else if (down (isWakeKey || keyCode KeyEvent.KEYCODE_WAKEUP) isWakeKeyWhenScreenOff(keyCode)) {wakeUpFromWakeKey(event);}// 拦截掉电源键return 0;}// interceptKeyBeforeQueueing 主要就是对手机按键的事件拦截这里我们简单列举几个// 返回键音量键等等。switch (keyCode) {case KeyEvent.KEYCODE_BACK: {if (down) {mBackKeyHandled false;} else {if (!hasLongPressOnBackBehavior()) {mBackKeyHandled | backKeyPress();}// Dont pass back press to app if weve already handled it via long pressif (mBackKeyHandled) {result ~ACTION_PASS_TO_USER;}}break;}case KeyEvent.KEYCODE_VOLUME_DOWN:case KeyEvent.KEYCODE_VOLUME_UP:返回值是一个整型如果是 0 就表示被拦截一开始的电源按键我们就看到了在系统没有启动前电源按键只能用于系统启动但是系统启动后电源按键就可以用于其他的作用了例如语音助手。
PhoneWindowManager 这个类主要的作用有
按键的分发窗口的管理
这里我们就不扩展了后面遇到实际的场景再来说明。
七 总结
WMS 的启动流程比较简单主要就是启动了两个线程 android.display 和 android.ui
如果你还没有掌握Framework现在想要在最短的时间里吃透它可以参考一下《Android Framework核心知识点》里面内容包含了Init、Zygote、SystemServer、Binder、Handler、AMS、PMS、Launcher……等知识点记录。
《Framework 核心知识点汇总手册》:https://qr18.cn/AQpN4J
Handler 机制实现原理部分 1.宏观理论分析与Message源码分析 2.MessageQueue的源码分析 3.Looper的源码分析 4.handler的源码分析 5.总结 Binder 原理 1.学习Binder前必须要了解的知识点 2.ServiceManager中的Binder机制 3.系统服务的注册过程 4.ServiceManager的启动过程 5.系统服务的获取过程 6.Java Binder的初始化 7.Java Binder中系统服务的注册过程 Zygote
Android系统的启动过程及Zygote的启动过程应用进程的启动过程 AMS源码分析
Activity生命周期管理onActivityResult执行过程AMS中Activity栈管理详解 深入PMS源码
1.PMS的启动过程和执行流程 2.APK的安装和卸载源码分析 3.PMS中intent-filter的匹配架构 WMS 1.WMS的诞生 2.WMS的重要成员和Window的添加过程 3.Window的删除过程 《Android Framework学习手册》https://qr18.cn/AQpN4J
开机Init 进程开机启动 Zygote 进程开机启动 SystemServer 进程Binder 驱动AMS 的启动过程PMS 的启动过程Launcher 的启动过程Android 四大组件Android 系统服务 - Input 事件的分发过程Android 底层渲染 - 屏幕刷新机制源码分析Android 源码分析实战