Android TV セットトップ ボックス(STB)やオーバー ザ トップ(OTT)など、外部接続されたディスプレイ(HDMI または DisplayPort 経由)を持つデバイスでは、ディスプレイ機能(ディスプレイ モードやサポートされている HDR タイプなど)が動的に変更されることがあります。この変更は、HDMI ホットプラグ信号が検出された場合(ユーザーがディスプレイを切り替えたり、ディスプレイが接続されていない状態でデバイスを起動したりした場合など)に発生する可能性があります。Android 12 以降では、ホットプラグや動的なディスプレイ機能に対応できるようにフレームワークが変更されました。
このページでは、Composer HAL 実装でのディスプレイ ホットプラグの処理やディスプレイ機能の変更について説明します。また、このような場合に、関連するフレームバッファを管理し、競合状態を防ぐ方法についても解説します。
ディスプレイ機能の更新
このセクションでは、Composer HAL によって開始されたディスプレイ機能の変更を Android フレームワークがどのように処理するかについて説明します。
Android がディスプレイ機能の変更を適切に処理できるように、OEM は、onHotplug(display, connection=CONNECTED)
を使用してディスプレイ機能の変更をフレームワークに通知するように Composer HAL を実装する必要があります。実装が完了すると、Android はディスプレイ機能の変更を次のように処理します。
- ディスプレイ機能の変更が検出されると、フレームワークは
onHotplug(display, connection=CONNECTED)
通知を受信します。 - 通知を受信すると、フレームワークは自身のディスプレイ状態をドロップし、
getActiveConfig
、getDisplayConfigs
、getDisplayAttribute
、getColorModes
、getHdrCapabilities
、getDisplayCapabilities
メソッドを使用して新しい機能を持つディスプレイ状態を HAL から再作成します。 - フレームワークは、新しいディスプレイ状態を再作成すると、そのイベントをリッスンしているアプリに
onDisplayChanged
コールバックを送信します。
フレームワークは、後続の onHotplug(display, connection=CONNECTED)
イベントでフレームバッファを再度割り当てます。新しいフレームバッファの割り当て時の失敗を回避するためにフレームバッファ メモリを適切に管理する方法については、クライアントのフレームバッファ管理をご覧ください。
一般的な接続シナリオの処理
このセクションでは、実装でプライマリ ディスプレイが接続または切断される場合のさまざまな接続シナリオを適切に処理する方法について説明します。
Android フレームワークはモバイル デバイス向けに構築されているため、切断されたプライマリ ディスプレイに対するサポートが組み込まれていません。そのため、HAL は、プライマリ ディスプレイが物理的に切断された場合に、フレームワークとのやり取りでプライマリ ディスプレイをプレースホルダ ディスプレイに置き換える必要があります。
ディスプレイが外部接続されており、それらが切断される可能性のある STB とテレビドングルでは、以下のシナリオが考えられます。こうしたシナリオに対するサポートを実装するには、次の表の情報を使用します。
シナリオ | 処理 |
---|---|
起動時にディスプレイが接続されていない場合 |
|
プライマリ ディスプレイが物理的に接続された場合 |
|
プライマリ ディスプレイが物理的に切断された場合 |
|
連続した構成 ID を使用して競合状態を回避する
Composer HAL がサポートされているディスプレイ構成を更新するのと同時に、フレームワークが setActiveConfig
または setActiveConfigWithConstraints
を呼び出した場合、競合状態が発生することがあります。
この解決策は、連続した ID を使用してこの問題を回避するように Composer HAL を実装することです。
このセクションでは、競合状態が発生する仕組みと、連続した ID を使用して競合状態を回避するように Composer HAL を実装する方法について詳しく説明します。
次のようなイベント シーケンスについて考えてみましょう。新しいディスプレイ構成に、連続した新しい ID が割り当てられていないため、競合状態が発生しています。
サポートされているディスプレイ構成 ID は次のとおりです。
- id=1、1080x1920 60 Hz
- id=2、1080x1920 50 Hz
フレームワークは
setActiveConfig(display, config=1)
を呼び出します。同時に、Composer HAL は、ディスプレイ構成の変更を処理し、その内部状態を新しいディスプレイ構成のセットに更新します。以下をご覧ください。
- id=1、2160x3840 60 Hz
- id=2、2160x3840 50 Hz
- id=3、1080x1920 60 Hz
- id=4、1080x1920 50 Hz
Composer HAL はフレームワークに
onHotplug
イベントを送信して、サポートされているモードセットが変更されたことを通知します。Composer HAL は、ステップ 2 で呼び出された
setActiveConfig(display, config=1)
を受け取ります。HAL は、フレームワークが構成を 2160x3840 60 Hz に変更するようリクエストしたと解釈しますが、実際には 1080x1920 60 Hz が必要とされていました。
連続していない ID の割り当てを使用するプロセスは、ここで目的の構成変更の解釈を間違えて終了します。
連続した ID を使用するように Composer HAL を設定する
このような競合状態を回避するため、OEM は Composer HAL を次のように実装する必要があります。
- Composer HAL は、サポートされているディスプレイ構成を更新する際、新しいディスプレイ構成に新しい連続した ID を割り当てる。
- フレームワークが無効な構成 ID を使用して
setActiveConfig
またはsetActiveConfigWithConstraints
を呼び出した場合、Composer HAL はその呼び出しを無視する。
このように実装することで、次のとおり競合状態を回避できます。
連続した新しい ID が新しいディスプレイ構成に割り当てられた場合のイベント シーケンスを考えてみましょう。
サポートされているディスプレイ構成 ID は次のとおりです。
- id=1、1080x1920 60 Hz
- id=2、1080x1920 50 Hz
フレームワークは
setActiveConfig(display, config=1)
を呼び出します。ディスプレイ構成の変更が処理されると、以下のように、使用されていない後続の整数を使用して、次の構成 ID のセットが割り当てられます。
id=3、2160x3840 60 Hz
id=4、2160x3840 50 Hz
id=5、1080x1920 60 Hz
id=6、1080x1920 50 Hz
Composer HAL はフレームワークに
onHotplug
イベントを送信して、サポートされているモードセットが変更されたことを通知します。Composer HAL は、ステップ 2 で呼び出された
setActiveConfig(display, config=1)
を受け取ります。ID が無効であるため、Composer HAL は呼び出しを無視します。
フレームワークは、ステップ 4 で送信された
onHotplug
イベントを受信して処理し、getDisplayConfigs
関数とgetDisplayAttribute
関数を使用して Composer HAL を呼び出します。 フレームワークはこれらの関数を使用して、目的の構成(解像度 1080x1920、リフレッシュ レート 60 Hz)に対応する新しい ID(5)を識別します。フレームワークは、更新された ID(5)を使用して別の
setActiveConfig
イベントを送信します。Composer HAL は、ステップ 5 で送信された
setActiveConfig(display, config=5)
を受け取ります。HAL は、フレームワークが構成を 1080x1920 60 Hz に変更するようリクエストしたことを正しく解釈します。
上記の例に示すように、連続した ID の割り当てを使用したプロセスにより、競合状態を回避し、ディスプレイ構成の変更を正しく更新できるようになります。