34-Android之耳机音量加大时警告提示框问题(展锐SC9820E平台)

34-Android之耳机音量加大时警告提示框问题


Android4.4

展锐SC9820E平台,在进行GCF测试时,提出耳机警语问题。

我们在使用手机时,插入耳机,然后加大音量至安全音量时,会出现一个警告提示框,点击确定(或连续多次按音量+按键),才会继续增大音量。

而根据规范要求,在超过显示警告提示框的安全音量后, 如果播放音乐等超过20个小时,音量会自动回退到显示警告提示的安全音量。如果继续加大音量,又会出现警告提示框。

而GCF测试出现的问题是,超过20个小时后,音量没有回退安全音量。通过了解GCF测试时, 是通过播放FM进行测试的,通过对AudioService进行查看后,发现AudioService中展锐没有对AudioSystem.STREAM_FM(展锐添加的音频流类型)进行安全音量处理,因此需要自己添加,可以通过对比AudioSystem.STREAM_MUSIC进行添加。

frameworks/base/media/java/android/media/AudioService.java
    /** @see AudioManager#adjustStreamVolume(int, int, int) */
    public void adjustStreamVolume(int streamType, int direction, int flags,
            String callingPackage) {
        // ...省略
	    // 进行安全音量检查
            if ((direction == AudioManager.ADJUST_RAISE) &&
                    !checkSafeMediaVolume(streamTypeAlias, aliasIndex + step, device)) {
                Log.e(TAG, "adjustStreamVolume() safe volume index = "+oldIndex);
                mVolumePanel.postDisplaySafeVolumeWarning(flags); // 显示警告提示框
            } else if (streamState.adjustIndex(direction * step, device)) {

        // ... 省略

        int index = mStreamStates[streamType].getIndex(device);
        sendVolumeUpdate(streamType, oldIndex, index, flags);
    }

    // 检查安全音量
    private boolean checkSafeMediaVolume(int streamType, int index, int device) {
        synchronized (mSafeMediaVolumeState) {
            if ((mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE) &&
                    ((mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) || 
                    // 此处添加对AudioSystem.STREAM_FM的判断
                    (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_FM)) &&
                    ((device & mSafeMediaVolumeDevices) != 0) &&
                    (index > mSafeMediaVolumeIndex)) {
                return false;
            }
            return true;
        }
    }

当点击警告提示框的确定或者继续加大音量,则执行AudioService的以下方法:

    private final int SAFE_MEDIA_VOLUME_NOT_CONFIGURED = 0;
    private final int SAFE_MEDIA_VOLUME_DISABLED = 1;
    private final int SAFE_MEDIA_VOLUME_INACTIVE = 2;
    private final int SAFE_MEDIA_VOLUME_ACTIVE = 3;
    private Integer mSafeMediaVolumeState;

    private int mMcc = 0;
    // mSafeMediaVolumeIndex is the cached value of config_safe_media_volume_index property
    private int mSafeMediaVolumeIndex;
    // mSafeMediaVolumeDevices lists the devices for which safe media volume is enforced,
    // 安全音量提示针对的是插入耳机的情况
    private final int mSafeMediaVolumeDevices = AudioSystem.DEVICE_OUT_WIRED_HEADSET |
                                                AudioSystem.DEVICE_OUT_WIRED_HEADPHONE;
    // mMusicActiveMs is the cumulative time of music activity since safe volume was disabled.
    // When this time reaches UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX, the safe media volume is re-enabled
    // automatically. mMusicActiveMs is rounded to a multiple of MUSIC_ACTIVE_POLL_PERIOD_MS.
    private int mMusicActiveMs;  //  超过安全音量使用时长的计时器
    // 此处就是超过安全音量,使用的最长时间20个小时
    private static final int UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX =  (20 * 3600 * 1000); // 20 hours
    private static final int MUSIC_ACTIVE_POLL_PERIOD_MS = 60000;  // 1 minute polling interval
    private static final int SAFE_VOLUME_CONFIGURE_TIMEOUT_MS = 30000;  // 30s after boot completed
    // 设置是否启用安全音量
    private void setSafeMediaVolumeEnabled(boolean on) {
    	Log.d(TAG, "setSafeMediaVolumeEnabled on: " + on);
        synchronized (mSafeMediaVolumeState) {
            if ((mSafeMediaVolumeState != SAFE_MEDIA_VOLUME_NOT_CONFIGURED) &&
                    (mSafeMediaVolumeState != SAFE_MEDIA_VOLUME_DISABLED)) {
                if (on && (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_INACTIVE)) {
                    mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_ACTIVE; // 修改安全音量的状态, 启用
                    // 当超过安全音量使用超过20小时的时候, 执行此处,启用安全音量
                    enforceSafeMediaVolume();  
                } else if (!on && (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE)) {
                    // 点击警告提示框的确定或者继续加大音量,  执行此处,取消安全音量
                    mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_INACTIVE;  // 修改安全音量的状态, 未启用
                    mMusicActiveMs = 0; // 将计时器的时间置为0
                    sendMsg(mAudioHandler,
                            MSG_CHECK_MUSIC_ACTIVE,
                            SENDMSG_REPLACE,
                            0,
                            0,
                            null,
                            MUSIC_ACTIVE_POLL_PERIOD_MS); // 延迟1分钟进行音乐播放检测,执行onCheckMusicActive方法
                }
            }
        }
    }
    private void onCheckMusicActive() {  // 检测音乐是否播放
        synchronized (mSafeMediaVolumeState) {
            if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_INACTIVE) {
                 // 因为AudioSystem.STREAM_FM, 底层实际也是用的AudioSystem.STREAM_MUSIC, 因此播放FM时, 也能获取到输出设备
                int device = getDeviceForStream(AudioSystem.STREAM_MUSIC);
                if ((device & mSafeMediaVolumeDevices) != 0) {
                    sendMsg(mAudioHandler,
                            MSG_CHECK_MUSIC_ACTIVE,
                            SENDMSG_REPLACE,
                            0,
                            0,
                            null,
                            MUSIC_ACTIVE_POLL_PERIOD_MS); // 此处延迟1分钟, 再执行该方法,重新进行校验
                    int index = mStreamStates[AudioSystem.STREAM_MUSIC].getIndex(device);
                    // 修改的代码, 添加AudioSystem.STREAM_FM的判断,参照AudioSystem.STREAM_MUSIC
                    int index2 = mStreamStates[AudioSystem.STREAM_FM].getIndex(device);
                    if (
                    		(AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0) && (index > mSafeMediaVolumeIndex))
                    		|| 
                    		(AudioSystem.isStreamActive(AudioSystem.STREAM_FM, 0) && (index2 > mSafeMediaVolumeIndex))
                    		) {
                        // 将计时器加上MUSIC_ACTIVE_POLL_PERIOD_MS(1分钟), 因为上面是延迟1分钟再次执行该方法
                        // 这里其实有问题,就是上面执行延迟1分钟执行该方法,延迟的时间可能不精确, 导致计时器的时间可能小于实际播放时长,
                        // 这个在下篇文章MTK的Android10中解决。 因为该版本是Android4.4, 目前还没有出现这中情况
                        mMusicActiveMs += MUSIC_ACTIVE_POLL_PERIOD_MS;
                        Log.d(TAG, "onCheckMusicActive mMusicActiveMs: " + mMusicActiveMs);
                        // 当超过20小时的时候, 启动安全音量
                        if (mMusicActiveMs > UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX) {  
                            setSafeMediaVolumeEnabled(true); // 接下来看enforceSafeMediaVolume方法
                            mMusicActiveMs = 0; // 将计时器的置为0
                        }
                    }
                }
            }
        }
    }

    private void enforceSafeMediaVolume() {  // 将AudioSystem.STREAM_MUSIC强制设置为安全音量
        VolumeStreamState streamState = mStreamStates[AudioSystem.STREAM_MUSIC];
        int devices = mSafeMediaVolumeDevices;
        int i = 0;
        while (devices != 0) {
            final int device = 1 << i++;
            if ((device & devices) == 0) {
                continue;
            }
            int index = streamState.getIndex(device);
            if (index > mSafeMediaVolumeIndex) {
                streamState.setIndex(mSafeMediaVolumeIndex, device);
                sendMsg(mAudioHandler,
                        MSG_SET_DEVICE_VOLUME,
                        SENDMSG_QUEUE,
                        device,
                        0,
                        streamState,
                        0);
            }
            // 此处是添加的代码,参考上面的AudioSystem.STREAM_MUSIC
            VolumeStreamState state = mStreamStates[AudioSystem.STREAM_FM];
            final int fmIndex = state.getIndex(device);
            if (fmIndex > mSafeMediaVolumeIndex) {
            	state.setIndex(mSafeMediaVolumeIndex, device);
                sendMsg(mAudioHandler,
                        MSG_SET_DEVICE_VOLUME,
                        SENDMSG_QUEUE,
                        device,
                        0,
                        state,
                        0);
                 // 注意此处,AudioSystem.STREAM_MUSIC在执行MSG_SET_DEVICE_VOLUME消息后, 可以正常的将音量设置为安全音量, 但是AudioSystem.STREAM_FM不行,具体什么原因,还没有去跟代码, 只知道执行下面的代码后, AudioSystem.STREAM_FM可以被修改到安全音量
                mAudioHandler.postDelayed(new Runnable() {
					@Override
					public void run() {
						  int index = mStreamStates[AudioSystem.STREAM_FM].getIndex(device);
					      sendVolumeUpdate(AudioSystem.STREAM_FM, fmIndex, index, 0);
					}
				}, 200);
            }
            devices &= ~device;
        }
    }

此外,关于安全音量(mSafeMediaVolumeIndex)可以在AudioService的构造方法中看到赋值:

public AudioService(Context context) {
     // ...
     // The default safe volume index read here will be replaced by the actual value when
     // the mcc is read by onConfigureSafeVolume()
     mSafeMediaVolumeIndex = mContext.getResources().getInteger(
                com.android.internal.R.integer.config_safe_media_volume_index) * 10;    
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值