summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/api/current.txt8
-rw-r--r--media/java/android/media/AudioManager.java88
-rwxr-xr-xmedia/java/android/media/IAudioService.aidl8
-rw-r--r--services/core/java/com/android/server/audio/AudioService.java131
4 files changed, 223 insertions, 12 deletions
diff --git a/core/api/current.txt b/core/api/current.txt
index ece1ce64d928..6d5e58c965b9 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -20215,6 +20215,7 @@ package android.media {
method @NonNull public java.util.List<android.media.AudioDeviceInfo> getAvailableCommunicationDevices();
method @Nullable public android.media.AudioDeviceInfo getCommunicationDevice();
method public android.media.AudioDeviceInfo[] getDevices(int);
+ method @RequiresPermission(android.Manifest.permission.WRITE_SETTINGS) public int getEncodedSurroundMode();
method public java.util.List<android.media.MicrophoneInfo> getMicrophones() throws java.io.IOException;
method public int getMode();
method public String getParameters(String);
@@ -20237,6 +20238,7 @@ package android.media {
method public static boolean isOffloadedPlaybackSupported(@NonNull android.media.AudioFormat, @NonNull android.media.AudioAttributes);
method public boolean isSpeakerphoneOn();
method public boolean isStreamMute(int);
+ method @RequiresPermission(android.Manifest.permission.WRITE_SETTINGS) public boolean isSurroundFormatEnabled(int);
method public boolean isVolumeFixed();
method @Deprecated public boolean isWiredHeadsetOn();
method public void loadSoundEffects();
@@ -20256,6 +20258,7 @@ package android.media {
method @Deprecated public void setBluetoothA2dpOn(boolean);
method public void setBluetoothScoOn(boolean);
method public boolean setCommunicationDevice(@NonNull android.media.AudioDeviceInfo);
+ method @RequiresPermission(android.Manifest.permission.WRITE_SETTINGS) public boolean setEncodedSurroundMode(int);
method public void setMicrophoneMute(boolean);
method public void setMode(int);
method public void setParameters(String);
@@ -20265,6 +20268,7 @@ package android.media {
method @Deprecated public void setStreamMute(int, boolean);
method @Deprecated public void setStreamSolo(int, boolean);
method public void setStreamVolume(int, int, int);
+ method @RequiresPermission(android.Manifest.permission.WRITE_SETTINGS) public boolean setSurroundFormatEnabled(int, boolean);
method @Deprecated public void setVibrateSetting(int, int);
method @Deprecated public void setWiredHeadsetOn(boolean);
method @Deprecated public boolean shouldVibrate(int);
@@ -20303,6 +20307,10 @@ package android.media {
field public static final int AUDIOFOCUS_REQUEST_FAILED = 0; // 0x0
field public static final int AUDIOFOCUS_REQUEST_GRANTED = 1; // 0x1
field public static final int AUDIO_SESSION_ID_GENERATE = 0; // 0x0
+ field public static final int ENCODED_SURROUND_OUTPUT_ALWAYS = 2; // 0x2
+ field public static final int ENCODED_SURROUND_OUTPUT_AUTO = 0; // 0x0
+ field public static final int ENCODED_SURROUND_OUTPUT_MANUAL = 3; // 0x3
+ field public static final int ENCODED_SURROUND_OUTPUT_NEVER = 1; // 0x1
field public static final int ERROR = -1; // 0xffffffff
field public static final int ERROR_DEAD_OBJECT = -6; // 0xfffffffa
field public static final String EXTRA_AUDIO_PLUG_STATE = "android.media.extra.AUDIO_PLUG_STATE";
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index ea8356bf9508..8a3deb6aefce 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -568,6 +568,42 @@ public class AudioManager {
public static final int FLAG_FROM_KEY = 1 << 12;
/** @hide */
+ @IntDef(prefix = {"ENCODED_SURROUND_OUTPUT_"}, value = {
+ ENCODED_SURROUND_OUTPUT_AUTO,
+ ENCODED_SURROUND_OUTPUT_NEVER,
+ ENCODED_SURROUND_OUTPUT_ALWAYS,
+ ENCODED_SURROUND_OUTPUT_MANUAL
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface EncodedSurroundOutputMode {}
+
+ /**
+ * The surround sound formats are available for use if they are detected. This is the default
+ * mode.
+ */
+ public static final int ENCODED_SURROUND_OUTPUT_AUTO = 0;
+
+ /**
+ * The surround sound formats are NEVER available, even if they are detected by the hardware.
+ * Those formats will not be reported.
+ */
+ public static final int ENCODED_SURROUND_OUTPUT_NEVER = 1;
+
+ /**
+ * The surround sound formats are ALWAYS available, 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.
+ */
+ 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.
+ */
+ public static final int ENCODED_SURROUND_OUTPUT_MANUAL = 3;
+
+ /** @hide */
@IntDef(flag = true, prefix = "FLAG", value = {
FLAG_SHOW_UI,
FLAG_ALLOW_RINGER_MODES,
@@ -6722,6 +6758,34 @@ public class AudioManager {
}
/**
+ * Sets the surround sound mode.
+ *
+ * @return true if successful, otherwise false
+ */
+ @RequiresPermission(android.Manifest.permission.WRITE_SETTINGS)
+ public boolean setEncodedSurroundMode(@EncodedSurroundOutputMode int mode) {
+ try {
+ return getService().setEncodedSurroundMode(mode);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Gets the surround sound mode.
+ *
+ * @return true if successful, otherwise false
+ */
+ @RequiresPermission(android.Manifest.permission.WRITE_SETTINGS)
+ public @EncodedSurroundOutputMode int getEncodedSurroundMode() {
+ try {
+ return getService().getEncodedSurroundMode();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* @hide
* Returns all surround formats.
* @return a map where the key is a surround format and
@@ -6739,7 +6803,6 @@ public class AudioManager {
}
/**
- * @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},
@@ -6753,10 +6816,29 @@ public class AudioManager {
* @param enabled the required surround format state, true for enabled, false for disabled
* @return true if successful, otherwise false
*/
+ @RequiresPermission(android.Manifest.permission.WRITE_SETTINGS)
public boolean setSurroundFormatEnabled(
@AudioFormat.SurroundSoundEncoding int audioFormat, boolean enabled) {
- int status = AudioSystem.setSurroundFormatEnabled(audioFormat, enabled);
- return status == AudioManager.SUCCESS;
+ try {
+ return getService().setSurroundFormatEnabled(audioFormat, enabled);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Gets whether a certain surround format is enabled or not.
+ * @param audioFormat a surround format
+ *
+ * @return whether the required surround format is enabled
+ */
+ @RequiresPermission(android.Manifest.permission.WRITE_SETTINGS)
+ public boolean isSurroundFormatEnabled(@AudioFormat.SurroundSoundEncoding int audioFormat) {
+ try {
+ return getService().isSurroundFormatEnabled(audioFormat);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
}
/**
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 4f87fe6c5f8c..ee945d5a715f 100755
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -158,6 +158,14 @@ interface IAudioService {
oneway void reloadAudioSettings();
+ boolean setSurroundFormatEnabled(int audioFormat, boolean enabled);
+
+ boolean isSurroundFormatEnabled(int audioFormat);
+
+ boolean setEncodedSurroundMode(int mode);
+
+ int getEncodedSurroundMode();
+
oneway void avrcpSupportsAbsoluteVolume(String address, boolean support);
void setSpeakerphoneOn(IBinder cb, boolean on);
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 68f10a5106ef..81b5dc79f28e 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -1815,6 +1815,127 @@ public class AudioService extends IAudioService.Stub
}
}
+ /** @see AudioManager#isSurroundFormatEnabled(int) */
+ @Override
+ public boolean isSurroundFormatEnabled(int audioFormat) {
+ if (!isSurroundFormat(audioFormat)) {
+ Log.w(TAG, "audioFormat to enable is not a surround format.");
+ return false;
+ }
+ if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.WRITE_SETTINGS)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Missing WRITE_SETTINGS permission");
+ }
+
+ final long token = Binder.clearCallingIdentity();
+ try {
+ synchronized (mSettingsLock) {
+ HashSet<Integer> enabledFormats = getEnabledFormats();
+ return enabledFormats.contains(audioFormat);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ /** @see AudioManager#setSurroundFormatEnabled(int, boolean) */
+ @Override
+ public boolean setSurroundFormatEnabled(int audioFormat, boolean enabled) {
+ if (!isSurroundFormat(audioFormat)) {
+ Log.w(TAG, "audioFormat to enable is not a surround format.");
+ return false;
+ }
+ if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.WRITE_SETTINGS)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Missing WRITE_SETTINGS permission");
+ }
+
+ HashSet<Integer> enabledFormats = getEnabledFormats();
+ if (enabled) {
+ enabledFormats.add(audioFormat);
+ } else {
+ enabledFormats.remove(audioFormat);
+ }
+ final long token = Binder.clearCallingIdentity();
+ try {
+ synchronized (mSettingsLock) {
+ Settings.Global.putString(mContentResolver,
+ Settings.Global.ENCODED_SURROUND_OUTPUT_ENABLED_FORMATS,
+ TextUtils.join(",", enabledFormats));
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ return true;
+ }
+
+ /** @see AudioManager#setEncodedSurroundMode(int) */
+ @Override
+ public boolean setEncodedSurroundMode(int mode) {
+ if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.WRITE_SETTINGS)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Missing WRITE_SETTINGS permission");
+ }
+
+ final long token = Binder.clearCallingIdentity();
+ try {
+ synchronized (mSettingsLock) {
+ Settings.Global.putInt(mContentResolver,
+ Settings.Global.ENCODED_SURROUND_OUTPUT,
+ mode);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ return true;
+ }
+
+ /** @see AudioManager#getEncodedSurroundMode() */
+ @Override
+ public int getEncodedSurroundMode() {
+ if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.WRITE_SETTINGS)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Missing WRITE_SETTINGS permission");
+ }
+
+ final long token = Binder.clearCallingIdentity();
+ try {
+ synchronized (mSettingsLock) {
+ return Settings.Global.getInt(mContentResolver,
+ Settings.Global.ENCODED_SURROUND_OUTPUT,
+ AudioManager.ENCODED_SURROUND_OUTPUT_AUTO);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ /** @return the formats that are enabled in global settings */
+ private HashSet<Integer> getEnabledFormats() {
+ HashSet<Integer> formats = new HashSet<>();
+ String enabledFormats = Settings.Global.getString(mContentResolver,
+ Settings.Global.ENCODED_SURROUND_OUTPUT_ENABLED_FORMATS);
+ if (enabledFormats != null) {
+ try {
+ Arrays.stream(TextUtils.split(enabledFormats, ","))
+ .mapToInt(Integer::parseInt)
+ .forEach(formats::add);
+ } catch (NumberFormatException e) {
+ Log.w(TAG, "ENCODED_SURROUND_OUTPUT_ENABLED_FORMATS misformatted.", e);
+ }
+ }
+ return formats;
+ }
+
+ private boolean isSurroundFormat(int audioFormat) {
+ for (int sf : AudioFormat.SURROUND_SOUND_ENCODING) {
+ if (sf == audioFormat) {
+ return true;
+ }
+ }
+ return false;
+ }
+
private void sendEnabledSurroundFormats(ContentResolver cr, boolean forceUpdate) {
if (mEncodedSurroundMode != Settings.Global.ENCODED_SURROUND_OUTPUT_MANUAL) {
// Manually enable surround formats only when the setting is in manual mode.
@@ -1839,14 +1960,7 @@ public class AudioService extends IAudioService.Stub
for (String format : surroundFormats) {
try {
int audioFormat = Integer.valueOf(format);
- boolean isSurroundFormat = false;
- for (int sf : AudioFormat.SURROUND_SOUND_ENCODING) {
- if (sf == audioFormat) {
- isSurroundFormat = true;
- break;
- }
- }
- if (isSurroundFormat && !formats.contains(audioFormat)) {
+ if (isSurroundFormat(audioFormat) && !formats.contains(audioFormat)) {
formats.add(audioFormat);
}
} catch (Exception e) {
@@ -7309,7 +7423,6 @@ public class AudioService extends IAudioService.Stub
Settings.Global.ENCODED_SURROUND_OUTPUT_AUTO);
mContentResolver.registerContentObserver(Settings.Global.getUriFor(
Settings.Global.ENCODED_SURROUND_OUTPUT), false, this);
-
mEnabledSurroundFormats = Settings.Global.getString(
mContentResolver, Settings.Global.ENCODED_SURROUND_OUTPUT_ENABLED_FORMATS);
mContentResolver.registerContentObserver(Settings.Global.getUriFor(