Android 9.0 system source code_window management (2) WindowManager's window management process

foreword

In the previous article, we analyzed the startup process of the window manager WindowManagerService in detail, and had a preliminary understanding of WindowManagerService. On this basis, I planned to further analyze how WindowManagerService manages various windows in the system. However, due to the architecture design of the Android system, before analyzing WindowManagerService, we must first have a basic understanding of WindowManager in order to be better. Understand the window management process of WindowManagerService.
System operation on Window
As shown in the figure above, the system mainly operates and manages windows through WindowManager and WindowManagerService. WindowManager is higher-level, and WindowManagerService is lower-level. WindowManager’s various processing of windows is finally realized by calling WindowMnagerService. For different types of windows, the process of adding WindowManager may be different, but the part handled by WindowManagerService is basically the same.

1. Window type

Before analyzing WindowManager's management of windows, we need to first understand the window types in the Android system, because the addition process of WindowManager will be different for different window types.

There are many types of Window, such as application window, system error window, input method window, PopupWindow, Toast, Dialog, etc. Generally speaking, Window is divided into three types, namely Application Window (application window), Sub Window (sub window), and System Window (system window). Each large type is divided into many small types, which are all defined in In the static internal class LayoutParams of WindowManager, the following briefly introduces the three types of Window.

1. Application window
Activity is a typical application window. The types of application windows are as follows:

frameworks/base/core/java/android/view/WindowManager.java

public interface WindowManager extends ViewManager {
    
    
    public static class LayoutParams extends ViewGroup.LayoutParams implements Parcelable {
    
    
        public static final int FIRST_APPLICATION_WINDOW = 1;
        public static final int TYPE_BASE_APPLICATION = 1;//应用程序窗口的基础值,其他窗口的值都要大于这个值
        public static final int TYPE_APPLICATION = 2;//普通的应用程序窗口类型
        public static final int TYPE_APPLICATION_STARTING = 3;//应用程序启动窗口类型,用户系统在应用程序窗口启动前显示的窗口
        public static final int TYPE_DRAWN_APPLICATION = 4;
        public static final int LAST_APPLICATION_WINDOW = 99;//应用程序窗口的结束值
}
}

The Type value of the application window ranges from 1 to 99.

2. Sub-window
A sub-window cannot exist alone, it needs to be attached to other windows. PopupWindow is a sub-window. The type definition of the child window is as follows:

frameworks/base/core/java/android/view/WindowManager.java

public interface WindowManager extends ViewManager {
    
    
    public static class LayoutParams extends ViewGroup.LayoutParams implements Parcelable {
    
    
       public static final int FIRST_SUB_WINDOW = 1000;//子窗口类型初始值
        public static final int TYPE_APPLICATION_PANEL = FIRST_SUB_WINDOW;
        public static final int TYPE_APPLICATION_MEDIA = FIRST_SUB_WINDOW + 1;
        public static final int TYPE_APPLICATION_SUB_PANEL = FIRST_SUB_WINDOW + 2;
        public static final int TYPE_APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW + 3;
        public static final int TYPE_APPLICATION_MEDIA_OVERLAY  = FIRST_SUB_WINDOW + 4;
        public static final int TYPE_APPLICATION_ABOVE_SUB_PANEL = FIRST_SUB_WINDOW + 5;
        public static final int LAST_SUB_WINDOW = 1999;//子窗口类型结束值
}
}

The range of the Type value of the sub-window is 1000~1999.
3. The system window
Toast, the input method window, the system volume bar window, and the system error window all belong to the system window. The type definition of the system window is as follows:

public interface WindowManager extends ViewManager {
    
    
    public static class LayoutParams extends ViewGroup.LayoutParams implements Parcelable {
    
    
        public static final int FIRST_SYSTEM_WINDOW     = 2000; //系统窗口类型初始值
        public static final int TYPE_STATUS_BAR         = FIRST_SYSTEM_WINDOW; //系统状态栏窗口
        public static final int TYPE_SEARCH_BAR         = FIRST_SYSTEM_WINDOW+1; //搜索条窗口
        @Deprecated //use TYPE_APPLICATION_OVERLAY instead
        public static final int TYPE_PHONE              = FIRST_SYSTEM_WINDOW+2; //通话窗口
        @Deprecated //use TYPE_APPLICATION_OVERLAY instead
        public static final int TYPE_SYSTEM_ALERT       = FIRST_SYSTEM_WINDOW+3; //系统Alert窗口
        public static final int TYPE_KEYGUARD           = FIRST_SYSTEM_WINDOW+4; //锁屏窗口
        @Deprecated//use TYPE_APPLICATION_OVERLAY instead
        public static final int TYPE_TOAST              = FIRST_SYSTEM_WINDOW+5; //Toast窗口
        @Deprecated //use TYPE_APPLICATION_OVERLAY instead
        public static final int TYPE_SYSTEM_OVERLAY     = FIRST_SYSTEM_WINDOW+6;
        @Deprecated //use TYPE_APPLICATION_OVERLAY instead
        public static final int TYPE_PRIORITY_PHONE     = FIRST_SYSTEM_WINDOW+7;
        public static final int TYPE_SYSTEM_DIALOG      = FIRST_SYSTEM_WINDOW+8;//系统弹窗
        public static final int TYPE_KEYGUARD_DIALOG    = FIRST_SYSTEM_WINDOW+9;//锁屏弹窗
        @Deprecated//use TYPE_APPLICATION_OVERLAY instead
        public static final int TYPE_SYSTEM_ERROR       = FIRST_SYSTEM_WINDOW+10;
        public static final int TYPE_INPUT_METHOD       = FIRST_SYSTEM_WINDOW+11;
        public static final int TYPE_INPUT_METHOD_DIALOG= FIRST_SYSTEM_WINDOW+12;
        public static final int TYPE_WALLPAPER          = FIRST_SYSTEM_WINDOW+13;
        public static final int TYPE_STATUS_BAR_PANEL   = FIRST_SYSTEM_WINDOW+14;
        public static final int TYPE_SECURE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+15;
        public static final int TYPE_DRAG               = FIRST_SYSTEM_WINDOW+16;
        public static final int TYPE_STATUS_BAR_SUB_PANEL = FIRST_SYSTEM_WINDOW+17;
        public static final int TYPE_POINTER = FIRST_SYSTEM_WINDOW+18;
   public static final int TYPE_NAVIGATION_BAR = FIRST_SYSTEM_WINDOW+19;//系统导航栏
        public static final int TYPE_VOLUME_OVERLAY = FIRST_SYSTEM_WINDOW+20;//音量
        public static final int TYPE_BOOT_PROGRESS = FIRST_SYSTEM_WINDOW+21;
        public static final int TYPE_INPUT_CONSUMER = FIRST_SYSTEM_WINDOW+22;
        public static final int TYPE_DREAM = FIRST_SYSTEM_WINDOW+23;
        public static final int TYPE_NAVIGATION_BAR_PANEL = FIRST_SYSTEM_WINDOW+24;
        public static final int TYPE_DISPLAY_OVERLAY = FIRST_SYSTEM_WINDOW+26;
        public static final int TYPE_MAGNIFICATION_OVERLAY = FIRST_SYSTEM_WINDOW+27;
        public static final int TYPE_PRIVATE_PRESENTATION = FIRST_SYSTEM_WINDOW+30;
        public static final int TYPE_VOICE_INTERACTION = FIRST_SYSTEM_WINDOW+31;
        public static final int TYPE_ACCESSIBILITY_OVERLAY = FIRST_SYSTEM_WINDOW+32;
        public static final int TYPE_VOICE_INTERACTION_STARTING = FIRST_SYSTEM_WINDOW+33;
        public static final int TYPE_DOCK_DIVIDER = FIRST_SYSTEM_WINDOW+34;
        public static final int TYPE_QS_DIALOG = FIRST_SYSTEM_WINDOW+35;
        public static final int TYPE_PRESENTATION = FIRST_SYSTEM_WINDOW + 37;
        public static final int TYPE_APPLICATION_OVERLAY = FIRST_SYSTEM_WINDOW + 38;//很多废弃的系统弹窗类型都可以使用这个进行替换
        public static final int LAST_SYSTEM_WINDOW      = 2999; //系统窗口类型的结束值
}
}

There are nearly 40 type values ​​of the system window, and the type value range of the system window is 2000~2999.

4. Display order of windows
When a process applies for a window from the system, the system will determine the display order for the windows. In order to facilitate the management of the window display order, the screen of the mobile phone can be represented virtually by X, Y, and Z axes. The Z axis is perpendicular to the screen and points from the inside to the outside of the screen. In this way, the display order of the windows is actually the order of the windows on the Z axis. Order, this order is called Z-Oder. The Type value is the basis for Z-Order sorting. We know that the Type value range of the application window is 1-99, the sub-window is 1000-1999, and the system window is 2000-2999. In general, the larger the Type value, the Z~ The higher the Order is sorted, the closer the window is to the user.
However, the logic of the window display order does not only depend on the type of the window, there are many cases; the most common case, when the Type of multiple windows is Type_APPLICATION, then the system needs to combine the specific situation to calculate the final Z-Oder .

2. The process of adding the system window StatusBar

Earlier we introduced the three types of Window, such as the most common activity in application development, and its corresponding Window is the application type. Since the analysis of the process of adding the Windows corresponding to the Activity also needs to analyze the creation process of the Windows corresponding to them, here we are simple, first take the system status bar window StatusBar as an example, and follow the source code to sort out how WindowMnager adds the status bar window .

1. StatusBar is an important part of SystemUI, specifically referring to the system status bar. We have analyzed its related source code in Android 9.0 system source code _SystemUI (2) the creation and addition of the system status bar navigation bar . StatusBar mainly calls the addStatusBarWindow method to add the status bar window.

frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java

public class StatusBar extends SystemUI implements DemoMode,
        DragDownHelper.DragDownCallback, ActivityStarter, OnUnlockMethodChangedListener,
        OnHeadsUpChangedListener, CommandQueue.Callbacks, ZenModeController.Callback,
        ColorExtractor.OnColorsChangedListener, ConfigurationListener, NotificationPresenter {
    
    
  
   protected StatusBarWindowView mStatusBarWindow;
   protected StatusBarWindowManager mStatusBarWindowManager;

    private void addStatusBarWindow() {
    
    
    	//构建视图
        makeStatusBarView();
        ...代码省略...
        //调用StatusBarWindowManager的add方法将系统状态栏的视图添加到窗口上
        mStatusBarWindowManager.add(mStatusBarWindow, getStatusBarHeight());
    }
    
    protected void makeStatusBarView() {
    
    
        ...代码省略...
        //创建系统状态栏的视图
        inflateStatusBarWindow(context); 
        ...代码省略...
	}
	
    protected void inflateStatusBarWindow(Context context) {
    
    
    	//将视图赋值给mStatusBarWindow
        mStatusBarWindow = (StatusBarWindowView) View.inflate(context, R.layout.super_status_bar, null);
    }    

 }

The addStatusBarWindow method first calls makeStatusBarView to build the status bar view, and assigns the view to mStatusBarWindow, and then calls the add method of StatusBarWindowManager, passing the status bar view and status bar height as parameters.

2. The code related to the StatusBarWindowManager class and the add method is as follows.

frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java

public class StatusBarWindowManager implements RemoteInputController.Callback, Dumpable {
    
    
   
    private final WindowManager mWindowManager;
    
    public StatusBarWindowManager(Context context) {
    
    
        mContext = context;
        mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        ...代码省略...
    }

    public void add(View statusBarView, int barHeight) {
    
    
        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");//对用的Window的名称为StatusBar
        mLp.packageName = mContext.getPackageName();
        mStatusBarView = statusBarView;
        mBarHeight = barHeight;
        mWindowManager.addView(mStatusBarView, mLp);//将状态栏视图添加到WindowManager中
        mLpChanged = new WindowManager.LayoutParams();
        mLpChanged.copyFrom(mLp);
    }
    
}    

The add method of StatusBarWindowManager first creates LayoutParams,
and configures the properties of the StatusBar view including Width, Height, Type, Flag, Gravity, SoftInputMode, etc. In particular, the window type is set to TYPE_STATUS_BAR, which makes it clear that the window type of the StatusBar view is the status bar. Then call the addView method of WindowManager to add the status bar view to WindowManager.

3. The addView method of WindowManager

1. Regarding the addView method of WindowManager, it is specifically implemented in WindowManagerImpl.

frameworks/base/core/java/android/view/WindowManagerImpl.java

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);
    }
    
}

2. The addView of WindowManagerImpl further calls the addView method of WindowManagerGlobal.

frameworks/base/core/java/android/view/WindowManagerGlobal.java

public final class WindowManagerGlobal {
    
    

    private final ArrayList<View> mViews = new ArrayList<View>();//当前存在的View列表
    private final ArrayList<ViewRootImpl> mRoots = new ArrayList<ViewRootImpl>();//当前存在的ViewRootImpl列表
    private final ArrayList<WindowManager.LayoutParams> mParams =
            new ArrayList<WindowManager.LayoutParams>();//当前存在的布局参数列表
 public void addView(View view, ViewGroup.LayoutParams params,
            Display display, Window parentWindow) {
    
    
      	...代码省略...
        final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;
        if (parentWindow != null) {
    
    
            parentWindow.adjustLayoutParamsForSubWindow(wparams);//如果当前窗口要作为子窗口显示,需要父窗口根据WindowManager.LayoutParams类型的wparams参数对子窗口进行相应调整
        } else {
    
    
            final Context context = view.getContext();
            if (context != null
                    && (context.getApplicationInfo().flags
                            & ApplicationInfo.FLAG_HARDWARE_ACCELERATED) != 0) {
    
    
                wparams.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
            }
        }

        ViewRootImpl root;
        View panelParentView = null;

        synchronized (mLock) {
    
    
            ...代码省略...
            root = new ViewRootImpl(view.getContext(), display);//创建ViewRootImpl实例对象
            view.setLayoutParams(wparams);
            mViews.add(view);//将要添加的view保存到View列表中
            mRoots.add(root);//将新创建的root保存到ViewRootImpl列表中
            mParams.add(wparams);//将窗口的参数保存到布局参数列表中
            try {
    
    
                root.setView(view, wparams, panelParentView);//将窗口和窗口参数设置到ViewRootImpl中
            } catch (RuntimeException e) {
    
    
                if (index >= 0) {
    
    
                    removeViewLocked(index, true);
                }
                throw e;
            }
        }
    }
}

1) WindowManagerGlobal maintains 3 key lists related to Window operations. These 3 lists are involved in the process of adding, updating and deleting windows. They are View list, ViewRootImpl list, and layout parameter list.
2) The addView method first checks the incoming parameters view, params, and display. In addition, if the parentWindow is not empty, the parent window needs to adjust the view accordingly according to the wparams parameter of the WindowManager.LayoutParams type.
3) When everything is ready, a ViewRootImpl object instance will be created. After saving the view, root, and mparams in the corresponding data list, the setView method of ViewRootImpl will be called to set the window and window parameters to ViewRootImpl.
4) ViewRootImpl shoulders many responsibilities, mainly as follows:

  • The root of the View tree and manages the View tree
  • Trigger View's measurement, layout and drawing
  • A staging point for input events
  • Manage Surfaces
  • Responsible for inter-process communication with WindowManagerService

3. After understanding the responsibilities of ViewRootImpl, continue to look at the setView method of ViewRootImpl.

frameworks/base/core/java/android/view/ViewRootImpl.java

public final class ViewRootImpl implements ViewParent,
        View.AttachInfo.Callbacks, ThreadedRenderer.DrawCallbacks {
    
    

  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);
                } 
              ...代码省略...
    }
}

There are a lot of logic codes in the setView method, here only the most critical part is intercepted, the addToDisplay method of mWindowSession is called, mWindowSession is of IWindowSession type, it is a Binder object, used for inter-process communication, IWindowSession is the proxy of the client side, it The implementation of the Server side is Session, the previous code logic is running in the local process, and the addToDisplay method of Session is running in the process (SystemServer) where WindowManagerService is located.
ViewRootImpl communicates with WindowManagerService
As can be seen from the above figure, if the ViewRootImpl of the local process wants to communicate with WindowManagerService, it needs to go through Session, so why is Session included in WindowManagerService?

4. Continue to look at the addToDisplay method of Session.

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

class Session extends IWindowSession.Stub implements IBinder.DeathRecipient {
    
    

    final WindowManagerService mService;

    public Session(WindowManagerService service, IWindowSessionCallback callback,
            IInputMethodClient client, IInputContext inputContext) {
    
    
        mService = service;
        ...代码省略...
 	}
 	
    @Override
    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,
                outContentInsets, outStableInsets, outOutsets, outInputChannel);
    }
}    

1) The addToDisplay method will further call the addWindow method of WindowManagerService, and pass itself in as a parameter. Each application process will correspond to a Session, and WindowManagerService will use ArrayList to save these Sessions, which is why WindowManagerService includes Session.
2) All subsequent work is handed over to WindowManagerService. WindowManagerService will allocate a Surface for the added window and determine the display order of the windows. It can be seen that the canvas Surface is responsible for displaying the interface, not the window itself. WindowManagerService will hand over the Surface it manages to SurfaceFlinger, and SurfaceFlinger will mix and draw these Surfaces to the screen.

Four. Summary

The process of adding the system status bar window

Guess you like

Origin blog.csdn.net/abc6368765/article/details/129781572