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

Commit 24482018 authored by Eric Laurent's avatar Eric Laurent
Browse files

AudioService: fix various volume issues.

Fix various issues in adjustStreamVolume() related to stream type aliases
using different ranges.

Always Update last audible index on all streams sharing the same alias.

Add check on setRingerMode() to prevent setting mode to VIBRATE when no
vibrator is present.

Issue 6455831.

Change-Id: Id110e05d2f16e208e1e398922617bf31967b62db
parent 24938df9
Loading
Loading
Loading
Loading
+76 −56
Original line number Original line Diff line number Diff line
@@ -501,6 +501,24 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
        }
        }
    }
    }


    private void checkAllAliasStreamVolumes() {
        int numStreamTypes = AudioSystem.getNumStreamTypes();
        for (int streamType = 0; streamType < numStreamTypes; streamType++) {
            if (streamType != mStreamVolumeAlias[streamType]) {
                mStreamStates[streamType].
                                    setAllIndexes(mStreamStates[mStreamVolumeAlias[streamType]],
                                                  false /*lastAudible*/);
                mStreamStates[streamType].
                                    setAllIndexes(mStreamStates[mStreamVolumeAlias[streamType]],
                                                  true /*lastAudible*/);
            }
            // apply stream volume
            if (mStreamStates[streamType].muteCount() == 0) {
                mStreamStates[streamType].applyAllVolumes();
            }
        }
    }

    private void createStreamStates() {
    private void createStreamStates() {
        int numStreamTypes = AudioSystem.getNumStreamTypes();
        int numStreamTypes = AudioSystem.getNumStreamTypes();
        VolumeStreamState[] streams = mStreamStates = new VolumeStreamState[numStreamTypes];
        VolumeStreamState[] streams = mStreamStates = new VolumeStreamState[numStreamTypes];
@@ -509,23 +527,7 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
            streams[i] = new VolumeStreamState(System.VOLUME_SETTINGS[mStreamVolumeAlias[i]], i);
            streams[i] = new VolumeStreamState(System.VOLUME_SETTINGS[mStreamVolumeAlias[i]], i);
        }
        }


        // Correct stream index values for streams with aliases
        checkAllAliasStreamVolumes();
        for (int i = 0; i < numStreamTypes; i++) {
            int device = getDeviceForStream(i);
            if (mStreamVolumeAlias[i] != i) {
                int index = rescaleIndex(streams[i].getIndex(device, false  /* lastAudible */),
                                mStreamVolumeAlias[i],
                                i);
                synchronized (streams[i]) {
                    streams[i].mIndex.put(device, streams[i].getValidIndex(index));
                    streams[i].applyDeviceVolume(device);
                    index = rescaleIndex(streams[i].getIndex(device, true  /* lastAudible */),
                                mStreamVolumeAlias[i],
                                i);
                    streams[i].mLastAudibleIndex.put(device, streams[i].getValidIndex(index));
                }
            }
        }
    }
    }


    private void dumpStreamStates(PrintWriter pw) {
    private void dumpStreamStates(PrintWriter pw) {
@@ -679,10 +681,13 @@ public class AudioService extends IAudioService.Stub implements OnFinished {


        final int device = getDeviceForStream(streamTypeAlias);
        final int device = getDeviceForStream(streamTypeAlias);
        // get last audible index if stream is muted, current index otherwise
        // get last audible index if stream is muted, current index otherwise
        final int oldIndex = streamState.getIndex(device,
        final int aliasIndex = streamState.getIndex(device,
                                                  (streamState.muteCount() != 0) /* lastAudible */);
                                                  (streamState.muteCount() != 0) /* lastAudible */);
        boolean adjustVolume = true;
        boolean adjustVolume = true;


        // convert one UI step (+/-1) into a number of internal units on the stream alias
        int step = rescaleIndex(10, streamType, streamTypeAlias);

        // If either the client forces allowing ringer modes for this adjustment,
        // If either the client forces allowing ringer modes for this adjustment,
        // or the stream type is one that is affected by ringer modes
        // or the stream type is one that is affected by ringer modes
        if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
        if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
@@ -694,35 +699,30 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
            }
            }
            // Check if the ringer mode changes with this volume adjustment. If
            // Check if the ringer mode changes with this volume adjustment. If
            // it does, it will handle adjusting the volume, so we won't below
            // it does, it will handle adjusting the volume, so we won't below
            adjustVolume = checkForRingerModeChange(oldIndex, direction);
            adjustVolume = checkForRingerModeChange(aliasIndex, direction, step);
        }
        }


        // If stream is muted, adjust last audible index only
        // If stream is muted, adjust last audible index only
        int index;
        int index;
        final int oldIndex = mStreamStates[streamType].getIndex(device,
                (mStreamStates[streamType].muteCount() != 0) /* lastAudible */);

        if (streamState.muteCount() != 0) {
        if (streamState.muteCount() != 0) {
            if (adjustVolume) {
            if (adjustVolume) {
                // adjust volume on all stream types sharing the same alias otherwise a query
                // on last audible index for an alias would not give the correct value
                int numStreamTypes = AudioSystem.getNumStreamTypes();
                for (int i = numStreamTypes - 1; i >= 0; i--) {
                    if (mStreamVolumeAlias[i] == streamTypeAlias) {
                        VolumeStreamState s = mStreamStates[i];

                        s.adjustLastAudibleIndex(direction, device);
                // Post a persist volume msg
                // Post a persist volume msg
                // no need to persist volume on all streams sharing the same alias
                streamState.adjustLastAudibleIndex(direction * step, device);
                sendMsg(mAudioHandler,
                sendMsg(mAudioHandler,
                        MSG_PERSIST_VOLUME,
                        MSG_PERSIST_VOLUME,
                        SENDMSG_QUEUE,
                        SENDMSG_QUEUE,
                        PERSIST_LAST_AUDIBLE,
                        PERSIST_LAST_AUDIBLE,
                        device,
                        device,
                                s,
                        streamState,
                        PERSIST_DELAY);
                        PERSIST_DELAY);
            }
            }
                }
            index = mStreamStates[streamType].getIndex(device, true  /* lastAudible */);
            }
            index = streamState.getIndex(device, true  /* lastAudible */);
        } else {
        } else {
            if (adjustVolume && streamState.adjustIndex(direction, device)) {
            if (adjustVolume && streamState.adjustIndex(direction * step, device)) {
                // Post message to set system volume (it in turn will post a message
                // Post message to set system volume (it in turn will post a message
                // to persist). Do not change volume if stream is muted.
                // to persist). Do not change volume if stream is muted.
                sendMsg(mAudioHandler,
                sendMsg(mAudioHandler,
@@ -733,7 +733,7 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
                        streamState,
                        streamState,
                        0);
                        0);
            }
            }
            index = streamState.getIndex(device, false  /* lastAudible */);
            index = mStreamStates[streamType].getIndex(device, false  /* lastAudible */);
        }
        }


        sendVolumeUpdate(streamType, oldIndex, index, flags);
        sendVolumeUpdate(streamType, oldIndex, index, flags);
@@ -765,6 +765,8 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
        final int oldIndex = streamState.getIndex(device,
        final int oldIndex = streamState.getIndex(device,
                                                  (streamState.muteCount() != 0) /* lastAudible */);
                                                  (streamState.muteCount() != 0) /* lastAudible */);


        index = rescaleIndex(index * 10, streamType, mStreamVolumeAlias[streamType]);

        // setting volume on master stream type also controls silent mode
        // setting volume on master stream type also controls silent mode
        if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
        if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
                (mStreamVolumeAlias[streamType] == getMasterStreamType())) {
                (mStreamVolumeAlias[streamType] == getMasterStreamType())) {
@@ -783,11 +785,10 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
            setRingerMode(newRingerMode);
            setRingerMode(newRingerMode);
        }
        }


        index = rescaleIndex(index * 10, streamType, mStreamVolumeAlias[streamType]);
        setStreamVolumeInt(mStreamVolumeAlias[streamType], index, device, false, true);
        setStreamVolumeInt(mStreamVolumeAlias[streamType], index, device, false, true);
        // get last audible index if stream is muted, current index otherwise
        // get last audible index if stream is muted, current index otherwise
        index = streamState.getIndex(device,
        index = mStreamStates[streamType].getIndex(device,
                                     (streamState.muteCount() != 0) /* lastAudible */);
                                 (mStreamStates[streamType].muteCount() != 0) /* lastAudible */);


        sendVolumeUpdate(streamType, oldIndex, index, flags);
        sendVolumeUpdate(streamType, oldIndex, index, flags);
    }
    }
@@ -1089,7 +1090,9 @@ public class AudioService extends IAudioService.Stub implements OnFinished {


    /** @see AudioManager#setRingerMode(int) */
    /** @see AudioManager#setRingerMode(int) */
    public void setRingerMode(int ringerMode) {
    public void setRingerMode(int ringerMode) {
        ensureValidRingerMode(ringerMode);
        if ((ringerMode == AudioManager.RINGER_MODE_VIBRATE) && !mHasVibrator) {
            ringerMode = AudioManager.RINGER_MODE_SILENT;
        }
        if (ringerMode != getRingerMode()) {
        if (ringerMode != getRingerMode()) {
            setRingerModeInt(ringerMode, true);
            setRingerModeInt(ringerMode, true);
            // Send sticky broadcast
            // Send sticky broadcast
@@ -1599,13 +1602,11 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
                        streamState.mDeathHandlers.get(i).mute(false);
                        streamState.mDeathHandlers.get(i).mute(false);
                    }
                    }
                }
                }
                // apply stream volume
                if (streamState.muteCount() == 0) {
                    streamState.applyAllVolumes();
                }
            }
            }
        }
        }


        checkAllAliasStreamVolumes();

        // apply new ringer mode
        // apply new ringer mode
        setRingerModeInt(getRingerMode(), false);
        setRingerModeInt(getRingerMode(), false);
    }
    }
@@ -2015,20 +2016,25 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
     * adjusting volume. If so, this will set the proper ringer mode and volume
     * adjusting volume. If so, this will set the proper ringer mode and volume
     * indices on the stream states.
     * indices on the stream states.
     */
     */
    private boolean checkForRingerModeChange(int oldIndex, int direction) {
    private boolean checkForRingerModeChange(int oldIndex, int direction,  int step) {
        boolean adjustVolumeIndex = true;
        boolean adjustVolumeIndex = true;
        int ringerMode = getRingerMode();
        int ringerMode = getRingerMode();
        int uiIndex = (oldIndex + 5) / 10;


        switch (ringerMode) {
        switch (ringerMode) {
        case RINGER_MODE_NORMAL:
        case RINGER_MODE_NORMAL:
            if (direction == AudioManager.ADJUST_LOWER) {
            if (direction == AudioManager.ADJUST_LOWER) {
                if (mHasVibrator) {
                if (mHasVibrator) {
                    if (uiIndex == 1) {
                    // "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;
                        ringerMode = RINGER_MODE_VIBRATE;
                    }
                    }
                } else {
                } else {
                    if (uiIndex == 0 && mPrevVolDirection != AudioManager.ADJUST_LOWER) {
                    // (oldIndex < step) is equivalent to (old UI index == 0)
                    if ((oldIndex < step) && mPrevVolDirection != AudioManager.ADJUST_LOWER) {
                        ringerMode = RINGER_MODE_SILENT;
                        ringerMode = RINGER_MODE_SILENT;
                    }
                    }
                }
                }
@@ -2257,8 +2263,6 @@ public class AudioService extends IAudioService.Stub implements OnFinished {


            readSettings();
            readSettings();


            applyAllVolumes();

            mDeathHandlers = new ArrayList<VolumeDeathHandler>();
            mDeathHandlers = new ArrayList<VolumeDeathHandler>();
        }
        }


@@ -2369,7 +2373,7 @@ public class AudioService extends IAudioService.Stub implements OnFinished {


        public boolean adjustIndex(int deltaIndex, int device) {
        public boolean adjustIndex(int deltaIndex, int device) {
            return setIndex(getIndex(device,
            return setIndex(getIndex(device,
                                     false  /* lastAudible */) + deltaIndex * 10,
                                     false  /* lastAudible */) + deltaIndex,
                            device,
                            device,
                            true  /* lastAudible */);
                            true  /* lastAudible */);
        }
        }
@@ -2424,12 +2428,28 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
        }
        }


        public synchronized void setLastAudibleIndex(int index, int device) {
        public synchronized void setLastAudibleIndex(int index, int device) {
            // Apply change to all streams using this one as alias
            // if changing volume of current device, also change volume of current
            // device on aliased stream
            boolean currentDevice = (device == getDeviceForStream(mStreamType));
            int numStreamTypes = AudioSystem.getNumStreamTypes();
            for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
                if (streamType != mStreamType &&
                        mStreamVolumeAlias[streamType] == mStreamType) {
                    int scaledIndex = rescaleIndex(index, mStreamType, streamType);
                    mStreamStates[streamType].setLastAudibleIndex(scaledIndex, device);
                    if (currentDevice) {
                        mStreamStates[streamType].setLastAudibleIndex(scaledIndex,
                                                                   getDeviceForStream(streamType));
                    }
                }
            }
            mLastAudibleIndex.put(device, getValidIndex(index));
            mLastAudibleIndex.put(device, getValidIndex(index));
        }
        }


        public synchronized void adjustLastAudibleIndex(int deltaIndex, int device) {
        public synchronized void adjustLastAudibleIndex(int deltaIndex, int device) {
            setLastAudibleIndex(getIndex(device,
            setLastAudibleIndex(getIndex(device,
                                         true  /* lastAudible */) + deltaIndex * 10,
                                         true  /* lastAudible */) + deltaIndex,
                                device);
                                device);
        }
        }