AndroidQ 设置静音模式后按音量上键不能调节音量大小

AndroidQ按音量键,默认会调出meida的音量,但是客户要求将默认调出ringer。改为默认ringer后,发现点击音量条上方的ringer_icon,设置为静音模式后,在按音量上键,不能调节音量大小了。

关于音量这块,framework中是与AudioService、AudioManager、AudioSystem相关,音量弹框的界面处理是在SystemUI下,有个volumn的文件夹。

要解此问题,很显然要从AudioService入手,因为音量的加减和AudioProfile模式都是在AudioServie处理好之后,将消息发给SystemUI,SystemUI去做界面上的更新。

AudioService中处理音量的关键方法adjustSuggestedStreamVolume–>adjustStreamVolume
adjustSuggestedStreamVolume根据名称可以猜到是Suggested,建议的音量调整。该方法主要是将传递进来的suggestedStreamType,通过etActiveStreamType方法计算出来真正要调整的音量类型。前面说的客户要求将默认的音量类型由media改为ringer关键就是在这个方法中处理的。
AndroidQ 设置静音模式后按音量上键不能调节音量大小_第1张图片
adjustSuggestedStreamVolume计算出来真正需要调整的音量类型后就调用adjustStreamVolume,流程转到adjustStreamVolume中。

这里先说一个AudioService中的内部类VolumeStreamState,每种音量类型(STREAM_VOICE_CALL、STREAM_RING、STREAM_MUSIC。。。)都会实例化一个VolumeStreamState对象,其中int mStreamType就是音量类型,还有一个SparseIntArray mIndexMap,这里有个device的概念,比如说STREAM_MUSIC类型,music可以通过麦克、耳机(有线、蓝牙耳机)等很多设备播放,这个SparseIntArray就是保存的该种音量类型在不同设备上的音量大小。

AndroidQ 设置静音模式后按音量上键不能调节音量大小_第2张图片
流程转到adjustStreamVolume中,首先该方法有一些条件判断,不满足的直接return。通过重重判断后来到第一个关键的地方:
AndroidQ 设置静音模式后按音量上键不能调节音量大小_第3张图片
计算步长,就是本次音量调整调多少,log看到是以10为步长的。比如15级的音量,通过音量键调大小是70、80、90等等这样的大小,step是以10来增加的。
再下来就进入了RingerMode的相关处理了
AndroidQ 设置静音模式后按音量上键不能调节音量大小_第4张图片
跟踪getUiSoundsStreamType的实现,就是STREAM_RING

/** @see AudioManager#getUiSoundsStreamType()  */
    public int getUiSoundsStreamType() {
        return mStreamVolumeAlias[AudioSystem.STREAM_SYSTEM];
    }
    private final int[] STREAM_VOLUME_ALIAS_VOICE = new int[] {
        AudioSystem.STREAM_VOICE_CALL,      // STREAM_VOICE_CALL
        AudioSystem.STREAM_RING,            // STREAM_SYSTEM
        AudioSystem.STREAM_RING,            // STREAM_RING
        AudioSystem.STREAM_MUSIC,           // STREAM_MUSIC
        AudioSystem.STREAM_ALARM,           // STREAM_ALARM
        AudioSystem.STREAM_RING,            // STREAM_NOTIFICATION
        AudioSystem.STREAM_BLUETOOTH_SCO,   // STREAM_BLUETOOTH_SCO
        AudioSystem.STREAM_RING,            // STREAM_SYSTEM_ENFORCED
        AudioSystem.STREAM_RING,            // STREAM_DTMF
        AudioSystem.STREAM_MUSIC,           // STREAM_TTS
        AudioSystem.STREAM_MUSIC            // STREAM_ACCESSIBILITY
    };

来看下checkForRingerModeChange的逻辑,该方法是case不同的mode,我们重点关注RINGER_MODE_SILENT。mIsSingleVolume为false,那就进到else if中
!mVolumePolicy.volumeUpToExitSilent =====》添加一个hint标志位
else ====》切换到振动模式(振动模式下增加音量就会切到normal模式,然后就可以正常调整音量了)
AndroidQ 设置静音模式后按音量上键不能调节音量大小_第5张图片
现在暂时将mVolumePolicy.volumeUpToExitSilent的来源忽略,继续跟踪adjustStreamVolume后面的逻辑。
AndroidQ 设置静音模式后按音量上键不能调节音量大小_第6张图片
checkForRingerModeChange的计算结果会影响adjustVolume的boolean值。
调整音量值的是在我们上面提到的内部类VolumeStreamState中,
AndroidQ 设置静音模式后按音量上键不能调节音量大小_第7张图片
adjustStreamVolume方法的最后一行是调用sendVolumeUpdate

// UI update and Broadcast Intent
    protected void sendVolumeUpdate(int streamType, int oldIndex, int index, int flags, int device)
    {
        streamType = mStreamVolumeAlias[streamType];

        if (streamType == AudioSystem.STREAM_MUSIC) {
            flags = updateFlagsForTvPlatform(flags);
            if ((device & mFullVolumeDevices) != 0) {
                flags &= ~AudioManager.FLAG_SHOW_UI;
            }
        }
        mVolumeController.postVolumeChanged(streamType, flags);
    }
	public void postVolumeChanged(int streamType, int flags) {
            if (mController == null)
                return;
            try {
                mController.volumeChanged(streamType, flags);
            } catch (RemoteException e) {
                Log.w(TAG, "Error calling volumeChanged", e);
            }
        }

这里的volumeChanged就是向SystemUI去通知音量变化了,SystemUI收到该通知就会读取系统音量:
frameworks\base\packages\SystemUI\src\com\android\systemui\volume\VolumeDialogControllerImpl.java代码:
AndroidQ 设置静音模式后按音量上键不能调节音量大小_第8张图片
AndroidQ 设置静音模式后按音量上键不能调节音量大小_第9张图片
这里的getAudioManagerStreamVolume,最后就是调用AudioService的getLastAudibleStreamVolume,即上面提到的VolumeStreamType中put的值

/** Get last audible volume before stream was muted. */
    public int getLastAudibleStreamVolume(int streamType) {
        ensureValidStreamType(streamType);
        int device = getDeviceForStream(streamType);
        return (mStreamStates[streamType].getIndex(device) + 5) / 10;
    }

到此是音量调整从AudioService到SystemUI中的逻辑。
对于我们这个问题,静音模式下不能调节音量的问题,我们回到前面忽略的关键判断:checkForRingerModeChange方法中的mVolumePolicy.volumeUpToExitSilent,从名称上就好理解,音量上键退出静音模式,追踪mVolumePolicy的赋值

@Override
    public void setVolumePolicy(VolumePolicy policy) {
        enforceVolumeController("set volume policy");
        if (policy != null && !policy.equals(mVolumePolicy)) {
            mVolumePolicy = policy;
            if (DEBUG_VOL) Log.d(TAG, "Volume policy changed: " + mVolumePolicy);
        }
    }

public方法,显然是被外界调用的,framework/base下搜索,竟然是在SystemUI下的VolumeDialogComponent.java中调用
看下该类是如果实例化VolumePolicy对象的:
AndroidQ 设置静音模式后按音量上键不能调节音量大小_第10张图片
果然DEFAULT_VOLUME_UP_TO_EXIT_SILENT配置的是false,改为true就可以在静音模式下按音量上面,先切换到振动模式,再按音量上键,进入normal模式,就可以正常调节音量了。

你可能感兴趣的:(Android源码)