오디오 포커스

논리적 스트림을 시작하기 전에 앱은 논리적 스트림에 사용되는 동일한 오디오 속성을 사용하여 오디오 포커스를 요청합니다. 앱은 자동차 사용 사례에서 예상대로 실행되려면 포커스 상실을 존중해야 합니다.

포커스 요청을 보내는 것이 좋긴 하지만 시스템에서 이를 강제하지는 않습니다. 따라서 포커스는 기본 오디오 제어 메커니즘이 아니라 재생을 간접적으로 제어하고 재생 중의 충돌을 방지하는 수단으로 생각하세요. 차량은 오디오 하위 시스템을 작동하기 위해 포커스 시스템을 사용해서는 안 됩니다.

포커스 상호작용

AAOS를 지원하기 위해 오디오 포커스 요청은 요청의 CarAudioContext와 현재 포커스 보유자 간 사전 정의된 상호작용에 기반하여 처리됩니다. 상호작용에는 세 가지 유형이 있습니다.

  • 배타적 상호작용
  • 거부 상호작용
  • 동시 상호작용

배타적 상호작용

이것이 Android에서 가장 일반적으로 사용되는 상호작용 모델입니다.

배타적 상호작용에서는 한 번에 한 앱만 포커스를 보유할 수 있습니다. 따라서 수신되는 포커스 요청에 포커스가 부여되고 기존 포커스 보유자는 포커스를 상실합니다. 두 앱에서 모두 미디어를 재생하므로 한 앱만 포커스를 보유할 수 있습니다. 따라서 새로 시작된 앱의 포커스 요청이 AUDIOFOCUS_REQUEST_GRANTED와 함께 반환되고, 현재 음악을 재생 중인 앱은 요청의 유형에 해당하는 포커스 변경 이벤트를 상실 상태와 함께 수신합니다.

거부 상호작용

거부 상호작용에서는 수신되는 요청이 항상 거부됩니다. 예를 들어 통화가 진행되는 동안 음악을 재생하려는 경우입니다. 다이얼러가 통화의 오디오 포커스를 보유하고 있는데 두 번째 앱이 음악 재생을 위해 포커스를 요청하는 경우 음악 앱은 요청에 대한 응답으로 AUDIOFOCUS_REQUEST_FAILED를 수신합니다. 포커스 요청이 거부되었으므로 현재 포커스 보유자에 포커스 상실이 전달되지 않습니다.

동시 상호작용

동시 상호작용은 AAOS에 고유한 기능입니다. 이를 사용하면 자동차에서 오디오 포커스를 요청하는 앱이 다른 앱과 동시에 포커스를 보유할 수 있습니다. 동시 상호작용이 발생하려면 다음 조건을 충족해야 합니다.

이러한 기준이 충족되면 포커스 요청이 AUDIOFOCUS_REQUEST_GRANTED와 함께 반환되고 현재 포커스 보유자는 포커스 변경사항이 없습니다. 하지만 현재 포커스 보유자가 볼륨 낮추기 이벤트를 수신하도록 또는 볼륨을 낮출 때 일시중지하도록 선택하면 현재 포커스 보유자는 배타적 상호작용과 마찬가지로 포커스를 상실합니다.

동시 스트림 처리

동시 상호작용의 용도는 여러 가지로 다양하지만 출력 장치 전반의 하드웨어 수준에서 믹싱과 볼륨 낮추기를 처리할 때는 주의해야 합니다. 동시 재생이 허용된 CarAudioContext는 다양한 출력 장치로 라우팅되는 것이 좋습니다.

동시 스트림을 위한 별도의 출력 장치가 있으면 HAL이 스트림을 믹싱하기 전에 두 스트림 중 하나의 볼륨을 낮추거나 물리적 스트림을 차량의 다른 스피커로 라우팅할 수 있습니다. 논리적 스트림이 Android 내에서 믹싱되는 경우 게인이 변경되지 않고 동일한 물리적 스트림의 일부로 제공됩니다.

예를 들어 내비게이션과 미디어가 동시에 제공될 때 내비게이션의 안내가 선명하게 들릴 수 있도록 미디어 스트림의 게인이 일시적으로 줄어들(볼륨을 낮출) 수 있습니다. 또는 내비게이션 스트림을 운전자 쪽 스피커로 라우팅하고 미디어는 계속 재생하여 차량에 있는 나머지 스피커를 통해 제공할 수도 있습니다.

상호작용 매트릭스

아래 표는 CarAudioService에서 정의된 상호작용 매트릭스를 보여줍니다. 각 행은 현재 포커스 보유자의 CarAudioContext를 나타내고 각 열은 수신 요청의 CarAudioContext를 나타냅니다.

예를 들어 음악 미디어 앱에 포커스가 있는 상황에서 내비게이션 앱이 포커스를 요청하는 경우, 매트릭스는 동시 상호작용의 다른 기준이 충족된다는 전제하에 이 두 가지 상호작용이 동시에 재생될 수 있음을 나타냅니다.

동시 상호작용으로 인해 포커스 보유자가 둘 이상 있을 수 있습니다. 이 경우 수신 포커스 요청을 현재 포커스 보유자와 각각 비교한 후 적용할 상호작용을 결정합니다. 이 경우에는 가장 보수적인 상호작용이 적용됩니다. 거부, 배타적, 동시 상호작용 순입니다.

오디오 포커스 상호작용 매트릭스

그림 1. 오디오 포커스 상호작용 매트릭스

Android 11에는 사용자가 내비게이션과 전화 통화 간의 상호작용 동작을 변경할 수 있도록 새로운 사용자 설정이 도입되었습니다. 설정되면 android.car.KEY_AUDIO_FOCUS_NAVIGATION_REJECTED_DURING_CALL은 수신되는 NAVIGATION 포커스 요청과 현재 CALL 포커스 보유자 간의 상호작용을 동시에서 거부로 변경합니다. 사용자가 내비게이션 안내로 인해 통화가 방해되는 것을 원하지 않으면 설정을 사용 설정하면 됩니다. 이 설정은 사용자에게 유지되며 후속 포커스 요청이 새 설정을 따르도록 동적으로 설정할 수 있습니다.

지연 가능한 오디오 포커스

AAOS는 Android 11에서 지연 가능한 오디오 포커스 요청을 지원합니다. 이에 따라, 일시적이지 않은 포커스 요청의 경우 현재 포커스 보유자와의 상호작용의 결과 일반적으로 거부되면 지연할 수 있습니다. 이후 포커스가 변경되어 지연된 요청이 포커스를 획득할 수 있는 상태가 되면 요청한 포커스가 부여됩니다.

지연된 오디오 포커스 요청의 규칙

  • 일시적이지 않은 요청만. 지연된 요청은 일시적인 사운드가 관련성이 없어진 후에도 오래 재생되는 것을 방지하기 위해 일시적이지 않은 소스의 경우에만 할 수 있습니다.

  • 한 번에 요청 하나만 지연할 수 있음. 지연된 요청이 이미 있는 상황에서 지연 가능한 요청이 발생하는 경우 원래 있던 지연된 요청은 AUDIOFOCUS_LOSS 변경 이벤트를 수신하고 새 요청은 AUDIOFOCUS_REQUEST_DELAYED의 동기 응답을 수신합니다.

  • 지연 가능한 요청에는 OnAudioFocusChangeListener가 있어야 함. 요청이 지연되면 리스너는 최종적으로 요청이 승인(AUDIOFOCUS_GAIN)될 때나 나중에 요청이 거부(AUDIOFOCUS_LOSS)될 때 요청자에 이를 알리는 데 사용됩니다.

지연 가능한 포커스 요청

지연 가능한 요청을 작성하려면 다음을 실행합니다.

  1. AudioFocusRequest.Builder#setAcceptsDelayedFocusGain을 사용합니다.

    mMediaWithDelayedFocusListener = new MediaWithDelayedFocusListener();
    
    mDelayedFocusRequest = new AudioFocusRequest
         .Builder(AudioManager.AUDIOFOCUS_GAIN)
         .setAudioAttributes(mMusicAudioAttrib)
         .setOnAudioFocusChangeListener(mMediaWithDelayedFocusListener)
         .setForceDucking(false)
         .setWillPauseWhenDucked(false)
         .setAcceptsDelayedFocusGain(true)
         .build();
    
  2. 요청할 때 AUDIOFOCUS_REQUEST_DELAYED 응답을 처리합니다.

    int delayedFocusRequestResults = mAudioManager.requestAudioFocus(mDelayedFocusRequest);
    if (delayedFocusRequestResults == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
        // start audio playback
        return;
    }
    if (delayedFocusRequestResults == AudioManager.AUDIOFOCUS_REQUEST_DELAYED) {
         // audio playback delayed to audio focus listener
         return;
    }
    
  3. 요청이 지연되면 포커스 리스너가 포커스의 변경사항을 처리합니다.

    private final class MediaWithDelayedFocusListener implements
    OnAudioFocusChangeListener {
           @Override
           public void onAudioFocusChange(int focusChange) {
               synchronized (mLock) {
                   switch (focusChange) {
                       case AudioManager.AUDIOFOCUS_GAIN:
                           … // Start focus playback
                       case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
                           … // Pause media transiently
                       case AudioManager.AUDIOFOCUS_LOSS:
                           … // Stop media
    

다중 영역 포커스 관리

오디오 영역이 여러 개 있는 차량의 경우 오디오 포커스는 영역별로 독립적으로 관리됩니다. 따라서 한 영역에 요청하는 경우 다른 영역의 포커스 보유자를 고려하지 않으며 다른 영역의 포커스 보유자가 포커스를 상실하지도 않습니다. 이를 통해 운전석 공간의 포커스를 뒷좌석 엔터테인먼트 시스템과 별도로 관리할 수 있으므로 한 영역의 포커스 변경으로 인해 다른 영역의 오디오 재생이 중단되지 않습니다.

모든 앱에 대해 CarAudioService가 자동으로 포커스를 관리합니다. 포커스 요청의 오디오 영역은 연결된 UserId 또는 UID로 결정됩니다(자세한 내용은 오디오 라우팅 참고).

여러 영역에서 동시에 오디오 요청

앱이 여러 영역에서 오디오를 동시에 재생하려면 번들에 AUDIOFOCUS_EXTRA_REQUEST_ZONE_ID를 포함하여 각 영역에 포커스를 요청해야 합니다.

//Create attribute with bundle and AUDIOFOCUS_EXTRA_REQUEST_ZONE_ID
Bundle bundle = new Bundle();
bundle.putInt(CarAudioManager.AUDIOFOCUS_EXTRA_REQUEST_ZONE_ID,
               zoneId);

AudioAttributes attributesWithZone = new AudioAttributes.Builder()
     .setUsage(AudioAttributes.USAGE_MEDIA)
     .addBundle(bundle)
     .build();

//Create focus request using built attributesWithZone

이 번들 매개변수를 사용하면 요청자가 자동 오디오 영역 매핑을 재정의하여 지정된 영역 ID를 대신 사용할 수 있습니다. 따라서 앱은 다양한 오디오 영역에 대해 별도의 요청을 실행할 수 있습니다.

HAL 오디오 포커스

Android 11부터 외부 스트림을 대신하여 하드웨어 추상화 계층(HAL)이 포커스를 요청할 수 있습니다. 이러한 API 사용은 선택사항이지만 사용하는 것이 좋습니다. 외부 사운드가 Android 생태계에 최적으로 참여하고 원활한 사용자 환경을 제공할 수 있습니다.

HAL은 우선순위를 적용할 사운드를 최종적으로 결정합니다. 응급 상황 및 안전에 중요한 사운드는 HAL에 오디오 포커스가 부여되었는지 여부와 상관없이 재생되어야 하며 HAL이 오디오 포커스를 상실하더라도 계속 재생되어야 합니다. 정부 규정에 따라 요구되는 사운드의 경우도 마찬가지입니다.

HAL은 응급 상황이나 안전에 중요한 사운드가 재생될 때 선명하게 들리도록 적절하게 Android 스트림을 사전에 음소거해야 합니다.

AudioControl@2.0

2.0 버전의 AudioControl HAL에는 다음과 같은 새로운 API가 도입되었습니다.

API 목적
IAudioControl#registerFocusListener IFocusListener의 인스턴스를 AudioControl HAL에 등록합니다. 이 리스너를 사용하면 HAL이 오디오 포커스를 요청하고 포기할 수 있습니다. HAL은 Android에서 리스너를 등록 취소하는 데 사용할 ICloseHandle 인스턴스를 제공합니다.
IAudioControl#onAudioFocusChange 초기 포커스 요청에 대한 응답을 비롯하여 IFocusListener를 통해 HAL이 실행한 포커스 요청의 상태 변경사항을 HAL에 알립니다.
IFocusListener#requestAudioFocus 지정된 용도, 영역 ID, 포커스 게인 유형의 경우 HAL을 대신하여 포커스를 요청합니다.
IFocusListener#abandonAudioFocus 지정된 용도 및 영역 ID에 관한 기존 HAL 포커스 요청을 포기합니다.

HAL은 동시에 여러 개의 포커스 요청을 할 수 있지만, 용도-영역 ID의 쌍별 요청 하나씩으로 제한됩니다. Android에서는 요청이 발생하면 HAL에서 용도에 해당하는 사운드를 즉시 재생하기 시작하고 포커스를 포기할 때까지 계속 재생한다고 가정합니다.

registerFocusListener를 제외하고 이러한 요청은 oneway입니다. 이는 포커스 요청이 처리되는 동안 Android가 HAL을 지연시키지 않도록 하기 위함입니다. HAL은 안전에 중요한 사운드를 재생할 때는 포커스를 획득할 때까지 기다려서는 안 됩니다. HAL이 IAudioControl#onAudioFocusChange를 통해 오디오 포커스의 변경사항을 수신 대기하고 이에 응답하는 것은 선택사항입니다.

OEM 자동차 오디오 포커스 서비스

Android 14에서는 AAOS에 자동차 OEM 플러그인 서비스가 도입되었습니다. 이를 통해 일부 자동차 구성요소를 구성할 수 있습니다. 자동차 오디오 플러그인 서비스의 경우 플러그인 서비스를 통해 OEM이 자동차 오디오 서비스가 가로채는 포커스 요청을 관리할 수 있습니다. 이를 통해 OEM은 규칙 및 규정 요구사항에 따른 포커스 관리를 좀 더 유연하게 처리할 수 있습니다. 따라서 오디오 포커스 상호작용은 제조업체와 지역마다 다를 수 있습니다. 앱은 더 나은 오디오 관리를 위해 계속 포커스를 요청하여 사용자 환경을 개선해야 한다는 오디오 포커스의 기본 전제는 여전히 유지됩니다. 일반적으로 특정 규칙은 앱의 오디오 포커스 요청에 계속 적용됩니다.

  • 높은 우선순위의 오디오 포커스(예: 전화 통화, 긴급 재난 문자 또는 안전 관련 알림)가 없으면 앱은 일시적 또는 영구적으로 오디오 포커스를 획득할 수 있어야 합니다.

  • 미디어 포커스가 활성 상태인 동안:

    • 통화 용도 포커스를 요청하는 앱은 동시에 또는 독점적으로 통화를 수신할 수 있어야 합니다.

    • 내비게이션 용도 포커스를 요청하는 앱은 동시에 또는 독점적으로 내비게이션 포커스를 수신할 수 있어야 합니다.

    • 어시스턴트 용도 포커스를 요청하는 앱은 동시에 또는 독점적으로 용도 포커스를 수신할 수 있어야 합니다.

  • 높은 우선순위의 오디오 포커스(예: 전화 통화, 긴급 재난 문자, 안전 관련 알림)를 유지하는 앱이 활성 상태인 동안 수신되는 지연된 오디오 포커스 요청은 필요에 따라 승인되거나 지연되어야 합니다.

위의 제안사항은 일부만 나온 것이지만 높은 우선순위의 활성 사운드가 없는 경우 포커스를 요청하는 앱이 포커스를 획득하는 데 도움이 될 수 있습니다. 우선순위가 높은 사운드가 활성 상태인 동안에도 지연된 포커스 요청은 여전히 존중되어야 하며 높은 우선순위의 사운드가 중지되면 포커스를 획득할 수 있어야 합니다.