Google is committed to advancing racial equity for Black communities. See how.

Audio Focus

Typically, there is at most one application which holds audio focus globally at any time. When another application requests focus, the former one receives a focus loss event, and then the new one is granted focus. There are some exceptions to this behavior; for example, when a call holds focus, new focus requests are rejected.

New context interaction definitions

Starting in Android 9, car audio focus is managed differently. An interaction matrix has been introduced to CarAudioFocus that captures the desired behavior when a focus request comes based on the usage types of both the new source as well as the one currently holding focus. There are three interaction types:

Exclusive Interaction

In exclusive application context interactions only one application is allowed to hold focus at a time. An example of this would be two media player applications, since both are playing media only one of the applications is allowed to hold focus. This is the default interaction between most focus holder and focus requester when both request AudioManager.AUDIOFOCUS_GAIN. In such case, when the incoming focus request is granted an AudioManager.AUDIOFOCUS_LOSS is dispatched to current focus holders. Exclusive usage interactions may also request different audio focus other then AudioManager.AUDIOFOCUS_GAIN. Still, the interaction will be exclusive and a focus loss of the appropriate type will be dispatched.

Reject Interaction

With reject context interaction, the request is always rejected for the incoming focus requester. Attempts to transition from Notification to Alarm is an example of reject usage interaction. In this case, if an application playing notification ringtone is currently holding audio focus and a second application request focus to play alarm, the alarm application will receive a focus request rejection. Since the focus request is rejected no focus loss of any type is dispatched to current focus holder.

Concurrent Interaction

Most interesting to the car audio users are the concurrent context interactions. This gives applications requesting audio focus in the car the ability to play sound concurrently with other applications. This, along with the car audio routing, gives OEM the ability to concurrently route audio sounds to different parts of the car. In order for a concurrent interaction to take place, the focus requester must ask for AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK. setPauseWhenDucked(true) when used in conjunction with AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK continues to work as expected. Dk events will be delivered for concurrent focus requests so that the application can pause playback. The latter is typically used by audio books applications to keep user from missing any event in the audio.

While the concurrent interaction has many useful applications, OEMs must take care of the mixing and ducking at the hardware level across output devices. For example, when navigation and media are delivered simultaneously, OEM may want to temporarily mute media playing in the driver side speaker (duck media) and play navigation instead. If the configuration of the car is such that media and navigation are delivered to different devices this can be accomplished by ducking media when any data is delivery to the navigation device. In this manner OEM can play navigation instructions on the driver side while media continues to play through the rest of the cabin. If however the two sources are mixed into the same output device, then no ducking will be applied. It's therefore recommended that any contexts that can be played concurrently should be routed to separate devices so that ducking can be handled appropriately.

Interaction Matrix

Table 1 below shows the interaction matrix defined in CarAudioFocus. In the table, rows represent the current application holding focus and columns represent the incoming focus requester.

Looking at an example, where a music media app is currently holding focus and a navigation app request focus, the matrix shows that the two interactions can play concurrently. If the focus requested by the incoming navigation application is AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK, then focus request will be granted and no focus loss will be sent to the media application. It is possible for more than one focus holder to exist. In this case, an incoming focus requester will be compared with each of the current focus holders before deciding what sort of transitions to apply.

Table 1. Car Audio Focus usage interaction matrix.

Context of an incoming focus requester:

Context Invalid Music Nav Voice Ring Call Alarm Noti Sys
Invalid REJ REJ REJ REJ REJ REJ REJ REJ REJ
Music REJ EXC CON EXC EXC EXC EXC CON CON
Nav REJ CON CON EXC CON EXC CON CON CON
Voice REJ CON REJ CON EXC EXC REJ REJ REJ
Ring REJ REJ CON CON CON CON REJ REJ CON
Call REJ REJ CON REJ CON CON CON CON REJ
Alarm REJ CON CON EXC EXC EXC CON CON CON
Noti REJ CON CON EXC EXC EXC CON CON CON
Sys REJ CON CON EXC EXC EXC CON CON CON

Legend:

  • REJ. Reject
  • EXC. Exclusive
  • CON. Concurrent

For details, see packages/services/Car/service/src/com/android/car/audio/CarAudioFocus.java

Multi-zone focus management

In Android 10, the rules for application usage interactions from Android 9 are maintained but focus is further separated for each audio zone. With this, the main cabin's focus can be managed separately from a rear seat entertainment system, thus avoiding interrupting the audio playback in one zone by the changes in focus in another.

For all applications focus management is taken care of by the CarAudioService automatically and set via the CarAudioManager.setZoneIdForUid API. Once a UID has been mapped to a particular zone focus will be automatically requested from that zone. Here is an example of focus request:

//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()); }

This is no different as to how a third party app would request focus, thus third party apps can still use the audio zone capability with the caveat that zone management must be taken be cared by an OEM app launcher or some other management app.

Streaming to multiple zones concurrently

In the case of apps streaming to a single zone, audio focus operates the same from the app's perspective, and zone management can be set by using CarAudioManager.setZoneIdForUid. However, 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,
               zoneIdForDisplayId);

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