Zen: Ringer mode integration fixes.
- Properly mute media + alarm streams in total silence. - Allow system components to update the "ringer mode affected" streams dynamically. - Improve dumpsys output for ringer mode streams (include names). - Remember last ringer mode properly when entering dnd via a volume down (so we can restore it properly when exiting). Bug: 20854925 Bug: 20950463 Bug: 20756527 Change-Id: I80afc1f639ff802c541020e25ade1b23e9997ef9
This commit is contained in:
@@ -43,6 +43,8 @@ public abstract class AudioManagerInternal {
|
||||
|
||||
public abstract int getVolumeControllerUid();
|
||||
|
||||
public abstract void updateRingerModeAffectedStreamsInternal();
|
||||
|
||||
public interface RingerModeDelegate {
|
||||
/** Called when external ringer mode is evaluated, returns the new internal ringer mode */
|
||||
int onSetRingerModeExternal(int ringerModeOld, int ringerModeNew, String caller,
|
||||
@@ -53,5 +55,7 @@ public abstract class AudioManagerInternal {
|
||||
int ringerModeExternal, VolumePolicy policy);
|
||||
|
||||
boolean canVolumeDownEnterSilent();
|
||||
|
||||
int getRingerModeAffectedStreams(int streams);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +43,6 @@ import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
@@ -1106,7 +1105,8 @@ public class AudioService extends IAudioService.Stub {
|
||||
}
|
||||
// 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);
|
||||
final int result = checkForRingerModeChange(aliasIndex, direction, step,
|
||||
streamState.mIsMuted);
|
||||
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) {
|
||||
@@ -1117,6 +1117,11 @@ public class AudioService extends IAudioService.Stub {
|
||||
flags |= AudioManager.FLAG_SHOW_VIBRATE_HINT;
|
||||
}
|
||||
}
|
||||
// If the ringermode is suppressing media, prevent changes
|
||||
if (streamTypeAlias == AudioSystem.STREAM_MUSIC
|
||||
&& (mRingerModeMutedStreams & (1 << AudioSystem.STREAM_MUSIC)) != 0) {
|
||||
adjustVolume = false;
|
||||
}
|
||||
|
||||
int oldIndex = mStreamStates[streamType].getIndex(device);
|
||||
|
||||
@@ -1796,20 +1801,14 @@ public class AudioService extends IAudioService.Stub {
|
||||
broadcastRingerMode(AudioManager.RINGER_MODE_CHANGED_ACTION, ringerMode);
|
||||
}
|
||||
|
||||
private void setRingerModeInt(int ringerMode, boolean persist) {
|
||||
final boolean change;
|
||||
synchronized(mSettingsLock) {
|
||||
change = mRingerMode != ringerMode;
|
||||
mRingerMode = ringerMode;
|
||||
}
|
||||
|
||||
private void muteRingerModeStreams() {
|
||||
// Mute stream if not previously muted by ringer mode and ringer mode
|
||||
// is not RINGER_MODE_NORMAL and stream is affected by ringer mode.
|
||||
// Unmute stream if previously muted by ringer mode and ringer mode
|
||||
// is RINGER_MODE_NORMAL or stream is not affected by ringer mode.
|
||||
int numStreamTypes = AudioSystem.getNumStreamTypes();
|
||||
final boolean ringerModeMute = ringerMode == AudioManager.RINGER_MODE_VIBRATE
|
||||
|| ringerMode == AudioManager.RINGER_MODE_SILENT;
|
||||
final boolean ringerModeMute = mRingerMode == AudioManager.RINGER_MODE_VIBRATE
|
||||
|| mRingerMode == AudioManager.RINGER_MODE_SILENT;
|
||||
for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
|
||||
final boolean isMuted = isStreamMutedByRingerMode(streamType);
|
||||
final boolean shouldMute = ringerModeMute && isStreamAffectedByRingerMode(streamType);
|
||||
@@ -1846,6 +1845,16 @@ public class AudioService extends IAudioService.Stub {
|
||||
mRingerModeMutedStreams |= (1 << streamType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void setRingerModeInt(int ringerMode, boolean persist) {
|
||||
final boolean change;
|
||||
synchronized(mSettingsLock) {
|
||||
change = mRingerMode != ringerMode;
|
||||
mRingerMode = ringerMode;
|
||||
}
|
||||
|
||||
muteRingerModeStreams();
|
||||
|
||||
// Post a persist ringer mode msg
|
||||
if (persist) {
|
||||
@@ -3084,30 +3093,19 @@ public class AudioService extends IAudioService.Stub {
|
||||
return (mRingerModeMutedStreams & (1 << streamType)) != 0;
|
||||
}
|
||||
|
||||
boolean updateRingerModeAffectedStreams() {
|
||||
int ringerModeAffectedStreams;
|
||||
// make sure settings for ringer mode are consistent with device type: non voice capable
|
||||
// devices (tablets) include media stream in silent mode whereas phones don't.
|
||||
ringerModeAffectedStreams = Settings.System.getIntForUser(mContentResolver,
|
||||
private boolean updateRingerModeAffectedStreams() {
|
||||
int ringerModeAffectedStreams = Settings.System.getIntForUser(mContentResolver,
|
||||
Settings.System.MODE_RINGER_STREAMS_AFFECTED,
|
||||
((1 << AudioSystem.STREAM_RING)|(1 << AudioSystem.STREAM_NOTIFICATION)|
|
||||
(1 << AudioSystem.STREAM_SYSTEM)|(1 << AudioSystem.STREAM_SYSTEM_ENFORCED)),
|
||||
UserHandle.USER_CURRENT);
|
||||
|
||||
// ringtone, notification and system streams are always affected by ringer mode
|
||||
ringerModeAffectedStreams |= (1 << AudioSystem.STREAM_RING)|
|
||||
(1 << AudioSystem.STREAM_NOTIFICATION)|
|
||||
(1 << AudioSystem.STREAM_SYSTEM);
|
||||
|
||||
switch (mPlatformType) {
|
||||
case AudioSystem.PLATFORM_TELEVISION:
|
||||
ringerModeAffectedStreams = 0;
|
||||
break;
|
||||
default:
|
||||
ringerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_MUSIC);
|
||||
break;
|
||||
if (mPlatformType == AudioSystem.PLATFORM_TELEVISION) {
|
||||
ringerModeAffectedStreams = 0;
|
||||
} else if (mRingerModeDelegate != null) {
|
||||
ringerModeAffectedStreams = mRingerModeDelegate
|
||||
.getRingerModeAffectedStreams(ringerModeAffectedStreams);
|
||||
}
|
||||
|
||||
synchronized (mCameraSoundForced) {
|
||||
if (mCameraSoundForced) {
|
||||
ringerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
|
||||
@@ -5541,13 +5539,35 @@ public class AudioService extends IAudioService.Stub {
|
||||
pw.println("\nRinger mode: ");
|
||||
pw.println("- mode (internal) = " + RINGER_MODE_NAMES[mRingerMode]);
|
||||
pw.println("- mode (external) = " + RINGER_MODE_NAMES[mRingerModeExternal]);
|
||||
pw.print("- ringer mode affected streams = 0x");
|
||||
pw.println(Integer.toHexString(mRingerModeAffectedStreams));
|
||||
pw.print("- ringer mode muted streams = 0x");
|
||||
pw.println(Integer.toHexString(mRingerModeMutedStreams));
|
||||
dumpRingerModeStreams(pw, "affected", mRingerModeAffectedStreams);
|
||||
dumpRingerModeStreams(pw, "muted", mRingerModeMutedStreams);
|
||||
pw.print("- delegate = "); pw.println(mRingerModeDelegate);
|
||||
}
|
||||
|
||||
private void dumpRingerModeStreams(PrintWriter pw, String type, int streams) {
|
||||
pw.print("- ringer mode "); pw.print(type); pw.print(" streams = 0x");
|
||||
pw.print(Integer.toHexString(streams));
|
||||
if (streams != 0) {
|
||||
pw.print(" (");
|
||||
boolean first = true;
|
||||
for (int i = 0; i < AudioSystem.STREAM_NAMES.length; i++) {
|
||||
final int stream = (1 << i);
|
||||
if ((streams & stream) != 0) {
|
||||
if (!first) pw.print(',');
|
||||
pw.print(AudioSystem.STREAM_NAMES[i]);
|
||||
streams &= ~stream;
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
if (streams != 0) {
|
||||
if (!first) pw.print(',');
|
||||
pw.print(streams);
|
||||
}
|
||||
pw.print(')');
|
||||
}
|
||||
pw.println();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
|
||||
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
|
||||
@@ -5780,6 +5800,7 @@ public class AudioService extends IAudioService.Stub {
|
||||
public void setRingerModeDelegate(RingerModeDelegate delegate) {
|
||||
mRingerModeDelegate = delegate;
|
||||
if (mRingerModeDelegate != null) {
|
||||
updateRingerModeAffectedStreams();
|
||||
setRingerModeInternal(getRingerModeInternal(), TAG + ".setRingerModeDelegate");
|
||||
}
|
||||
}
|
||||
@@ -5820,6 +5841,15 @@ public class AudioService extends IAudioService.Stub {
|
||||
public int getVolumeControllerUid() {
|
||||
return mControllerService.mUid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateRingerModeAffectedStreamsInternal() {
|
||||
synchronized (mSettingsLock) {
|
||||
if (updateRingerModeAffectedStreams()) {
|
||||
setRingerModeInt(getRingerModeInternal(), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================================
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
package com.android.server.notification;
|
||||
|
||||
import static android.media.AudioAttributes.USAGE_ALARM;
|
||||
import static android.media.AudioAttributes.USAGE_MEDIA;
|
||||
import static android.media.AudioAttributes.USAGE_NOTIFICATION;
|
||||
import static android.media.AudioAttributes.USAGE_NOTIFICATION_RINGTONE;
|
||||
|
||||
@@ -32,6 +30,7 @@ import android.content.res.XmlResourceParser;
|
||||
import android.database.ContentObserver;
|
||||
import android.media.AudioManager;
|
||||
import android.media.AudioManagerInternal;
|
||||
import android.media.AudioSystem;
|
||||
import android.media.VolumePolicy;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
@@ -41,7 +40,6 @@ import android.os.Message;
|
||||
import android.os.UserHandle;
|
||||
import android.provider.Settings.Global;
|
||||
import android.service.notification.IConditionListener;
|
||||
import android.service.notification.NotificationListenerService;
|
||||
import android.service.notification.ZenModeConfig;
|
||||
import android.service.notification.ZenModeConfig.EventInfo;
|
||||
import android.service.notification.ZenModeConfig.ScheduleInfo;
|
||||
@@ -300,6 +298,7 @@ public class ZenModeHelper {
|
||||
if (zen == mZenMode) return false;
|
||||
ZenLog.traceSetZenMode(zen, reason);
|
||||
mZenMode = zen;
|
||||
updateRingerModeAffectedStreams();
|
||||
setZenModeSetting(mZenMode);
|
||||
if (setRingerMode) {
|
||||
applyZenToRingerMode();
|
||||
@@ -309,6 +308,12 @@ public class ZenModeHelper {
|
||||
return true;
|
||||
}
|
||||
|
||||
private void updateRingerModeAffectedStreams() {
|
||||
if (mAudioManager != null) {
|
||||
mAudioManager.updateRingerModeAffectedStreamsInternal();
|
||||
}
|
||||
}
|
||||
|
||||
private int computeZenMode(ArraySet<ZenRule> automaticRulesOut) {
|
||||
if (mConfig == null) return Global.ZEN_MODE_OFF;
|
||||
if (mConfig.manualRule != null) return mConfig.manualRule.zenMode;
|
||||
@@ -334,11 +339,6 @@ public class ZenModeHelper {
|
||||
final boolean muteCalls = zen && !mConfig.allowCalls && !mConfig.allowRepeatCallers
|
||||
|| mEffectsSuppressed;
|
||||
applyRestrictions(muteCalls, USAGE_NOTIFICATION_RINGTONE);
|
||||
|
||||
// alarm/media restrictions
|
||||
final boolean zenNone = mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS;
|
||||
applyRestrictions(zenNone, USAGE_ALARM);
|
||||
applyRestrictions(zenNone, USAGE_MEDIA);
|
||||
}
|
||||
|
||||
private void applyRestrictions(boolean mute, int usage) {
|
||||
@@ -523,6 +523,7 @@ public class ZenModeHelper {
|
||||
&& mZenMode != Global.ZEN_MODE_ALARMS) {
|
||||
newZen = Global.ZEN_MODE_ALARMS;
|
||||
}
|
||||
mPreviousRingerMode = ringerModeOld;
|
||||
}
|
||||
break;
|
||||
case AudioManager.RINGER_MODE_VIBRATE:
|
||||
@@ -587,6 +588,24 @@ public class ZenModeHelper {
|
||||
public boolean canVolumeDownEnterSilent() {
|
||||
return mZenMode == Global.ZEN_MODE_OFF;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRingerModeAffectedStreams(int streams) {
|
||||
// ringtone, notification and system streams are always affected by ringer mode
|
||||
streams |= (1 << AudioSystem.STREAM_RING) |
|
||||
(1 << AudioSystem.STREAM_NOTIFICATION) |
|
||||
(1 << AudioSystem.STREAM_SYSTEM);
|
||||
|
||||
// alarm and music streams are only affected by ringer mode when in total silence
|
||||
if (mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS) {
|
||||
streams |= (1 << AudioSystem.STREAM_ALARM) |
|
||||
(1 << AudioSystem.STREAM_MUSIC);
|
||||
} else {
|
||||
streams &= ~((1 << AudioSystem.STREAM_ALARM) |
|
||||
(1 << AudioSystem.STREAM_MUSIC));
|
||||
}
|
||||
return streams;
|
||||
}
|
||||
}
|
||||
|
||||
private final class SettingsObserver extends ContentObserver {
|
||||
|
||||
Reference in New Issue
Block a user