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

Commit f855a2ff authored by Matthew Xie's avatar Matthew Xie Committed by Android (Google) Code Review
Browse files

Merge "Adding support for Absolute Volume" into klp-dev

parents e265d96e 5a0cf7a2
Loading
Loading
Loading
Loading
+60 −0
Original line number Diff line number Diff line
@@ -387,6 +387,66 @@ public final class BluetoothA2dp implements BluetoothProfile {
        return BluetoothProfile.PRIORITY_OFF;
    }

    /**
     * Checks if Avrcp device supports the absolute volume feature.
     *
     * @return true if device supports absolute volume
     * @hide
     */
    public boolean isAvrcpAbsoluteVolumeSupported() {
        if (DBG) Log.d(TAG, "isAvrcpAbsoluteVolumeSupported");
        if (mService != null && isEnabled()) {
            try {
                return mService.isAvrcpAbsoluteVolumeSupported();
            } catch (RemoteException e) {
                Log.e(TAG, "Error talking to BT service in isAvrcpAbsoluteVolumeSupported()", e);
                return false;
            }
        }
        if (mService == null) Log.w(TAG, "Proxy not attached to service");
        return false;
    }

    /**
     * Tells remote device to adjust volume. Only if absolute volume is supported.
     *
     * @param direction 1 to increase volume, or -1 to decrease volume
     * @hide
     */
    public void adjustAvrcpAbsoluteVolume(int direction) {
        if (DBG) Log.d(TAG, "adjustAvrcpAbsoluteVolume");
        if (mService != null && isEnabled()) {
            try {
                mService.adjustAvrcpAbsoluteVolume(direction);
                return;
            } catch (RemoteException e) {
                Log.e(TAG, "Error talking to BT service in adjustAvrcpAbsoluteVolume()", e);
                return;
            }
        }
        if (mService == null) Log.w(TAG, "Proxy not attached to service");
    }

    /**
     * Tells remote device to set an absolute volume. Only if absolute volume is supported
     *
     * @param volume Absolute volume to be set on AVRCP side
     * @hide
     */
    public void setAvrcpAbsoluteVolume(int volume) {
        if (DBG) Log.d(TAG, "setAvrcpAbsoluteVolume");
        if (mService != null && isEnabled()) {
            try {
                mService.setAvrcpAbsoluteVolume(volume);
                return;
            } catch (RemoteException e) {
                Log.e(TAG, "Error talking to BT service in setAvrcpAbsoluteVolume()", e);
                return;
            }
        }
        if (mService == null) Log.w(TAG, "Proxy not attached to service");
    }

    /**
     * Check if A2DP profile is streaming music.
     *
+3 −0
Original line number Diff line number Diff line
@@ -32,5 +32,8 @@ interface IBluetoothA2dp {
    int getConnectionState(in BluetoothDevice device);
    boolean setPriority(in BluetoothDevice device, int priority);
    int getPriority(in BluetoothDevice device);
    boolean isAvrcpAbsoluteVolumeSupported();
    oneway void adjustAvrcpAbsoluteVolume(int direction);
    oneway void setAvrcpAbsoluteVolume(int volume);
    boolean isA2dpPlaying(in BluetoothDevice device);
}
+29 −0
Original line number Diff line number Diff line
@@ -2387,6 +2387,35 @@ public class AudioManager {
        }
    }

    /**
     * @hide
     * Notifies AudioService that it is connected to an A2DP device that supports absolute volume,
     * so that AudioService can send volume change events to the A2DP device, rather than handling
     * them.
     */
    public void avrcpSupportsAbsoluteVolume(String address, boolean support) {
        IAudioService service = getService();
        try {
            service.avrcpSupportsAbsoluteVolume(address, support);
        } catch (RemoteException e) {
            Log.e(TAG, "Dead object in avrcpSupportsAbsoluteVolume", e);
        }
    }

    /**
     * @hide
     * Notifies AudioService of the volume set on the A2DP device as a callback, so AudioService
     * is able to update the UI.
     */
    public void avrcpUpdateVolume(int oldVolume, int volume) {
        IAudioService service = getService();
        try {
            service.avrcpUpdateVolume(oldVolume, volume);
        } catch (RemoteException e) {
            Log.e(TAG, "Dead object in avrcpUpdateVolume", e);
        }
    }

     /**
      * {@hide}
      */
+88 −19
Original line number Diff line number Diff line
@@ -460,6 +460,12 @@ public class AudioService extends IAudioService.Stub {

    private final MediaFocusControl mMediaFocusControl;

    // Reference to BluetoothA2dp to query for AbsoluteVolume.
    private BluetoothA2dp mA2dp;
    private final Object mA2dpAvrcpLock = new Object();
    // If absolute volume is supported in AVRCP device
    private boolean mAvrcpAbsVolSupported = false;

    ///////////////////////////////////////////////////////////////////////////
    // Construction
    ///////////////////////////////////////////////////////////////////////////
@@ -901,6 +907,15 @@ public class AudioService extends IAudioService.Stub {
        int oldIndex = mStreamStates[streamType].getIndex(device);

        if (adjustVolume && (direction != AudioManager.ADJUST_SAME)) {
            // Check if volume update should be send to AVRCP
            synchronized (mA2dpAvrcpLock) {
                if (mA2dp != null && mAvrcpAbsVolSupported) {
                    mA2dp.adjustAvrcpAbsoluteVolume(direction);
                    return;
                    // No need to send volume update, because we will update the volume with a
                    // callback from Avrcp.
                }
            }
            if ((direction == AudioManager.ADJUST_RAISE) &&
                    !checkSafeMediaVolume(streamTypeAlias, aliasIndex + step, device)) {
                Log.e(TAG, "adjustStreamVolume() safe volume index = "+oldIndex);
@@ -998,6 +1013,15 @@ public class AudioService extends IAudioService.Stub {

            index = rescaleIndex(index * 10, streamType, streamTypeAlias);

            synchronized (mA2dpAvrcpLock) {
                if (mA2dp != null && mAvrcpAbsVolSupported) {
                    mA2dp.setAvrcpAbsoluteVolume(index);
                    return;
                    // No need to send volume update, because we will update the volume with a
                    // callback from Avrcp.
                }
            }

            flags &= ~AudioManager.FLAG_FIXED_VOLUME;
            if ((streamTypeAlias == AudioSystem.STREAM_MUSIC) &&
                    ((device & mFixedVolumeDevices) != 0)) {
@@ -2268,12 +2292,13 @@ public class AudioService extends IAudioService.Stub {
            List<BluetoothDevice> deviceList;
            switch(profile) {
            case BluetoothProfile.A2DP:
                BluetoothA2dp a2dp = (BluetoothA2dp) proxy;
                deviceList = a2dp.getConnectedDevices();
                synchronized (mA2dpAvrcpLock) {
                    mA2dp = (BluetoothA2dp) proxy;
                    deviceList = mA2dp.getConnectedDevices();
                    if (deviceList.size() > 0) {
                        btDevice = deviceList.get(0);
                        synchronized (mConnectedDevices) {
                        int state = a2dp.getConnectionState(btDevice);
                            int state = mA2dp.getConnectionState(btDevice);
                            int delay = checkSendBecomingNoisyIntent(
                                                    AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
                                                    (state == BluetoothA2dp.STATE_CONNECTED) ? 1 : 0);
@@ -2285,6 +2310,7 @@ public class AudioService extends IAudioService.Stub {
                                    delay);
                        }
                    }
                }
                break;

            case BluetoothProfile.HEADSET:
@@ -2344,12 +2370,15 @@ public class AudioService extends IAudioService.Stub {
        public void onServiceDisconnected(int profile) {
            switch(profile) {
            case BluetoothProfile.A2DP:
                synchronized (mA2dpAvrcpLock) {
                    mA2dp = null;
                    synchronized (mConnectedDevices) {
                        if (mConnectedDevices.containsKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP)) {
                            makeA2dpDeviceUnavailableNow(
                                    mConnectedDevices.get(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP));
                        }
                    }
                }
                break;

            case BluetoothProfile.HEADSET:
@@ -3697,6 +3726,7 @@ public class AudioService extends IAudioService.Stub {

    private void onSetA2dpConnectionState(BluetoothDevice btDevice, int state)
    {
        if (DEBUG_VOL) Log.d(TAG, "onSetA2dpConnectionState btDevice="+btDevice+" state="+state);
        if (btDevice == null) {
            return;
        }
@@ -3704,6 +3734,20 @@ public class AudioService extends IAudioService.Stub {
        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
            address = "";
        }

        // Disable absolute volume, if device is disconnected
        synchronized (mA2dpAvrcpLock) {
            if (state == BluetoothProfile.STATE_DISCONNECTED && mAvrcpAbsVolSupported) {
                mAvrcpAbsVolSupported = false;
                sendMsg(mAudioHandler,
                        MSG_SET_DEVICE_VOLUME,
                        SENDMSG_QUEUE,
                        getDeviceForStream(AudioSystem.STREAM_MUSIC),
                        0,
                        mStreamStates[AudioSystem.STREAM_MUSIC],
                        0);
            }
        }
        synchronized (mConnectedDevices) {
            boolean isConnected =
                (mConnectedDevices.containsKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP) &&
@@ -3754,6 +3798,31 @@ public class AudioService extends IAudioService.Stub {
        }
    }

    public void avrcpSupportsAbsoluteVolume(String address, boolean support) {
        // address is not used for now, but may be used when multiple a2dp devices are supported
        synchronized (mA2dpAvrcpLock) {
            mAvrcpAbsVolSupported = support;
            if (support) {
                VolumeStreamState streamState = mStreamStates[AudioSystem.STREAM_MUSIC];
                int device = getDeviceForStream(AudioSystem.STREAM_MUSIC);
                streamState.setIndex(streamState.getMaxIndex(), device);
                sendMsg(mAudioHandler,
                        MSG_SET_DEVICE_VOLUME,
                        SENDMSG_QUEUE,
                        device,
                        0,
                        streamState,
                        0);
            }
        }
    }

    public void avrcpUpdateVolume(int oldVolume, int volume) {
        mStreamStates[AudioSystem.STREAM_MUSIC].
                        setIndex(volume, getDeviceForStream(AudioSystem.STREAM_MUSIC));
        sendVolumeUpdate(AudioSystem.STREAM_MUSIC, oldVolume, volume, AudioManager.FLAG_SHOW_UI);
    }

    private boolean handleDeviceConnection(boolean connected, int device, String params) {
        synchronized (mConnectedDevices) {
            boolean isConnected = (mConnectedDevices.containsKey(device) &&
+4 −0
Original line number Diff line number Diff line
@@ -98,6 +98,10 @@ interface IAudioService {

    oneway void reloadAudioSettings();

    oneway void avrcpSupportsAbsoluteVolume(String address, boolean support);

    oneway void avrcpUpdateVolume(int oldVolume, int volume);

    void setSpeakerphoneOn(boolean on);

    boolean isSpeakerphoneOn();