Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 50ced3f3 authored by John Spurlock's avatar John Spurlock
Browse files

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
parent e74d5d09
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -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);
    }
}
+63 −33
Original line number Diff line number Diff line
@@ -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:
        if (mPlatformType == AudioSystem.PLATFORM_TELEVISION) {
            ringerModeAffectedStreams = 0;
                break;
            default:
                ringerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_MUSIC);
                break;
        } 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);
                }
            }
        }
    }

    //==========================================================================================
+27 −8
Original line number Diff line number Diff line
@@ -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 {