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
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相关的一切资源。