fwrite

fwrite

好好生活
twitter
github
email

WMS

WMS の全名は WindowManagerService であり、クライアントアプリの管理者であり、SystemServer プロセスに存在します。WMS は主にいくつかのことを管理します。
ウィンドウ管理
ウィンドウの追加、更新、削除を担当し、コア管理メンバーには DisplayContentWindowTokenWindowState が含まれます。
ウィンドウアニメーション
ウィンドウの切り替え時にアニメーションを追加でき、ウィンドウの切り替えをより自然にします。アニメーションは WMS のアニメーションサブシステムによって管理され、このシステムは WindowAnimator です。
入力システムの中継
ユーザーがウィンドウに触れたり入力したりすると、InputManagerService がタッチイベントを処理し、WMS を介して適切なウィンドウにイベントを渡します(この時、WMS は 中継地点 です)。
Surface 管理
WMS はウィンドウの描画機能を持っていません。各ウィンドウには描画用の Surface があり、WMS は Surface の割り当てを担当します。

WMS の起動 - SystemServer#

WMS は WindowManagerService であり、システムサービスです。システムサービスといえば SystemServer を思い浮かべるので、WMS がどのように SystemServer によって呼び出されるかを見てみましょう。
SystemServer は WMS#main メソッドを通じて WMS を起動します。
WMS を Context#WINDOW_SERVICEwindow)として ServiceManager に設定します。
起動した WMS オブジェクトを AMS サービスに設定します。

// SystemServer.java

    private void run() {

        ... 省略部分

        // サービスを開始します。
        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 はセンサーサービスが準備される必要があります
            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 のスレッドに戻ります。

// 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, ... 省略部分の引数) {

      // 新しいスレッドを作成
      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();
        
        // このスレッド専用の Looper & MessageQueue オブジェクトを準備
        Looper.prepare();
        synchronized (this) {
            mLooper = Looper.myLooper();
            
            // すべての待機スレッドに通知、Looper が作成されました
            notifyAll();
        }
        Process.setThreadPriority(mPriority);
        
        // Looper の準備が整いました
        onLooperPrepared();
        // ループを開始してメッセージタスクを処理し続けます
        Looper.loop();
        
        mTid = -1;
    }
    
    public Looper getLooper() {
        if (!isAlive()) {
            return null;
        }
        
        // スレッドが開始されている場合、looper が作成されるまで待機します。
        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 は重要な処理を実行しますが、これらは AnimationThread で実行されるものほど重要ではありません。
        // したがって、優先度を1つ下げます。
        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 に渡す方法は 2 つあります。
直接 WMS 関数を呼び出し、即時に送信します。

// WindowManagerService.java

    @Override
    public boolean isKeyguardLocked() {
        // mPolicy のタイプは WindowManagerPolicy 
        return mPolicy.isKeyguardLocked();
    }

DisplayThread の Looper を介してイベントを WMS スレッド(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;
        }

        // 設定を永続化
        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() {
        // UiThread が fg stune boost グループにいることを確認します
        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;
        }
    }
    /**
     * 現在の ui スレッドを初期化されている場合に破棄します。新しい環境を設定するためにのみテストで使用する必要があります。
     */
    @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(スレッド)を通じて WMS のインスタンスを作成します。ここで H クラス が作成され、その Looper は現在のスレッド、つまり DisplayThread です。

// WindowManagerService.java

    // Looper が指定されていない場合、現在のスレッドの 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();
        
        // ウィンドウアニメーション
        mAnimator = new WindowAnimator(this);
        
        // すべてのウィンドウのルートノード (RootWindowContainer オブジェクト)
        mRoot = new RootWindowContainer(this);    
    }

WMS#onInitReady - WindowManagerPolicy の初期化#

WMS#onInitReady 関数:UiThread (別のスレッド) の 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 の Looper を使用します
        
    }
}

WMS#displayReady - 表示の準備#

ウィンドウアニメーターの初期化が完了したことを示します。
設定を再構成し、DisplayWindowSettings 設定が正常に使用されていることを保証します。
ActivityTaskManager を介して設定を更新します。

// WindowManagerService.java

    WindowManagerPolicy mPolicy;
    final WindowAnimator mAnimator;

    // WMS の構築時に初期化されます
    RootWindowContainer mRoot;

    public void displayReady() {
        synchronized (mGlobalLock) {    // ActivityTaskManagerService 内のオブジェクト
            if (mMaxUiWidth > 0) {
                mRoot.forAllDisplays(displayContent -> displayContent.setMaxUiWidth(mMaxUiWidth));
            }
            applyForcedPropertiesForDefaultDisplay();
            
            // 1. 初期化完了を示します
            mAnimator.ready();
            mDisplayReady = true;
            // すべての表示を再構成して、強制プロパティと
            // DisplayWindowSettings が適用されていることを確認します。
          
            // 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) {
                // 無視します。VR モードリスナーの登録に失敗した場合、何もできません。
            }
        }
    }

WMS のポイント#

ウィンドウ属性 - レイヤータイプ#

Android は複数のウィンドウをサポートし、ウィンドウを 3 つのカテゴリに分け、WindowManager#LayoutParams に定義されています。
アプリケーションウィンドウ:通常のアプリケーションは以下のウィンドウタイプを使用します(いくつかの例を挙げます)、範囲は 1 ~ 99 の間です。

名称説明
1FIRST_APPLICATION_WINDOWアプリケーションウィンドウの開始値
1TYPE_BASE_APPLICATION他のアプリがこのウィンドウの上に重なることができる
2TYPE_APPLICATION一般的なアプリウィンドウ
3TYPE_APPLICATION_STARTINGアプリケーション起動前の画面(特定の画面を読み込む前)
4TYPE_DRAWN_APPLICATION描画が完了するまで待機
99LAST_APPLICATION_WINDOWアプリウィンドウの終了値

サブウィンドウ:アプリケーションの上に追加されるウィンドウで、一般に サブウィンドウ と呼ばれ、その値の範囲は 1000 ~ 1999 の間です。

名称説明
1000FIRST_SUB_WINDOWサブウィンドウの開始値
1000TYPE_APPLICATION_PANELこのサブウィンドウは依存するアプリの上に表示される
1001TYPE_APPLICATION_MEDIAビデオに関連するサブウィンドウを表示
1002TYPE_APPLICATION_SUB_PANELアプリの上に表示され、他のサブウィンドウの上にも表示
1003TYPE_APPLICATION_ATTACHED_DIALOGダイアログタイプのウィンドウ
1004TYPE_APPLICATION_MEDIA_OVERLAYTYPE_APPLICATION_MEDIA と下のアプリウィンドウの間に表示
1005TYPE_APPLICATION_ABOVE_SUB_PANELTYPE_APPLICATION_SUB_PANEL よりも上のウィンドウ
1999LAST_SUB_WINDOWサブウィンドウの終了値

システムウィンドウ:システムが使用するウィンドウ(以下にいくつかの例を示します)、範囲は 2000 ~ 2999 の間です。

名称説明
2000FIRST_SYSTEM_WINDOWシステムウィンドウの開始値
2001TYPE_STATUS_BARステータスバーのウィンドウ
2002TYPE_SEARCH_BAR検索バーのウィンドウ
2038TYPE_APPLICATION_OVERLAY他のアクティビティウィンドウの上に表示
2999LAST_SYSTEM_WINDOWシステムウィンドウの終了値

WindowState の初期化 - ベースレイヤーの決定#

WindowState のコンストラクタから、ベースレイヤーの値は WindowManagerPolicy#getWindowLayerLw メソッドから取得できます。

// WindowManagerPolicyConstants.java

// 複数のウィンドウ(同じレイヤー)用に予約
int TYPE_LAYER_MULTIPLIER = 10000;

// 複数のウィンドウ(同じレイヤー)の 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;

    ...

    // 現在のウィンドウがサブウィンドウかどうかを判断
    if (mAttrs.type >= FIRST_SUB_WINDOW && mAttrs.type <= LAST_SUB_WINDOW) {
        // 同じレイヤーの複数のウィンドウ用にスペースを予約

        // @ getWindowLayerLw メソッドを確認
        mBaseLayer = mPolicy.getWindowLayerLw(parentWindow)    // 1.
                * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;   // 2.

        // サブウィンドウ 
        mSubLayer = mPolicy.getSubWindowLayerFromTypeLw(a.type);
        ...
    } else {
        // @ getWindowLayerLw メソッドを確認
        mBaseLayer = mPolicy.getWindowLayerLw(this)
                * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;
        mSubLayer = 0;
        ...
    }

}

WindowManagerPolicy は渡された WindowState を通じてウィンドウの基本レイヤーのレベルを決定します(数値が高いほど、ユーザーに近く、上層になります)。

// 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) {
        // 常に丸みのあるコーナーレイヤーを最上位に配置します。
        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:
                // 壁紙は一番下にありますが、ウィンドウマネージャーがそれを移動させることがあります。
                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:
                // トーストと接続されたバッテリーのもの
                return  7;
            case TYPE_PRIORITY_PHONE:
                // SIM エラーとロック解除。これが本当に高いレイヤーにあるべきかは不明です。
                return  8;
            case TYPE_SYSTEM_ALERT:
                // ANR / アプリがクラッシュしたダイアログのようなもの
                // タイプは非システムアプリには非推奨です。システムアプリの場合、このタイプは
                // TYPE_APPLICATION_OVERLAY よりも高いレイヤーにあるべきです。
                return  canAddInternalSystemWindow ? 12 : 9;
            case TYPE_APPLICATION_OVERLAY:
                return  11;
            case TYPE_INPUT_METHOD:
                // 画面上のキーボードやその他の入力メソッドユーザーインターフェースがここに入ります。
                return  13;
            case TYPE_INPUT_METHOD_DIALOG:
                // 画面上のキーボードやその他の入力メソッドユーザーインターフェースがここに入ります。
                return  14;
            case TYPE_STATUS_BAR:
                return  15;

            ... 省略部分の case

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

渡された WindowState を通じてウィンドウの基本レイヤーのレベルを決定します(数値が高いほど、ユーザーに近く、上層になります)。
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#

ウィンドウの統一属性設定は WindowManager#LayoutParams にあり、typeFlags の 2 つの設定に分かれています。
タイプ:上記で述べたように、主に アプリケーションウィンドウサブウィンドウシステムウィンドウ の 3 つに分かれています。
フラグ:0 ではなく、以下にいくつかを示します(多くのものがあります)。

フラグ説明
0x00000001FLAG_ALLOW_LOCK_WHILE_SCREEN_ONこのウィンドウが表示されている限り、画面をロックすることを許可します(FLAG_KEEP_SCREEN_ON と併用可能)
0x00000002FLAG_DIM_BEHINDウィンドウの背後のウィンドウが薄くなります
0x00000004FLAG_BLUR_BEHINDウィンドウの背後のウィンドウがぼやけます
0x00000008FLAG_NOT_FOCUSABLEこのウィンドウはイベントを受け付けず、イベントは直接後方のウィンドウに渡されます
0x00000010FLAG_NOT_TOUCHABLEこのウィンドウはイベントを受け付けません
0x00000080FLAG_KEEP_SCREEN_ONこのウィンドウが表示されている限り、画面を点灯させ続けます

システム UI の制御:システム UI の設定は View に定義され、各 View に個別に設定されます。

フラグ説明
0SYSTEM_UI_FLAG_VISIBLEシステム UI を表示する設定
0x00000002SYSTEM_UI_FLAG_HIDE_NAVIGATIONナビゲーションバーを表示しない設定
0x00000004SYSTEM_UI_FLAG_FULLSCREENフルスクリーン
0x00000100SYSTEM_UI_FLAG_LAYOUT_STABLEUI レイアウトの安定性をできるだけ保持する
0x00000400SYSTEM_UI_FLAG_LAYOUT_FULLSCREENスクリーン(0,0)から描画を開始し、ステータスバーから描画を開始します

WindowManagerService は、このデバイスのすべてのウィンドウの上下関係(z 軸の管理)を管理し、描画タスクを下層に伝達します。

変数説明補足
mPolicy : WindowManagerPolicyウィンドウポリシーが遵守すべき 一般的な規範 を定義し、WindowManager 特有の UI 動作を提供しますWindowManager はインターフェースであり、その実装は PhoneWindowManager です
mSessions : ArraySet主にプロセス通信に使用され、他のアプリプロセスの View が WMS と通信するには、Session を介して通信する必要があります各アプリケーションは WindowManagerGlobal から Session を取得します
mWindowMap : WindowHashMapWindowHashMap は HashMap を継承し、すべての ViewImpl を保存するために使用されます;キー: IBinder、値: WindowStateキーは実際には IWindow(ViewRootImpl の内部クラス W)、値はウィンドウ情報を保存します
mFinishedStarting : ArrayListAppWindowToken の親クラスは WindowToken であり、アプリが WMS に新しいウィンドウを要求する際にこのトークンを提供し、WMS が検証します各 Activity は 1 つの AppWindowToken に対応し、1 つの AppWindowToken が複数の WindowToken ウィンドウを管理します
mResizingWindows : ArrayListサイズ変更中のウィンドウを保存するために使用されます
mAnimator : WindowAnimatorウィンドウアニメーションとエフェクトを管理します
mH : HH は Handler タイプで、DisplayThread Looper に属しますWMS にメッセージを送信します
mInputManager : InputManagerServiceIMS システムサービスで、ユーザーが入力メッセージを持つとき、WMS は適切なウィンドウを提供します
読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。