【安卓12源码】WMS系列:addWindow 和 removeWindow流程

news2024/11/29 2:51:39

一、Window 的属性

Window的属性定义在WindowManager的内部类LayoutParams中,了解Window的属性能够更好的理解WMS的内部原理。Window的属性有很多种,与应用开发最密切的有三种,它们分别是Type(Window的类型)、Flag(Window的标志)和SoftInputMode(软键盘相关模式)

1. Window的类型 Type

Window的类型有很多种,比如应用程序窗口、系统错误窗口、输入法窗口、PopupWindow、Toast、Dialog等等。总来来说分为三大类分别是:Application Window(应用程序窗口)、Sub Windwow(子窗口)、System Window(系统窗口),每个大类又包含了很多种类型,它们都定义在WindowManager的静态内部类LayoutParams中

Window 窗口的显示次序:

当一个进程向WMS申请一个窗口时,WMS会为窗口确定显示次序。为了方便窗口显示次序的管理,手机屏幕可以虚拟的用X、Y、Z轴来表示,其中Z轴垂直于屏幕,从屏幕内指向屏幕外,这样确定窗口显示次序也就是确定窗口在Z轴上的次序,这个次序称为Z-Oder。Type值是Z-Oder排序的依据,我们知道Application应用程序窗口的Type值范围为1到99,Sub子窗口1000到1999 ,System系统窗口 2000到2999,,一般情况下,Type值越大则Z-Oder排序越靠前,就越靠近用户。当然窗口显示次序的逻辑不会这么简单,情况会比较多,举个常见的情况:当多个窗口的Type值都是TYPE_APPLICATION,这时WMS会结合各种情况给出最终的Z-Oder

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

  • 应用程序窗

应用程序的window 的值是从 1 到 99

// 在内部类 LayoutParams 中
    public static class LayoutParams extends ViewGroup.LayoutParams implements Parcelable {

// 应用程序的window 的值是从 1 到 99
        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 LAST_APPLICATION_WINDOW = 99;
  • Sub子窗口

子窗口是不能独立的存在,需要附着在其他窗口才可以,PopupWindow属于子窗口 。type值是从 1000-1999

// 子窗口的type 值是从 1000 到 1999
        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;

  • System系统窗口

Toast、输入法窗口、系统音量条窗口、系统错误窗口都属于系统窗口。type 值是从 2000-2999 

// 系统窗口的type值是从 2000 到 2999
        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
        public static final int TYPE_PHONE              = FIRST_SYSTEM_WINDOW+2;

        @Deprecated
        public static final int TYPE_SYSTEM_ALERT       = FIRST_SYSTEM_WINDOW+3;

        public static final int TYPE_KEYGUARD           = FIRST_SYSTEM_WINDOW+4;

        @Deprecated
        public static final int TYPE_TOAST              = FIRST_SYSTEM_WINDOW+5;

        @Deprecated
        public static final int TYPE_SYSTEM_OVERLAY     = FIRST_SYSTEM_WINDOW+6;

        @Deprecated
        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
        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_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_SCREENSHOT = FIRST_SYSTEM_WINDOW + 36;

        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 TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY = FIRST_SYSTEM_WINDOW + 39;
// 通知栏
        public static final int TYPE_NOTIFICATION_SHADE = FIRST_SYSTEM_WINDOW + 40;

        public static final int TYPE_STATUS_BAR_ADDITIONAL = FIRST_SYSTEM_WINDOW + 41;

        public static final int LAST_SYSTEM_WINDOW      = 2999;

2. Window的标志Flag

Flag描述
FLAG_ALLOW_LOCK_WHILE_SCREEN_ON只要窗口可见,就允许在开启状态的屏幕上锁屏
FLAG_NOT_FOCUSABLE窗口不能获得输入焦点,设置该标志的同时,FLAG_NOT_TOUCH_MODAL也会被设置
FLAG_NOT_TOUCHABLE窗口不接收任何触摸事件
FLAG_NOT_TOUCH_MODAL在该窗口区域外的触摸事件传递给其他的Window,而自己只会处理窗口区域内的触摸事件
FLAG_KEEP_SCREEN_ON只要窗口可见,屏幕就会一直亮着
FLAG_LAYOUT_NO_LIMITS允许窗口超过屏幕之外
FLAG_FULLSCREEN隐藏所有的屏幕装饰窗口,比如在游戏、播放器中的全屏显示
FLAG_SHOW_WHEN_LOCKED窗口可以在锁屏的窗口之上显示
FLAG_IGNORE_CHEEK_PRESSES当用户的脸贴近屏幕时(比如打电话),不会去响应此事件
FLAG_TURN_SCREEN_ON窗口显示时将屏幕点亮

设置 flags  的 3 种方式:

// 1. 通过addFlags 方法
// getWindow 获取的是对象 PhoneWindow对象
Window mWindow =getWindow(); 
mWindow.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);

// 2. 通过setFlags 方法
Window mWindow =getWindow();            
mWindow.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN
,WindowManager.LayoutParams.FLAG_FULLSCREEN);

// 3. 通过创建 LayoutParams 对象赋值方式
WindowManager.LayoutParams mWindowLayoutParams =
              new WindowManager.LayoutParams();
      mWindowLayoutParams.flags=WindowManager.LayoutParams.FLAG_FULLSCREEN;
      WindowManager mWindowManager =(WindowManager) getSystemService(Context.WINDOW_SERVICE);  
      TextView mTextView=new TextView(this);
      mWindowManager.addView(mTextView,mWindowLayoutParams);
                                                                                                                     

3. Window 的软键盘相关模式SoftInputMode

窗口和窗口的叠加是非常常见的场景,但如果其中的窗口是软键盘窗口,可能就会出现一些问题,比如典型的用户登录界面,默认的情况弹出的软键盘窗口可能会盖住输入框下方的按钮,这样用户体验会非常糟糕。
为了使得软键盘窗口能够按照期望来显示,WindowManager的静态内部类LayoutParams中定义了软键盘相关模式,这里给出常用的几个:

SoftInputMode描述
SOFT_INPUT_STATE_UNSPECIFIED没有指定状态,系统会选择一个合适的状态或依赖于主题的设置
SOFT_INPUT_STATE_UNCHANGED不会改变软键盘状态
SOFT_INPUT_STATE_HIDDEN当用户进入该窗口时,软键盘默认隐藏
SOFT_INPUT_STATE_ALWAYS_HIDDEN当窗口获取焦点时,软键盘总是被隐藏
SOFT_INPUT_ADJUST_RESIZE当软键盘弹出时,窗口会调整大小
SOFT_INPUT_ADJUST_PAN当软键盘弹出时,窗口不需要调整大小,要确保输入焦点是可见的

从上面给出的SoftInputMode ,可以发现,它们与AndroidManifest中Activity的属性android:windowSoftInputMode是对应的。因此,除了在AndroidMainfest中为Activity设置android:windowSoftInputMode以外还可以在Java代码中为Window设置SoftInputMode:

getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);

Android解析WindowManager(二)Window的属性 | BATcoder - 刘望舒

二、WMS 窗口添加addWindow流程

有关于 WMS 的 一些重要类:

  • WindowManager

具体的实现是WindowManagerImpl 应用与窗口管理服务WindowManagerService交互的接口;

  • PhoneWindowManager

继承了WindowManagerPolicy,在UI线程创建的。实现了窗口的各种策略,定义了窗口相关策略,比如:告诉WMS某一个类型Window的Z-Order的值是多少,帮助WMS矫正不合理的窗口属性,为WMS监听屏幕旋转的状态,预处理一些系统按键事件;

  • Choreographer

用户控制窗口动画、屏幕选择等操作,它拥有从显示子系统获取Vsync同步事件的能力,从而可以在合适的时机通知渲染动作,避免在渲染的过程中因为发生屏幕重绘而导致的画面撕裂。WMS使用Choreographer负责驱动所有的窗口动画、屏幕旋转动画、墙纸动画的渲染;

  • DisplayContent

用于描述多屏输出相关信息;

根据窗口的显示位置将其分组。隶属于同一个DisplayContent的窗口将会被显示在同一个屏幕中。每个DisplayContent都对应着唯一ID,在添加窗口的时候可以通过指定这个ID决定其将显示在哪个屏幕中;

DisplayContent是一个非常具有隔离性的一个概念。处于不同DisplayContent的两个窗口在布局、显示顺序以及动画处理上不会产生任何耦合;

  • WindowState

描述窗口的状态信息以及和WindowManagerService进行通信,一般一个窗口对应一个WindowState。它用来表示一个窗口的所有属性;

  • WindowToken
  • 窗口Token,用来做Binder通信;同时也是一种标识;
  • 在进行窗口Zorder排序时,属于同一个WindowToken的窗口会被安排在一起,而且在其中定义的一些属性将会影响所有属于此WindowToken的窗口,这些都表明了属于同一个WindowToken的窗口之间的紧密联系;
  • 应用组件在需要新的窗口时,必须提供WindowToken以表明自己的身份,并且窗口的类型必须与所持有的WindowToken的类型一致;
  • 在创建系统类型的窗口时不需要提供一个有效的Token,WMS会隐式地为其声明一个WindowToken,看起来谁都可以添加个系统级的窗口。难道Android为了内部使用方便而置安全于不顾吗?非也,addWindow()函数一开始的mPolicy.checkAddPermission()的目的就是如此。它要求客户端必须拥有SYSTEM_ALERT_WINDOW或INTERNAL_SYSTEM_WINDOW权限才能创建系;
  • Session

App进程通过建立Session代理对象和Session对象通信,进而和WMS建立连接;

  • SurfaceFlinger

SurfaceFlinger负责管理Android系统的帧缓冲区(Frame Buffer),Android设备的显示屏被抽象为一个帧缓冲区,而Android系统中的SurfaceFlinger服务就是通过向这个帧缓冲区写入内容来绘制应用程序中的用户界面的;

  • InputManager

管理每个窗口的输入事件通道(InputChannel)以及向通道上派发事件;

  • Animator

所有窗口动画的总管(WindowStateAnimator对象)。在Choreographer的驱动下,逐个渲染所有的动画;

Window 的概念

  • 表示一个窗口的概念,是所有View的直接管理者,任何视图都通过Window呈现(点击事件由Window->DecorView->View;Activity的setContentView底层通过Window完成)
  • Window是一个抽象类,具体实现是PhoneWindow;
  • 创建Window需要通过WindowManager创建;
  • WindowManager是外界访问Window的入口;
  • Window的具体实现位于WindowManagerService中;
  • WindowManager和WindowManagerService的交互是通过IPC进程间通信完成的;
  • 定义窗口样式和行为的抽象基类,用于作为顶层的View加到WindowManager中,其实现类是PhoneWindow;
  • 每个Window都需要指定一个Type(应用窗口、子窗口、系统窗口)。Activity对应的窗口是应用窗口;PhoneWindow,ContextMenu,OptionMenu是常用的子窗口;像Toast和系统警告提示框(如ANR)就是系统窗口,还有很多应用的悬浮窗也属于系统窗口;

Surface 的作用

  • 在Android中,一个窗口会独占一个Surface,Surface其实就是一个画布,应用程序通过Canvas或者OpenGL在Surface上绘制内容;
  • 在Surface上绘制后,通过SurfaceFlinger将多块Surface的内容按照Z-order进行混合并输出到FrameBuffer,从而将Android页面展示给用户;
  • 每个窗口都有一块Surface用于显示自己的ui,必然需要一个角色对窗口进行统一管理,这个时候,WMS应运而生。WMS为所有窗口分配Surface,掌管z-order以及位置、尺寸、窗口的进场出场动画,并且还是输入系统的中转站;
  • 布局系统:计算管理窗口的位置和层次;
  • 动画系统:根据布局系统的计算渲染窗口动画;

Android进阶:深入理解Android窗口管理框架机制-android 窗口管理

我们在学习activity 的生命周期的时候,参考一些资料说 on_resume的时候,才真正去显示view,相信本文可以给个基础的解答。 

窗口的添加从Activity::makeVisible开始,由WindowManagerImpl委托给WindowManagerGlobal处理,WindowManagerGlobal内部的mViewsmRootsmParamsmDyingViews分别管理窗口的试图、主线程、布局参数以及死亡过程中的视图;ViewRootImpl持有Session的代理端与WMS通信;

/frameworks/base/core/java/android/app/ActivityThread.java

// 执行 handleResumeActivity 

    @Override
    public void handleResumeActivity(ActivityClientRecord r, boolean finalStateRequest,
            boolean isForward, String reason) {

        unscheduleGcIdler();
        mSomeActivitiesChanged = true;

// 先执行 performResumeActivity
        if (!performResumeActivity(r, finalStateRequest, reason)) {
            return;
        }


        final Activity a = r.activity;

        final int forwardBit = isForward
                ? WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION : 0;

// mStartedActivity在 performResumeActivity 设置为 false
// willBeVisible  为 true
        boolean willBeVisible = !a.mStartedActivity;
        if (!willBeVisible) {
            willBeVisible = ActivityClient.getInstance().willActivityBeVisible(
                    a.getActivityToken());
        }
        if (r.window == null && !a.mFinished && willBeVisible) {

// 获取的对象是: PhoneWindow
            r.window = r.activity.getWindow();
// decor 是 new DecorView 对象
            View decor = r.window.getDecorView();

// DecorView 设置不可见
            decor.setVisibility(View.INVISIBLE);

// 在lauchactivity时候分析:activity.getWindowManager 是 WindowManagerImpl
            ViewManager wm = a.getWindowManager();
            WindowManager.LayoutParams l = r.window.getAttributes();

// 设置 activity 的 mDecor 为:DecorView 对象,先 install。。。
            a.mDecor = decor;

// 这里设置 layout 的类型为 TYPE_BASE_APPLICATION
            l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
            l.softInputMode |= forwardBit;
            if (r.mPreserveWindow) {
                a.mWindowAdded = true;
                r.mPreserveWindow = false;
                // Normally the ViewRoot sets up callbacks with the Activity
                // in addView->ViewRootImpl#setView. If we are instead reusing
                // the decor view we have to notify the view root that the
                // callbacks may have changed.
                ViewRootImpl impl = decor.getViewRootImpl();
                if (impl != null) {
                    impl.notifyChildRebuilt();
                }
            }
            if (a.mVisibleFromClient) {
                if (!a.mWindowAdded) {
                    a.mWindowAdded = true;

// addview 流程
                    wm.addView(decor, l);
                } else {
                    // The activity will get a callback for this {@link LayoutParams} change
                    // earlier. However, at that time the decor will not be set (this is set
                    // in this method), so no action will be taken. This call ensures the
                    // callback occurs with the decor set.
                    a.onWindowAttributesChanged(l);
                }
            }

            // If the window has already been added, but during resume
            // we started another activity, then don't yet make the
            // window visible.
        } else if (!willBeVisible) {
            if (localLOGV) Slog.v(TAG, "Launch " + r + " mStartedActivity set");
            r.hideForNow = true;
        }

4870          if (!r.activity.mFinished && willBeVisible && r.activity.mDecor != null && !r.hideForNow) {

4888              r.activity.mVisibleFromServer = true;
4889              mNumVisibleActivities++;
4890              if (r.activity.mVisibleFromClient) {
4891                  r.activity.makeVisible();
4892              }
4893          }

// 先执行 performResumeActivity

    @VisibleForTesting
    public boolean performResumeActivity(ActivityClientRecord r, boolean finalStateRequest,
            String reason) {

        if (r.getLifecycleState() == ON_RESUME) {
// finalStateRequest 为 true
            if (!finalStateRequest) {

            return false;
        }
        if (finalStateRequest) {
            r.hideForNow = false;
            r.activity.mStartedActivity = false;
        }
        try {
            r.activity.onStateNotSaved();
            r.activity.mFragments.noteStateNotSaved();
            checkAndBlockForNetworkAccess();
            if (r.pendingIntents != null) {
                deliverNewIntents(r, r.pendingIntents);
                r.pendingIntents = null;
            }
            if (r.pendingResults != null) {
                deliverResults(r, r.pendingResults, reason);
                r.pendingResults = null;
            }
// 回调 on_resume
            r.activity.performResume(r.startsNotResumed, reason);

            r.state = null;
            r.persistentState = null;
// 设置状态为 ON_RESUME
            r.setState(ON_RESUME);

            reportTopResumedActivityChanged(r, r.isTopResumedActivity, "topWhenResuming");
        } catch (Exception e) {
            if (!mInstrumentation.onException(r.activity, e)) {
                throw new RuntimeException("Unable to resume activity "
                        + r.intent.getComponent().toShortString() + ": " + e.toString(), e);
            }
        }
        return true;
    }

addView  相关的调用栈

WindowManagerImpl.addView()
    new ViewRoot
    // 保存到 mViews  mRoots  mParams
    ViewRoot.setView(xx)
        requestLayout // 检查主线程
            scheduleTraversals
                sendEmptyMessage
                handleMessage
                    performTraversals  // 2.11 测量 布局 绘制
                        ViewRoot.relayoutWindow
                            IWindowSession.relayout // 参考relayout的调用栈
                        draw
                            View.draw
                        scheduleTralScheduled // try again
        mWindowSession.addToDisplay // 2.15 与requestLayout同级
        // sWindowSession.add
            WMS.addWindow // 2.16
                new WindowState // 
                WindowState.attach // 
                    Session.windowAddedLocked
                        new SurfaceSession // 开辟一块内存,由SurfaceFlinger进行混合处理

 WindowManager是一个接口类,继承自接口ViewManager,从名称就知道它是用来管理Window的,它的实现类为WindowManagerImpl。如果我们想要对Window进行添加和删除就可以使用WindowManager

WindowManagerImpl 实现了 ViewManager  接口

public interface ViewManager
{
    public void addView(View view, ViewGroup.LayoutParams params);
    public void updateViewLayout(View view, ViewGroup.LayoutParams params);
    public void removeView(View view);

 wm.addView(decor, l) 流程

 // WindowManagerImpl 增加 view ,mDecor为 DecorView

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

    private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();

    @Override
    public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
        applyTokens(params);

// WindowManagerGlobal 增加 view,mParentWindow 为 PhoneWindow
        mGlobal.addView(view, params, mContext.getDisplayNoVerify(), mParentWindow,
                mContext.getUserId());
    }

// WindowManagerGlobal 增加 view,mParentWindow 为 PhoneWindow

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

// WindowManagerGlobal  是单例模式
    @UnsupportedAppUsage
    public static WindowManagerGlobal getInstance() {
        synchronized (WindowManagerGlobal.class) {
            if (sDefaultWindowManager == null) {
                sDefaultWindowManager = new WindowManagerGlobal();
            }
            return sDefaultWindowManager;
        }
    }

=========
    public void addView(View view, ViewGroup.LayoutParams params,
            Display display, Window parentWindow, int userId) {
。。。。。

        ViewRootImpl root;
        View panelParentView = null;

....

            int index = findViewLocked(view, false);
            if (index >= 0) {
                if (mDyingViews.contains(view)) {
                    // Don't wait for MSG_DIE to make it's way through root's queue.
                    mRoots.get(index).doDie();
....

// 1-5-2-1-1)创建 ViewRootImpl 对象
            root = new ViewRootImpl(view.getContext(), display);

            view.setLayoutParams(wparams);

// 将 DecorView 放到 mViews 数组中
            mViews.add(view);

// 将 ViewRootImpl 放到 mRoots 数组中
            mRoots.add(root);
            mParams.add(wparams);

            try {

// 1-5-2-2)ViewRootImpl 设置  view,为 DecorView,两者关联
                root.setView(view, wparams, panelParentView, userId);
            } catch (RuntimeException e) {
                // BadTokenException or InvalidDisplayException, clean up.
                if (index >= 0) {
                    removeViewLocked(index, true);
                }
                throw e;
            }
        }
    }

// 1-5-2-1-1)创建 ViewRootImpl 对象

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

    public ViewRootImpl(Context context, Display display) {

// getWindowSession 获取为 IWindowSession ,与 wms 通信,对象为 wm/Session.java
// 不使用 useSfChoreographer 
        this(context, display, WindowManagerGlobal.getWindowSession(),
                false /* useSfChoreographer */);
    }


    public ViewRootImpl(@UiContext Context context, Display display, IWindowSession session,
            boolean useSfChoreographer) {
        mContext = context;
// 缓存 session 与 wms 通信
        mWindowSession = session;
        mDisplay = display;
        mBasePackageName = context.getBasePackageName();
        mThread = Thread.currentThread();
        mLocation = new WindowLeaked(null);
        mLocation.fillInStackTrace();
        mWidth = -1;
        mHeight = -1;
        mDirty = new Rect();
        mTempRect = new Rect();
        mVisRect = new Rect();
        mWinFrame = new Rect();

// mWindow  为 W 对象
        mWindow = new W(this);
        mLeashToken = new Binder();
        mTargetSdkVersion = context.getApplicationInfo().targetSdkVersion;
        mViewVisibility = View.GONE;
        mTransparentRegion = new Region();
        mPreviousTransparentRegion = new Region();
        mFirst = true; // true for the first time the view is added
        mPerformContentCapture = true; // also true for the first time the view is added
        mAdded = false;

// 创建 View.AttachInfo 对象,传入 WindowSession,
        mAttachInfo = new View.AttachInfo(mWindowSession, mWindow, display, this, mHandler, this,
                context);
        mCompatibleVisibilityInfo = new SystemUiVisibilityInfo();
        mAccessibilityManager = AccessibilityManager.getInstance(context);
        mAccessibilityManager.addAccessibilityStateChangeListener(
                mAccessibilityInteractionConnectionManager, mHandler);
        mHighContrastTextManager = new HighContrastTextManager();
        mAccessibilityManager.addHighTextContrastStateChangeListener(
                mHighContrastTextManager, mHandler);
        mViewConfiguration = ViewConfiguration.get(context);
        mDensity = context.getResources().getDisplayMetrics().densityDpi;
        mNoncompatDensity = context.getResources().getDisplayMetrics().noncompatDensityDpi;
        mFallbackEventHandler = new PhoneFallbackEventHandler(context);

// 创建 Choreographer 对象
        mChoreographer = useSfChoreographer
                ? Choreographer.getSfInstance() : Choreographer.getInstance();
        mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
        mInsetsController = new InsetsController(new ViewRootInsetsControllerHost(this));

。。。。

    }

ViewRootImp 与 Session 的关系:

ViewRootImpl获取Session的代理类,通过Binder::IPC通信;
Session持有WMS服务;
InputStage为事件传递相关的类,管理窗口焦点focus;
W代表当前操作的窗口, 是ViewRootImpl的内部类,且持有ViewRootImpl的弱引用

// 1-5-2-2)ViewRootImpl 设置  view,为 DecorView,两者关联

root.setView(view, wparams, panelParentView, userId)

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

    public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView,
            int userId) {
        synchronized (this) {
            if (mView == null) {
// 缓存 decorview
                mView = view;
。。。
                mSoftInputMode = attrs.softInputMode;
                mWindowAttributesChanged = true;

// 设置 mRootView 为 decorview
                mAttachInfo.mRootView = view;
                mAttachInfo.mScalingRequired = mTranslator != null;
                mAttachInfo.mApplicationScale =
                        mTranslator == null ? 1.0f : mTranslator.applicationScale;
                if (panelParentView != null) {
                    mAttachInfo.mPanelParentWindowToken
                            = panelParentView.getApplicationWindowToken();
                }
                mAdded = true;

。。。。。
                // Schedule the first layout -before- adding to the window
                // manager, to make sure we do the relayout before receiving
                // any other events from the system.
// 1)请求vysnc,走绘制三大流程:requestLayout
                requestLayout();

。。。。
                try {
                    mOrigWindowType = mWindowAttributes.type;
                    mAttachInfo.mRecomputeGlobalAttributes = true;
                    collectViewAttributes();
                    adjustLayoutParamsForCompatibility(mWindowAttributes);
                    controlInsetsForCompatibility(mWindowAttributes);

// 2)与wms 通信,增加 window:addToDisplayAsUser
                    res = mWindowSession.addToDisplayAsUser(mWindow, mWindowAttributes,
                            getHostVisibility(), mDisplay.getDisplayId(), userId,
                            mInsetsController.getRequestedVisibility(), inputChannel, mTempInsets,
                            mTempControls);

// 1)请求vysnc,走绘制三大流程:requestLayout

    @Override
    public void requestLayout() {

// 如果没有走 performLayout 流程
        if (!mHandlingLayoutInLayoutRequest) {
            checkThread();
            mLayoutRequested = true;
            scheduleTraversals();
        }
    }

===========
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    void scheduleTraversals() {
        if (!mTraversalScheduled) {
            mTraversalScheduled = true;
// 消息同步屏障机制
            mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
// 给 Choreographer 编舞者发送 CALLBACK_TRAVERSAL 消息,请求一个 vsync,然后主线程走绘制三大流程
            mChoreographer.postCallback(
                    Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
            notifyRendererOfFramePending();
            pokeDrawLockIfNeeded();
        }
    }

// 2)与wms 通信,增加 window:addToDisplayAsUser

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

// session 作为连接 wms 的中介
    @Override
    public int addToDisplayAsUser(IWindow window, WindowManager.LayoutParams attrs,
            int viewVisibility, int displayId, int userId, InsetsState requestedVisibility,
            InputChannel outInputChannel, InsetsState outInsetsState,
            InsetsSourceControl[] outActiveControls) {
        return mService.addWindow(this, window, attrs, viewVisibility, displayId, userId,
                requestedVisibility, outInputChannel, outInsetsState, outActiveControls);
    }

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

    public int addWindow(Session session, IWindow client, LayoutParams attrs, int viewVisibility,
            int displayId, int requestUserId, InsetsState requestedVisibility,
            InputChannel outInputChannel, InsetsState outInsetsState,
            InsetsSourceControl[] outActiveControls) {
        Arrays.fill(outActiveControls, null);
        int[] appOp = new int[1];
        final boolean isRoundedCornerOverlay = (attrs.privateFlags
                & PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY) != 0;

// PhoneWindowManager 做权限检查,layout 的参数类型是 TYPE_BASE_APPLICATION
// PhoneWindowManager 也是个比较重要的类
        int res = mPolicy.checkAddPermission(attrs.type, isRoundedCornerOverlay, attrs.packageName,
                appOp);
        if (res != ADD_OKAY) {
            return res;
        }

        WindowState parentWindow = null;
        final int callingUid = Binder.getCallingUid();
        final int callingPid = Binder.getCallingPid();
        final long origId = Binder.clearCallingIdentity();
        final int type = attrs.type;

        synchronized (mGlobalLock) {
            if (!mDisplayReady) {
                throw new IllegalStateException("Display has not been initialialized");
            }

// 2-1) 创建或者获取 DisplayContent 对象 getDisplayContentOrCreate
            final DisplayContent displayContent = getDisplayContentOrCreate(displayId, attrs.token);

.....
// type 为:TYPE_BASE_APPLICATION,不满足下列条件
            if (type >= FIRST_SUB_WINDOW && type <= LAST_SUB_WINDOW) {
                parentWindow = windowForClientLocked(null, attrs.token, false);

。。。
            ActivityRecord activity = null;

// hasParent  为false
            final boolean hasParent = parentWindow != null;

// 没有执行 addWindowToken,返回的 token 为null
            WindowToken token = displayContent.getWindowToken(
                    hasParent ? parentWindow.mAttrs.token : attrs.token);

            final int rootType = hasParent ? parentWindow.mAttrs.type : type;
            boolean addToastWindowRequiresToken = false;
            final IBinder windowContextToken = attrs.mWindowContextToken;

            if (token == null) {
。。。
                } else if (mWindowContextListenerController.hasListener(windowContextToken)) {

//  2-2) 执行下列流程,创建 WindowToken 对象
                } else {
                    final IBinder binder = attrs.token != null ? attrs.token : client.asBinder();
                    token = new WindowToken.Builder(this, binder, type)
                            .setDisplayContent(displayContent)
                            .setOwnerCanManageAppTokens(session.mCanAddInternalSystemWindow)
                            .setRoundedCornerOverlay(isRoundedCornerOverlay)
                            .build();
                }

。。。。一些权限检查
。。。。

//  2-3) 创建 WindowState 对象
            final WindowState win = new WindowState(this, session, client, token, parentWindow,
                    appOp[0], attrs, viewVisibility, session.mUid, userId,
                    session.mCanAddInternalSystemWindow);
            if (win.mDeathRecipient == null) {
                // Client has apparently died, so there is no reason to
                // continue.
                ProtoLog.w(WM_ERROR, "Adding window client %s"
                        + " that is dead, aborting.", client.asBinder());
                return WindowManagerGlobal.ADD_APP_EXITING;
            }

            if (win.getDisplayContent() == null) {
                ProtoLog.w(WM_ERROR, "Adding window to Display that has been removed.");
                return WindowManagerGlobal.ADD_INVALID_DISPLAY;
            }

            final DisplayPolicy displayPolicy = displayContent.getDisplayPolicy();

// DisplayPolicy  执行 adjustWindowParamsLw 调整 参数,为 TYPE_BASE_APPLICATION没有调整
            displayPolicy.adjustWindowParamsLw(win, win.mAttrs);
            win.updateRequestedVisibility(requestedVisibility);

            res = displayPolicy.validateAddingWindowLw(attrs, callingPid, callingUid);
            if (res != ADD_OKAY) {
                return res;
            }

// 2-4) WinState去 打开InputChannel
            final boolean openInputChannels = (outInputChannel != null
                    && (attrs.inputFeatures & INPUT_FEATURE_NO_INPUT_CHANNEL) == 0);
            if  (openInputChannels) {
                win.openInputChannel(outInputChannel);
            }

            if (mUseBLAST) {
                res |= WindowManagerGlobal.ADD_FLAG_USE_BLAST;
            }

// 在 mWinAddedSinceNullFocus 数组增加这个 winstate
            if (displayContent.mCurrentFocus == null) {
                displayContent.mWinAddedSinceNullFocus.add(win);
            }

            if (excludeWindowTypeFromTapOutTask(type)) {
                displayContent.mTapExcludedWindows.add(win);
            }

// 2-5)调用WindowState 的attach 方法,其调用 Session 创建 SurfaceSession对象
            win.attach();
// 将 winstate 放到 map 中
            mWindowMap.put(client.asBinder(), win);
            win.initAppOpsState();

            final boolean suspended = mPmInternal.isPackageSuspended(win.getOwningPackage(),
                    UserHandle.getUserId(win.getOwningUid()));
            win.setHiddenWhileSuspended(suspended);

            final boolean hideSystemAlertWindows = !mHidingNonSystemOverlayWindows.isEmpty();
            win.setForceHideNonSystemOverlayWindowIfNeeded(hideSystemAlertWindows);

            final ActivityRecord tokenActivity = token.asActivityRecord();
            if (type == TYPE_APPLICATION_STARTING && tokenActivity != null) {
                tokenActivity.mStartingWindow = win;
                ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "addWindow: %s startingWindow=%s",
                        activity, win);
            }

            boolean imMayMove = true;
// 2-6) 在 winstate 的WinToken 中增加自己:addWindow
            win.mToken.addWindow(win);
            displayPolicy.addWindowLw(win, attrs);

            final WindowStateAnimator winAnimator = win.mWinAnimator;
// 设置为进入到动画
            winAnimator.mEnterAnimationPending = true;
            winAnimator.mEnteringAnimation = true;

// 看起来和动画相关
            if (activity != null && activity.isVisible()
                    && !prepareWindowReplacementTransition(activity)) {
                // If not, check if need to set up a dummy transition during display freeze
                // so that the unfreeze wait for the apps to draw. This might be needed if
                // the app is relaunching.
                prepareNoneTransitionForRelaunching(activity);
            }
。。。。

            boolean focusChanged = false;
            if (win.canReceiveKeys()) {

// 更新焦点
                focusChanged = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS,
                        false /*updateInputWindows*/);
                if (focusChanged) {
                    imMayMove = false;
                }
            }

            win.getParent().assignChildLayers();

            if (focusChanged) {
                displayContent.getInputMonitor().setInputFocusLw(displayContent.mCurrentFocus,
                        false /*updateInputWindows*/);
            }
            displayContent.getInputMonitor().updateInputWindowsLw(false /*force*/);

            ProtoLog.v(WM_DEBUG_ADD_REMOVE, "addWindow: New client %s"
                    + ": window=%s Callers=%s", client.asBinder(), win, Debug.getCallers(5));

            if (win.isVisibleOrAdding() && displayContent.updateOrientation()) {
                displayContent.sendNewConfiguration();
            }

            // This window doesn't have a frame yet. Don't let this window cause the insets change.
            displayContent.getInsetsStateController().updateAboveInsetsState(
                    win, false /* notifyInsetsChanged */);

            getInsetsSourceControls(win, outActiveControls);
        }

addToDisplay方法中会调用了WMS的addWindow方法,并将自身也就是Session,作为参数传了进去,每个应用程序进程都会对应一个Session,WMS会用ArrayList来保存这些Session。这样剩下的工作就交给WMS来处理,在WMS中会为这个添加的窗口分配Surface,并确定窗口显示次序,可见负责显示界面的是画布Surface,而不是窗口本身。WMS会将它所管理的Surface交由SurfaceFlinger处理,SurfaceFlinger会将这些Surface混合并绘制到屏幕上。

// 2-1) 创建或者获取 DisplayContent 对象 getDisplayContentOrCreate

    RootWindowContainer mRoot;

    private DisplayContent getDisplayContentOrCreate(int displayId, IBinder token) {
        if (token != null) {
// mRoot 为 RootWindowContainer,这里返回是 null
            final WindowToken wToken = mRoot.getWindowToken(token);
            if (wToken != null) {
                return wToken.getDisplayContent();
            }
        }

// 调用 RootWindowContainer,返回 DisplayContent  对象
        return mRoot.getDisplayContentOrCreate(displayId);
    }

=======

    // TODO: Look into consolidating with getDisplayContent()
    @Nullable
    DisplayContent getDisplayContentOrCreate(int displayId) {
        DisplayContent displayContent = getDisplayContent(displayId);
        if (displayContent != null) {
            return displayContent;
        }

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

    /** Returns the window token for the input binder if it exist in the system. */
    WindowToken getWindowToken(IBinder binder) {
        for (int i = mChildren.size() - 1; i >= 0; --i) {
// 如下分析,setWindowManager创建了DisplayContent, 获取到 DisplayContent
            final DisplayContent dc = mChildren.get(i);

// 需要调用 addWindowToken,才有对应的 WindowToken
            final WindowToken wtoken = dc.getWindowToken(binder);
            if (wtoken != null) {
                return wtoken;
            }
        }
        return null;
    }

=========
// mChildren 是再父类WindowContainer.java addChild 赋值的

514      protected void addChild(E child, Comparator<E> comparator) {
515          if (!child.mReparenting && child.getParent() != null) {
516              throw new IllegalArgumentException("addChild: container=" + child.getName()
517                      + " is already a child of container=" + child.getParent().getName()
518                      + " can't add to container=" + getName());
519          }
520  
521          int positionToAdd = -1;
522          if (comparator != null) {
523              final int count = mChildren.size();
524              for (int i = 0; i < count; i++) {
525                  if (comparator.compare(child, mChildren.get(i)) < 0) {
526                      positionToAdd = i;
527                      break;
528                  }
529              }
530          }
531  
532          if (positionToAdd == -1) {
533              mChildren.add(child);
534          } else {
535              mChildren.add(positionToAdd, child);
536          }

========
// 在 系统进程初始化的时候有 setWindowManager
    void setWindowManager(WindowManagerService wm) {
        mWindowManager = wm;
        mDisplayManager = mService.mContext.getSystemService(DisplayManager.class);
        mDisplayManager.registerDisplayListener(this, mService.mUiHandler);
        mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);

        final Display[] displays = mDisplayManager.getDisplays();
        for (int displayNdx = 0; displayNdx < displays.length; ++displayNdx) {
            final Display display = displays[displayNdx];
// 创建 DisplayContent 对象
            final DisplayContent displayContent = new DisplayContent(display, this);
// 增加这个 child
            addChild(displayContent, POSITION_BOTTOM);
            if (displayContent.mDisplayId == DEFAULT_DISPLAY) {
                mDefaultDisplay = displayContent;
            }
        }

综上 // 调用 RootWindowContainer,返回 DisplayContent  对象,是在RootWindowContainer调用 setWindowManager创建的

//  2-2) 执行下列流程,创建 WindowToken 对象

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

    static class Builder {
        private final WindowManagerService mService;
        private final IBinder mToken;
        @WindowType
        private final int mType;

        private boolean mPersistOnEmpty;
        private DisplayContent mDisplayContent;
        private boolean mOwnerCanManageAppTokens;
        private boolean mRoundedCornerOverlay;
        private boolean mFromClientToken;
        @Nullable
        private Bundle mOptions;

        Builder(WindowManagerService service, IBinder token, int type) {
            mService = service;
            mToken = token;
            mType = type;
        }
.。。。
        WindowToken build() {
            return new WindowToken(mService, mToken, mType, mPersistOnEmpty, mDisplayContent,
                    mOwnerCanManageAppTokens, mRoundedCornerOverlay, mFromClientToken, mOptions);
        }

//  2-3) 创建 WindowState 对象

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

IWindow c 为:ViewRootImpl 的 final W mWindow,与客户端通信

WindowToken token,: 为 WindowToken
WindowState parentWindow: 为null

    WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,
            WindowState parentWindow, int appOp, WindowManager.LayoutParams a, int viewVisibility,
            int ownerId, int showUserId, boolean ownerCanAddInternalSystemWindow) {
        this(service, s, c, token, parentWindow, appOp, a, viewVisibility, ownerId, showUserId,
                ownerCanAddInternalSystemWindow, new PowerManagerWrapper() {
                    @Override
                    public void wakeUp(long time, @WakeReason int reason, String details) {
                        service.mPowerManager.wakeUp(time, reason, details);
                    }

                    @Override
                    public boolean isInteractive() {
                        return service.mPowerManager.isInteractive();
                    }
                });
    }

    WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,
            WindowState parentWindow, int appOp, WindowManager.LayoutParams a, int viewVisibility,
            int ownerId, int showUserId, boolean ownerCanAddInternalSystemWindow,
            PowerManagerWrapper powerManagerWrapper) {
        super(service);
// SurfaceControl.Transaction 对象
        mTmpTransaction = service.mTransactionFactory.get();
        mSession = s;
// viewrootimpl 的 W
        mClient = c;
        mAppOp = appOp;
        mToken = token;
// 为 null
        mActivityRecord = mToken.asActivityRecord();
        mOwnerUid = ownerId;
        mShowUserId = showUserId;
        mOwnerCanAddInternalSystemWindow = ownerCanAddInternalSystemWindow;
        mWindowId = new WindowId(this);
        mAttrs.copyFrom(a);
        mLastSurfaceInsets.set(mAttrs.surfaceInsets);
        mViewVisibility = viewVisibility;

// policy是 PhoneWindowManager
        mPolicy = mWmService.mPolicy;
        mContext = mWmService.mContext;
        DeathRecipient deathRecipient = new DeathRecipient();
        mPowerManagerWrapper = powerManagerWrapper;
        mForceSeamlesslyRotate = token.mRoundedCornerOverlay;
        mInputWindowHandle = new InputWindowHandleWrapper(new InputWindowHandle(
                mActivityRecord != null
                        ? mActivityRecord.getInputApplicationHandle(false /* update */) : null,
                getDisplayId()));
        mInputWindowHandle.setOwnerPid(s.mPid);
        mInputWindowHandle.setOwnerUid(s.mUid);
        mInputWindowHandle.setName(getName());
        mInputWindowHandle.setPackageName(mAttrs.packageName);
        mInputWindowHandle.setLayoutParamsType(mAttrs.type);

// 。。。。。。。
        } else {
            // The multiplier here is to reserve space for multiple
            // windows in the same type layer.

// 这里乘以 10000 然后加 TYPE_LAYER_OFFSET = 1000==》 11000
            mBaseLayer = mPolicy.getWindowLayerLw(this)
                    * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;
            mSubLayer = 0;
            mIsChildWindow = false;
            mLayoutAttached = false;
            mIsImWindow = mAttrs.type == TYPE_INPUT_METHOD
                    || mAttrs.type == TYPE_INPUT_METHOD_DIALOG;
            mIsWallpaper = mAttrs.type == TYPE_WALLPAPER;
        }
// 为 false
        mIsFloatingLayer = mIsImWindow || mIsWallpaper;

        if (mActivityRecord != null && mActivityRecord.mShowForAllUsers) {
            // Windows for apps that can show for all users should also show when the device is
            // locked.
            mAttrs.flags |= FLAG_SHOW_WHEN_LOCKED;
        }

// 创建 WindowStateAnimator 对象
        mWinAnimator = new WindowStateAnimator(this);
        mWinAnimator.mAlpha = a.alpha;

        mRequestedWidth = 0;
        mRequestedHeight = 0;
        mLastRequestedWidth = 0;
        mLastRequestedHeight = 0;
        mLayer = 0;
        mOverrideScale = mWmService.mAtmService.mCompatModePackages.getCompatScale(
                mAttrs.packageName, s.mUid);

。。。。

// 2-4) WinState去 打开InputChannel

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

    void openInputChannel(InputChannel outInputChannel) {
        if (mInputChannel != null) {
            throw new IllegalStateException("Window already has an input channel.");
        }
// 获取名字
        String name = getName();

// 调用 wms 的inputmanagerservice 去 创建channel: nativeCreateInputChannel
        mInputChannel = mWmService.mInputManager.createInputChannel(name);
        mInputChannelToken = mInputChannel.getToken();
        mInputWindowHandle.setToken(mInputChannelToken);

// 将其token 放入到 wms 的焦点map 中
        mWmService.mInputToWindowMap.put(mInputChannelToken, this);
        if (outInputChannel != null) {
            mInputChannel.copyTo(outInputChannel);
        } else {

// 2-5)调用WindowState 的attach 方法,其调用 Session 创建 SurfaceSession对象

    void attach() {
        if (DEBUG) Slog.v(TAG, "Attaching " + this + " token=" + mToken);
        mSession.windowAddedLocked();
    }

调用 Session 的 windowAddedLocked

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

    SurfaceSession mSurfaceSession;

    void windowAddedLocked() {
        if (mPackageName == null) {
            final WindowProcessController wpc = mService.mAtmService.mProcessMap.getProcess(mPid);
            if (wpc != null) {

// 获取包名
                mPackageName = wpc.mInfo.packageName;
                mRelayoutTag = "relayoutWindow: " + mPackageName;
            } else {
                Slog.e(TAG_WM, "Unknown process pid=" + mPid);
            }
        }
        if (mSurfaceSession == null) {
// 创建 SurfaceSession 对象,mSurfaceSession 是public 方法,可以通过对象.mSurfaceSession 获取
            mSurfaceSession = new SurfaceSession();
            ProtoLog.i(WM_SHOW_TRANSACTIONS, "  NEW SURFACE SESSION %s", mSurfaceSession);
// 将这个应用进程创建的 session 添加到 wms 的 mSessions 数组中
            mService.mSessions.add(this);
            if (mLastReportedAnimatorScale != mService.getCurrentAnimatorScale()) {
                mService.dispatchNewAnimatorScaleLocked(this);
            }
        }
// 增加这个window 的数量
        mNumWindow++;
    }

// 创建 SurfaceSession 对象

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

// 创建一个链接与 surfaceflinger 通信
    /** Create a new connection with the surface flinger. */
    @UnsupportedAppUsage
    public SurfaceSession() {
        mNativeClient = nativeCreate();
    }

===========
/frameworks/base/core/jni/android_view_SurfaceSession.cpp

static jlong nativeCreate(JNIEnv* env, jclass clazz) {
// 创建 SurfaceComposerClient 对象
    SurfaceComposerClient* client = new SurfaceComposerClient();
    client->incStrong((void*)nativeCreate);
// 返回引用给java 层
    return reinterpret_cast<jlong>(client);
}

=========
// 创建 SurfaceComposerClient 对象

/frameworks/native/libs/gui/SurfaceComposerClient.cpp

SurfaceComposerClient::SurfaceComposerClient()
    : mStatus(NO_INIT)
{
}

// 初始化对象时会调用 onFirstRef
void SurfaceComposerClient::onFirstRef() {
// 获取与surfaceflinger 通信的客户端
    sp<ISurfaceComposer> sf(ComposerService::getComposerService());
    if (sf != nullptr && mStatus == NO_INIT) {
        sp<ISurfaceComposerClient> conn;

// 调用surfaceflinger 的 createConnection 方法
        conn = sf->createConnection();
        if (conn != nullptr) {
            mClient = conn;
            mStatus = NO_ERROR;
        }
    }
}

// 2-6) 在 winstate 的WinToken 中增加自己:addWindow

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

    void addWindow(final WindowState win) {
        ProtoLog.d(WM_DEBUG_FOCUS,
                "addWindow: win=%s Callers=%s", win, Debug.getCallers(5));

// 这里为 false
        if (win.isChildWindow()) {
            // Child windows are added to their parent windows.
            return;
        }

// 先创建个 SurfaceControl,设置了 setSurfaceControl,SurfaceControl
        if (mSurfaceControl == null) {
            createSurfaceControl(true /* force */);
        }
        if (!mChildren.contains(win)) {
            ProtoLog.v(WM_DEBUG_ADD_REMOVE, "Adding %s to %s", win, this);

// 调用父类将win 增加到 mChildren 中
            addChild(win, mWindowComparator);
            mWmService.mWindowsChanged = true;
            // TODO: Should we also be setting layout needed here and other places?
        }
    }

三、移除窗口操作 removeWindow

调用 WindowManagerGlobal 的removeView 方法

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

431      @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
432      public void removeView(View view, boolean immediate) {
433          if (view == null) {
434              throw new IllegalArgumentException("view must not be null");
435          }
436  
437          synchronized (mLock) {
438              int index = findViewLocked(view, true);
439              View curView = mRoots.get(index).getView();

// 加锁移除这个 view
440              removeViewLocked(index, immediate);
441              if (curView == view) {
442                  return;
443              }
444  
445              throw new IllegalStateException("Calling with view " + view
446                      + " but the ViewAncestor is attached to " + curView);
447          }
448      }

=============
492      private void removeViewLocked(int index, boolean immediate) {
493          ViewRootImpl root = mRoots.get(index);
494          View view = root.getView();
495  
496          if (root != null) {
497              root.getImeFocusController().onWindowDismissed();
498          }

// 通过 ViewRootImpl 的 die 方法去移除
499          boolean deferred = root.die(immediate);
500          if (view != null) {
501              view.assignParent(null);
502              if (deferred) {
503                  mDyingViews.add(view);
504              }
505          }
506      }

// 通过 ViewRootImpl 的 die 方法去移除

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

8117      boolean die(boolean immediate) {
8118          // Make sure we do execute immediately if we are in the middle of a traversal or the damage
8119          // done by dispatchDetachedFromWindow will cause havoc on return.

// 如果是马上移除,并且没有在遍历绘制的话,处理Vsync 事件
8120          if (immediate && !mIsInTraversal) {
// 执行 dodie 方法
8121              doDie();
8122              return false;
8123          }
8124  
8125          if (!mIsDrawing) {
8126              destroyHardwareRenderer();
8127          } else {
8128              Log.e(mTag, "Attempting to destroy the window while drawing!\n" +
8129                      "  window=" + this + ", title=" + mWindowAttributes.getTitle());
8130          }
// 这里其实也需要执行 dodie 方法
8131          mHandler.sendEmptyMessage(MSG_DIE);
8132          return true;
8133      }

==============
8135      void doDie() {
// 看是否在主线程中处理
8136          checkThread();
8137          if (LOCAL_LOGV) Log.v(mTag, "DIE in " + this + " of " + mSurface);
8138          synchronized (this) {
8139              if (mRemoved) {
8140                  return;
8141              }
8142              mRemoved = true;
// 在增加view 的时候,设置了 mAdded 为true
8143              if (mAdded) {
8144                  dispatchDetachedFromWindow();
8145              }
8146  
8147              if (mAdded && !mFirst) {
8148                  destroyHardwareRenderer();
8149  
。。。。
====================
4968      void dispatchDetachedFromWindow() {
4969          // Make sure we free-up insets resources if view never received onWindowFocusLost()
4970          // because of a die-signal
4971          mInsetsController.onWindowFocusLost();
4972          mFirstInputStage.onDetachedFromWindow();
4973          if (mView != null && mView.mAttachInfo != null) {
4974              mAttachInfo.mTreeObserver.dispatchOnWindowAttachedChange(false);
4975              mView.dispatchDetachedFromWindow();
4976          }
4977  
4978          mAccessibilityInteractionConnectionManager.ensureNoConnection();
4979          mAccessibilityManager.removeAccessibilityStateChangeListener(
4980                  mAccessibilityInteractionConnectionManager);
4981          mAccessibilityManager.removeHighTextContrastStateChangeListener(
4982                  mHighContrastTextManager);
4983          removeSendWindowContentChangedCallback();
4984  
// 销毁硬件渲染相关的对象
4985          destroyHardwareRenderer();
4986  
4987          setAccessibilityFocus(null, null);
4988  
4989          mInsetsController.cancelExistingAnimations();
4990  
4991          mView.assignParent(null);
4992          mView = null;
4993          mAttachInfo.mRootView = null;
4994  

// 销毁创建的surface
4995          destroySurface();
4996  
4997          if (mInputQueueCallback != null && mInputQueue != null) {
4998              mInputQueueCallback.onInputQueueDestroyed(mInputQueue);
4999              mInputQueue.dispose();
5000              mInputQueueCallback = null;
5001              mInputQueue = null;
5002          }
5003          try {

// 与 wms 通信移除这个window
5004              mWindowSession.remove(mWindow);

// 与 wms 通信移除这个window

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

216      @Override
217      public void remove(IWindow window) {
218          mService.removeWindow(this, window);
219      }

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

2023  
2024      void removeWindow(Session session, IWindow client) {
2025          synchronized (mGlobalLock) {
2026              WindowState win = windowForClientLocked(session, client, false);
2027              if (win != null) {

// 通过 WindowState 去移除 removeIfPossible
2028                  win.removeIfPossible();
2029                  return;
2030              }

// 通过 WindowState 去移除 removeIfPossible

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

2417      @Override
2418      void removeIfPossible() {
2419          super.removeIfPossible();
2420          removeIfPossible(false /*keepVisibleDeadWindow*/);
2421      }

===========
2423      private void removeIfPossible(boolean keepVisibleDeadWindow) {
2424          mWindowRemovalAllowed = true;
2425          ProtoLog.v(WM_DEBUG_ADD_REMOVE,
2426                  "removeIfPossible: %s callers=%s", this, Debug.getCallers(5));
2427  
。。。。
2491                  // If we are not currently running the exit animation, we need to see about starting one

// 如果还在执行动画
2492                  wasVisible = isWinVisibleLw();
。。。
// 如果还是动画,这里去执行动画
2509                  if (wasVisible) {
2510                      final int transit = (!startingWindow) ? TRANSIT_EXIT : TRANSIT_PREVIEW_DONE;
2511  
2512                      // Try starting an animation.
2513                      if (mWinAnimator.applyAnimationLocked(transit, false)) {
2514                          mAnimatingExit = true;
2515  
。。。。。。。
// 如果上面没有return,则立即执行移除方法 removeImmediately
2550              removeImmediately();

// 去更新焦点
2559              mWmService.updateFocusedWindowLocked(isFocused()
2560                              ? UPDATE_FOCUS_REMOVING_FOCUS
2561                              : UPDATE_FOCUS_NORMAL,
2562                      true /*updateInputWindows*/);

// 立即执行移除方法 removeImmediately

2361      @Override
2362      void removeImmediately() {

// 调用 WindowContainer ,移除创建的 mSurfaceControl
2363          super.removeImmediately();
2364  
2365          if (mRemoved) {
2366              // Nothing to do.
2367              ProtoLog.v(WM_DEBUG_ADD_REMOVE,
2368                      "WS.removeImmediately: %s Already removed...", this);
2369              return;
2370          }
2371  
2372          mRemoved = true;

// 移除input 相关的对象
2402          disposeInputChannel();
2403  

// WindowStateAnimator销毁 surface
2404          mWinAnimator.destroySurfaceLocked(mTmpTransaction);
// 提交事务
2405          mTmpTransaction.apply();
// 将与wms 通信的session 移除
2406          mSession.windowRemovedLocked();
2407          try {
2408              mClient.asBinder().unlinkToDeath(mDeathRecipient, 0);

WindowStateAnimator销毁 surface

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

    void destroySurfaceLocked(SurfaceControl.Transaction t) {
        final ActivityRecord activity = mWin.mActivityRecord;
        if (activity != null) {
            if (mWin == activity.mStartingWindow) {
                activity.startingDisplayed = false;
            }
        }

        if (mSurfaceController == null) {
            return;
        }

// 设置 WindowState 的状态是隐藏的 mHidden
        mWin.mHidden = true;

        try {
            if (DEBUG_VISIBILITY) {
                logWithStack(TAG, "Window " + this + " destroying surface "
                        + mSurfaceController + ", session " + mSession);
            }
            ProtoLog.i(WM_SHOW_SURFACE_ALLOC, "SURFACE DESTROY: %s. %s",
                    mWin, new RuntimeException().fillInStackTrace());
// 销毁surface
            destroySurface(t);

            mWallpaperControllerLocked.hideWallpapers(mWin);
        } catch (RuntimeException e) {
            Slog.w(TAG, "Exception thrown when destroying Window " + this
                    + " surface " + mSurfaceController + " session " + mSession + ": "
                    + e.toString());
        }

// windowstate 设置没有surface 
        mWin.setHasSurface(false);
        if (mSurfaceController != null) {

// WindowSurfaceController.java 设置显示状态为 false
            mSurfaceController.setShown(false);
        }

// 回收 mSurfaceController
        mSurfaceController = null;

// 设置绘制状态为 NO_SURFACE
        mDrawState = NO_SURFACE;
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1300088.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【蜗牛到家】获南明电子信息产业引导基金战略投资

智慧社区生活服务平台「蜗牛到家」已于近期获得贵阳南明电子信息产业引导基金、华科明德战略投资。 贵阳南明电子信息产业引导基金属于政府旗下产业引导基金&#xff0c;贵州华科明德基金管理有限公司擅长电子信息产业、高科技产业、城市建设及民生保障领域的投资&#xff0c;双…

【EI会议征稿中】第三届信号处理与通信安全国际学术会议(ICSPCS 2024)

第三届信号处理与通信安全国际学术会议&#xff08;ICSPCS 2024&#xff09; 2024 3rd International Conference on Signal Processing and Communication Security 信号处理和通信安全是现代信息技术应用的重要领域&#xff0c;近年来这两个领域的研究相互交叉促进&#xf…

[每周一更]-(第76期):Go源码阅读与分析的方式

读源码可以深层理解Go的编写方式&#xff0c;理解作者们的思维方式&#xff1b;也有助于对Go语法用法深刻的理解&#xff0c;我们从这一篇说一下如何读源码&#xff0c;从哪些源码着手&#xff0c;从 简单到深入的方式学习源码&#xff1b; 学习源码也是一个修炼过程&#xff0…

【小白专用】Sql Server 连接Mysql 更新23.12.09

目标 已知mysql连接参数&#xff08;地址和用户&#xff09;&#xff0c;期望通过Microsoft Sql Server Management Studio &#xff08;以下简称MSSSMS&#xff09;连接Mysql&#xff0c;在MSSSMS中直接查询或修改Mysql中的数据。 一般是选最新的版本下载。 选64位还是32位&a…

P13 Linux进程间通信——管道

前言 &#x1f3ac; 个人主页&#xff1a;ChenPi &#x1f43b;推荐专栏1: 《Linux C应用编程&#xff08;概念类&#xff09;_ChenPi的博客-CSDN博客》✨✨✨ &#x1f525; 推荐专栏2: 《C_ChenPi的博客-CSDN博客》✨✨✨ &#x1f6f8;推荐专栏3: ​​​​​​《链表_C…

LeetCode二分查找:寻找旋转排序数组中的最小值

LeetCode二分查找&#xff1a;寻找旋转排序数组中的最小值 题目描述 已知一个长度为 n 的数组&#xff0c;预先按照升序排列&#xff0c;经由 1 到 n 次 旋转 后&#xff0c;得到输入数组。例如&#xff0c;原数组 nums [0,1,2,4,5,6,7] 在变化后可能得到&#xff1a; 若旋…

Nginx【通俗易懂】《上篇》

目录 1.什么是Nginx&#x1f495;&#x1f495;&#x1f495; 2.Nginx的基本目录&#x1f495;&#x1f495;&#x1f495; 3.基本原理图 &#x1f495;&#x1f495;&#x1f495; 4.Nginx配置 &#x1f495;&#x1f495;&#x1f495; 5.日志的分析 &#x1f495;&…

neuq-acm预备队训练week 8 P4779 【模板】单源最短路径(标准版)

题目背景 题目限制 题目描述 给定一个 n 个点&#xff0c;m 条有向边的带非负权图&#xff0c;请你计算从 s 出发&#xff0c;到每个点的距离。 数据保证你能从 s 出发到任意点。 输入格式 第一行为三个正整数n,m,s。 第二行起 m 行&#xff0c;每行三个非负整数 ui​,vi​…

Grounding DINO、TAG2TEXT、RAM、RAM++论文解读

提示&#xff1a;Grounding DINO、TAG2TEXT、RAM、RAM论文解读 文章目录 前言一、Grounding DINO: Marrying DINO with Grounded Pre-Training for Open-Set Object Detection1、摘要2、背景3、部分文献翻译4、贡献5、模型结构解读a.模型整体结构b.特征增强结构c.解码结构 6、实…

JAVAEE-8-线程池

池 我们之前也接触过,比如说常量池,数据库连接池,线程池,进程池,内存池等等, 池的共性: 1.提前把要用的对象准备好 2.把用完的对象也不要立即释放,先留着以备下次使用 来提高效率!!! 最开始,进程能够解决并发编程的问题,因为频繁创建销毁进程的开销成本太大了,所以我们引…

接口自动化测试框架的搭建

经过了一年多的接口测试工作&#xff0c;旧的框架也做了一些新的调整&#xff0c;删除了很多冗余的功能&#xff0c;只保留了最基本的接口结构验证、接口回归测试、线上定时巡检功能。 框架的演进 1.界面 UI 做了优化&#xff0c;整个框架的画风突然不一样了&#xff08;人靠…

11、虚函数、多态、纯虚函数

11、虚函数、多态、纯虚函数 虚函数覆盖调用 多态实现多态的两个必要条件多态 和 this指针多态的实现&#xff1a;虚函数表虚函数表与动态绑定动态绑定动态绑定对性能的影响 纯虚函数抽象类纯抽象类 虚函数 形如class 类名{ virtual 返回值 函数名(形参表) { … } }; 的成员函…

Git merge 与 Git rebase 与 Git fetch

Git merge 与 Git rebase 看这个图就行了 git merge、git rebase 和 git fetch 是 Git 中的三个不同的命令&#xff0c;它们分别用于不同的目的。以下是它们的主要区别&#xff1a; git merge&#xff08;合并&#xff09;&#xff1a; 用途&#xff1a; 用于将一个分支的更改…

pta模拟题——7-34 刮刮彩票

“刮刮彩票”是一款网络游戏里面的一个小游戏。如图所示&#xff1a; 每次游戏玩家会拿到一张彩票&#xff0c;上面会有 9 个数字&#xff0c;分别为数字 1 到数字 9&#xff0c;数字各不重复&#xff0c;并以 33 的“九宫格”形式排布在彩票上。 在游戏开始时能看见一个位置上…

带你搞懂JavaScript中的原型和原型链

简介 原型和原型链是JavaScript中与对象有关的重要概念&#xff0c;但是部分前端开发者却不太理解&#xff0c;也不清楚原型链有什么用处。其实&#xff0c;学过其他面对对象语言的同学应该了解&#xff0c;对象是由类生成的实例&#xff0c;类与类之间有继承的关系。在ES6之前…

html网页设计 01marquee标签广告滚动(1)

<!DOCTYPE html> <html><head><meta charset"utf-8"><title></title></head><body><!-- scrollamount:数字越大&#xff0c;滚动越快direction:滚动方向滚动的类型behaior"slide",文字滚动到边界后就会…

Redis分布式缓存超详细总结!

文章目录 前言一、Redis持久化解决数据丢失问题1.RDB&#xff08;Redis Database Backup file&#xff09;持久化&#xff08;1&#xff09;执行RDB&#xff08;2&#xff09;RDB方式bgsave的基本流程&#xff08;3&#xff09;RDB会在什么时候执行&#xff1f;save 60 1000代表…

Vulnhub-DC-9 靶机复现完整过程

一、搭建环境 kali的IP地址是&#xff1a;192.168.200.14 DC-9的IP地址暂时未知 二、信息收集 1、探索同网段下存活的主机 arp-scan -l #2、探索开放的端口 开启端口有&#xff1a;80和22端口 3、目录扫描 访问80 端口显示的主页面 分别点击其他几个页面 可以看到是用户…

13、C++异常处理

13、c异常处理 抛出异常捕获异常未抛出异常时的流程抛出异常时的流程捕获异常匹配顺序异常说明异常处理构造函数中的异常析构函数中的异常标准库异常类 抛出异常 throw 异常对象可以抛出基本类型的对象&#xff0c;如:throw -1;throw "内存分配失败!";也可以抛出类类…

【C语言:动态内存管理】

文章目录 前言1.malloc2.free3.calloc4.realloc5.动态内存常见错误6.动态内存经典笔试题分析7.柔性数组8.C/C中的内存区域划分 前言 文章的标题是动态内存管理&#xff0c;那什么是动态内存管理&#xff1f;为什么有动态内存管理呢&#xff1f; 回顾一下以前学的知识&#xff…