banner
fwrite

fwrite

好好生活
twitter
github
email

WMS

WMS 全名是 WindowManagerService,它是客户端 APP 的管理者,处于 SystemServe r 进程,WMS 主要负责管理几件事情
窗口管理
负责 Window 添加、更新、删除,核心管理成员有 DisplayContentWindowTokenWindowState
窗口动画
Window 切换时,可以添加动画,让 Window 切换时更加自然,动画由 WMS 的动画子系统负责,该系统是 WindowAnimator
输入系统的中转
当使用者对视窗触控 or 输入时,都会触发 InputManagerService 会对触摸事件进行处理,将事件通过 WMS 传递到合适的窗口进行处理(这时 WMS 就是 中转站
Surface 管理
WMS 并不具备 Window 绘制的功能,每个 Window 都有一个 Surface 来绘制,而 WMS 负责 Surface 的分配

WMS 启动 - SystemServer#

WMS 是就是 WindowManagerService,它是系统服务,说到系统服务自然就会想到 SystemServer,那就让我们来看看 WMS 是如何被 SystemServer 唤起的
SystemServer 透过 WMS#main 方法启动
把 WMS 以Context#WINDOW_SERVICE window)设定到 ServiceManager 中
把启动的 WMS 对象设定给 AMS 服务

// SystemServer.java

    private void run() {

        ... 省略部分

        // Start services.
        try {
            t.traceBegin("StartServices");
            startBootstrapServices(t);
            startCoreServices(t);

            // WMS 是在 OtherServices 启动
            startOtherServices(t);
        } catch (Throwable ex) {

            ... 省略 Log

            throw ex;
        } /* 省略 finally */

    }

    private void startOtherServices(@NonNull TimingsTraceAndSlog t) {

        ... 省略部分

        try {
            t.traceBegin("StartWindowManagerService");
            // WMS needs sensor service ready
            mSystemServiceManager.startBootPhase(t, SystemService.PHASE_WAIT_FOR_SENSOR_SERVICE);

            // 1. 启动 WMS
            wm = WindowManagerService.main(context, inputManager, !mFirstBoot, mOnlyCore,
                    new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager);

            // 2. 对 ServiceManager 添加服务 "window"
            ServiceManager.addService(Context.WINDOW_SERVICE, wm, /* allowIsolated= */ false,
                    DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PROTO);

            ServiceManager.addService(Context.INPUT_SERVICE, inputManager,
                    /* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL);
            t.traceEnd();

               // 3. 与 AMS 产生关系
             t.traceBegin("SetWindowManagerService");
             mActivityManagerService.setWindowManager(wm);
             t.traceEnd();

           } /* 省略 catch */

       }

在 WMS 启动后会透过 onInitReadydisplayReadysystemReady 来完成 WMS 的后续动作(这些方法之后会介绍)

// SystemServer.java

    private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
    
        ... 省略部分
        
        try {

            // 初始化准备
            wm.onInitReady();
            
            ... 省略部分
                
            try {
                wm.displayReady();
            } catch (Throwable e) {
                reportWtf("making display ready", e);
            }
                
            wm.systemReady();
        } /* 省略 catch */
    }  

WMS - main 函数#

透过 DisplayThread 中的 Handler#runWithScissors 创建 WMS 对象(也就是创建 WMS 的线程与 SystemServer 线程不同)
Handler#runWithScissors 方法是透过锁来达成同步任务,保证该 Runnable 会先被 DisplayThread 的 Looper 先执行,执行完后才回到 SystemServer 的 Thread

// WindowManagerService.java

 public static WindowManagerService main(final Context context, final InputManagerService im,
        final boolean showBootMsgs, final boolean onlyCore, WindowManagerPolicy policy,
        ActivityTaskManagerService atm) {

    // @ 查看 main 方法
    return main(context, im, showBootMsgs, onlyCore, policy, atm,
            new DisplayWindowSettingsProvider(), SurfaceControl.Transaction::new, Surface::new,
            SurfaceControl.Builder::new);
}


  @VisibleForTesting
  public static WindowManagerService main(final Context context, final InputManagerService im,
          final boolean showBootMsgs, final boolean onlyCore, WindowManagerPolicy policy,
          ActivityTaskManagerService atm, ... 省略部分參數) {

      // 创建新 Thread
      DisplayThread.getHandler().runWithScissors(() ->
              sInstance = new WindowManagerService(context, im, showBootMsgs, onlyCore, policy,
                      atm, displayWindowSettingsProvider, transactionFactory, surfaceFactory,
                      surfaceControlFactory), 0);
      // 执行完 runWithScissors 中的 Runnable 任务后才返回
      return sInstance;
  }

HandlerThread - 创建 Looper#

// HandlerThread.java

public class HandlerThread extends Thread {
    
    ... 省略部分方法
    
    @Override
    public void run() {
        mTid = Process.myTid();
        
        // 准备该 Thread 专用的 Looper & MessageQueue 对象
        Looper.prepare();
        synchronized (this) {
            mLooper = Looper.myLooper();
            
            // 通知所有等待的 Thread,Looper 已经创建完成
            notifyAll();
        }
        Process.setThreadPriority(mPriority);
        
        // Looper 准备好
        onLooperPrepared();
        // 准备开始运行 Loop 不断循环处理 Message 任务
        Looper.loop();
        
        mTid = -1;
    }
    
    public Looper getLooper() {
        if (!isAlive()) {
            return null;
        }
        
        // If the thread has been started, wait until the looper has been created.
        synchronized (this) {    // 以当前对象作为锁
            while (isAlive() && mLooper == null) {
                try {
                    wait();    // 直到 Looper 创建
                } catch (InterruptedException e) {
                }
            }
        }
        return mLooper;
    }
    
    
    // 在需要时才创建(但线程不安全)
    public Handler getThreadHandler() {
        if (mHandler == null) {
            mHandler = new Handler(getLooper());
        }
        return mHandler;
    }
}

DisplayThread - 创建 WMS 对象#

WMS 就是在 DisplayThread 类中被启动,DisplayThread 可以说是 WMS 的 MainThread
DisplayThread 可以创建安全 Handler,其主要功能是:处理 低延迟显示 的相关操作,并只能由 WindowManager、DisplayManager、InputManager 执行快速操作
从上面可以看到 DisplayThread 继承于 ServiceThread(而它继承于 HandlerThread),所以 它会在执行 run 方法时自动创建 Looper 对象,鉴于 HandlerThread 创建的 Handler 并不安全,所以 DisplayThread 这里自己创建 Handler(使用类锁)

// DisplayThread.java

public final class DisplayThread extends ServiceThread {
    private static DisplayThread sInstance;
    private static Handler sHandler;

    // 單例模式
    private DisplayThread() {
        // DisplayThread runs important stuff, but these are not as important as things running in
        // AnimationThread. Thus, set the priority to one lower.
        super("android.display", Process.THREAD_PRIORITY_DISPLAY + 1, false /*allowIo*/);
    }

    private static void ensureThreadLocked() {
        if (sInstance == null) {
            sInstance = new DisplayThread();
            sInstance.start();
            sInstance.getLooper().setTraceTag(Trace.TRACE_TAG_SYSTEM_SERVER);
            sHandler = new Handler(sInstance.getLooper());
        }
    }

    public static DisplayThread get() {
        // 类锁
        synchronized (DisplayThread.class) {
            // 创建 DisplayThread 对象
            ensureThreadLocked();
            return sInstance;
        }
    }

    // 透过 DisplayThread.class 类锁来达成安全创建
    public static Handler getHandler() {
        // 类锁
        synchronized (DisplayThread.class) {
            // 创建 DisplayThread 对象
            ensureThreadLocked();
            return sHandler;
        }
    }
}

传递事件给 WMS 有两种方式
直接呼叫 WMS function,即时传送

// WindowManagerService.java

    @Override
    public boolean isKeyguardLocked() {
        // mPolicy 类型 WindowManagerPolicy 
        return mPolicy.isKeyguardLocked();
    }

透过 DisplayThread 的 Looper 将事件丢入 WMS Thread(DisplayThread)中

// WindowManagerService.java

    final H mH = new H();

    final class H extends android.os.Handler {
        ...
    }

    @Override
    public void setAnimationScale(int which, float scale) {
        if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE,
                "setAnimationScale()")) {
            throw new SecurityException("Requires SET_ANIMATION_SCALE permission");
        }

        scale = fixScale(scale);
        switch (which) {
            case 0: mWindowAnimationScaleSetting = scale; break;
            case 1: mTransitionAnimationScaleSetting = scale; break;
            case 2: mAnimatorDurationScaleSetting = scale; break;
        }

        // Persist setting
        mH.sendEmptyMessage(H.PERSIST_ANIMATION_SCALE);
    }

UiThread 类#

UiThread 与 DisplayThread 差不多,但多添加了一个 dispose 方法,来停止 Looper,并结束该对象(置为 null),在 initPolicy()systemReady() 会使用到

// UiThread.java
public final class UiThread extends ServiceThread {
    private static final long SLOW_DISPATCH_THRESHOLD_MS = 100;
    private static final long SLOW_DELIVERY_THRESHOLD_MS = 200;
    private static UiThread sInstance;
    private static Handler sHandler;
    private UiThread() {
        super("android.ui", Process.THREAD_PRIORITY_FOREGROUND, false /*allowIo*/);
    }
    @Override
    public void run() {
        // Make sure UiThread is in the fg stune boost group
        Process.setThreadGroup(Process.myTid(), Process.THREAD_GROUP_TOP_APP);
        super.run();
    }
    private static void ensureThreadLocked() {
        if (sInstance == null) {
            sInstance = new UiThread();
            sInstance.start();
            final Looper looper = sInstance.getLooper();
            looper.setTraceTag(Trace.TRACE_TAG_SYSTEM_SERVER);
            looper.setSlowLogThresholdMs(
                    SLOW_DISPATCH_THRESHOLD_MS, SLOW_DELIVERY_THRESHOLD_MS);
            sHandler = new Handler(sInstance.getLooper());
        }
    }
    public static UiThread get() {
        synchronized (UiThread.class) {
            ensureThreadLocked();
            return sInstance;
        }
    }
    public static Handler getHandler() {
        synchronized (UiThread.class) {
            ensureThreadLocked();
            return sHandler;
        }
    }
    /**
     * Disposes current ui thread if it's initialized. Should only be used in tests to set up a
     * new environment.
     */
    @VisibleForTesting
    public static void dispose() {
        synchronized (UiThread.class) {
            if (sInstance == null) {
                return;
            }
            // 执行完 runWithScissors 才会往下执行
            getHandler().runWithScissors(sInstance::quit, 0 /* timeout */);
            sInstance = null;
        }
    }
}

AnimationThread 类#

AnimationThread 与 DisplayThread 差不多,但多添加了一个 dispose 方法,来停止 Looper,并结束该对象(置为 null)

// AnimationThread.java

public final class AnimationThread extends ServiceThread {
    private static AnimationThread sInstance;
    private static Handler sHandler;
    
    private AnimationThread() {
        super("android.anim", THREAD_PRIORITY_DISPLAY, false /*allowIo*/);
    }
    
    private static void ensureThreadLocked() {
        if (sInstance == null) {
            sInstance = new AnimationThread();
            sInstance.start();
            sInstance.getLooper().setTraceTag(Trace.TRACE_TAG_WINDOW_MANAGER);
            sHandler = new Handler(sInstance.getLooper());
        }
    }
    public static AnimationThread get() {
        synchronized (AnimationThread.class) {
            ensureThreadLocked();
            return sInstance;
        }
    }
    public static Handler getHandler() {
        synchronized (AnimationThread.class) {
            ensureThreadLocked();
            return sHandler;
        }
    }
    
    // 使用到 HandlerThread#quit 方法,停止 Looper
    @VisibleForTesting
    public static void dispose() {
        synchronized (AnimationThread.class) {
            if (sInstance == null) {
                return;
            }
            getHandler().runWithScissors(() -> sInstance.quit(), 0 /* timeout */);
            sInstance = null;
        }
    }
}

SystemServer - WMS 启动后续#

// SystemServer.java

private void startOtherServices(@NonNull TimingsTraceAndSlog t) {

    ... 省略部分

    try {

        // 初始化准备
        wm.onInitReady();

        ... 省略部分

        try {
            wm.displayReady();
        } catch (Throwable e) {
            reportWtf("making display ready", e);
        }

        wm.systemReady();
    } /* 省略 catch */
}                    

WMS 创建#

前面有提到 WindowManagerService#main 方法会透过 DisplayThread(Thread)创建 WMS 的实例,在这里就会创建 H 类,而它的 Looper 就是当前 Thread 也就是 DisplayThread

// WindowManagerService.java

    // 当没有指定 Looper 就会依现在 Thread 的 Looper 
    final H mH = new H();        // 也就是 DisplayThread 的 Looper

    WindowManagerPolicy mPolicy;
    final WindowAnimator mAnimator;

    RootWindowContainer mRoot;

    final class H extends android.os.Handler {
        ...
    }

    private WindowManagerService(Context context, InputManagerService inputManager,
            boolean showBootMsgs, boolean onlyCore, WindowManagerPolicy policy,
            ActivityTaskManagerService atm, DisplayWindowSettingsProvider
            displayWindowSettingsProvider, Supplier<SurfaceControl.Transaction> transactionFactory,
            Supplier<Surface> surfaceFactory,
            Function<SurfaceSession, SurfaceControl.Builder> surfaceControlFactory) {

        ... 省略部分

        // WMS 持有 InputManagerService 引用
        mInputManager = inputManager; 
        
        ...
        
        // 取得 DisplayManagerService 代理
        mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);

      
        mPolicy = policy;        // SystemServer 传进来的实例是PhoneWindowManager类
      
        // 取得 WMS 代理
        mActivityManager = ActivityManager.getService();
        mActivityTaskManager = ActivityTaskManager.getService();
        
        // Window 动画
        mAnimator = new WindowAnimator(this);
        
        // 所有 Window 的根节点 (RootWindowContainer 对象)
        mRoot = new RootWindowContainer(this);    
    }

WMS#onInitReady - 初始化 WindowManagerPolicy#

WMS#onInitReady 函数:取得 UiThread (另外一个 Thread) 的 Handler,并初始化 WindowManagerPolicy 实作呼叫 PhoneWindowManager#init 函数)

// WindowManagerService.java

public class WindowManagerService extends IWindowManager.Stub
        implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {

    WindowManagerPolicy mPolicy;    // 实作是 PhoneWindowManager 类

    public void onInitReady() {
        // @重点分析 initPolicy 函数
        initPolicy();
        
        ... 省略部分
    }

    private void initPolicy() {
        UiThread.getHandler().runWithScissors(new Runnable() {
            @Override
            public void run() {
                WindowManagerPolicyThread.set(Thread.currentThread(), Looper.myLooper());
                mPolicy.init(mContext, WindowManagerService.this, WindowManagerService.this);
            }
        }, 0);
    }

}

// ---------------------------------------------
// WindowManagerPolicy.java

public interface WindowManagerPolicy extends WindowManagerPolicyConstants {
    
    ... 省略部分
        
    public void init(Context context, IWindowManager windowManager,
        WindowManagerFuncs windowManagerFuncs);

    
// ----------------------------------------------
// PhoneWindowManager.java

public class PhoneWindowManager implements WindowManagerPolicy {
    
    ... 省略部分
    
    private class PolicyHandler extends Handler {
        ... 省略部分
    }
    
    public void init(Context context, IWindowManager windowManager,
        WindowManagerFuncs windowManagerFuncs) {
        
        // 省略部分…后面介绍
        
        mHandler = new PolicyHandler();    // 该 Handler 使用 UiThread's Looper
        
    }
}

WMS#displayReady - 准备显示#

标示 WindowAnimator 初始化完成
重新配置设定,保证 DisplayWindowSettings 设定都有被正常使用
透过 ActivityTaskManager 来更新设置

// WindowManagerService.java

    WindowManagerPolicy mPolicy;
    final WindowAnimator mAnimator;

    // 在 WMS construct 被初始化
    RootWindowContainer mRoot;

    public void displayReady() {
        synchronized (mGlobalLock) {    // ActivityTaskManagerService 中的對象
            if (mMaxUiWidth > 0) {
                mRoot.forAllDisplays(displayContent -> displayContent.setMaxUiWidth(mMaxUiWidth));
            }
            applyForcedPropertiesForDefaultDisplay();
            
            // 1. 标识初始化完成
            mAnimator.ready();
            mDisplayReady = true;
            // Reconfigure all displays to make sure that forced properties and
            // DisplayWindowSettings are applied.
          
            // 2. 重新配置设定,保证 DisplayWindowSettings 设定都有被正常使用
            mRoot.forAllDisplays(DisplayContent::reconfigureDisplayLocked);
            
            // 硬件是否是可触控屏幕
            mIsTouchDevice = mContext.getPackageManager().hasSystemFeature(
                    PackageManager.FEATURE_TOUCHSCREEN);
            
            // 硬件是否是假的可触控屏幕
            mIsFakeTouchDevice = mContext.getPackageManager().hasSystemFeature(
                    PackageManager.FEATURE_FAKETOUCH);
        }
        
        try {
            // 3. 透过 ActivityTaskManager 来更新设置
            mActivityTaskManager.updateConfiguration(null);
        } catch (RemoteException e) {
        }
    }

WMS#systemReady - 服务准备完成#

// WindowManagerService.java

    public void systemReady() {
        mSystemReady = true;
        mPolicy.systemReady();
        mRoot.forAllDisplayPolicies(DisplayPolicy::systemReady);
        mTaskSnapshotController.systemReady();
        mHasWideColorGamutSupport = queryWideColorGamutSupport();
        mHasHdrSupport = queryHdrSupport();
        mPrimaryDisplayOrientation = queryPrimaryDisplayOrientation();
        mPrimaryDisplayPhysicalAddress =
            DisplayAddress.fromPhysicalDisplayId(SurfaceControl.getPrimaryPhysicalDisplayId());
        UiThread.getHandler().post(mSettingsObserver::loadSettings);
        IVrManager vrManager = IVrManager.Stub.asInterface(
                ServiceManager.getService(Context.VR_SERVICE));
        if (vrManager != null) {
            try {
                final boolean vrModeEnabled = vrManager.getVrModeState();
                synchronized (mGlobalLock) {
                    vrManager.registerListener(mVrStateCallbacks);
                    if (vrModeEnabled) {
                        mVrModeEnabled = vrModeEnabled;
                        mVrStateCallbacks.onVrStateChanged(vrModeEnabled);
                    }
                }
            } catch (RemoteException e) {
                // Ignore, we cannot do anything if we failed to register VR mode listener
            }
        }
    }

WMS 重点#

窗口属性 - Layer Type#

Android 支持多种窗口,并且会将窗口分为三类,定义在 WindowManager#LayoutParams
Application Window:普通 App 应用就是使用以下窗口类型(列出几种举例),区间为 1 ~ 99 之间

Value名称说明
1FIRST_APPLICATION_WINDOW应用类视窗的起始值
1TYPE_BASE_APPLICATION其他应用都可覆盖在该 Window 之上
2TYPE_APPLICATION一般的应用窗口
3TYPE_APPLICATION_STARTING应用程序启动前的画面(用在加载某个画面之前的预前画面)
4TYPE_DRAWN_APPLICATION在绘画完成前等待
99LAST_APPLICATION_WINDOW应用视窗的结束值

Sub Window:附加在应用之上的视窗,一般称为 子窗口,其值区间为 1000 ~ 1999 之间

Value名称说明
1000FIRST_SUB_WINDOWSubWindow 的起始值
1000TYPE_APPLICATION_PANEL该 SubWindow 显示在依附的 App 之上
1001TYPE_APPLICATION_MEDIA显示有关 video 的 SubWindow
1002TYPE_APPLICATION_SUB_PANEL显示在依附的 app 之上,也在其他 SubWinow 之上
1003TYPE_APPLICATION_ATTACHED_DIALOGDialog 类型的 Window
1004TYPE_APPLICATION_MEDIA_OVERLAY显示在 TYPE_APPLICATION_MEDIA 还有底下的应用视窗之间
1005TYPE_APPLICATION_ABOVE_SUB_PANELTYPE_APPLICATION_SUB_PANEL 更上层的 Window
1999LAST_SUB_WINDOWSubWindow 的结束值

System Window:系统使用的 Window 视窗(以下列出几种),区间为 2000 ~ 2999 之间

Value名称说明
2000FIRST_SYSTEM_WINDOWSystem Window 的起始值
2001TYPE_STATUS_BARStatus bar 的 Window
2002TYPE_SEARCH_BAR搜寻 Bar 的 Window
2038TYPE_APPLICATION_OVERLAY覆盖于其他 Activity 视窗
2999LAST_SYSTEM_WINDOWSystem Window 的结束值

WindowState 初始化 - 决定 Base Layer#

从 WindState 构造函数可以知道,Base Laye r 数值可以从WindowManagerPolicy#getWindowLayerLw 方法取得

// WindowManagerPolicyConstants.java

// 保留給多 Window (相同 Layer)
int TYPE_LAYER_MULTIPLIER = 10000;

// 保留給多 Window (相同 Layer),Z 轴偏移量
int TYPE_LAYER_OFFSET = 1000


// ---------------------------------------------------------------
// WindowState.java

final WindowManagerPolicy mPolicy;

WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,
        WindowState parentWindow, int appOp, WindowManager.LayoutParams a, 
       ... 省略部分入參) {

    // 复制 `WindowManager.LayoutParams`
    mAttrs.copyFrom(a);

    ...

    mPolicy = mWmService.mPolicy;

    ...

    // 判断目前 Window 是否是 SubWindow
    if (mAttrs.type >= FIRST_SUB_WINDOW && mAttrs.type <= LAST_SUB_WINDOW) {
        // 保留空间给多个相同 Layer 等级的 Window

        // @ 查看 getWindowLayerLw 方法
        mBaseLayer = mPolicy.getWindowLayerLw(parentWindow)    // 1.
                * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;   // 2.

        // SubWindow 
        mSubLayer = mPolicy.getSubWindowLayerFromTypeLw(a.type);
        ...
    } else {
        // @ 查看 getWindowLayerLw 方法
        mBaseLayer = mPolicy.getWindowLayerLw(this)
                * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;
        mSubLayer = 0;
        ...
    }

}

WindowManagerPolicy 透过传入的 WindowState 决定 Window 基础 Layer 层级(数值越高,越接近使用者 & 上层)

// WindowManagerPolicy.java

    default int getWindowLayerLw(WindowState win) {
        return getWindowLayerFromTypeLw(win.getBaseType(), win.canAddInternalSystemWindow());
    }

    default int getWindowLayerFromTypeLw(int type, boolean canAddInternalSystemWindow) {
        return getWindowLayerFromTypeLw(type, canAddInternalSystemWindow,
                false /* roundedCornerOverlay */);
    }

    default int getWindowLayerFromTypeLw(int type, boolean canAddInternalSystemWindow,
            boolean roundedCornerOverlay) {
        // Always put the rounded corner layer to the top most.
        if (roundedCornerOverlay && canAddInternalSystemWindow) {
            return getMaxWindowLayer();
        }

        // 1 ~ 99 之间
        if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
            return APPLICATION_LAYER;    // APPLICATION_LAYER 是 2
        }

        switch (type) {
            case TYPE_WALLPAPER:
                // wallpaper is at the bottom, though the window manager may move it.
                return  1;
            case TYPE_PRESENTATION:
            case TYPE_PRIVATE_PRESENTATION:
            case TYPE_DOCK_DIVIDER:
            case TYPE_QS_DIALOG:
            case TYPE_PHONE:
                return  3;
            case TYPE_SEARCH_BAR:
                return  4;
            case TYPE_INPUT_CONSUMER:
                return  5;
            case TYPE_SYSTEM_DIALOG:
                return  6;
            case TYPE_TOAST:
                // toasts and the plugged-in battery thing
                return  7;
            case TYPE_PRIORITY_PHONE:
                // SIM errors and unlock.  Not sure if this really should be in a high layer.
                return  8;
            case TYPE_SYSTEM_ALERT:
                // like the ANR / app crashed dialogs
                // Type is deprecated for non-system apps. For system apps, this type should be
                // in a higher layer than TYPE_APPLICATION_OVERLAY.
                return  canAddInternalSystemWindow ? 12 : 9;
            case TYPE_APPLICATION_OVERLAY:
                return  11;
            case TYPE_INPUT_METHOD:
                // on-screen keyboards and other such input method user interfaces go here.
                return  13;
            case TYPE_INPUT_METHOD_DIALOG:
                // on-screen keyboards and other such input method user interfaces go here.
                return  14;
            case TYPE_STATUS_BAR:
                return  15;

            ... 省略部分 case

            default:
                Slog.e("WindowManager", "Unknown window type: " + type);
                return 3;
        }
    }

透过传入的WindowState决定 Window 基础 Layer 层级(数值越高,越接近使用者 & 上层)
WindowManagerPolicy#getSubWindowLayerFromTypeLw 方法:决定子窗口在父窗口中的偏移量

// WindowManagerPolicy.java

    default int getSubWindowLayerFromTypeLw(int type) {
        switch (type) {
            case TYPE_APPLICATION_PANEL:
            case TYPE_APPLICATION_ATTACHED_DIALOG:
                return APPLICATION_PANEL_SUBLAYER;    // 1
                
            case TYPE_APPLICATION_MEDIA:
                return APPLICATION_MEDIA_SUBLAYER;    // -2
                
            case TYPE_APPLICATION_MEDIA_OVERLAY:
                return APPLICATION_MEDIA_OVERLAY_SUBLAYER;    // -1
                
            case TYPE_APPLICATION_SUB_PANEL:
                return APPLICATION_SUB_PANEL_SUBLAYER;    // 2
                
            case TYPE_APPLICATION_ABOVE_SUB_PANEL:
                return APPLICATION_ABOVE_SUB_PANEL_SUBLAYER;    // 3
        }
        Slog.e("WindowManager", "Unknown sub-window type: " + type);
        return 0;
    }

窗口属性 - LayoutParams#

Window 的统一属性设定在 WindowManager#LayoutParams中,并且有分为 typeFlags 两种设定
Type:上面已经说过,主要有分为 Application WindowSub WindowSystem Window 三种
Flag:莫认为 0,以下列出几个(有满多的)

ValueFlag说明
0x00000001FLAG_ALLOW_LOCK_WHILE_SCREEN_ON只要该窗口可见,就允许锁住屏幕(可配合 FLAG_KEEP_SCREEN_ON 使用)
0x00000002FLAG_DIM_BEHIND窗口后的 Window 都变淡
0x00000004FLAG_BLUR_BEHIND窗口后的 Window 变模糊
0x00000008FLAG_NOT_FOCUSABLE该 Window 视窗不可事件,事件会直接传递给后方 Window
0x00000010FLAG_NOT_TOUCHABLE该窗口不接受任何事件
0x00000080FLAG_KEEP_SCREEN_ON只要该窗口可见,就保持屏幕亮起

System UI 控制:System UI 的设定定义在 View 中,针对每个 View 个别设置

ValueFlag说明
0SYSTEM_UI_FLAG_VISIBLE设定 System UI 可见
0x00000002SYSTEM_UI_FLAG_HIDE_NAVIGATION设定 Navigtion Bar 不可见
0x00000004SYSTEM_UI_FLAG_FULLSCREEN屏幕全屏
0x00000100SYSTEM_UI_FLAG_LAYOUT_STABLE尽量保持 UI 布局的稳定性
0x00000400SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN从屏幕(0,0)开始绘制,也就是会从 Status Bar 开始绘制

WindowManagerService 简单理解起来是掌管该装置所有的 Window 的上下关系(z 轴的管理)、传输绘制任务到底层

变量说明补充
mPolicy : WindowManagerPolicy定义一个窗口策略所须遵循的 通用规范,并提供了 WindowManger 特定的 UI 行为WindowManager 是 interface,它的实作是 PhoneWindowManager
mSessions : ArraySet它主要用于进程通信,其他的应用进程的 View 想要和 WMS 通信,都要通过 Session 与 WMS 通信每个应用程序是透过 WindowManagerGlobal 取得 Session
mWindowMap : WindowHashMapWindowHashMap 继承 HashMap,用来保存所有 ViewImpl;Key: IBinder、Value: WindowStateKey 其实是 IWindow(ViewRootImpl 的内部类 W)、Value 是保存窗口信息
mFinishedStarting : ArrayListAppWindowToken 的父类是 WindowToken 当 APP 要向 WMS 申请一个新窗口时就要给予这个 token 让 WMS 验证每个 Activity 对应一个 AppWindowToken(一个 AppWindowToken 管理多个 WindowToken 视窗)
mResizingWindows : ArrayList用来存储正在调整大小的视窗
mAnimator : WindowAnimator管理 Window 动画 & 特效
mH : HH 是 Handler 类型,它是属于 DisplayThread Looper将消息给 WMS
mInputManager : InputManagerServiceIMS 系统服务,当使用者有输入讯息时,WMS 会给予一个适合的视窗
Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.