《深入理解android》学习:WMS(一)
1.WMS综述
WMS是android中的一个重要的系统服务,用于窗口管理。从其内部实现来看,包含以下的一些功能
- 窗口的添加与删除
- 启动窗口
- 窗口动画
- 窗口大小
- 窗口层级
1.1 WMS的启动
WMS的启动是在SysteServer中,先来看下其启动代码
本文中的代码若未特别说明,都是来自android P源码。
/frameworks/base/services/java/com/android/server/SystemServer.java
wm = WindowManagerService.main(context, inputManager,
mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
!mFirstBoot, mOnlyCore, new PhoneWindowManager());
ServiceManager.addService(Context.WINDOW_SERVICE, wm, /* allowIsolated= */ false,
DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PROTO);
这里先通过WindowManagerService的main方法将服务启动起来,再注册到ServiceManager当中。
我们再来看下WindowManagerService的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(() ->
sInstance = new WindowManagerService(context, im, haveInputMethods, showBootMsgs,
onlyCore, policy), 0);
return sInstance;
}
这里创建并返回了一个WindowManagerService的实例。
1.2 WMS,AMS和Activity之间的联系
书中从IPC通信和内部组织方式这两个角度来描述了这三者之间的关系。
1.2.1 IPC通信方式
Activity运行在应用程序中,而AMS和WMS通过上面的描述可以知道是在SystemServer中启动的,所以这两个驻留在同一个进程当中。应用程序中获取AMS服务和WMS服务实际也都是通过Binder来实现。
下图描述了这三者之间的关系。(图来自书中)
1.2.2 内部组织方式
新的Activity在启动后都需要在AMS中进行注册,AMS会生成一个对应的ActivityRecord来记录对应的信息。同时由于Activity是进行UI显示的,因此在WMS中进行记录,WindowState保存了有关信息。下图展示了有关关系,图同样来自书中。
1.3 窗口属性
下面绘制了窗口属性这一小节的思维导图,大多是概念性的东西,不进行赘述。
1.4 窗口的添加过程
前面介绍过窗口分为系统窗口和应用程序的窗口,下面分别介绍这两种窗口的添加过程。
1.4.1 系统窗口添加
这里以StatusBar添加过程为案例进行描述。
/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
private void addStatusBarWindow() {
makeStatusBarView();
mStatusBarWindowManager = Dependency.get(StatusBarWindowManager.class);
mRemoteInputManager.setUpWithPresenter(this, mEntryManager, this,
new RemoteInputController.Delegate() {
public void setRemoteInputActive(NotificationData.Entry entry,
boolean remoteInputActive) {
mHeadsUpManager.setRemoteInputActive(entry, remoteInputActive);
entry.row.notifyHeightChanged(true /* needsAnimation */);
updateFooter();
}
public void lockScrollTo(NotificationData.Entry entry) {
mStackScroller.lockScrollTo(entry.row);
}
public void requestDisallowLongPressAndDismiss() {
mStackScroller.requestDisallowLongPress();
mStackScroller.requestDisallowDismiss();
}
});
mRemoteInputManager.getController().addCallback(mStatusBarWindowManager);
mStatusBarWindowManager.add(mStatusBarWindow, getStatusBarHeight());
}
这里先调用了makeStatusBarView方法来创建状态栏的控件树,该方法可以参考这篇文章中的讲解系统服务-System UI,然后通过StatusBarWindowManager来add到WMS中。
frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
public void add(View statusBarView, int barHeight) {
// Now that the status bar window encompasses the sliding panel and its
// translucent backdrop, the entire thing is made TRANSLUCENT and is
// hardware-accelerated.
mLp = new WindowManager.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, //宽度填满
barHeight,
WindowManager.LayoutParams.TYPE_STATUS_BAR,