解像度変更設定のある端末の解像度情報を取得する方法

Pxiel 8 Proなど、高解像度なディスプレイを持つAndroid端末の中には省電力化などのために解像度を変更できる端末があります。アプリ上からどのような解像度モードを持っているかを知りたい時にどうすれば良いでしょうか？

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155171/c01e2ef8-d5e5-5d20-d108-d239a24ed8d0.png" width="400" />

# ディスプレイの情報を取得する

DisplayManagerを使うことで、ディスプレイの情報を取得することができます。

```kotlin
val displayManager = getSystemService<DisplayManager>() ?: return
val display = displayManager.getDisplay(Display.DEFAULT_DISPLAY)
Log.e("XXXX", "Display:${display.displayId} ${display.name}")
display.supportedModes
    .forEach { mode ->
        val alt = mode.alternativeRefreshRates
            .joinToString(prefix = "[", postfix = "]")
        val hdr = mode.supportedHdrTypes.map {
            when (it) {
                Display.HdrCapabilities.HDR_TYPE_HDR10 -> "HDR10"
                Display.HdrCapabilities.HDR_TYPE_DOLBY_VISION -> "Dolby Vision"
                Display.HdrCapabilities.HDR_TYPE_HLG -> "HLG"
                Display.HdrCapabilities.HDR_TYPE_HDR10_PLUS -> "HLG"
                else -> "Unknown"
            }
        }.joinToString(prefix = "[", postfix = "]")
        Log.e("XXXX", "Mode:${mode.modeId} ${mode.physicalWidth} x ${mode.physicalHeight} fps:${mode.refreshRate} $alt hdr:$hdr")
    }
```

これを実行すると以下のような情報を得ることができます。

```
Display:0 内蔵スクリーン
Mode:1 1344 x 2992 fps:60.0 [120.00001] hdr:[HDR10, HLG, HLG]
Mode:2 1344 x 2992 fps:120.00001 [60.0] hdr:[HDR10, HLG, HLG]
Mode:3 1008 x 2244 fps:120.00001 [60.0] hdr:[HDR10, HLG, HLG]
Mode:4 1008 x 2244 fps:60.0 [120.00001] hdr:[HDR10, HLG, HLG]
```

通常必要となることは無いと思いますが、
`getAlternativeRefreshRates()`はAPI 31
`getSupportedHdrTypes()`はAPI 34
である点に注意です。

`getDisplays()`を使って配列で受け取ることもできます。以下のようにすると一覧を出力することができます。

```kotlin
val displayManager = getSystemService<DisplayManager>() ?: return
displayManager.displays
    .forEach { display ->
        Log.e("XXXX", "Display:${display.displayId} ${display.name}")
        display.supportedModes.forEach { mode ->
            val alt = mode.alternativeRefreshRates
                .joinToString(prefix = "[", postfix = "]")
            val hdr = mode.supportedHdrTypes.map {
                when (it) {
                    Display.HdrCapabilities.HDR_TYPE_HDR10 -> "HDR10"
                    Display.HdrCapabilities.HDR_TYPE_DOLBY_VISION -> "Dolby Vision"
                    Display.HdrCapabilities.HDR_TYPE_HLG -> "HLG"
                    Display.HdrCapabilities.HDR_TYPE_HDR10_PLUS -> "HLG"
                    else -> "Unknown"
                }
            }.joinToString(prefix = "[", postfix = "]")
            Log.e("XXXX", "Mode:${mode.modeId} ${mode.physicalWidth} x ${mode.physicalHeight} fps:${mode.refreshRate} $alt hdr:$hdr")
        }
    }
```

ただし、これで出力されるのは有効なディスプレイのみのため、一部のFoldableデバイスの用に内側と外側で別のディスプレイを持っている場合、使われていないディスプレイの情報を取得することはできません。

## 使われていないディスプレイの情報も取得する

`getDisplays()`の引数に`DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED`を指定することで無効になっているディスプレイの情報も取得することができるのですが、こちらは`@hide`がついたフィールドのため、参照できません。当然将来的に変更される可能性がありますが、以下のように直接そのString値（`"android.hardware.display.category.ALL_INCLUDING_DISABLED"`）を指定することで一覧を取得できます。

```kotlin
val displayManager = getSystemService<DisplayManager>() ?: return
displayManager.getDisplays("android.hardware.display.category.ALL_INCLUDING_DISABLED")
    .forEach { display ->
        Log.e("XXXX", "Display:${display.displayId} ${display.name} ${display.state}")
        display.supportedModes.forEach { mode ->
            val alt = mode.alternativeRefreshRates
                .joinToString(prefix = "[", postfix = "]")
            val hdr = mode.supportedHdrTypes.map {
                when (it) {
                    Display.HdrCapabilities.HDR_TYPE_HDR10 -> "HDR10"
                    Display.HdrCapabilities.HDR_TYPE_DOLBY_VISION -> "Dolby Vision"
                    Display.HdrCapabilities.HDR_TYPE_HLG -> "HLG"
                    Display.HdrCapabilities.HDR_TYPE_HDR10_PLUS -> "HLG"
                    else -> "Unknown"
                }
            }.joinToString(prefix = "[", postfix = "]")
            Log.e("XXXX", "Mode:${mode.modeId} ${mode.physicalWidth} x ${mode.physicalHeight} fps:${mode.refreshRate} $alt hdr:$hdr")
        }
    }
```

Pxiel Foldで実行すると以下のような結果が得られます。

```
Display:0 Inner Display 2
Mode:1 2208 x 1840 fps:60.0 [120.00001] hdr:[HDR10, HLG, HLG]
Mode:2 2208 x 1840 fps:120.00001 [60.0] hdr:[HDR10, HLG, HLG]
Display:2 Outer Display 1
Mode:3 1080 x 2092 fps:60.0 [120.00001] hdr:[HDR10, HLG, HLG]
Mode:4 1080 x 2092 fps:120.00001 [60.0] hdr:[HDR10, HLG, HLG]
```

---

以上です。