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

Commit 24a4e3fd authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Add APIs for setting preferred mixer attributes."

parents f1bb949d 89f87edf
Loading
Loading
Loading
Loading
+25 −0
Original line number Diff line number Diff line
@@ -20549,10 +20549,12 @@ package android.media {
    method public int abandonAudioFocusRequest(@NonNull android.media.AudioFocusRequest);
    method public void addOnCommunicationDeviceChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.AudioManager.OnCommunicationDeviceChangedListener);
    method public void addOnModeChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.AudioManager.OnModeChangedListener);
    method public void addOnPreferredMixerAttributesChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.AudioManager.OnPreferredMixerAttributesChangedListener);
    method public void adjustStreamVolume(int, int, int);
    method public void adjustSuggestedStreamVolume(int, int, int);
    method public void adjustVolume(int, int);
    method public void clearCommunicationDevice();
    method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_SETTINGS) public boolean clearPreferredMixerAttributes(@NonNull android.media.AudioAttributes, @NonNull android.media.AudioDeviceInfo);
    method public void dispatchMediaKeyEvent(android.view.KeyEvent);
    method public int generateAudioSessionId();
    method @NonNull public java.util.List<android.media.AudioPlaybackConfiguration> getActivePlaybackConfigurations();
@@ -20570,6 +20572,7 @@ package android.media {
    method public int getMode();
    method public String getParameters(String);
    method @Deprecated public static int getPlaybackOffloadSupport(@NonNull android.media.AudioFormat, @NonNull android.media.AudioAttributes);
    method @Nullable public android.media.AudioMixerAttributes getPreferredMixerAttributes(@NonNull android.media.AudioAttributes, @NonNull android.media.AudioDeviceInfo);
    method public String getProperty(String);
    method public int getRingerMode();
    method @Deprecated public int getRouting(int);
@@ -20578,6 +20581,7 @@ package android.media {
    method public int getStreamMinVolume(int);
    method public int getStreamVolume(int);
    method public float getStreamVolumeDb(int, int, int);
    method @NonNull public java.util.List<android.media.AudioMixerAttributes> getSupportedMixerAttributes(@NonNull android.media.AudioDeviceInfo);
    method @Deprecated public int getVibrateSetting(int);
    method @Deprecated public boolean isBluetoothA2dpOn();
    method public boolean isBluetoothScoAvailableOffCall();
@@ -20605,6 +20609,7 @@ package android.media {
    method @Deprecated public boolean registerRemoteController(android.media.RemoteController);
    method public void removeOnCommunicationDeviceChangedListener(@NonNull android.media.AudioManager.OnCommunicationDeviceChangedListener);
    method public void removeOnModeChangedListener(@NonNull android.media.AudioManager.OnModeChangedListener);
    method public void removeOnPreferredMixerAttributesChangedListener(@NonNull android.media.AudioManager.OnPreferredMixerAttributesChangedListener);
    method @Deprecated public int requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, int, int);
    method public int requestAudioFocus(@NonNull android.media.AudioFocusRequest);
    method public void setAllowedCapturePolicy(int);
@@ -20615,6 +20620,7 @@ package android.media {
    method public void setMicrophoneMute(boolean);
    method public void setMode(int);
    method public void setParameters(String);
    method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_SETTINGS) public boolean setPreferredMixerAttributes(@NonNull android.media.AudioAttributes, @NonNull android.media.AudioDeviceInfo, @NonNull android.media.AudioMixerAttributes);
    method public void setRingerMode(int);
    method @Deprecated public void setRouting(int, int, int);
    method @Deprecated public void setSpeakerphoneOn(boolean);
@@ -20770,6 +20776,10 @@ package android.media {
    method public void onModeChanged(int);
  }
  public static interface AudioManager.OnPreferredMixerAttributesChangedListener {
    method public void onPreferredMixerAttributesChanged(@NonNull android.media.AudioAttributes, @NonNull android.media.AudioDeviceInfo, @Nullable android.media.AudioMixerAttributes);
  }
  public final class AudioMetadata {
    method @NonNull public static android.media.AudioMetadataMap createMap();
  }
@@ -20805,6 +20815,21 @@ package android.media {
    method @IntRange(from=0) public int size();
  }
  public final class AudioMixerAttributes implements android.os.Parcelable {
    method public int describeContents();
    method @NonNull public android.media.AudioFormat getFormat();
    method public int getMixerBehavior();
    method public void writeToParcel(@NonNull android.os.Parcel, int);
    field @NonNull public static final android.os.Parcelable.Creator<android.media.AudioMixerAttributes> CREATOR;
    field public static final int MIXER_BEHAVIOR_DEFAULT = 0; // 0x0
  }
  public static final class AudioMixerAttributes.Builder {
    ctor public AudioMixerAttributes.Builder(@NonNull android.media.AudioFormat);
    method @NonNull public android.media.AudioMixerAttributes build();
    method @NonNull public android.media.AudioMixerAttributes.Builder setMixerBehavior(int);
  }
  public final class AudioPlaybackCaptureConfiguration {
    method @NonNull public int[] getExcludeUids();
    method @NonNull public int[] getExcludeUsages();
+46 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ANDROID_MEDIA_AUDIOMIXERATTRIBUTES_H
#define ANDROID_MEDIA_AUDIOMIXERATTRIBUTES_H

#include <system/audio.h>

// Keep sync with AudioMixerAttributes.java
#define MIXER_BEHAVIOR_DEFAULT 0
// Invalid value is not added in JAVA API, but keep sync with native value
#define MIXER_BEHAVIOR_INVALID -1

static inline audio_mixer_behavior_t audioMixerBehaviorToNative(int mixerBehavior) {
    switch (mixerBehavior) {
        case MIXER_BEHAVIOR_DEFAULT:
            return AUDIO_MIXER_BEHAVIOR_DEFAULT;
        default:
            return AUDIO_MIXER_BEHAVIOR_INVALID;
    }
}

static inline jint audioMixerBehaviorFromNative(audio_mixer_behavior_t mixerBehavior) {
    switch (mixerBehavior) {
        case AUDIO_MIXER_BEHAVIOR_DEFAULT:
            return MIXER_BEHAVIOR_DEFAULT;
        case AUDIO_MIXER_BEHAVIOR_INVALID:
        default:
            return MIXER_BEHAVIOR_INVALID;
    }
}

#endif
+252 −1
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@
#include <android/media/AudioVibratorInfo.h>
#include <android/media/INativeSpatializerCallback.h>
#include <android/media/ISpatializer.h>
#include <android/media/audio/common/AudioConfigBase.h>
#include <android_os_Parcel.h>
#include <audiomanager/AudioManager.h>
#include <jni.h>
@@ -34,6 +35,7 @@
#include <system/audio_policy.h>
#include <utils/Log.h>

#include <optional>
#include <sstream>
#include <vector>

@@ -43,6 +45,7 @@
#include "android_media_AudioEffectDescriptor.h"
#include "android_media_AudioErrors.h"
#include "android_media_AudioFormat.h"
#include "android_media_AudioMixerAttributes.h"
#include "android_media_AudioProfile.h"
#include "android_media_MicrophoneInfo.h"
#include "android_util_Binder.h"
@@ -51,6 +54,7 @@
// ----------------------------------------------------------------------------

using namespace android;
using media::audio::common::AudioConfigBase;

static const char* const kClassPathName = "android/media/AudioSystem";

@@ -145,10 +149,12 @@ static struct {
} gAudioMixFields;

static jclass gAudioFormatClass;
static jmethodID gAudioFormatCstor;
static struct {
    jfieldID    mEncoding;
    jfieldID    mSampleRate;
    jfieldID    mChannelMask;
    jfieldID mChannelIndexMask;
    // other fields unused by JNI
} gAudioFormatFields;

@@ -211,6 +217,7 @@ static struct {
    jfieldID mChannelMasks;
    jfieldID mChannelIndexMasks;
    jfieldID mEncapsulationType;
    jfieldID mMixerBehaviors;
} gAudioProfileFields;

jclass gVibratorClass;
@@ -221,6 +228,13 @@ static struct {
    jmethodID getMaxAmplitude;
} gVibratorMethods;

jclass gAudioMixerAttributesClass;
jmethodID gAudioMixerAttributesCstor;
static struct {
    jfieldID mFormat;
    jfieldID mMixerBehavior;
} gAudioMixerAttributesField;

static Mutex gLock;

enum AudioError {
@@ -237,6 +251,12 @@ enum {

#define MAX_PORT_GENERATION_SYNC_ATTEMPTS 5

// Keep sync with AudioFormat.java
#define AUDIO_FORMAT_HAS_PROPERTY_ENCODING 0x1
#define AUDIO_FORMAT_HAS_PROPERTY_SAMPLE_RATE 0x2
#define AUDIO_FORMAT_HAS_PROPERTY_CHANNEL_MASK 0x4
#define AUDIO_FORMAT_HAS_PROPERTY_CHANNEL_INDEX_MASK 0x8

// ----------------------------------------------------------------------------
// ref-counted object for audio port callbacks
class JNIAudioPortCallback: public AudioSystem::AudioPortCallback
@@ -2105,6 +2125,80 @@ void javaAudioFormatToNativeAudioConfig(JNIEnv *env, audio_config_t *nConfig,
    }
}

void javaAudioFormatToNativeAudioConfigBase(JNIEnv *env, const jobject jFormat,
                                            audio_config_base_t *nConfigBase, bool isInput) {
    *nConfigBase = AUDIO_CONFIG_BASE_INITIALIZER;
    nConfigBase->format =
            audioFormatToNative(env->GetIntField(jFormat, gAudioFormatFields.mEncoding));
    nConfigBase->sample_rate = env->GetIntField(jFormat, gAudioFormatFields.mSampleRate);
    jint jChannelMask = env->GetIntField(jFormat, gAudioFormatFields.mChannelMask);
    jint jChannelIndexMask = env->GetIntField(jFormat, gAudioFormatFields.mChannelIndexMask);
    nConfigBase->channel_mask = jChannelIndexMask != 0
            ? audio_channel_mask_from_representation_and_bits(AUDIO_CHANNEL_REPRESENTATION_INDEX,
                                                              jChannelIndexMask)
            : isInput ? inChannelMaskToNative(jChannelMask)
                      : outChannelMaskToNative(jChannelMask);
}

jobject nativeAudioConfigBaseToJavaAudioFormat(JNIEnv *env, const audio_config_base_t *nConfigBase,
                                               bool isInput) {
    if (nConfigBase == nullptr) {
        return nullptr;
    }
    int propertyMask = AUDIO_FORMAT_HAS_PROPERTY_ENCODING | AUDIO_FORMAT_HAS_PROPERTY_SAMPLE_RATE;
    int channelMask = 0;
    int channelIndexMask = 0;
    switch (audio_channel_mask_get_representation(nConfigBase->channel_mask)) {
        case AUDIO_CHANNEL_REPRESENTATION_POSITION:
            channelMask = isInput ? inChannelMaskFromNative(nConfigBase->channel_mask)
                                  : outChannelMaskFromNative(nConfigBase->channel_mask);
            propertyMask |= AUDIO_FORMAT_HAS_PROPERTY_CHANNEL_MASK;
            break;
        case AUDIO_CHANNEL_REPRESENTATION_INDEX:
            channelIndexMask = audio_channel_mask_get_bits(nConfigBase->channel_mask);
            propertyMask |= AUDIO_FORMAT_HAS_PROPERTY_CHANNEL_INDEX_MASK;
            break;
        default:
            // This must not happen
            break;
    }
    return env->NewObject(gAudioFormatClass, gAudioFormatCstor, propertyMask,
                          audioFormatFromNative(nConfigBase->format), nConfigBase->sample_rate,
                          channelMask, channelIndexMask);
}

jint convertAudioMixerAttributesToNative(JNIEnv *env, const jobject jAudioMixerAttributes,
                                         audio_mixer_attributes_t *nMixerAttributes) {
    ScopedLocalRef<jobject> jFormat(env,
                                    env->GetObjectField(jAudioMixerAttributes,
                                                        gAudioMixerAttributesField.mFormat));
    javaAudioFormatToNativeAudioConfigBase(env, jFormat.get(), &nMixerAttributes->config,
                                           false /*isInput*/);
    nMixerAttributes->mixer_behavior = audioMixerBehaviorToNative(
            env->GetIntField(jAudioMixerAttributes, gAudioMixerAttributesField.mMixerBehavior));
    if (nMixerAttributes->mixer_behavior == AUDIO_MIXER_BEHAVIOR_INVALID) {
        return (jint)AUDIO_JAVA_BAD_VALUE;
    }
    return (jint)AUDIO_JAVA_SUCCESS;
}

jobject convertAudioMixerAttributesFromNative(JNIEnv *env,
                                              const audio_mixer_attributes_t *nMixerAttributes) {
    if (nMixerAttributes == nullptr) {
        return nullptr;
    }
    jint mixerBehavior = audioMixerBehaviorFromNative(nMixerAttributes->mixer_behavior);
    if (mixerBehavior == MIXER_BEHAVIOR_INVALID) {
        return nullptr;
    }
    ScopedLocalRef<jobject>
            jFormat(env,
                    nativeAudioConfigBaseToJavaAudioFormat(env, &nMixerAttributes->config,
                                                           false /*isInput*/));
    return env->NewObject(gAudioMixerAttributesClass, gAudioMixerAttributesCstor, jFormat.get(),
                          mixerBehavior);
}

static jint convertAudioMixToNative(JNIEnv *env,
                                    AudioMix *nAudioMix,
                                    const jobject jAudioMix)
@@ -2966,6 +3060,142 @@ static jint android_media_AudioSystem_getDirectProfilesForAttributes(JNIEnv *env
    return jStatus;
}

static jint android_media_AudioSystem_getSupportedMixerAttributes(JNIEnv *env, jobject thiz,
                                                                  jint jDeviceId,
                                                                  jobject jAudioMixerAttributes) {
    ALOGV("%s", __func__);
    if (jAudioMixerAttributes == NULL) {
        ALOGE("getSupportedMixerAttributes NULL AudioMixerAttributes list");
        return (jint)AUDIO_JAVA_BAD_VALUE;
    }
    if (!env->IsInstanceOf(jAudioMixerAttributes, gListClass)) {
        ALOGE("getSupportedMixerAttributes not a list");
        return (jint)AUDIO_JAVA_BAD_VALUE;
    }

    std::vector<audio_mixer_attributes_t> nMixerAttributes;
    status_t status = AudioSystem::getSupportedMixerAttributes((audio_port_handle_t)jDeviceId,
                                                               &nMixerAttributes);
    if (status != NO_ERROR) {
        return nativeToJavaStatus(status);
    }
    for (const auto &mixerAttr : nMixerAttributes) {
        ScopedLocalRef<jobject> jMixerAttributes(env,
                                                 convertAudioMixerAttributesFromNative(env,
                                                                                       &mixerAttr));
        if (jMixerAttributes.get() == nullptr) {
            return (jint)AUDIO_JAVA_ERROR;
        }

        env->CallBooleanMethod(jAudioMixerAttributes, gListMethods.add, jMixerAttributes.get());
    }

    return (jint)AUDIO_JAVA_SUCCESS;
}

static jint android_media_AudioSystem_setPreferredMixerAttributes(JNIEnv *env, jobject thiz,
                                                                  jobject jAudioAttributes,
                                                                  jint portId, jint uid,
                                                                  jobject jAudioMixerAttributes) {
    ALOGV("%s", __func__);

    if (jAudioAttributes == nullptr) {
        ALOGE("jAudioAttributes is NULL");
        return (jint)AUDIO_JAVA_BAD_VALUE;
    }
    if (jAudioMixerAttributes == nullptr) {
        ALOGE("jAudioMixerAttributes is NULL");
        return (jint)AUDIO_JAVA_BAD_VALUE;
    }

    JNIAudioAttributeHelper::UniqueAaPtr paa = JNIAudioAttributeHelper::makeUnique();
    jint jStatus = JNIAudioAttributeHelper::nativeFromJava(env, jAudioAttributes, paa.get());
    if (jStatus != (jint)AUDIO_JAVA_SUCCESS) {
        return jStatus;
    }

    audio_mixer_attributes_t mixerAttributes = AUDIO_MIXER_ATTRIBUTES_INITIALIZER;
    jStatus = convertAudioMixerAttributesToNative(env, jAudioMixerAttributes, &mixerAttributes);
    if (jStatus != (jint)AUDIO_JAVA_SUCCESS) {
        return jStatus;
    }

    status_t status =
            AudioSystem::setPreferredMixerAttributes(paa.get(), (audio_port_handle_t)portId,
                                                     (uid_t)uid, &mixerAttributes);
    return nativeToJavaStatus(status);
}

static jint android_media_AudioSystem_getPreferredMixerAttributes(JNIEnv *env, jobject thiz,
                                                                  jobject jAudioAttributes,
                                                                  jint portId,
                                                                  jobject jAudioMixerAttributes) {
    ALOGV("%s", __func__);

    if (jAudioAttributes == nullptr) {
        ALOGE("getPreferredMixerAttributes jAudioAttributes is NULL");
        return (jint)AUDIO_JAVA_BAD_VALUE;
    }
    if (jAudioMixerAttributes == NULL) {
        ALOGE("getPreferredMixerAttributes NULL AudioMixerAttributes list");
        return (jint)AUDIO_JAVA_BAD_VALUE;
    }
    if (!env->IsInstanceOf(jAudioMixerAttributes, gListClass)) {
        ALOGE("getPreferredMixerAttributes not a list");
        return (jint)AUDIO_JAVA_BAD_VALUE;
    }

    JNIAudioAttributeHelper::UniqueAaPtr paa = JNIAudioAttributeHelper::makeUnique();
    jint jStatus = JNIAudioAttributeHelper::nativeFromJava(env, jAudioAttributes, paa.get());
    if (jStatus != (jint)AUDIO_JAVA_SUCCESS) {
        return jStatus;
    }

    std::optional<audio_mixer_attributes_t> nMixerAttributes;
    status_t status =
            AudioSystem::getPreferredMixerAttributes(paa.get(), (audio_port_handle_t)portId,
                                                     &nMixerAttributes);
    if (status != NO_ERROR) {
        return nativeToJavaStatus(status);
    }

    ScopedLocalRef<jobject>
            jMixerAttributes(env,
                             convertAudioMixerAttributesFromNative(env,
                                                                   nMixerAttributes.has_value()
                                                                           ? &nMixerAttributes
                                                                                      .value()
                                                                           : nullptr));
    if (jMixerAttributes.get() == nullptr) {
        return (jint)AUDIO_JAVA_ERROR;
    }

    env->CallBooleanMethod(jAudioMixerAttributes, gListMethods.add, jMixerAttributes.get());
    return AUDIO_JAVA_SUCCESS;
}

static jint android_media_AudioSystem_clearPreferredMixerAttributes(JNIEnv *env, jobject thiz,
                                                                    jobject jAudioAttributes,
                                                                    jint portId, jint uid) {
    ALOGV("%s", __func__);

    if (jAudioAttributes == nullptr) {
        ALOGE("jAudioAttributes is NULL");
        return (jint)AUDIO_JAVA_BAD_VALUE;
    }

    JNIAudioAttributeHelper::UniqueAaPtr paa = JNIAudioAttributeHelper::makeUnique();
    jint jStatus = JNIAudioAttributeHelper::nativeFromJava(env, jAudioAttributes, paa.get());
    if (jStatus != (jint)AUDIO_JAVA_SUCCESS) {
        return jStatus;
    }

    status_t status =
            AudioSystem::clearPreferredMixerAttributes(paa.get(), (audio_port_handle_t)portId,
                                                       (uid_t)uid);
    return nativeToJavaStatus(status);
}

// ----------------------------------------------------------------------------

static const JNINativeMethod gMethods[] =
@@ -3120,7 +3350,16 @@ static const JNINativeMethod gMethods[] =
          (void *)android_media_AudioSystem_getDirectPlaybackSupport},
         {"getDirectProfilesForAttributes",
          "(Landroid/media/AudioAttributes;Ljava/util/ArrayList;)I",
          (void *)android_media_AudioSystem_getDirectProfilesForAttributes}};
          (void *)android_media_AudioSystem_getDirectProfilesForAttributes},
         {"getSupportedMixerAttributes", "(ILjava/util/List;)I",
          (void *)android_media_AudioSystem_getSupportedMixerAttributes},
         {"setPreferredMixerAttributes",
          "(Landroid/media/AudioAttributes;IILandroid/media/AudioMixerAttributes;)I",
          (void *)android_media_AudioSystem_setPreferredMixerAttributes},
         {"getPreferredMixerAttributes", "(Landroid/media/AudioAttributes;ILjava/util/List;)I",
          (void *)android_media_AudioSystem_getPreferredMixerAttributes},
         {"clearPreferredMixerAttributes", "(Landroid/media/AudioAttributes;II)I",
          (void *)android_media_AudioSystem_clearPreferredMixerAttributes}};

static const JNINativeMethod gEventHandlerMethods[] = {
    {"native_setup",
@@ -3283,9 +3522,12 @@ int register_android_media_AudioSystem(JNIEnv *env)

    jclass audioFormatClass = FindClassOrDie(env, "android/media/AudioFormat");
    gAudioFormatClass = MakeGlobalRefOrDie(env, audioFormatClass);
    gAudioFormatCstor = GetMethodIDOrDie(env, audioFormatClass, "<init>", "(IIIII)V");
    gAudioFormatFields.mEncoding = GetFieldIDOrDie(env, audioFormatClass, "mEncoding", "I");
    gAudioFormatFields.mSampleRate = GetFieldIDOrDie(env, audioFormatClass, "mSampleRate", "I");
    gAudioFormatFields.mChannelMask = GetFieldIDOrDie(env, audioFormatClass, "mChannelMask", "I");
    gAudioFormatFields.mChannelIndexMask =
            GetFieldIDOrDie(env, audioFormatClass, "mChannelIndexMask", "I");

    jclass audioMixingRuleClass = FindClassOrDie(env, "android/media/audiopolicy/AudioMixingRule");
    gAudioMixingRuleClass = MakeGlobalRefOrDie(env, audioMixingRuleClass);
@@ -3359,6 +3601,15 @@ int register_android_media_AudioSystem(JNIEnv *env)
    gVibratorMethods.getMaxAmplitude =
            GetMethodIDOrDie(env, vibratorClass, "getHapticChannelMaximumAmplitude", "()F");

    jclass audioMixerAttributesClass = FindClassOrDie(env, "android/media/AudioMixerAttributes");
    gAudioMixerAttributesClass = MakeGlobalRefOrDie(env, audioMixerAttributesClass);
    gAudioMixerAttributesCstor = GetMethodIDOrDie(env, audioMixerAttributesClass, "<init>",
                                                  "(Landroid/media/AudioFormat;I)V");
    gAudioMixerAttributesField.mFormat = GetFieldIDOrDie(env, audioMixerAttributesClass, "mFormat",
                                                         "Landroid/media/AudioFormat;");
    gAudioMixerAttributesField.mMixerBehavior =
            GetFieldIDOrDie(env, audioMixerAttributesClass, "mMixerBehavior", "I");

    AudioSystem::addErrorCallback(android_media_AudioSystem_error_callback);

    RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
+215 −0

File changed.

Preview size limit exceeded, changes collapsed.

+18 −0
Original line number Diff line number Diff line
/* Copyright 2022, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
**     http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/

package android.media;

parcelable AudioMixerAttributes;
Loading