android开发浅谈之WindowState

什么是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

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hfreeman2008

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值