什么是WindowState
WindowState表示一个窗口的所有属性,它是WMS中事实上的窗口.
其源码中定义为:
/** A window in the window manager. */
class WindowState extends WindowContainer<WindowState> implements WindowManagerPolicy.WindowState {
WindowState也就是WindowState是WMS中的一个窗口。
借用别人的一张图片来表示WindowState:
一个正在回放视频并弹出两个对话框的Activity为例,WindowToken与WindowState的意义如图:
WindowState与WindowToken的从属关系
通过上面这张图,我们可以知道,WindowState是在WMS中表示的任何一个窗口,也就是任何一个窗口,都有一个WindowState对象来表示此窗口。
WindowState的内容
我们查看WindowState的内容,可以使用命令:
adb shell dumpsys window windows
事实上,此命令可以查看手机所有的window的信息。
例如下面这个是短信列表界面的一个WindowState dump信息:
Window #9 Window{884cb45 u0 com.android.messaging/com.android.messaging.ui.conversationlist.ConversationListActivity}:
mDisplayId=0 stackId=3 mSession=Session{f1b7b8e 4307:u0a10065} mClient=android.os.BinderProxy@a512fbc
mOwnerUid=10065 mShowToOwnerOnly=true package=com.android.messaging appop=NONE
mAttrs={(0,36)(828xwrap) gr=BOTTOM CENTER sim={adjust=pan forwardNavigation} ty=APPLICATION fmt=TRANSLUCENT wanim=0x7f130015
fl=DIM_BEHIND ALT_FOCUSABLE_IM HARDWARE_ACCELERATED
vsysui=LIGHT_STATUS_BAR LIGHT_NAVIGATION_BAR}
Requested w=828 h=290 mLayoutSeq=220
mBaseLayer=21000 mSubLayer=0 mToken=AppWindowToken{3f9efb8 token=Token{2b272cc ActivityRecord{55a41e u0 com.android.messaging/.ui.conversationlist.ConversationListActivity t8}}}
mAppToken=AppWindowToken{3f9efb8 token=Token{2b272cc ActivityRecord{55a41e u0 com.android.messaging/.ui.conversationlist.ConversationListActivity t8}}}
mAppDied=false drawnStateEvaluated=true mightAffectAllDrawn=true
mViewVisibility=0x0 mHaveFrame=true mObscured=false
mSeq=0 mSystemUiVisibility=0x2010
mGivenContentInsets=[0,0][0,0] mGivenVisibleInsets=[0,0][0,0]
mFullConfiguration={1.0 ?mcc?mnc [zh_CN] ldltr sw720dp w960dp h648dp 320dpi lrg hdr land finger -keyb/v/h -nav/h winConfig={ mBounds=Rect(0, 0 - 1920, 1440) mAppBounds=Rect(0, 0 - 1920, 1344) mWindowingMode=fullscreen mDisplayWindowingMode=fullscreen mActivityType=standard mAlwaysOnTop=undefined mRotation=ROTATION_90} s.1}
mLastReportedConfiguration={1.0 ?mcc?mnc [zh_CN] ldltr sw720dp w960dp h648dp 320dpi lrg hdr land finger -keyb/v/h -nav/h winConfig={ mBounds=Rect(0, 0 - 1920, 1440) mAppBounds=Rect(0, 0 - 1920, 1344) mWindowingMode=fullscreen mDisplayWindowingMode=fullscreen mActivityType=standard mAlwaysOnTop=undefined mRotation=ROTATION_90} s.1}
mHasSurface=true isReadyForDisplay()=true mWindowRemovalAllowed=false
Frames: containing=[0,48][1920,1344] parent=[0,48][1920,1344]
display=[0,48][1920,1344] overscan=[0,48][1920,1344]
content=[546,1018][1374,1308] visible=[546,1018][1374,1308]
decor=[0,48][1920,1344]
outset=[0,0][0,0]
mFrame=[546,1018][1374,1308] last=[546,1018][1374,1308]
cutout=DisplayCutout{insets=Rect(0, 0 - 0, 0) boundingRect={Bounds=[Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0)]}} last=DisplayCutout{insets=Rect(0, 0 - 0, 0) boundingRect={Bounds=[Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0)]}}
Cur insets: overscan=[0,0][0,0] content=[0,0][0,0] visible=[0,0][0,0] stable=[0,0][0,0] outsets=[0,0][0,0] Lst insets: overscan=[0,0][0,0] content=[0,0][0,0] visible=[0,0][0,0] stable=[0,0][0,0] outset=[0,0][0,0]
surface=[0,0][0,0]
WindowStateAnimator{8de1dfd com.android.messaging/com.android.messaging.ui.conversationlist.ConversationListActivity}:
mAnimationIsEntrance=true mSurface=Surface(name=com.android.messaging/com.android.messaging.ui.conversationlist.ConversationListActivity)/@0x2640af2
Surface: shown=true layer=0 alpha=1.0 rect=(0.0,0.0) 828 x 290 transform=(1.0, 0.0, 1.0, 0.0)
mDrawState=HAS_DRAWN mLastHidden=false
mSystemDecorRect=[0,0][828,290] mLastClipRect=[0,0][828,290]
mForceSeamlesslyRotate=false seamlesslyRotate: pending=null finishedFrameNumber=0
isOnScreen=true
isVisible=true
mEmbeddedDisplayContents={}
这个内容对应于WindowState.dump方法.
WindowState的创建
在WindowState.WindowState方法中添加日志:
WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,
WindowState parentWindow, int appOp, int seq, WindowManager.LayoutParams a,
int viewVisibility, int ownerId, boolean ownerCanAddInternalSystemWindow) {
this(service, s, c, token, parentWindow, appOp, seq, a, viewVisibility, ownerId,
ownerCanAddInternalSystemWindow, new PowerManagerWrapper() {
@Override
public void wakeUp(long time, @WakeReason int reason, String details) {
service.mPowerManager.wakeUp(time, reason, details);
}
@Override
public boolean isInteractive() {
return service.mPowerManager.isInteractive();
}
});
}
我们在点击短信应用时,可以看到WindowState的创建过程:
第一个:
WindowManager: WindowState:Window{18bd0d7 u0 Splash Screen com.android.messaging}
WindowManager: at com.android.server.wm.WindowState.<init>(WindowState.java:751)
WindowManager: at com.android.server.wm.WindowManagerService.addWindow(WindowManagerService.java:1562)
WindowManager: at com.android.server.wm.Session.addToDisplay(Session.java:159)
WindowManager: at android.view.ViewRootImpl.setView(ViewRootImpl.java:923)
WindowManager: at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:387)
WindowManager: at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:96)
WindowManager: at com.android.server.policy.PhoneWindowManager.addSplashScreen(PhoneWindowManager.java:2802)
WindowManager: at com.android.server.wm.SplashScreenStartingData.createStartingSurface(SplashScreenStartingData.java:56)
WindowManager: at com.android.server.wm.AppWindowToken$1.run(AppWindowToken.java:2258)
WindowManager: at android.os.Handler.handleCallback(Handler.java:883)
WindowManager: at android.os.Handler.dispatchMessage(Handler.java:100)
WindowManager: at android.os.Looper.loop(Looper.java:221)
WindowManager: at android.os.HandlerThread.run(HandlerThread.java:67)
WindowManager: at com.android.server.ServiceThread.run(ServiceThread.java:44)
第二个:
WindowManager: WindowState:Window{5a02cc1 u0 com.android.messaging/com.android.messaging.ui.conversationlist.ConversationListActivity}
WindowManager: at com.android.server.wm.WindowState.<init>(WindowState.java:751)
WindowManager: at com.android.server.wm.WindowManagerService.addWindow(WindowManagerService.java:1562)
WindowManager: at com.android.server.wm.Session.addToDisplay(Session.java:159)
WindowManager: at android.view.IWindowSession$Stub.onTransact(IWindowSession.java:525)
WindowManager: at com.android.server.wm.Session.onTransact(Session.java:134)
WindowManager: at android.os.Binder.execTransactInternal(Binder.java:1021)
WindowManager: at android.os.Binder.execTransact(Binder.java:994)
在WindowManagerService.addWindow中,我们可以看到当向WMS添加一个窗口时,WMS会为其创建一个WindowState:
......
final WindowState win = new WindowState(this, session, client, token, parentWindow,
appOp[0], seq, attrs, viewVisibility, session.mUid,
session.mCanAddInternalSystemWindow);
......
final DisplayPolicy displayPolicy = displayContent.getDisplayPolicy();
displayPolicy.adjustWindowParamsLw(win, win.mAttrs, Binder.getCallingPid(),
Binder.getCallingUid());
win.setShowToOwnerOnlyLocked(mPolicy.checkShowToOwnerOnly(attrs));
res = displayPolicy.prepareAddWindowLw(win, attrs);
......
win.openInputChannel(outInputChannel);
......
win.attach();
mWindowMap.put(client.asBinder(), win);
win.initAppOpsState();
......
win.setHiddenWhileSuspended(suspended);
win.setForceHideNonSystemOverlayWindowIfNeeded(hideSystemAlertWindows);
win.mToken.addWindow(win);
win.applyAdjustForImeIfNeeded();
而win是添加在mWindowMap变量中:
/** Mapping from an IWindow IBinder to the server's Window object. */
final WindowHashMap mWindowMap = new WindowHashMap();
主序,子序
在WindowState.WindowState方法
if (mAttrs.type >= FIRST_SUB_WINDOW && mAttrs.type <= LAST_SUB_WINDOW) {
// The multiplier here is to reserve space for multiple
// windows in the same type layer.
mBaseLayer = mPolicy.getWindowLayerLw(parentWindow)
* TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;
mSubLayer = mPolicy.getSubWindowLayerFromTypeLw(a.type);
......
} else {
// The multiplier here is to reserve space for multiple
// windows in the same type layer.
mBaseLayer = mPolicy.getWindowLayerLw(this)
* TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;
mSubLayer = 0;
......
}
窗口的显示次序由两个成员字段描述:主序mBaseLayer和子序mSubLayer。
主序用于描述窗口及其子窗口在所有窗口中的显示位置。
子序则描述了一个子窗口在其兄弟窗口中的显示位置。
- 主序越大,则窗口及其子窗口的显示位置相对于其他窗口的位置越靠前。
- 子序越大,则子窗口相对于其兄弟窗口的位置越靠前。对于父窗口而言,其主序取决于其类型,其子序则保持为0。而子窗口的主序与其父窗口一样,子序则取决于其类型。
mAttrs变量
mAttrs变量:
// mAttrs.flags is tested in animation without being locked. If the bits tested are ever
// modified they will need to be locked.
final WindowManager.LayoutParams mAttrs = new WindowManager.LayoutParams();
我们查看其具体值为:
mAttrs={(0,36)(828xwrap) gr=BOTTOM CENTER sim={adjust=pan forwardNavigation} ty=APPLICATION fmt=TRANSLUCENT wanim=0x7f130015
fl=DIM_BEHIND ALT_FOCUSABLE_IM HARDWARE_ACCELERATED
vsysui=LIGHT_STATUS_BAR LIGHT_NAVIGATION_BAR}
其WindowManager.LayoutParams定义为:
public static class LayoutParams extends ViewGroup.LayoutParams implements Parcelable {
......
public String toString(String prefix) {
参考资料
1.4.2.2理解WindowState
https://www.kancloud.cn/alex_wsc/android-deep3/416392
2.4.3.1主序、子序和窗口类型
https://www.kancloud.cn/alex_wsc/android-deep3/416395