Before starting a logical stream, an app request audio focus using the same audio attributes as is used for the logical stream. The app must respect focus losses to perform as expected in the automotive use cases.
While sending a focus request is recommended, it isn't enforced by the system. Therefore, consider focus as a means to indirectly control and avoid conflict during playback instead of as a primary audio control mechanism. The vehicle shouldn't depend on the focus system for operation of the audio subsystem.
Focus interactions
To support AAOS, audio focus requests are handled based on predefined
interactions between the request’s CarAudioContext
and that of current
focus holders. There are three types of interactions:
- Exclusive
- Reject
- Concurrent
Exclusive interaction
This is the interaction model most commonly used with Android.
In exclusive interactions, only one app is allowed to hold focus at a time.
Therefore, an incoming focus request is granted focus while the existing focus
holder loses focus. Since both apps play media, only one app is allowed to hold
focus. As a result, the newly started app’s focus request is returned with
AUDIOFOCUS_REQUEST_GRANTED
while the app currently playing music receives a
focus change event with a loss status that corresponds to the type of request
that was made.
Reject interaction
With reject interactions, the incoming request is always rejected. For
example, when attempting to play music while a call is in progress. In this
case, if the Dialer holds audio focus for a call and a second app requests focus
to play music, the music app receives AUDIOFOCUS_REQUEST_FAILED
in response
to the request. Since the focus request is rejected, no focus loss is dispatched
to the current focus holder.
Concurrent interaction
Unique to AAOS are concurrent interactions. This gives apps that request audio focus in the car the ability to hold focus concurrently with other apps. For a concurrent interaction to take place, the following conditions must be met. The:
Incoming focus request must ask for AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK
Current focus holder doesn't setPauseWhenDucked(true)
Current focus holder opts not to receive duck events
If these criteria are met, then the focus request returns with
AUDIOFOCUS_REQUEST_GRANTED
while the current focus holder has no change in
focus. However, if the current focus holder opts to receive duck events or to
pause when ducked, the current focus holder loses focus, as occurs with an
exclusive interaction.
Handling concurrent streams
While the concurrent interaction has numerous uses, be careful at the mixing and
ducking at the hardware level across output devices. We strongly recommend that
CarAudioContext
's that are allowed to play concurrently should be routed to
different output devices.
By having separate output devices for concurrent streams, this enables the HAL to duck one of the streams before mixing them, or to route the physical streams to different speakers in the vehicle. If the logical streams are mixed within Android, gains are unaltered and delivered as part of the same physical stream.
For example, when navigation and media are delivered simultaneously, the gain for the media stream could temporarily be reduced (or, ducked) so that navigation instructions can be heard more clearly. Alternatively, the navigation stream could be routed to the driver side speakers while media continues to play throughout the rest of the cabin.
Interaction matrix
The table below shows the interaction matrix as defined by CarAudioService
.
Each row represents the current focus holder’s CarAudioContext
and each
column represents that of the incoming request.
For example, when a music media app holds focus as a navigation app requests focus, the matrix indicates that the two interactions can play concurrently, assuming the other criteria for concurrent interactions are fulfilled.
Because of the concurrent interactions, it's possible to have more than one focus holder. In this case, an incoming focus request is compared with each of the current focus holders before determining what interaction to apply. In this case, the most conservative interaction wins. Reject, then exclusive, and finally concurrent.
Figure 1. Audio focus interaction matrix.
Navigation during phone calls
In Android 11, a new user setting was introduced to allow users to alter the
interaction behavior between navigation and phone calls. When set,
android.car.KEY_AUDIO_FOCUS_NAVIGATION_REJECTED_DURING_CALL
changes the
interaction between incoming NAVIGATION
focus requests and current CALL
focus holders from concurrent to rejects. If a user prefers that
navigation instructions not interrupt a call, they can enable the setting. This
is persisted for the user, and can be set dynamically so that subsequent focus
requests respect the new setting.
Delayable audio focus
In Android 11, AAOS added support for requesting delayable audio focus. This allows non-transient focus requests to be delayed when their interaction with current focus holders would normally result in them being rejected. Once a change in focus results in a state where the delayed request can gain focus, the request is granted.
Rules for delayed audio focus requests
Non-transient requests only. A delayed request can only be made for non-transient sources in order to avoid having a transient sound play long after it's relevant.
Only one request can be delayed at a time. If a delayable request is made while there is already a delayed request, the original delayed request receives a
AUDIOFOCUS_LOSS
change event and the new request receives a synchronous response ofAUDIOFOCUS_REQUEST_DELAYED
.Delayable requests must have a
OnAudioFocusChangeListener
Once a request is delayed, the listener is used to notify the requester when the request is eventually granted (AUDIOFOCUS_GAIN
), or if it’s rejected later (AUDIOFOCUS_LOSS
).
Request delayable focus
To build a request that can be delayed:
Use
AudioFocusRequest.Builder#setAcceptsDelayedFocusGain
.mMediaWithDelayedFocusListener = new MediaWithDelayedFocusListener(); mDelayedFocusRequest = new AudioFocusRequest .Builder(AudioManager.AUDIOFOCUS_GAIN) .setAudioAttributes(mMusicAudioAttrib) .setOnAudioFocusChangeListener(mMediaWithDelayedFocusListener) .setForceDucking(false) .setWillPauseWhenDucked(false) .setAcceptsDelayedFocusGain(true) .build();
When making the request, handle the
AUDIOFOCUS_REQUEST_DELAYED
response: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; }
When the request is delayed, the focus listener handles changes in focus:
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
Multi-zone focus management
For vehicles with multiple audio zones, audio focus is managed independently for each zone. As such, a request to one zone doesn't take into account what holds focus in other zones, nor does it cause focus holders in other zones to lose focus. With this, the main cabin's focus can be managed separately from a rear seat entertainment system, thereby not interrupting the audio playback in one zone by changes made in focus to another.
For all apps, the CarAudioService
automatically manages focus. A focus
request’s audio zone is determined by its associated UserId
or UID
(for details, see Audio Routing).
Request audio from multiple zones concurrently
If an app wants to play audio in multiple zones concurrently, it must request
focus for each zone by including AUDIOFOCUS_EXTRA_REQUEST_ZONE_ID
in the
bundle:
//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
This bundle parameter allows the requestor to override the automatic audio zone mappings to instead use the specified zone ID. Therefore, an app could issue separate requests for different audio zones.
HAL audio focus
Starting in Android 11, the HAL is enabled to request focus on behalf of external streams. While optional, use of these APIs is highly encouraged to enable external sounds to be optimal participants in the Android ecosystem and to provide a seamless user experience.
The HAL makes the final determination around which sounds should get priority. To this extent, emergency and safety critical sounds should be played regardless of whether or not the HAL is granted audio focus and should continue to be played as appropriate even if the HAL loses audio focus. The same is true for any sounds required by government regulations.
The HAL should proactively mute Android streams as appropriate when playing emergency or safety-critical sounds to ensure they are heard clearly.
AudioControl@2.0
Version 2.0 of AudioControl HAL introduces these new APIs:
API | Purpose |
---|---|
IAudioControl#registerFocusListener |
Registers an instance of IFocusListener with the
AudioControl HAL. This listener enables the HAL to request and abandon audio
focus. The HAl provides an ICloseHandle instance to be used by
Android to unregister the listener. |
IAudioControl#onAudioFocusChange |
Notifies the HAL of changes in status to focus requests made by the HAL
through the IFocusListener , including responses to initial
focus requests. |
IFocusListener#requestAudioFocus
| Requests focus on behalf of the HAL for a specified usage, zone Id, and focus gain type. |
IFocusListener#abandonAudioFocus |
Abandons existing HAL focus requests for the specified usage and zone Id. |
The HAL can have multiple focus requests at the same time, but is limited to one request per usage and zone Id pairing. Android assumes the HAL immediately starts playing sounds for a usage once a request has been made and continutes to do so until it abandons focus.
Other than registerFocusListener
, these requests are oneway
to ensure that
Android doesn't delay the HAL while a focus request is processed. The HAL should
not wait to gain focus before playing safety-critical sounds. It's optional
for the HAL to listen for and respond to changes in audio focus through
IAudioControl#onAudioFocusChange
.
OEM car audio focus service
In Android 14, AAOS introduced the car OEM plugin services to enable configurability for some car components. For Car Audio Plugin Service, the plugin service allows for OEMs to manage focus requests intercepted by the car audio service. This gives OEMs more flexibility in terms of managing focus as required by rules and regulations. As such, audio focus interaction may differ between manufacturers, and from region to region. The basic premise for audio focus still holds, that apps should still request focus for better management audio to enhance user experience. In general, certain rules still apply for audio focus request by apps:
Without any standing, high priority audio focus (including a phone call, emergency alert, or safety notification) apps should be able to gain audio focus either transiently or permanently.
While a media focus is active:
Apps requesting call usage focus should be able to receive the call either concurrently or exclusively.
Apps requesting navigation usage focus should be able to receive navigation focus either concurrently or exclusively.
Apps requesting assistant usage focus should be able to receive usage focus either concurrently or exclusively.
While standing high priority audio focus (including a phone call, emergency alert, or safety notification) apps are active, any incoming delayed audio focus request should be granted or delayed as needed.
While the suggestions above are not exhaustive, they can help apps requesting focus to obtain focus if no active high priority sounds exist. Even while high priority sounds are active, delayed focus requests should still be respected and should be able to gain focus when the high priority sound stops.