am fc7c9b48: Merge "audio service: allow touch sounds customization" into jb-mr2-dev

* commit 'fc7c9b484a25e60a569253d9e0c24d1f4205f490':
  audio service: allow touch sounds customization
This commit is contained in:
Eric Laurent
2013-03-21 00:09:05 +00:00
committed by Android Git Automerger
3 changed files with 149 additions and 24 deletions

View File

@ -1136,6 +1136,7 @@
<java-symbol type="xml" name="power_profile" />
<java-symbol type="xml" name="time_zones_by_country" />
<java-symbol type="xml" name="sms_short_codes" />
<java-symbol type="xml" name="audio_assets" />
<java-symbol type="raw" name="accessibility_gestures" />
<java-symbol type="raw" name="incognito_mode_start_page" />

View File

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
** Copyright 2012, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
-->
<!-- 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"/>
</group>
</audio_assets>

View File

@ -42,6 +42,8 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.database.ContentObserver;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnErrorListener;
@ -70,10 +72,14 @@ import android.view.KeyEvent;
import android.view.VolumePanel;
import com.android.internal.telephony.ITelephony;
import com.android.internal.util.XmlUtils;
import org.xmlpull.v1.XmlPullParserException;
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.concurrent.ConcurrentHashMap;
import java.util.HashMap;
@ -197,28 +203,12 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
/* Sound effect file names */
private static final String SOUND_EFFECTS_PATH = "/media/audio/ui/";
private static final String[] SOUND_EFFECT_FILES = new String[] {
"Effect_Tick.ogg",
"KeypressStandard.ogg",
"KeypressSpacebar.ogg",
"KeypressDelete.ogg",
"KeypressReturn.ogg"
};
private static final List<String> SOUND_EFFECT_FILES = new ArrayList<String>();
/* Sound effect file name mapping sound effect id (AudioManager.FX_xxx) to
* file index in SOUND_EFFECT_FILES[] (first column) and indicating if effect
* uses soundpool (second column) */
private final int[][] SOUND_EFFECT_FILES_MAP = new int[][] {
{0, -1}, // FX_KEY_CLICK
{0, -1}, // FX_FOCUS_NAVIGATION_UP
{0, -1}, // FX_FOCUS_NAVIGATION_DOWN
{0, -1}, // FX_FOCUS_NAVIGATION_LEFT
{0, -1}, // FX_FOCUS_NAVIGATION_RIGHT
{1, -1}, // FX_KEYPRESS_STANDARD
{2, -1}, // FX_KEYPRESS_SPACEBAR
{3, -1}, // FX_FOCUS_DELETE
{4, -1} // FX_FOCUS_RETURN
};
private final int[][] SOUND_EFFECT_FILES_MAP = new int[AudioManager.NUM_SOUND_EFFECTS][2];
/** @hide Maximum volume index values for audio streams */
private final int[] MAX_STREAM_VOLUME = new int[] {
@ -1634,6 +1624,99 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
return mMode;
}
//==========================================================================================
// Sound Effects
//==========================================================================================
private static final String TAG_AUDIO_ASSETS = "audio_assets";
private static final String ATTR_VERSION = "version";
private static final String TAG_GROUP = "group";
private static final String ATTR_GROUP_NAME = "name";
private static final String TAG_ASSET = "asset";
private static final String ATTR_ASSET_ID = "id";
private static final String ATTR_ASSET_FILE = "file";
private static final String ASSET_FILE_VERSION = "1.0";
private static final String GROUP_TOUCH_SOUNDS = "touch_sounds";
private void loadTouchSoundAssetDefaults() {
SOUND_EFFECT_FILES.add("Effect_Tick.ogg");
for (int i = 0; i < AudioManager.NUM_SOUND_EFFECTS; i++) {
SOUND_EFFECT_FILES_MAP[i][0] = 0;
SOUND_EFFECT_FILES_MAP[i][1] = -1;
}
}
private void loadTouchSoundAssets() {
XmlResourceParser parser = null;
loadTouchSoundAssetDefaults();
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;
if (ASSET_FILE_VERSION.equals(version)) {
while (true) {
XmlUtils.nextElement(parser);
String element = parser.getName();
if (element == null) {
break;
}
if (element.equals(TAG_GROUP)) {
String name = parser.getAttributeValue(null, ATTR_GROUP_NAME);
if (GROUP_TOUCH_SOUNDS.equals(name)) {
inTouchSoundsGroup = true;
break;
}
}
}
while (inTouchSoundsGroup) {
XmlUtils.nextElement(parser);
String element = parser.getName();
if (element == null) {
break;
}
if (element.equals(TAG_ASSET)) {
String id = parser.getAttributeValue(null, ATTR_ASSET_ID);
String file = parser.getAttributeValue(null, ATTR_ASSET_FILE);
int fx;
try {
Field field = AudioManager.class.getField(id);
fx = field.getInt(null);
} catch (Exception e) {
Log.w(TAG, "Invalid touch sound ID: "+id);
continue;
}
int i = SOUND_EFFECT_FILES.indexOf(file);
if (i == -1) {
i = SOUND_EFFECT_FILES.size();
SOUND_EFFECT_FILES.add(file);
}
SOUND_EFFECT_FILES_MAP[fx][0] = i;
} else {
break;
}
}
}
} 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);
} catch (IOException e) {
Log.w(TAG, "I/O exception reading touch sound assets", e);
} finally {
if (parser != null) {
parser.close();
}
}
}
/** @see AudioManager#playSoundEffect(int) */
public void playSoundEffect(int effectType) {
sendMsg(mAudioHandler, MSG_PLAY_SOUND_EFFECT, SENDMSG_NOOP,
@ -1654,6 +1737,8 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
public boolean loadSoundEffects() {
int status;
loadTouchSoundAssets();
synchronized (mSoundEffectsLock) {
if (!mBootCompleted) {
Log.w(TAG, "loadSoundEffects() called before boot complete");
@ -1692,8 +1777,8 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
* Once loaded, the value in poolId is the sample ID and the same
* sample can be reused for another effect using the same file.
*/
int[] poolId = new int[SOUND_EFFECT_FILES.length];
for (int fileIdx = 0; fileIdx < SOUND_EFFECT_FILES.length; fileIdx++) {
int[] poolId = new int[SOUND_EFFECT_FILES.size()];
for (int fileIdx = 0; fileIdx < SOUND_EFFECT_FILES.size(); fileIdx++) {
poolId[fileIdx] = -1;
}
/*
@ -1711,7 +1796,7 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
if (poolId[SOUND_EFFECT_FILES_MAP[effect][0]] == -1) {
String filePath = Environment.getRootDirectory()
+ SOUND_EFFECTS_PATH
+ SOUND_EFFECT_FILES[SOUND_EFFECT_FILES_MAP[effect][0]];
+ SOUND_EFFECT_FILES.get(SOUND_EFFECT_FILES_MAP[effect][0]);
int sampleId = mSoundPool.load(filePath, 0);
if (sampleId <= 0) {
Log.w(TAG, "Soundpool could not load file: "+filePath);
@ -1776,8 +1861,8 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
mAudioHandler.removeMessages(MSG_LOAD_SOUND_EFFECTS);
mAudioHandler.removeMessages(MSG_PLAY_SOUND_EFFECT);
int[] poolId = new int[SOUND_EFFECT_FILES.length];
for (int fileIdx = 0; fileIdx < SOUND_EFFECT_FILES.length; fileIdx++) {
int[] poolId = new int[SOUND_EFFECT_FILES.size()];
for (int fileIdx = 0; fileIdx < SOUND_EFFECT_FILES.size(); fileIdx++) {
poolId[fileIdx] = 0;
}
@ -3279,7 +3364,8 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
} else {
MediaPlayer mediaPlayer = new MediaPlayer();
try {
String filePath = Environment.getRootDirectory() + SOUND_EFFECTS_PATH + SOUND_EFFECT_FILES[SOUND_EFFECT_FILES_MAP[effectType][0]];
String filePath = Environment.getRootDirectory() + SOUND_EFFECTS_PATH +
SOUND_EFFECT_FILES.get(SOUND_EFFECT_FILES_MAP[effectType][0]);
mediaPlayer.setDataSource(filePath);
mediaPlayer.setAudioStreamType(AudioSystem.STREAM_SYSTEM);
mediaPlayer.prepare();