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:
John Spurlock
2015-05-11 16:00:09 -04:00
parent e74d5d09e1
commit 50ced3f323
3 changed files with 94 additions and 41 deletions

View File

@@ -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);
}
}

View File

@@ -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);
}
}
}
}
//==========================================================================================

View File

@@ -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 {