Android点击和触摸音量小的问题(问题追踪)
有客户反馈:A14触摸声音没有
于是乎,追踪setting打开触摸声音的代码:
@Overridepublic boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {if (preference == mVibrateWhenRinging) {Settings.System.putInt(getContentResolver(), Settings.System.VIBRATE_WHEN_RINGING,mVibrateWhenRinging.isChecked() ? 1 : 0);} else if (preference == mDtmfTone) {Settings.System.putInt(getContentResolver(), Settings.System.DTMF_TONE_WHEN_DIALING,mDtmfTone.isChecked() ? 1 : 0);} else if (preference == mSoundEffects) {if (mSoundEffects.isChecked()) {mAudioManager.loadSoundEffects();} else {mAudioManager.unloadSoundEffects();}Settings.System.putInt(getContentResolver(), Settings.System.SOUND_EFFECTS_ENABLED,mSoundEffects.isChecked() ? 1 : 0);}
可以看出来是用:Settings.System.SOUND_EFFECTS_ENABLED这个setting值来控制的。
利用adb看这个值:
确实是开启了的,于是怀疑跑的过程中哪里中断了(可能谷歌加了些判断逻辑),于是继续追:
在View.java里面的触摸声音代码:
/*** Set whether this view should have sound effects enabled for events such as* clicking and touching.** <p>You may wish to disable sound effects for a view if you already play sounds,* for instance, a dial key that plays dtmf tones.** @param soundEffectsEnabled whether sound effects are enabled for this view.* @see #isSoundEffectsEnabled()* @see #playSoundEffect(int)* @attr ref android.R.styleable#View_soundEffectsEnabled*/public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);}/*** @return whether this view should have sound effects enabled for events such as* clicking and touching.** @see #setSoundEffectsEnabled(boolean)* @see #playSoundEffect(int)* @attr ref android.R.styleable#View_soundEffectsEnabled*/@ViewDebug.ExportedPropertypublic boolean isSoundEffectsEnabled() {return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);}
看到这2个方法我就有底了。很明显,我们要查看isSoundEffectsEnabled的调用关系。
/*** Play a sound effect for this view.** <p>The framework will play sound effects for some built in actions, such as* clicking, but you may wish to play these effects in your widget,* for instance, for internal navigation.** <p>The sound effect will only be played if sound effects are enabled by the user, and* {@link #isSoundEffectsEnabled()} is true.** @param soundConstant One of the constants defined in {@link SoundEffectConstants}*/public void playSoundEffect(int soundConstant) {if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {return;}mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);}
接着我们看谁调用了它,找到在AudioServeice.java中
/** @see AudioManager#playSoundEffect(int) */public void playSoundEffect(int effectType) {playSoundEffectVolume(effectType, -1.0f);}/** @see AudioManager#playSoundEffect(int, float) */public void playSoundEffectVolume(int effectType, float volume) {sendMsg(mAudioHandler, MSG_PLAY_SOUND_EFFECT, SENDMSG_QUEUE,effectType, (int) (volume * 1000), null, 0);}
发送MSG_PLAY_SOUND_EFFECT消息,发送的消息在AudioHandler的handleMessage中处理:
public class AudioService extends IAudioService.Stubimplements AccessibilityManager.TouchExplorationStateChangeListener,AccessibilityManager.AccessibilityServicesStateChangeListener,AudioSystemAdapter.OnRoutingUpdatedListener,AudioSystemAdapter.OnVolRangeInitRequestListener {private SoundEffectsHelper mSfxHelper;/** Handles internal volume messages in separate volume thread. */private class AudioHandler extends Handler {@Overridepublic void handleMessage(Message msg) {switch (msg.what) {case MSG_PLAY_SOUND_EFFECT:mSfxHelper.playSoundEffect(msg.arg1, msg.arg2);break;}}
}
调用SoundEffectsHelper的playSoundEffect方法
//frameworks/base/service/java/com/android/server/audio/SoundEffectsHelper.java
class SoundEffectsHelper {/*package*/ void playSoundEffect(int effect, int volume) {sendMsg(MSG_PLAY_EFFECT, effect, volume, null, 0);}
}
发送MSG_PLAY_EFFECT消息:
//frameworks/base/service/java/com/android/server/audio/SoundEffectsHelper.java
class SoundEffectsHelper {private class SfxHandler extends Handler {@Overridepublic void handleMessage(Message msg) {switch (msg.what) {case MSG_PLAY_EFFECT:final int effect = msg.arg1, volume = msg.arg2;onLoadSoundEffects(new OnEffectsLoadCompleteHandler() {@Overridepublic void run(boolean success) {if (success) {onPlaySoundEffect(effect, volume);}}});break;}}}
}
调用onLoadSoundEffects方法:
//frameworks/base/service/java/com/android/server/audio/SoundEffectsHelper.java
class SoundEffectsHelper {private SoundPool mSoundPool;private void onLoadSoundEffects(OnEffectsLoadCompleteHandler onComplete) {if (mSoundPoolLoader != null) {// Loading is ongoing.mSoundPoolLoader.addHandler(onComplete);return;}if (mSoundPool != null) {if (onComplete != null) {onComplete.run(true /*success*/);}return;}logEvent("effects loading started");mSoundPool = new SoundPool.Builder().setMaxStreams(NUM_SOUNDPOOL_CHANNELS).setAudioAttributes(new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION).setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION).build()).build(); //创建SoundPool对象loadSoundAssets(); //加载声音资料mSoundPoolLoader = new SoundPoolLoader(); //创建SoundPoolLoader对象mSoundPoolLoader.addHandler(new OnEffectsLoadCompleteHandler() { //增加OnEffectsLoadComplete Handler@Overridepublic void run(boolean success) {mSoundPoolLoader = null;if (!success) {Log.w(TAG, "onLoadSoundEffects(), Error while loading samples");onUnloadSoundEffects();}}});mSoundPoolLoader.addHandler(onComplete); //增加onComplete Handlerint resourcesToLoad = 0;for (Resource res : mResources) {String filePath = getResourceFilePath(res);int sampleId = mSoundPool.load(filePath, 0);if (sampleId > 0) {res.mSampleId = sampleId;res.mLoaded = false;resourcesToLoad++;} else {logEvent("effect " + filePath + " rejected by SoundPool");Log.w(TAG, "SoundPool could not load file: " + filePath);}}if (resourcesToLoad > 0) {sendMsg(MSG_LOAD_EFFECTS_TIMEOUT, 0, 0, null, SOUND_EFFECTS_LOAD_TIMEOUT_MS);} else {logEvent("effects loading completed, no effects to load");mSoundPoolLoader.onComplete(true /*success*/);}}
}
直到追到这里我才惊觉,好像每个流程都正常!!!
于是我放在耳朵边上听,微弱的触摸音传出的时候,我心态崩了
但是问题还要继续,客户是上帝,所以要解决的是触摸声音小的问题
追踪SoundEffectsHelper.java的代码时发现:
SoundEffectsHelper(Context context, Consumer<PlayerBase> playerAvailableCb) {mContext = context;mSfxAttenuationDb = mContext.getResources().getInteger(com.android.internal.R.integer.config_soundEffectVolumeDb);mPlayerAvailableCb = playerAvailableCb;startWorker();}
触摸声音是由config_soundEffectVolumeDb这个值控制的:范围是-6到0,代码如下:
void onPlaySoundEffect(int effect, int volume) {float volFloat;// use default if volume is not specified by callerif (volume < 0) {volFloat = (float) Math.pow(10, (float) mSfxAttenuationDb / 20);} else {volFloat = volume / 1000.0f;}//android.util.Log.d("hqb","volFloat==="+volFloat);Resource res = mResources.get(mEffects[effect]);if (mSoundPool != null && res.mSampleId != EFFECT_NOT_IN_SOUND_POOL && res.mLoaded) {mSoundPool.play(res.mSampleId, volFloat, volFloat, 0, 0, 1.0f);} else {MediaPlayer mediaPlayer = new MediaPlayer();
可以看出最大值应该是1.0f
但是即使调整到最大,其声音也是很细微
看网友有以下修改来增大音量:
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index f00a910..3ee0c85 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -1757,7 +1757,7 @@public static int[] DEFAULT_STREAM_VOLUME = new int[] {4, // STREAM_VOICE_CALL7, // STREAM_SYSTEM
- 5, // STREAM_RING
+ 7, // STREAM_RING15, // STREAM_MUSIC6, // STREAM_ALARM7, // STREAM_NOTIFICATION
diff --git a/media/jni/soundpool/SoundPool.cpp b/media/jni/soundpool/SoundPool.cpp
index 253b4e3..5733d8e 100644
--- a/media/jni/soundpool/SoundPool.cpp
+++ b/media/jni/soundpool/SoundPool.cpp
@@ -49,7 +49,7 @@*rightVolume != std::clamp(*rightVolume, 0.f, 1.f)) {ALOGI("volume l=%f r=%f out of (0.f, 1.f) bounds, using 1.f", *leftVolume, *rightVolume);// for backward compatibility use 1.f.
- *leftVolume = *rightVolume = 1.f;
+ //*leftVolume = *rightVolume = 1.f;}return false;}
diff --git a/services/core/java/com/android/server/audio/SoundEffectsHelper.java b/services/core/java/com/android/server/audio/SoundEffectsHelper.java
index 762f4d7..afd62c6 100644
--- a/services/core/java/com/android/server/audio/SoundEffectsHelper.java
+++ b/services/core/java/com/android/server/audio/SoundEffectsHelper.java
@@ -248,7 +248,8 @@Resource res = mResources.get(mEffects[effect]);if (mSoundPool != null && res.mSampleId != EFFECT_NOT_IN_SOUND_POOL && res.mLoaded) {
- mSoundPool.play(res.mSampleId, volFloat, volFloat, 0, 0, 1.0f);
+ // mSoundPool.play(res.mSampleId, volFloat, volFloat, 0, 0, 1.0f);
+ mSoundPool.play(res.mSampleId, volFloat*30, volFloat*30, 0, 0, 1.0f);} else {MediaPlayer mediaPlayer = new MediaPlayer();try {
实测可行
但到这里因为设备是不带电话功能的 所以ring的音量条被移除了 然而触摸声音默认就是跟着这个走的,所以我们还需要对其修改:
--- a/alps-mp-u0/frameworks/base/services/core/java/com/android/server/audio/SoundEffectsHelper.java
+++ b/alps-mp-u0/frameworks/base/services/core/java/com/android/server/audio/SoundEffectsHelper.java
@@ -190,8 +190,8 @@ class SoundEffectsHelper {mSoundPool = new SoundPool.Builder().setMaxStreams(NUM_SOUNDPOOL_CHANNELS).setAudioAttributes(new AudioAttributes.Builder()
- .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
- .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
+ .setUsage(AudioAttributes.USAGE_MEDIA)
+ .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC).build()).build();mPlayerAvailableCb.accept(mSoundPool);
@@ -265,7 +265,7 @@ class SoundEffectsHelper {
修改为AudioSystem.STREAM_MUSIC即可
至此 修改完成!