Android 9.0系统源码_窗口管理(一)WindowManagerService的启动流程
创始人
2025-05-29 06:58:50
0

前言

WindowManagerService是Android系统中重要的服务,它是WindowManager的管理者,WindowManagerService无论对于应用开发还是Framework开发都是重要的知识点,究其原因是因为WindowManagerService有很多职责,每个职责都会涉及重要且复杂的系统,这使得WindowManagerService就像一个十字路口的交通灯一样,没有了这个交通灯,十字路口就无法正常通车,WindowManagerService的职责只要有以下几点。

1)窗口管理
WindowManagerService是窗口的管理者,它负责窗口的启动、添加和删除,另外窗口的大小和层级也是由WMS进行管理的。窗口管理的核心成员由DisplayContent、WindowToken和WindowState。
2)窗口动画
窗口间进行切换时,使用窗口动画可以显得更炫一些,窗口动画由WMS的动画子系统来负责,动画子系统的管理者为WindowAnimator。
3)输入系统的中转站
通过对窗口的触摸从而产生触摸事件,InputManagerService(IMS)会对触摸事件进行处理,它会寻找一个最合适的窗口来处理触摸反馈信息,WindowManagerService是窗口的管理者,它作为输入系统的中转站再合适不过。
4)Surface管理
窗口并不具备绘制的功能,因此每个窗口都需要有一块Surface来供自己绘制,为每个窗口分配Surface时由WMS来完成的。
WindowManagerService的职责
从上图可以看出WindowManagerService很复杂,与它关联的有窗口管理、窗口动画、输入系统和Surface,它们每一个都是重要且负责的系统,在具体讲述这些功能之前,我们需要先梳理一下WindowManagerService的启动流程,这样才能更好的理解这个服务。

一、SystemServer的启动WindowManagerService

1、系统启动后会启动JVM虚拟机,SystemServer 是虚拟机的第一个进程,由init 进程fork 产生。主要用来启动frameworks层中的服务。SystemServer进程里面有个main()方法,main 方法如下:

frameworks/base/service/java/com/android/server/SystemServer.java

public final class SystemServer {public static void main(String[] args) {new SystemServer().run();}
}

2、main 方法里启动了 run() 方法,而在 run 方法中调用了startOtherServices() 方法:

public final class SystemServer {private void run() {...代码省略...try {traceBeginAndSlog("StartServices");startBootstrapServices();//启动引导服务startCoreServices();//启动核心服务startOtherServices();//启动其他服务SystemServerInitThreadPool.shutdown();} catch (Throwable ex) {Slog.e("System", "******************************************");Slog.e("System", "************ Failure starting system services", ex);throw ex;} finally {traceEnd();}...代码省略...}
}

3、startOtherServices方法和WindowManagerService服务启动相关的代码如下所示。

public final class SystemServer {private ActivityManagerService mActivityManagerService;private boolean mOnlyCore;private boolean mFirstBoot;private void startOtherServices() {...代码省略...WindowManagerService wm = null;InputManagerService inputManager = null;...代码省略...boolean isWatch = context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH);...代码省略...traceBeginAndSlog("StartInputManagerService");inputManager = new InputManagerService(context);//创建InputManagerServicetraceEnd();traceBeginAndSlog("StartWindowManagerService");// WMS needs sensor service readyConcurrentUtils.waitForFutureNoInterrupt(mSensorServiceStart, START_SENSOR_SERVICE);mSensorServiceStart = null;//执行WMS的main方法,其内部会创建WMS对象实例wm = WindowManagerService.main(context, inputManager,mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,!mFirstBoot, mOnlyCore, new PhoneWindowManager());//将WMS注册到服务管理器中        ServiceManager.addService(Context.WINDOW_SERVICE, wm, /* allowIsolated= */ false,DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PROTO);//将IMS注册到服务管理器中        ServiceManager.addService(Context.INPUT_SERVICE, inputManager,/* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL);traceEnd();traceBeginAndSlog("SetWindowManagerService");mActivityManagerService.setWindowManager(wm);traceEnd();traceBeginAndSlog("WindowManagerServiceOnInitReady");wm.onInitReady();traceEnd();...代码省略...        try {wm.displayReady();//初始化屏幕显示信息} catch (Throwable e) {reportWtf("making display ready", e);}...代码省略...      if (!isWatch) {traceBeginAndSlog("StartStatusBarManagerService");try {//状态栏管理服务statusBar = new StatusBarManagerService(context, wm);ServiceManager.addService(Context.STATUS_BAR_SERVICE, statusBar);} catch (Throwable e) {reportWtf("starting StatusBarManagerService", e);}traceEnd();}...代码省略...       try {wm.systemReady();//通知WMS,系统的初始化工作已经完成} catch (Throwable e) {reportWtf("making Window Manager Service ready", e);}...代码省略...       }
}     

二、WindowManagerService的启动

1、WindowManagerService的main方法如下:

frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java

public class WindowManagerService extends IWindowManager.Stubimplements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {public static WindowManagerService main(final Context context, final InputManagerService im,final boolean showBootMsgs, final boolean onlyCore, WindowManagerPolicy policy,ActivityTaskManagerService atm) {//调用main方法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, Supplier transactionFactory,Supplier surfaceFactory,Function surfaceControlFactory) {DisplayThread.getHandler().runWithScissors(() ->sInstance = new WindowManagerService(context, im, showBootMsgs, onlyCore, policy,atm, displayWindowSettingsProvider, transactionFactory, surfaceFactory,surfaceControlFactory), 0);return sInstance;}}
}

DisplayThread是一个单例的前台线程,这个线程用来处理需要低延时显示的相关操作,并只能由WindowManager、DisplayManager和InputManager实时执行快速操作。正是在DisplayThread的run方法中创建了WMS的实例,这就意味着WMS的创建时运行在android.display线程中的。
2、来看下Handler的runWithScissors方法:

frameworks/base/core/java/android/os/Handler.java

    public final boolean runWithScissors(final 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);}
  • 对传入的Runnable的timeout进行判断,如果Runnable为null或者timeout小于0则抛出异常。
  • 根据每个线程只有一个Looper的原理来判断当前线程(system_server线程)是否是Handler所指向的线程(android.display线程),如果是则直接执行Runnable的run方法,否则调用BlockingRunnable的postAndWait方法,并将当前线程的Runnable作为参数传递进去。

3、BlockingRunnable是Handler的内部类。

 private static final class BlockingRunnable implements Runnable {private final Runnable mTask;private boolean mDone;public BlockingRunnable(Runnable task) {mTask = task;}@Overridepublic void run() {try {mTask.run();//注释1} finally {synchronized (this) {mDone = true;notifyAll();}}}public boolean postAndWait(Handler handler, long timeout) {if (!handler.post(this)) {//注释2return false;}synchronized (this) {if (timeout > 0) {final long expirationTime = SystemClock.uptimeMillis() + timeout;while (!mDone) {long delay = expirationTime - SystemClock.uptimeMillis();if (delay <= 0) {return false; // timeout}try {wait(delay);} catch (InterruptedException ex) {}}} else {while (!mDone) {try {wait();//注释3} catch (InterruptedException ex) {}}}}return true;}}
  • 在注释2处将当前的BlockingRunnable添加到Handler的任务队列中,上面第3步我们知道runWithScissors方法的第二个参数为0,因此timeout等于0,这样如果mDone为false的话会一直调用注释3处的wait方法使得当前线程(system_server线程)进入等待状态。
  • 在注释1处执行了传入的Runnable的run方法(运行在android.display线程中),执行完毕后finally代码块中将mDone设置为true,并调用noifyAll方法唤醒处于等待状态的线程,这样就不会继续调用注释3处的wait方法。

结合以上两点我们可以得出一个结论,system_server线程会一直等待android.display线程执行完毕才开始执行system_server线程,这是因为android.display线程内部执行了WMS的创建,而WMS的创建优先级要更高。

4、接下来我们来查看一下WMS的构造方法。

frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java

    private WindowManagerService(Context context, InputManagerService inputManager,boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore,WindowManagerPolicy policy) {...代码省略...mInputManager = inputManager; // 注释1...代码省略...mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);mDisplays = mDisplayManager.getDisplays(); // 注释2for (Display display : mDisplays) {createDisplayContentLocked(display); // 注释3}...代码省略...mActivityManager = ActivityManager.getService(); // 注释4...代码省略...mAmInternal = LocalServices.getService(ActivityManagerInternal.class);...代码省略...mAnimator = new WindowAnimator(this); // 注释5mAllowTheaterModeWakeFromLayout = context.getResources().getBoolean(
com.android.internal.R.bool.config_allowTheaterModeWakeFromWindowLayout);LocalServices.addService(WindowManagerInternal.class, new LocalService());initPolicy(); // 注释6Watchdog.getInstance().addMonitor(this); // 注释7...代码省略...}
  • 注释1处保存传递进来的IMS,这样WMS就持有了IMS的引用。
  • 注释2处通过DisplayManager的getDisplay方法得到Display数组(每个显示设备都有一个Display实例),接着遍历Display数组。
  • 注释3处的createDisplayContentLocked方法将Display封装成DisplayContent,DisplayContent用来描述一块屏幕。
  • 注释4处得到AMS实例,并赋值给mActivityManager,这样WMS就持有了AMS的引用。
  • 注释5处创建WindowAnimator,用于管理所有的窗口动画。
  • 注释6处初始化了窗口管理策略的接口类WindowManagerPolicy(WMP),它用来定义一个窗口策略所要遵循的通用规范。
  • 注释7处调用addMonitor方法将自身添加到watchdog中,Watchdog用来监控系统的一些关键服务的运行状况,这些被监控的服务都会实现Watchdog.Monitor接口。Watchdog每分钟都会对被监控的系统服务进行检查,如果被监控的系统服务出现了死锁,就会杀死Watchdog所在的进程,也就是SystemServer进程。

5、继续来看注释6处的initPolicy方法。

    private void initPolicy() {UiThread.getHandler().runWithScissors(new Runnable() {@Overridepublic void run() {WindowManagerPolicyThread.set(Thread.currentThread(), Looper.myLooper());mPolicy.init(mContext, WindowManagerService.this, WindowManagerService.this);//注释1}}, 0);}

initPolicy方法和此前讲的WMS的main方法的实现类似,在注释1处执行了WMP的init方法,WMP是一个接口,init方法具体在PhoneWindowManager(PWM)中实现。PWM的init方法运行在android.ui线程中,它的优先级要高于initPolicy方法所在的android.display线程,因此android.display线程要等PWM的init方法执行完毕后,处于等待状态的android.display线程才会被唤醒从而继续执行下面的代码。

三、WMS的创建过程的3个线程

上面WMS创建的过程中有提到3个线程,分别是system_server、android.display和android.ui,下图是关于这三个线程的三个步骤。
三个线程之间的关系

1)首先在system_server线程中执行了SystemServer的startOtherServices方法,在startOtherServices方法中会调用WMS的main方,main方法会创建WMS,创建的过程是在android.display线程中实现的,由于创建WMS的优先级更高,因此system_server线程要等WMS创建完成后,处于等待状态的system_server线程才会被唤醒从而继续执行下面的代码。

2)在WMS的构造方法中会调用WMS的initPolicy方法,在initPolicy方法中又会调用PWM的init方法,PWM的init方法在android.ui线程中运行,它的优先级要高于android.display线程,因此"android.display"线程要等PWM的init方法执行完毕后,处于等待状态的android.display线程才会被唤醒从而继续执行下面的代码。

3)PWM的init方法执行完毕后,android.display线程就完成了WMS的创建,等待的system_server线程被唤醒后继续执行WMS的main方法后的代码逻辑,比如在前面第二部分第2步的注释7的地方,WMS的displayReady方法用来初始化屏幕显示信息。

相关内容

热门资讯

今起停牌!北汽旗下零部件企业筹... 红星资本局6月3日消息,5月30日晚间,渤海汽车(600960.SH)公告称,公司拟筹划发行股份及支...
撤33家分支机构,大手笔分红、... 本报(chinatimes.net.cn)记者胡金华 上海报道端午节前的最后一个交易日,国泰海通发布...
恒指半日涨1.13% 恒指半日... 【恒指半日涨1.13%】截至午间收盘,香港恒生指数涨1.13%,恒生科技指数涨0.59%。老铺黄金、...
恒生指数早盘涨1.13%,恒生... 6月3日午盘,香港恒生指数上扬1.13%,报23420.36点;恒生科技指数攀升0.59%,报516...
于东来回应停工:胖东来郑州项目... 针对近期网络流传的关于“胖东来郑州项目停工”的消息,胖东来集团创始人于东来通过短视频社交平台回应称:...
「午盘」A股早盘低开高走,大金... A股三大股指6月3日集体低开。早盘两市低开高走,三大股指很快转涨。从盘面上看,大金融领涨,银行股再度...
【商界头条】雷军再发文回应被质... 商界头条丨6月3日都有哪些财经大事件?今日聚焦【雷军再发文回应被质疑:后来者总有机会】6月1日雷军发...
短剧变天:免费当道,投流平台“... 来源|Tech星球文|翟元元张扬是一位短剧导演,个体户,长期以来依靠接拍付费小程序短剧为生。但是最近...
信用债ETF天弘(159398... 近期,信用债ETF迎来纳入质押库利好,多只基准做市信用债ETF成交活跃,且有大量资金流入。其中,Wi...
白天当医生,晚上做游戏,80后... 一个独立游戏制作人的生存样本。文|《中国企业家》记者 李晓天编辑|张昊头图来源|AI生今年3月,整形...
赛诺菲斥资超90亿美元收购罕见... 2025.06.03本文字数:787,阅读时长大约1分钟作者 |第一财经 钱童心当地时间6月2日,法...
估值432亿的全球龙头,英伟达... 今年1月,英伟达CEO黄仁勋在CES展会上抛出一颗“深水炸弹”:“非常有用的量子计算机可能还需20年...
Robotaxi推出前夕,“木... 在特斯拉即将推出备受期待的Robotaxi服务之际,其最著名的支持者之一“木头姐”却悄然减持。公开数...
历史最差!美元刚刚跌出“新纪录... 美元已经创下有记录以来最糟糕的年初以来走势,而隐藏在特朗普最新税法中的"隐秘条款"可能将进一步加剧美...
保险公司债:保住“生存线”和“... 在“偿二代”二期深化、低利率与“资产荒”并存的背景下,偿付能力管理对保险公司而言,既是“生存线”也是...
科创综指ETF天弘(58986... 6月3日,A股三大指数全线翻红,科创综指截至发稿涨0.90%,相关ETF中,科创综指ETF天弘(58...
265亿天津富豪,熬过严峻考验... 记者丨杨松 编辑丨李惠琳回归一号位,两轮车大佬正恢复斗志。5月下旬,爱玛科技董事长张剑,在线出席业绩...
国家持续加力 解决中小企业拖欠... 攸关我国经济运行的基本面。作者丨华商韬略出品人毕亚军拖欠账款是近几年中小企业反映的突出问题,国家解决...
黄金概念持续走强,西部黄金涨停... 6月3日,黄金概念持续走强,西部黄金涨停,曼卡龙涨超10%,晓程科技、赤峰黄金、潮宏基等多股涨超5%...
新能源汽车行业周报(5月26日... 行情回顾1.新能源汽车相关板块一周行情梳理同花顺数据显示,上周(5月26日-5月30日,下同),新能...