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

Commit 5bbcd44c authored by Jean-Michel Trivi's avatar Jean-Michel Trivi
Browse files

AudioService: async volume updates from DeviceInventory

Make VolumeStreamState private to AudioService, and don't let
  AudioDeviceBroker, AudioDeviceInventory manipulate it. Only
  let them post messages on AudioService message handler to
  access them.
Refactor methods to set a volume index and observe devices
  from AudioDeviceInventory to AudioService to be asynchronous.

Bug: 130686447
Bug: 129163231
Test: verify volume is last used when connecting A2DP or hearing aid
Change-Id: I356af79213f4c21ed4ebaf86922fbbd9bf48a892
parent fb3c3679
Loading
Loading
Loading
Loading
+13 −9
Original line number Diff line number Diff line
@@ -43,7 +43,6 @@ import android.util.Log;

import com.android.internal.annotations.GuardedBy;

import java.util.ArrayList;

/** @hide */
/*package*/ final class AudioDeviceBroker {
@@ -376,24 +375,29 @@ import java.util.ArrayList;
        mAudioService.postAccessoryPlugMediaUnmute(device);
    }

    /*package*/ AudioService.VolumeStreamState getStreamState(int streamType) {
        return mAudioService.getStreamState(streamType);
    /*package*/ int getVssVolumeForDevice(int streamType, int device) {
        return mAudioService.getVssVolumeForDevice(streamType, device);
    }

    /*package*/ ArrayList<AudioService.SetModeDeathHandler> getSetModeDeathHandlers() {
        return mAudioService.mSetModeDeathHandlers;
    /*package*/ int getModeOwnerPid() {
        return mAudioService.getModeOwnerPid();
    }

    /*package*/ int getDeviceForStream(int streamType) {
        return mAudioService.getDeviceForStream(streamType);
    }

    /*package*/ void setDeviceVolume(AudioService.VolumeStreamState streamState, int device) {
        mAudioService.setDeviceVolume(streamState, device);
    /*package*/ void postApplyVolumeOnDevice(int streamType, int device, String caller) {
        mAudioService.postApplyVolumeOnDevice(streamType, device, caller);
    }

    /*packages*/ void observeDevicesForAllStreams() {
        mAudioService.observeDevicesForAllStreams();
    /*package*/ void postSetVolumeIndexOnDevice(int streamType, int vssVolIndex, int device,
                                                String caller) {
        mAudioService.postSetVolumeIndexOnDevice(streamType, vssVolIndex, device, caller);
    }

    /*packages*/ void postObserveDevicesForAllStreams() {
        mAudioService.postObserveDevicesForAllStreams();
    }

    /*package*/ boolean isInCommunication() {
+13 −23
Original line number Diff line number Diff line
@@ -198,14 +198,10 @@ public final class AudioDeviceInventory {
                    }
                }
                if (a2dpVolume != -1) {
                    AudioService.VolumeStreamState streamState =
                            mDeviceBroker.getStreamState(AudioSystem.STREAM_MUSIC);
                    // Convert index to internal representation in VolumeStreamState
                    a2dpVolume = a2dpVolume * 10;
                    streamState.setIndex(a2dpVolume, AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
                            "onSetA2dpSinkConnectionState");
                    mDeviceBroker.setDeviceVolume(
                            streamState, AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP);
                    mDeviceBroker.postSetVolumeIndexOnDevice(AudioSystem.STREAM_MUSIC,
                            // convert index to internal representation in VolumeStreamState
                            a2dpVolume * 10,
                            AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, "onSetA2dpSinkConnectionState");
                }
                makeA2dpDeviceAvailable(address, BtHelper.getName(btDevice),
                        "onSetA2dpSinkConnectionState", a2dpCodec);
@@ -302,14 +298,11 @@ public final class AudioDeviceInventory {
            if (event == BtHelper.EVENT_ACTIVE_DEVICE_CHANGE) {
                // Device is connected
                if (a2dpVolume != -1) {
                    final AudioService.VolumeStreamState streamState =
                            mDeviceBroker.getStreamState(AudioSystem.STREAM_MUSIC);
                    // Convert index to internal representation in VolumeStreamState
                    a2dpVolume = a2dpVolume * 10;
                    streamState.setIndex(a2dpVolume, AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
                    mDeviceBroker.postSetVolumeIndexOnDevice(AudioSystem.STREAM_MUSIC,
                            // convert index to internal representation in VolumeStreamState
                            a2dpVolume * 10,
                            AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
                            "onBluetoothA2dpActiveDeviceChange");
                    mDeviceBroker.setDeviceVolume(
                            streamState, AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP);
                }
            } else if (event == BtHelper.EVENT_DEVICE_CONFIG_CHANGE) {
                if (di.mDeviceCodecFormat != a2dpCodec) {
@@ -352,7 +345,7 @@ public final class AudioDeviceInventory {
            }
        }
        mRoutesObservers.finishBroadcast();
        mDeviceBroker.observeDevicesForAllStreams();
        mDeviceBroker.postObserveDevicesForAllStreams();
    }

    private static final int DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG =
@@ -655,8 +648,6 @@ public final class AudioDeviceInventory {
            int a2dpCodec) {
        // enable A2DP before notifying A2DP connection to avoid unnecessary processing in
        // audio policy manager
        AudioService.VolumeStreamState streamState =
                mDeviceBroker.getStreamState(AudioSystem.STREAM_MUSIC);
        mDeviceBroker.setBluetoothA2dpOnInt(true, eventSource);
        AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
                AudioSystem.DEVICE_STATE_AVAILABLE, address, name, a2dpCodec);
@@ -727,8 +718,8 @@ public final class AudioDeviceInventory {

    @GuardedBy("mConnectedDevices")
    private void makeHearingAidDeviceAvailable(String address, String name, String eventSource) {
        final int hearingAidVolIndex = mDeviceBroker.getStreamState(AudioSystem.STREAM_MUSIC)
                .getIndex(AudioSystem.DEVICE_OUT_HEARING_AID);
        final int hearingAidVolIndex = mDeviceBroker.getVssVolumeForDevice(AudioSystem.STREAM_MUSIC,
                AudioSystem.DEVICE_OUT_HEARING_AID);
        mDeviceBroker.postSetHearingAidVolumeIndex(hearingAidVolIndex, AudioSystem.STREAM_MUSIC);

        AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_HEARING_AID,
@@ -739,9 +730,8 @@ public final class AudioDeviceInventory {
                new DeviceInfo(AudioSystem.DEVICE_OUT_HEARING_AID, name,
                        address, AudioSystem.AUDIO_FORMAT_DEFAULT));
        mDeviceBroker.postAccessoryPlugMediaUnmute(AudioSystem.DEVICE_OUT_HEARING_AID);
        mDeviceBroker.setDeviceVolume(
                mDeviceBroker.getStreamState(AudioSystem.STREAM_MUSIC),
                AudioSystem.DEVICE_OUT_HEARING_AID);
        mDeviceBroker.postApplyVolumeOnDevice(AudioSystem.STREAM_MUSIC,
                AudioSystem.DEVICE_OUT_HEARING_AID, "makeHearingAidDeviceAvailable");
        setCurrentAudioRouteNameIfPossible(name);
    }

+103 −5
Original line number Diff line number Diff line
@@ -258,6 +258,8 @@ public class AudioService extends IAudioService.Stub
    private static final int MSG_DISPATCH_AUDIO_SERVER_STATE = 23;
    private static final int MSG_ENABLE_SURROUND_FORMATS = 24;
    private static final int MSG_UPDATE_RINGER_MODE = 25;
    private static final int MSG_SET_DEVICE_STREAM_VOLUME = 26;
    private static final int MSG_OBSERVE_DEVICES_FOR_ALL_STREAMS = 27;
    // start of messages handled under wakelock
    //   these messages can only be queued, i.e. sent with queueMsgUnderWakeLock(),
    //   and not with sendMsg(..., ..., SENDMSG_QUEUE, ...)
@@ -274,8 +276,8 @@ public class AudioService extends IAudioService.Stub
    /** @see VolumeStreamState */
    private VolumeStreamState[] mStreamStates;

    /*package*/ VolumeStreamState getStreamState(int stream) {
        return mStreamStates[stream];
    /*package*/ int getVssVolumeForDevice(int stream, int device) {
        return mStreamStates[stream].getIndex(device);
    }

    private SettingsObserver mSettingsObserver;
@@ -2920,7 +2922,21 @@ public class AudioService extends IAudioService.Stub

    }

    /*package*/ class SetModeDeathHandler implements IBinder.DeathRecipient {
    /**
     * Return the pid of the current audio mode owner
     * @return 0 if nobody owns the mode
     */
    /*package*/ int getModeOwnerPid() {
        int modeOwnerPid = 0;
        try {
            modeOwnerPid = mSetModeDeathHandlers.get(0).getPid();
        } catch (Exception e) {
            // nothing to do, modeOwnerPid is not modified
        }
        return modeOwnerPid;
    }

    private class SetModeDeathHandler implements IBinder.DeathRecipient {
        private IBinder mCb; // To be notified of client's death
        private int mPid;
        private int mMode = AudioSystem.MODE_NORMAL; // Current mode set by this client
@@ -4080,8 +4096,14 @@ public class AudioService extends IAudioService.Stub
        }
    }

    /*package*/ void postObserveDevicesForAllStreams() {
        sendMsg(mAudioHandler,
                MSG_OBSERVE_DEVICES_FOR_ALL_STREAMS,
                SENDMSG_QUEUE, 0 /*arg1*/, 0 /*arg2*/, null /*obj*/,
                0 /*delay*/);
    }

    /*package*/ void observeDevicesForAllStreams() {
    private void onObserveDevicesForAllStreams() {
        observeDevicesForStreams(-1);
    }

@@ -4254,7 +4276,7 @@ public class AudioService extends IAudioService.Stub
    //  2   mSetModeLock
    //  3     mSettingsLock
    //  4       VolumeStreamState.class
    public class VolumeStreamState {
    private class VolumeStreamState {
        private final int mStreamType;
        private int mIndexMin;
        private int mIndexMax;
@@ -4724,6 +4746,74 @@ public class AudioService extends IAudioService.Stub
        }
    }

    private static final class DeviceVolumeUpdate {
        final int mStreamType;
        final int mDevice;
        final @NonNull String mCaller;
        private static final int NO_NEW_INDEX = -2049;
        private final int mVssVolIndex;

        // Constructor with volume index, meant to cause this volume to be set and applied for the
        // given stream type on the given device
        DeviceVolumeUpdate(int streamType, int vssVolIndex, int device, @NonNull String caller) {
            mStreamType = streamType;
            mVssVolIndex = vssVolIndex;
            mDevice = device;
            mCaller = caller;
        }

        // Constructor with no volume index, meant to cause re-apply of volume for the given
        // stream type on the given device
        DeviceVolumeUpdate(int streamType, int device, @NonNull String caller) {
            mStreamType = streamType;
            mVssVolIndex = NO_NEW_INDEX;
            mDevice = device;
            mCaller = caller;
        }

        boolean hasVolumeIndex() {
            return mVssVolIndex != NO_NEW_INDEX;
        }

        int getVolumeIndex() throws IllegalStateException {
            Preconditions.checkState(mVssVolIndex != NO_NEW_INDEX);
            return mVssVolIndex;
        }
    }

    /*package*/ void postSetVolumeIndexOnDevice(int streamType, int vssVolIndex, int device,
                                                String caller) {
        sendMsg(mAudioHandler,
                MSG_SET_DEVICE_STREAM_VOLUME,
                SENDMSG_QUEUE, 0 /*arg1*/, 0 /*arg2*/,
                new DeviceVolumeUpdate(streamType, vssVolIndex, device, caller),
                0 /*delay*/);
    }

    /*package*/ void postApplyVolumeOnDevice(int streamType, int device, @NonNull String caller) {
        sendMsg(mAudioHandler,
                MSG_SET_DEVICE_STREAM_VOLUME,
                SENDMSG_QUEUE, 0 /*arg1*/, 0 /*arg2*/,
                new DeviceVolumeUpdate(streamType, device, caller),
                0 /*delay*/);
    }

    private void onSetVolumeIndexOnDevice(@NonNull DeviceVolumeUpdate update) {
        synchronized (VolumeStreamState.class) {
            final VolumeStreamState streamState = mStreamStates[update.mStreamType];
            if (update.hasVolumeIndex()) {
                final int index = update.getVolumeIndex();
                streamState.setIndex(index, update.mDevice, update.mCaller);
                sVolumeLogger.log(new AudioEventLogger.StringEvent(update.mCaller + " dev:0x"
                        + Integer.toHexString(update.mDevice) + " volIdx:" + index));
            } else {
                sVolumeLogger.log(new AudioEventLogger.StringEvent(update.mCaller
                        + " update vol on dev:0x" + Integer.toHexString(update.mDevice)));
            }
            setDeviceVolume(streamState, update.mDevice);
        }
    }

    /*package*/ void setDeviceVolume(VolumeStreamState streamState, int device) {

        final boolean isAvrcpAbsVolSupported = mDeviceBroker.isAvrcpAbsoluteVolumeSupported();
@@ -5164,6 +5254,14 @@ public class AudioService extends IAudioService.Stub
                case MSG_UPDATE_RINGER_MODE:
                    onUpdateRingerModeServiceInt();
                    break;

                case MSG_SET_DEVICE_STREAM_VOLUME:
                    onSetVolumeIndexOnDevice((DeviceVolumeUpdate) msg.obj);
                    break;

                case MSG_OBSERVE_DEVICES_FOR_ALL_STREAMS:
                    onObserveDevicesForAllStreams();
                    break;
            }
        }
    }
+1 −2
Original line number Diff line number Diff line
@@ -765,8 +765,7 @@ public class BtHelper {
                broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_CONNECTING);
                // Accept SCO audio activation only in NORMAL audio mode or if the mode is
                // currently controlled by the same client process.
                int modeOwnerPid =  mDeviceBroker.getSetModeDeathHandlers().isEmpty()
                        ? 0 : mDeviceBroker.getSetModeDeathHandlers().get(0).getPid();
                final int modeOwnerPid =  mDeviceBroker.getModeOwnerPid();
                if (modeOwnerPid != 0 && (modeOwnerPid != mCreatorPid)) {
                    Log.w(TAG, "requestScoState: audio mode is not NORMAL and modeOwnerPid "
                            + modeOwnerPid + " != creatorPid " + mCreatorPid);