Android8.0.0-r4——WindowManagerService

1.WMS概述


WMS是系统的其他服务,无论对于应用开发还是Framework开发都是重点的知识,它的职责有很多,主要有以下几点:

窗口管理:WMS是窗口的管理者,它负责窗口的启动、添加和删除,另外窗口的大小和层级也是由WMS进行管理的。窗口管理的核心成员有DisplayContent、WindowToken和WindowState。
窗口动画:窗口间进行切换时,使用窗口动画可以显得更炫一些,窗口动画由WMS的动画子系统来负责,动画子系统的管理者为WindowAnimator。
输入系统的中转站:通过对窗口的触摸从而产生触摸事件,InputManagerService(IMS)会对触摸事件进行处理,它会寻找一个最合适的窗口来处理触摸反馈信息,WMS是窗口的管理者,因此,WMS“理所应当”的成为了输入系统的中转站。

Surface管理:窗口并不具备有绘制的功能,因此每个窗口都需要有一块Surface来供自己绘制。为每个窗口分配Surface是由WMS来完成的


2.WMS的启动及其初始化

WMS是在systemServer启动其他服务的时候启动

2.1 在SystemServer中启动WMS服务

2.1.1 SystemServer.main

代码路径:/frameworks/base/services/java/com/android/server/SystemServer.java

(http://androidxref.com/8.0.0_r4/xref/frameworks/base/services/java/com/android/server/SystemServer.java) 
259    public static void main(String[] args) {
260        new SystemServer().run();
261    }
 

在main中创建一个SystemServer的匿名对象并调用它的run函数

263    public SystemServer() {
264        // Check for factory test mode.
265        mFactoryTestMode = FactoryTest.getMode();
266        // Remember if it's runtime restart(when sys.boot_completed is already set) or reboot
267        mRuntimeRestart = "1".equals(SystemProperties.get("sys.boot_completed"));
268    }

创建匿名对象,在构造函数中得到启动模式和sys.boot_completed的属性。用来判断是否为正常模式启动和boot启动是否完成。在run函数中会对系统属性进行初始化设置,并启动一些关键的服务:

391        // Start services.
392        try {
393            traceBeginAndSlog("StartServices");
394            startBootstrapServices();
395            startCoreServices();//BatteryService在startCoreServices中创建的
396            startOtherServices();
397            SystemServerInitThreadPool.shutdown();

例如此次要说明的WMS服务就在startOtherServices()函数中

 
 
671    private void startOtherServices() {
              ..........................................
806
807            traceBeginAndSlog("InitWatchdog");
808            final Watchdog watchdog = Watchdog.getInstance();//得到看门狗实例
809            watchdog.init(context, mActivityManagerService);//进行初始化
810            traceEnd();
811
812            traceBeginAndSlog("StartInputManagerService");
813            inputManager = new InputManagerService(context);//创建了IMS,并赋值给IMS类型的inputManager对象
814            traceEnd();
815
816            traceBeginAndSlog("StartWindowManagerService");
817            // WMS needs sensor service ready
818            ConcurrentUtils.waitForFutureNoInterrupt(mSensorServiceStart, START_SENSOR_SERVICE);
819            mSensorServiceStart = null;
820            wm = WindowManagerService.main(context, inputManager,
821                    mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
822                    !mFirstBoot, mOnlyCore, new PhoneWindowManager());//执行了WMS的main方法
823            ServiceManager.addService(Context.WINDOW_SERVICE, wm);//WMS注册到ServiceManager
824            ServiceManager.addService(Context.INPUT_SERVICE, inputManager);//IMS注册到ServiceManager
825            traceEnd();
826
          ........................................................
909        traceBeginAndSlog("MakeDisplayReady");
910        try {
911            wm.displayReady();//初始化显示信息
912        } catch (Throwable e) {
913            reportWtf("making display ready", e);
914        }
915        traceEnd();
916
           .......................................................
1569
1570        traceBeginAndSlog("MakeWindowManagerServiceReady");
1571        try {
1572            wm.systemReady();//通知WMS,系统的初始化工作已经完成,其内部调用了WindowManagerPolicy的systemReady方法
1573        } catch (Throwable e) {
1574            reportWtf("making Window Manager Service ready", e);
1575        }
1576        traceEnd();
1577
            ...............................................
1824    }

在820行调用了WMS的main方法,是启动的核心。

2.2 WMS.main

代码路径:/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
(http://androidxref.com/8.0.0_r4/xref/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java) 

977    public static WindowManagerService main(final Context context, final InputManagerService im,
978            final boolean haveInputMethods, final boolean showBootMsgs, final boolean onlyCore,
979            WindowManagerPolicy policy) {
            //调用了DisplayThread的getHandler方法,用来得到DisplayThread的Handler实例
980        DisplayThread.getHandler().runWithScissors(() ->//使用了Java8中的Lambda表达式,
981                sInstance = new WindowManagerService(context, im, haveInputMethods, showBootMsgs,
982                        onlyCore, policy), 0);//
983        return sInstance;
984    }

lambda表达式允许你通过表达式来代替功能接口(本人不建议这么写,兼容性太差,太晦涩难懂了)。Lambda表达式的语法基本语法:(parameters) -> expression或(parameters) ->{ statements; }

DisplayThread是一个单例的前台线程,这个线程用来处理需要低延时显示的相关操作,并只能由WindowManager、DisplayManager和InputManager实时执行快速操作

代码路径:/frameworks/base/core/java/android/os/Handler.java
(http://androidxref.com/8.0.0_r4/xref/frameworks/base/core/java/android/os/Handler.java) 

491    public final boolean runWithScissors(final Runnable r, long timeout) {
492        if (r == null) {
493            throw new IllegalArgumentException("runnable must not be null");
494        }
495        if (timeout < 0) {
496            throw new IllegalArgumentException("timeout must be non-negative");
497        }
498
499        if (Looper.myLooper() == mLooper) {
500            r.run();
501            return true;
502        }
503
504        BlockingRunnable br = new BlockingRunnable(r);
505        return br.postAndWait(this, timeout);
506    }

开头对传入的Runnable和timeout进行了判断,如果Runnable为null或者timeout小于0则抛出异常。

在500行根据每个线程只有一个Looper的原理来判断当前的线程(”system_server”线程)是否是Handler所指向的线程(”android.display”线程),如果是则直接执行Runnable的run方法,如果不是则调用BlockingRunnable的postAndWait方法,并将当前线程的Runnable作为参数传进去

代码路径:/frameworks/base/core/java/android/os/Handler.java
(http://androidxref.com/8.0.0_r4/xref/frameworks/base/core/java/android/os/Handler.java) 

798    private static final class BlockingRunnable implements Runnable {
799        private final Runnable mTask;
800        private boolean mDone;
801
802        public BlockingRunnable(Runnable task) {
803            mTask = task;
804        }
805
806        @Override
807        public void run() {
808            try {
809                mTask.run();
810            } finally {
811                synchronized (this) {
812                    mDone = true;
813                    notifyAll();
814                }
815            }
816        }
817
818        public boolean postAndWait(Handler handler, long timeout) {
819            if (!handler.post(this)) {//将当前的BlockingRunnable添加到Handler的任务队列中
820                return false;
821            }
822
823            synchronized (this) {
824                if (timeout > 0) {
825                    final long expirationTime = SystemClock.uptimeMillis() + timeout;
826                    while (!mDone) {
827                        long delay = expirationTime - SystemClock.uptimeMillis();
828                        if (delay <= 0) {
829                            return false; // timeout
830                        }
831                        try {
832                            wait(delay);
833                        } catch (InterruptedException ex) {
834                        }
835                    }
836                } else {
837                    while (!mDone) {
838                        try {
839                            wait();
840                        } catch (InterruptedException ex) {
841                        }
842                    }
843                }
844            }
845            return true;
846        }
847    }
848}
849
前面runWithScissors方法的第二个参数为0,因此timeout等于0,这样如果mDone为false的话会一直调用839行的wait方法使得当前线程(”system_server”线程)进入等待状态,那么等待的是哪个线程呢?在809行执行了传入的Runnable的run方法(运行在”android.display”线程),执行完毕后在finally代码块中将mDone设置为true,并调用notifyAll方法唤醒处于等待状态的线程,这样就不会继续调用839行的wait方法。因此得出结论,”system_server”线程线程等待的就是”android.display”线程,一直到”android.display”线程执行完毕再执行”system_server”线程,这是因为”android.display”线程内部执行了WMS的创建,显然WMS的创建优先级更高些。 
 

2.3 WMS的构造方法

代码路径:/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java

(http://androidxref.com/8.0.0_r4/xref/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java)  
997    private WindowManagerService(Context context, InputManagerService inputManager,
          ..........................................................
1018        mInputManager = inputManager; //保存传进来的IMS,这样WMS就持有了IMS的引用
           ....................................
          //通过DisplayManager的getDisplays方法得到Display数组(每个显示设备都有一个Display实例),接着遍历Display数组
1038        mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
1039        mDisplays = mDisplayManager.getDisplays();
1040        for (Display display : mDisplays) {
1041            createDisplayContentLocked(display);//将Display封装成DisplayContent,DisplayContent用来描述一快屏幕
1042        }
1043
           .......................................................
1082
1083        mActivityManager = ActivityManager.getService();//得到AMS实例,并赋值给mActivityManager ,这样WMS就持有了AMS的引用
           .................................................
1118
1119        mAnimator = new WindowAnimator(this);//创建了WindowAnimator,它用于管理所有的窗口动画
1120
1121        mAllowTheaterModeWakeFromLayout = context.getResources().getBoolean(
1122                com.android.internal.R.bool.config_allowTheaterModeWakeFromWindowLayout);
1123
1124
1125        LocalServices.addService(WindowManagerInternal.class, new LocalService());
1126        initPolicy();//初始化了窗口管理策略的接口类WindowManagerPolicy(WMP),它用来定义一个窗口策略所要遵循的通用规范
1127
1128        // Add ourself to the Watchdog monitors.
1129        Watchdog.getInstance().addMonitor(this);
1130
1131        openSurfaceTransaction();
1132        try {
1133            createWatermarkInTransaction();
1134        } finally {
1135            closeSurfaceTransaction();
1136        }
1137
1138        showEmulatorDisplayOverlayIfNeeded();
1139    }

在1129行将自身也就是WMS通过addMonitor方法添加到Watchdog中,Watchdog用来监控系统的一些关键服务的运行状况(比如传入的WMS的运行状况),这些被监控的服务都会实现Watchdog.Monitor接口。Watchdog每分钟都会对被监控的系统服务进行检查,如果被监控的系统服务出现了死锁,则会杀死Watchdog所在的进程,也就是SystemServer进程

代码路径:/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
(http://androidxref.com/8.0.0_r4/xref/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java) 

986    private void initPolicy() {
987        UiThread.getHandler().runWithScissors(new Runnable() {
988            @Override
989            public void run() {
990                WindowManagerPolicyThread.set(Thread.currentThread(), Looper.myLooper());
991
992                mPolicy.init(mContext, WindowManagerService.this, WindowManagerService.this);
993            }
994        }, 0);
995    }

initPolicy方法和此前讲的WMS的main方法的实现类似,在992行执行了WMP的init方法,WMP是一个接口,init方法的具体实现在PhoneWindowManager(PWM)中。PWM的init方法运行在”android.ui”线程中,它的优先级要高于initPolicy方法所在的”android.display”线程,因此”android.display”线程要等PWM的init方法执行完毕后,处于等待状态的”android.display”线程才会被唤醒从而继续执行下面的代码

涉及到的3个线程,分别是”system_server”、”android.display”和”android.ui”,这三个线程之间的关系。

“system_server”线程中会调用WMS的main方法,main方法中会创建WMS,创建WMS的过程运行在”android.display”线程中,它的优先级更高一些,因此要等创建WMS完毕后才会唤醒处于等待状态的”system_server”线程。 
WMS初始化时会执行initPolicy方法,initPolicy方法会调用PWM的init方法,这个init方法运行在”android.ui”线程,并且优先级更高,因此要先执行完PWM的init方法后,才会唤醒处于等待状态的”android.display”线程。 
PWM的init方法执行完毕后会接着执行运行在”system_server”线程的代码,例如WMS的 systemReady方法。


3.Window的添加

3.1 WMS的重要成员

WMS的重要成员是指WMS中的重要的成员变量:
代码路径:/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java

(http://androidxref.com/8.0.0_r4/xref/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java) 

403    final WindowManagerPolicy mPolicy;
404
405    final IActivityManager mActivityManager;
406    final ActivityManagerInternal mAmInternal;
407
408    final AppOpsManager mAppOps;
409
410    final DisplaySettings mDisplaySettings;
411
          ..........................................................
418    final ArraySet<Session> mSessions = new ArraySet<>();
419
420    /**
421     * Mapping from an IWindow IBinder to the server's Window object.
422     * This is also used as the lock for all of our state.
423     * NOTE: Never call into methods that lock ActivityManagerService while holding this object.
424     */
425    final WindowHashMap mWindowMap = new WindowHashMap();
426
427    /**
428     * List of window tokens that have finished starting their application,
429     * and now need to have the policy remove their windows.
430     */
431    final ArrayList<AppWindowToken> mFinishedStarting = new ArrayList<>();
432
433    /**
434     * List of window tokens that have finished drawing their own windows and
435     * no longer need to show any saved surfaces. Windows that's still showing
436     * saved surfaces will be cleaned up after next animation pass.
437     */
438    final ArrayList<AppWindowToken> mFinishedEarlyAnim = new ArrayList<>();
439
440    /**
441     * List of app window tokens that are waiting for replacing windows. If the
442     * replacement doesn't come in time the stale windows needs to be disposed of.
443     */
444    final ArrayList<AppWindowToken> mWindowReplacementTimeouts = new ArrayList<>();
445
446    /**
447     * Windows that are being resized.  Used so we can tell the client about
448     * the resize after closing the transaction in which we resized the
449     * underlying surface.
450     */
451    final ArrayList<WindowState> mResizingWindows = new ArrayList<>();
452
453    /**
454     * Windows whose animations have ended and now must be removed.
455     */
456    final ArrayList<WindowState> mPendingRemove = new ArrayList<>();
457
458    /**
459     * Used when processing mPendingRemove to avoid working on the original array.
460     */
461    WindowState[] mPendingRemoveTmp = new WindowState[20];
462
463    /**
464     * Windows whose surface should be destroyed.
465     */
466    final ArrayList<WindowState> mDestroySurface = new ArrayList<>();
467
468    /**
469     * Windows with a preserved surface waiting to be destroyed. These windows
470     * are going through a surface change. We keep the old surface around until
471     * the first frame on the new surface finishes drawing.
472     */
473    final ArrayList<WindowState> mDestroyPreservedSurface = new ArrayList<>();
474
        ..........................................
611
612    final H mH = new H();
613
614    /**
615     * Handler for things to run that have direct impact on an animation, i.e. animation tick,
616     * layout, starting window creation, whereas {@link H} runs things that are still important, but
617     * not as critical.
618     */
619    final Handler mAnimationHandler = new Handler(AnimationThread.getHandler().getLooper());
620
621    WindowState mCurrentFocus = null;
622    WindowState mLastFocus = null;
623
624    /** Windows added since {@link #mCurrentFocus} was set to null. Used for ANR blaming. */
625    private final ArrayList<WindowState> mWinAddedSinceNullFocus = new ArrayList<>();
626    /** Windows removed since {@link #mCurrentFocus} was set to null. Used for ANR blaming. */
627    private final ArrayList<WindowState> mWinRemovedSinceNullFocus = new ArrayList<>();
628
629    /** This just indicates the window the input method is on top of, not
630     * necessarily the window its input is going to. */
631    WindowState mInputMethodTarget = null;
632
633    /** If true hold off on modifying the animation layer of mInputMethodTarget */
634    boolean mInputMethodTargetWaitingAnim;
635
636 
.............................................
710
711    final InputManagerService mInputManager;
...............................................
738    final WindowAnimator     mAnimator;
 

WMS的部分成员变量:

mPolicy:WindowManagerPolicy WindowManagerPolicy(WMP)类型的变量。WindowManagerPolicy是窗口管理策略的接口类,用来定义一个窗口策略所要遵循的通用规范,并提供了WindowManager所有的特定的UI行为。它的具体实现类为PhoneWindowManager,这个实现类在WMS创建时被创建。WMP允许定制窗口层级和特殊窗口类型以及关键的调度和布局。

mSessions:ArraySet ArraySet类型的变量,元素类型为Session。主要用于进程间通信,其他的应用程序进程想要和WMS进程进行通信就需要经过Session,并且每个应用程序进程都会对应一个Session,WMS保存这些Session用来记录所有向WMS提出窗口管理服务的客户端。 mWindowMap:WindowHashMap WindowHashMap类型的变量,WindowHashMap继承了HashMap,它限制了HashMap的key值的类型为IBinder,value值的类型为WindowState。WindowState用于保存窗口的信息,在WMS中它用来描述一个窗口。综上得出结论,mWindowMap就是用来保存WMS中各种窗口的集合。

mFinishedStarting:ArrayList ArrayList类型的变量,元素类型为AppWindowToken,它是WindowToken的子类。要想理解mFinishedStarting的含义,需要先了解WindowToken是什么。WindowToken主要有两个作用:

  • 可以理解为窗口令牌,当应用程序想要向WMS申请新创建一个窗口,则需要向WMS出示有效的WindowToken。AppWindowToken作为WindowToken的子类,主要用来描述应用程序的WindowToken结构, 应用程序中每个Activity都对应一个AppWindowToken。
  • WindowToken会将相同组件(比如Acitivity)的窗口(WindowState)集合在一起,方便管理。

mFinishedStarting就是用于存储已经完成启动的应用程序窗口(比如Acitivity)的AppWindowToken的列表。 除了mFinishedStarting,还有类似的mFinishedEarlyAnim和mWindowReplacementTimeouts,其中mFinishedEarlyAnim存储了已经完成窗口绘制并且不需要展示任何已保存surface的应用程序窗口的AppWindowToken。mWindowReplacementTimeout存储了等待更换的应用程序窗口的AppWindowToken,如果更换不及时,旧窗口就需要被处理。

mResizingWindows:ArrayList ArrayList类型的变量,元素类型为WindowState。 mResizingWindows是用来存储正在调整大小的窗口的列表。与mResizingWindows类似的还有mPendingRemove、mDestroySurface和mDestroyPreservedSurface等等。其中mPendingRemove是在内存耗尽时设置的,里面存有需要强制删除的窗口。mDestroySurface里面存有需要被Destroy的Surface。mDestroyPreservedSurface里面存有窗口需要保存的等待销毁的Surface,为什么窗口要保存这些Surface?这是因为当窗口经历Surface变化时,窗口需要一直保持旧Surface,直到新Surface的第一帧绘制完成。

mAnimator:WindowAnimator WindowAnimator类型的变量,用于管理窗口的动画以及特效动画。

mH:H H类型的变量,系统的Handler类,用于将任务加入到主线程的消息队列中,这样代码逻辑就会在主线程中执行。

mInputManager:InputManagerService InputManagerService类型的变量,输入系统的管理者。InputManagerService(IMS)会对触摸事件进行处理,它会寻找一个最合适的窗口来处理触摸反馈信息,WMS是窗口的管理者,因此,WMS“理所应当”的成为了输入系统的中转站,WMS包含了IMS的引用不足为怪。

2.Window的添加过程(WMS部分)

我们知道Window的操作分为两大部分,一部分是WindowManager处理部分,另一部分是WMS处理部分,如下所示。 无论是系统窗口还是Activity,它们的Window的添加过程都会调用WMS的addWindow方法

addWindow方法总结

addWindow方法分了3个部分来进行讲解,主要就是做了下面4件事: 1. 对所要添加的窗口进行检查,如果窗口不满足一些条件,就不会再执行下面的代码逻辑。 2. WindowToken相关的处理,比如有的窗口类型需要提供WindowToken,没有提供的话就不会执行下面的代码逻辑,有的窗口类型则需要由WMS隐式创建WindowToken。 3. WindowState的创建和相关处理,将WindowToken和WindowState相关联。 4. 创建和配置DisplayContent,完成窗口添加到系统前的准备工作。

4.Window的删除

要删除Window需要先调用WindowManagerImpl的removeView方法,removeView方法中又会调用WindowManagerGlobal的removeView方法。

4.1 WindowManagerGlobal.removeView代码路径:/frameworks/base/core/java/android/view/WindowManagerGlobal.java(http://androidxref.com/8.0.0_r4/xref/frameworks/base/core/java/android/view/WindowManagerGlobal.java) 

388    public void removeView(View view, boolean immediate) {
389        if (view == null) {
390            throw new IllegalArgumentException("view must not be null");
391        }
392
393        synchronized (mLock) {
394            int index = findViewLocked(view, true);//找到要V在View列表中的索引
395            View curView = mRoots.get(index).getView();
396            removeViewLocked(index, immediate);//调用了removeViewLocked方法并将这个索引传进去
397            if (curView == view) {
398                return;
399            }
400
401            throw new IllegalStateException("Calling with view " + view
402                    + " but the ViewAncestor is attached to " + curView);
403        }
404    }


4.2 WindowManagerGlobal.removeViewLocked
代码路径:/frameworks/base/core/java/android/view/WindowManagerGlobal.java
(http://androidxref.com/8.0.0_r4/xref/frameworks/base/core/java/android/view/WindowManagerGlobal.java) 

448    private void removeViewLocked(int index, boolean immediate) {
449        ViewRootImpl root = mRoots.get(index);//根据传入的索引在ViewRootImpl列表中获得V的ViewRootImpl
450        View view = root.getView();
451
452        if (view != null) {
453            InputMethodManager imm = InputMethodManager.getInstance();//得到InputMethodManager实例
454            if (imm != null) {//调用InputMethodManager的windowDismissed方法来结束V的输入法相关的逻辑
455                imm.windowDismissed(mViews.get(index).getWindowToken());
456            }
457        }
458        boolean deferred = root.die(immediate);//调用ViewRootImpl 的die方法
459        if (view != null) {
460            view.assignParent(null);
461            if (deferred) {
462                mDyingViews.add(view);
463            }
464        }
465    }


4.3 ViewRootImpl.die
代码路径:/frameworks/base/core/java/android/view/ViewRootImpl.java
(http://androidxref.com/8.0.0_r4/xref/frameworks/base/core/java/android/view/ViewRootImpl.java) 

6283    boolean die(boolean immediate) {//die方法需要立即执行并且此时ViewRootImpl不在执行performTraversals方法
6284        // Make sure we do execute immediately if we are in the middle of a traversal or the damage
6285        // done by dispatchDetachedFromWindow will cause havoc on return.
6286        if (immediate && !mIsInTraversal) {
6287            doDie();
6288            return false;
6289        }
6290
6291        if (!mIsDrawing) {
6292            destroyHardwareRenderer();
6293        } else {
6294            Log.e(mTag, "Attempting to destroy the window while drawing!\n" +
6295                    "  window=" + this + ", title=" + mWindowAttributes.getTitle());
6296        }
6297        mHandler.sendEmptyMessage(MSG_DIE);
6298        return true;
6299    }

在6286行如果immediate为ture(需要立即执行),并且mIsInTraversal值为false则执行6287行的代码,mIsInTraversal在执行ViewRootImpl的performTraversals方法时会被设置为true,在performTraversals方法执行完时被设置为false,因此6286行可以理解为die方法需要立即执行并且此时ViewRootImpl不在执行performTraversals方法。

4.4 ViewRootImpl.doDie
代码路径:/frameworks/base/core/java/android/view/ViewRootImpl.java

(http://androidxref.com/8.0.0_r4/xref/frameworks/base/core/java/android/view/ViewRootImpl.java) 

6301    void doDie() {
6302        checkThread();//检查执行doDie方法的线程的正确性
6303        if (LOCAL_LOGV) Log.v(mTag, "DIE in " + this + " of " + mSurface);
6304        synchronized (this) {
6305            if (mRemoved) {//用于防止doDie方法被重复调用
6306                return;
6307            }
6308            mRemoved = true;
6309            if (mAdded) {
6310                dispatchDetachedFromWindow();//V有子View就会调用dispatchDetachedFromWindow方法来销毁View
6311            }
6312
6313            if (mAdded && !mFirst) {//如果V有子View并且不是第一次被添加,就会执行后面的代码逻辑
6314                destroyHardwareRenderer();
6315
6316                if (mView != null) {
6317                    int viewVisibility = mView.getVisibility();
6318                    boolean viewVisibilityChanged = mViewVisibility != viewVisibility;
6319                    if (mWindowAttributesChanged || viewVisibilityChanged) {
6320                        // If layout params have been changed, first give them
6321                        // to the window manager to make sure it has the correct
6322                        // animation info.
6323                        try {
6324                            if ((relayoutWindow(mWindowAttributes, viewVisibility, false)
6325                                    & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) {
6326                                mWindowSession.finishDrawing(mWindow);
6327                            }
6328                        } catch (RemoteException e) {
6329                        }
6330                    }
6331
6332                    mSurface.release();
6333                }
6334            }
6335
6336            mAdded = false;
6337        }
6338        WindowManagerGlobal.getInstance().doRemoveView(this);//WindowManagerGlobal的doRemoveView方法
6339    }
6340


4.5 WindowManagerGlobal.doRemoveView
代码路径:/frameworks/base/core/java/android/view/WindowManagerGlobal.java

(http://androidxref.com/8.0.0_r4/xref/frameworks/base/core/java/android/view/WindowManagerGlobal.java) 

467    void doRemoveView(ViewRootImpl root) {
468        synchronized (mLock) {
469            final int index = mRoots.indexOf(root);
470            if (index >= 0) {
471                mRoots.remove(index);
472                mParams.remove(index);
473                final View view = mViews.remove(index);
474                mDyingViews.remove(view);
475            }
476        }
477        if (ThreadedRenderer.sTrimForeground && ThreadedRenderer.isAvailable()) {
478            doTrimForeground();
479        }
480    }

WindowManagerGlobal中维护了和 Window操作相关的三个列表,doRemoveView方法会从这三个列表中清除V对应的元素。在469行找到V对应的ViewRootImpl在ViewRootImpl列表中的索引,接着根据这个索引从ViewRootImpl列表、布局参数列表和View列表中删除与V对应的元素。 接着回到ViewRootImpl的doDie方法

4.6 ViewRootImpl.doRemoveView
代码路径:/frameworks/base/core/java/android/view/ViewRootImpl.java

(http://androidxref.com/8.0.0_r4/xref/frameworks/base/core/java/android/view/ViewRootImpl.java) 

3459    void dispatchDetachedFromWindow() {
      ........................................
3492        try {
3493            mWindowSession.remove(mWindow);
3494        } catch (RemoteException e) {
      ..................................
3507    }

dispatchDetachedFromWindow方法中主要调用了IWindowSession的remove方法,IWindowSession在Server端的实现为Session

4.7 Session.doRemoveView
代码路径:/frameworks/base/services/core/java/com/android/server/wm/Session.java

(http://androidxref.com/8.0.0_r4/xref/frameworks/base/services/core/java/com/android/server/wm/Session.java) 

211    public void remove(IWindow window) {
212        mService.removeWindow(this, window);
213    }


4.8 WindowManagerService.removeWindow
代码路径:/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService .java

(http://androidxref.com/8.0.0_r4/xref/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService .java) 

1682    void removeWindow(Session session, IWindow client) {
1683        synchronized(mWindowMap) {//获取Window对应的WindowState,WindowState用于保存窗口的信息
1684            WindowState win = windowForClientLocked(session, client, false);
1685            if (win == null) {
1686                return;
1687            }
1688            win.removeIfPossible();//调用WindowState的removeIfPossible方法
1689        }
1690    }


4.9 WindowState.removeIfPossible
代码路径:/frameworks/base/services/core/java/com/android/server/wm/WindowState.java

(http://androidxref.com/8.0.0_r4/xref/frameworks/base/services/core/java/com/android/server/wm/WindowState.java) 

1758    void removeIfPossible() {
1759        super.removeIfPossible();
1760        removeIfPossible(false /*keepVisibleDeadWindow*/);
1761    }
1762
1763    private void removeIfPossible(boolean keepVisibleDeadWindow) {
1764      //条件判断过滤,满足其中一个条件就会return,推迟删除操作
        ...........................................
1889        removeImmediately();
1890        // Removing a visible window will effect the computed orientation
1891        // So just update orientation if needed.
1892        if (wasVisible && mService.updateOrientationFromAppTokensLocked(false, displayId)) {
1893            mService.mH.obtainMessage(SEND_NEW_CONFIGURATION, displayId).sendToTarget();
1894        }
1895        mService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
1896        Binder.restoreCallingIdentity(origId);
1897    }

removeIfPossible方法和它的名字一样,并不是直接执行删除操作,而是进行多个条件判断过滤,满足其中一个条件就会return,推迟删除操作。比如这时V正在运行一个动画,这时就得推迟删除操作,直到动画完成。通过这些条件判断过滤就会执行1889行的removeImmediately方法


4.10 WindowState.removeImmediately
代码路径:/frameworks/base/services/core/java/com/android/server/wm/WindowState.java

(http://androidxref.com/8.0.0_r4/xref/frameworks/base/services/core/java/com/android/server/wm/WindowState.java) 

1713    @Override
1714    void removeImmediately() {
1715        super.removeImmediately();
1716
1717        if (mRemoved) {
1718            // Nothing to do.
1719            if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
1720                    "WS.removeImmediately: " + this + " Already removed...");
1721            return;
1722        }
1723
1724        mRemoved = true;
1725
1726        mWillReplaceWindow = false;
1727        if (mReplacementWindow != null) {
1728            mReplacementWindow.mSkipEnterAnimationForSeamlessReplacement = false;
1729        }
1730
1731        final DisplayContent dc = getDisplayContent();
1732        if (mService.mInputMethodTarget == this) {
1733            dc.computeImeTarget(true /* updateImeTarget */);
1734        }
1735
1736        final int type = mAttrs.type;
1737        if (WindowManagerService.excludeWindowTypeFromTapOutTask(type)) {
1738            dc.mTapExcludedWindows.remove(this);
1739        }
1740        mPolicy.removeWindowLw(this);
1741
1742        disposeInputChannel();
1743
1744        mWinAnimator.destroyDeferredSurfaceLocked();
1745        mWinAnimator.destroySurfaceLocked();
1746        mSession.windowRemovedLocked();
1747        try {
1748            mClient.asBinder().unlinkToDeath(mDeathRecipient, 0);
1749        } catch (RuntimeException e) {
1750            // Ignore if it has already been removed (usually because
1751            // we are doing this as part of processing a death note.)
1752        }
1753        //调用了WMS的postWindowRemoveCleanupLocked方法用于对V进行一些集中的清理工作
1754        mService.postWindowRemoveCleanupLocked(this);
1755    }
removeImmediately方法如同它的名字一样,用于立即进行删除操作。1717行的mRemoved为true意味着正在执行删除Window操作。在1740行如果当前要删除的Window是StatusBar或者NavigationBar就会将这个Window从对应的控制器中删除。在1746行会将V对应的Session从WMS的ArraySet<Session> mSessions中删除并清除Session对应的SurfaceSession资源(SurfaceSession是SurfaceFlinger的一个连接,通过这个连接可以创建1个或者多个Surface并渲染到屏幕上 )。

Window的删除过程可以简单的总结为以下4点: 
1. 检查删除线程的正确性,如果不正确就抛出异常。 
2. 从ViewRootImpl列表、布局参数列表和View列表中删除与V对应的元素。 
3. 判断是否可以直接执行删除操作,如果不能就推迟删除操作。 
4. 执行删除操作,清理和释放与V相关的一切资源。


  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值