• android display 杂谈(三)WMS


    用来记录学习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
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    android14中,在startOtherServices中启动WindowManagerService

    1606              wm = WindowManagerService.main(context, inputManager, !mFirstBoot,
    1607                      new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager);
    
    • 1
    • 2

    该代码执行了WMS的main方法,会在内部创建一个WMS。其中有一个参数inputManager也是在startOtherServices中创建的,如下。

    1589              t.traceBegin("StartInputManagerService");
    1590              inputManager = new InputManagerService(context);
    
    
    • 1
    • 2
    • 3

    总结,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);
    
    • 1
    • 2
    • 3
    • 4

    上述代码将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      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    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);
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    上述通过checkAddpermission方法来检测权限,如果没有权限则不会执行后续代码。

    1457              final DisplayContent displayContent = getDisplayContentOrCreate(displayId, attrs.token);
    
    • 1

    上述代码中有一个参数: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              }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    如果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                  }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    上述的一个判断,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);
    
    
    • 1
    • 2

    看一下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      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    根据attrs.token作为key值从mWindowMap中得到该子窗口的父窗口,如果win父类窗口等于null会返回错误。

     WindowToken token = displayContent.getWindowToken(
    1525                      hasParent ? parentWindow.mAttrs.token : attrs.token);
    
    • 1
    • 2

    通过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                  }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    如果token为空,则做些判断,如果rootType等于TYPE_INPUT_METHOD等时,会返回ADD_BAD_APP_TOKEN状态值。

  • 相关阅读:
    【批处理DOS-CMD命令-汇总和小结】-CMD窗口的设置与操作命令-关闭cmd窗口、退出cmd环境(exit、exit /b、goto :eof)
    GBase 8s是否带集群模块并实现负载均衡
    mac 安装nodemon报错和解决方法 npm i nodemon -g
    day49 ARM
    02-csa练习题
    如何把MapGIS的区文件转为ArcGIS的SHAPE面文件
    浅学Nginx学习笔记
    项目总结——深入浅出socket网络编程
    java毕业设计家教管理系统mybatis+源码+调试部署+系统+数据库+lw
    JavaScript中作用域问题讨论及示例代码探究
  • 原文地址:https://blog.csdn.net/u013574207/article/details/134124629