Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d59b90ac authored by Hayden Gomes's avatar Hayden Gomes Committed by Android (Google) Code Review
Browse files

Merge changes from topic "system_usages"

* changes:
  Add API for setting supported system usages
  Adding System Usages to AudioAttributes
parents 6f0d16df 62812aa8
Loading
Loading
Loading
Loading
+10 −1
Original line number Diff line number Diff line
@@ -4112,17 +4112,24 @@ package android.media {
    method public int getAllFlags();
    method public android.os.Bundle getBundle();
    method public int getCapturePreset();
    method public int getSystemUsage();
    method public static boolean isSystemUsage(int);
    field public static final int FLAG_BEACON = 8; // 0x8
    field public static final int FLAG_BYPASS_INTERRUPTION_POLICY = 64; // 0x40
    field public static final int FLAG_BYPASS_MUTE = 128; // 0x80
    field public static final int FLAG_HW_HOTWORD = 32; // 0x20
    field @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public static final int USAGE_CALL_ASSISTANT = 17; // 0x11
    field @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public static final int USAGE_ANNOUNCEMENT = 1003; // 0x3eb
    field @RequiresPermission(allOf={android.Manifest.permission.MODIFY_PHONE_STATE, android.Manifest.permission.MODIFY_AUDIO_ROUTING}) public static final int USAGE_CALL_ASSISTANT = 17; // 0x11
    field @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public static final int USAGE_EMERGENCY = 1000; // 0x3e8
    field @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public static final int USAGE_SAFETY = 1001; // 0x3e9
    field @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public static final int USAGE_VEHICLE_STATUS = 1002; // 0x3ea
  }
  public static class AudioAttributes.Builder {
    method public android.media.AudioAttributes.Builder addBundle(@NonNull android.os.Bundle);
    method public android.media.AudioAttributes.Builder setCapturePreset(int);
    method public android.media.AudioAttributes.Builder setInternalCapturePreset(int);
    method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public android.media.AudioAttributes.Builder setSystemUsage(int);
  }
  public final class AudioDeviceAddress implements android.os.Parcelable {
@@ -4173,6 +4180,7 @@ package android.media {
    method @IntRange(from=0) @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getMaxVolumeIndexForAttributes(@NonNull android.media.AudioAttributes);
    method @IntRange(from=0) @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getMinVolumeIndexForAttributes(@NonNull android.media.AudioAttributes);
    method @Nullable @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public android.media.AudioDeviceAddress getPreferredDeviceForStrategy(@NonNull android.media.audiopolicy.AudioProductStrategy);
    method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int[] getSupportedSystemUsages();
    method @IntRange(from=0) @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getVolumeIndexForAttributes(@NonNull android.media.AudioAttributes);
    method public boolean isAudioServerRunning();
    method public boolean isHdmiSystemAudioSupported();
@@ -4185,6 +4193,7 @@ package android.media {
    method public void setAudioServerStateCallback(@NonNull java.util.concurrent.Executor, @NonNull android.media.AudioManager.AudioServerStateCallback);
    method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void setFocusRequestResult(@NonNull android.media.AudioFocusInfo, int, @NonNull android.media.audiopolicy.AudioPolicy);
    method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public boolean setPreferredDeviceForStrategy(@NonNull android.media.audiopolicy.AudioProductStrategy, @NonNull android.media.AudioDeviceAddress);
    method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void setSupportedSystemUsages(@NonNull int[]);
    method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void setVolumeIndexForAttributes(@NonNull android.media.AudioAttributes, int, int);
    method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void unregisterAudioPolicy(@NonNull android.media.audiopolicy.AudioPolicy);
    method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void unregisterAudioPolicyAsync(@NonNull android.media.audiopolicy.AudioPolicy);
+20 −3
Original line number Diff line number Diff line
@@ -48,11 +48,14 @@ static struct {
    jfieldID    mFormattedTags; // AudioAttributes.mFormattedTags
} gAudioAttributesFields;

static struct { jmethodID isSystemUsage; } gAudioAttributesClassMethods;

static jclass gAudioAttributesBuilderClass;
static jmethodID gAudioAttributesBuilderCstor;
static struct {
    jmethodID build;
    jmethodID setUsage;
    jmethodID setSystemUsage;
    jmethodID setInternalCapturePreset;
    jmethodID setContentType;
    jmethodID setFlags;
@@ -109,9 +112,17 @@ static jint nativeAudioAttributesToJavaAudioAttributes(
    if (jAttributeBuilder.get() == nullptr) {
        return (jint)AUDIO_JAVA_ERROR;
    }

    const bool isSystemUsage = env->CallStaticBooleanMethod(gAudioAttributesClass,
                                                      gAudioAttributesClassMethods.isSystemUsage,
                                                      attributes.usage);
    if (isSystemUsage) {
        env->CallObjectMethod(jAttributeBuilder.get(),
                          gAudioAttributesBuilderMethods.setUsage,
                              gAudioAttributesBuilderMethods.setSystemUsage, attributes.usage);
    } else {
        env->CallObjectMethod(jAttributeBuilder.get(), gAudioAttributesBuilderMethods.setUsage,
                              attributes.usage);
    }
    env->CallObjectMethod(jAttributeBuilder.get(),
                          gAudioAttributesBuilderMethods.setInternalCapturePreset,
                          attributes.source);
@@ -168,6 +179,9 @@ int register_android_media_AudioAttributes(JNIEnv *env)
{
    jclass audioAttributesClass = FindClassOrDie(env, kClassPathName);
    gAudioAttributesClass = MakeGlobalRefOrDie(env, audioAttributesClass);
    gAudioAttributesClassMethods.isSystemUsage =
            GetStaticMethodIDOrDie(env, gAudioAttributesClass, "isSystemUsage", "(I)Z");

    gAudioAttributesFields.mUsage = GetFieldIDOrDie(env, audioAttributesClass, "mUsage", "I");
    gAudioAttributesFields.mSource = GetFieldIDOrDie(env, audioAttributesClass, "mSource", "I");
    gAudioAttributesFields.mContentType =
@@ -186,6 +200,9 @@ int register_android_media_AudioAttributes(JNIEnv *env)
    gAudioAttributesBuilderMethods.setUsage = GetMethodIDOrDie(
                env, audioAttributesBuilderClass, "setUsage",
                "(I)Landroid/media/AudioAttributes$Builder;");
    gAudioAttributesBuilderMethods.setSystemUsage =
            GetMethodIDOrDie(env, audioAttributesBuilderClass, "setSystemUsage",
                             "(I)Landroid/media/AudioAttributes$Builder;");
    gAudioAttributesBuilderMethods.setInternalCapturePreset = GetMethodIDOrDie(
                env, audioAttributesBuilderClass, "setInternalCapturePreset",
                "(I)Landroid/media/AudioAttributes$Builder;");
+26 −0
Original line number Diff line number Diff line
@@ -2239,6 +2239,31 @@ android_media_AudioSystem_isHapticPlaybackSupported(JNIEnv *env, jobject thiz)
    return AudioSystem::isHapticPlaybackSupported();
}

static jint android_media_AudioSystem_setSupportedSystemUsages(JNIEnv *env, jobject thiz,
                                                               jintArray systemUsages) {
    std::vector<audio_usage_t> nativeSystemUsagesVector;

    if (systemUsages == nullptr) {
        return (jint) AUDIO_JAVA_BAD_VALUE;
    }

    int *nativeSystemUsages = nullptr;
    nativeSystemUsages = env->GetIntArrayElements(systemUsages, 0);

    if (nativeSystemUsages != nullptr) {
        jsize len = env->GetArrayLength(systemUsages);
        for (size_t i = 0; i < len; i++) {
            audio_usage_t nativeAudioUsage =
                    static_cast<audio_usage_t>(nativeSystemUsages[i]);
            nativeSystemUsagesVector.push_back(nativeAudioUsage);
        }
        env->ReleaseIntArrayElements(systemUsages, nativeSystemUsages, 0);
    }

    status_t status = AudioSystem::setSupportedSystemUsages(nativeSystemUsagesVector);
    return (jint)nativeToJavaStatus(status);
}

static jint
android_media_AudioSystem_setAllowedCapturePolicy(JNIEnv *env, jobject thiz, jint uid, jint flags) {
    return AudioSystem::setAllowedCapturePolicy(uid, flags);
@@ -2430,6 +2455,7 @@ static const JNINativeMethod gMethods[] = {
    {"isHapticPlaybackSupported", "()Z", (void *)android_media_AudioSystem_isHapticPlaybackSupported},
    {"getHwOffloadEncodingFormatsSupportedForA2DP", "(Ljava/util/ArrayList;)I",
                    (void*)android_media_AudioSystem_getHwOffloadEncodingFormatsSupportedForA2DP},
    {"setSupportedSystemUsages", "([I)I", (void *)android_media_AudioSystem_setSupportedSystemUsages},
    {"setAllowedCapturePolicy", "(II)I", (void *)android_media_AudioSystem_setAllowedCapturePolicy},
    {"setRttEnabled",       "(Z)I",     (void *)android_media_AudioSystem_setRttEnabled},
    {"setAudioHalPids",  "([I)I", (void *)android_media_AudioSystem_setAudioHalPids},
+178 −21
Original line number Diff line number Diff line
@@ -98,6 +98,10 @@ public final class AudioAttributes implements Parcelable {
     */
    public final static int CONTENT_TYPE_SONIFICATION = 4;

    /**
     * Invalid value, only ever used for an uninitialized usage value
     */
    private static final int USAGE_INVALID = -1;
    /**
     * Usage value to use when the usage is unknown.
     */
@@ -184,9 +188,43 @@ public final class AudioAttributes implements Parcelable {
     * Usage value to use for assistant voice interaction with remote caller on Cell and VoIP calls.
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
    @RequiresPermission(allOf = {
            android.Manifest.permission.MODIFY_PHONE_STATE,
            android.Manifest.permission.MODIFY_AUDIO_ROUTING
    })
    public static final int USAGE_CALL_ASSISTANT = 17;

    private static final int SYSTEM_USAGE_OFFSET = 1000;

    /**
     * @hide
     * Usage value to use when the usage is an emergency.
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
    public static final int USAGE_EMERGENCY = SYSTEM_USAGE_OFFSET;
    /**
     * @hide
     * Usage value to use when the usage is a safety sound.
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
    public static final int USAGE_SAFETY = SYSTEM_USAGE_OFFSET + 1;
    /**
     * @hide
     * Usage value to use when the usage is a vehicle status.
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
    public static final int USAGE_VEHICLE_STATUS = SYSTEM_USAGE_OFFSET + 2;
    /**
     * @hide
     * Usage value to use when the usage is an announcement.
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
    public static final int USAGE_ANNOUNCEMENT = SYSTEM_USAGE_OFFSET + 3;

    /**
     * IMPORTANT: when adding new usage types, add them to SDK_USAGES and update SUPPRESSIBLE_USAGES
     *            if applicable, as well as audioattributes.proto.
@@ -489,6 +527,20 @@ public final class AudioAttributes implements Parcelable {
     * @return one of the values that can be set in {@link Builder#setUsage(int)}
     */
    public int getUsage() {
        if (isSystemUsage(mUsage)) {
            return USAGE_UNKNOWN;
        }
        return mUsage;
    }

    /**
     * @hide
     * Return the system usage.
     * @return one of the values that can be set in {@link Builder#setUsage(int)} or
     * {@link Builder#setSystemUsage(int)}
     */
    @SystemApi
    public int getSystemUsage() {
        return mUsage;
    }

@@ -591,7 +643,8 @@ public final class AudioAttributes implements Parcelable {
     * {@link MediaPlayer} will use a default usage of {@link AudioAttributes#USAGE_MEDIA}.
     */
    public static class Builder {
        private int mUsage = USAGE_UNKNOWN;
        private int mUsage = USAGE_INVALID;
        private int mSystemUsage = USAGE_INVALID;
        private int mContentType = CONTENT_TYPE_UNKNOWN;
        private int mSource = MediaRecorder.AudioSource.AUDIO_SOURCE_INVALID;
        private int mFlags = 0x0;
@@ -637,7 +690,22 @@ public final class AudioAttributes implements Parcelable {
        public AudioAttributes build() {
            AudioAttributes aa = new AudioAttributes();
            aa.mContentType = mContentType;

            if (mUsage == USAGE_INVALID) {
                if (mSystemUsage == USAGE_INVALID) {
                    aa.mUsage = USAGE_UNKNOWN;
                } else {
                    aa.mUsage = mSystemUsage;
                }
            } else {
                if (mSystemUsage == USAGE_INVALID) {
                    aa.mUsage = mUsage;
                } else {
                    throw new IllegalArgumentException(
                            "Cannot set both usage and system usage on same builder");
                }
            }

            aa.mSource = mSource;
            aa.mFlags = mFlags;
            if (mMuteHapticChannels) {
@@ -667,26 +735,26 @@ public final class AudioAttributes implements Parcelable {
        }

        /**
         * Sets the attribute describing what is the intended use of the the audio signal,
         * Sets the attribute describing what is the intended use of the audio signal,
         * such as alarm or ringtone.
         * @param usage one of {@link AudioAttributes#USAGE_UNKNOWN},
         *     {@link AudioAttributes#USAGE_MEDIA},
         *     {@link AudioAttributes#USAGE_VOICE_COMMUNICATION},
         *     {@link AudioAttributes#USAGE_VOICE_COMMUNICATION_SIGNALLING},
         *     {@link AudioAttributes#USAGE_ALARM}, {@link AudioAttributes#USAGE_NOTIFICATION},
         *     {@link AudioAttributes#USAGE_NOTIFICATION_RINGTONE},
         *     {@link AudioAttributes#USAGE_NOTIFICATION_COMMUNICATION_REQUEST},
         *     {@link AudioAttributes#USAGE_NOTIFICATION_COMMUNICATION_INSTANT},
         *     {@link AudioAttributes#USAGE_NOTIFICATION_COMMUNICATION_DELAYED},
         *     {@link AudioAttributes#USAGE_NOTIFICATION_EVENT},
         *     {@link AudioAttributes#USAGE_ASSISTANT},
         *     {@link AudioAttributes#USAGE_ASSISTANCE_ACCESSIBILITY},
         *     {@link AudioAttributes#USAGE_ASSISTANCE_NAVIGATION_GUIDANCE},
         *     {@link AudioAttributes#USAGE_ASSISTANCE_SONIFICATION},
         *     {@link AudioAttributes#USAGE_GAME}.
         * @param usage one of {@link AttributeSdkUsage#USAGE_UNKNOWN},
         *     {@link AttributeSdkUsage#USAGE_MEDIA},
         *     {@link AttributeSdkUsage#USAGE_VOICE_COMMUNICATION},
         *     {@link AttributeSdkUsage#USAGE_VOICE_COMMUNICATION_SIGNALLING},
         *     {@link AttributeSdkUsage#USAGE_ALARM}, {@link AudioAttributes#USAGE_NOTIFICATION},
         *     {@link AttributeSdkUsage#USAGE_NOTIFICATION_RINGTONE},
         *     {@link AttributeSdkUsage#USAGE_NOTIFICATION_COMMUNICATION_REQUEST},
         *     {@link AttributeSdkUsage#USAGE_NOTIFICATION_COMMUNICATION_INSTANT},
         *     {@link AttributeSdkUsage#USAGE_NOTIFICATION_COMMUNICATION_DELAYED},
         *     {@link AttributeSdkUsage#USAGE_NOTIFICATION_EVENT},
         *     {@link AttributeSdkUsage#USAGE_ASSISTANT},
         *     {@link AttributeSdkUsage#USAGE_ASSISTANCE_ACCESSIBILITY},
         *     {@link AttributeSdkUsage#USAGE_ASSISTANCE_NAVIGATION_GUIDANCE},
         *     {@link AttributeSdkUsage#USAGE_ASSISTANCE_SONIFICATION},
         *     {@link AttributeSdkUsage#USAGE_GAME}.
         * @return the same Builder instance.
         */
        public Builder setUsage(@AttributeUsage int usage) {
        public Builder setUsage(@AttributeSdkUsage int usage) {
            switch (usage) {
                case USAGE_UNKNOWN:
                case USAGE_MEDIA:
@@ -705,7 +773,6 @@ public final class AudioAttributes implements Parcelable {
                case USAGE_GAME:
                case USAGE_VIRTUAL_SOURCE:
                case USAGE_ASSISTANT:
                case USAGE_CALL_ASSISTANT:
                    mUsage = usage;
                    break;
                default:
@@ -714,6 +781,28 @@ public final class AudioAttributes implements Parcelable {
            return this;
        }

        /**
         * @hide
         * Sets the attribute describing what is the intended use of the audio signal for categories
         * of sounds restricted to the system, such as vehicle status or emergency.
         *
         * <p>Note that the AudioAttributes have a single usage value, therefore it is illegal to
         * call both this method and {@link #setUsage(int)}.
         * @param systemUsage the system-restricted usage.
         * @return the same Builder instance.
         */
        @SystemApi
        @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
        public @NonNull Builder setSystemUsage(@AttributeSystemUsage int systemUsage) {
            if (isSystemUsage(systemUsage)) {
                mSystemUsage = systemUsage;
            } else {
                throw new IllegalArgumentException("Invalid system usage " + systemUsage);
            }

            return this;
        }

        /**
         * Sets the attribute describing the content type of the audio signal, such as speech,
         * or music.
@@ -1175,6 +1264,14 @@ public final class AudioAttributes implements Parcelable {
                return new String("USAGE_ASSISTANT");
            case USAGE_CALL_ASSISTANT:
                return new String("USAGE_CALL_ASSISTANT");
            case USAGE_EMERGENCY:
                return new String("USAGE_EMERGENCY");
            case USAGE_SAFETY:
                return new String("USAGE_SAFETY");
            case USAGE_VEHICLE_STATUS:
                return new String("USAGE_VEHICLE_STATUS");
            case USAGE_ANNOUNCEMENT:
                return new String("USAGE_ANNOUNCEMENT");
            default:
                return new String("unknown usage " + usage);
        }
@@ -1220,6 +1317,25 @@ public final class AudioAttributes implements Parcelable {
        }
    }

    /**
     * @param usage one of {@link AttributeSystemUsage},
     *     {@link AttributeSystemUsage#USAGE_CALL_ASSISTANT},
     *     {@link AttributeSystemUsage#USAGE_EMERGENCY},
     *     {@link AttributeSystemUsage#USAGE_SAFETY},
     *     {@link AttributeSystemUsage#USAGE_VEHICLE_STATUS},
     *     {@link AttributeSystemUsage#USAGE_ANNOUNCEMENT}
     * @return boolean indicating if the usage is a system usage or not
     * @hide
     */
    @SystemApi
    public static boolean isSystemUsage(@AttributeSystemUsage int usage) {
        return (usage == USAGE_CALL_ASSISTANT
                || usage == USAGE_EMERGENCY
                || usage == USAGE_SAFETY
                || usage == USAGE_VEHICLE_STATUS
                || usage == USAGE_ANNOUNCEMENT);
    }

    /**
     * Returns the stream type matching this {@code AudioAttributes} instance for volume control.
     * Use this method to derive the stream type needed to configure the volume
@@ -1295,6 +1411,10 @@ public final class AudioAttributes implements Parcelable {
                return AudioSystem.STREAM_NOTIFICATION;
            case USAGE_ASSISTANCE_ACCESSIBILITY:
                return AudioSystem.STREAM_ACCESSIBILITY;
            case USAGE_EMERGENCY:
            case USAGE_SAFETY:
            case USAGE_VEHICLE_STATUS:
            case USAGE_ANNOUNCEMENT:
            case USAGE_UNKNOWN:
                return AudioSystem.STREAM_MUSIC;
            default:
@@ -1325,6 +1445,39 @@ public final class AudioAttributes implements Parcelable {
        return flags;
    }

    /** @hide */
    @IntDef({
            USAGE_CALL_ASSISTANT,
            USAGE_EMERGENCY,
            USAGE_SAFETY,
            USAGE_VEHICLE_STATUS,
            USAGE_ANNOUNCEMENT
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface AttributeSystemUsage {}

    /** @hide */
    @IntDef({
            USAGE_UNKNOWN,
            USAGE_MEDIA,
            USAGE_VOICE_COMMUNICATION,
            USAGE_VOICE_COMMUNICATION_SIGNALLING,
            USAGE_ALARM,
            USAGE_NOTIFICATION,
            USAGE_NOTIFICATION_RINGTONE,
            USAGE_NOTIFICATION_COMMUNICATION_REQUEST,
            USAGE_NOTIFICATION_COMMUNICATION_INSTANT,
            USAGE_NOTIFICATION_COMMUNICATION_DELAYED,
            USAGE_NOTIFICATION_EVENT,
            USAGE_ASSISTANCE_ACCESSIBILITY,
            USAGE_ASSISTANCE_NAVIGATION_GUIDANCE,
            USAGE_ASSISTANCE_SONIFICATION,
            USAGE_GAME,
            USAGE_ASSISTANT,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface AttributeSdkUsage {}

    /** @hide */
    @IntDef({
        USAGE_UNKNOWN,
@@ -1344,6 +1497,10 @@ public final class AudioAttributes implements Parcelable {
        USAGE_GAME,
        USAGE_ASSISTANT,
        USAGE_CALL_ASSISTANT,
        USAGE_EMERGENCY,
        USAGE_SAFETY,
        USAGE_VEHICLE_STATUS,
        USAGE_ANNOUNCEMENT,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface AttributeUsage {}
+34 −0
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@ import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.media.AudioAttributes.AttributeSystemUsage;
import android.media.audiopolicy.AudioPolicy;
import android.media.audiopolicy.AudioPolicy.AudioPolicyFocusListener;
import android.media.audiopolicy.AudioProductStrategy;
@@ -1267,6 +1268,39 @@ public class AudioManager {
        }
    }

    /**
     * Set the system usages to be supported on this device.
     * @param systemUsages array of system usages to support {@link AttributeSystemUsage}
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
    public void setSupportedSystemUsages(@NonNull @AttributeSystemUsage int[] systemUsages) {
        Objects.requireNonNull(systemUsages, "systemUsages must not be null");
        final IAudioService service = getService();
        try {
            service.setSupportedSystemUsages(systemUsages);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Get the system usages supported on this device.
     * @return array of supported system usages {@link AttributeSystemUsage}
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
    public @NonNull @AttributeSystemUsage int[] getSupportedSystemUsages() {
        final IAudioService service = getService();
        try {
            return service.getSupportedSystemUsages();
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Solo or unsolo a particular stream.
     * <p>
Loading