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

Commit 8d245a42 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "AudioService: Fix mute issue when changing audio routes"

parents 968e2483 1def04cc
Loading
Loading
Loading
Loading
+116 −34
Original line number Diff line number Diff line
@@ -285,6 +285,8 @@ public class AudioService extends IAudioService.Stub
    private static final int MSG_PLAYBACK_CONFIG_CHANGE = 29;
    private static final int MSG_BROADCAST_MICROPHONE_MUTE = 30;
    private static final int MSG_CHECK_MODE_FOR_UID = 31;
    private static final int MSG_STREAM_DEVICES_CHANGED = 32;
    private static final int MSG_UPDATE_VOLUME_STATES_FOR_DEVICE = 33;
    // start of messages handled under wakelock
    //   these messages can only be queued, i.e. sent with queueMsgUnderWakeLock(),
    //   and not with sendMsg(..., ..., SENDMSG_QUEUE, ...)
@@ -1283,7 +1285,6 @@ public class AudioService extends IAudioService.Stub
            }

            if (isPlatformTelevision()) {
                checkAddAllFixedVolumeDevices(AudioSystem.DEVICE_OUT_HDMI, caller);
                synchronized (mHdmiClientLock) {
                    if (mHdmiManager != null && mHdmiPlaybackClient != null) {
                        updateHdmiCecSinkLocked(mHdmiCecSink | false);
@@ -1303,9 +1304,50 @@ public class AudioService extends IAudioService.Stub
        }
    }

    private void checkAddAllFixedVolumeDevices(int device, String caller) {
    /**
     * Asynchronously update volume states for the given device.
     *
     * @param device a single audio device, ensure that this is not a devices bitmask
     * @param caller caller of this method
     */
    private void postUpdateVolumeStatesForAudioDevice(int device, String caller) {
        sendMsg(mAudioHandler,
                MSG_UPDATE_VOLUME_STATES_FOR_DEVICE,
                SENDMSG_QUEUE, device /*arg1*/, 0 /*arg2*/, caller /*obj*/,
                0 /*delay*/);
    }

    /**
     * Update volume states for the given device.
     *
     * This will initialize the volume index if no volume index is available.
     * If the device is the currently routed device, fixed/full volume policies will be applied.
     *
     * @param device a single audio device, ensure that this is not a devices bitmask
     * @param caller caller of this method
     */
    private void onUpdateVolumeStatesForAudioDevice(int device, String caller) {
        final int numStreamTypes = AudioSystem.getNumStreamTypes();
        synchronized (mSettingsLock) {
            synchronized (VolumeStreamState.class) {
                for (int streamType = 0; streamType < numStreamTypes; streamType++) {
                    updateVolumeStates(device, streamType, caller);
                }
            }
        }
    }

    /**
     * Update volume states for the given device and given stream.
     *
     * This will initialize the volume index if no volume index is available.
     * If the device is the currently routed device, fixed/full volume policies will be applied.
     *
     * @param device a single audio device, ensure that this is not a devices bitmask
     * @param streamType streamType to be updated
     * @param caller caller of this method
     */
    private void updateVolumeStates(int device, int streamType, String caller) {
        if (!mStreamStates[streamType].hasIndexForDevice(device)) {
            // set the default value, if device is affected by a full/fix/abs volume rule, it
            // will taken into account in checkFixedVolumeDevices()
@@ -1314,14 +1356,22 @@ public class AudioService extends IAudioService.Stub
                            .getIndex(AudioSystem.DEVICE_OUT_DEFAULT),
                    device, caller, true /*hasModifyAudioSettings*/);
        }

        // Check if device to be updated is routed for the given audio stream
        List<AudioDeviceAttributes> devicesForAttributes = getDevicesForAttributesInt(
                new AudioAttributes.Builder().setInternalLegacyStreamType(streamType).build());
        for (AudioDeviceAttributes deviceAttributes : devicesForAttributes) {
            if (deviceAttributes.getType() == AudioDeviceInfo.convertInternalDeviceToDeviceType(
                    device)) {
                mStreamStates[streamType].checkFixedVolumeDevices();

            // Unmute streams if device is full volume
            if (mFullVolumeDevices.contains(device)) {
                // Unmute streams if required and device is full volume
                if (isStreamMute(streamType) && mFullVolumeDevices.contains(device)) {
                    mStreamStates[streamType].mute(false);
                }
            }
        }
    }

    private void checkAllFixedVolumeDevices()
    {
@@ -1868,8 +1918,13 @@ public class AudioService extends IAudioService.Stub
    /** @see AudioManager#getDevicesForAttributes(AudioAttributes) */
    public @NonNull ArrayList<AudioDeviceAttributes> getDevicesForAttributes(
            @NonNull AudioAttributes attributes) {
        Objects.requireNonNull(attributes);
        enforceModifyAudioRoutingPermission();
        return getDevicesForAttributesInt(attributes);
    }

    protected @NonNull ArrayList<AudioDeviceAttributes> getDevicesForAttributesInt(
            @NonNull AudioAttributes attributes) {
        Objects.requireNonNull(attributes);
        return AudioSystem.getDevicesForAttributes(attributes);
    }

@@ -4912,11 +4967,21 @@ public class AudioService extends IAudioService.Stub
        }
    }

    private void observeDevicesForStreams(int skipStream) {
    private void onObserveDevicesForAllStreams(int skipStream) {
        synchronized (mSettingsLock) {
            synchronized (VolumeStreamState.class) {
                for (int stream = 0; stream < mStreamStates.length; stream++) {
                    if (stream != skipStream) {
                    mStreamStates[stream].observeDevicesForStream_syncVSS(false /*checkOthers*/);
                        int devices = mStreamStates[stream].observeDevicesForStream_syncVSS(
                                false /*checkOthers*/);

                        Set<Integer> devicesSet = AudioSystem.generateAudioDeviceTypesSet(devices);
                        for (Integer device : devicesSet) {
                            // Update volume states for devices routed for the stream
                            updateVolumeStates(device, stream,
                                    "AudioService#onObserveDevicesForAllStreams");
                        }
                    }
                }
            }
        }
@@ -4925,16 +4990,18 @@ public class AudioService extends IAudioService.Stub
    /** only public for mocking/spying, do not call outside of AudioService */
    @VisibleForTesting
    public void postObserveDevicesForAllStreams() {
        postObserveDevicesForAllStreams(-1);
    }

    /** only public for mocking/spying, do not call outside of AudioService */
    @VisibleForTesting
    public void postObserveDevicesForAllStreams(int skipStream) {
        sendMsg(mAudioHandler,
                MSG_OBSERVE_DEVICES_FOR_ALL_STREAMS,
                SENDMSG_QUEUE, 0 /*arg1*/, 0 /*arg2*/, null /*obj*/,
                SENDMSG_QUEUE, skipStream /*arg1*/, 0 /*arg2*/, null /*obj*/,
                0 /*delay*/);
    }

    private void onObserveDevicesForAllStreams() {
        observeDevicesForStreams(-1);
    }

    /**
     * @see AudioManager#setDeviceVolumeBehavior(AudioDeviceAttributes, int)
     * @param device the audio device to be affected
@@ -4985,7 +5052,8 @@ public class AudioService extends IAudioService.Stub
                      + Integer.toHexString(audioSystemDeviceOut) + " from:" + caller));
        // make sure we have a volume entry for this device, and that volume is updated according
        // to volume behavior
        checkAddAllFixedVolumeDevices(audioSystemDeviceOut, "setDeviceVolumeBehavior:" + caller);
        postUpdateVolumeStatesForAudioDevice(audioSystemDeviceOut,
                "setDeviceVolumeBehavior:" + caller);
    }

    /**
@@ -5616,6 +5684,7 @@ public class AudioService extends IAudioService.Stub
            }
        }

        @GuardedBy("VolumeStreamState.class")
        public int observeDevicesForStream_syncVSS(boolean checkOthers) {
            if (!mSystemServer.isPrivileged()) {
                return AudioSystem.DEVICE_NONE;
@@ -5628,15 +5697,19 @@ public class AudioService extends IAudioService.Stub
            mObservedDevices = devices;
            if (checkOthers) {
                // one stream's devices have changed, check the others
                observeDevicesForStreams(mStreamType);
                postObserveDevicesForAllStreams(mStreamType);
            }
            // log base stream changes to the event log
            if (mStreamVolumeAlias[mStreamType] == mStreamType) {
                EventLogTags.writeStreamDevicesChanged(mStreamType, prevDevices, devices);
            }
            sendBroadcastToAll(mStreamDevicesChanged
                    .putExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_DEVICES, prevDevices)
                    .putExtra(AudioManager.EXTRA_VOLUME_STREAM_DEVICES, devices));
            // send STREAM_DEVICES_CHANGED_ACTION on the message handler so it is scheduled after
            // the postObserveDevicesForStreams is handled
            sendMsg(mAudioHandler,
                    MSG_STREAM_DEVICES_CHANGED,
                    SENDMSG_QUEUE, prevDevices /*arg1*/, devices /*arg2*/,
                    // ok to send reference to this object, it is final
                    mStreamDevicesChanged /*obj*/, 0 /*delay*/);
            return devices;
        }

@@ -6408,7 +6481,7 @@ public class AudioService extends IAudioService.Stub
                    break;

                case MSG_OBSERVE_DEVICES_FOR_ALL_STREAMS:
                    onObserveDevicesForAllStreams();
                    onObserveDevicesForAllStreams(/*skipStream*/ msg.arg1);
                    break;

                case MSG_HDMI_VOLUME_CHECK:
@@ -6451,6 +6524,16 @@ public class AudioService extends IAudioService.Stub
                        mModeLogger.log(new PhoneStateEvent(h.getPackage(), h.getPid()));
                    }
                    break;

                case MSG_STREAM_DEVICES_CHANGED:
                    sendBroadcastToAll(((Intent) msg.obj)
                            .putExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_DEVICES, msg.arg1)
                            .putExtra(AudioManager.EXTRA_VOLUME_STREAM_DEVICES, msg.arg2));
                    break;

                case MSG_UPDATE_VOLUME_STATES_FOR_DEVICE:
                    onUpdateVolumeStatesForAudioDevice(msg.arg1, (String) msg.obj);
                    break;
            }
        }
    }
@@ -7207,11 +7290,10 @@ public class AudioService extends IAudioService.Stub
                // HDMI output
                removeAudioSystemDeviceOutFromFullVolumeDevices(AudioSystem.DEVICE_OUT_HDMI);
            }
        }

        checkAddAllFixedVolumeDevices(AudioSystem.DEVICE_OUT_HDMI,
            postUpdateVolumeStatesForAudioDevice(AudioSystem.DEVICE_OUT_HDMI,
                    "HdmiPlaybackClient.DisplayStatusCallback");
        }
    }

    private class MyHdmiControlStatusChangeListenerCallback
            implements HdmiControlManager.HdmiControlStatusChangeListener {