Car audio plugin service

New car OEM plugin services in Android 14 enable some car components to be configured. For audio specifically, three new plugin services are introduced, which enable OEMs to flexibly configure audio management on AAOS devices:

  • Audio focus control
  • Audio volume and mute control
  • Audio Ducking control

Car plugin service architecture

The figure below provides an overview of the car services and their relationship to the OEM car service. Similar to the app processes and car service process, the OEM car service process occupies its own process space.

image

Car service starts the OEM car service by finding the component defined in config_oemCarService. If the config is empty, the OEM service does not exist and no service is started. The component must extend OemCarService. The car audio service must overwrite the APIs for acquiring the car audio OEM service:

public final class OemCarServiceImp extends OemCarService {
    @Override
    public OemCarAudioFocusService getOemAudioFocusService();

    @Override
    public OemCarAudioDuckingService getOemAudioDuckingService();

    @Override
    public OemCarAudioVolumeService getOemAudioVolumeService();
}

For example, see the reference test app defined in packages/services/Car/tests/OemCarServiceTestApp.

Even though the service is started by car service, it does not automatically inherit the permissions available to car audio service. As such, any permission required by OEM services should be acquired with the proper mechanism. For example, see packages/services/Car/data/etc/com.android.car.oemcarservice.testapp.xml.

Car audio service with OEM service architecture

In AAOS, car audio service manages these actions:

  • Audio routing
  • Audio focus
  • Audio ducking
  • Volume and mute

Before Android 14, this behavior was largely static and could only be modified through settings, albeit for a very limited set of cases. Android 14 introduced a mechanism for car audio service to communicate with an OEM-defined component that manages:

  • Audio focus
  • Audio ducking
  • Volume and mute

The figure below shows a simplified architecture for the car audio service and car OEM service. The car audio service defines different hooks that can call on the car OEM audio service to manage audio behavior. The latter occurs only if the corresponding OEM car audio service component is defined. Otherwise, the car audio service uses the default behavior.

image

To ensure that the car audio service and car OEM audio service are always in sync, for each call the car audio service passes the required parts of the current state of the audio stack to the car OEM audio service. For example, when the car audio service intercepts a request to evaluate audio focus, it passes the current state of the stack to the car OEM audio service. The current state includes the current focus holder and the current focus losers. Focus losers are focus requests that are still part of the stack but that have temporarily lost focus.

The car audio service must manage all audio activity in the car. If the car audio service does not manage some parts of the audio behavior, then the information exposed to the car OEM audio service is incomplete. For example, if an OEM overwrites the audio focus handling in the car service by registering their own audio focus policy, then the car audio service can't provide complete information to the car OEM audio service. This can affect the ability of the car OEM audio service to make decisions since it may lack information not visible to the car audio service.

To take actions, the car audio service calls the OEM car services. These calls are made across processes, which requires inter-process communication (IPC). IPC adds latency to each call. It's important to minimize latency in the OEM service.

Since car audio service calls to OEM service are blocking, the OEM service should not call the car audio service on direct API evaluations. Instead, the car audio service provides the necessary information so that calls between the two processes need only travel in one direction.

OEM car audio service definitions

OEM car audio focus service

Car audio service manages audio focus requests from apps by registering an audio policy focus listener. Car audio service has a mechanism to manage the focus behavior based on a static Interaction matrix. The matrix defines three different kind of interactions:

  • Concurrent interaction. Focus holders can maintain focus at the same time.

  • Exclusive interactions. Incoming focus request takes focus from the current focus holder.

  • Reject interaction. Incoming focus request rejected based on the current focus holder.

While this suffices for some automotive use cases, it does not fulfill all the needs of interaction that may differ due to OEM requirements. For this we introduce the OemCarAudioFocusService:

public interface OEmCarAudioFocusService {
    OemCarAuddioFocusResults evaluateAudioFocusRequest(
        OemCarAudioFocusEvaluationRequest request);
    
    void notifyAudioFocusChange(
        List<AudioFocusEntry> holder,
        List<AudioFocusEntry> losers, int zoneId);
}

The API evaluateAudioFocusRequest is called from the car audio service anytime there is a request for audio focus that needs to be evaluated, it is a two way API that blocks for the results to return. The request contains information about current state of the audio stack:

This information can be used to evaluate the newFocusRequest compared to the current focus holders in focusHolders and the current focus losers in focusLosers. The API should return the results:

class OemCarAudioFocusResult {
    int audioZoneId;
    int audioFocusEvaluationResults;
    AudioFocusEntry focusResult;
    List<AudioFocusEntry> newLosers;
    List<AudioFocusEntry> newlyBlocked;
}

This contains the information about actual evaluation results in audioFocusEvaluationResults, which indicates whether the current request has been granted, delayed, or it has failed. Any changes to the current focus stack should be set in newLosers and newlyBlocked entries, depending on the nature of the stack change.

Where the newLosers contains entries that were previously holding focus but should now lose focus, either permanently or transiently. Permanent focus losers will be further removed from the audio focus stack, and transient focus losers will be moved to the current focus losers stack until they regain focus or are abandoned from the original focus requester. Regardless, the focus listener for the requests will receive a corresponding focus lost.

The newlyBlocked list contains entries that were previously in the focus loser list but now are blocked by the new entry. The block can be permanent or transient, for permanent focus blocked the entry will be removed from the stack and focus loss will be sent to the focus listeners. For transient focus loss, the entry will remain in the focus losers stack but a new focus blocker will be added to its list of blocker, no focus loss will be sent as one was previously sent when it was first blocked. The request will finally be unblocked when all current blockers are removed, or it will be removed from the stack if focus is abandoned.

The second API, notifyAudioFocusChange, is a one way which is called on every audio focus request or abandon. The API is mostly used to inform the OEM service about focus changes, which may affect the behavior of the OEM car audio service.

Guidelines for focus evaluation

In AAOS, audio focus is used to manage audio playback and to determine which app should adhere to provide an optimal experience for the user. As such, the OEM plugin service should take into account the following when managing an audio focus request:

  • Without any standing high priority audio focus (such as a phone call, emergency, or safety) 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 focus either concurrently or exclusively.

    • Navigation usage focus, should be able to receive focus either concurrently or exclusively.

    • Assistant usage focus, should be able to receive focus either concurrently or exclusively.

  • While standing high priority audio focus (such as a phone call, emergency alert, or safety alert) apps are active, any incoming delayed audio focus request should be either granted or delayed as needed.

While the suggestions above are not exhaustive, they can help guarantee that apps requesting focus should be able to obtain focus when there are no active high priority sounds. Even while high priority sounds are active, delayed focus requests should still be respected and should be able to gain focus once the high priority sound stops.

OEM car volume service

The car audio service manages volume key events by either listening to volume adjustments from the audio system or by listening to volume key events directly from the car input service. In each case, the default behavior of the car audio service is to determine which volume group to change based on the active audio players and an audio context priority list.

We provide two volume priority lists. The first list considers all audio contexts in this order. The list is presented in descending order, the highest priority at the top and the lowest priority at the bottom. For example, if navigation audio and music audio are both active at the same time, then navigation volume is changed during a volume key event.

  1. Navigation
  2. Call
  3. Music
  4. Announcement
  5. Voice command
  6. Call ring
  7. System sound
  8. Safety
  9. Alarm
  10. Notification
  11. Vehicle status
  12. Emergency

To make the volume key event management less complex, car audio service has a second priority list of audio context:

  1. Call
  2. Media
  3. Announcement
  4. Voice command

This list is also presented in descending order. The purpose of this secon list is to allow more common sounds to be changed through key events. Uncommon, perhaps sounds of a shorter duration, can be managed through the audio settings UI only.

The actual version of the volume can be set with the audioVolumeAdjustmentContextsVersion configuration. The configuration can be set to either 1 or 2 (2 is the default).

To provide more flexibility to volume management, OemCarAudioVolumeService is introduced in Android 14:

public interface OemCarAudioVolumeService {
    OemCarvolumeChangeInfo getSuggestedGroupForVolumeChange(
OemCarAudioVolumeRequest request, int volumeAdjustment);
}

The OEM car audio volume service has a single method, which takes in a volumeAdjustment and an OemCarAudioVolumeRequest:

class OemCarAudioVolumeRequest {
    int audioZoneId;
    int callState;
    List<AudioAttributes> activePlaybackAttributes;
    List<AudioAttributes> duckedAttributes;
    List<CarVolumeGroupInfo> volumeGroupState;
}

The request’s activePlaybackAttributes has the active audio attributes. The duckedAttributes are all currently ducked audio attributes. The volumeGroupState has the current state of the volumes group. The request represents the current state of the audio stack and can be used to determine which volume group should be changed. The results should be returned in OemCarVolumeChangeInfo:

class OemCarVolumeChangeInfo {
    boolean change;
    CarVolumeGroupInfo volumeGroupChanged;
}

The change boolean indicates if any volume has changed, true indicates that there is a change and the volume group should be updated. The volumeGroupChanged is the actual volume group that should be changed. This group should be changed according to the original volumeAdjustment parameter passed to the API. For example, if the results indicate that the navigation volume group should be muted, then the boolean would be true and the returned volume group should be that for navigation.

OEM car ducking service

Car audio service manages audio ducking by monitoring audio focus changes and sending a signal to the AudioControl HAL about which audio devices to duck. When the focus changes, all the active focus holders are evaluated to determine which should be ducked based on this set of static ducking rules:

  • Emergency sounds duck everything except call sounds
  • Safety ducks everything except emergency sounds
  • Navigation ducks everything except safety and emergency sounds
  • Call ducks everything except safety, emergency, and navigation sounds
  • Voice ducks call ring sounds
  • Music and announcements should be ducked by everything

These rules are not exhaustive and OEMs remain responsible for determining how sounds should be ducked based on these guidelines. OEMs can control these recommendations more actively based on the available requirements. The OemCarDuckingService is introduced in Android 14:

class OemCarAudioDuckingService {
List<AudioAttributes>   evaluateAttributesToDuck(
        OemCarAudioVolumeRequest request);
}

This API is called from the car audio service on audio focus changes. It re-uses the OemCarAudioVolumeRequest introduced in OEM car volume service, and contains the relevant information to make the decision about which attributes to duck. The list of audio attributes to duck from the API is compared to the current audio state:

  • Audio attribute currently ducked:

    • On list, continues to be ducked
    • Not on list, ducking turned off
  • Audio attribute not currently ducked:

    • On list, ducked
    • Not on list, ducking turned off

The car audio service then determines which audio output devices the audio attributes belong to and adds them to the ducked audio output device list or the unducked audio devices list, respectively. This is ultimately sent to the AudioControl HAL to perform the required ducking at the hardware level.

The figure below shows a simplified sequence diagram of the audio ducking control for a focus request when the OEM ducking service is used:

image

The sequence starts when an app requests Manage audio focus through public audio manager APIs. The request is forwarded to the car audio service to determine the results. When audio focus is decided, the audio ducking is evaluated by the car audio service calling the OemCarAudioDuckingService to evaluate which audio attributes should be ducked. Once the results are returned from the evaluateAttributesToDuck API, the audio devices to duck are computed, and finally the information is sent to the AudioControl to apply ducking to the audio hardware.

OEM car audio service reference implementation

AAOS provides a reference implementation of the OEM car service in packages/services/Car/tests/OemCarServiceTestApp, which implements the OemCarService, along with OemCarAudioFocusService, OemCarAudioDuckingService, and the OemCarAudioVolumeService. For the latter, each service uses and XML file to load a static behavior. For example, OemCarAudioFocusServiceImp loads the oem_focus_config.xml, which contains an interaction matrix. The matrix is used to evaluate the focus request when the evaluateAudioFocusRequest is called.

Reference test app debugging

The OEM car service test app is part of the AOSP source code. OEMs can make changes according to their needs. For debugging, use the config_oemCarService configuration to enable the test app.

<!-- This is the component name for the OEM customization service. OEM can choose to implement
this service to customize car service behavior for different policies. If OEMs choose to
implement it, they have to implement a service extending OemCarService exposed by car-lib,
and implement the required component services.
If the component name is invalid, CarService would not connect to any OEM service.
Component name can not be a third party package. It should be pre-installed -->
<string name="config_oemCarService" translatable="false">
com.android.car.oemcarservice.testapp/.OemCarServiceImpl
</string>

To verify the OEM car service uses the car service dump command for the OEM service:

adb shell dumpsys car_service --oem-service

The results could be similar to the output below:

***CarOemProxyService dump***
  mIsFeatureEnabled: true
  mIsOemServiceBound: true
  mIsOemServiceReady: true
  mIsOemServiceConnected: true
  mInitComplete: true
  OEM_CAR_SERVICE_CONNECTED_TIMEOUT_MS: 5000
  OEM_CAR_SERVICE_READY_TIMEOUT_MS: 5000
  mComponentName: com.android.car.oemcarservice.testapp/.OemCarServiceImpl

Each boolean in each batch of dump info determines the state of the feature and service. For example, the dump info mIsOemServiceReady specifies if the service is ready to be used, where true indicates it is ready and false indicates it is not ready.