Android 11 では、複数のリフレッシュ レートを持つデバイスのサポートが追加されています。この機能には 3 つの主要なコンポーネントがあります。
- 新しい HAL API が
android.hardware.graphics.composer@2.4
で導入されました。 - さまざまなリフレッシュ レートのデバイス構成を解析し、必要なリフレッシュ レートを設定するプラットフォーム コード
- アプリが希望のフレーム レートを設定できるようにする新しい SDK および NDK API
実装
リフレッシュ レート切り替えの専用サポートがandroid.hardware.graphics.composer@2.4 HAL
に追加されました。 Composer HAL の以前のバージョンではリフレッシュ レート切り替えのサポートが制限されているため、このバージョンを使用することを強くお勧めします。
構成グループ
getDisplayAttribute_2_4
API を使用してクエリできる新しい属性CONFIG_GROUP
がIComposerClient::Attribute
に追加されました。この属性により、ベンダーはディスプレイ構成をグループ化できます。同じグループ内の構成では、ほとんどの場合、それらの間でシームレスに切り替えることができます。構成グループは、構成の他の属性ではなくリフレッシュ レートを切り替えるために、プラットフォーム間でどの構成を切り替えることができるかを区別するためにプラットフォームによって使用されます。
4 つのディスプレイ構成をサポートするデバイスで構成グループを使用する利点を示す次の例を考えてみましょう。
- 1080p@60Hz
- 1080p@90Hz
- 1080i@72Hz
- 1080i@48Hz
デバイスは 48Hz、60Hz、72Hz、90Hz のリフレッシュ レートをサポートしていますが、ディスプレイは別のモードで動作し、60Hz から 72Hz に切り替えるとディスプレイ構成が 1080p から 1080i に変更され、これは望ましい動作ではない可能性があります。これは、構成グループを使用することで解決されます。 60Hz と 90Hz を 1 つの構成グループにグループ化し、48Hz と 72Hz を別の構成グループにグループ化します。プラットフォームは、60Hz と 90Hz の間、および 48Hz と 72Hz の間は切り替えられるが、60Hz と 72Hz の間は切り替えられないことを認識しています。これは、単にリフレッシュ レートを変更するのではなく、構成が変更されることになるためです。
Composer API の更新
- getDisplayVsyncPeriod
- リフレッシュ レート変更時の制御と予測性を向上させるために、
getDisplayVsyncPeriod
が追加されました。getDisplayVsyncPeriod
ディスプレイが動作する現在のリフレッシュ レート (vsync 期間に関して) を返します。これは、リフレッシュ レートと現在のリフレッシュ レートの間で移行するときに、プラットフォームが次のフレームをいつ開始するかを決定するために必要になるときに特に役立ちます。 - setActiveConfigWithConstraints
-
setActiveConfigWithConstraints
メソッドは、既存のsetActiveConfig
メソッドの新しい拡張機能であり、構成の変更に関する詳細情報を提供します。制約はvsyncPeriodChangeConstraints
パラメーターの一部として指定され、次のパラメーターが含まれます。 - 希望時間ナノ
- vsync 期間が変更されるまでの
CLOCK_MONOTONIC
の時刻 (つまり、この時刻より前に vsync 期間を変更してはなりません)。これは、プラットフォームがリフレッシュ レートの変更を事前に計画したいが、キュー内に提示するバッファがすでにいくつかある場合に便利です。プラットフォームは、これらのバッファを考慮してこの時間を設定し、リフレッシュ レートの移行が可能な限りスムーズになるようにします。 - シームレス必須
- true の場合、vsync 期間の変更は、目に見えるアーチファクトを生じることなくシームレスに行われる必要があります。このフラグは、コンテンツ変更の結果としてリフレッシュ レートの変更が必要な場合 (たとえば、デバイスがアイドル状態でアニメーションが開始される場合)、プラットフォームによって使用されます。これにより、ベンダーは、目に見えるアーチファクトが発生する可能性がある特定の構成変更を許可しない機会が得られます。構成をシームレスに変更できず、
seamlessRequired
がtrue
に設定されている場合、同じ構成変更をシームレスに実行できる場合、実装は戻りコードとしてSEAMLESS_NOT_POSSIBLE
を返し、新しいonSeamlessPossible
コールバックを呼び出すことが期待されます。 成功すると、実装は、リフレッシュ レートの変更がいつ発生するかをプラットフォームに通知する
VsyncPeriodChangeTimeline
を返します。newVsyncAppliedTimeNanos
パラメータは、新しい vsync 期間で新しい表示の更新が開始される時刻をCLOCK_MONOTONIC
に設定する必要があります。これにより、desiredTimeNanos
と組み合わせることで、プラットフォームはリフレッシュ レートの切り替えを事前に計画し、事前に新しいリフレッシュ レートに合わせてアプリを起動し始めることができます。これにより、リフレッシュ レートのシームレスな移行が可能になります。一部の実装では、リフレッシュ レートを送信する前にリフレッシュ フレームを送信する必要があります。そのため、HAL には、リフレッシュ フレームが必要であることを示す
refreshRequired
パラメータと、その後リフレッシュ フレームを送信する必要がある最初の vsync を示すrefreshTimeNanos
があります。- onVsyncPeriodTimingChanged [コールバック]
- HAL によって呼び出されて、タイムラインの一部のパラメーターが変更され、プラットフォームがタイムラインを調整する必要があることをプラットフォームに示す新しいコールバック。このコールバックは、HAL での長い処理時間または遅いリフレッシュ フレームにより、何らかの理由で古いタイムラインが失われた場合に呼び出されることが期待されます。
プラットフォームはリフレッシュ レートの変更をどのように決定するのでしょうか?
リフレッシュ レートの選択は、次の 2 つのシステム サービスで行われます。
- ディスプレイマネージャー
DisplayManager
リフレッシュ レートに関する高レベルのポリシーを設定します。これは、コンポーザー HAL 構成と同じデフォルトの表示構成を設定します。さらに、SurfaceFlinger
リフレッシュ レートとして選択する最小値と最大値の範囲を設定します。- サーフェスフリンガー
- デフォルト設定と同じ設定グループにあり、最小/最大範囲内のリフレッシュ レートを持つ設定を設定することによって、リフレッシュ レートを決定します。
ディスプレイ マネージャーは次の手順を実行してポリシーを決定します。
-
SurfaceFlinger
からアクティブな構成をクエリして、デフォルトの構成 ID を検索します - システム条件を反復して最小値と最大値の範囲を制限する
- デフォルトのリフレッシュ レート設定: デフォルトのリフレッシュ レート値は、
R.integer.config_defaultRefreshRate
構成オーバーレイで設定されます。この値は、アニメーションとタッチ操作の標準デバイス リフレッシュ レートを決定するために使用されます。 - ピーク リフレッシュ レートの設定: ピーク リフレッシュ レートの値は、
Settings.System.PEAK_REFRESH_RATE
から読み取られます。この値は、現在のデバイス設定 (メニュー オプションなど) を反映するために実行時に変更されます。デフォルト値は、R.integer.config_defaultPeakRefreshRate
構成オーバーレイで設定されます。 - 最小リフレッシュ レート設定: 最小リフレッシュ レート値は、
Settings.System.MIN_REFRESH_RATE
から読み取られます。この値は、現在のデバイス設定 (メニュー オプションなどから) を反映するために実行時に変更できます。デフォルト値は 0 であるため、デフォルトの最小値はありません。 - アプリケーションは ModeId を要求しました: アプリケーションは
WindowManager.LayoutParams.preferredDisplayModeId
を設定して、ディスプレイが動作する必要がある優先構成を反映できます。ほとんどの状況では、DisplayManager
それに応じてデフォルトの構成 ID を設定し、構成のリフレッシュ レートに一致するように最小および最大のリフレッシュ レートを設定します。 - バッテリー セーバー: デバイスが低電力モードの場合、リフレッシュ レートは 60Hz 以下に制限されます。これは、
Settings.Global.LOW_POWER_MODE.
- デフォルトのリフレッシュ レート設定: デフォルトのリフレッシュ レート値は、
DisplayManager
ポリシーを設定すると、 SurfaceFlinger
アクティブ レイヤー (フレーム更新をキューに入れるレイヤー) に基づいてリフレッシュ レートを設定します。レイヤーの所有者がフレーム レートを設定すると、SurfaceFlinger はリフレッシュ レートをそのレートの乗数に設定しようとします。たとえば、2 つのアクティブ レイヤーのフレーム レートが 24 と 60 に設定されている場合、SurfaceFlinger は、利用可能な場合は 120 Hz を選択します。そのようなリフレッシュ レートが SurfaceFlinger で利用できない場合、フレーム レートの誤差が最小となるリフレッシュ レートを選択しようとします。詳細については、 developer.android.comの開発者ドキュメントを参照してください。
SurfaceFlinger
リフレッシュ レートの決定方法を制御するために次のフラグを維持します。
-
ro.surface_flinger.use_content_detection_for_refresh_rate:
設定されている場合、フレーム レートが設定されていない場合でも、リフレッシュ レートはアクティブなレイヤーに基づいて決定されます。 SurfaceFlinger は、バッファーに付加されたプレゼンテーション タイムスタンプを確認することで、レイヤーがバッファーに投稿している平均 fps を見つけるヒューリスティックを維持します。 -
ro.surface_flinger.set_touch_timer_ms
: > 0 の場合、設定されたタイムアウトの間、ユーザーが画面に触れたときにデフォルトのリフレッシュ レートが使用されます。このヒューリスティックは、アニメーションのデフォルトのリフレッシュ レートを準備するために行われます。 -
ro.surface_flinger.set_idle_timer_ms
: > 0 の場合、設定されたタイムアウトの間画面の更新がないときに最小リフレッシュ レートが使用されます。 -
ro.surface_flinger.set_display_power_timer_ms
: > 0 の場合、設定されたタイムアウトの間、ディスプレイをオンにするとき (または AOD を終了するとき) にデフォルトのリフレッシュ レートが使用されます。
フレームレートAPI
フレーム レート API を使用すると、アプリは意図したフレーム レートを Android プラットフォームに通知でき、Android 11 をターゲットとするアプリで利用できます。フレーム レート API の詳細については、 developer.android.comの開発者ドキュメントを確認してください。
開発者向けオプション
現在のリフレッシュ レートでディスプレイ上のオーバーレイを切り替える新しい開発者向けオプションがメニューに追加されました。新しいオプションは、 [設定] > [システム] > [開発者向けオプション] > [リフレッシュ レートの表示] にあります。