Google은 흑인 공동체를 위한 인종 간 평등을 진전시키기 위해 노력하고 있습니다. Google에서 어떤 노력을 하고 있는지 확인하세요.

AudioControl HAL 구현

Android 9에서는 차량 HAL의 이전 반복에서 사용된 AUDIO_* 속성을 적절하지 않은 것으로 판단해, 명시적 함수 호출 및 입력된 매개변수 목록을 포함하는 전용 Audio Control HAL로 대체했습니다.

이 새로운 HAL은 구성과 볼륨 조절을 위해 차량의 오디오 엔진과 상호 작용할 시작 지점을 제공하는 기본 인터페이스 개체로 IAudioControl을 노출합니다. 시스템은 CarAudioService가 시작 시 생성하는 이 개체의 인스턴스를 정확히 하나만 포함할 수 있습니다. 이 개체는 전통적인 Android Audio HAL의 자동차용 확장 프로그램으로, 대부분의 구현에서 오디오 HAL 인터페이스를 게시하는 동일한 프로세스가 IAudioControl interfaces도 게시해야 합니다.

지원되는 인터페이스

AudioControl HAL은 다음 인터페이스를 지원합니다.

  • getBusforContext. ContextNumber에서 busAddress으로 매핑을 가져오기 위해 컨텍스트마다 시작 시 한 번 호출됩니다. 사용 예:
        getBusForContext(ContextNumber contextNumber)
            generates (uint32_t busNumber);
        
    차량이 프레임워크에 각 컨텍스트에 대한 물리적 출력 스트림을 라우팅할 지점을 알릴 수 있도록 합니다. 모든 컨텍스트에 대해 유효한 버스 번호(0 - num busses-1)가 반환되어야 합니다. 인식할 수 없는 contextNumber가 있으면 -1이 반환됩니다. 잘못된 busNumber가 반환되는 컨텍스트는 버스 0으로 라우팅됩니다.

    Android HAL로 단일 스트림으로 전달되기 전에 이 메커니즘을 통해 동일한 busNumber와 연결된 모든 동시 사운드는 Android AudioFlinger에서 믹싱합니다. 이는 차량 HAL 속성 AUDIO_HW_VARIANTAUDIO_ROUTING_POLICY를 대체합니다.
  • setBalanceTowardRight. 차량 스피커의 좌우 밸런스 설정을 제어합니다. 사용 예:
        setBalanceTowardRight(float value);
        
    스피커 볼륨을 차량의 오른쪽(+) 또는 왼쪽(-)으로 이동합니다. 0.0은 중앙에, -1.0은 맨 오른쪽으로 -1.0은 맨 왼쪽으로 이동하고, -1과 1 사이의 범위를 벗어난 값은 오류입니다.
  • setFadeTowardFront. 차량 스피커의 전후방 페이드 설정을 제어합니다. 사용 예:
        setFadeTowardFront(float value);
        
    스피커 볼륨을 차량의 정면(+) 또는 후면(-) 방향으로 이동합니다. 0.0은 중앙으로, +1은 맨 앞으로, -1.0은 맨 뒤로 이동하고, -1과 1 사이 범위를 벗어난 값은 오류입니다.

볼륨 구성

Android Automotive 구현은 소프트웨어 믹서 대신 하드웨어 앰프를 사용하여 볼륨을 제어해야 합니다. 부작용을 피하기 위해 device/generic/car/emulator/audio/overlay/frameworks/base/core/res/res/values/config.xml에서 config_useFixedVolume 플래그를 true(필요한 경우 오버레이)로 설정합니다.

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

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

볼륨 그룹 구성

CarAudioServicepackages/services/Car/service/res/xml/car_volume_group.xml에서 정의된 볼륨 그룹을 사용합니다. 이 파일을 재정의하여 필요한 만큼 볼륨 그룹을 다시 정의할 수 있습니다. 그룹은 런타임 시 XML 파일의 정의 순서에 따라 식별됩니다. ID의 범위는 0에서 N-1이며, 여기서 N은 볼륨 그룹의 수입니다. 예:

    <volumeGroups xmlns:car="http://schemas.android.com/apk/res-auto">
        <group>
            <context car:context="music"/>
            <context car:context="call_ring"/>
            <context car:context="notification"/>
            <context car:context="system_sound"/>
        </group>
        <group>
            <context car:context="navigation"/>
            <context car:context="voice_command"/>
        </group>
        <group>
            <context car:context="call"/>
        </group>
        <group>
            <context car:context="alarm"/>
        </group>
    </volumeGroups>
    

이 구성에서 사용되는 속성은 packages/services/Car/service/res/values/attrs.xml에 정의되어 있습니다.

볼륨 키 이벤트 처리

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

이 동작을 강제로 수행하도록 하려면 device/generic/car/emulator/car/overlay/frameworks/base/core/res/res/values/config.xml에서 config_handleVolumeKeysInWindowManager 플래그를 true로 설정합니다.

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

CarAudioManager API

CarAudioManagerCarAudioService를 사용하여 차량 오디오 시스템을 구성하고 제어합니다. 관리자는 시스템의 대부분의 앱에서 보이지 않지만 볼륨 컨트롤러와 같은 차량 관련 구성요소는 CarAudioManager API를 사용하여 시스템과 상호 작용할 수 있습니다.

다음 섹션에서는 Android 9에서 CarAudioManager API에 대한 변경 사항에 대해 설명합니다.

지원 중단된 API

Android 9는 기존 AudioManager getDeviceList API를 통해 기기 열거를 처리하므로 다음 차량 관련 함수가 더 이상 사용되지 않아 제거되었습니다.

  • String[] getSupportedExternalSourceTypes()
  • String[] getSupportedRadioTypes()

Android 9은 AudioAttributes.AttributeUsage 또는 볼륨 그룹 기반 진입점을 사용하여 볼륨을 처리하므로 streamType을 사용하는 다음 API가 삭제되었습니다.

  • void setStreamVolume(int streamType, int index, int flags)
  • int getStreamMaxVolume(int streamType)
  • int getStreamMinVolume(int streamType)
  • void setVolumeController(IVolumeController controller)

새로운 API

Android 9에는 볼륨 그룹을 기반으로 명시적으로 앰프 하드웨어를 제어하기 위해 다음과 같은 새 API를 추가했습니다.

  • int getVolumeGroupIdForUsage(@AudioAttributes.AttributeUsage int usage)
  • int getVolumeGroupCount()
  • int getGroupVolume(int groupId)
  • int getGroupMaxVolume(int groupId)
  • int getGroupMinVolume(int groupId)

또한 Android 9은 시스템 GUI에서 사용할 수 있도록 다음과 같은 새로운 시스템 API를 제공합니다.

  • void setGroupVolume(int groupId, int index, int flags)
  • void registerVolumeChangeObserver(@NonNull ContentObserver observer)
  • void unregisterVolumeChangeObserver(@NonNull ContentObserver observer)
  • void registerVolumeCallback(@NonNull IBinder binder)
  • void unregisterVolumeCallback(@NonNull IBinder binder)
  • void setFadeToFront(float value)
  • Void setBalanceToRight(float value)

마지막으로 Android 9에서는 외부 소스 관리를 위한 새로운 API가 추가되었습니다. 이러한 API는 주로 미디어 유형에 따라 외부 소스에서 출력 버스로의 오디오 라우팅을 지원하기 위한 용도입니다. 또한 외부 기기에 타사 애플리케이션이 액세스하도록 허용할 수도 있습니다.

  • String[] getExternalSources(). AUX_LINE, FM_TUNER, TV_TUNERBUS_INPUT 유형의 시스템에서 사용 가능한 오디오 포트를 식별하는 주소 배열을 반환합니다.
  • CarPatchHandle createAudioPatch(String sourceAddress, int carUsage). 제공된 carUsage와 연결된 출력 BUS로 소스 주소를 라우팅합니다.
  • int releaseAudioPatch(CarPatchHandle patch). 제공된 패치를 삭제합니다. CarPatchHandle의 생성자가 예기치 않게 종료되면 AudioPolicyService::removeNotificationClient()가 자동으로 처리합니다.

오디오 패치 만들기

두 오디오 포트(믹스 포트 또는 기기 포트) 사이에 오디오 패치를 만들 수 있습니다. 일반적으로 믹스 포트에서 기기 포트로의 오디오 패치는 재생용이고 그 반대 방향은 캡처용입니다.

예를 들어 FM_TUNER 소스의 오디오 샘플을 미디어 싱크로 직접 라우팅하는 오디오 패치는 소프트웨어 믹서를 우회합니다. 그런 다음 하드웨어 믹서를 사용하여 Android 및 FM_TUNER의 오디오 샘플을 싱크에 믹싱해야 합니다. FM_TUNER 소스에서 미디어 싱크로 직접 오디오 패치를 만드는 경우:

  • 볼륨 조절은 미디어 싱크에 적용되며 Android 및 FM_TUNER 오디오 둘 다에 영향을 미쳐야 합니다.
  • 사용자는 간단한 앱 전환을 통해 Android와 FM_TUNER 오디오 간에 전환할 수 있어야 합니다. 명확하게 미디어 소스를 선택하지 않아도 됩니다.

또한 Automotive 구현은 두 개의 기기 포트 사이에 오디오 패치를 만들어야 할 수도 있습니다. 이렇게 하려면 먼저 audio_policy_configuration.xml에서 기기 포트와 가능한 경로를 선언하고 mixports를 이러한 기기 포트와 연결해야 합니다.

구성의 예

device/generic/car/emulator/audio/audio_policy_configuration.xml을 참조하세요.

    <audioPolicyConfiguration>
        <modules>
            <module name="primary" halVersion="3.0">
                <attachedDevices>
                    <item>bus0_media_out</item>
                    <item>bus1_audio_patch_test_in</item>
                </attachedDevices>
                <mixPorts>
                    <mixPort name="mixport_bus0_media_out" role="source"
                            flags="AUDIO_OUTPUT_FLAG_PRIMARY">
                        <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                                samplingRates="48000"
                                channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
                    </mixPort>
                    <mixPort name="mixport_audio_patch_in" role="sink">
                        <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                               samplingRates="48000"
                               channelMasks="AUDIO_CHANNEL_IN_STEREO"/>
                    </mixPort>
                </mixPorts>
                <devicePorts>
                    <devicePort tagName="bus0_media_out" role="sink" type="AUDIO_DEVICE_OUT_BUS"
                            address="bus0_media_out">
                        <profile balance="" format="AUDIO_FORMAT_PCM_16_BIT"
                                samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
                        <gains>
                            <gain name="" mode="AUDIO_GAIN_MODE_JOINT"
                                    minValueMB="-8400" maxValueMB="4000" defaultValueMB="0" stepValueMB="100"/>
                        </gains>
                    </devicePort>
                    <devicePort tagName="bus1_audio_patch_test_in" type="AUDIO_DEVICE_IN_BUS" role="source"
                            address="bus1_audio_patch_test_in">
                        <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                                samplingRates="48000" channelMasks="AUDIO_CHANNEL_IN_STEREO"/>
                        <gains>
                            <gain name="" mode="AUDIO_GAIN_MODE_JOINT"
                                    minValueMB="-8400" maxValueMB="4000" defaultValueMB="0" stepValueMB="100"/>
                        </gains>
                    </devicePort>
                </devicePorts>
                <routes>
                    <route type="mix" sink="bus0_media_out" sources="mixport_bus0_media_out,bus1_audio_patch_test_in"/>
                    <route type="mix" sink="mixport_audio_patch_in" sources="bus1_audio_patch_test_in"/>
                </routes>
            </module>
        </modules>
    </audioPolicyConfiguration>
    

오디오 드라이버 API

getExternalSources()를 사용하여 (주소로 식별된) 사용 가능한 소스의 목록을 검색한 다음 이러한 소스와 싱크 포트 사이에 오디오 사용을 기준으로 오디오 패치를 만들 수 있습니다. 오디오 HAL의 해당 진입점이 IDevice.hal에 나타납니다.

    Interface IDevice {
    ...
    /
    * Creates an audio patch between several source and sink ports.  The handle
    * is allocated by the HAL and must be unique for this audio HAL module.
    *
    * @param sources patch sources.
    * @param sinks patch sinks.
    * @return retval operation completion status.
    * @return patch created patch handle.
    */
    createAudioPatch(vec<AudioPortConfig> sources, vec<AudioPortConfig> sinks)
           generates (Result retval, AudioPatchHandle patch);

    /
    * Release an audio patch.
    *
    * @param patch patch handle.
    * @return retval operation completion status.
    */
    releaseAudioPatch(AudioPatchHandle patch) generates (Result retval);
    ...
    }
    

볼륨 설정 UI 구성

Android 9은 볼륨 그룹 구성에서 볼륨 설정 UI를 분리합니다(볼륨 그룹 구성에서 설명하는 것처럼 중첩 가능). 이렇게 분리한 덕분에 향후 볼륨 그룹 구성이 변경될 경우 변경이 필요 없습니다.

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

예를 들어, 다음 예에서는 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():볼륨 변경 시 알림을 받습니다.