diff options
| -rw-r--r-- | core/api/current.txt | 1 | ||||
| -rw-r--r-- | core/res/res/values/config.xml | 5 | ||||
| -rw-r--r-- | core/res/res/values/symbols.xml | 2 | ||||
| -rw-r--r-- | core/res/res/xml/audio_assets.xml | 25 | ||||
| -rw-r--r-- | media/java/android/media/AudioManager.java | 136 | ||||
| -rwxr-xr-x | media/java/android/media/IAudioService.aidl | 8 | ||||
| -rw-r--r-- | services/core/java/com/android/server/audio/AudioService.java | 25 | ||||
| -rw-r--r-- | services/core/java/com/android/server/audio/SoundEffectsHelper.java | 75 |
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)) { |