詳細な技術情報

このセクションでは、コントロール センター リファレンス アプリに固有の技術的な詳細について説明します。

コントロール センターは、バンドルされていない、特権を持つ、システム署名付きのアプリで、最小 SDK バージョン 35(Android V(API レベル 35))が必要です。このアプリは、System APIs を使用するために system/priv-app にインストールされます。メディア情報を読み取るには、アプリにプラットフォーム署名が必要です。アプリは無線(OTA)で更新できます。

バックグラウンド サービス

コントロール センター アプリは、その機能のためにバックグラウンド サービスに依存しています。 Control Center Service は、ユーザー ライフサイクルの user-post-unlocked 状態で Vendor ServiceController によって開始されます。コントロール センターは常にアクティブで、バックグラウンドで通信している必要があります。ユーザーがアプリを開くことに依存することはできません。

Control Center Service は、 他の乗員ゾーンの他のインスタンスに接続して通信します。Communication API を使用します。各ユーザーのコントロール センター インスタンスが接続を確立し、データを送受信する方法を理解するには、統合ガイドを読むことが不可欠です。

ベンダー ServiceController によって開始される Control Center Service を示す図。
図 5.Vendor ServiceController によって開始された Control Center Service。

コミュニケーション

接続すると、Control Center Service は情報を伝達する protobuf オブジェクトと通信します。protobuf を別の乗員ゾーンに渡すには、Communication APIs を使用して、protobufbyte array に変換し、payload object を作成して、PayloadCarOccupantConnectionManager#sendPayload を介して送信します。

message ControlCenterPayload {
    required Type messageType = 1;
    // ...
    enum Type {
       MEDIA_STATUS = 0;
       MEDIA_COMMAND = 1;
       INPUT_LOCK_COMMAND = 2;
       INPUT_LOCK_SUCCESSFUL = 3;
       CANCEL_AUDIO_REQUEST = 4;
       MIRRORING_REQUEST_RECEIVER_DECISION = 5;
       MIRRORING_SESSION_ENDED = 6;
    }
}

private fun parsePayload(
    senderZone: OccupantZoneInfo,
    payload: Payload
) {
     val parsedPayload =
         ControlCenterPayload.parseFrom(payload.bytes)
             when (parsedPayload.messageType) {
                 ControlCenterPayload.Type.MEDIA_STATUS -> {
                     // logic here
                 }
             }
             //…
}

データ

乗員ゾーンに関する情報は、OccupantZoneData オブジェクトの形式でコントロール センターに保存されます。ローカルの OccupantZoneData の変更は、Comms API を介して他のコントロール センター インスタンスに送信されます。

受信した Payload が解析されると、解析されたデータはローカルの OccupantZoneStateRepository に渡され、ビューに変更が通知されます。ほとんどの データは、Kotlin flows on Android を使用してクラス間で渡されます。

車内スピーカーの音声リクエストを処理する

ドライバーが常に乗客からの車内スピーカーでの音声再生リクエストを受け取れるように、作成時にドライバーの Control Center Service Primary ZoneMedia Audio RequestCallbackを登録します。

コールバックは、 CarAudioManager#requestMediaAudioOnPrimaryZoneの呼び出しを通知します。ドライバーの Control Center Service は、ヘッドアップ通知 (HUN)を作成してリクエストを処理します。これは、 CarAudioManager#allowMediaAudioOnPrimaryZone(boolean) を介して受け入れまたは拒否できます。

他の画面で動画を同時視聴する

同時視聴は、CarActivityManagerTask Mirroring APIs によって機能します。The TaskMirroringManager は、最初に CarActivityManager#getVisibleTasks で再生中の MediaSession アプリの パッケージを検索し、次に VirtualDisplay を作成して、 CarActivityManager#moveRootTaskToDisplay を介して表示されているタスクをこのディスプレイに移動します。

これにより、IBinder トークンが MirroredSurfaceView が レイアウトで使用して MirroredSurfaceView#mirrorSurface を介してタスクを表示できます。 Communication API Payload オブジェクトは、トークンを他の乗員ゾーンに渡しました。

これらの乗員ゾーンの各コントロール センター インスタンスは Mirroring activity を起動し、そのトークンを使用して MirroredSurfaceView にデータを入力します。

別の画面にタスクを表示するためのミラーリング トークンのフロー。
図 6.トークンフローをミラーリングします。

タスク ミラーリング API

コントロール センターでは、次のタスク ミラーリング API を使用します。

CarActivityManager#getVisibleTasks(int displayId)
<ActivityManager.RunningTaskInfo> 送信元ディスプレイに対して呼び出される。

CarActivityManager#moveRootTaskToDisplay(int virtualDisplayId)
選択した表示タスクを作成した仮想ディスプレイに移動します。

CarActivityManager#createTaskMirroringToken(int taskId)
IBinder トークンをミラーリングするタスクを作成します。タスクが仮想ディスプレイに移動された後に呼び出す必要があります。

MirroredSurfaceView#mirrorSurface(IBinder token)
トークンを使用して仮想ディスプレイの内容を表示するカスタム ビュー オブジェクト。|

コントロール センターでのタスク ミラーリングの制限事項

コントロール センターは、MediaSession アプリのタスク ミラーリングのみをサポートしています。 ただし、この API は任意のタスクをミラーリングできます。仮想ディスプレイは、送信元ディスプレイのサイズで作成されます。受信側のディスプレイで異なる解像度とサイズが使用されている場合、仮想ディスプレイは画面の中央に表示されます。

表示タスクをサーフェスする

コントロール センターは、シャーシ Theme.CarUi.NoToolbar を拡張して半透明のウィンドウにします。つまり、タスクの上にコントロール センターが開くと、タスクは CarActivityManager#getVisibleTasks で返され、タスクをミラーリングできます。

ミラーリング情報を受け取る

コントロール センターは、ミラーリング セッションを他のアプリに通知します。更新を受け取るには、アプリが Control Center Service にバインドし、Control Center Service から Messages を受信して処理するクライアントとして Handler クラスを送信する必要があります。

クライアント アプリは、ミラーリングされたアプリのパッケージ名を受け取り、次のキーを使用して、ミラーリングされたアプリをホストするコントロール センターのアクティビティの intent URI を起動できます。

  • _config_msg_mirroring_pkg_name_key_
  • _config_msg_mirroring_redirect_uri_key_

これらの構成は、クライアント アプリのリソースとコントロール センターのリソースに存在する必要があります。

クライアント アプリはコントロール センターからミラーリング情報を受け取ります。
図 7.コントロール センターからミラーリング情報を受け取ります。

コントロール センターをデバッグする

Logger クラスはコントロール センターのログを処理します。ログを強制的に出力するように構成できます。

class Logger(cls: Class<*>) {

   companion object {
       private const val FORCE_LOGS = false
   }

   private val tag: String

   init {
       tag = cls.simpleName
   }

   fun v(message: String) {
       if (Log.isLoggable(tag, Log.VERBOSE) || FORCE_LOGS) {
           Log.v(tag, message)
       }
   }
...

システムアプリと更新可能性

コントロール センターはシステムアプリであり、署名のみの権限を使用しているためプラットフォーム署名されています。そのため、コントロール センターはデバイスにプリインストールする必要があり、Car Media App と同様に OTA でのみ更新できます。

ソースからコントロール センターをビルドする

コントロール センターのソースコードを取得するには、バンドルされていないアプリを統合するをご覧ください。

マルチディスプレイでのユーザー プライバシー

コントロール センターを使用すると、すべての車内乗員がすべてのディスプレイでメディア情報を確認できます。 ユーザーに通知するために、ブロックしないプライバシーに関するお知らせを挿入することをおすすめします。ディスプレイにログインするときに、システムレベルでこれを行うことをおすすめします。