Tecnología de desarrollo de Android: aprendizaje WMS de tecnología de vehículos

Introducción a la clase principal de administración de ventanas

DisplayContent, WindowToken y WindowState utilizados por la gestión de ventanas.

DisplayContent

Se utiliza para administrar todas las ventanas en una pantalla lógica y habrá varios DisplayContents para varias pantallas. Utilice displayId para distinguir.

Dos ventanas con DisplayContent diferente no tendrán ningún acoplamiento en el diseño, orden de visualización y procesamiento de animación. Entonces, en estos aspectos, DisplayContent es como una isla, y todas estas operaciones se pueden realizar de forma independiente dentro de él.

Declaración de la clase DisplayContent:

class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowContainer>{
    
        // Mapping from a token IBinder to a WindowToken object on this display.    private final HashMap<IBinder, WindowToken> mTokenMap = new HashMap();}   

El subcontenedor de DisplayContent es su clase interna DisplayChildWindowContainer
DisplayContent se usa internamente: el par clave-valor con IBinder como clave y WindowToken como valor se almacena en HashMap.
DisplayContent se inicializa cuando se agrega Window a WMS.

WMS

public int addWindow(Session session, ..){
    
        final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);    ..}

mRoot es un objeto de tipo RootWindowContainer y, por su nombre, se puede saber que es la raíz del contenedor de la ventana. Tenga en cuenta que en el sistema de ventanas, el nodo RootWindowContainer es el contenedor principal superior del contenedor.

class RootWindowContainer extends WindowContainer<DisplayContent> {
    
        DisplayContent getDisplayContentOrCreate(int displayId) {
    
            DisplayContent dc = getDisplayContent(displayId);        if (dc == null) {
    
                final Display display = mService.mDisplayManager.getDisplay(displayId);            if (display != null) {
    
                                  dc = createDisplayContent(display);                     }        }        return dc;    }   DisplayContent getDisplayContent(int displayId) {
    
          for (int i = mChildren.size() - 1; i >= 0; --i) {
    
              final DisplayContent current = mChildren.get(i);           if (current.getDisplayId() == displayId) {
    
                  return current;           }      }      return null;  }}

Hereda WindowContainer, donde DisplayContent es una declaración genérica, lo que indica que el tipo de su subcontenedor es DisplayContent También se puede saber por el método getDisplayContent que su lista mChildren es una colección de DisplayContent. Esto también muestra que DisplayContent también es un contenedor disfrazado.

Declaración de la clase WindowToken
:

class WindowToken extends WindowContainer<WindowState>

表明 WindowToken 也是子容器,其子容器是 WindowState,所以 WindowState 也是一个容器。

WindowToken 在窗口体系中有两个作用:

    应用组件标识:将属于同一个应用组件的窗口组织在一起,这里的应用组件可以是:ActivityInputMethodWallpaper 以及 Dream。WMS 在对窗口的管理过程中用 WindowToken 来指代一个应用组件。例如在进行窗口的 Z-Order 排序时,属于同一个 WindowToken 的窗口会被安排在一起。
    令牌作用:WindowToken 由应用组件或其管理者负责向 WMS 声明并持有,应用组件在需要更新窗口时,需要向 WMS 提供令牌表明自己的身份, 并且窗口的类型必须与所持有的 WindowToken 的类型一致。

但是系统窗口是个例外,并不需要提供 token,WMS 会隐式声明一个WindowToken。那是不是说谁都可以添加系统窗口了呢?非也,在 addWindow 开始处就会调用下面代码:

mPolicy.checkAddPermission()

Requiere que el cliente tenga el permiso SYSTEM_ALERT_WINDOW o INTERNAL_SYSTEM_WINDOW para crear una ventana de tipo de sistema. La relación entre Window y WindowToken es la siguiente:

inserte la descripción de la imagen aquíDeclaración de la clase WindowState
:

clase WindowState extiende WindowContainer

Muestra que WindowState también es un contenedor WindowContainer, pero su subcontenedor también es WindowState. Generalmente, cuando una ventana tiene una subventana SUB_WINDOW, WindowState tiene nodos subcontenedores. WindowState representa un atributo de estado de ventana en WMS y almacena toda la información de atributos de una ventana en su interior. Su relación con View y WindowToken es la siguiente:
inserte la descripción de la imagen aquí¿Cómo ver el comando de estado de la ventana del dispositivo actual?

adb shell dumpsys window windows    
Window #9 Window{
    
    884cb45 u0 com.android.messaging/com.android.messaging.ui.conversationlist.ConversationListActivity}:    mDisplayId=0 stackId=3 mSession=Session{
    
    f1b7b8e 4307:u0a10065} mClient=android.os.BinderProxy@a512fbc    mOwnerUid=10065 mShowToOwnerOnly=true package=com.android.messaging appop=NONE    mAttrs={
    
    (0,36)(828xwrap) gr=BOTTOM CENTER sim={
    
    adjust=pan forwardNavigation} ty=APPLICATION fmt=TRANSLUCENT wanim=0x7f130015      fl=DIM_BEHIND ALT_FOCUSABLE_IM HARDWARE_ACCELERATED      vsysui=LIGHT_STATUS_BAR LIGHT_NAVIGATION_BAR}    Requested w=828 h=290 mLayoutSeq=220    mBaseLayer=21000 mSubLayer=0    mToken=AppWindowToken{
    
    3f9efb8 token=Token{
    
    2b272cc ActivityRecord{
    
    55a41e u0 com.android.messaging/.ui.conversationlist.ConversationListActivity t8}}}    mAppToken=AppWindowToken{
    
    3f9efb8 token=Token{
    
    2b272cc ActivityRecord{
    
    55a41e u0 com.android.messaging/.ui.conversationlist.ConversationListActivity t8}}}...  

A continuación, el autor toma como ejemplo la operación de adición de ventanas para explicar la gestión de ventanas de WMS.

operación de adición de ventana

public int addWindow(Session session, IWindow client, int seq,        WindowManager.LayoutParams attrs, int viewVisibility, int displayId,        Rect outContentInsets, Rect outStableInsets, Rect outOutsets,        InputChannel outInputChannel) {
    
        ...    int res = mPolicy.checkAddPermission(attrs, appOp);//1    ...    synchronized(mWindowMap) {        final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);//2        if (type >= FIRST_SUB_WINDOW && type <= LAST_SUB_WINDOW) {            parentWindow = windowForClientLocked(null, attrs.token, false);//3        }        ...                    WindowToken token = displayContent.getWindowToken(                hasParent ? parentWindow.mAttrs.token : attrs.token);//4        if (token == null) {                                          final IBinder binder = attrs.token != null ? attrs.token : client.asBinder();            token = new WindowToken(this, binder, type, false, displayContent,                    session.mCanAddInternalSystemWindow);//5        }         ...        final WindowState win = new WindowState(this, session, client, token, parentWindow,                appOp[0], seq, attrs, viewVisibility, session.mUid,                session.mCanAddInternalSystemWindow);//6        ...        mPolicy.adjustWindowParamsLw(win.mAttrs);//7        ...        if  (openInputChannels) {            win.openInputChannel(outInputChannel);//8        }        ...        mWindowMap.put(client.asBinder(), win);//9        ...        win.mToken.addWindow(win);//10        ...        displayContent.assignWindowLayers(false /* setLayoutNeeded */);//11        //12        if (focusChanged) {            mInputMonitor.setInputFocusLw(mCurrentFocus, false /*updateInputWindows*/);        }        mInputMonitor.updateInputWindowsLw(false /*force*/);    }    ...    return res;}

Nota 1: Verifique la validez del token y otros permisos de la Ventana actual.
Nota 2: Esto ya se ha dicho en la introducción de DisplayContent. Utilice el subcontenedor de RootWindowContainer para obtener un DisplayContent. Si no existe en la colección de subcontenedores, obtenga uno y agréguelo a la colección secundaria. Nota 3 : si es una subventana como Diálogo
, Obtenga la ventana principal, si no, informe una excepción de que no se puede encontrar la ventana principal.
Nota 4: use attr.token para obtener el WindowToken correspondiente del par clave-valor mTokenMap de displayContent, y un grupo de Window se almacena en WindowToken.
Nota 5: si el WindowToken en 4 es nulo, cree un WindowToken, pase los objetos attr.token y displayContent pasados ​​desde la capa de la aplicación, y guarde internamente el WindowToken creado en displayContent Nota 6: Cree un WindowState y páselo en
All las propiedades relacionadas con Window, por lo que WindowState existe como una propiedad de Window en WMS y se agregará a WindowToken durante la construcción de WindowState.
Nota 7: ajuste el atributo attr de la ventana según mPolicy, la clase de implementación de mPolicy es PhoneManagerPolicy.
Nota 8: Ejecute openInputChannel de WindowState, que principalmente abre el canal con el sistema de entrada para recibir la solicitud de evento de entrada de IMS.
Nota 9: asocie el objeto Window de la capa de la aplicación cliente con WindowState, de modo que WMS pueda encontrar el objeto WindowState en WMS a través de Window.
Nota 10: win.mToken es el objeto WindowToken creado anteriormente, por lo que aquí se debe agregar WindowState a la colección de subcontenedores de WindowToken.
Nota 11: Asigne el nivel de la ventana, aquí el parámetro setLayoutNeeded es falso, lo que indica que no se requiere la operación de diseño.

Aquí hay un resumen del método addWindow, que crea principalmente un objeto WindowState correspondiente a Window uno por uno, e inserta WindowState en la colección de subcontenedores del contenedor principal WindowToken, y WindowToken se almacena en la colección de pares clave-valor de Mostrar contenido. Las tres relaciones se pueden resumir brevemente de la siguiente manera:
inserte la descripción de la imagen aquí

Supongo que te gusta

Origin blog.csdn.net/qq_24252589/article/details/131353002
Recomendado
Clasificación