summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/api/current.txt1
-rw-r--r--core/res/res/values/config.xml5
-rw-r--r--core/res/res/values/symbols.xml2
-rw-r--r--core/res/res/xml/audio_assets.xml25
-rw-r--r--media/java/android/media/AudioManager.java136
-rwxr-xr-xmedia/java/android/media/IAudioService.aidl8
-rw-r--r--services/core/java/com/android/server/audio/AudioService.java25
-rw-r--r--services/core/java/com/android/server/audio/SoundEffectsHelper.java75
8 files changed, 236 insertions, 41 deletions
diff --git a/core/api/current.txt b/core/api/current.txt
index 2ce0b35a218a..cd23fda5e14a 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -19860,6 +19860,7 @@ package android.media {
field public static final int FLAG_REMOVE_SOUND_AND_VIBRATE = 8; // 0x8
field public static final int FLAG_SHOW_UI = 1; // 0x1
field public static final int FLAG_VIBRATE = 16; // 0x10
+ field public static final int FX_BACK = 10; // 0xa
field public static final int FX_FOCUS_NAVIGATION_DOWN = 2; // 0x2
field public static final int FX_FOCUS_NAVIGATION_LEFT = 3; // 0x3
field public static final int FX_FOCUS_NAVIGATION_RIGHT = 4; // 0x4
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index da658cc3d525..9c28fd37e34e 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -4588,4 +4588,9 @@
<!-- If true, attach the navigation bar to the app during app transition -->
<bool name="config_attachNavBarToAppDuringTransition">false</bool>
+
+ <!-- Flag indicating that the media framework should play a back sound when a back-transition
+ happens that doesn't result in bringing the home task to the front.
+ This is currently only used on TV. -->
+ <bool name="config_enableBackSound">false</bool>
</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 2df9684e0e6f..cf41cfe35353 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -4135,4 +4135,6 @@
<java-symbol type="dimen" name="accessibility_focus_highlight_stroke_width" />
<java-symbol type="bool" name="config_attachNavBarToAppDuringTransition" />
+
+ <java-symbol type="bool" name="config_enableBackSound" />
</resources>
diff --git a/core/res/res/xml/audio_assets.xml b/core/res/res/xml/audio_assets.xml
index af5798a33b32..57789e14619a 100644
--- a/core/res/res/xml/audio_assets.xml
+++ b/core/res/res/xml/audio_assets.xml
@@ -19,21 +19,18 @@
<!-- Mapping of UI sound effects to audio assets under /system/media/audio/ui.
Modify this file to override default sound assets.
- Currently only touch sounds can be overridden. Other groups can be added
- in the future for other UI sounds like camera, lock, dock...
-->
<audio_assets version="1.0">
- <group name="touch_sounds">
- <asset id="FX_KEY_CLICK" file="Effect_Tick.ogg"/>
- <asset id="FX_FOCUS_NAVIGATION_UP" file="Effect_Tick.ogg"/>
- <asset id="FX_FOCUS_NAVIGATION_DOWN" file="Effect_Tick.ogg"/>
- <asset id="FX_FOCUS_NAVIGATION_LEFT" file="Effect_Tick.ogg"/>
- <asset id="FX_FOCUS_NAVIGATION_RIGHT" file="Effect_Tick.ogg"/>
- <asset id="FX_KEYPRESS_STANDARD" file="KeypressStandard.ogg"/>
- <asset id="FX_KEYPRESS_SPACEBAR" file="KeypressSpacebar.ogg"/>
- <asset id="FX_KEYPRESS_DELETE" file="KeypressDelete.ogg"/>
- <asset id="FX_KEYPRESS_RETURN" file="KeypressReturn.ogg"/>
- <asset id="FX_KEYPRESS_INVALID" file="KeypressInvalid.ogg"/>
- </group>
+ <asset id="FX_KEY_CLICK" file="Effect_Tick.ogg"/>
+ <asset id="FX_FOCUS_NAVIGATION_UP" file="Effect_Tick.ogg"/>
+ <asset id="FX_FOCUS_NAVIGATION_DOWN" file="Effect_Tick.ogg"/>
+ <asset id="FX_FOCUS_NAVIGATION_LEFT" file="Effect_Tick.ogg"/>
+ <asset id="FX_FOCUS_NAVIGATION_RIGHT" file="Effect_Tick.ogg"/>
+ <asset id="FX_KEYPRESS_STANDARD" file="KeypressStandard.ogg"/>
+ <asset id="FX_KEYPRESS_SPACEBAR" file="KeypressSpacebar.ogg"/>
+ <asset id="FX_KEYPRESS_DELETE" file="KeypressDelete.ogg"/>
+ <asset id="FX_KEYPRESS_RETURN" file="KeypressReturn.ogg"/>
+ <asset id="FX_KEYPRESS_INVALID" file="KeypressInvalid.ogg"/>
+ <asset id="FX_BACK" file="Effect_Tick.ogg"/>
</audio_assets>
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 367b78470cd5..000c34ded3a4 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -3096,11 +3096,140 @@ public class AudioManager {
* @see #playSoundEffect(int)
*/
public static final int FX_KEYPRESS_INVALID = 9;
+
+ /**
+ * Back sound
+ * @see #playSoundEffect(int)
+ */
+ public static final int FX_BACK = 10;
+
+ /**
+ * @hide Home sound
+ * Played by the framework when the home app becomes active if config_enableHomeSound is set to
+ * true. This is currently only used on TV devices.
+ * Note that this sound is only available if a sound file is specified in audio_assets.xml.
+ * @see #playSoundEffect(int)
+ */
+ public static final int FX_HOME = 11;
+
+ /**
+ * @hide Fast scroll sound 1
+ * To be by the framework when a fast-scrolling is performed and
+ * {@link #areFastScrollSoundEffectsEnabled()} is true.
+ * This is currently only used on TV devices.
+ * Note that this sound is only available if a sound file is specified in audio_assets.xml
+ * @see #playSoundEffect(int)
+ */
+ public static final int FX_FAST_SCROLL_1 = 12;
+
+ /**
+ * @hide Fast scroll sound 2
+ * To be by the framework when a fast-scrolling is performed and
+ * {@link #areFastScrollSoundEffectsEnabled()} is true.
+ * This is currently only used on TV devices.
+ * Note that this sound is only available if a sound file is specified in audio_assets.xml
+ * @see #playSoundEffect(int)
+ */
+ public static final int FX_FAST_SCROLL_2 = 13;
+
+ /**
+ * @hide Fast scroll sound 3
+ * To be by the framework when a fast-scrolling is performed and
+ * {@link #areFastScrollSoundEffectsEnabled()} is true.
+ * This is currently only used on TV devices.
+ * Note that this sound is only available if a sound file is specified in audio_assets.xml
+ * @see #playSoundEffect(int)
+ */
+ public static final int FX_FAST_SCROLL_3 = 14;
+
+ /**
+ * @hide Fast scroll sound 4
+ * To be by the framework when a fast-scrolling is performed and
+ * {@link #areFastScrollSoundEffectsEnabled()} is true.
+ * This is currently only used on TV devices.
+ * Note that this sound is only available if a sound file is specified in audio_assets.xml
+ * @see #playSoundEffect(int)
+ */
+ public static final int FX_FAST_SCROLL_4 = 15;
+
/**
* @hide Number of sound effects
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public static final int NUM_SOUND_EFFECTS = 10;
+ public static final int NUM_SOUND_EFFECTS = 16;
+
+ /**
+ * @hide Number of fast scroll sound effects
+ */
+ public static final int NUM_FAST_SCROLL_SOUND_EFFECTS = 4;
+
+ /**
+ * @hide
+ * @param n a value in [0, {@link #NUM_FAST_SCROLL_SOUND_EFFECTS}[
+ * @return The id of a fast scroll sound effect or -1 if out of bounds
+ */
+ public static int getNthFastScrollSoundEffectId(int n) {
+ switch (n) {
+ case 0:
+ return FX_FAST_SCROLL_1;
+ case 1:
+ return FX_FAST_SCROLL_2;
+ case 2:
+ return FX_FAST_SCROLL_3;
+ case 3:
+ return FX_FAST_SCROLL_4;
+ default:
+ Log.w(TAG, "Invalid fast-scroll sound effect id: " + n);
+ return -1;
+ }
+ }
+
+ /**
+ * @hide
+ */
+ public void setFastScrollSoundEffectsEnabled(boolean enabled) {
+ try {
+ getService().setFastScrollSoundEffectsEnabled(enabled);
+ } catch (RemoteException e) {
+
+ }
+ }
+
+ /**
+ * @hide
+ * @return true if the fast scroll sound effects are enabled
+ */
+ public boolean areFastScrollSoundEffectsEnabled() {
+ try {
+ return getService().areFastScrollSoundEffectsEnabled();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * @hide
+ * @param enabled
+ */
+ public void setHomeSoundEffectEnabled(boolean enabled) {
+ try {
+ getService().setHomeSoundEffectEnabled(enabled);
+ } catch (RemoteException e) {
+
+ }
+ }
+
+ /**
+ * @hide
+ * @return true if the home sound effect is enabled
+ */
+ public boolean isHomeSoundEffectEnabled() {
+ try {
+ return getService().isHomeSoundEffectEnabled();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
/**
* Plays a sound effect (Key clicks, lid open/close...)
@@ -3115,10 +3244,11 @@ public class AudioManager {
* {@link #FX_KEYPRESS_DELETE},
* {@link #FX_KEYPRESS_RETURN},
* {@link #FX_KEYPRESS_INVALID},
+ * {@link #FX_BACK},
* NOTE: This version uses the UI settings to determine
* whether sounds are heard or not.
*/
- public void playSoundEffect(int effectType) {
+ public void playSoundEffect(int effectType) {
if (effectType < 0 || effectType >= NUM_SOUND_EFFECTS) {
return;
}
@@ -3148,6 +3278,7 @@ public class AudioManager {
* {@link #FX_KEYPRESS_DELETE},
* {@link #FX_KEYPRESS_RETURN},
* {@link #FX_KEYPRESS_INVALID},
+ * {@link #FX_BACK},
* @param userId The current user to pull sound settings from
* NOTE: This version uses the UI settings to determine
* whether sounds are heard or not.
@@ -3183,6 +3314,7 @@ public class AudioManager {
* {@link #FX_KEYPRESS_DELETE},
* {@link #FX_KEYPRESS_RETURN},
* {@link #FX_KEYPRESS_INVALID},
+ * {@link #FX_BACK},
* @param volume Sound effect volume.
* The volume value is a raw scalar so UI controls should be scaled logarithmically.
* If a volume of -1 is specified, the AudioManager.STREAM_MUSIC stream volume minus 3dB will be used.
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index b6bb3a3df38b..e32185a08501 100755
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -348,4 +348,12 @@ interface IAudioService {
oneway void unregisterCommunicationDeviceDispatcher(
ICommunicationDeviceDispatcher dispatcher);
+
+ boolean areFastScrollSoundEffectsEnabled();
+
+ oneway void setFastScrollSoundEffectsEnabled(boolean enabled);
+
+ boolean isHomeSoundEffectEnabled();
+
+ oneway void setHomeSoundEffectEnabled(boolean enabled);
}
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 391a64ccf0e3..08eeda20b4ba 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -600,6 +600,9 @@ public class AudioService extends IAudioService.Stub
// caches the value returned by AudioSystem.isMicrophoneMuted()
private boolean mMicMuteFromSystemCached;
+ private boolean mFastScrollSoundEffectsEnabled;
+ private boolean mHomeSoundEffectEnabled;
+
@GuardedBy("mSettingsLock")
private int mAssistantUid;
@@ -2195,6 +2198,28 @@ public class AudioService extends IAudioService.Stub
caller, Binder.getCallingUid(), hasModifyAudioSettings, VOL_ADJUST_NORMAL);
}
+ public void setFastScrollSoundEffectsEnabled(boolean enabled) {
+ mFastScrollSoundEffectsEnabled = enabled;
+ }
+
+ /**
+ * @return true if the fast scroll sound effects are enabled
+ */
+ public boolean areFastScrollSoundEffectsEnabled() {
+ return mFastScrollSoundEffectsEnabled;
+ }
+
+ public void setHomeSoundEffectEnabled(boolean enabled) {
+ mHomeSoundEffectEnabled = enabled;
+ }
+
+ /**
+ * @return true if the home sound effect is enabled
+ */
+ public boolean isHomeSoundEffectEnabled() {
+ return mHomeSoundEffectEnabled;
+ }
+
private void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags,
String callingPackage, String caller, int uid, boolean hasModifyAudioSettings,
int keyEventMode) {
diff --git a/services/core/java/com/android/server/audio/SoundEffectsHelper.java b/services/core/java/com/android/server/audio/SoundEffectsHelper.java
index 27d57674e0f1..c14bb3ee5df1 100644
--- a/services/core/java/com/android/server/audio/SoundEffectsHelper.java
+++ b/services/core/java/com/android/server/audio/SoundEffectsHelper.java
@@ -42,7 +42,10 @@ import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
/**
* A helper class for managing sound effects loading / unloading
@@ -180,7 +183,7 @@ class SoundEffectsHelper {
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.build())
.build();
- loadTouchSoundAssets();
+ loadSoundAssets();
mSoundPoolLoader = new SoundPoolLoader();
mSoundPoolLoader.addHandler(new OnEffectsLoadCompleteHandler() {
@@ -316,15 +319,22 @@ class SoundEffectsHelper {
return filePath;
}
- private void loadTouchSoundAssetDefaults() {
+ private void loadSoundAssetDefaults() {
int defaultResourceIdx = mResources.size();
mResources.add(new Resource("Effect_Tick.ogg"));
- for (int i = 0; i < mEffects.length; i++) {
- mEffects[i] = defaultResourceIdx;
- }
+ Arrays.fill(mEffects, defaultResourceIdx);
}
- private void loadTouchSoundAssets() {
+ /**
+ * Loads the sound assets information from audio_assets.xml
+ * The expected format of audio_assets.xml is:
+ * <ul>
+ * <li> all {@code <asset>s} listed directly in {@code <audio_assets>} </li>
+ * <li> for backwards compatibility: exactly one {@code <group>} with name
+ * {@link #GROUP_TOUCH_SOUNDS} </li>
+ * </ul>
+ */
+ private void loadSoundAssets() {
XmlResourceParser parser = null;
// only load assets once.
@@ -332,15 +342,14 @@ class SoundEffectsHelper {
return;
}
- loadTouchSoundAssetDefaults();
+ loadSoundAssetDefaults();
try {
parser = mContext.getResources().getXml(com.android.internal.R.xml.audio_assets);
XmlUtils.beginDocument(parser, TAG_AUDIO_ASSETS);
String version = parser.getAttributeValue(null, ATTR_VERSION);
- boolean inTouchSoundsGroup = false;
-
+ Map<Integer, Integer> parserCounter = new HashMap<>();
if (ASSET_FILE_VERSION.equals(version)) {
while (true) {
XmlUtils.nextElement(parser);
@@ -350,19 +359,10 @@ class SoundEffectsHelper {
}
if (element.equals(TAG_GROUP)) {
String name = parser.getAttributeValue(null, ATTR_GROUP_NAME);
- if (GROUP_TOUCH_SOUNDS.equals(name)) {
- inTouchSoundsGroup = true;
- break;
+ if (!GROUP_TOUCH_SOUNDS.equals(name)) {
+ Log.w(TAG, "Unsupported group name: " + name);
}
- }
- }
- while (inTouchSoundsGroup) {
- XmlUtils.nextElement(parser);
- String element = parser.getName();
- if (element == null) {
- break;
- }
- if (element.equals(TAG_ASSET)) {
+ } else if (element.equals(TAG_ASSET)) {
String id = parser.getAttributeValue(null, ATTR_ASSET_ID);
String file = parser.getAttributeValue(null, ATTR_ASSET_FILE);
int fx;
@@ -371,22 +371,38 @@ class SoundEffectsHelper {
Field field = AudioManager.class.getField(id);
fx = field.getInt(null);
} catch (Exception e) {
- Log.w(TAG, "Invalid touch sound ID: " + id);
+ Log.w(TAG, "Invalid sound ID: " + id);
continue;
}
-
+ int currentParserCount = parserCounter.getOrDefault(fx, 0) + 1;
+ parserCounter.put(fx, currentParserCount);
+ if (currentParserCount > 1) {
+ Log.w(TAG, "Duplicate definition for sound ID: " + id);
+ }
mEffects[fx] = findOrAddResourceByFileName(file);
} else {
break;
}
}
+
+ boolean fastScrollSoundEffectsParsed = allFastScrollSoundsParsed(parserCounter);
+ boolean homeSoundParsed = parserCounter.getOrDefault(AudioManager.FX_HOME, 0) > 0;
+ if (fastScrollSoundEffectsParsed || homeSoundParsed) {
+ AudioManager audioManager = mContext.getSystemService(AudioManager.class);
+ if (audioManager != null && fastScrollSoundEffectsParsed) {
+ audioManager.setFastScrollSoundEffectsEnabled(true);
+ }
+ if (audioManager != null && homeSoundParsed) {
+ audioManager.setHomeSoundEffectEnabled(true);
+ }
+ }
}
} catch (Resources.NotFoundException e) {
Log.w(TAG, "audio assets file not found", e);
} catch (XmlPullParserException e) {
- Log.w(TAG, "XML parser exception reading touch sound assets", e);
+ Log.w(TAG, "XML parser exception reading sound assets", e);
} catch (IOException e) {
- Log.w(TAG, "I/O exception reading touch sound assets", e);
+ Log.w(TAG, "I/O exception reading sound assets", e);
} finally {
if (parser != null) {
parser.close();
@@ -394,6 +410,15 @@ class SoundEffectsHelper {
}
}
+ private boolean allFastScrollSoundsParsed(Map<Integer, Integer> parserCounter) {
+ int numFastScrollSoundEffectsParsed =
+ parserCounter.getOrDefault(AudioManager.FX_FAST_SCROLL_1, 0)
+ + parserCounter.getOrDefault(AudioManager.FX_FAST_SCROLL_2, 0)
+ + parserCounter.getOrDefault(AudioManager.FX_FAST_SCROLL_3, 0)
+ + parserCounter.getOrDefault(AudioManager.FX_FAST_SCROLL_4, 0);
+ return numFastScrollSoundEffectsParsed == AudioManager.NUM_FAST_SCROLL_SOUND_EFFECTS;
+ }
+
private int findOrAddResourceByFileName(String fileName) {
for (int i = 0; i < mResources.size(); i++) {
if (mResources.get(i).mFileName.equals(fileName)) {