宁波网站建设公司地址,企业网站的布局类型,网站好坏标准,个人 网站建设方案书 备案一、Window 的属性 Window的属性定义在WindowManager的内部类LayoutParams中#xff0c;了解Window的属性能够更好的理解WMS的内部原理。Window的属性有很多种#xff0c;与应用开发最密切的有三种#xff0c;它们分别是Type(Window的类型)、Flag(Window的标志)和SoftInputM…
一、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到99Sub子窗口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 到 99public 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 到 1999public 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 到 2999public 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_WINDOW1;Deprecatedpublic static final int TYPE_PHONE FIRST_SYSTEM_WINDOW2;Deprecatedpublic static final int TYPE_SYSTEM_ALERT FIRST_SYSTEM_WINDOW3;public static final int TYPE_KEYGUARD FIRST_SYSTEM_WINDOW4;Deprecatedpublic static final int TYPE_TOAST FIRST_SYSTEM_WINDOW5;Deprecatedpublic static final int TYPE_SYSTEM_OVERLAY FIRST_SYSTEM_WINDOW6;Deprecatedpublic static final int TYPE_PRIORITY_PHONE FIRST_SYSTEM_WINDOW7;public static final int TYPE_SYSTEM_DIALOG FIRST_SYSTEM_WINDOW8;public static final int TYPE_KEYGUARD_DIALOG FIRST_SYSTEM_WINDOW9;Deprecatedpublic static final int TYPE_SYSTEM_ERROR FIRST_SYSTEM_WINDOW10;public static final int TYPE_INPUT_METHOD FIRST_SYSTEM_WINDOW11;public static final int TYPE_INPUT_METHOD_DIALOG FIRST_SYSTEM_WINDOW12;
// 壁纸public static final int TYPE_WALLPAPER FIRST_SYSTEM_WINDOW13;public static final int TYPE_STATUS_BAR_PANEL FIRST_SYSTEM_WINDOW14;public static final int TYPE_SECURE_SYSTEM_OVERLAY FIRST_SYSTEM_WINDOW15;public static final int TYPE_DRAG FIRST_SYSTEM_WINDOW16;public static final int TYPE_STATUS_BAR_SUB_PANEL FIRST_SYSTEM_WINDOW17;public static final int TYPE_POINTER FIRST_SYSTEM_WINDOW18;
// 导航栏public static final int TYPE_NAVIGATION_BAR FIRST_SYSTEM_WINDOW19;
// 音量条public static final int TYPE_VOLUME_OVERLAY FIRST_SYSTEM_WINDOW20;public static final int TYPE_BOOT_PROGRESS FIRST_SYSTEM_WINDOW21;public static final int TYPE_INPUT_CONSUMER FIRST_SYSTEM_WINDOW22;public static final int TYPE_NAVIGATION_BAR_PANEL FIRST_SYSTEM_WINDOW24;public static final int TYPE_DISPLAY_OVERLAY FIRST_SYSTEM_WINDOW26;public static final int TYPE_MAGNIFICATION_OVERLAY FIRST_SYSTEM_WINDOW27;public static final int TYPE_PRIVATE_PRESENTATION FIRST_SYSTEM_WINDOW30;public static final int TYPE_VOICE_INTERACTION FIRST_SYSTEM_WINDOW31;public static final int TYPE_ACCESSIBILITY_OVERLAY FIRST_SYSTEM_WINDOW32;public static final int TYPE_VOICE_INTERACTION_STARTING FIRST_SYSTEM_WINDOW33;public static final int TYPE_DOCK_DIVIDER FIRST_SYSTEM_WINDOW34;public static final int TYPE_QS_DIALOG FIRST_SYSTEM_WINDOW35;
// 截图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.flagsWindowManager.LayoutParams.FLAG_FULLSCREEN;WindowManager mWindowManager (WindowManager) getSystemService(Context.WINDOW_SERVICE); TextView mTextViewnew 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的类型一致;在创建系统类型的窗口时不需要提供一个有效的TokenWMS会隐式地为其声明一个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对应的窗口是应用窗口;PhoneWindowContextMenuOptionMenu是常用的子窗口;像Toast和系统警告提示框(如ANR)就是系统窗口还有很多应用的悬浮窗也属于系统窗口; Surface 的作用 在Android中一个窗口会独占一个SurfaceSurface其实就是一个画布应用程序通过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内部的mViews、mRoots、mParams、mDyingViews分别管理窗口的试图、主线程、布局参数以及死亡过程中的视图ViewRootImpl持有Session的代理端与WMS通信 /frameworks/base/core/java/android/app/ActivityThread.java
// 执行 handleResumeActivity Overridepublic void handleResumeActivity(ActivityClientRecord r, boolean finalStateRequest,boolean isForward, String reason) {unscheduleGcIdler();mSomeActivitiesChanged true;// 先执行 performResumeActivityif (!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 为 trueboolean willBeVisible !a.mStartedActivity;if (!willBeVisible) {willBeVisible ActivityClient.getInstance().willActivityBeVisible(a.getActivityToken());}if (r.window null !a.mFinished willBeVisible) {// 获取的对象是 PhoneWindowr.window r.activity.getWindow();
// decor 是 new DecorView 对象View decor r.window.getDecorView();// DecorView 设置不可见decor.setVisibility(View.INVISIBLE);// 在lauchactivity时候分析activity.getWindowManager 是 WindowManagerImplViewManager wm a.getWindowManager();WindowManager.LayoutParams l r.window.getAttributes();// 设置 activity 的 mDecor 为DecorView 对象,先 install。。。a.mDecor decor;// 这里设置 layout 的类型为 TYPE_BASE_APPLICATIONl.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 dont 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 VisibleForTestingpublic boolean performResumeActivity(ActivityClientRecord r, boolean finalStateRequest,String reason) {if (r.getLifecycleState() ON_RESUME) {
// finalStateRequest 为 trueif (!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_resumer.activity.performResume(r.startsNotResumed, reason);r.state null;r.persistentState null;
// 设置状态为 ON_RESUMEr.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 mParamsViewRoot.setView(xx)requestLayout // 检查主线程scheduleTraversalssendEmptyMessagehandleMessageperformTraversals // 2.11 测量 布局 绘制ViewRoot.relayoutWindowIWindowSession.relayout // 参考relayout的调用栈drawView.drawscheduleTralScheduled // try againmWindowSession.addToDisplay // 2.15 与requestLayout同级// sWindowSession.addWMS.addWindow // 2.16new WindowState // WindowState.attach // Session.windowAddedLockednew 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();Overridepublic void addView(NonNull View view, NonNull ViewGroup.LayoutParams params) {applyTokens(params);// WindowManagerGlobal 增加 viewmParentWindow 为 PhoneWindowmGlobal.addView(view, params, mContext.getDisplayNoVerify(), mParentWindow,mContext.getUserId());}
// WindowManagerGlobal 增加 viewmParentWindow 为 PhoneWindow
/frameworks/base/core/java/android/view/WindowManagerGlobal.java
// WindowManagerGlobal 是单例模式UnsupportedAppUsagepublic 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)) {// Dont wait for MSG_DIE to make its way through roots 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-2ViewRootImpl 设置 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 addedmPerformContentCapture true; // also true for the first time the view is addedmAdded false;// 创建 View.AttachInfo 对象传入 WindowSessionmAttachInfo 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为事件传递相关的类管理窗口焦点focusW代表当前操作的窗口, 是ViewRootImpl的内部类且持有ViewRootImpl的弱引用 // 1-5-2-2ViewRootImpl 设置 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) {
// 缓存 decorviewmView view;
。。。mSoftInputMode attrs.softInputMode;mWindowAttributesChanged true;// 设置 mRootView 为 decorviewmAttachInfo.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走绘制三大流程requestLayoutrequestLayout();。。。。try {mOrigWindowType mWindowAttributes.type;mAttachInfo.mRecomputeGlobalAttributes true;collectViewAttributes();adjustLayoutParamsForCompatibility(mWindowAttributes);controlInsetsForCompatibility(mWindowAttributes);// 2与wms 通信增加 windowaddToDisplayAsUserres mWindowSession.addToDisplayAsUser(mWindow, mWindowAttributes,getHostVisibility(), mDisplay.getDisplayId(), userId,mInsetsController.getRequestedVisibility(), inputChannel, mTempInsets,mTempControls);// 1请求vysnc走绘制三大流程requestLayout Overridepublic 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 通信增加 windowaddToDisplayAsUser
/frameworks/base/services/core/java/com/android/server/wm/Session.java
// session 作为连接 wms 的中介Overridepublic 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 对象 getDisplayContentOrCreatefinal 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 为falsefinal boolean hasParent parentWindow ! null;// 没有执行 addWindowToken返回的 token 为nullWindowToken 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去 打开InputChannelfinal 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 数组增加这个 winstateif (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 中增加自己addWindowwin.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 doesnt have a frame yet. Dont let this window cause the insets change.displayContent.getInsetsStateController().updateAboveInsetsState(win, false /* notifyInsetsChanged */);getInsetsSourceControls(win, outActiveControls);} addToDisplay方法中会调用了WMS的addWindow方法并将自身也就是Session作为参数传了进去每个应用程序进程都会对应一个SessionWMS会用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这里返回是 nullfinal WindowToken wToken mRoot.getWindowToken(token);if (wToken ! null) {return wToken.getDisplayContent();}}// 调用 RootWindowContainer返回 DisplayContent 对象return mRoot.getDisplayContentOrCreate(displayId);}// TODO: Look into consolidating with getDisplayContent()NullableDisplayContent 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 获取到 DisplayContentfinal DisplayContent dc mChildren.get(i);// 需要调用 addWindowToken才有对应的 WindowTokenfinal WindowToken wtoken dc.getWindowToken(binder);if (wtoken ! null) {return wtoken;}}return null;}
// mChildren 是再父类WindowContainer.java addChild 赋值的514 protected void addChild(E child, ComparatorE 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 cant 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 }
// 在 系统进程初始化的时候有 setWindowManagervoid 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);
// 增加这个 childaddChild(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;WindowTypeprivate final int mType;private boolean mPersistOnEmpty;private DisplayContent mDisplayContent;private boolean mOwnerCanManageAppTokens;private boolean mRoundedCornerOverlay;private boolean mFromClientToken;Nullableprivate 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() {Overridepublic void wakeUp(long time, WakeReason int reason, String details) {service.mPowerManager.wakeUp(time, reason, details);}Overridepublic 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 的 WmClient c;mAppOp appOp;mToken token;
// 为 nullmActivityRecord mToken.asActivityRecord();mOwnerUid ownerId;mShowUserId showUserId;mOwnerCanAddInternalSystemWindow ownerCanAddInternalSystemWindow;mWindowId new WindowId(this);mAttrs.copyFrom(a);mLastSurfaceInsets.set(mAttrs.surfaceInsets);mViewVisibility viewVisibility;// policy是 PhoneWindowManagermPolicy 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》 11000mBaseLayer 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;}
// 为 falsemIsFloatingLayer 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 nativeCreateInputChannelmInputChannel 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. */UnsupportedAppUsagepublic SurfaceSession() {mNativeClient nativeCreate();}
/frameworks/base/core/jni/android_view_SurfaceSession.cppstatic jlong nativeCreate(JNIEnv* env, jclass clazz) {
// 创建 SurfaceComposerClient 对象SurfaceComposerClient* client new SurfaceComposerClient();client-incStrong((void*)nativeCreate);
// 返回引用给java 层return reinterpret_castjlong(client);
}
// 创建 SurfaceComposerClient 对象/frameworks/native/libs/gui/SurfaceComposerClient.cppSurfaceComposerClient::SurfaceComposerClient(): mStatus(NO_INIT)
{
}// 初始化对象时会调用 onFirstRef
void SurfaceComposerClient::onFirstRef() {
// 获取与surfaceflinger 通信的客户端spISurfaceComposer sf(ComposerService::getComposerService());if (sf ! nullptr mStatus NO_INIT) {spISurfaceComposerClient 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));// 这里为 falseif (win.isChildWindow()) {// Child windows are added to their parent windows.return;}// 先创建个 SurfaceControl设置了 setSurfaceControlSurfaceControlif (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 的状态是隐藏的 mHiddenmWin.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());
// 销毁surfacedestroySurface(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 设置显示状态为 falsemSurfaceController.setShown(false);}// 回收 mSurfaceControllermSurfaceController null;// 设置绘制状态为 NO_SURFACEmDrawState NO_SURFACE;}