FrameWork内核解析之WindowManagerService(一)中篇,震撼来袭

watchdog.init(context, mActivityManagerService);//2
traceEnd();
traceBeginAndSlog(“StartInputManagerService”);
inputManager = new InputManagerService(context);//3
traceEnd();
traceBeginAndSlog(“StartWindowManagerService”);
ConcurrentUtils.waitForFutureNoInterrupt(mSensorServiceStart, START_SENSOR_SERVICE);
mSensorServiceStart = null;
wm = WindowManagerService.main(context, inputManager,
mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
!mFirstBoot, mOnlyCore, new PhoneWindowManager());//4
ServiceManager.addService(Context.WINDOW_SERVICE, wm);//5
ServiceManager.addService(Context.INPUT_SERVICE, inputManager);//6
traceEnd();

try {
wm.displayReady();//7
} catch (Throwable e) {
reportWtf(“making display ready”, e);
}

try {
wm.systemReady();//8
} catch (Throwable e) {
reportWtf(“making Window Manager Service ready”, e);
}

}

startOtherServices方法用于启动其他服务,其他服务大概有70多个,上面的代码只列出了WMS以及和它相关的IMS的启动逻辑,剩余的其他服务的启动逻辑也都大同小异。

在注释1、2处分别得到Watchdog实例并对它进行初始化,Watchdog用来监控系统的一些关键服务的运行状况,后文会再次提到它。
在注释3处创建了IMS,并赋值给IMS类型的inputManager对象。
注释4处执行了WMS的main方法,其内部会创建WMS,需要注意的是main方法其中一个传入的参数就是注释1处创建的IMS,WMS是输入事件的中转站,其内部包含了IMS引用并不意外。结合上文,我们可以得知WMS的main方法是运行在SystemServer的run方法中,换句话说就是运行在"system_server"线程”中,后面会再次提到"system_server"线程。
注释5和注释6处分别将WMS和IMS注册到ServiceManager中,这样如果某个客户端想要使用WMS,就需要先去ServiceManager中查询信息,然后根据信息与WMS所在的进程建立通信通路,客户端就可以使用WMS了。
注释7处用来初始化显示信息。
注释8处则用来通知WMS,系统的初始化工作已经完成,其内部调用了WindowManagerPolicy的systemReady方法。

我们来查看注释4处WMS的main方法,如下所示。

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

public static WindowManagerService main(final Context context, final InputManagerService im,
final boolean haveInputMethods, final boolean showBootMsgs, final boolean onlyCore,
WindowManagerPolicy policy) {
DisplayThread.getHandler().runWithScissors(() ->//1
sInstance = new WindowManagerService(context, im, haveInputMethods, showBootMsgs,
onlyCore, policy), 0);
return sInstance;
}

在注释1处调用了DisplayThread的getHandler方法,用来得到DisplayThread的Handler实例。DisplayThread是一个单例的前台线程,这个线程用来处理需要低延时显示的相关操作,并只能由WindowManager、DisplayManager和InputManager实时执行快速操作。注释1处的runWithScissors方法中使用了Java8中的Lambda表达式,它等价于如下代码:

DisplayThread.getHandler().runWithScissors(new Runnable() {
@Override
public void run() {
sInstance = new WindowManagerService(context, im, haveInputMethods, showBootMsgs,
onlyCore, policy);//2
}
}, 0);

在注释2处创建了WMS的实例,这个过程运行在Runnable的run方法中,而Runnable则传入到了DisplayThread对应Handler的runWithScissors方法中,说明WMS的创建是运行在“android.display”线程中。需要注意的是,runWithScissors方法的第二个参数传入的是0,后面会提到。来查看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) {//1
r.run();
return true;
}
BlockingRunnable br = new BlockingRunnable®;
return br.postAndWait(this, timeout);
}

开头对传入的Runnable和timeout进行了判断,如果Runnable为null或者timeout小于0则抛出异常。注释1处根据每个线程只有一个Looper的原理来判断当前的线程("system_server"线程)是否是Handler所指向的线程("android.display"线程),如果是则直接执行Runnable的run方法,如果不是则调用BlockingRunnable的postAndWait方法,并将当前线程的Runnable作为参数传进去 ,BlockingRunnable是Handler的内部类,代码如下所示。

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

private static final class BlockingRunnable implements Runnable {
private final Runnable mTask;
private boolean mDone;
public BlockingRunnable(Runnable task) {
mTask = task;
}
@Override
public void run() {
try {
mTask.run();//1
} finally {
synchronized (this) {
mDone = true;
notifyAll();
}
}
}
public boolean postAndWait(Handler handler, long timeout) {
if (!handler.post(this)) {//2
return 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的任务队列中。前面runWithScissors方法的第二个参数为0,因此timeout等于0,这样如果mDone为false的话会一直调用注释3处的wait方法使得当前线程("system_server"线程)进入等待状态,那么等待的是哪个线程呢?我们往上看,注释1处,执行了传入的Runnable的run方法(运行在"android.display"线程),执行完毕后在finally代码块中将mDone设置为true,并调用notifyAll方法唤醒处于等待状态的线程,这样就不会继续调用注释3处的wait方法。
因此得出结论,"system_server"线程线程等待的就是"android.display"线程,一直到"android.display"线程执行完毕再执行"system_server"线程,这是因为"android.display"线程内部执行了WMS的创建,显然WMS的创建优先级更高些。
WMS的创建就讲到这,最后我们来查看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();//2
for (Display display : mDisplays) {
createDisplayContentLocked(display);//3
}

mActivityManager = ActivityManager.getService();//4

mAnimator = new WindowAnimator(this);//5
mAllowTheaterModeWakeFromLayout = context.getResources().getBoolean(
com.android.internal.R.bool.config_allowTheaterModeWakeFromWindowLayout);
LocalServices.addService(WindowManagerInternal.class, new LocalService());
initPolicy();//6
// Add ourself to the Watchdog monitors.
Watchdog.getInstance().addMonitor(this);//7

}

注释1处用来保存传进来的IMS,这样WMS就持有了IMS的引用。
注释2处通过DisplayManager的getDisplays方法得到Display数组(每个显示设备都有一个Display实例),接着遍历Display数组。
.getInstance().addMonitor(this);//7

}

注释1处用来保存传进来的IMS,这样WMS就持有了IMS的引用。
注释2处通过DisplayManager的getDisplays方法得到Display数组(每个显示设备都有一个Display实例),接着遍历Display数组。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值