首次开机接收来电后短信无声

xiaoxiao2021-02-28  102

故障现场

这里的首次开机也包括恢复出厂设置后的第一次开机。出现故障后,配合机发送一条短信过来,一直没有提示音。打开AudioHW的PCM DUMP之后发现写下去的音频流为全0数据,查看dumpsys media.audio_policy的信息如下: Streams dump:  Stream  Can be muted  Index Min  Index Max  Index Cur [device : index]...  00      true          01         05         0001 : 04, 40000000 : 04,   01      true          00         07         0001 : 00, 0002 : 00, 40000000 : 05,   02      true          00         07         0001 : 05, 0002 : 05, 40000000 : 05,   03      true          00         15         0004 : 10, 0008 : 10, 40000000 : 11,   04      true          00         07         40000000 : 06,   05      true          00         07         0001 : 00, 0002 : 00, 40000000 : 05,   06      true          00         15         40000000 : 07,   07      true          00         07         0001 : 00, 0002 : 00, 40000000 : 05,   08      true          00         15         0001 : 11, 0002 : 11, 40000000 : 11,   09      true          00         15         0002 : 11, 40000000 : 11,   10      true          00         15         0004 : 10, 0008 : 10, 40000000 : 11,   11      true          00         01         40000000 : 00,   12      true          00         01         40000000 : 00, 可以看到SYSTEM、NOTIFICATION和ENFORCED_AUDIBLE的当前音量值被设置0。查看log可以发现在来电前后有如下的几行可疑打印: 05-03 21:06:09.419  2826  2932 I vol.Events: writeEvent internal_ringer_mode_changed silent 05-03 21:06:09.420  2826  2932 I vol.Events: writeEvent mute_changed STREAM_RING true 05-03 21:06:09.433  2826  2932 I vol.Events: writeEvent mute_changed STREAM_SYSTEM true 05-03 21:06:09.433  2826  2932 I vol.Events: writeEvent external_ringer_mode_changed silent 来电铃音播放结束后对应有: 05-03 21:06:18.479  2826  2932 I vol.Events: writeEvent mute_changed STREAM_RING false 05-03 21:06:18.525  2826  2932 I vol.Events: writeEvent mute_changed STREAM_SYSTEM false 05-03 21:06:18.532  2826  2932 I vol.Events: writeEvent internal_ringer_mode_changed normal 这些代码是电话接通后切成勿扰模式相关的调用,是在systemUI中控制的。

进一步分析

增加AudioFlinger、Thread和APM的log之后,来电之后开始播放短信提示音时将Stream 5设为了Mute。 05-03 21:06:36.752  1517  2963 I ExtendedNuUtils: printFileName fd(13) -> /data/system_de/0/ringtones/notification_sound_cache 05-03 21:06:37.055  1504  1690 V APM_AudioPolicyManager: startOutput() output 13, stream 5, session 425 05-03 21:06:37.057  1504  1690 V APM_AudioPolicyManager: setStrategyMute() strategy 3, mute 1, output ID 3 05-03 21:06:37.057  1504  1690 V APM_AudioPolicyManager: setStreamMute() stream 5, mute 1, mMuteCount 0 device 0002 05-03 21:06:37.058  1504  1690 V APM_AudioPolicyManager: setStrategyMute() strategy 3, mute 0, output ID 3 05-03 21:06:37.058  1504  1690 V APM_AudioPolicyManager: setStreamMute() stream 5, mute 0, mMuteCount 1 device 0002 整体搜索Stream 5,发现了如下两条打印: 05-03 21:06:17.097  1504  9147 V APM_AudioPolicyManager: setStreamVolumeIndex() stream 5, device 00000001, index 0 05-03 21:06:17.953  1504  1882 V APM_AudioPolicyManager: setStreamVolumeIndex() stream 5, device 00000002, index 0 下面分别从两个方向来分析这个故障的原因: 1)调用setStreamVolumeIndex将音量设为0 发起该调用的地方来自AudioService.java,总共有applyDeviceVolume_syncVSS(int device)和applyAllVolumes()两个函数,它们的逻辑是从mIsMuted、mFullVolumeDevices和mIndexMap获取各个设备和Stream的音量值并设置下去。结合另一个故障的细节(即发生故障后,上面直接从AudioManager读取出来的音量值为5,且按下音量上键时直接跳到6级音量,因此可以判断,这里一定是mIsMuted起了效果),继续检查mIsMuted的来源。发现它的设置只有一个地方就是VolumeStreamState的mute函数,继续向上的调用函数有adjustStreamVolume()、onUnmuteStream()、onSetStreamVolume()、muteRingerModeStreams(),直接导致被设为音量0的log在结束通话之后,mute_changed STREAM_RING false之前,目前来看分析受阻。 2)调用setStreamMute()将音量设为0 经过查看代码发现,这个调用只是setOutputDevice函数中,如果设备确实发生切换的情况下,在checkDeviceMuteStrategies中暂时将Stream静音一下子避免设备切换时的POP音问题,因此不是问题所在。 返回到第一个方向,虽然分析受阻,不过通过分析代码逻辑有一个怀疑对象,就是如下调用/frameworks/base/services/core/java/com/android/server/notification/ZenModeHelper.java中的updateRingerModeAffectedStreams(),这里调用updateRingerModeAffectedStreamsInternal,如果该调用比将RingerMode切回Normal早的话,就会发现这个问题了。不过,还是加调用栈来定位最直接了,比猜的来得快(上述代码应该就是勿打扰相关的实现)。 增加log后,得到调用栈如下: 05-04 14:31:05.094  1945  2680 E AudioService: applyDeviceVolume_syncVSS mIsMuted : true Index : 50 05-04 14:31:05.096  1945  2680 E AudioService: java.lang.Throwable 05-04 14:31:05.096  1945  2680 E AudioService: at com.android.server.audio.AudioService$VolumeStreamState.applyDeviceVolume_syncVSS(AudioService.java:4162) 05-04 14:31:05.096  1945  2680 E AudioService: at com.android.server.audio.AudioService$AudioHandler.setDeviceVolume(AudioService.java:4462) 05-04 14:31:05.096  1945  2680 E AudioService: at com.android.server.audio.AudioService$AudioHandler.handleMessage(AudioService.java:4746) 05-04 14:31:05.096  1945  2680 E AudioService: at android.os.Handler.dispatchMessage(Handler.java:102) 05-04 14:31:05.096  1945  2680 E AudioService: at android.os.Looper.loop(Looper.java:154) 05-04 14:31:05.096  1945  2680 E AudioService: at  05-04 14:31:05.097  1436  8963 V APM_AudioPolicyManager: setStreamVolumeIndex() stream 5, device 00000001, index 0 而在进入通话状态时,有从ZenModeHelper发起的经过muteRingerModeStreams到mute的调用,因此是因此勿扰模式的设置是音量为0的原因,但是发起setDeviceVolume调用的另有流程。再添加log后的新场景分析如下: 挂断电话时,经过如下的setMode调用栈,发送MSG_SET_DEVICE_VOLUME消息。 05-04 15:05:46.517  1940  3150 E AudioService: java.lang.Throwable 05-04 15:05:46.517  1940  3150 E AudioService: at com.android.server.audio.AudioService.setStreamVolumeInt(AudioService.java:1896) 05-04 15:05:46.517  1940  3150 E AudioService: at com.android.server.audio.AudioService.setModeInt(AudioService.java:2525) 05-04 15:05:46.517  1940  3150 E AudioService: at com.android.server.audio.AudioService.setMode(AudioService.java:2431) 05-04 15:05:46.517  1940  3150 E AudioService: at android.media.AudioManager.setMode(AudioManager.java:1618) 05-04 15:05:46.517  1940  3150 E AudioService: at com.android.server.telecom.CallAudioModeStateMachine$UnfocusedState.enter(CallAudioModeStateMachine.java:152) 05-04 15:05:46.517  1940  3150 E AudioService: at com.android.internal.util.StateMachine$SmHandler.invokeEnterMethods(StateMachine.java:1021) 05-04 15:05:46.517  1940  3150 E AudioService: at com.android.internal.util.StateMachine$SmHandler.performTransitions(StateMachine.java:867) 05-04 15:05:46.517  1940  3150 E AudioService: at com.android.internal.util.StateMachine$SmHandler.handleMessage(StateMachine.java:809) 05-04 15:05:46.517  1940  3150 E AudioService: at android.os.Handler.dispatchMessage(Handler.java:102) 05-04 15:05:46.517  1940  3150 E AudioService: at android.os.Looper.loop(Looper.java:154) 05-04 15:05:46.517  1940  3150 E AudioService: at android.os.HandlerThread.run(HandlerThread.java:61) 然后经过如下调用栈,将Stream 5的扬声器设为静音 05-04 15:05:46.568  1940  2684 E AudioService: java.lang.Throwable 05-04 15:05:46.568  1940  2684 E AudioService: at com.android.server.audio.AudioService$VolumeStreamState.applyDeviceVolume_syncVSS(AudioService.java:4164) 05-04 15:05:46.568  1940  2684 E AudioService: at com.android.server.audio.AudioService$AudioHandler.setDeviceVolume(AudioService.java:4464) 05-04 15:05:46.568  1940  2684 E AudioService: at com.android.server.audio.AudioService$AudioHandler.handleMessage(AudioService.java:4748) 05-04 15:05:46.568  1940  2684 E AudioService: at android.os.Handler.dispatchMessage(Handler.java:102) 05-04 15:05:46.568  1940  2684 E AudioService: at android.os.Looper.loop(Looper.java:154) 05-04 15:05:46.568  1940  2684 E AudioService: at com.android.server.audio.AudioService$AudioSystemThread.run(AudioService.java:4439) 05-04 15:05:46.572  3562  3562 I LauncherUnreadService: Call log content changed 05-04 15:05:46.577  1439  2686 V APM_AudioPolicyManager: setStreamVolumeIndex() stream 5, device 00000002, index 0 进一步在勿扰模式的后续处理中,会调用经过如下调用栈将需要的Stream的音量值给恢复,但是异常时Stream 5的扬声器对应音量没有设置。 05-04 15:05:46.973  1940  1940 E AudioService: java.lang.Throwable 05-04 15:05:46.973  1940  1940 E AudioService: at com.android.server.audio.AudioService$VolumeStreamState.mute(AudioService.java:4320) 05-04 15:05:46.973  1940  1940 E AudioService: at com.android.server.audio.AudioService.muteRingerModeStreams(AudioService.java:2289) 05-04 15:05:46.973  1940  1940 E AudioService: at com.android.server.audio.AudioService.setRingerModeInt(AudioService.java:2306) 05-04 15:05:46.973  1940  1940 E AudioService: at com.android.server.audio.AudioService.setRingerMode(AudioService.java:2230) 05-04 15:05:46.973  1940  1940 E AudioService: at com.android.server.audio.AudioService.setRingerModeInternal(AudioService.java:2200) 05-04 15:05:46.973  1940  1940 E AudioService: at com.android.server.audio.AudioService$AudioServiceInternal.setRingerModeInternal(AudioService.java:6396) 05-04 15:05:46.973  1940  1940 E AudioService: at com.android.server.notification.ZenModeHelper.applyZenToRingerMode(ZenModeHelper.java:786) 05-04 15:05:46.973  1940  1940 E AudioService: at com.android.server.notification.ZenModeHelper.evaluateZenMode(ZenModeHelper.java:699) 05-04 15:05:46.973  1940  1940 E AudioService: at com.android.server.notification.ZenModeHelper.applyConfig(ZenModeHelper.java:665) 05-04 15:05:46.973  1940  1940 E AudioService: at com.android.server.notification.ZenModeHelper.-wrap3(ZenModeHelper.java) 05-04 15:05:46.973  1940  1940 E AudioService: at com.android.server.notification.ZenModeHelper$H.handleMessage(ZenModeHelper.java:1135) 05-04 15:05:46.973  1940  1940 E AudioService: at android.os.Handler.dispatchMessage(Handler.java:102) 05-04 15:05:46.973  1940  1940 E AudioService: at android.os.Looper.loop(Looper.java:154) 05-04 15:05:46.973  1940  1940 E AudioService: at com.android.server.SystemServer.run(SystemServer.java:366) 05-04 15:05:46.973  1940  1940 E AudioService: at com.android.server.SystemServer.main(SystemServer.java:236) 05-04 15:05:46.973  1940  1940 E AudioService: at java.lang.reflect.Method.invoke(Native Method) 05-04 15:05:46.973  1940  1940 E AudioService: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886) 05-04 15:05:46.973  1940  1940 E AudioService: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776) 05-04 15:05:46.974  1940  2684 E AudioService: java.lang.Throwable 05-04 15:05:46.974  1940  2684 E AudioService: at com.android.server.audio.AudioService$VolumeStreamState.applyAllVolumes(AudioService.java:4178) 05-04 15:05:46.974  1940  2684 E AudioService: at com.android.server.audio.AudioService$AudioHandler.setAllVolumes(AudioService.java:4482) 05-04 15:05:46.974  1940  2684 E AudioService: at com.android.server.audio.AudioService$AudioHandler.handleMessage(AudioService.java:4752) 05-04 15:05:46.974  1940  2684 E AudioService: at android.os.Handler.dispatchMessage(Handler.java:102) 05-04 15:05:46.974  1940  2684 E AudioService: at android.os.Looper.loop(Looper.java:154) 05-04 15:05:46.974  1940  2684 E AudioService: at com.android.server.audio.AudioService$AudioSystemThread.run(AudioService.java:4439) 05-04 15:05:46.974  1940  2684 E AudioService: applyAllVolumes Muted:false index:107 Stream 5异常的设置栈如下: 05-04 15:05:47.097  1940  2684 E AudioService: java.lang.Throwable 05-04 15:05:47.097  1940  2684 E AudioService: at com.android.server.audio.AudioService$VolumeStreamState.applyAllVolumes(AudioService.java:4178) 05-04 15:05:47.097  1940  2684 E AudioService: at com.android.server.audio.AudioService$AudioHandler.setAllVolumes(AudioService.java:4482) 05-04 15:05:47.097  1940  2684 E AudioService: at com.android.server.audio.AudioService$AudioHandler.handleMessage(AudioService.java:4752) 05-04 15:05:47.097  1940  2684 E AudioService: at android.os.Handler.dispatchMessage(Handler.java:102) 05-04 15:05:47.097  1940  2684 E AudioService: at android.os.Looper.loop(Looper.java:154) 05-04 15:05:47.097  1940  2684 E AudioService: at com.android.server.audio.AudioService$AudioSystemThread.run(AudioService.java:4439) 05-04 15:05:47.097  1439  1810 V APM_AudioPolicyManager: setStreamVolumeIndex() stream 5, device 40000000, index 5 也就是说,将音量设回到非静音,也是先要经过ZenModeHelper的mute调用。要注意的一点是,VolumeStreamState.applyAllVolumes对象是每个Stream一个,并不是所有Stream的音量只要调用一个applyAllVolumes即可。上述两个调用栈的衔接就是mute函数,因此从muteRingerModeStreams入手分析。从效果上看,就是VolumeStreamState对象(Stream 5对应的)的mIndexMap包含的没有了扬声器这样的设备,而这些对象全部来自于mStreamStates[streamType],正常情况下,mIndexMap只有添加的流程,并没有删除的流程。因此我们要关注一下,会添加这些信息的调用有哪些。 分别是readSettings()、setIndex、setAllIndexes、setAllIndexesToMax、checkFixedVolumeDevices,根据首次开机这样的场景来说,最可能实现这个功能的是readSettings函数,在这里发现了一个可能的问题: public void readSettings() {    // retrieve current volume for device    String name = getSettingNameForDevice(device);    // if no volume stored for current stream and device, use default volume if default    // device, continue otherwise    int defaultIndex = (device == AudioSystem.DEVICE_OUT_DEFAULT) ?               AudioSystem.DEFAULT_STREAM_VOLUME[mStreamType] : -1;    int index = Settings.System.getIntForUser(    mContentResolver, name, defaultIndex, UserHandle.USER_CURRENT);    if (index == -1) {       continue;    }    mIndexMap.put(device, getValidIndex(10 * index)); } 缺省的音量值来自Settings的设置,索引值System.VOLUME_SETTINGS[mStreamVolumeAlias[i]]加设备名,对应开机时VolumeStreamState对象创建时的入参(如下)。 private void createStreamStates() {    int numStreamTypes = AudioSystem.getNumStreamTypes();    VolumeStreamState[] streams = mStreamStates =  new VolumeStreamState[numStreamTypes];    for (int i = 0; i < numStreamTypes; i++) {       streams[i] =  new VolumeStreamState(System.VOLUME_SETTINGS[mStreamVolumeAlias[i]], i);    } } 数据库索引值的字符串定义在/frameworks/base/core/java/android/provider/Settings.java中,而数据库System是运行中创建的/data/system/users/0/settings_system.xml文件。创建函数是AudioService:: AudioHandler:: persistVolume函数,向上追溯就是MSG_PERSIST_VOLUME消息,会发送该消息的一个函数就是setDeviceVolume,综合起来可以初步得出结论: ---在手机开机时,会通过readSettings()读取settings_system.xml创建mIndexMap数组内容;如果运行期间有发送MSG_PERSIST_VOLUME消息的函数被调用时,可能会在settings_system.xml中新建新的条目; ---settings_system.xml中条目的索引值是volume_notification以及volume_notification加设备名,前者设为DEFAULT_DEVICE的音量值,后者对应各个设备的音量值; ---setModeInt函数中会调用setStreamVolumeInt更新Stream和Device的音量,这里有一个不对称的处理,一个是通过HAL层修改mStreamType的音量值,另一个是增加上述xml的设置,但是缺少了一个添加mIndexMap的动作,导致后续的恢复处理回出现跳过新增设备的音量恢复的故障。 不过,对于这个故障,按照上述思路,很快就发现了代码遗漏,缺少了一个资源配置: frameworks/base/packages/SettingsProvider/res/values/customize.xml <resources>     <integer name="def_notification_speaker_volume" translatable="false">5</integer> </resources> /frameworks/base/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java中的loadCustomizedVolumeLevels调用systemSettings.updateSettingLocked设置Stream的音量值,也是给settings_system.xml增加数据库条目的途径之一,增加以上配置后,扬声器播放短信提示音的故障就可以解决了。
转载请注明原文地址: https://www.6miu.com/read-24185.html

最新回复(0)