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

Commit c8985eb7 authored by Oscar Azucena's avatar Oscar Azucena
Browse files

Add audio permission check to audio product strategies

Also moved legacy audio stream conversion methods outside of the
permission check since they are used in various non-permission
guarded use cases (i.e. audio attribute legacy stream conversions)

Bug: 316643994
Test: atest AudioManagerTest
Flag: android.media.audiopolicy.multi_zone_audio
Change-Id: I542545ee174e6712d56bf8ab820a7676dcb37be5
parent 3f045c85
Loading
Loading
Loading
Loading
+13 −13
Original line number Diff line number Diff line
@@ -7550,7 +7550,7 @@ package android.media {
    method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int[] getActiveAssistantServicesUids();
    method @IntRange(from=0) public long getAdditionalOutputDeviceDelay(@NonNull android.media.AudioDeviceInfo);
    method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int[] getAssistantServicesUids();
    method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public static java.util.List<android.media.audiopolicy.AudioProductStrategy> getAudioProductStrategies();
    method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MODIFY_AUDIO_ROUTING, "android.permission.QUERY_AUDIO_STATE", android.Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED}) public static java.util.List<android.media.audiopolicy.AudioProductStrategy> getAudioProductStrategies();
    method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public static java.util.List<android.media.audiopolicy.AudioVolumeGroup> getAudioVolumeGroups();
    method @NonNull @RequiresPermission(android.Manifest.permission.CALL_AUDIO_INTERCEPTION) public android.media.AudioRecord getCallDownlinkExtractionAudioRecord(@NonNull android.media.AudioFormat);
    method @NonNull @RequiresPermission(android.Manifest.permission.CALL_AUDIO_INTERCEPTION) public android.media.AudioTrack getCallUplinkInjectionAudioTrack(@NonNull android.media.AudioFormat);
@@ -8097,18 +8097,18 @@ package android.media.audiopolicy {
  }
  public final class AudioProductStrategy implements android.os.Parcelable {
    method @NonNull public static android.media.audiopolicy.AudioProductStrategy createInvalidAudioProductStrategy(int);
    method public int describeContents();
    method @NonNull public android.media.AudioAttributes getAudioAttributes();
    method @FlaggedApi("android.media.audiopolicy.multi_zone_audio") @Nullable public static android.media.audiopolicy.AudioProductStrategy getAudioProductStrategyForAudioAttributes(@NonNull android.media.AudioAttributes, int, boolean);
    method public int getId();
    method @NonNull public String getName();
    method @FlaggedApi("android.media.audiopolicy.multi_zone_audio") public static int getVolumeGroupIdForAudioAttributes(@NonNull android.media.AudioAttributes, int, boolean);
    method @FlaggedApi("android.media.audiopolicy.multi_zone_audio") public int getVolumeGroupIdForAudioAttributes(@NonNull android.media.AudioAttributes, int);
    method @FlaggedApi("android.media.audiopolicy.multi_zone_audio") public int getZoneId();
    method @FlaggedApi("android.media.audiopolicy.multi_zone_audio") public static int getZoneIdForAudioVolumeGroupId(int);
    method public boolean supportsAudioAttributes(@NonNull android.media.AudioAttributes);
    method @FlaggedApi("android.media.audiopolicy.multi_zone_audio") public boolean supportsAudioAttributes(@NonNull android.media.AudioAttributes, int);
    method @FlaggedApi("android.media.audiopolicy.multi_zone_audio") @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MODIFY_AUDIO_ROUTING, "android.permission.QUERY_AUDIO_STATE", android.Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED}) public static android.media.audiopolicy.AudioProductStrategy createInvalidAudioProductStrategy(int);
    method public int describeContents();
    method @FlaggedApi("android.media.audiopolicy.multi_zone_audio") @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MODIFY_AUDIO_ROUTING, "android.permission.QUERY_AUDIO_STATE", android.Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED}) public android.media.AudioAttributes getAudioAttributes();
    method @FlaggedApi("android.media.audiopolicy.multi_zone_audio") @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MODIFY_AUDIO_ROUTING, "android.permission.QUERY_AUDIO_STATE", android.Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED}) public static android.media.audiopolicy.AudioProductStrategy getAudioProductStrategyForAudioAttributes(@NonNull android.media.AudioAttributes, int, boolean);
    method @FlaggedApi("android.media.audiopolicy.multi_zone_audio") @RequiresPermission(anyOf={android.Manifest.permission.MODIFY_AUDIO_ROUTING, "android.permission.QUERY_AUDIO_STATE", android.Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED}) public int getId();
    method @FlaggedApi("android.media.audiopolicy.multi_zone_audio") @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MODIFY_AUDIO_ROUTING, "android.permission.QUERY_AUDIO_STATE", android.Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED}) public String getName();
    method @FlaggedApi("android.media.audiopolicy.multi_zone_audio") @RequiresPermission(anyOf={android.Manifest.permission.MODIFY_AUDIO_ROUTING, "android.permission.QUERY_AUDIO_STATE", android.Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED}) public static int getVolumeGroupIdForAudioAttributes(@NonNull android.media.AudioAttributes, int, boolean);
    method @FlaggedApi("android.media.audiopolicy.multi_zone_audio") @RequiresPermission(anyOf={android.Manifest.permission.MODIFY_AUDIO_ROUTING, "android.permission.QUERY_AUDIO_STATE", android.Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED}) public int getVolumeGroupIdForAudioAttributes(@NonNull android.media.AudioAttributes, int);
    method @FlaggedApi("android.media.audiopolicy.multi_zone_audio") @RequiresPermission(anyOf={android.Manifest.permission.MODIFY_AUDIO_ROUTING, "android.permission.QUERY_AUDIO_STATE", android.Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED}) public int getZoneId();
    method @FlaggedApi("android.media.audiopolicy.multi_zone_audio") @RequiresPermission(anyOf={android.Manifest.permission.MODIFY_AUDIO_ROUTING, "android.permission.QUERY_AUDIO_STATE", android.Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED}) public static int getZoneIdForAudioVolumeGroupId(int);
    method @FlaggedApi("android.media.audiopolicy.multi_zone_audio") @RequiresPermission(anyOf={android.Manifest.permission.MODIFY_AUDIO_ROUTING, "android.permission.QUERY_AUDIO_STATE", android.Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED}) public boolean supportsAudioAttributes(@NonNull android.media.AudioAttributes);
    method @FlaggedApi("android.media.audiopolicy.multi_zone_audio") @RequiresPermission(anyOf={android.Manifest.permission.MODIFY_AUDIO_ROUTING, "android.permission.QUERY_AUDIO_STATE", android.Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED}) public boolean supportsAudioAttributes(@NonNull android.media.AudioAttributes, int);
    method public void writeToParcel(@NonNull android.os.Parcel, int);
    field @NonNull public static final android.os.Parcelable.Creator<android.media.audiopolicy.AudioProductStrategy> CREATOR;
    field @FlaggedApi("android.media.audiopolicy.multi_zone_audio") public static final int DEFAULT_ZONE_ID = 0; // 0x0
+37 −16
Original line number Diff line number Diff line
@@ -104,37 +104,43 @@ static jint nativeAudioAttributesFromJavaAudioAttributes(
    return (jint)AUDIO_JAVA_SUCCESS;
}

static jint nativeAudioAttributesToJavaAudioAttributes(
        JNIEnv* env, jobject *jAudioAttributes, const audio_attributes_t &attributes)
static jint nativeAudioAttributesToJavaAudioAttributesBuilder(
        JNIEnv* env, jobject jAudioAttributesBuilder, const audio_attributes_t &attributes)
{
    ScopedLocalRef<jobject> jAttributeBuilder(env, env->NewObject(gAudioAttributesBuilderClass,
                                                                  gAudioAttributesBuilderCstor));
    if (jAttributeBuilder.get() == nullptr) {
        return (jint)AUDIO_JAVA_ERROR;
    }

    const bool isSystemUsage = env->CallStaticBooleanMethod(gAudioAttributesClass,
                                                      gAudioAttributesClassMethods.isSystemUsage,
                                                      attributes.usage);
        gAudioAttributesClassMethods.isSystemUsage, attributes.usage);
    if (isSystemUsage) {
        env->CallObjectMethod(jAttributeBuilder.get(),
        env->CallObjectMethod(jAudioAttributesBuilder,
                              gAudioAttributesBuilderMethods.setSystemUsage, attributes.usage);
    } else {
        env->CallObjectMethod(jAttributeBuilder.get(), gAudioAttributesBuilderMethods.setUsage,
        env->CallObjectMethod(jAudioAttributesBuilder, gAudioAttributesBuilderMethods.setUsage,
                              attributes.usage);
    }
    env->CallObjectMethod(jAttributeBuilder.get(),
    env->CallObjectMethod(jAudioAttributesBuilder,
                          gAudioAttributesBuilderMethods.setInternalCapturePreset,
                          attributes.source);
    env->CallObjectMethod(jAttributeBuilder.get(),
    env->CallObjectMethod(jAudioAttributesBuilder,
                          gAudioAttributesBuilderMethods.setInternalContentType,
                          attributes.content_type);
    env->CallObjectMethod(jAttributeBuilder.get(),
    env->CallObjectMethod(jAudioAttributesBuilder,
                          gAudioAttributesBuilderMethods.replaceFlags,
                          attributes.flags);
    env->CallObjectMethod(jAttributeBuilder.get(),
    env->CallObjectMethod(jAudioAttributesBuilder,
                          gAudioAttributesBuilderMethods.addTag,
                          env->NewStringUTF(attributes.tags));
    return (jint)AUDIO_JAVA_SUCCESS;
}

static jint nativeAudioAttributesToJavaAudioAttributes(
        JNIEnv* env, jobject *jAudioAttributes, const audio_attributes_t &attributes)
{
    ScopedLocalRef<jobject> jAttributeBuilder(env, env->NewObject(gAudioAttributesBuilderClass,
                                                                  gAudioAttributesBuilderCstor));
    if (jAttributeBuilder.get() == nullptr) {
        return (jint)AUDIO_JAVA_ERROR;
    }

    nativeAudioAttributesToJavaAudioAttributesBuilder(env, jAttributeBuilder.get(), attributes);

    *jAudioAttributes = env->CallObjectMethod(jAttributeBuilder.get(),
                                              gAudioAttributesBuilderMethods.build);
@@ -161,6 +167,13 @@ jint JNIAudioAttributeHelper::nativeToJava(
    return nativeAudioAttributesToJavaAudioAttributes(env, jAudioAttributes, attributes);
}


jint JNIAudioAttributeHelper::nativeToJavaBuilder(
        JNIEnv* env, jobject jAttributesBuilder, const audio_attributes_t &attributes)
{
    return nativeAudioAttributesToJavaAudioAttributesBuilder(env, jAttributesBuilder, attributes);
}

jint JNIAudioAttributeHelper::getJavaArray(
        JNIEnv* env, jobjectArray *jAudioAttributeArray, jint numAudioAttributes)
{
@@ -168,6 +181,14 @@ jint JNIAudioAttributeHelper::getJavaArray(
    return *jAudioAttributeArray == NULL? (jint)AUDIO_JAVA_ERROR : (jint)AUDIO_JAVA_SUCCESS;
}

bool JNIAudioAttributeHelper::isInstanceOfAudioAttributes(JNIEnv *env, jobject object) {
    return env->IsInstanceOf(object, gAudioAttributesClass);
}

bool JNIAudioAttributeHelper::isInstanceOfAudioAttributesBuilder(JNIEnv *env, jobject object) {
    return env->IsInstanceOf(object, gAudioAttributesBuilderClass);
}

/*
 * JNI registration.
 */
+14 −0
Original line number Diff line number Diff line
@@ -60,6 +60,16 @@ public:
    static jint nativeToJava(
            JNIEnv* env, jobject *jAudioAttributes, const audio_attributes_t &attributes);

    /**
     * @brief nativeToJava AudioAttributes.Builder Java object from a native AudioAttributes.
     * @param env
     * @param jAttributesBuilder JAVA AudioAttribute.Builder object
     * @param attributes native AudioAttribute
     * @return AUDIO_JAVA_SUCCESS on success, error code otherwise
     */
    static jint nativeToJavaBuilder(
            JNIEnv* env, jobject jAttributesBuilder, const audio_attributes_t &attributes);

    /**
     * @brief getJavaArray: creates an array of JAVA AudioAttributes objects
     * @param env
@@ -69,6 +79,10 @@ public:
     */
    static jint getJavaArray(
            JNIEnv* env, jobjectArray *jAudioAttributeArray, jint numAudioAttributes);

    static bool isInstanceOfAudioAttributes(JNIEnv *env, jobject object);

    static bool isInstanceOfAudioAttributesBuilder(JNIEnv *env, jobject object);
};

}; // namespace android
+72 −0
Original line number Diff line number Diff line
@@ -172,6 +172,74 @@ exit:
    return jStatus;
}

static jint android_media_AudioSystem_getAudioAttributesForLegacyStream(JNIEnv *env, jobject clazz,
                                                                       jint jStreamType,
                                                                       jobject jAttributesBuilder) {
    if (env == NULL) {
        return AUDIO_JAVA_DEAD_OBJECT;
    }

    if (jAttributesBuilder == NULL) {
        ALOGE("%s: NULL AudioAttributes.Builder", __func__);
        return (jint)AUDIO_JAVA_BAD_VALUE;
    }

    if (!JNIAudioAttributeHelper::isInstanceOfAudioAttributesBuilder(env, jAttributesBuilder)) {
        ALOGE("%s: not an AudioAttributes", __func__);
        return (jint)AUDIO_JAVA_BAD_VALUE;
    }

    audio_attributes_t attributes;
    status_t status = AudioSystem::getAttributesForStreamType((audio_stream_type_t)jStreamType,
                                                          attributes);

    if (status != NO_ERROR) {
        ALOGE("%s: error getting audio attributes for stream %d", __func__, jStreamType);
        return nativeToJavaStatus(status);
    }

    status = JNIAudioAttributeHelper::nativeToJavaBuilder(env, jAttributesBuilder, attributes);

    if (status != NO_ERROR) {
        ALOGE("getAudioAttributesForLegacyStream error %d", status);
        return nativeToJavaStatus(status);
    }

    return AUDIO_JAVA_SUCCESS;
}

static jint android_media_AudioSystem_getLegacyStreamForAudioAttributes(JNIEnv *env, jobject clazz,
                                                                       jobject jattributes) {
    if (env == NULL) {
        return (jint)AUDIO_STREAM_DEFAULT;
    }

    if (jattributes == NULL) {
        ALOGE("%s: NULL AudioAttributes", __func__);
        return (jint)AUDIO_STREAM_DEFAULT;
    }

    if (!JNIAudioAttributeHelper::isInstanceOfAudioAttributes(env, jattributes)) {
        ALOGE("%s not an AudioAttributes", __func__ );
        return (jint)AUDIO_STREAM_DEFAULT;
    }

    audio_attributes_t attributes;
    int status = JNIAudioAttributeHelper::nativeFromJava(env, jattributes, &attributes);

    if (status != NO_ERROR) {
        ALOGE("%s error %d", __func__,  status);
        return (jint)AUDIO_STREAM_DEFAULT;;
    }
    audio_stream_type_t type;
    status = AudioSystem::getStreamTypeForAttributes(attributes, type);
    if (status != NO_ERROR) {
        ALOGE("%s error %d", __func__, status);
        return (jint)AUDIO_STREAM_DEFAULT;;
    }
    return (jint)type;
}

static jint
android_media_AudioSystem_listAudioProductStrategies(JNIEnv *env, jobject clazz,
                                                     jobject jStrategies)
@@ -218,6 +286,10 @@ exit:
static const JNINativeMethod gMethods[] = {
    {"native_list_audio_product_strategies", "(Ljava/util/ArrayList;)I",
                        (void *)android_media_AudioSystem_listAudioProductStrategies},
    {"native_get_audio_attributes_for_legacy_stream", "(ILandroid/media/AudioAttributes$Builder;)I",
     (void *)android_media_AudioSystem_getAudioAttributesForLegacyStream},
    {"native_get_legacy_stream_for_audio_attributes", "(Landroid/media/AudioAttributes;)I",
     (void *)android_media_AudioSystem_getLegacyStreamForAudioAttributes},
};

int register_android_media_AudioProductStrategies(JNIEnv *env)
+14 −0
Original line number Diff line number Diff line
@@ -896,6 +896,18 @@ static jint android_media_AudioSystem_setMaxVolumeIndexForGroup(JNIEnv *env, job
            AudioSystem::setMaxVolumeIndexForGroup(static_cast<volume_group_t>(groupId), index));
}

static jint android_media_AudioSystem_getVolumeGroupIdForStreamType(JNIEnv *env, jobject thiz,
                                                                jint stream) {
    int group;
    status_t status = AudioSystem::getVolumeGroupIdForStreamType(
            static_cast<audio_stream_type_t>(stream), group);
    if (status != NO_ERROR) {
        ALOGE("%s AudioSystem::getVolumeGroupIdForStreamType error %d", __func__, status);
        group = -1;
    }
    return group;
}

static jint
android_media_AudioSystem_setMasterVolume(JNIEnv *env, jobject thiz, jfloat value)
{
@@ -3566,6 +3578,8 @@ static const JNINativeMethod gMethods[] = {
                               android_media_AudioSystem_getMaxVolumeIndexForGroup),
        MAKE_JNI_NATIVE_METHOD("setMaxVolumeIndexForGroup", "(II)I",
                               android_media_AudioSystem_setMaxVolumeIndexForGroup),
        MAKE_JNI_NATIVE_METHOD("getVolumeGroupIdForStreamType", "(I)I",
                               android_media_AudioSystem_getVolumeGroupIdForStreamType),
        MAKE_AUDIO_SYSTEM_METHOD(setMasterVolume),
        MAKE_AUDIO_SYSTEM_METHOD(getMasterVolume),
        MAKE_AUDIO_SYSTEM_METHOD(setMasterMute),
Loading