用来记录学习wms,后续会一点一点更新。。。。。。
代码:android14
WMS是在SystemServer进程中启动的
在SystemServer中的main方法中,调用run方法。
private void run() {
// Initialize native services.初始化服务,加载android_servers so库
870 System.loadLibrary("android_servers");
// Create the system service manager.创建SystemServiceManager
895 mSystemServiceManager = new SystemServiceManager(mSystemContext);
942 startOtherServices(t);//android14在startOtherServices中启动WindowManagerService
android14中,在startOtherServices中启动WindowManagerService
1606 wm = WindowManagerService.main(context, inputManager, !mFirstBoot,
1607 new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager);
该代码执行了WMS的main方法,会在内部创建一个WMS。其中有一个参数inputManager也是在startOtherServices中创建的,如下。
1589 t.traceBegin("StartInputManagerService");
1590 inputManager = new InputManagerService(context);
总结,WMS的main方法在startOtherServices中,而startOtherServices在SystemServer的run方法中,运行在system_server线程中。
1608 ServiceManager.addService(Context.WINDOW_SERVICE, wm, /* allowIsolated= */ false,
1609 DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PROTO);
1610 ServiceManager.addService(Context.INPUT_SERVICE, inputManager,
1611 /* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL);
上述代码将WMS和IMS注册到ServerManager中。
回到上述的WindowManagerService main中。
/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
1137 public static WindowManagerService main(final Context context, final InputManagerService im,
1138 final boolean showBootMsgs, WindowManagerPolicy policy, ActivityTaskManagerService atm,
1139 DisplayWindowSettingsProvider displayWindowSettingsProvider,
1140 Supplier<SurfaceControl.Transaction> transactionFactory,
1141 Function<SurfaceSession, SurfaceControl.Builder> surfaceControlFactory) {
1142 final WindowManagerService[] wms = new WindowManagerService[1];
1143 DisplayThread.getHandler().runWithScissors(() ->
1144 wms[0] = new WindowManagerService(context, im, showBootMsgs, policy, atm,
1145 displayWindowSettingsProvider, transactionFactory,
1146 surfaceControlFactory), 0);
1147 return wms[0];
1148 }
DisplayThread.getHandler().runWithScissors调用DisplayThread的getHandler方法,获得DisplayThread的handler实例。
可以用来处理需要低延时显示的相关操作。
这张图可以清晰的了解到,不管是applicationWindow,还是SystemWindow都是由WindowManager和WMS处理。
public int addWindow(Session session, IWindow client, LayoutParams attrs, int viewVisibility,
1432 int displayId, int requestUserId, @InsetsType int requestedVisibleTypes,
1433 InputChannel outInputChannel, InsetsState outInsetsState,
1434 InsetsSourceControl.Array outActiveControls, Rect outAttachedFrame,
1435 float[] outSizeCompatScale) {
int res = mPolicy.checkAddPermission(attrs.type, isRoundedCornerOverlay, attrs.packageName,
1441 appOp);
上述通过checkAddpermission方法来检测权限,如果没有权限则不会执行后续代码。
1457 final DisplayContent displayContent = getDisplayContentOrCreate(displayId, attrs.token);
上述代码中有一个参数:displayId,该参数获得窗口添加到哪个DisplayContent上。
if (displayContent == null) {
1460 ProtoLog.w(WM_ERROR, "Attempted to add window to a display that does "
1461 + "not exist: %d. Aborting.", displayId);
1462 return WindowManagerGlobal.ADD_INVALID_DISPLAY;
1463 }
如果displatContent等于null,则会返回一个ADD_INVALID_DISPLAY无效的状态,类似的还有成功的状态,这些状态都在WindowManagerGlobal中被定义。
if (type >= FIRST_SUB_WINDOW && type <= LAST_SUB_WINDOW) {
1478 parentWindow = windowForClientLocked(null, attrs.token, false);
1479 if (parentWindow == null) {
1480 ProtoLog.w(WM_ERROR, "Attempted to add window with token that is not a window: "
1481 + "%s. Aborting.", attrs.token);
1482 return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN;
1483 }
上述的一个判断,type代码窗口类型,它介于FIRST_SUB_WINDOW和LAST_SUB_WINDOW之间,FIRST_SUB_WINDOW和LAST_SUB_WINDOW值定义在windowmanger中
通常Window有三种类型,以及它们的值范围分别是:
Application Window(应用窗口) 1-99
Sub Window(子窗口)1000-1999
System Window(系统窗口)2000-2999
所以上述可以看出上述窗口是一个子窗口。
1478 parentWindow = windowForClientLocked(null, attrs.token, false);
看一下windowforclientLocked方法
6033 final WindowState windowForClientLocked(Session session, IWindow client, boolean throwOnError) {
6034 return windowForClientLocked(session, client.asBinder(), throwOnError);
6035 }
6036
6037 final WindowState windowForClientLocked(Session session, IBinder client, boolean throwOnError) {
6038 WindowState win = mWindowMap.get(client);
6039 if (DEBUG) Slog.v(TAG_WM, "Looking up client " + client + ": " + win);
6040 if (win == null) {
6041 if (throwOnError) {
6042 throw new IllegalArgumentException(
6043 "Requested window " + client + " does not exist");
6044 }
6045 ProtoLog.w(WM_ERROR, "Failed looking up window session=%s callers=%s", session,
6046 Debug.getCallers(3));
6047 return null;
6048 }
6049 if (session != null && win.mSession != session) {
6050 if (throwOnError) {
6051 throw new IllegalArgumentException("Requested window " + client + " is in session "
6052 + win.mSession + ", not " + session);
6053 }
6054 ProtoLog.w(WM_ERROR, "Failed looking up window session=%s callers=%s", session,
6055 Debug.getCallers(3));
6056 return null;
6057 }
6058
6059 return win;
6060 }
根据attrs.token作为key值从mWindowMap中得到该子窗口的父窗口,如果win父类窗口等于null会返回错误。
WindowToken token = displayContent.getWindowToken(
1525 hasParent ? parentWindow.mAttrs.token : attrs.token);
通过displayContent的getWindowToken方法获得WindowToken
if (token == null) {
1535 if (!unprivilegedAppCanCreateTokenWith(parentWindow, callingUid, type,
1536 rootType, attrs.token, attrs.packageName)) {
1537 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1538 }
......
1585 } else if (rootType == TYPE_INPUT_METHOD) {
1586 if (token.windowType != TYPE_INPUT_METHOD) {
1587 ProtoLog.w(WM_ERROR, "Attempted to add input method window with bad token "
1588 + "%s. Aborting.", attrs.token);
1589 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1590 }
} else if (rootType == TYPE_VOICE_INTERACTION) {
1592 if (token.windowType != TYPE_VOICE_INTERACTION) {
1593 ProtoLog.w(WM_ERROR, "Attempted to add voice interaction window with bad token "
1594 + "%s. Aborting.", attrs.token);
1595 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1596 }
1597 } else if (rootType == TYPE_WALLPAPER) {
1598 if (token.windowType != TYPE_WALLPAPER) {
1599 ProtoLog.w(WM_ERROR, "Attempted to add wallpaper window with bad token "
1600 + "%s. Aborting.", attrs.token);
1601 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1602 }
1603 } else if (rootType == TYPE_ACCESSIBILITY_OVERLAY) {
1604 if (token.windowType != TYPE_ACCESSIBILITY_OVERLAY) {
1605 ProtoLog.w(WM_ERROR,
1606 "Attempted to add Accessibility overlay window with bad token "
1607 + "%s. Aborting.", attrs.token);
1608 return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
1609 }
如果token为空,则做些判断,如果rootType等于TYPE_INPUT_METHOD等时,会返回ADD_BAD_APP_TOKEN状态值。