用来记录学习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中启动WindowManagerServiceandroid14中,在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处理。
addwindow
 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状态值。