修改系统默认音量值
路径:framework/base/media/java/android/media/AudioSystem.java
public static int[] DEFAULT_STREAM_VOLUME = new int[] { 4, // STREAM_VOICE_CALL 7, // STREAM_SYSTEM 5, // STREAM_RING // MStar Android Patch Begin // this setting is subject to MAX_STREAM_VOLUME[STREAM_MUSIC] = 100 (in AudioService.java) 35, // STREAM_MUSIC // MStar Android Patch End 6, // STREAM_ALARM 5, // STREAM_NOTIFICATION 7, // STREAM_BLUETOOTH_SCO 7, // STREAM_SYSTEM_ENFORCED 11, // STREAM_DTMF 11, // STREAM_TTS 15 //STREAM_MUSIC_SUB };
由上可以看出,系统的各个通道的默认音量值会在这里定义,但是需要修改默认的音量值,仅仅在这里修改无法改变的,因为系统在其他地方默认的音量值进行了补充修改。具体可以看下面的代码:
路径:framework/base/services/core/java/com/android/server/audio/AudioService
/** @hide */ public AudioService(Context context) { //省略部分代码 int maxVolume = SystemProperties.getInt("ro.config.vc_call_vol_steps", MAX_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL]); if (maxVolume != MAX_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL]) { MAX_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL] = maxVolume; AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL] = (maxVolume * 3) / 4; } maxVolume = SystemProperties.getInt("ro.config.media_vol_steps", MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC]); if (maxVolume != MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC]) { MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] = maxVolume; AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] = (maxVolume * 3) / 4; } }
上面可以看出,在获取到系统的最大音量值的地方,系统队默认的音量值进行了重新定义。因此,如果需要对音量进行自定义修改,需要在这里进行适当的控制。
修改系统音量极值
- 路径:framework/base/services/core/java/com/android/server/audio/AudioService
最大值定义代码
/** Maximum volume index values for audio streams */ private static int[] MAX_STREAM_VOLUME = new int[] { // MStar Android Patch Begin 100, // STREAM_VOICE_CALL 100, // STREAM_SYSTEM 100, // STREAM_RING 100, // STREAM_MUSIC 100, // STREAM_ALARM 100, // STREAM_NOTIFICATION 100, // STREAM_BLUETOOTH_SCO 100, // STREAM_SYSTEM_ENFORCED 100, // STREAM_DTMF 100, // STREAM_TTS 100 // STREAM_MUSIC_SUB // MStar Android Patch End };
最小值定义代码
/** Minimum volume index values for audio streams */ private static int[] MIN_STREAM_VOLUME = new int[] { // MStar Android Patch Begin 0, // STREAM_VOICE_CALL // MStar Android Patch End 0, // STREAM_SYSTEM 0, // STREAM_RING 0, // STREAM_MUSIC 0, // STREAM_ALARM 0, // STREAM_NOTIFICATION // MStar Android Patch Begin 0, // STREAM_BLUETOOTH_SCO // MStar Android Patch End 0, // STREAM_SYSTEM_ENFORCED 0, // STREAM_DTMF 0, // STREAM_TTS 0 //STREAM_MUSIC_SUB };
上面定义了系统的各个通道的最大音量值和最小音量值。注意这里的最大最小只是划分的等级,如果划分等级变大了,单位调节音量时候,用户的感知就变小了,反之亦然。同时经过编译测试发现音量条会同步极值发生变化。
修改系统音量的两个方法说明
- 路径:framework/base/services/core/java/com/android/server/audio/AudioService
渐进式:adjustStreamVolume
根据音量键进行声音的递增和递减跳跃式:setStreamVolume
根据音量值,直接可以设置音量的大小
功放音量约束实现
根据公司的需求,在设置电视外放的功放时候,要求音量极值100情况下65为最大,否则电视外放会出现破音、失真情况。这种情况下,我们需要监控所有的音量控制接口,使得其音量控制均系统程序控制内。第三方app也要受到约束。为此,我们需要找到音量控制相对应的aidl文件,根据aidl文件找到其映射的c++文件,直接在底层c++修改约束条件。
- 在设置音量值,我们会首先回去到AudioManager服务,这个服务在安卓系统启动的时候,已经通过system_server注册过。在AudioManager中的控制音量方法代码如下:
渐进式:
public void adjustStreamVolume(int streamType, int direction, int flags) {
IAudioService service = getService(); try { service.adjustStreamVolume(streamType, direction, flags, getContext().getOpPackageName()); } catch (RemoteException e) { Log.e(TAG, "Dead object in adjustStreamVolume", e); }
}
跳跃式:
public void setStreamVolume(int streamType, int index, int flags) {
IAudioService service = getService(); try { service.setStreamVolume(streamType, index, flags, getContext().getOpPackageName()); } catch (RemoteException e) { Log.e(TAG, "Dead object in setStreamVolume", e); }
}
由上面可以看出,其最终是通过从Server端获取到的IAudioService(service)对象,调用其声的aidl接口方法。
IAudioService的aidl接口文件
interface IAudioService { oneway void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags, String callingPackage, String caller); void adjustStreamVolume(int streamType, int direction, int flags, String callingPackage); void setStreamVolume(int streamType, int index, int flags, String callingPackage); //省略部分 }
Client端根据定义好的aidl文件,对应Server端的c++文件,通过binder机制远程调用,jni实现底层音量的控制。
在查找过程中发现有些文件方法没有写全,是因为在IAudioService.aidl文件中,import了其他的aidl文件,因此这里的aidl文件是总文件,所以我们根据这个aidl文件,找到对应的c++文件即可。
根据其定义native方法的包名、类名,可以对应拼出其jni的实现文件名为android_media_AudioSystem.cpp音量控制jni文件android_media_AudioSystem.cpp,在gMethods中,定义了方法的一一映射关系
static JNINativeMethod gMethods[] = { //省略部分 {"setParameters", "(Ljava/lang/String;)I", (void *)android_media_AudioSystem_setParameters}, {"initStreamVolume", "(III)I", (void *)android_media_AudioSystem_initStreamVolume}, {"setStreamVolumeIndex","(III)I", (void *)android_media_AudioSystem_setStreamVolumeIndex}, //省略部分 }
修改C++层其最终调用的方法
static jint android_media_AudioSystem_setStreamVolumeIndex(JNIEnv *env, jobject thiz, jint stream, jint index, jint device) { //new code for restraining volume index = jint(index * 65 / 100); return (jint) check_AudioSystem_Command( AudioSystem::setStreamVolumeIndex(static_cast <audio_stream_type_t>(stream), index, (audio_devices_t)device)); }
在这里我们增加约束条件即可实现从最底层修改声音的控制,无论是系统还是第三方应用均会受到制约
修改音量条
路径:framework/base/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
减少音量通道
addRow(AudioManager.STREAM_RING, R.drawable.ic_volume_ringer, R.drawable.ic_volume_ringer_mute, true); addRow(AudioManager.STREAM_MUSIC, R.drawable.ic_volume_hint, R.drawable.ic_volume_hint, true); addRow(AudioManager.STREAM_ALARM, R.drawable.ic_volume_alarm, R.drawable.ic_volume_alarm_mute, false); addRow(AudioManager.STREAM_VOICE_CALL, R.drawable.ic_volume_voice, R.drawable.ic_volume_voice, false); addRow(AudioManager.STREAM_BLUETOOTH_SCO, R.drawable.ic_volume_bt_sco, R.drawable.ic_volume_bt_sco, false); addRow(AudioManager.STREAM_SYSTEM, R.drawable.ic_volume_system, R.drawable.ic_volume_system_mute, false);
addRow方法实现了音量条下多通道声音控制的加载
音量条样式自定义
修改对应文件加下res/layout布局文件,在make之前,先make res一下,将res资源更新,否则会找不到资源,出现编译错误
修改音量动画
修改其文件夹中的VolumeDialogMotion.java文件即可
监测控制音量按键
其文件夹下的VolumeDialogController实现了广播的监听,修改这里即可
修改音量策略(增加音量跳出静音模式等)
修改文件夹下的VolumeDialogComponent文件中的VolumePolicy即可