오디오 라우팅

Android 10에서는 car_audio_configuration.xmlcar_volumes_groups.xmlIAudioControl.getBusForContext를 대체합니다. 새 구성 파일에 영역 목록이 정의되어 있습니다. 각 영역에는 연결된 기기가 있는 하나 이상의 볼륨 그룹이 있으며 각 기기에는 해당 영역 내에서 라우팅해야 하는 컨텍스트가 있습니다. 모든 컨텍스트는 각 영역 내에 표시되어야 합니다.

오디오 라우팅 구성

일반적으로 공급업체 파티션에 있는 오디오 정책 파일은 보드의 오디오 하드웨어 구성을 나타냅니다. car_audio_configuration.xml에 참조된 모든 기기는 audio_policy_configuration.xml 내에서 정의해야 합니다.

AAOS 라우팅 사용 설정

AAOS 기반 라우팅을 사용하려면 audioUseDynamicRouting 플래그를 true로 설정해야 합니다.

<resources>
    <bool name="audioUseDynamicRouting">true</bool>
</resources>

false인 경우 라우팅 및 많은 CarAudioService가 사용 중지되며 OS가 AudioService의 기본 동작으로 대체됩니다.

기본 영역

기본적으로 모든 오디오는 기본 영역으로 라우팅됩니다. 기본 영역은 하나만 있을 수 있으며 구성에서 isPrimary="true" 속성으로 표시됩니다.

샘플 구성

예를 들어 차량에는 기본 영역과 뒷좌석 엔터테인먼트 시스템, 이렇게 두 영역이 있을 수 있습니다. 이 점을 고려하면 가능한 car_audio_configuration.xml은 다음과 같이 정의됩니다.

<audioZoneConfiguration version="2.0">
       <zone name="primary zone" isPrimary="true">
           <volumeGroups>
               <group>
                   <device address="bus0_media_out">
                       <context context="music"/>
                       <context context="announcement"/>
                   </device>
                   <device address="bus3_call_ring_out">
                       <context context="call_ring"/>
                   </device>
                   <device address="bus6_notification_out">
                       <context context="notification"/>
                   </device>
                   <device address="bus7_system_sound_out">
                       <context context="system_sound"/>
                       <context context="emergency"/>
                       <context context="safety"/>
                       <context context="vehicle_status"/>
                   </device>
               </group>
               <group>
                   <device address="bus1_navigation_out">
                       <context context="navigation"/>
                   </device>
                   <device address="bus2_voice_command_out">
                       <context context="voice_command"/>
                   </device>
               </group>
               <group>
                   <device address="bus4_call_out">
                       <context context="call"/>
                   </device>
               </group>
               <group>
                   <device address="bus5_alarm_out">
                       <context context="alarm"/>
                   </device>
               </group>
           </volumeGroups>
       </zone>
        <zone name="rear seat zone" audioZoneId="1">
           <volumeGroups>
               <group>
                   <device address="bus100_rear_seat">
                       <context context="music"/>
                       <context context="navigation"/>
                       <context context="voice_command"/>
                       <context context="call_ring"/>
                       <context context="call"/>
                       <context context="alarm"/>
                       <context context="notification"/>
                       <context context="system_sound"/>
                       <context context="emergency"/>
                       <context context="safety"/>
                       <context context="vehicle_status"/>
                       <context context="announcement"/>
                   </device>
               </group>
           </volumeGroups>
    </zones>
</audioZoneConfiguration>

여기서 기본 영역은 컨텍스트를 서로 다른 기기로 분리했습니다. 이렇게 하면 HAL이 차량의 하드웨어를 사용하여 서로 다른 후처리 효과와 믹싱을 각 기기 출력에 적용할 수 있습니다. 기기는 미디어, 내비게이션, 통화, 알람의 4가지 볼륨 그룹으로 정렬되었습니다. 시스템이 useFixedVolume으로 구성된 경우 각 그룹의 볼륨 수준이 HAL로 전달되어 그러한 기기의 출력에 적용됩니다.

보조 영역의 경우 예상 출력은 단일 출력 장치를 통해 이루어집니다. 이 예에서는 작동이 단순하도록 모든 사용이 단일 기기 및 볼륨 그룹으로 라우팅됩니다.

점유 영역 오디오 구성

Android 11에서는 car_audio_configuraton.xml이 더욱 확장되어 새로운 필드 두 필드, 즉 audioZoneIdoccupantZoneId가 도입되었습니다. audioZoneId를 사용하여 영역 관리를 더 효율적으로 제어할 수 있습니다. 한편, occupantZoneId는 사용자 ID 기반 라우팅을 구성하는 데 사용할 수 있습니다.

이 새 필드를 사용하려면 car_audio_configuration.xml의 V2가 필요합니다. 위의 오디오 구성을 사용하고 점유 영역 ID와 오디오 영역 ID 간의 매핑을 위한 새 필드를 활용하면 볼륨 그룹 정의가 없는 새 구성을 다음과 같이 설정할 수 있습니다.

<audioZoneConfiguration version="2.0">
       <zone name="primary zone" isPrimary="true" occupantZoneId="0">
         ...
       </zone>
       <zone name="rear seat zone" audioZoneId="1" occupantZoneId="1">
         ...
       </zone>
    </zones>
</audioZoneConfiguration>

위의 구성은 기본 영역을 점유 영역 0으로, audioZoneId 1을 occupantZoneId 1로 매핑하도록 정의합니다. 일반적으로 점유 영역과 오디오 영역 간에 모든 매핑을 설정할 수 있지만 일대일로 매핑해야 합니다. 다음은 두 새 필드를 정의하는 규칙입니다.

  • 기본 영역의 audioZoneId는 항상 0입니다.
  • audioZoneId 번호와 occupantZoneId 번호는 반복할 수 없습니다.
  • audioZoneIdoccupantZoneId는 일대일 매핑만 가질 수 있습니다.

애플리케이션 UID를 통한 라우팅

Android 10에는 앱이 오디오 영역과 포커스를 쿼리하고 설정할 수 있도록 일련의 숨겨진 API가 CarAudioManager에 도입되었습니다.

int[] getAudioZoneIds();
int getZoneIdForUid(int uid);
boolean setZoneIdForUid(int zoneId, int uid);
boolean clearZoneIdForUid(int uid);

위의 API를 사용하면 자사 애플리케이션이 애플리케이션의 UID를 기반으로 오디오 라우팅을 관리할 수 있습니다. 따라서 오디오 영역 ID와 애플리케이션의 UID도 모두 필요합니다. 이 정보를 사용하여 CarAudioManager#setZoneIdForUid API를 통해 오디오 라우팅을 설정할 수 있습니다.

앱의 영역 변경

기본적으로 모든 오디오는 기본 영역으로 라우팅됩니다. 애플리케이션을 다른 영역으로 라우팅하도록 업데이트하려면 CarAudioManager#setZoneIdForUid를 사용합니다.

// Find zone to play
int zoneId = ...

// Find application's uid
Int uid = mContext.getPackageManager()
        .getApplicationInfo(mContext.getPackageName(), 0)
        .uid;

if (mCarAudioManager.setZoneIdForUid(zoneId, info.uid)) {
    Log.d(TAG, "Zone successfully updated");
} else {
    Log.d(TAG, "Failed to change zone");
}

참고: 스트림은 영역을 동적으로 전환할 수 없습니다. 따라서 재생을 중지하고 영역 변경을 위해 포커스를 다시 요청해야 합니다.

사용자 ID를 사용한 라우팅

애플리케이션의 UID 기반 라우팅을 사용하면 각 애플리케이션의 오디오 라우팅을 세밀하게 제어할 수 있지만, 애플리케이션에서 실제로 오디오 포커스를 요청하고 오디오를 재생하기 전에 각 애플리케이션의 오디오 라우팅을 정의해야 합니다. 이 문제를 완화하고 서드 파티 애플리케이션이 수정 없이 오디오를 재생할 수 있도록 CarAudioService는 차량 점유 영역과 오디오 영역 매핑을 사용하여 사용자 ID 기반 라우팅을 정의합니다. 이렇게 하면 사용자가 점유 영역에 로그인할 때 차량 오디오 서비스에 알림이 전송됩니다. 알림 신호를 통해 오디오 포커스 관리 및 라우팅이 모든 오디오 영역에서 자동으로 구성됩니다.

애플리케이션 UID 기반 라우팅은 계속 사용할 수 있지만 사용자 ID 라우팅과는 별도로 사용해야 합니다. 즉, 점유 영역과 차량 오디오 영역 간의 매핑이 정의된 경우 UID 기반 라우팅이 사용 중지되고 CarAudioManager#setZoneidForUid 호출 시 오류가 발생합니다.

오디오 라우팅과 포커스 관리는 점유 영역 관리로 단순화되었지만, 사용자는 여전히 점유 영역에 할당되어야 합니다. CarOccupantZoneManager#assignProfileUserToOccupantZone을 사용하면 됩니다. 이 API에는 사용자 관리 권한이 필요합니다. 현재는 OEM에서 일종의 시스템 UI를 통해 사용자의 점유 영역 할당을 관리할 것으로 예상됩니다. 그렇게 되면 애플리케이션 실행, 오디오 라우팅, 포커스 관리가 모두 사용자에 맞춰 자동으로 구성됩니다.

setPreferredDevice를 사용한 라우팅

위의 변경사항과 함께 Android 11에는 각 영역과 연결된 출력 장치를 쿼리하는 새로운 API도 있습니다. CarAudioManager#getOutputDeviceForUsage(int zoneId, int usage)입니다.

이 API를 사용하여 특정 영역의 출력 장치 및 오디오 속성 용도를 쿼리할 수 있습니다. 이러한 방식으로 자사 애플리케이션은 플레이어의 setPreferredDevice API를 활용하여 오디오를 다른 영역으로 라우팅할 수 있습니다. getOutputDeviceForUsage API는 시스템 API이며 PERMISSION_CAR_CONTROL_AUDIO_SETTINGS가 필요합니다. 다음은 setPreferredDevice API를 사용하여 특정 영역의 미디어 기기를 찾고 기기로 라우팅하는 예시입니다.

audioZoneId = ... ;
mediaDeviceInfo = mCarAudioManager
            .getOutputDeviceForUsage(audioZoneId, AudioAttributes.USAGE_MEDIA);
…
mPlayer.setPreferredDevice(mediaDeviceInfo);