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

Commit b6e19e3e authored by John Spurlock's avatar John Spurlock
Browse files

AudioService: Define minimum levels for volume streams.

 - Set a floor of 1 for voice call + bluetooth sco, otherwise 0.
 - All api calls validated to ensure a floor of the min level.
 - Volume UI updated to shift the seekbar by the min value.
 - Remove duplicate static max method in AudioService.
 - Ensure streams with a min level > 0 are not considered muteable.

Bug: 19260237
Change-Id: I213180c9c277f51bd3897b7f777e5f88ed1db125
parent 63b9e820
Loading
Loading
Loading
Loading
+18 −0
Original line number Diff line number Diff line
@@ -865,6 +865,24 @@ public class AudioManager {
        }
    }

    /**
     * Returns the minimum volume index for a particular stream.
     *
     * @param streamType The stream type whose minimum volume index is returned.
     * @return The minimum valid volume index for the stream.
     * @see #getStreamVolume(int)
     * @hide
     */
    public int getStreamMinVolume(int streamType) {
        IAudioService service = getService();
        try {
            return service.getStreamMinVolume(streamType);
        } catch (RemoteException e) {
            Log.e(TAG, "Dead object in getStreamMinVolume", e);
            return 0;
        }
    }

    /**
     * Returns the current volume index for a particular stream.
     *
+2 −0
Original line number Diff line number Diff line
@@ -59,6 +59,8 @@ interface IAudioService {

    int getStreamVolume(int streamType);

    int getStreamMinVolume(int streamType);

    int getStreamMaxVolume(int streamType);

    int getLastAudibleStreamVolume(int streamType);
+14 −28
Original line number Diff line number Diff line
@@ -253,6 +253,7 @@ public class VolumePanel extends Handler implements DemoMode {
        int iconRes;
        int iconMuteRes;
        int iconSuppressedRes;
        int minVolume;
    }

    // Synchronize when accessing this
@@ -558,6 +559,14 @@ public class VolumePanel extends Handler implements DemoMode {
        }
    }

    private int getStreamMinVolume(int streamType) {
        if (streamType == STREAM_REMOTE_MUSIC) {
            return 0;
        } else {
            return mAudioManager.getStreamMinVolume(streamType);
        }
    }

    private int getStreamMaxVolume(int streamType) {
        if (streamType == STREAM_REMOTE_MUSIC) {
            if (mStreamControls != null) {
@@ -661,9 +670,8 @@ public class VolumePanel extends Handler implements DemoMode {
                    }
                });
            }
            final int plusOne = (streamType == AudioSystem.STREAM_BLUETOOTH_SCO ||
                    streamType == AudioSystem.STREAM_VOICE_CALL) ? 1 : 0;
            sc.seekbarView.setMax(getStreamMaxVolume(streamType) + plusOne);
            sc.minVolume = getStreamMinVolume(streamType);
            sc.seekbarView.setMax(getStreamMaxVolume(streamType) - sc.minVolume);
            sc.seekbarView.setOnSeekBarChangeListener(mSeekListener);
            sc.seekbarView.setTag(sc);
            mStreamControls.put(streamType, sc);
@@ -706,7 +714,7 @@ public class VolumePanel extends Handler implements DemoMode {
        if (progress < 0) {
            progress = getStreamVolume(sc.streamType);
        }
        sc.seekbarView.setProgress(progress);
        sc.seekbarView.setProgress(progress - sc.minVolume);
        if (isRinger) {
            mLastRingerProgress = progress;
        }
@@ -1034,7 +1042,7 @@ public class VolumePanel extends Handler implements DemoMode {

        // get max volume for progress bar

        int max = getStreamMaxVolume(streamType);
        int max = getStreamMaxVolume(streamType) - getStreamMinVolume(streamType);
        StreamControl sc = mStreamControls.get(streamType);

        switch (streamType) {
@@ -1061,17 +1069,6 @@ public class VolumePanel extends Handler implements DemoMode {
                break;
            }

            case AudioManager.STREAM_VOICE_CALL: {
                /*
                 * For in-call voice call volume, there is no inaudible volume.
                 * Rescale the UI control so the progress bar doesn't go all
                 * the way to zero and don't show the mute icon.
                 */
                index++;
                max++;
                break;
            }

            case AudioManager.STREAM_ALARM: {
                break;
            }
@@ -1085,17 +1082,6 @@ public class VolumePanel extends Handler implements DemoMode {
                break;
            }

            case AudioManager.STREAM_BLUETOOTH_SCO: {
                /*
                 * For in-call voice call volume, there is no inaudible volume.
                 * Rescale the UI control so the progress bar doesn't go all
                 * the way to zero and don't show the mute icon.
                 */
                index++;
                max++;
                break;
            }

            case STREAM_REMOTE_MUSIC: {
                if (controller == null && sc != null) {
                    // If we weren't passed one try using the last one set.
@@ -1493,7 +1479,7 @@ public class VolumePanel extends Handler implements DemoMode {
            final Object tag = seekBar.getTag();
            if (fromUser && tag instanceof StreamControl) {
                StreamControl sc = (StreamControl) tag;
                setStreamVolume(sc, progress,
                setStreamVolume(sc, progress + sc.minVolume,
                        AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_VIBRATE);
            }
            resetTimeout();
+51 −15
Original line number Diff line number Diff line
@@ -249,7 +249,7 @@ public class AudioService extends IAudioService.Stub {
     * uses soundpool (second column) */
    private final int[][] SOUND_EFFECT_FILES_MAP = new int[AudioManager.NUM_SOUND_EFFECTS][2];

   /** @hide Maximum volume index values for audio streams */
   /** Maximum volume index values for audio streams */
    private static int[] MAX_STREAM_VOLUME = new int[] {
        5,  // STREAM_VOICE_CALL
        7,  // STREAM_SYSTEM
@@ -263,6 +263,20 @@ public class AudioService extends IAudioService.Stub {
        15  // STREAM_TTS
    };

    /** Minimum volume index values for audio streams */
    private static int[] MIN_STREAM_VOLUME = new int[] {
        1,  // STREAM_VOICE_CALL
        0,  // STREAM_SYSTEM
        0,  // STREAM_RING
        0,  // STREAM_MUSIC
        0,  // STREAM_ALARM
        0,  // STREAM_NOTIFICATION
        1,  // STREAM_BLUETOOTH_SCO
        0,  // STREAM_SYSTEM_ENFORCED
        0,  // STREAM_DTMF
        0   // STREAM_TTS
    };

    /* mStreamVolumeAlias[] indicates for each stream if it uses the volume settings
     * of another stream: This avoids multiplying the volume settings for hidden
     * stream types that follow other stream behavior for volume settings
@@ -565,7 +579,7 @@ public class AudioService extends IAudioService.Stub {
        Vibrator vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
        mHasVibrator = vibrator == null ? false : vibrator.hasVibrator();

       // Intialized volume
        // Initialize volume
        int maxVolume = SystemProperties.getInt("ro.config.vc_call_vol_steps",
                MAX_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL]);
        if (maxVolume != MAX_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL]) {
@@ -586,9 +600,6 @@ public class AudioService extends IAudioService.Stub {

        createAudioSystemThread();

        mMediaFocusControl = new MediaFocusControl(mAudioHandler.getLooper(),
                mContext, mVolumeController, this);

        AudioSystem.setErrorCallback(mAudioSystemCallback);

        boolean cameraSoundForced = readCameraSoundForced();
@@ -620,6 +631,9 @@ public class AudioService extends IAudioService.Stub {
        mSettingsObserver = new SettingsObserver();
        createStreamStates();

        mMediaFocusControl = new MediaFocusControl(mAudioHandler.getLooper(),
                mContext, mVolumeController, this);

        readAndSetLowRamDevice();

        // Call setRingerModeInt() to apply correct mute
@@ -765,6 +779,16 @@ public class AudioService extends IAudioService.Stub {
        mStreamStates[streamType].checkFixedVolumeDevices();
    }

    private void checkMuteAffectedStreams() {
        // any stream with a min level > 0 is not muteable by definition
        for (int i = 0; i < mStreamStates.length; i++) {
            final VolumeStreamState vss = mStreamStates[i];
            if (vss.mIndexMin > 0) {
                mMuteAffectedStreams &= ~(1 << vss.mStreamType);
            }
        }
    }

    private void createStreamStates() {
        int numStreamTypes = AudioSystem.getNumStreamTypes();
        VolumeStreamState[] streams = mStreamStates = new VolumeStreamState[numStreamTypes];
@@ -775,6 +799,7 @@ public class AudioService extends IAudioService.Stub {

        checkAllFixedVolumeDevices();
        checkAllAliasStreamVolumes();
        checkMuteAffectedStreams();
    }

    private void dumpStreamStates(PrintWriter pw) {
@@ -1617,10 +1642,6 @@ public class AudioService extends IAudioService.Stub {
        setMasterMuteInternal(mute, flags, callingPackage, Binder.getCallingUid());
    }

    protected static int getMaxStreamVolume(int streamType) {
        return MAX_STREAM_VOLUME[streamType];
    }

    /** @see AudioManager#getStreamVolume(int) */
    public int getStreamVolume(int streamType) {
        ensureValidStreamType(streamType);
@@ -1646,6 +1667,12 @@ public class AudioService extends IAudioService.Stub {
        return (mStreamStates[streamType].getMaxIndex() + 5) / 10;
    }

    /** @see AudioManager#getStreamMinVolume(int) */
    public int getStreamMinVolume(int streamType) {
        ensureValidStreamType(streamType);
        return (mStreamStates[streamType].getMinIndex() + 5) / 10;
    }

    /** Get last audible volume before stream was muted. */
    public int getLastAudibleStreamVolume(int streamType) {
        ensureValidStreamType(streamType);
@@ -2279,6 +2306,7 @@ public class AudioService extends IAudioService.Stub {

        checkAllFixedVolumeDevices();
        checkAllAliasStreamVolumes();
        checkMuteAffectedStreams();

        synchronized (mSafeMediaVolumeState) {
            mMusicActiveMs = MathUtils.constrain(Settings.Secure.getIntForUser(mContentResolver,
@@ -3370,10 +3398,12 @@ public class AudioService extends IAudioService.Stub {
    //  5         mCameraSoundForced
    public class VolumeStreamState {
        private final int mStreamType;
        private final int mIndexMin;
        private final int mIndexMax;

        private boolean mIsMuted;
        private String mVolumeIndexSettingName;
        private int mIndexMax;

        private final SparseIntArray mIndexMap = new SparseIntArray(8);
        private final Intent mVolumeChanged;

@@ -3382,9 +3412,9 @@ public class AudioService extends IAudioService.Stub {
            mVolumeIndexSettingName = settingName;

            mStreamType = streamType;
            mIndexMax = MAX_STREAM_VOLUME[streamType];
            AudioSystem.initStreamVolume(streamType, 0, mIndexMax);
            mIndexMax *= 10;
            mIndexMin = MIN_STREAM_VOLUME[streamType] * 10;
            mIndexMax = MAX_STREAM_VOLUME[streamType] * 10;
            AudioSystem.initStreamVolume(streamType, mIndexMin / 10, mIndexMax / 10);

            readSettings();
            mVolumeChanged = new Intent(AudioManager.VOLUME_CHANGED_ACTION);
@@ -3564,6 +3594,10 @@ public class AudioService extends IAudioService.Stub {
            return mIndexMax;
        }

        public int getMinIndex() {
            return mIndexMin;
        }

        public void setAllIndexes(VolumeStreamState srcStream, String caller) {
            synchronized (VolumeStreamState.class) {
                int srcStreamType = srcStream.getStreamType();
@@ -3643,8 +3677,8 @@ public class AudioService extends IAudioService.Stub {
        }

        private int getValidIndex(int index) {
            if (index < 0) {
                return 0;
            if (index < mIndexMin) {
                return mIndexMin;
            } else if (mUseFixedVolume || index > mIndexMax) {
                return mIndexMax;
            }
@@ -3655,6 +3689,8 @@ public class AudioService extends IAudioService.Stub {
        private void dump(PrintWriter pw) {
            pw.print("   Muted: ");
            pw.println(mIsMuted);
            pw.print("   Min: ");
            pw.println((mIndexMin + 5) / 10);
            pw.print("   Max: ");
            pw.println((mIndexMax + 5) / 10);
            pw.print("   Current: ");
+2 −3
Original line number Diff line number Diff line
@@ -102,9 +102,8 @@ public class MediaFocusControl implements OnFinished {

        PowerManager pm = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
        mMediaEventWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "handleMediaEvent");
        mMainRemote = new RemotePlaybackState(-1,
                AudioService.getMaxStreamVolume(AudioManager.STREAM_MUSIC),
                AudioService.getMaxStreamVolume(AudioManager.STREAM_MUSIC));
        int maxMusicLevel = as.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
        mMainRemote = new RemotePlaybackState(-1, maxMusicLevel, maxMusicLevel);

        // Register for phone state monitoring
        TelephonyManager tmgr = (TelephonyManager)