1、WMS
- WMS主要功能
- 窗口管理:WMS负责整个系统窗口的启动、添加、删除工作,系统中每个程序的显示都由WMS管理
- 窗口动画管理:WMS负责窗口添加或切换时动画效果的执行
- 窗口输入管理:WMS负责对窗口的触摸事件进行反馈和处理
- Surface管理:每个Window都有对应的Surface负责窗口的显示,而WMS负责所有Surface的管理调度
- WMS属性介绍
public class WindowManagerService extends IWindowManager.Stub
implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
final WindowManagerPolicy mPolicy;
final ArraySet<Session> mSessions = new ArraySet<>();
final WindowHashMap mWindowMap = new WindowHashMap();
final ArrayList<AppWindowToken> mFinishedStarting = new ArrayList<>();
final H mH = new H();
final WindowAnimator mAnimator;
final InputManagerService mInputManager;
final IActivityManager mActivityManager;
}
- mPolicy:WindowManagerPolicy的实例,WindowManagerPolicy是窗口管理策略的接口类,它的具体实现类为PhoneWindowManager
- mSessions:ArraySet对象,保存元素类型为Session,主要用于应用程序与WMS间的进程通信,每个应用程序对应一个Session,WMS内部保存这些Session,用来记录所有像WMS提出窗口服务的客户端
- mWindowMap:WindowHashMap对象,它内部以IBinder为Key,WindowState为Value,所以mWindowMap中保存着WMS中所有窗口的集合,而WindowState中保存着每个窗口的所有信息;
- mFinishedStarting:ArrayList对象,内部保存着已经启动窗口的WindowToken,WindowToken为窗口令牌,当程序像WMS申请创建Window时需要出具Token,程序中的每个Activity对应一个AppWindowToken(WindowToken的子类),WindowToken会将统一Actiivty的窗口组合在一起进行管理;
- mAnimator:WindowAnimator的对象,用于窗口的动画管理
- mH:H的实例,负责将任务添加到主线程中
- mInputManager:InputManagerService对象负责输入系统的管理,对窗口的触摸事件反馈和处理
- mActivityManager:内部保存AMS的对象
2、创建过程
由Android进程的启动过程知道,程序会同过JNI调用ZygiteInit.main()进入Java层,在main()方法中完成启动工作,其中重要的一步就是调用startSystemServer()启动系统服务,WMS就是其中一个系统服务,startSystemServer()使用反射最终调用SystemServer.main()方法(本文源码参照Android P),
public static void main(String[] args) {
new SystemServer().run();
}
private void run() {
mSystemServiceManager = new SystemServiceManager(mSystemContext);
startBootstrapServices();
startCoreServices();
startOtherServices();
}
在main方法中直接调用SystemService的run(),在run中首先创建SystemServiceManager对象,然后利用SystemServiceManager分别启动引导服务、核心服务、其他服务,WMS的启动就在startOtherServices()过程中;
- startOtherServices()
inputManager = new InputManagerService(context);
wm = WindowManagerService.main(context, inputManager,
mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
!mFirstBoot, mOnlyCore, new PhoneWindowManager());
ServiceManager.addService(Context.WINDOW_SERVICE, wm, false,
DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PROTO);
ServiceManager.addService(Context.INPUT_SERVICE, inputManager,
false, DUMP_FLAG_PRIORITY_CRITICAL);
在startOtherServices()中首先创建InputManagerService对象,然后调用WindowManagerService.main()创建WMS对象,此时最后一个参数就是前面讲的窗口策略类PhoneWindowManager,最后调用ServiceManager.addService()将WMS和InputManagerService保存在ServiceManager中;
- WindowManagerService.main()
public class WindowManagerService extends IWindowManager.Stub{
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是IWindowManager接口的代理类,在main()方法中调用DisplayThread.getHandler().runWithScissors()方法执行WindowManagerService的创建;
DisplayThread.getHandler().runWithScissors()其实就是发送一个事件消息,DisplayThread继承ServiceThread,而ServiceThread继承与HandlerThread,熟悉HandlerThread的同学都知道它是Android内部封装好的工具类,DisplayThread.getHandler()就是利用HandlerThread内部创建的Looper而创建的Handler,所以本质上执行的是Handler.runWithScissors()
- Handler.runWithScissors()
public final boolean runWithScissors(final Runnable r, long timeout) {
if (Looper.myLooper() == mLooper) {
r.run();
return true;
}
BlockingRunnable br = new BlockingRunnable(r);
return br.postAndWait(this, timeout);
}
runWithScissors()中接收到事件runnable后,先判断当前线程是否为创建Looper的线程,如果是则直接在当前线程执行,否则创建BlockingRunnable封装事件并发送到创建线程的队列中,由上面的启动知道此时程序执行在systemserver线程,所以此处会创建BlockingRunnable对象
- BlockingRunnable
private static final class BlockingRunnable implements Runnable {
883 private final Runnable mTask;
884 private boolean mDone;
886 public BlockingRunnable(Runnable task) {
887 mTask = task;
888 }
889
890 @Override
891 public void run() {
892 try {
893 mTask.run();
894 } finally {
895 synchronized (this) {
896 mDone = true;
897 notifyAll();
898 }
899 }
900 }
901
902 public boolean postAndWait(Handler handler, long timeout) {
903 if (!handler.post(this)) {
904 return false;
905 }
906
907 synchronized (this) {
908 if (timeout > 0) {
909 final long expirationTime = SystemClock.uptimeMillis() + timeout;
910 while (!mDone) {
911 long delay = expirationTime - SystemClock.uptimeMillis();
912 if (delay <= 0) {
913 return false; // timeout
914 }
915 try {
916 wait(delay);
917 } catch (InterruptedException ex) {
918 }
919 }
920 } else {
921 while (!mDone) {
922 try {
923 wait();
924 } catch (InterruptedException ex) {
925 }
926 }
927 }
928 }
929 return true;
930 }
931 }
BlockingRunnable是Handler的内部类,是专门用来处理线程安全的类,在postAndWait中首先使用Handler发送事件到当前队列,然后调用wait()方法使当前线程进入等待,然后在run()中执行传入的事件,在事件执行结束后调用notifyAll()方法唤醒线程,结合这里的启动过程总结一下:
- 在WindowManagerService.main()中即在system_service线程中,使用DisplayThread初始化的Handler发送事件,执行WMS的创建
- 在DisplayThread初始化的Handler中,首先会调用wait()使system_service线程执行等待,然后发送post发送事件到当前队列,即执行display线程
- 在display线程执行创建后,调用notify唤醒system_service线程继续执行
- WindowManagerService
private WindowManagerService(Context context, InputManagerService inputManager,
boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore,
WindowManagerPolicy policy) {
mAnimator = new WindowAnimator(this);
mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
mActivityManager = ActivityManager.getService();
}
在搞清楚上面的线程和执行的顺序后,下面进入到WMS的创建过程中,在WindowManagerService的构造函数中完成了WindowAnimator、mDisplayManager、mActivityManager的初始化,到此WMS启动已经完成
3、添加过程
对与Window添加过程的前半部分见Android进阶知识树—— 理解WindowManager,本文只分析WMS执行的部分,上一文章中知道添加过程最终调用到WMS中的addWindow(),下面分步骤阅读源码;
- 对添加窗口的检查
public int addWindow(){
int res = mPolicy.checkAddPermission(attrs, appOp);//1
final DisplayContent displayContent = getDisplayContentOrCreate(displayId);//2
if (type >= FIRST_SUB_WINDOW && type <= LAST_SUB_WINDOW) {
parentWindow = windowForClientLocked(null, attrs.token, false);
if (parentWindow == null) {
return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN;
}
if (parentWindow.mAttrs.type >= FIRST_SUB_WINDOW
&& parentWindow.mAttrs.type <= LAST_SUB_WINDOW) {
return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN;
}
}
}
在addWindow()中具体执行如下:
- 首先调用传入的窗口策略对窗口进行权限检查,具体执行在PhoneWindowManager中,
- 根据displayId获取要添加到对应的DisplayContent
- 根据添加的Type确定添加窗口的类型
- 调用windowForClientLocked根据窗口令牌token查找窗口是否已添加过
- 创建WindowToken
WindowToken token = displayContent.getWindowToken(
1191 hasParent ? parentWindow.mAttrs.token : attrs.token);//1
final int rootType = hasParent ? parentWindow.mAttrs.type : type;
token = new WindowToken(this, binder, type, false, displayContent,
1247 session.mCanAddInternalSystemWindow, isRoundedCornerOverlay);//2
atoken = token.asAppWindowToken();
总结:
- 调用displayContent.getWindowToken()获取WindowToken,然后判断是否有父窗口和父窗口的Type类型
- 创建窗口令牌WindowToken
- 将WindowToken转换为程序窗口令牌AppWindowToken
- 窗口添加和数据保存
final WindowState win = new WindowState(this, session, client, token, parentWindow,appOp[0], seq, attrs, viewVisibility, session.mUid,
session.mCanAddInternalSystemWindow);// 1
mPolicy.adjustWindowParamsLw(win, win.mAttrs, hasStatusBarServicePermission);//2
res = mPolicy.prepareAddWindowLw(win, attrs);//3
mWindowMap.put(client.asBinder(), win);//4
win.mToken.addWindow(win);//5
addWindow()最后部分执行以下步骤:
- 创建WidowState保存Window的全部信息
- 调用mPolicy.adjustWindowParamsLw()根据窗口Type修改Window的LayoutParam
- 调用prepareAddWindowLw()执行Window的添加
- 以Binder为Key将WindowState对象保存在mWindowMap中
- 将WindowState保存在窗口的Token中
4、删除过程
关于Window的删除过程见Android进阶知识树—— 理解WindowManager,程序最终调用WMS的removeWindow(),在removeWindow()中首先获取到保存Window所有信息的WidowState对象,然后调用WindowState.removeIfPossible()方法,removeIfPossible中直接调用重载的方法,最终调用 removeImmediately();
void removeWindow(Session session, IWindow client) {
synchronized(mWindowMap) {
WindowState win = windowForClientLocked(session, client, false);
if (win == null) {
return;
}
win.removeIfPos();
}
}
- removeImmediately()
@Override
void removeImmediately() {
super.removeImmediately();
mPolicy.removeWindowLw(this);
1921 disposeInputChannel();
1923 mWinAnimator.destroyDeferredSurfaceLocked();
1924 mWinAnimator.destroySurfaceLocked();
1925 mSession.windowRemovedLocked();
1927 mClient.asBinder().unlinkToDeath(mDeathRecipient, 0);
1933 mService.postWindowRemoveCleanupLocked(this);
}
removeImmediately中主要做一些清理工作,移除当前Widow、通知当前窗口动画、移除mSession等;
到此这对WMS的介绍和窗口的添加就介绍完毕了,希望有所帮助,后面会继续整理相关内容!