Loading core/jni/android_media_AudioSystem.cpp +27 −11 Original line number Diff line number Diff line Loading @@ -18,6 +18,8 @@ //#define LOG_NDEBUG 0 #define LOG_TAG "AudioSystem-JNI" #include <android/binder_ibinder_jni.h> #include <android/binder_libbinder.h> #include <android/media/AudioVibratorInfo.h> #include <android/media/INativeSpatializerCallback.h> #include <android/media/ISpatializer.h> Loading @@ -25,6 +27,7 @@ #include <android_media_audiopolicy.h> #include <android_os_Parcel.h> #include <audiomanager/AudioManager.h> #include <binder/IBinder.h> #include <jni.h> #include <media/AidlConversion.h> #include <media/AudioContainers.h> Loading Loading @@ -157,6 +160,7 @@ static struct { jfieldID mDeviceAddress; jfieldID mMixType; jfieldID mCallbackFlags; jfieldID mToken; } gAudioMixFields; static jclass gAudioFormatClass; Loading Loading @@ -2300,11 +2304,15 @@ static jint convertAudioMixFromNative(JNIEnv *env, jobject *jAudioMix, const Aud if (status != AUDIO_JAVA_SUCCESS) { return status; } std::unique_ptr<AIBinder, decltype(&AIBinder_decStrong)> aiBinder(AIBinder_fromPlatformBinder( nAudioMix.mToken), &AIBinder_decStrong); jobject jBinderToken = AIBinder_toJavaBinder(env, aiBinder.get()); jstring deviceAddress = env->NewStringUTF(nAudioMix.mDeviceAddress.c_str()); *jAudioMix = env->NewObject(gAudioMixClass, gAudioMixCstor, jAudioMixingRule, jAudioFormat, nAudioMix.mRouteFlags, nAudioMix.mCbFlags, nAudioMix.mDeviceType, deviceAddress); deviceAddress, jBinderToken); return AUDIO_JAVA_SUCCESS; } Loading Loading @@ -2333,6 +2341,12 @@ static jint convertAudioMixToNative(JNIEnv *env, AudioMix *nAudioMix, const jobj nAudioMix->mVoiceCommunicationCaptureAllowed = env->GetBooleanField(jRule, gAudioMixingRuleFields.mVoiceCommunicationCaptureAllowed); jobject jToken = env->GetObjectField(jAudioMix, gAudioMixFields.mToken); std::unique_ptr<AIBinder, decltype(&AIBinder_decStrong)> aiBinder(AIBinder_fromJavaBinder(env, jToken), &AIBinder_decStrong); nAudioMix->mToken = AIBinder_toPlatformBinder(aiBinder.get()); jint status = convertAudioMixingRuleToNative(env, jRule, &(nAudioMix->mCriteria)); env->DeleteLocalRef(jRule); Loading Loading @@ -3659,9 +3673,10 @@ int register_android_media_AudioSystem(JNIEnv *env) jclass audioMixClass = FindClassOrDie(env, "android/media/audiopolicy/AudioMix"); gAudioMixClass = MakeGlobalRefOrDie(env, audioMixClass); if (audio_flags::audio_mix_test_api()) { gAudioMixCstor = GetMethodIDOrDie(env, audioMixClass, "<init>", gAudioMixCstor = GetMethodIDOrDie(env, audioMixClass, "<init>", "(Landroid/media/audiopolicy/AudioMixingRule;Landroid/" "media/AudioFormat;IIILjava/lang/String;)V"); "media/AudioFormat;IIILjava/lang/String;Landroid/os/IBinder;)V"); } gAudioMixFields.mRule = GetFieldIDOrDie(env, audioMixClass, "mRule", "Landroid/media/audiopolicy/AudioMixingRule;"); Loading @@ -3673,6 +3688,7 @@ int register_android_media_AudioSystem(JNIEnv *env) "Ljava/lang/String;"); gAudioMixFields.mMixType = GetFieldIDOrDie(env, audioMixClass, "mMixType", "I"); gAudioMixFields.mCallbackFlags = GetFieldIDOrDie(env, audioMixClass, "mCallbackFlags", "I"); gAudioMixFields.mToken = GetFieldIDOrDie(env, audioMixClass, "mToken", "Landroid/os/IBinder;"); jclass audioFormatClass = FindClassOrDie(env, "android/media/AudioFormat"); gAudioFormatClass = MakeGlobalRefOrDie(env, audioFormatClass); Loading media/java/android/media/audiopolicy/AudioMix.java +27 −4 Original line number Diff line number Diff line Loading @@ -27,7 +27,9 @@ import android.compat.annotation.UnsupportedAppUsage; import android.media.AudioDeviceInfo; import android.media.AudioFormat; import android.media.AudioSystem; import android.os.Binder; import android.os.Build; import android.os.IBinder; import android.os.Parcel; import android.os.Parcelable; Loading @@ -52,6 +54,8 @@ public class AudioMix implements Parcelable { @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) private int mMixType = MIX_TYPE_INVALID; private final IBinder mToken; // written by AudioPolicy int mMixState = MIX_STATE_DISABLED; @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) Loading @@ -68,7 +72,7 @@ public class AudioMix implements Parcelable { */ private AudioMix(@NonNull AudioMixingRule rule, @NonNull AudioFormat format, int routeFlags, int callbackFlags, int deviceType, @Nullable String deviceAddress) { int deviceType, @Nullable String deviceAddress, IBinder token) { mRule = Objects.requireNonNull(rule); mFormat = Objects.requireNonNull(format); mRouteFlags = routeFlags; Loading @@ -76,6 +80,7 @@ public class AudioMix implements Parcelable { mCallbackFlags = callbackFlags; mDeviceSystemType = deviceType; mDeviceAddress = (deviceAddress == null) ? new String("") : deviceAddress; mToken = token; } // CALLBACK_FLAG_* values: keep in sync with AudioMix::kCbFlag* values defined Loading Loading @@ -273,13 +278,14 @@ public class AudioMix implements Parcelable { return Objects.equals(this.mRouteFlags, that.mRouteFlags) && Objects.equals(this.mRule, that.mRule) && Objects.equals(this.mMixType, that.mMixType) && Objects.equals(this.mFormat, that.mFormat); && Objects.equals(this.mFormat, that.mFormat) && Objects.equals(this.mToken, that.mToken); } /** @hide */ @Override public int hashCode() { return Objects.hash(mRouteFlags, mRule, mMixType, mFormat); return Objects.hash(mRouteFlags, mRule, mMixType, mFormat, mToken); } @Override Loading @@ -298,6 +304,7 @@ public class AudioMix implements Parcelable { dest.writeString8(mDeviceAddress); mFormat.writeToParcel(dest, flags); mRule.writeToParcel(dest, flags); dest.writeStrongBinder(mToken); } public static final @NonNull Parcelable.Creator<AudioMix> CREATOR = new Parcelable.Creator<>() { Loading @@ -317,6 +324,7 @@ public class AudioMix implements Parcelable { mixBuilder.setDevice(p.readInt(), p.readString8()); mixBuilder.setFormat(AudioFormat.CREATOR.createFromParcel(p)); mixBuilder.setMixingRule(AudioMixingRule.CREATOR.createFromParcel(p)); mixBuilder.setToken(p.readStrongBinder()); return mixBuilder.build(); } Loading @@ -339,6 +347,7 @@ public class AudioMix implements Parcelable { private AudioFormat mFormat = null; private int mRouteFlags = 0; private int mCallbackFlags = 0; private IBinder mToken = null; // an AudioSystem.DEVICE_* value, not AudioDeviceInfo.TYPE_* private int mDeviceSystemType = AudioSystem.DEVICE_NONE; private String mDeviceAddress = null; Loading Loading @@ -378,6 +387,15 @@ public class AudioMix implements Parcelable { return this; } /** * @hide * Only used by AudioMix internally. */ Builder setToken(IBinder token) { mToken = token; return this; } /** * @hide * Only used by AudioPolicyConfig, not a public API. Loading Loading @@ -540,8 +558,13 @@ public class AudioMix implements Parcelable { throw new IllegalArgumentException(error); } } if (mToken == null) { mToken = new Binder(); } return new AudioMix(mRule, mFormat, mRouteFlags, mCallbackFlags, mDeviceSystemType, mDeviceAddress); mDeviceAddress, mToken); } private int getLoopbackDeviceSystemTypeForAudioMixingRule(AudioMixingRule rule) { Loading media/java/android/media/audiopolicy/AudioPolicy.java +10 −6 Original line number Diff line number Diff line Loading @@ -337,7 +337,9 @@ public class AudioPolicy { /** * Update the current configuration of the set of audio mixes by adding new ones, while * keeping the policy registered. * keeping the policy registered. If any of the provided audio mixes is invalid then none of * the passed mixes will be registered. * * This method can only be called on a registered policy. * @param mixes the list of {@link AudioMix} to add * @return {@link AudioManager#SUCCESS} if the change was successful, {@link AudioManager#ERROR} Loading Loading @@ -375,12 +377,15 @@ public class AudioPolicy { } /** * Update the current configuration of the set of audio mixes by removing some, while * keeping the policy registered. * This method can only be called on a registered policy. * Update the current configuration of the set of audio mixes for this audio policy by * removing some, while keeping the policy registered. Will unregister all provided audio * mixes, if possible. * * This method can only be called on a registered policy and only affects this current policy. * @param mixes the list of {@link AudioMix} to remove * @return {@link AudioManager#SUCCESS} if the change was successful, {@link AudioManager#ERROR} * otherwise. * otherwise. If only some of the provided audio mixes were detached but any one mix * failed to be detached, this method returns {@link AudioManager#ERROR}. */ public int detachMixes(@NonNull List<AudioMix> mixes) { if (mixes == null) { Loading @@ -394,7 +399,6 @@ public class AudioPolicy { for (AudioMix mix : mixes) { if (mix == null) { throw new IllegalArgumentException("Illegal null AudioMix in detachMixes"); // TODO also check mix is currently contained in list of mixes } else { zeMixes.add(mix); } Loading media/java/android/media/audiopolicy/AudioPolicyConfig.java +4 −2 Original line number Diff line number Diff line Loading @@ -228,7 +228,7 @@ public class AudioPolicyConfig implements Parcelable { } } private void setMixRegistration(@NonNull final AudioMix mix) { protected void setMixRegistration(@NonNull final AudioMix mix) { if (!mRegistrationId.isEmpty()) { if ((mix.getRouteFlags() & AudioMix.ROUTE_FLAG_LOOP_BACK) == AudioMix.ROUTE_FLAG_LOOP_BACK) { Loading @@ -246,7 +246,9 @@ public class AudioPolicyConfig implements Parcelable { @GuardedBy("mMixes") protected void add(@NonNull ArrayList<AudioMix> mixes) { for (AudioMix mix : mixes) { if (mix.getRegistration() == null || mix.getRegistration().isEmpty()) { setMixRegistration(mix); } mMixes.add(mix); } } Loading services/core/java/com/android/server/audio/AudioService.java +28 −1 Original line number Diff line number Diff line Loading @@ -12528,6 +12528,16 @@ public class AudioService extends IAudioService.Stub if (app == null) { return AudioManager.ERROR; } if (android.media.audiopolicy.Flags.audioMixOwnership()) { for (AudioMix mix : policyConfig.getMixes()) { if (!app.getMixes().contains(mix)) { Slog.e(TAG, "removeMixForPolicy attempted to unregister AudioMix(es) not " + "belonging to the AudioPolicy"); return AudioManager.ERROR; } } } return app.removeMixes(policyConfig.getMixes()) == AudioSystem.SUCCESS ? AudioManager.SUCCESS : AudioManager.ERROR; } Loading Loading @@ -13306,7 +13316,13 @@ public class AudioService extends IAudioService.Stub } final long identity = Binder.clearCallingIdentity(); try { if (android.media.audiopolicy.Flags.audioMixOwnership()) { synchronized (mMixes) { removeMixes(new ArrayList(mMixes)); } } else { mAudioSystem.registerPolicyMixes(mMixes, false); } } finally { Binder.restoreCallingIdentity(identity); } Loading Loading @@ -13350,6 +13366,17 @@ public class AudioService extends IAudioService.Stub int addMixes(@NonNull ArrayList<AudioMix> mixes) { synchronized (mMixes) { if (android.media.audiopolicy.Flags.audioMixOwnership()) { for (AudioMix mix : mixes) { setMixRegistration(mix); } int result = mAudioSystem.registerPolicyMixes(mixes, true); if (result == AudioSystem.SUCCESS) { this.add(mixes); } return result; } this.add(mixes); return mAudioSystem.registerPolicyMixes(mixes, true); } Loading
core/jni/android_media_AudioSystem.cpp +27 −11 Original line number Diff line number Diff line Loading @@ -18,6 +18,8 @@ //#define LOG_NDEBUG 0 #define LOG_TAG "AudioSystem-JNI" #include <android/binder_ibinder_jni.h> #include <android/binder_libbinder.h> #include <android/media/AudioVibratorInfo.h> #include <android/media/INativeSpatializerCallback.h> #include <android/media/ISpatializer.h> Loading @@ -25,6 +27,7 @@ #include <android_media_audiopolicy.h> #include <android_os_Parcel.h> #include <audiomanager/AudioManager.h> #include <binder/IBinder.h> #include <jni.h> #include <media/AidlConversion.h> #include <media/AudioContainers.h> Loading Loading @@ -157,6 +160,7 @@ static struct { jfieldID mDeviceAddress; jfieldID mMixType; jfieldID mCallbackFlags; jfieldID mToken; } gAudioMixFields; static jclass gAudioFormatClass; Loading Loading @@ -2300,11 +2304,15 @@ static jint convertAudioMixFromNative(JNIEnv *env, jobject *jAudioMix, const Aud if (status != AUDIO_JAVA_SUCCESS) { return status; } std::unique_ptr<AIBinder, decltype(&AIBinder_decStrong)> aiBinder(AIBinder_fromPlatformBinder( nAudioMix.mToken), &AIBinder_decStrong); jobject jBinderToken = AIBinder_toJavaBinder(env, aiBinder.get()); jstring deviceAddress = env->NewStringUTF(nAudioMix.mDeviceAddress.c_str()); *jAudioMix = env->NewObject(gAudioMixClass, gAudioMixCstor, jAudioMixingRule, jAudioFormat, nAudioMix.mRouteFlags, nAudioMix.mCbFlags, nAudioMix.mDeviceType, deviceAddress); deviceAddress, jBinderToken); return AUDIO_JAVA_SUCCESS; } Loading Loading @@ -2333,6 +2341,12 @@ static jint convertAudioMixToNative(JNIEnv *env, AudioMix *nAudioMix, const jobj nAudioMix->mVoiceCommunicationCaptureAllowed = env->GetBooleanField(jRule, gAudioMixingRuleFields.mVoiceCommunicationCaptureAllowed); jobject jToken = env->GetObjectField(jAudioMix, gAudioMixFields.mToken); std::unique_ptr<AIBinder, decltype(&AIBinder_decStrong)> aiBinder(AIBinder_fromJavaBinder(env, jToken), &AIBinder_decStrong); nAudioMix->mToken = AIBinder_toPlatformBinder(aiBinder.get()); jint status = convertAudioMixingRuleToNative(env, jRule, &(nAudioMix->mCriteria)); env->DeleteLocalRef(jRule); Loading Loading @@ -3659,9 +3673,10 @@ int register_android_media_AudioSystem(JNIEnv *env) jclass audioMixClass = FindClassOrDie(env, "android/media/audiopolicy/AudioMix"); gAudioMixClass = MakeGlobalRefOrDie(env, audioMixClass); if (audio_flags::audio_mix_test_api()) { gAudioMixCstor = GetMethodIDOrDie(env, audioMixClass, "<init>", gAudioMixCstor = GetMethodIDOrDie(env, audioMixClass, "<init>", "(Landroid/media/audiopolicy/AudioMixingRule;Landroid/" "media/AudioFormat;IIILjava/lang/String;)V"); "media/AudioFormat;IIILjava/lang/String;Landroid/os/IBinder;)V"); } gAudioMixFields.mRule = GetFieldIDOrDie(env, audioMixClass, "mRule", "Landroid/media/audiopolicy/AudioMixingRule;"); Loading @@ -3673,6 +3688,7 @@ int register_android_media_AudioSystem(JNIEnv *env) "Ljava/lang/String;"); gAudioMixFields.mMixType = GetFieldIDOrDie(env, audioMixClass, "mMixType", "I"); gAudioMixFields.mCallbackFlags = GetFieldIDOrDie(env, audioMixClass, "mCallbackFlags", "I"); gAudioMixFields.mToken = GetFieldIDOrDie(env, audioMixClass, "mToken", "Landroid/os/IBinder;"); jclass audioFormatClass = FindClassOrDie(env, "android/media/AudioFormat"); gAudioFormatClass = MakeGlobalRefOrDie(env, audioFormatClass); Loading
media/java/android/media/audiopolicy/AudioMix.java +27 −4 Original line number Diff line number Diff line Loading @@ -27,7 +27,9 @@ import android.compat.annotation.UnsupportedAppUsage; import android.media.AudioDeviceInfo; import android.media.AudioFormat; import android.media.AudioSystem; import android.os.Binder; import android.os.Build; import android.os.IBinder; import android.os.Parcel; import android.os.Parcelable; Loading @@ -52,6 +54,8 @@ public class AudioMix implements Parcelable { @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) private int mMixType = MIX_TYPE_INVALID; private final IBinder mToken; // written by AudioPolicy int mMixState = MIX_STATE_DISABLED; @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) Loading @@ -68,7 +72,7 @@ public class AudioMix implements Parcelable { */ private AudioMix(@NonNull AudioMixingRule rule, @NonNull AudioFormat format, int routeFlags, int callbackFlags, int deviceType, @Nullable String deviceAddress) { int deviceType, @Nullable String deviceAddress, IBinder token) { mRule = Objects.requireNonNull(rule); mFormat = Objects.requireNonNull(format); mRouteFlags = routeFlags; Loading @@ -76,6 +80,7 @@ public class AudioMix implements Parcelable { mCallbackFlags = callbackFlags; mDeviceSystemType = deviceType; mDeviceAddress = (deviceAddress == null) ? new String("") : deviceAddress; mToken = token; } // CALLBACK_FLAG_* values: keep in sync with AudioMix::kCbFlag* values defined Loading Loading @@ -273,13 +278,14 @@ public class AudioMix implements Parcelable { return Objects.equals(this.mRouteFlags, that.mRouteFlags) && Objects.equals(this.mRule, that.mRule) && Objects.equals(this.mMixType, that.mMixType) && Objects.equals(this.mFormat, that.mFormat); && Objects.equals(this.mFormat, that.mFormat) && Objects.equals(this.mToken, that.mToken); } /** @hide */ @Override public int hashCode() { return Objects.hash(mRouteFlags, mRule, mMixType, mFormat); return Objects.hash(mRouteFlags, mRule, mMixType, mFormat, mToken); } @Override Loading @@ -298,6 +304,7 @@ public class AudioMix implements Parcelable { dest.writeString8(mDeviceAddress); mFormat.writeToParcel(dest, flags); mRule.writeToParcel(dest, flags); dest.writeStrongBinder(mToken); } public static final @NonNull Parcelable.Creator<AudioMix> CREATOR = new Parcelable.Creator<>() { Loading @@ -317,6 +324,7 @@ public class AudioMix implements Parcelable { mixBuilder.setDevice(p.readInt(), p.readString8()); mixBuilder.setFormat(AudioFormat.CREATOR.createFromParcel(p)); mixBuilder.setMixingRule(AudioMixingRule.CREATOR.createFromParcel(p)); mixBuilder.setToken(p.readStrongBinder()); return mixBuilder.build(); } Loading @@ -339,6 +347,7 @@ public class AudioMix implements Parcelable { private AudioFormat mFormat = null; private int mRouteFlags = 0; private int mCallbackFlags = 0; private IBinder mToken = null; // an AudioSystem.DEVICE_* value, not AudioDeviceInfo.TYPE_* private int mDeviceSystemType = AudioSystem.DEVICE_NONE; private String mDeviceAddress = null; Loading Loading @@ -378,6 +387,15 @@ public class AudioMix implements Parcelable { return this; } /** * @hide * Only used by AudioMix internally. */ Builder setToken(IBinder token) { mToken = token; return this; } /** * @hide * Only used by AudioPolicyConfig, not a public API. Loading Loading @@ -540,8 +558,13 @@ public class AudioMix implements Parcelable { throw new IllegalArgumentException(error); } } if (mToken == null) { mToken = new Binder(); } return new AudioMix(mRule, mFormat, mRouteFlags, mCallbackFlags, mDeviceSystemType, mDeviceAddress); mDeviceAddress, mToken); } private int getLoopbackDeviceSystemTypeForAudioMixingRule(AudioMixingRule rule) { Loading
media/java/android/media/audiopolicy/AudioPolicy.java +10 −6 Original line number Diff line number Diff line Loading @@ -337,7 +337,9 @@ public class AudioPolicy { /** * Update the current configuration of the set of audio mixes by adding new ones, while * keeping the policy registered. * keeping the policy registered. If any of the provided audio mixes is invalid then none of * the passed mixes will be registered. * * This method can only be called on a registered policy. * @param mixes the list of {@link AudioMix} to add * @return {@link AudioManager#SUCCESS} if the change was successful, {@link AudioManager#ERROR} Loading Loading @@ -375,12 +377,15 @@ public class AudioPolicy { } /** * Update the current configuration of the set of audio mixes by removing some, while * keeping the policy registered. * This method can only be called on a registered policy. * Update the current configuration of the set of audio mixes for this audio policy by * removing some, while keeping the policy registered. Will unregister all provided audio * mixes, if possible. * * This method can only be called on a registered policy and only affects this current policy. * @param mixes the list of {@link AudioMix} to remove * @return {@link AudioManager#SUCCESS} if the change was successful, {@link AudioManager#ERROR} * otherwise. * otherwise. If only some of the provided audio mixes were detached but any one mix * failed to be detached, this method returns {@link AudioManager#ERROR}. */ public int detachMixes(@NonNull List<AudioMix> mixes) { if (mixes == null) { Loading @@ -394,7 +399,6 @@ public class AudioPolicy { for (AudioMix mix : mixes) { if (mix == null) { throw new IllegalArgumentException("Illegal null AudioMix in detachMixes"); // TODO also check mix is currently contained in list of mixes } else { zeMixes.add(mix); } Loading
media/java/android/media/audiopolicy/AudioPolicyConfig.java +4 −2 Original line number Diff line number Diff line Loading @@ -228,7 +228,7 @@ public class AudioPolicyConfig implements Parcelable { } } private void setMixRegistration(@NonNull final AudioMix mix) { protected void setMixRegistration(@NonNull final AudioMix mix) { if (!mRegistrationId.isEmpty()) { if ((mix.getRouteFlags() & AudioMix.ROUTE_FLAG_LOOP_BACK) == AudioMix.ROUTE_FLAG_LOOP_BACK) { Loading @@ -246,7 +246,9 @@ public class AudioPolicyConfig implements Parcelable { @GuardedBy("mMixes") protected void add(@NonNull ArrayList<AudioMix> mixes) { for (AudioMix mix : mixes) { if (mix.getRegistration() == null || mix.getRegistration().isEmpty()) { setMixRegistration(mix); } mMixes.add(mix); } } Loading
services/core/java/com/android/server/audio/AudioService.java +28 −1 Original line number Diff line number Diff line Loading @@ -12528,6 +12528,16 @@ public class AudioService extends IAudioService.Stub if (app == null) { return AudioManager.ERROR; } if (android.media.audiopolicy.Flags.audioMixOwnership()) { for (AudioMix mix : policyConfig.getMixes()) { if (!app.getMixes().contains(mix)) { Slog.e(TAG, "removeMixForPolicy attempted to unregister AudioMix(es) not " + "belonging to the AudioPolicy"); return AudioManager.ERROR; } } } return app.removeMixes(policyConfig.getMixes()) == AudioSystem.SUCCESS ? AudioManager.SUCCESS : AudioManager.ERROR; } Loading Loading @@ -13306,7 +13316,13 @@ public class AudioService extends IAudioService.Stub } final long identity = Binder.clearCallingIdentity(); try { if (android.media.audiopolicy.Flags.audioMixOwnership()) { synchronized (mMixes) { removeMixes(new ArrayList(mMixes)); } } else { mAudioSystem.registerPolicyMixes(mMixes, false); } } finally { Binder.restoreCallingIdentity(identity); } Loading Loading @@ -13350,6 +13366,17 @@ public class AudioService extends IAudioService.Stub int addMixes(@NonNull ArrayList<AudioMix> mixes) { synchronized (mMixes) { if (android.media.audiopolicy.Flags.audioMixOwnership()) { for (AudioMix mix : mixes) { setMixRegistration(mix); } int result = mAudioSystem.registerPolicyMixes(mixes, true); if (result == AudioSystem.SUCCESS) { this.add(mixes); } return result; } this.add(mixes); return mAudioSystem.registerPolicyMixes(mixes, true); }