ホットプラグの処理

Android TV セットトップ ボックス(STB)やオーバー ザ トップ(OTT)など、外部接続されたディスプレイ(HDMI または DisplayPort 経由)を持つデバイスでは、ディスプレイ機能(ディスプレイ モードやサポートされている HDR タイプなど)が動的に変更されることがあります。この変更は、HDMI ホットプラグ信号が検出された場合(ユーザーがディスプレイを切り替えたり、ディスプレイが接続されていない状態でデバイスを起動したりした場合など)に発生する可能性があります。Android 12 以降では、ホットプラグや動的なディスプレイ機能に対応できるようにフレームワークが変更されました。

このページでは、Composer HAL 実装でのディスプレイ ホットプラグの処理やディスプレイ機能の変更について説明します。また、このような場合に、関連するフレームバッファを管理し、競合状態を防ぐ方法についても解説します。

ディスプレイ機能の更新

このセクションでは、Composer HAL によって開始されたディスプレイ機能の変更を Android フレームワークがどのように処理するかについて説明します。

Android がディスプレイ機能の変更を適切に処理できるように、OEM は、onHotplug(display, connection=CONNECTED) を使用してディスプレイ機能の変更をフレームワークに通知するように Composer HAL を実装する必要があります。実装が完了すると、Android はディスプレイ機能の変更を次のように処理します。

  1. ディスプレイ機能の変更が検出されると、フレームワークは onHotplug(display, connection=CONNECTED) 通知を受信します。
  2. 通知を受信すると、フレームワークは自身のディスプレイ状態をドロップし、getActiveConfiggetDisplayConfigsgetDisplayAttributegetColorModesgetHdrCapabilitiesgetDisplayCapabilities メソッドを使用して新しい機能を持つディスプレイ状態を HAL から再作成します。
  3. フレームワークは、新しいディスプレイ状態を再作成すると、そのイベントをリッスンしているアプリに onDisplayChanged コールバックを送信します。

フレームワークは、後続の onHotplug(display, connection=CONNECTED) イベントでフレームバッファを再度割り当てます。新しいフレームバッファの割り当て時の失敗を回避するためにフレームバッファ メモリを適切に管理する方法については、クライアントのフレームバッファ管理をご覧ください。

一般的な接続シナリオの処理

このセクションでは、実装でプライマリ ディスプレイが接続または切断される場合のさまざまな接続シナリオを適切に処理する方法について説明します。

Android フレームワークはモバイル デバイス向けに構築されているため、切断されたプライマリ ディスプレイに対するサポートが組み込まれていません。そのため、HAL は、プライマリ ディスプレイが物理的に切断された場合に、フレームワークとのやり取りでプライマリ ディスプレイをプレースホルダ ディスプレイに置き換える必要があります。

ディスプレイが外部接続されており、それらが切断される可能性のある STB とテレビドングルでは、以下のシナリオが考えられます。こうしたシナリオに対するサポートを実装するには、次の表の情報を使用します。

シナリオ 処理
起動時にディスプレイが接続されていない場合
  • onHotplug(display, connection=CONNECTED) シグナルを Composer HAL からフレームワークに送信します。
  • Composer HAL 内の物理ディスプレイの状態をプレースホルダ ディスプレイの状態に置き換えます。
プライマリ ディスプレイが物理的に接続された場合
  • Composer HAL からフレームワークに別の onHotplug(display, connection=CONNECTED) イベントを送信します。

    これにより、フレームワークはすべてのディスプレイ機能を再読み込みします。

プライマリ ディスプレイが物理的に切断された場合
  • Composer HAL からフレームワークに別の onHotplug(display, connection=CONNECTED) イベントを送信します。
  • Composer HAL 内の物理ディスプレイの状態をプレースホルダ ディスプレイの状態に置き換えます。フレームワークがアプリに onDisplayChanged コールバックを送信できるように、プレースホルダ ディスプレイが持つディスプレイ モードは 1 つのみにする必要があります(サポートされているモードのセットが変更されるため)。また、アプリが設定変更イベントを受信しないように、この 1 つのディスプレイ モードは、切断前の物理ディスプレイで最後にアクティブだったモードと一致している必要があります。

連続した構成 ID を使用して競合状態を回避する

Composer HAL がサポートされているディスプレイ構成を更新するのと同時に、フレームワークが setActiveConfig または setActiveConfigWithConstraints を呼び出した場合、競合状態が発生することがあります。 この解決策は、連続した ID を使用してこの問題を回避するように Composer HAL を実装することです。

このセクションでは、競合状態が発生する仕組みと、連続した ID を使用して競合状態を回避するように Composer HAL を実装する方法について詳しく説明します。

次のようなイベント シーケンスについて考えてみましょう。新しいディスプレイ構成に、連続した新しい ID が割り当てられていないため、競合状態が発生しています。

  1. サポートされているディスプレイ構成 ID は次のとおりです。

    • id=1、1080x1920 60 Hz
    • id=2、1080x1920 50 Hz
  2. フレームワークは setActiveConfig(display, config=1) を呼び出します。

  3. 同時に、Composer HAL は、ディスプレイ構成の変更を処理し、その内部状態を新しいディスプレイ構成のセットに更新します。以下をご覧ください。

    • id=1、2160x3840 60 Hz
    • id=2、2160x3840 50 Hz
    • id=3、1080x1920 60 Hz
    • id=4、1080x1920 50 Hz
  4. Composer HAL はフレームワークに onHotplug イベントを送信して、サポートされているモードセットが変更されたことを通知します。

  5. Composer HAL は、ステップ 2 で呼び出された setActiveConfig(display, config=1) を受け取ります。

  6. HAL は、フレームワークが構成を 2160x3840 60 Hz に変更するようリクエストしたと解釈しますが、実際には 1080x1920 60 Hz が必要とされていました。

連続していない ID の割り当てを使用するプロセスは、ここで目的の構成変更の解釈を間違えて終了します。

連続した ID を使用するように Composer HAL を設定する

このような競合状態を回避するため、OEM は Composer HAL を次のように実装する必要があります。

  • Composer HAL は、サポートされているディスプレイ構成を更新する際、新しいディスプレイ構成に新しい連続した ID を割り当てる。
  • フレームワークが無効な構成 ID を使用して setActiveConfig または setActiveConfigWithConstraints を呼び出した場合、Composer HAL はその呼び出しを無視する。

このように実装することで、次のとおり競合状態を回避できます。

連続した新しい ID が新しいディスプレイ構成に割り当てられた場合のイベント シーケンスを考えてみましょう。

  1. サポートされているディスプレイ構成 ID は次のとおりです。

    • id=1、1080x1920 60 Hz
    • id=2、1080x1920 50 Hz
  2. フレームワークは setActiveConfig(display, config=1) を呼び出します。

  3. ディスプレイ構成の変更が処理されると、以下のように、使用されていない後続の整数を使用して、次の構成 ID のセットが割り当てられます。

    • id=3、2160x3840 60 Hz

    • id=4、2160x3840 50 Hz

    • id=5、1080x1920 60 Hz

    • id=6、1080x1920 50 Hz

  4. Composer HAL はフレームワークに onHotplug イベントを送信して、サポートされているモードセットが変更されたことを通知します。

  5. Composer HAL は、ステップ 2 で呼び出された setActiveConfig(display, config=1) を受け取ります。

  6. ID が無効であるため、Composer HAL は呼び出しを無視します。

  7. フレームワークは、ステップ 4 で送信された onHotplug イベントを受信して処理し、getDisplayConfigs 関数と getDisplayAttribute 関数を使用して Composer HAL を呼び出します。 フレームワークはこれらの関数を使用して、目的の構成(解像度 1080x1920、リフレッシュ レート 60 Hz)に対応する新しい ID(5)を識別します。

  8. フレームワークは、更新された ID(5)を使用して別の setActiveConfig イベントを送信します。

  9. Composer HAL は、ステップ 5 で送信された setActiveConfig(display, config=5) を受け取ります。

  10. HAL は、フレームワークが構成を 1080x1920 60 Hz に変更するようリクエストしたことを正しく解釈します。

上記の例に示すように、連続した ID の割り当てを使用したプロセスにより、競合状態を回避し、ディスプレイ構成の変更を正しく更新できるようになります。