Android O WMS -- addwindow

Android P WMS (1) -- Introduction to WMS

Android P WMS(2) -- wms initialization

Android O WMS(3) -- addwindow

Android P WMS(4) -- removewindow

Android P WMS(5) -- relayoutWindow

Android P WMS(6) -- windowanimator

Android P WMS(7) --wms Problem Types and Deug Skills

Android P WMS (8) -- Introduction to View SYstem

Android P WMS(9) --Surface

 

1.APP starts the add Window process

We add print stack log to WMS add Windows

//Add the following stack to WMS
@WindowManagerService.java
public int addWindow(Session session, IWindow client, int seq,
        LayoutParams attrs, int viewVisibility, int displayId, Rect outFrame,
        Rect outContentInsets, Rect outStableInsets, Rect outOutsets,
        DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel) {
             
        new Exception("William WindowManagerService stack").printStackTrace(); //add log  

Then click on launcher to start settings,log as follows. The first time addWindow is executed when splash screen is started, to SplashScreenStartingData.createStartingSurface, and the second time to start settings main interface com.android.settings/com.android.settings.Settings. This part can be referred to as:

TYPE_TOAST Summary of Android Suspension Window: Source Code Analysis

Android parsing Windows Manager (3) Windows adding process

        
//When settings are found to be activated, Splash Screen (also known as Welcome Page) is activated first.
1077  1148 W System.err: java.lang.Exception: William WindowManagerService stack
1077  1148 W System.err: 	at com.android.server.wm.WindowManagerService.addWindow(WindowManagerService.java:1157)
1077  1148 W System.err: 	at com.android.server.wm.Session.addToDisplay(Session.java:205)
1077  1148 W System.err: 	at android.view.ViewRootImpl.setView(ViewRootImpl.java:771)
1077  1148 W System.err: 	at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:356)
1077  1148 W System.err: 	at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:93)
1077  1148 W System.err: 	at com.android.server.policy.PhoneWindowManager.addSplashScreen(PhoneWindowManager.java:3214)
1077  1148 W System.err: 	at com.android.server.wm.SplashScreenStartingData.createStartingSurface(SplashScreenStartingData.java:56)
1077  1148 W System.err: 	at com.android.server.wm.AppWindowContainerController$1.run(AppWindowContainerController.java:170)
1077  1148 W System.err: 	at android.os.Handler.handleCallback(Handler.java:873)
1077  1148 W System.err: 	at android.os.Handler.dispatchMessage(Handler.java:99)
1077  1148 W System.err: 	at android.os.Looper.loop(Looper.java:193)
1077  1148 W System.err: 	at android.os.HandlerThread.run(HandlerThread.java:65)
1077  1148 W System.err: 	at com.android.server.ServiceThread.run(ServiceThread.java:44)
1077  1148 V WindowManager: Window Window{e56651a u0 Splash Screen com.android.settings} client=android.view.ViewRootImpl$W@f2667c5 token=AppWindowToken{4be29e3 token=Token{afc8e12 ActivityRecord{f88399d u0 com.android.settings/.Settings t7}}} (Token{afc8e12 ActivityRecord{f88399d u0 com.android.settings/.Settings t7}}) params={(0,0)(fillxfill) ty=APPLICATION_STARTING wanim=0x10302f8
1077  1148 V WindowManager: Attaching Window{e56651a u0 Splash Screen com.android.settings} token=AppWindowToken{4be29e3 token=Token{afc8e12 ActivityRecord{f88399d u0 com.android.settings/.Settings t7}}}
1077  1148 V WindowManager: addWindow: New client android.view.ViewRootImpl$W@f2667c5: window=Window{e56651a u0 Splash Screen com.android.settings} Callers=com.android.server.wm.Session.addToDisplay:205 android.view.ViewRootImpl.setView:771 android.view.WindowManagerGlobal.addView:356 android.view.WindowManagerImpl.addView:93 com.android.server.policy.PhoneWindowManager.addSplashScreen:3214 


//Then add settings windows (com. android. settings / com. android. settings. Settings)
1077  1236 W System.err: java.lang.Exception: William WindowManagerService stack
1077  1236 W System.err: 	at com.android.server.wm.WindowManagerService.addWindow(WindowManagerService.java:1157)
1077  1236 W System.err: 	at com.android.server.wm.Session.addToDisplay(Session.java:205)
1077  1236 W System.err: 	at android.view.IWindowSession$Stub.onTransact(IWindowSession.java:129)
1077  1236 W System.err: 	at com.android.server.wm.Session.onTransact(Session.java:164)
1077  1236 V WindowManager: Window Window{c70e488 u0 com.android.settings/com.android.settings.Settings} client=android.os.BinderProxy@d12a82b token=AppWindowToken{4be29e3 token=Token{afc8e12 ActivityRecord{f88399d u0 com.android.settings/.Settings t7}}} (Token{afc8e12 ActivityRecord{f88399d u0 com.android.settings/.Settings t7}}) params={(0,0)(fillxfill) sim={forwardNavigation} ty=BASE_APPLICATION wanim=0x10302f8
1077  1236 V WindowManager: Attaching Window{c70e488 u0 com.android.settings/com.android.settings.Settings} token=AppWindowToken{4be29e3 token=Token{afc8e12 ActivityRecord{f88399d u0 com.android.settings/.Settings t7}}}
1077  1236 V WindowManager: First window added to Session{d84ba9c 3168:1000}, creating SurfaceSession
1077  1236 V WindowManager: addWindow: New client android.os.BinderProxy@d12a82b: window=Window{c70e488 u0 com.android.settings/com.android.settings.Settings} Callers=com.android.server.wm.Session.addToDisplay:205 android.view.IWindowSession$Stub.onTransact:129 com.android.server.wm.Session.onTransact:164 android.os.Binder.execTransact:731 <bottom of call stack> 

Android parsing Windows Manager (3) Windows adding process

1.0 Overview

Windows Manager manages Windows. When it comes to management, it is inseparable from the operation of adding, updating and deleting Windows. Here we call them the operation of Windows. The operation of Windows is ultimately handled by WMS. The operation of windows is divided into two parts, one is the Windows Manager processing part, the other is the WMS processing part. We know that Windows can be divided into three categories: Application Window (Application Window), Sub Windwow (Sub Windwow) and System Window (System Window). The process of adding different types of windows will be different, but for the processing part of WMS, the process of adding is basically the same. WMS for these three types of windows. Large categories of windows are basically "non-discriminatory".

 

1.1 Addition of Activity

@frameworks/base/core/java/android/app/ActivityThread.java
 final void handleResumeActivity(IBinder token,
            boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {
       ...   
         r = performResumeActivity(token, clearHide, reason);//1           
       ...
          if (r.window == null && !a.mFinished && willBeVisible) {
                r.window = r.activity.getWindow();
                View decor = r.window.getDecorView();
                decor.setVisibility(View.INVISIBLE);
                ViewManager wm = a.getWindowManager();//2
                WindowManager.LayoutParams l = r.window.getAttributes();
                a.mDecor = decor;
                l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
                l.softInputMode |= forwardBit;
                if (r.mPreserveWindow) {
                    a.mWindowAdded = true;
                    r.mPreserveWindow = false;
                    ViewRootImpl impl = decor.getViewRootImpl();
                    if (impl != null) {
                        impl.notifyChildRebuilt();
                    }
                }
                if (a.mVisibleFromClient && !a.mWindowAdded) {
                    a.mWindowAdded = true;
                    wm.addView(decor, l);//3
                }
              
}

The performResumeActivity method at annotation 1 eventually calls the onResume method of Activity. Get the wm object of ViewManager type at Note 2.
wm's addView method is invoked in Note 3, and the implementation of addView method is in Windows Manager Impl. The process of adding system window above has been discussed since then.
The only thing to note is that the first parameter of addView is DecorView.

1.2 Adding process of system window

The process of adding three kinds of windows will be different. Take StatusBar as an example. StatusBar is an important part of System UI. It refers to the system status bar, which is used to display information such as time, electricity and signal. Let's look at the addStatusBar Window method of the implementation class PhoneStatusBar, which adds Windows to StatusBar, as shown below.

@/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
private void addStatusBarWindow() {
    makeStatusBarView();
    mStatusBarWindowManager = Dependency.get(StatusBarWindowManager.class);
    mRemoteInputController = new RemoteInputController(mHeadsUpManager);
    mStatusBarWindowManager.add(mStatusBarWindow, getStatusBarHeight());
}

@/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
public void add(View statusBarView, int barHeight) {

    // Now that the status bar window encompasses the sliding panel and its
    // translucent backdrop, the entire thing is made TRANSLUCENT and is
    // hardware-accelerated.
    mLp = new WindowManager.LayoutParams(
            ViewGroup.LayoutParams.MATCH_PARENT,
            barHeight,
            WindowManager.LayoutParams.TYPE_STATUS_BAR,
            WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                    | WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
                    | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
                    | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
                    | WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
             PixelFormat.TRANSLUCENT);
     mLp.token = new Binder();
     mLp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
     mLp.gravity = Gravity.TOP;
     mLp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
     mLp.setTitle("StatusBar");
     mLp.packageName = mContext.getPackageName();
     mStatusBarView = statusBarView;
     mBarHeight = barHeight;
     mWindowManager.addView(mStatusBarView, mLp);   //mWindowManager
     mLpChanged = new WindowManager.LayoutParams();
     mLpChanged.copyFrom(mLp);
 }
 
//Windows Manager inherits ViewManager, so it's still in ViewManager
@frameworks/base/core/java/android/view/WindowManager.java
/**
 * The interface that apps use to talk to the window manager.
 * </p><p>
@SystemService(Context.WINDOW_SERVICE)
public interface WindowManager extends ViewManager {
 

//Including addview update remove
@/frameworks/base/core/java/android/view/ViewManager.java
public interface ViewManager
    public void addView(View view, ViewGroup.LayoutParams params);
    public void updateViewLayout(View view, ViewGroup.LayoutParams params);
    public void removeView(View view);
}

 
//WindowManagerImpl Implementing addView concretely
public final class WindowManagerImpl implements WindowManager {
    private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
    @Override
    public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
        applyDefaultToken(params);
        mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
    }

@frameworks/base/core/java/android/view/WindowManagerGlobal.java
public void addView(View view, ViewGroup.LayoutParams params,
          Display display, Window parentWindow) {
    ...//Parameter checking
      final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;
      if (parentWindow != null) {
          parentWindow.adjustLayoutParamsForSubWindow(wparams);//1
      } else {
      ...
      }

      ViewRootImpl root;
      View panelParentView = null;
       ...
          root = new ViewRootImpl(view.getContext(), display);//2
          view.setLayoutParams(wparams);
          mViews.add(view);
          mRoots.add(root);//3
          mParams.add(wparams);
      }
      try {
          root.setView(view, wparams, panelParentView);//4
      } catch (RuntimeException e) {
         ...
      }
  }
  
/**
 * We have one child
 */
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
    synchronized (this) {
        try {
            mOrigWindowType = mWindowAttributes.type;
            mAttachInfo.mRecomputeGlobalAttributes = true;
            collectViewAttributes();
            res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
                    getHostVisibility(), mDisplay.getDisplayId(),
                    mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
                    mAttachInfo.mOutsets, mInputChannel);
        } 
}

@/frameworks/base/services/core/java/com/android/server/wm/Session.java
public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,
        int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets,
        Rect outOutsets, InputChannel outInputChannel) {
    return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId,  //Call to wms::addWindow
            outContentInsets, outStableInsets, outOutsets, outInputChannel);
}

 

2. Windows Addition Process (WMS Part)

frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java

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[] appOp = new int[1];
        int res = mPolicy.checkAddPermission(attrs, appOp);//1
        if (res != WindowManagerGlobal.ADD_OKAY) {
            return res;
        }
        ...
        synchronized(mWindowMap) {
            if (!mDisplayReady) {
                throw new IllegalStateException("Display has not been initialialized");
            }
            final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);//2
            if (displayContent == null) {
                Slog.w(TAG_WM, "Attempted to add window to a display that does not exist: "
                        + displayId + ".  Aborting.");
                return WindowManagerGlobal.ADD_INVALID_DISPLAY;
            }
            ...
            if (type >= FIRST_SUB_WINDOW && type <= LAST_SUB_WINDOW) {//3
                parentWindow = windowForClientLocked(null, attrs.token, false);//4
                if (parentWindow == null) {
                    Slog.w(TAG_WM, "Attempted to add window with token that is not a window: "
                          + attrs.token + ".  Aborting.");
                    return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN;
                }
                if (parentWindow.mAttrs.type >= FIRST_SUB_WINDOW
                        && parentWindow.mAttrs.type <= LAST_SUB_WINDOW) {
                    Slog.w(TAG_WM, "Attempted to add window with token that is a sub-window: "
                            + attrs.token + ".  Aborting.");
                    return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN;
                }
            }
           ...
}
...
}

WMS addWindows returns various states of addWindows, such as successful addition of Windows, invalid display, etc., which are defined in Windows Manager Global.  
Note 1 calls WMP's checkAddPermission method to check permissions according to the properties of Windows. Specifically, in Phone Windows Manager's checkAddPermission method, if there is no permission, the subsequent code logic will not be executed. Note 2 uses displayId to get which DisplayContent the Window wants to add to. If no DisplayContent is found, it returns to the state of Windows Manager Global. ADD_INVALID_DISPLAY, where DisplayContent is used to describe a screen. Note 3: Type represents the type of a Window. Its value is between FIRST_SUB_WINDOW and LAST_SUB_WINDOW (1000-1999). This value is defined in Windows Manager. This Window is a sub-Window. If you don't know the value range of Window type, please read Android to parse the properties of Windows Manager (2). This article. In Note 4, attrs.token is an IBinder type object, and the parent Window of the child Window is obtained from the mWindows Map based on attrs.token as the key value within the Windows ForClientLocked method. Then the parent Window is judged. If the value range of the parent Window is null or type is incorrect, the wrong state will be returned.
 

 

   ...
            AppWindowToken atoken = null;
            final boolean hasParent = parentWindow != null;
            WindowToken token = displayContent.getWindowToken(
                    hasParent ? parentWindow.mAttrs.token : attrs.token);//1
            final int rootType = hasParent ? parentWindow.mAttrs.type : type;//2
            boolean addToastWindowRequiresToken = false;

            if (token == null) {
                if (rootType >= FIRST_APPLICATION_WINDOW && rootType <= LAST_APPLICATION_WINDOW) {
                    Slog.w(TAG_WM, "Attempted to add application window with unknown token "
                          + attrs.token + ".  Aborting.");
                    return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
                }
                if (rootType == TYPE_INPUT_METHOD) {
                    Slog.w(TAG_WM, "Attempted to add input method window with unknown token "
                          + attrs.token + ".  Aborting.");
                    return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
                }
                if (rootType == TYPE_VOICE_INTERACTION) {
                    Slog.w(TAG_WM, "Attempted to add voice interaction window with unknown token "
                          + attrs.token + ".  Aborting.");
                    return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
                }
                if (rootType == TYPE_WALLPAPER) {
                    Slog.w(TAG_WM, "Attempted to add wallpaper window with unknown token "
                          + attrs.token + ".  Aborting.");
                    return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
                }
                ...
                if (type == TYPE_TOAST) {
                    // Apps targeting SDK above N MR1 cannot arbitrary add toast windows.
                    if (doesAddToastWindowRequireToken(attrs.packageName, callingUid,
                            parentWindow)) {
                        Slog.w(TAG_WM, "Attempted to add a toast window with unknown token "
                                + attrs.token + ".  Aborting.");
                        return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
                    }
                }
                final IBinder binder = attrs.token != null ? attrs.token : client.asBinder();
                token = new WindowToken(this, binder, type, false, displayContent,
                        session.mCanAddInternalSystemWindow);//3
            } else if (rootType >= FIRST_APPLICATION_WINDOW && rootType <= LAST_APPLICATION_WINDOW) {//4
                atoken = token.asAppWindowToken();//5
                if (atoken == null) {
                    Slog.w(TAG_WM, "Attempted to add window with non-application token "
                          + token + ".  Aborting.");
                    return WindowManagerGlobal.ADD_NOT_APP_TOKEN;
                } else if (atoken.removed) {
                    Slog.w(TAG_WM, "Attempted to add window with exiting application token "
                          + token + ".  Aborting.");
                    return WindowManagerGlobal.ADD_APP_EXITING;
                }
            } else if (rootType == TYPE_INPUT_METHOD) {
                if (token.windowType != TYPE_INPUT_METHOD) {
                    Slog.w(TAG_WM, "Attempted to add input method window with bad token "
                            + attrs.token + ".  Aborting.");
                      return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
                }
            }
      ...      

 

Summary of addWindow Method
The addWindow method is explained in three parts. The following four things are mainly done:
1. Check the window to be added. If the window does not satisfy some conditions, the following code logic will not be executed.  
2. Windows Token-related processing, for example, some window types need to provide Windows Token, if not, the following code logic will not be executed, and some window types need to be implicitly created by WMS Windows Token.  
3. The creation and processing of Windows State, which associates Windows Token with Windows State.  
4. Create and configure DisplayContent to complete the preparation before adding windows to the system.
 

 

Reference link:

TYPE_TOAST Summary of Android Suspension Window: Source Code Analysis

Android parses important members of Windows Manager Service (2) WMS and the process of adding Windows

Android Parsing Windows Manager Series

http://androidxref.com/8.0.0_r4/

Deep Understanding of Android: Volume III

Tags: Android Windows Java Session

Posted on Tue, 27 Aug 2019 20:06:24 -0700 by souravsasi123