오디오 포커스

일반적으로 시스템 전역에서 오디오 포커스를 보유하는 애플리케이션은 어느 시점이든 많아야 한 개입니다. 다른 애플리케이션이 포커스를 요청하면 이전 애플리케이션에서 포커스 손실 이벤트를 수신한 후에 새로운 애플리케이션이 포커스를 부여받습니다. 이 동작에는 몇 가지 예외가 있습니다. 예를 들어 통화에서 포커스를 보유하면 새 포커스 요청은 거부됩니다.

새로운 컨텍스트 상호작용 정의

Android 9부터 자동차의 오디오 포커스 관리 방식이 달라집니다. 상호작용 매트릭스가 CarAudioFocus에 도입되어, 포커스 요청이 오면 새로운 소스와 현재 포커스를 보유한 소스 모두의 사용 유형에 따라 원하는 동작을 캡처합니다. 상호작용에는 세 가지 유형이 있습니다.

배타적인 상호작용

배타적인 애플리케이션 컨텍스트 상호작용에서는 한 번에 하나의 애플리케이션만 포커스를 보유할 수 있습니다. 예를 들어 두 개의 미디어 플레이어 애플리케이션이 모두 미디어를 재생 중인 경우에도 하나의 애플리케이션만 포커스를 보유할 수 있습니다. 이는 포커스 보유자와 포커스 요청자가 모두 AudioManager.AUDIOFOCUS_GAIN을 요청할 때 그 사이에서 발생하는 기본 상호작용입니다. 이러한 경우, 수신 포커스 요청이 승인되면 AudioManager.AUDIOFOCUS_LOSS가 현재 포커스 보유자에게 전달됩니다. 배타적인 사용 상호작용에서는 AudioManager.AUDIOFOCUS_GAIN 외에 다른 오디오 포커스도 요청할 수 있습니다. 그러나 상호작용은 배타적이며 적절한 유형의 포커스 손실이 전달됩니다.

거부 상호작용

거부 컨텍스트 상호작용에서 수신 포커스 요청자의 요청은 항상 거부됩니다. 알림을 알람으로 전환하려는 시도가 거부 사용 상호작용의 예입니다. 이 경우, 현재 알림 벨소리를 재생하는 애플리케이션에서 오디오 포커스를 보유하고 있고 두 번째 애플리케이션에서 알람을 재생할 포커스를 요청한다면 알람 애플리케이션은 포커스 요청 거부를 수신하게 됩니다. 포커스 요청이 거부되므로, 어떤 유형의 포커스 손실도 현재 포커스 보유자에게 전달되지 않습니다.

동시 상호작용

자동차 오디오 사용자에게 가장 흥미 있는 유형은 동시 컨텍스트 상호작용입니다. 이 상호작용은 자동차에서 오디오 포커스를 요청하는 애플리케이션이 다른 애플리케이션과 동시에 소리를 재생할 수 있게 해줍니다. 이는 자동차 오디오 라우팅과 마찬가지로 OEM이 오디오 사운드를 자동차의 다른 부분으로 동시에 라우팅할 수 있게 해줍니다. 동시 상호작용을 실행하려면 포커스 요청자는 AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK을 요청해야 합니다. setPauseWhenDucked(true)AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK과 함께 사용하면 계속 정상적으로 작동합니다. 동시 포커스 요청을 위한 Dk 이벤트가 전달되므로 애플리케이션에서 재생을 일시중지할 수 있습니다. 후자는 일반적으로 오디오 북 애플리케이션에서 사용하며, 사용자가 오디오 이벤트를 놓치지 않게 해줍니다.

동시 상호작용에는 여러 가지 유용한 애플리케이션이 있지만, OEM이 출력 장치의 하드웨어 수준에서 사운드 믹스를 처리하고 볼륨을 낮춰야 합니다. 예를 들어 내비게이션과 미디어가 동시에 전송되는 경우 OEM은 운전자 측 스피커에서 재생되는 미디어를 일시적으로 음소거하고(미디어 볼륨 낮춤) 대신 내비게이션을 재생하는 것이 좋습니다. 미디어와 내비게이션이 다른 기기로 전송되도록 자동차가 구성되어 있다면, 데이터가 내비게이션 기기로 전송될 때 미디어 볼륨을 줄여 이를 실행할 수 있습니다. 이러한 방식으로 자동차의 운전자 측 스피커를 제외한 나머지 부분을 통해 미디어가 계속 재생되는 동안 OEM은 운전자에게 내비게이션 안내를 재생하면 됩니다. 하지만 두 소스가 동일한 출력 장치로 믹스된다면 오디오 볼륨을 낮추지 않습니다. 따라서 동시에 재생될 수 있는 모든 컨텍스트는 개별 기기로 라우팅되어 적절하게 볼륨을 줄이도록 하는 것이 좋습니다.

상호작용 매트릭스

아래의 표 1은 CarAudioFocus에 정의된 상호작용 매트릭스를 보여줍니다. 표에서 행은 현재 포커스를 보유하고 있는 애플리케이션을 나타내며 열은 수신 포커스 요청자를 나타냅니다.

현재 음악 미디어 앱에 포커스가 있고 내비게이션 앱에서 포커스를 요청하는 예를 보면, 매트릭스는 두 애플리케이션 상호작용이 동시에 재생될 수 있음을 나타냅니다. 수신 내비게이션 애플리케이션에서 요청한 포커스가 AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK이면 포커스 요청은 승인되고 미디어 애플리케이션으로 전송되는 포커스 손실은 없습니다. 둘 이상의 포커스 보유자가 존재할 수도 있습니다. 이 경우 수신 포커스 요청자와 현재 포커스 보유자를 각각 비교하여 적용할 전환 유형을 결정합니다.

표 1. 자동차 오디오 포커스 사용 상호작용 매트릭스

수신 포커스 요청자의 컨텍스트는 다음과 같습니다.

컨텍스트 잘못됨 음악 내비게이션 음성 벨소리 통화 알람 알림 시스템
잘못됨 REJ REJ REJ REJ REJ REJ REJ REJ REJ
음악 REJ EXC CON EXC EXC EXC EXC CON CON
내비게이션 REJ CON CON EXC CON EXC CON CON CON
음성 REJ CON REJ CON EXC EXC REJ REJ REJ
벨소리 REJ REJ CON CON CON CON REJ REJ CON
통화 REJ REJ CON REJ CON CON CON CON REJ
알람 REJ CON CON EXC EXC EXC CON CON CON
알림 REJ CON CON EXC EXC EXC CON CON CON
시스템 REJ CON CON EXC EXC EXC CON CON CON

범례:

  • REJ: 거부 상호작용
  • EXC: 배타적 상호작용
  • CON: 동시 상호작용

자세한 내용은 packages/services/Car/service/src/com/android/car/audio/CarAudioFocus.java를 참고하세요.

다중 영역 포커스 관리

Android 10에서는 Android 9의 애플리케이션 사용 상호작용 규칙이 유지되지만, 각 오디오 영역마다 포커스가 분리됩니다. 이를 통해 자동차 실내의 기본 포커스를 뒷좌석 엔터테인먼트 시스템과 별도로 관리할 수 있으므로 한 영역의 포커스 변경으로 인해 다른 영역의 오디오 재생이 중단되지 않습니다.

모든 애플리케이션의 포커스 관리는 CarAudioService에서 자동으로 처리하며 CarAudioManager.setZoneIdForUid API를 통해 설정됩니다. UID가 특정 영역에 매핑된 후에는 이 영역에서 자동으로 포커스를 요청합니다. 다음은 포커스 요청의 예입니다.

//Create focus
ret = mAudioManager
.requestAudioFocus(mFocusListener,
mMusicAudioAttrib,AudioManager.AUDIOFOCUS_GAIN, 0);

if (ret == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) { Log.i(TAG, "Got focus for usage " + mMusicAudioAttrib.getUsage()); start(); } else { Log.i(TAG, "MediaPlayer denied focus for usage " + mMusicAudioAttrib.getUsage()); }

이는 타사 앱에서 포커스를 요청하는 방식과 아무런 차이가 없으므로 타사 앱은 OEM 앱 런처 또는 일부 관리 앱에서 처리해야 하는 영역 관리에 주의하여 오디오 영역 기능을 계속 사용할 수 있습니다.

동시에 여러 영역으로 스트리밍

단일 영역으로 스트리밍하는 앱의 경우 오디오 포커스는 앱 관점에서 동일하게 작동하며 CarAudioManager.setZoneIdForUid를 사용하여 영역 관리를 설정할 수 있습니다. 그러나 앱이 여러 영역에서 오디오를 동시에 재생하려면 번들에 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,
               zoneIdForDisplayId);

mMusicAudioAttribForDisplay = new AudioAttributes.Builder() .setUsage(AudioAttributes.USAGE_MEDIA) .addBundle(bundle) .build();
//Create focus