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

Commit 2709d470 authored by Jiabin Huang's avatar Jiabin Huang Committed by android-build-merger
Browse files

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

am: bccbeb1b

Change-Id: I5bdce8b1103c970fd515028e48336fc26b9f2fbd
parents 12e9c004 bccbeb1b
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;
@@ -11313,16 +11314,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
@@ -11969,6 +12021,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,
@@ -12005,6 +12058,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 {
@@ -1832,6 +1841,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[] = {
@@ -1887,6 +1962,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},
};


@@ -1906,6 +1983,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;

@@ -5015,6 +5016,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