Testing Audio Focus

All applications playing audio should correctly acquire and abandon audio focus, exactly matching the duration of the playback. Well-behaving applications conform to the requirements described on our Requirements for Multimedia Applications page. The following sections describe how you can evaluate the behavior of your applications.

Checking the Status of the Audio Stack

You can check the current status of the audio stack by issuing the following command in adb:

adb shell dumpsys audio

The returned output varies based on the Android version, but the important part is probably at the beginning:

Audio Focus stack entries (last is top of stack):
  source:android.os.BinderProxy@e730bd -- pack: com.amazon.avod -- client: com.amazon.media.AmazonAudioManager@c7cb87ecom.amazon.avod.playbackclient.feature.audiofocus.AudioFocusManager$GlobalAudioFocusChangeListener@c521df -- gain: GAIN -- flags:  -- loss: LOSS_TRANSIENT -- uid: 10065 -- attr: AudioAttributes: usage=1 content=2 flags=0x0 tags= bundle=null
  source:android.os.BinderProxy@8089640 -- pack: com.amazon.vizzini -- client: com.amazon.media.AmazonAudioManager@461d1c8com.amazon.vizzini.vim.AudioFocusController@4417261 -- gain: GAIN_TRANSIENT_EXCLUSIVE -- flags:  -- loss: none -- uid: 10112 -- attr: AudioAttributes: usage=1 content=2 flags=0x0 tags= bundle=null
  ...

In this example, two items are in the focus stack; they refer the applications with package names com.amazon.avod and com.amazon.vizzini. The last item has the audio focus and all rights to play audio. All other items in the list have lost the focus but they are kept in the list until they call AudioManager.abandonAudioFocus(). This also means that all these applications above the last item have already received an OnAudioFocusChangeListener() callback, so they must have paused or muted the audio playback.

The second item, com.amazon.vizzini requested the focus using the duration flag AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE, so the application previously at the top of the stack received the OnAudioFocusChangeListener() callback with the TRANSIENT value, hence the loss: LOSS_TRANSIENT value is listed in the first line.

Well-behaving applications are not listed more than once in the stack: If you request audio focus for the second time (for example, for playing the next episode), your own app will cause your previous playback instances to receive the OnAudioFocusChangeListener() callback, and you should still acknowledge this by calling abandonAudioFocus() from the first.

Similarly, as soon as you finish playback, you should release your resources and abandon all focus requests so you will be completely removed from the list.

Testing onAudioFocusChange Callbacks

The following Audio Focus Requester tool lets you exercise the various audio focus changes in any application:

Install the application by running:

adb install -t -r audiofocusrequester.apk

There are two ways to use the tool: through its UI or by using the command line with intents sent from adb. Using the UI is simpler — you can configure all parameters using drop-down boxes. The command line does not let you pick all parameters (such as the stream type), but the focus changes can be timed accurately as they happen when you send the intents.

Using the UI

The drop-down boxes let you select all audio focus request parameters described in the Android documentation. Of course, the application under testing should be playing media in the foreground when the audio focus is taken away so you can also fine tune two additional timeouts: one wait period before the focus is requested by the tool and one before it is returned to your application.

This way you can select the use case you want to test, start the first timer, navigate to the application, and start playback. When the first timeout expires, the focus will be requested by the tool. Then the second timeout is started to wait before the focus is returned to your application.

Audio Focus Requester tool's UI
The Audio Focus Requester tool's UI

To use Audio Focus Requester UI with your application:

  1. Have both the target application and the Audio Focus Requester tool installed on the device.
  2. Start the Audio Focus Requester tool.
  3. Pick the parameters for the focus request and the timeouts.
  4. Click Finish setup and start timers and confirm that you want to start the timers.
  5. Navigate to your application and start playback.
  6. Wait for the timeouts to expire.

Using the command line

  1. Install both the target application and the audio focus tool.
  2. Start playback in your application.
  3. Use intents to instruct the service com.amazon.audiofocusrequester/.AudioFocusRequesterService to request and abandon audio focus.

    The following intent actions are supported:

    Permanent

    Instruct the tool to request audio focus using the duration hint AUDIOFOCUS_GAIN:

    adb shell am startservice -a "permanent" -n "com.amazon.audiofocusrequester/.AudioFocusRequesterService"
    

    Expected behavior:

    Transient

    Instruct the tool to request audio focus using the duration hint AUDIOFOCUS_GAIN_TRANSIENT:

    adb shell am startservice -a "transient" -n "com.amazon.audiofocusrequester/.AudioFocusRequesterService"
    

    Expected behavior:

    Duck

    Instruct the tool to request audio focus using the duration hint AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK.

    adb shell am startservice -a "duck" -n "com.amazon.audiofocusrequester/.AudioFocusRequesterService"
    

    Expected Behavior:

    Release

    Instruct the tool to abandon the audio focus:

    adb shell am startservice -a "release" -n "com.amazon.audiofocusrequester/.AudioFocusRequesterService"
    

    Expected behavior:

The behavior of all applications should align with the requirements described in Requirements for Multimedia Apps on Fire TV. If you encounter any issues, re-examine your implementation of the onAudioFocusChange() callbacks.