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

Commit eddc0d71 authored by Jiabin Huang's avatar Jiabin Huang Committed by Android (Google) Code Review
Browse files

Merge "Add support for manually set surround formats." into pi-dev

parents a2fccce5 3994075a
Loading
Loading
Loading
Loading
+58 −3
Original line number Diff line number Diff line
@@ -58,6 +58,7 @@ import android.content.res.Resources;
import android.database.Cursor;
import android.database.SQLException;
import android.location.LocationManager;
import android.media.AudioFormat;
import android.net.ConnectivityManager;
import android.net.NetworkScoreManager;
import android.net.Uri;
@@ -11307,16 +11308,67 @@ public final class Settings {
         */
         public static final int ENCODED_SURROUND_OUTPUT_ALWAYS = 2;
        /**
         * Surround sound formats are available according to the choice
         * of user, even if they are not detected by the hardware. Those
         * formats will be reported as part of the HDMI output capability.
         * Applications are then free to use either PCM or encoded output.
         *
         * An example use case would be an AVR that doesn't report a surround
         * format while the user knows the AVR does support it.
         * @hide
         */
        public static final int ENCODED_SURROUND_OUTPUT_MANUAL = 3;
        /**
         * Set to ENCODED_SURROUND_OUTPUT_AUTO,
         * ENCODED_SURROUND_OUTPUT_NEVER or
         * ENCODED_SURROUND_OUTPUT_ALWAYS
         * ENCODED_SURROUND_OUTPUT_NEVER,
         * ENCODED_SURROUND_OUTPUT_ALWAYS or
         * ENCODED_SURROUND_OUTPUT_MANUAL
         * @hide
         */
        public static final String ENCODED_SURROUND_OUTPUT = "encoded_surround_output";
        private static final Validator ENCODED_SURROUND_OUTPUT_VALIDATOR =
                new SettingsValidators.DiscreteValueValidator(new String[] {"0", "1", "2"});
                new SettingsValidators.DiscreteValueValidator(new String[] {"0", "1", "2", "3"});
        /**
         * Surround sounds formats that are enabled when ENCODED_SURROUND_OUTPUT is set to
         * ENCODED_SURROUND_OUTPUT_MANUAL. Encoded as comma separated list. Allowed values
         * are the format constants defined in AudioFormat.java. Ex:
         *
         * "5,6"
         *
         * @hide
         */
        public static final String ENCODED_SURROUND_OUTPUT_ENABLED_FORMATS =
                "encoded_surround_output_enabled_formats";
        private static final Validator ENCODED_SURROUND_OUTPUT_ENABLED_FORMATS_VALIDATOR =
                new Validator() {
            @Override
            public boolean validate(String value) {
                try {
                    String[] surroundFormats = TextUtils.split(value, ",");
                    for (String format : surroundFormats) {
                        int audioFormat = Integer.valueOf(format);
                        boolean isSurroundFormat = false;
                        for (int sf : AudioFormat.SURROUND_SOUND_ENCODING) {
                            if (sf == audioFormat) {
                                isSurroundFormat = true;
                                break;
                            }
                        }
                        if (!isSurroundFormat) {
                            return false;
                        }
                    }
                    return true;
                } catch (NumberFormatException e) {
                    return false;
                }
            }
        };
        /**
         * Persisted safe headphone volume management state by AudioService
@@ -11963,6 +12015,7 @@ public final class Settings {
            CALL_AUTO_RETRY,
            DOCK_AUDIO_MEDIA_ENABLED,
            ENCODED_SURROUND_OUTPUT,
            ENCODED_SURROUND_OUTPUT_ENABLED_FORMATS,
            LOW_POWER_MODE_TRIGGER_LEVEL,
            BLUETOOTH_ON,
            PRIVATE_DNS_MODE,
@@ -11999,6 +12052,8 @@ public final class Settings {
            VALIDATORS.put(CALL_AUTO_RETRY, CALL_AUTO_RETRY_VALIDATOR);
            VALIDATORS.put(DOCK_AUDIO_MEDIA_ENABLED, DOCK_AUDIO_MEDIA_ENABLED_VALIDATOR);
            VALIDATORS.put(ENCODED_SURROUND_OUTPUT, ENCODED_SURROUND_OUTPUT_VALIDATOR);
            VALIDATORS.put(ENCODED_SURROUND_OUTPUT_ENABLED_FORMATS,
                    ENCODED_SURROUND_OUTPUT_ENABLED_FORMATS_VALIDATOR);
            VALIDATORS.put(LOW_POWER_MODE_TRIGGER_LEVEL, LOW_POWER_MODE_TRIGGER_LEVEL_VALIDATOR);
            VALIDATORS.put(LOW_POWER_MODE_TRIGGER_LEVEL_MAX,
                    LOW_POWER_MODE_TRIGGER_LEVEL_VALIDATOR);
+89 −0
Original line number Diff line number Diff line
@@ -48,6 +48,15 @@ static struct {
    jmethodID    toArray;
} gArrayListMethods;

static jclass gBooleanClass;
static jmethodID gBooleanCstor;

static jclass gIntegerClass;
static jmethodID gIntegerCstor;

static jclass gMapClass;
static jmethodID gMapPut;

static jclass gAudioHandleClass;
static jmethodID gAudioHandleCstor;
static struct {
@@ -1829,6 +1838,72 @@ android_media_AudioSystem_getMicrophones(JNIEnv *env, jobject thiz, jobject jMic
    return jStatus;
}

static jint
android_media_AudioSystem_getSurroundFormats(JNIEnv *env, jobject thiz,
                                             jobject jSurroundFormats, jboolean reported)
{
    ALOGV("getSurroundFormats");

    if (jSurroundFormats == NULL) {
        ALOGE("jSurroundFormats is NULL");
        return (jint)AUDIO_JAVA_BAD_VALUE;
    }
    if (!env->IsInstanceOf(jSurroundFormats, gMapClass)) {
        ALOGE("getSurroundFormats not a map");
        return (jint)AUDIO_JAVA_BAD_VALUE;
    }

    jint jStatus;
    unsigned int numSurroundFormats = 0;
    audio_format_t *surroundFormats = NULL;
    bool *surroundFormatsEnabled = NULL;
    status_t status = AudioSystem::getSurroundFormats(
            &numSurroundFormats, surroundFormats, surroundFormatsEnabled, reported);
    if (status != NO_ERROR) {
        ALOGE_IF(status != NO_ERROR, "AudioSystem::getSurroundFormats error %d", status);
        jStatus = nativeToJavaStatus(status);
        goto exit;
    }
    if (numSurroundFormats == 0) {
        jStatus = (jint)AUDIO_JAVA_SUCCESS;
        goto exit;
    }
    surroundFormats = (audio_format_t *)calloc(numSurroundFormats, sizeof(audio_format_t));
    surroundFormatsEnabled = (bool *)calloc(numSurroundFormats, sizeof(bool));
    status = AudioSystem::getSurroundFormats(
            &numSurroundFormats, surroundFormats, surroundFormatsEnabled, reported);
    jStatus = nativeToJavaStatus(status);
    if (status != NO_ERROR) {
        ALOGE_IF(status != NO_ERROR, "AudioSystem::getSurroundFormats error %d", status);
        goto exit;
    }
    for (size_t i = 0; i < numSurroundFormats; i++) {
        jobject surroundFormat = env->NewObject(gIntegerClass, gIntegerCstor,
                                                audioFormatFromNative(surroundFormats[i]));
        jobject enabled = env->NewObject(gBooleanClass, gBooleanCstor, surroundFormatsEnabled[i]);
        env->CallObjectMethod(jSurroundFormats, gMapPut, surroundFormat, enabled);
        env->DeleteLocalRef(surroundFormat);
        env->DeleteLocalRef(enabled);
    }

exit:
    free(surroundFormats);
    free(surroundFormatsEnabled);
    return jStatus;
}

static jint
android_media_AudioSystem_setSurroundFormatEnabled(JNIEnv *env, jobject thiz,
                                                   jint audioFormat, jboolean enabled)
{
    status_t status = AudioSystem::setSurroundFormatEnabled(audioFormatToNative(audioFormat),
                                                            (bool)enabled);
    if (status != NO_ERROR) {
        ALOGE_IF(status != NO_ERROR, "AudioSystem::setSurroundFormatEnabled error %d", status);
    }
    return (jint)nativeToJavaStatus(status);
}

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

static const JNINativeMethod gMethods[] = {
@@ -1884,6 +1959,8 @@ static const JNINativeMethod gMethods[] = {
    {"getStreamVolumeDB", "(III)F", (void *)android_media_AudioSystem_getStreamVolumeDB},
    {"native_is_offload_supported", "(IIII)Z", (void *)android_media_AudioSystem_isOffloadSupported},
    {"getMicrophones", "(Ljava/util/ArrayList;)I", (void *)android_media_AudioSystem_getMicrophones},
    {"getSurroundFormats", "(Ljava/util/Map;Z)I", (void *)android_media_AudioSystem_getSurroundFormats},
    {"setSurroundFormatEnabled", "(IZ)I", (void *)android_media_AudioSystem_setSurroundFormatEnabled},
};


@@ -1903,6 +1980,18 @@ int register_android_media_AudioSystem(JNIEnv *env)
    gArrayListMethods.add = GetMethodIDOrDie(env, arrayListClass, "add", "(Ljava/lang/Object;)Z");
    gArrayListMethods.toArray = GetMethodIDOrDie(env, arrayListClass, "toArray", "()[Ljava/lang/Object;");

    jclass booleanClass = FindClassOrDie(env, "java/lang/Boolean");
    gBooleanClass = MakeGlobalRefOrDie(env, booleanClass);
    gBooleanCstor = GetMethodIDOrDie(env, booleanClass, "<init>", "(Z)V");

    jclass integerClass = FindClassOrDie(env, "java/lang/Integer");
    gIntegerClass = MakeGlobalRefOrDie(env, integerClass);
    gIntegerCstor = GetMethodIDOrDie(env, integerClass, "<init>", "(I)V");

    jclass mapClass = FindClassOrDie(env, "java/util/Map");
    gMapClass = MakeGlobalRefOrDie(env, mapClass);
    gMapPut = GetMethodIDOrDie(env, mapClass, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");

    jclass audioHandleClass = FindClassOrDie(env, "android/media/AudioHandle");
    gAudioHandleClass = MakeGlobalRefOrDie(env, audioHandleClass);
    gAudioHandleCstor = GetMethodIDOrDie(env, audioHandleClass, "<init>", "(I)V");
+54 −0
Original line number Diff line number Diff line
@@ -1074,4 +1074,58 @@ public final class AudioFormat implements Parcelable {
    @Retention(RetentionPolicy.SOURCE)
    public @interface Encoding {}

    /** @hide */
    public static final int[] SURROUND_SOUND_ENCODING = {
            ENCODING_AC3,
            ENCODING_E_AC3,
            ENCODING_DTS,
            ENCODING_DTS_HD,
            ENCODING_AAC_LC,
            ENCODING_DOLBY_TRUEHD,
            ENCODING_E_AC3_JOC,
    };

    /** @hide */
    @IntDef(flag = false, prefix = "ENCODING", value = {
            ENCODING_AC3,
            ENCODING_E_AC3,
            ENCODING_DTS,
            ENCODING_DTS_HD,
            ENCODING_AAC_LC,
            ENCODING_DOLBY_TRUEHD,
            ENCODING_E_AC3_JOC }
    )
    @Retention(RetentionPolicy.SOURCE)
    public @interface SurroundSoundEncoding {}

    /**
     * @hide
     *
     * Return default name for a surround format. This is not an International name.
     * It is just a default to use if an international name is not available.
     *
     * @param audioFormat a surround format
     * @return short default name for the format, eg. “AC3” for ENCODING_AC3.
     */
    public static String toDisplayName(@SurroundSoundEncoding int audioFormat) {
        switch (audioFormat) {
            case ENCODING_AC3:
                return "Dolby Digital (AC3)";
            case ENCODING_E_AC3:
                return "Dolby Digital Plus (E_AC3)";
            case ENCODING_DTS:
                return "DTS";
            case ENCODING_DTS_HD:
                return "DTS HD";
            case ENCODING_AAC_LC:
                return "AAC";
            case ENCODING_DOLBY_TRUEHD:
                return "Dolby TrueHD";
            case ENCODING_E_AC3_JOC:
                return "Dolby Atmos";
            default:
                return "Unknown surround sound format";
        }
    }

}
+61 −0
Original line number Diff line number Diff line
@@ -66,6 +66,7 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;

@@ -5014,6 +5015,66 @@ public class AudioManager {
        }
    }

    /**
     * @hide
     * Returns all surround formats.
     * @return a map where the key is a surround format and
     * the value indicates the surround format is enabled or not
     */
    public Map<Integer, Boolean> getSurroundFormats() {
        Map<Integer, Boolean> surroundFormats = new HashMap<>();
        int status = AudioSystem.getSurroundFormats(surroundFormats, false);
        if (status != AudioManager.SUCCESS) {
            // fail and bail!
            Log.e(TAG, "getSurroundFormats failed:" + status);
            return new HashMap<Integer, Boolean>(); // Always return a map.
        }
        return surroundFormats;
    }

    /**
     * @hide
     * Set a certain surround format as enabled or not.
     * @param audioFormat a surround format, the value is one of
     *        {@link AudioFormat#ENCODING_AC3}, {@link AudioFormat#ENCODING_E_AC3},
     *        {@link AudioFormat#ENCODING_DTS}, {@link AudioFormat#ENCODING_DTS_HD},
     *        {@link AudioFormat#ENCODING_AAC_LC}, {@link AudioFormat#ENCODING_DOLBY_TRUEHD},
     *        {@link AudioFormat#ENCODING_E_AC3_JOC}. Once {@link AudioFormat#ENCODING_AAC_LC} is
     *        set as enabled, {@link AudioFormat#ENCODING_AAC_LC},
     *        {@link AudioFormat#ENCODING_AAC_HE_V1}, {@link AudioFormat#ENCODING_AAC_HE_V2},
     *        {@link AudioFormat#ENCODING_AAC_ELD}, {@link AudioFormat#ENCODING_AAC_XHE} are
     *        all enabled.
     * @param enabled the required surround format state, true for enabled, false for disabled
     * @return true if successful, otherwise false
     */
    public boolean setSurroundFormatEnabled(
            @AudioFormat.SurroundSoundEncoding int audioFormat, boolean enabled) {
        int status = AudioSystem.setSurroundFormatEnabled(audioFormat, enabled);
        return status == AudioManager.SUCCESS;
    }

    /**
     * @hide
     * Returns all surround formats that are reported by the connected HDMI device.
     * The keys are not affected by calling setSurroundFormatEnabled(), and the values
     * are not affected by calling setSurroundFormatEnabled() when in AUTO mode.
     * This information can used to show the AUTO setting for SurroundSound.
     *
     * @return a map where the key is a surround format and
     * the value indicates the surround format is enabled or not
     */
    public Map<Integer, Boolean> getReportedSurroundFormats() {
        Map<Integer, Boolean> reportedSurroundFormats = new HashMap<>();
        int status = AudioSystem.getSurroundFormats(reportedSurroundFormats, true);
        if (status != AudioManager.SUCCESS) {
            // fail and bail!
            Log.e(TAG, "getReportedSurroundFormats failed:" + status);
            return new HashMap<Integer, Boolean>(); // Always return a map.
        }
        return reportedSurroundFormats;
    }


    //---------------------------------------------------------
    // Inner classes
    //--------------------
+9 −1
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import android.media.audiopolicy.AudioMix;
import android.util.Log;

import java.util.ArrayList;
import java.util.Map;

/* IF YOU CHANGE ANY OF THE CONSTANTS IN THIS FILE, DO NOT FORGET
 * TO UPDATE THE CORRESPONDING NATIVE GLUE AND AudioManager.java.
@@ -715,7 +716,8 @@ public class AudioSystem
    public static final int FORCE_HDMI_SYSTEM_AUDIO_ENFORCED = 12;
    public static final int FORCE_ENCODED_SURROUND_NEVER = 13;
    public static final int FORCE_ENCODED_SURROUND_ALWAYS = 14;
    public static final int NUM_FORCE_CONFIG = 15;
    public static final int FORCE_ENCODED_SURROUND_MANUAL = 15;
    public static final int NUM_FORCE_CONFIG = 16;
    public static final int FORCE_DEFAULT = FORCE_NONE;

    public static String forceUseConfigToString(int config) {
@@ -735,6 +737,7 @@ public class AudioSystem
            case FORCE_HDMI_SYSTEM_AUDIO_ENFORCED: return "FORCE_HDMI_SYSTEM_AUDIO_ENFORCED";
            case FORCE_ENCODED_SURROUND_NEVER: return "FORCE_ENCODED_SURROUND_NEVER";
            case FORCE_ENCODED_SURROUND_ALWAYS: return "FORCE_ENCODED_SURROUND_ALWAYS";
            case FORCE_ENCODED_SURROUND_MANUAL: return "FORCE_ENCODED_SURROUND_MANUAL";
            default: return "unknown config (" + config + ")" ;
        }
    }
@@ -836,6 +839,11 @@ public class AudioSystem

    public static native int getMicrophones(ArrayList<MicrophoneInfo> microphonesInfo);

    public static native int getSurroundFormats(Map<Integer, Boolean> surroundFormats,
                                                boolean reported);

    public static native int setSurroundFormatEnabled(int audioFormat, boolean enabled);

    // Items shared with audio service

    /**
Loading