볼륨 관리

AAOS에는 CarAudioService 내에 자체 볼륨 관리가 있습니다. 볼륨 관리는 볼륨이 소프트웨어가 아닌, 하드웨어 앰프로 인해 HAL 아래에 적용되어야 한다는 점을 바탕으로 고정 볼륨을 사용합니다. 또한 출력 장치를 볼륨 그룹으로 구성하여 볼륨 그룹에 연결된 모든 기기에 동일한 게인을 적용합니다.

고정 볼륨 사용

AAOS 구현은 소프트웨어 믹서 대신 하드웨어 앰프를 사용하여 볼륨을 제어해야 합니다. 부작용을 피하기 위해 config_useFixedVolume 플래그를 true로 설정합니다(필요한 경우 오버레이함).

<resources>
    <!-- Car uses hardware amplifier for volume. -->
    <bool name="config_useFixedVolume">true</bool>
</resources>

config_useFixedVolume 플래그가 설정되지 않았거나 false로 설정된 경우 애플리케이션에서 AudioManager.setStreamVolume()을 호출하고 소프트웨어 믹서의 스트림 유형별로 볼륨을 변경할 수 있습니다. 이는 다른 애플리케이션에 잠재적인 영향을 미치고, 소프트웨어 믹서의 볼륨 감쇠로 인해 하드웨어 앰프에서 수신 시 신호에서 사용 가능한 중요 비트 수가 적어지기 때문에 바람직하지 않을 수 있습니다.

볼륨 그룹

볼륨 그룹은 오디오 영역 내 기기 모음의 볼륨을 관리합니다. 볼륨 그룹별로 독립적으로 볼륨을 제어할 수 있으며, 결과 게인은 차량의 앰프에 의해 연결 기기에 적용되도록 구성됩니다. 볼륨 설정이 사용자에게 유지되며 사용자가 로그인하면 로드됩니다.

볼륨 그룹 정의

CarAudioService는 car_audio_configuration.xml에 정의된 볼륨 그룹을 사용합니다.

<audioZoneConfiguration version="2.0">
    <zones>
        <zone name="primary zone" isPrimary="true">
            <volumeGroups>
                <group>
                    <device address="bus0_media_out">
                        <context context="music"/>
                    </device>
                </group>
                <group>
                    <device address="bus1_navigation_out">
                        <context context="navigation"/>
                    </device>
                    <device address="bus2_voice_command_out">
                        <context context="voice_command"/>
                    </device>
                </group>
                ...
            </volumeGroups>
        </zone>
     </zones>
</audioZoneConfiguration>

car_audio_configruation.xml 구현 예시입니다.

각 볼륨 그룹에는 연결된 주소가 있는 출력 장치가 한 개 이상 포함되어야 합니다. 이 주소는 audio_policy_configuration.xml에 정의된 출력 장치에 상응해야 합니다.

볼륨 그룹 게인 구성

각 볼륨 그룹에는 최소, 최대, 기본 게인 값과 단계 크기가 있습니다. 이러한 값은 볼륨 그룹에 연결된 기기에 관해 audio_policy_configuration.xml에 구성된 값에 따라 결정됩니다.

<devicePort tagName="bus0_media_out" role="sink" type="AUDIO_DEVICE_OUT_BUS" address="bus0_media_out">
  <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
  <gains>
    <gain name="" mode="AUDIO_GAIN_MODE_JOINT"
      minValueMB="-3200" maxValueMB="600" defaultValueMB="0" stepValueMB="100"/>
  </gains>
</devicePort>

초기화 중에 볼륨 그룹은 연결된 기기의 게인 값을 확인하고 다음과 같이 그룹을 구성합니다.

  • 단계 크기. 볼륨 그룹이 제어하는 모든 기기에서 동일해야 함
  • 최소 게인. 그룹의 기기 중 가장 작은 최소 게인
  • 최대 게인. 그룹의 기기 중 가장 큰 최대 게인
  • 기본 게인. 그룹의 기기 중 가장 큰 기본 게인

이러한 값이 구성되는 방식 때문에 볼륨 그룹과 연결된 기기에 지원되는 범위를 벗어난 볼륨 그룹의 게인을 설정하는 것이 가능합니다. 이런 기기의 경우 볼륨 그룹의 값이 범위보다 낮은지 높은지에 따라 게인이 기기의 최소 또는 최대 게인 값으로 설정됩니다.

볼륨 그룹 식별자

볼륨 그룹은 런타임 시 XML 파일에 정의된 순서에 따라 식별됩니다. ID의 범위는 오디오 영역 내에서 0부터 N-1 사이이며, 여기서 N은 오디오 영역에 있는 볼륨 그룹의 수입니다. 이에 따라 볼륨 그룹 ID는 영역에서 고유하지 않습니다. 이 식별자는 볼륨 그룹과 연결된 CarAudioManager API에 사용됩니다. zoneId 없이 groupId를 사용하는 모든 API는 기본 오디오 영역으로 기본 설정됩니다.

다중 영역 볼륨 관리

각 오디오 영역에는 볼륨 그룹이 하나 이상 있어야 하고, 각 볼륨 그룹은 단일 오디오 영역과만 연결됩니다. 이 관계는 car_audio_configuration.xml의 일부로 정의됩니다. 위의 볼륨 그룹 정의에 나온 예시를 참고하세요.

각 영역의 현재 볼륨 수준은 영역과 연결된 사용자에게 유지됩니다. 이러한 설정은 영역별로 다릅니다. 즉, 사용자가 기본 영역과 연결된 디스플레이에서 로그인한 다음 이후에 보조 오디오 영역과 연결된 영역에 로그인하는 경우 첫 번째 영역용으로 로드되고 유지되는 볼륨 수준과 보조 영역의 볼륨 수준은 다릅니다.

볼륨 키 이벤트 처리

Android에서는 볼륨 제어를 위해 KEYCODE_VOLUME_UP, KEYCODE_VOLUME_DOWNKEYCODE_VOLUME_MUTE 등의 여러 키 코드를 정의합니다. 기본적으로 Android에서는 볼륨 키 이벤트를 애플리케이션으로 라우팅합니다. Automotive 구현은 이러한 키 이벤트를 CarAudioService로 강제 라우팅해야 하며, 그런 다음 setGroupVolume 또는 setMasterMute를 적절하게 호출할 수 있습니다.

이 동작을 강제하려면 config_handleVolumeKeysInWindowManager 플래그를 true로 설정합니다.

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

볼륨 키 이벤트는 현재 의도한 영역을 구별할 수 있는 방법이 없으며 모두 기본 오디오 영역과 연결되어 있다고 가정합니다. 볼륨 키 이벤트가 수신되면 CarAudioService는 활성 플레이어의 오디오 컨텍스트를 가져와 조정할 볼륨 그룹을 결정한 다음 가장 우선순위가 높은 오디오 컨텍스트와 연결된 출력 장치가 포함된 볼륨 그룹을 조정합니다. 우선순위는 CarVolume.AUDIO_CONTEXT_VOLUME_PRIORITY에 정의된 고정 순서에 따라 결정됩니다.

페이드 및 밸런스

두 AudioControl HAL 버전에는 모두 차량의 페이드와 밸런스를 설정하는 API가 있습니다. AudioControl HAL에 값을 전달하는, CarAudioManager에 상응하는 시스템 API가 있습니다. 이 API에는 android.car.permission.CAR_CONTROL_AUDIO_VOLUME이 필요합니다.

AudioControl API는 다음과 같습니다.

  • setBalanceTowardRight(float value) - 스피커 볼륨을 차량의 오른쪽(+)이나 왼쪽(-)으로 이동합니다. 0.0은 중앙으로, +1.0은 맨 오른쪽으로, -1.0은 맨 왼쪽으로 이동하는 것을 의미하며, -1과 1 사이 범위를 벗어난 값은 오류입니다.
  • setFadeTowardFront(float value) - 스피커 볼륨을 차량의 전면(+)이나 후면(-)으로 이동합니다. 0.0은 중앙으로, +1.0은 맨 앞으로, -1.0은 맨 뒤로 이동하는 것을 의미하며, -1과 1 사이 범위를 벗어난 값은 오류입니다.

이 값을 적용하는 방법과 사용자에게 표시하는 방식은 OEM이 결정합니다. 미디어에만 적용하거나 전체적으로 모든 Android 사운드에 적용할 수 있습니다.

Android 11에는 출력 장치에 오디오 효과를 적용하기 위한 지원도 도입되었습니다. 이에 따라 이러한 API를 사용하는 대신 적절한 출력 장치에서 오디오 효과를 통해 페이드와 밸런스를 관리할 수 있습니다.

오디오 볼륨 낮추기

오디오 볼륨 낮추기는 차량이 동시에 재생되는 다른 스트림이 더 선명하게 들리도록 스트림 하나의 게인을 줄이는 것입니다. AAOS에서는 OS가 제어할 수 없는 Android 외부 사운드가 많이 있을 수 있으므로 HAL이 오디오 볼륨 낮추기를 구현합니다. Android 11에서 볼륨 낮추기 결정을 위해 HAL에 제공되는 기본 정보는 두 출력 장치 모두에 활성 스트림이 있는지 여부입니다.

볼륨 낮추기가 필요한 경우

HAL이 볼륨 낮추기를 처리하는 방식을 결정하는 것은 개별 OEM에 달려 있지만, 일반적으로 권장되는 일반적인 가이드라인이 있습니다. Android 내에서 여러 스트림이 재생되는 일은 두 앱/서비스가 동시에 오디오 포커스를 보유할 때 가장 흔히 발생합니다. 이 점을 고려하여 상호작용 매트릭스에서 Android가 동시 포커스를 부여할 수 있는 경우 및 서로 다른 두 스트림이 동시에 재생될 수 있는 경우에 관해 알아보세요.

Android가 믹싱하는 스트림은 게인이 적용되기 전에 믹싱 처리된다는 점에 유의하세요. 따라서 다른 스트림과 동시에 재생될 때 볼륨을 낮춰야 하는 스트림은 HAL이 스트림 믹싱 전에 볼륨 낮추기를 적용할 수 있도록 별개의 출력 장치로 라우팅되어야 합니다.

권장되는 볼륨 낮추기 동작

다음은 볼륨 낮추기를 적용하도록 권장되는 동시 상호작용입니다.

  • EMERGENCY. 운전자가 사운드를 들을 수 있도록 SAFETY를 제외한 모든 스트림을 음소거하거나 볼륨 낮추기
  • SAFETY. 운전자가 사운드를 들을 수 있도록 EMERGENCY를 제외한 모든 스트림의 볼륨 낮추기
  • NAVIGATION. SAFETYEMERGENCY를 제외한 모든 스트림의 볼륨 낮추기
  • CALL. SAFETY, EMERGENCY, NAVIGATION을 제외한 모든 스트림의 볼륨 낮추기
  • VOICE. CALL_RING의 볼륨 낮추기
  • 활성 VEHICLE_SOUNDS의 중요도 및 운전자가 들을 수 있도록 다른 사운드의 볼륨을 낮춰야 할지 여부는 OEM이 결정합니다.
  • 다른 모든 스트림이 MUSICANNOUNCEMENT의 볼륨을 낮출 수 있어야 합니다. 가장 큰 예외는 현재 SYSTEM_SOUND로 재생되는 터치 상호작용 알림음입니다.

볼륨 낮추기의 기타 고려사항

내비게이션이나 어시스턴트 같은 일부 앱/서비스는 작업을 완료하는 데 여러 플레이어를 사용할 수도 있습니다. 사용자가 볼륨 낮추기가 적용되기 전에 미디어를 최대 볼륨으로 잠시 되돌렸다가 내비게이션 앱이나 어시스턴트 앱의 다음 재생이 시작되면 볼륨을 다시 낮추는 일이 없도록 하기 위해 OEM은 출력 장치에서 수신되는 스트림 데이터가 중지되는 시점을 기준으로 너무 공격적으로 볼륨 낮추기를 취소하지 않아야 합니다.

잘 격리되는 여러 사운드 단계가 있는 차량의 경우 볼륨 낮추기 대신 오디오를 차량의 서로 다른 영역으로 라우팅하는 옵션도 있습니다. 예를 들어 음악을 차량 실내 전체에서 정상 볼륨으로 계속 재생하고 내비게이션 안내는 운전자 머리 받침대에 있는 스피커로 라우팅할 수 있습니다.

안전에 중요한 사운드

Android 11에는 HAL 오디오 포커스 API가 도입되었지만, 안전에 중요한 사운드가 다른 사운드보다 우선하도록 하는 것은 여전히 HAL이 담당합니다. HAL이 USAGE_EMERGENCY의 오디오 포커스를 보유하더라도 Android 내의 앱과 서비스가 사운드를 재생하지 못하도록 보장하지는 않습니다. 안전에 중요한 사운드가 재생될 때 Android의 어떤 스트림을 믹싱하거나 음소거해야 할지를 결정하는 것은 HAL에 달려 있습니다.

볼륨 설정 UI 구성

AAOS에서는 볼륨 그룹 구성에서 볼륨 설정 UI를 분리합니다(볼륨 그룹 구성에서 설명하는 것처럼 오버레이 가능). 이렇게 분리한 덕분에 향후 볼륨 그룹 구성이 변경되어도 UI를 변경할 필요가 없습니다.

자동차 설정 UI에서 packages/apps/Car/Settings/res/xml/car_volume_items.xml 파일에는 정의된 각 AudioAttributes.USAGE와 연결된 UI 요소(제목 및 아이콘 리소스)가 포함됩니다. 이 파일은 각 VolumeGroup에 포함된 사용 중 첫 번째로 인식된 사용과 연결된 리소스를 사용하여 정의된 VolumeGroups의 적절한 렌더링을 제공합니다.

예를 들어 다음 예에서는 VolumeGroup을 voice_communicationvoice_communication_signalling을 모두 포함하는 것으로 정의합니다. 자동차 설정 UI의 기본 구현은 voice_communication이 파일에서 첫 번째 일치하는 항목이므로 이와 연결된 리소스를 사용하여 VolumeGroup을 렌더링합니다.

<carVolumeItems xmlns:car="http://schemas.android.com/apk/res-auto">
    <item car:usage="voice_communication"
          car:title="@*android:string/volume_call"
          car:icon="@*android:drawable/ic_audio_ring_notif"/>
    <item car:usage="voice_communication_signalling"
          car:title="@*android:string/volume_call"
          car:icon="@*android:drawable/ic_audio_ring_notif"/>
    <item car:usage="media"
          car:title="@*android:string/volume_music"
          car:icon="@*android:drawable/ic_audio_media"/>
    <item car:usage="game"
          car:title="@*android:string/volume_music"
          car:icon="@*android:drawable/ic_audio_media"/>
    <item car:usage="alarm"
          car:title="@*android:string/volume_alarm"
          car:icon="@*android:drawable/ic_audio_alarm"/>
    <item car:usage="assistance_navigation_guidance"
          car:title="@string/navi_volume_title"
          car:icon="@drawable/ic_audio_navi"/>
    <item car:usage="notification_ringtone"
          car:title="@*android:string/volume_ringtone"
          car:icon="@*android:drawable/ic_audio_ring_notif"/>
    <item car:usage="assistant"
          car:title="@*android:string/volume_unknown"
          car:icon="@*android:drawable/ic_audio_vol"/>
    <item car:usage="notification"
          car:title="@*android:string/volume_notification"
          car:icon="@*android:drawable/ic_audio_ring_notif"/>
    <item car:usage="notification_communication_request"
          car:title="@*android:string/volume_notification"
          car:icon="@*android:drawable/ic_audio_ring_notif"/>
    <item car:usage="notification_communication_instant"
          car:title="@*android:string/volume_notification"
          car:icon="@*android:drawable/ic_audio_ring_notif"/>
    <item car:usage="notification_communication_delayed"
          car:title="@*android:string/volume_notification"
          car:icon="@*android:drawable/ic_audio_ring_notif"/>
    <item car:usage="notification_event"
          car:title="@*android:string/volume_notification"
          car:icon="@*android:drawable/ic_audio_ring_notif"/>
    <item car:usage="assistance_accessibility"
          car:title="@*android:string/volume_notification"
          car:icon="@*android:drawable/ic_audio_ring_notif"/>
    <item car:usage="assistance_sonification"
          car:title="@*android:string/volume_unknown"
          car:icon="@*android:drawable/ic_audio_vol"/>
    <item car:usage="unknown"
          car:title="@*android:string/volume_unknown"
          car:icon="@*android:drawable/ic_audio_vol"/>
</carVolumeItems>

위의 구성에 사용된 속성과 값은 packages/apps/Car/Settings/res/values/attrs.xml에 선언됩니다. 볼륨 설정 UI는 다음 VolumeGroup 기반 CarAudioManager API를 사용합니다.

  • getVolumeGroupCount(): 그려야 하는 컨트롤 수를 알 수 있습니다.
  • getGroupMinVolume()getGroupMaxVolume(): 하한 및 상한을 가져옵니다.
  • getGroupVolume(): 현재 볼륨을 가져옵니다.
  • registerVolumeChangeObserver(): 볼륨 변경 시 알림을 받습니다.