获取情景模式的值方法:
AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
final int ringerMode = audioManager.getRingerMode();
结论:ringerMode值会在用户修改声音后发生改变,振动模式被修改为普通模式,无声模式还是无声模式
流程如下
/frameworks/base/services/core/java/com/android/server/audio/AudioService.java
private void setStreamVolume(int streamType, int index, int flags, String callingPackage,
String caller, int uid, boolean hasModifyAudioSettings) {
...
if (isAndroidNPlus(callingPackage)
&& wouldToggleZenMode(getNewRingerMode(streamTypeAlias, index, flags))
&& !mNm.isNotificationPolicyAccessGrantedForPackage(callingPackage)) {
throw new SecurityException("Not allowed to change Do Not Disturb state");
}
...
}
private int getNewRingerMode(int stream, int index, int flags) {
// setRingerMode does nothing if the device is single volume,so the value would be unchanged
if (mIsSingleVolume) {
return getRingerModeExternal();
}
// setting volume on ui sounds stream type also controls silent mode
if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
(stream == getUiSoundsStreamType())) {
int newRingerMode;
//index 音量大小
if (index == 0) {
//volumeDownToEnterSilent 注允许音量从振动调低进入铃声模式=静音
newRingerMode = mHasVibrator ? AudioManager.RINGER_MODE_VIBRATE
: mVolumePolicy.volumeDownToEnterSilent ? AudioManager.RINGER_MODE_SILENT
: AudioManager.RINGER_MODE_NORMAL;
Log.w(TAG, "setMode() getNewRingerMode22:"+newRingerMode);
} else {
//当声音不为0,改为RINGER_MODE_NORMAL模式value=2
newRingerMode = AudioManager.RINGER_MODE_NORMAL;
}
return newRingerMode;
}
return getRingerModeExternal();
}
private void setStreamVolume(int streamType, int index, int flags, String callingPackage,
String caller, int uid, boolean hasModifyAudioSettings) {
...
if (!checkSafeMediaVolume(streamTypeAlias, index, device)) {
mVolumeController.postDisplaySafeVolumeWarning(flags);
mPendingVolumeCommand = new StreamVolumeCommand(
streamType, index, flags, device);
} else {
//重置音量
onSetStreamVolume(streamType, index, flags, device, caller, hasModifyAudioSettings);
index = mStreamStates[streamType].getIndex(device);
}
...
}
private void onSetStreamVolume(int streamType, int index, int flags, int device,
String caller, boolean hasModifyAudioSettings) {
final int stream = mStreamVolumeAlias[streamType];
setStreamVolumeInt(stream, index, device, false, caller, hasModifyAudioSettings);
// setting volume on ui sounds stream type also controls silent mode
if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
(stream == getUiSoundsStreamType())) {
//重新设置模式 执行getNewRingerMode方法 根据上述分析该方法执行后返回的是RINGER_MODE_NORMAL模式,修改原模式
setRingerMode(getNewRingerMode(stream, index, flags),
TAG + ".onSetStreamVolume", false /*external*/);
}
// setting non-zero volume for a muted stream unmutes the stream and vice versa,
// except for BT SCO stream where only explicit mute is allowed to comply to BT requirements
if (streamType != AudioSystem.STREAM_BLUETOOTH_SCO) {
mStreamStates[stream].mute(index == 0);
}
}
private void setRingerMode(int ringerMode, String caller, boolean external) {
if (mUseFixedVolume || mIsSingleVolume) {
return;
}
if (caller == null || caller.length() == 0) {
throw new IllegalArgumentException("Bad caller: " + caller);
}
ensureValidRingerMode(ringerMode);
if ((ringerMode == AudioManager.RINGER_MODE_VIBRATE) && !mHasVibrator) {
ringerMode = AudioManager.RINGER_MODE_SILENT;
}
final long identity = Binder.clearCallingIdentity();
try {
synchronized (mSettingsLock) {
final int ringerModeInternal = getRingerModeInternal();
final int ringerModeExternal = getRingerModeExternal();
if (external) {
setRingerModeExt(ringerMode);
if (mRingerModeDelegate != null) {
ringerMode = mRingerModeDelegate.onSetRingerModeExternal(ringerModeExternal,
ringerMode, caller, ringerModeInternal, mVolumePolicy);
}
if (ringerMode != ringerModeInternal) {
setRingerModeInt(ringerMode, true /*persist*/);
}
} else /*internal*/ {
//走内部模式值ringerModeInternal,setRingerModeInt重置该settings.global数据
if (ringerMode != ringerModeInternal) {
setRingerModeInt(ringerMode, true /*persist*/);
}
if (mRingerModeDelegate != null) {
//此处会对外部值ringerModeExternal处理一些,涉及到ZenMode
ringerMode = mRingerModeDelegate.onSetRingerModeInternal(ringerModeInternal,
ringerMode, caller, ringerModeExternal, mVolumePolicy);
}
//****重点***此处重新对ringmodel赋值,振动模式修改为RINGER_MODE_NORMAL,但是无声模式还是RINGER_MODE_SILENT
//本文开始提及 audioManager.getRingerMode()取值则会发生变化问题,基本明确
setRingerModeExt(ringerMode);
}
}
} finally {
Binder.restoreCallingIdentity(identity);
}
}
frameworks/base/services/core/java/com/android/server/notification/ZenModeHelper.java
@Override
public int onSetRingerModeInternal(int ringerModeOld, int ringerModeNew, String caller,
int ringerModeExternal, VolumePolicy policy) {
final boolean isChange = ringerModeOld != ringerModeNew;
int ringerModeExternalOut = ringerModeNew;
if (mZenMode == Global.ZEN_MODE_OFF
|| (mZenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS
&& !ZenModeConfig.areAllPriorityOnlyRingerSoundsMuted(mConfig))) {
// in priority only with ringer not muted, save ringer mode changes
// in dnd off, save ringer mode changes
setPreviousRingerModeSetting(ringerModeNew);
}
int newZen = -1;
//对新ringmodel模式处理,因为方法会根据音量改变模式修改为ringerModeNew==2==RINGER_MODE_NORMAL
//当RINGER_MODE_VIBRATE/RINGER_MODE_NORMAL 重新处理
switch (ringerModeNew) {
case AudioManager.RINGER_MODE_SILENT:
if (isChange && policy.doNotDisturbWhenSilent) {
if (mZenMode == Global.ZEN_MODE_OFF) {
newZen = Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
}
setPreviousRingerModeSetting(ringerModeOld);
}
break;
case AudioManager.RINGER_MODE_VIBRATE:
case AudioManager.RINGER_MODE_NORMAL:
if (isChange && ringerModeOld == AudioManager.RINGER_MODE_SILENT
&& (mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS
|| mZenMode == Global.ZEN_MODE_ALARMS
|| (mZenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS
&& ZenModeConfig.areAllPriorityOnlyRingerSoundsMuted(
mConfig)))) {
newZen = Global.ZEN_MODE_OFF;
} else if (mZenMode != Global.ZEN_MODE_OFF) {
//若主动设置模式为无声模式即RINGER_MODE_SILENT,虽然会因音量值修改为RINGER_MODE_NORMAL,但传入的mZenMode值mZenMode==1==ZEN_MODE_IMPORTANT_INTERRUPTIONS
//也就是会重置ringerModeExternalOut==0,这是不同之处
//可打log当设置的模式不是RINGER_MODE_SILENT,mZenMode亦不同
ringerModeExternalOut = AudioManager.RINGER_MODE_SILENT;
}
break;
}
if (newZen != -1) {
setManualZenMode(newZen, null, "ringerModeInternal", null,
false /*setRingerMode*/);
}
if (isChange || newZen != -1 || ringerModeExternal != ringerModeExternalOut) {
ZenLog.traceSetRingerModeInternal(ringerModeOld, ringerModeNew, caller,
ringerModeExternal, ringerModeExternalOut);
}
return ringerModeExternalOut;
}
还有一种adjustStreamVolume音量递增方式设置音量
protected void adjustStreamVolume(int streamType, int direction, int flags,
String callingPackage, String caller, int uid, boolean hasModifyAudioSettings,
int keyEventMode) {
...
if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
(streamTypeAlias == getUiSoundsStreamType())) {
int ringerMode = getRingerModeInternal();
// do not vibrate if already in vibrate mode
if (ringerMode == AudioManager.RINGER_MODE_VIBRATE) {
flags &= ~AudioManager.FLAG_VIBRATE;
}
// Check if the ringer mode handles this adjustment. If it does we don't
// need to adjust the volume further.
//检查是否需要修改模式
final int result = checkForRingerModeChange(aliasIndex, direction, step,
streamState.mIsMuted, callingPackage, flags);
adjustVolume = (result & FLAG_ADJUST_VOLUME) != 0;
// If suppressing a volume adjustment in silent mode, display the UI hint
if ((result & AudioManager.FLAG_SHOW_SILENT_HINT) != 0) {
flags |= AudioManager.FLAG_SHOW_SILENT_HINT;
}
// If suppressing a volume down adjustment in vibrate mode, display the UI hint
if ((result & AudioManager.FLAG_SHOW_VIBRATE_HINT) != 0) {
flags |= AudioManager.FLAG_SHOW_VIBRATE_HINT;
}
}
...
}
private int checkForRingerModeChange(int oldIndex, int direction, int step, boolean isMuted,
String caller, int flags) {
int result = FLAG_ADJUST_VOLUME;
if (isPlatformTelevision() || mIsSingleVolume) {
return result;
}
int ringerMode = getRingerModeInternal();
switch (ringerMode) {
case RINGER_MODE_NORMAL://普通模式
if (direction == AudioManager.ADJUST_LOWER) {
if (mHasVibrator) {
// "step" is the delta in internal index units corresponding to a
// change of 1 in UI index units.
// Because of rounding when rescaling from one stream index range to its alias
// index range, we cannot simply test oldIndex == step:
// (step <= oldIndex < 2 * step) is equivalent to: (old UI index == 1)
if (step <= oldIndex && oldIndex < 2 * step) {
ringerMode = RINGER_MODE_VIBRATE;
mLoweredFromNormalToVibrateTime = SystemClock.uptimeMillis();
}
} else {
if (oldIndex == step && mVolumePolicy.volumeDownToEnterSilent) {
ringerMode = RINGER_MODE_SILENT;
}
}
} else if (mIsSingleVolume && (direction == AudioManager.ADJUST_TOGGLE_MUTE
|| direction == AudioManager.ADJUST_MUTE)) {
if (mHasVibrator) {
ringerMode = RINGER_MODE_VIBRATE;
} else {
ringerMode = RINGER_MODE_SILENT;
}
// Setting the ringer mode will toggle mute
result &= ~FLAG_ADJUST_VOLUME;
}
break;
case RINGER_MODE_VIBRATE://振动模式
if (!mHasVibrator) {
Log.e(TAG, "checkForRingerModeChange() current ringer mode is vibrate" +
"but no vibrator is present");
break;
}
if ((direction == AudioManager.ADJUST_LOWER)) {
// This is the case we were muted with the volume turned up
if (mIsSingleVolume && oldIndex >= 2 * step && isMuted) {
ringerMode = RINGER_MODE_NORMAL;
} else if (mPrevVolDirection != AudioManager.ADJUST_LOWER) {
if (mVolumePolicy.volumeDownToEnterSilent) {
final long diff = SystemClock.uptimeMillis()
- mLoweredFromNormalToVibrateTime;
if (diff > mVolumePolicy.vibrateToSilentDebounce
&& mRingerModeDelegate.canVolumeDownEnterSilent()) {
ringerMode = RINGER_MODE_SILENT;
}
} else {
result |= AudioManager.FLAG_SHOW_VIBRATE_HINT;
}
}
} else if (direction == AudioManager.ADJUST_RAISE
|| direction == AudioManager.ADJUST_TOGGLE_MUTE
|| direction == AudioManager.ADJUST_UNMUTE) {
//*****当设置为振动模式时,direction == AudioManager.ADJUST_UNMUTE满足,所以ringerMode被修改**
ringerMode = RINGER_MODE_NORMAL;
}
result &= ~FLAG_ADJUST_VOLUME;
break;
case RINGER_MODE_SILENT://无声模式
if (mIsSingleVolume && direction == AudioManager.ADJUST_LOWER && oldIndex >= 2 * step && isMuted) {
// This is the case we were muted with the volume turned up
ringerMode = RINGER_MODE_NORMAL;
} else if (direction == AudioManager.ADJUST_RAISE
|| direction == AudioManager.ADJUST_TOGGLE_MUTE
|| direction == AudioManager.ADJUST_UNMUTE) {
if (!mVolumePolicy.volumeUpToExitSilent) {
//******当设置为无声模式时,volumeUpToExitSilent为false,ringerMode不做修改**
result |= AudioManager.FLAG_SHOW_SILENT_HINT;
} else {
if (mHasVibrator && direction == AudioManager.ADJUST_RAISE) {
ringerMode = RINGER_MODE_VIBRATE;
} else {
// If we don't have a vibrator or they were toggling mute
// go straight back to normal.
ringerMode = RINGER_MODE_NORMAL;
}
}
}
result &= ~FLAG_ADJUST_VOLUME;
break;
default:
Log.e(TAG, "checkForRingerModeChange() wrong ringer mode: "+ringerMode);
break;
}
if (isAndroidNPlus(caller) && wouldToggleZenMode(ringerMode)
&& !mNm.isNotificationPolicyAccessGrantedForPackage(caller)
&& (flags & AudioManager.FLAG_FROM_KEY) == 0) {
throw new SecurityException("Not allowed to change Do Not Disturb state");
}
//进入模式修改
setRingerMode(ringerMode, TAG + ".checkForRingerModeChange", false /*external*/);
mPrevVolDirection = direction;
return result;
}
volumeUpToExitSilent说明:
/frameworks/base/media/java/android/media/VolumePolicy.java
public final class VolumePolicy implements Parcelable {
public static final VolumePolicy DEFAULT = new VolumePolicy(false, false, false, 400);
public VolumePolicy(boolean volumeDownToEnterSilent, boolean volumeUpToExitSilent,
boolean doNotDisturbWhenSilent, int vibrateToSilentDebounce) {
this.volumeDownToEnterSilent = volumeDownToEnterSilent;
this.volumeUpToExitSilent = volumeUpToExitSilent;//被设置为false
this.doNotDisturbWhenSilent = doNotDisturbWhenSilent;
this.vibrateToSilentDebounce = vibrateToSilentDebounce;
}
}
ringerModeInternal和ringerModeExternal区别
ringerModeInternal获取:adb shell settings get global mode_ringer
ringerModeExternal获取:audioManager.getRingerMode()