이 섹션에서는 제어 센터 참조 앱과 관련된 기술 세부정보를 제공합니다.
Control Center는 최소 SDK 버전 35 (Android V (API 수준 35))가 필요한 번들 해제된 권한이 있는 시스템 서명 앱입니다. 앱이 System APIs을 사용하기 위해 system/priv-app에 설치됩니다. 미디어 정보를 읽으려면 앱이 플랫폼 서명되어야 합니다. 무선 (OTA)으로 앱을 업데이트할 수 있습니다.
백그라운드 서비스
제어 센터 앱은 기능을 위해 백그라운드 서비스를 사용합니다.
Control Center Service은 Vendor ServiceController에 의해 사용자 수명 주기의 user-post-unlocked 상태에서 시작됩니다. 제어 센터는 항상 활성 상태여야 하며 백그라운드에서 통신해야 합니다. 앱이 사용자에 의해 열리는 것에 의존할 수 없습니다.
Control Center Service는 Communication API를 사용하여 다른 점유자 영역에 있는 자체의 다른 인스턴스에 연결하고 통신합니다. 통합 가이드를 읽으면 각 사용자의 제어 센터 인스턴스가 연결을 설정하고 데이터를 전송 및 수신하는 방법을 이해하는 데 도움이 됩니다.

커뮤니케이션
연결되면 Control Center Service은 정보를 전달하는 protobuf 객체와 통신합니다. Communication APIs을 사용하여 protobuf을 다른 점유자 영역으로 전달하기 위해 protobuf은 byte array로 변환되고 payload object이 생성되며 Payload은 CarOccupantConnectionManager#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에 전달되고, 로컬 OccupantZoneStateRepository는 변경사항을 뷰에 알립니다. 대부분의 데이터는 Kotlin flows on Android를 사용하여 클래스 간에 전달됩니다.
차량 스피커 오디오 요청 처리
운전자가 항상 승객이 차량 스피커를 통해 오디오를 재생하도록 요청을 수신할 수 있도록 생성 시 운전자의 Control Center Service가 Primary ZoneMedia Audio RequestCallback를 등록합니다.
콜백은 CarAudioManager#requestMediaAudioOnPrimaryZone 호출에 관해 알림을 받습니다. 드라이버의 Control Center Service는 CarAudioManager#allowMediaAudioOnPrimaryZone(boolean)를 통해 수락하거나 거부할 수 있는 헤드업 알림(HUN)을 만들어 요청을 처리합니다.
다른 화면에서 동영상 공동 시청하기
공동 시청은 CarActivityManager의 Task Mirroring APIs 덕분에 작동합니다. TaskMirroringManager는 먼저 재생 중인 MediaSession 앱의 패키지를 CarActivityManager#getVisibleTasks에서 검색한 다음 VirtualDisplay를 만들고 CarActivityManager#moveRootTaskToDisplay를 통해 표시되는 작업을 이 디스플레이로 이동합니다.
이렇게 하면 MirroredSurfaceView가 레이아웃에서 MirroredSurfaceView#mirrorSurface을 통해 작업을 표시하는 데 사용할 수 있는 IBinder 토큰이 반환됩니다.
Communication API Payload 객체가 토큰을 다른 점유자 영역에 전달했습니다.
이러한 점유자 영역의 각 제어 센터 인스턴스는 Mirroring activity를 실행하고 이 토큰을 사용하여 MirroredSurfaceView를 채웁니다.

작업 미러링 API
Control Center는 다음 작업 미러링 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_
이러한 구성은 클라이언트 앱 리소스와 제어 센터 리소스에 있어야 합니다.

디버그 제어 센터
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)
}
}
...
시스템 앱 및 업데이트 가능성
제어 센터는 서명 전용 권한을 사용하므로 시스템 앱이자 플랫폼 서명 앱이기 때문에 제어 센터는 기기에 미리 설치해야 하며 자동차 미디어 앱과 마찬가지로 OTA로만 업데이트할 수 있습니다.
소스에서 제어 센터 빌드
제어 센터 소스 코드를 가져오려면 번들로 묶이지 않은 앱 통합을 참고하세요.
다중 디스플레이를 통한 사용자 개인 정보 보호
제어 센터를 사용하면 모든 자동차 승객이 모든 디스플레이에서 미디어 정보를 볼 수 있습니다. 사용자에게 알리기 위해 차단되지 않는 개인 정보 보호 고지를 삽입하는 것이 좋습니다. 디스플레이에 로그인할 때 시스템 수준에서 이 작업을 실행하는 것이 좋습니다.