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

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

Merge "Send active device changed intent after connecting in AudioManager" into tm-qpr-dev

parents 7d39416c 7f5563d4
Loading
Loading
Loading
Loading
+94 −26
Original line number Diff line number Diff line
@@ -42,6 +42,8 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.AudioDeviceCallback;
import android.media.AudioDeviceInfo;
import android.media.AudioManager;
import android.media.BluetoothProfileConnectionInfo;
import android.os.Handler;
@@ -166,6 +168,10 @@ public class LeAudioService extends ProfileService {
    private BroadcastReceiver mMuteStateChangedReceiver;
    private int mStoredRingerMode = -1;
    private Handler mHandler = new Handler(Looper.getMainLooper());
    private final AudioManagerAddAudioDeviceCallback mAudioManagerAddAudioDeviceCallback =
            new AudioManagerAddAudioDeviceCallback();
    private final AudioManagerRemoveAudioDeviceCallback mAudioManagerRemoveAudioDeviceCallback =
            new AudioManagerRemoveAudioDeviceCallback();

    private final Map<Integer, Integer> mBroadcastStateMap = new HashMap<>();
    private final Map<Integer, Boolean> mBroadcastsPlaybackMap = new HashMap<>();
@@ -821,9 +827,6 @@ public class LeAudioService extends ProfileService {
                        + " isLeOutput: false");
            }

            mAudioManager.handleBluetoothActiveDeviceChanged(mActiveAudioInDevice,previousInDevice,
                    BluetoothProfileConnectionInfo.createLeAudioInfo(false, false));

            return true;
        }
        Log.d(TAG, "updateActiveInDevice: Nothing to do.");
@@ -876,28 +879,60 @@ public class LeAudioService extends ProfileService {
        if (!Objects.equals(device, previousOutDevice)
                || (oldSupportedByDeviceOutput != newSupportedByDeviceOutput)) {
            mActiveAudioOutDevice = newSupportedByDeviceOutput ? device : null;
            final boolean suppressNoisyIntent = (mActiveAudioOutDevice != null)
                    || (getConnectionState(previousOutDevice) == BluetoothProfile.STATE_CONNECTED);

            if (DBG) {
                Log.d(TAG, " handleBluetoothActiveDeviceChanged previousOutDevice: "
                        + previousOutDevice + ", mActiveOutDevice: " + mActiveAudioOutDevice
                        + " isLeOutput: true");
            }
            int volume = IBluetoothVolumeControl.VOLUME_CONTROL_UNKNOWN_VOLUME;
            if (mActiveAudioOutDevice != null) {
                volume = getAudioDeviceGroupVolume(groupId);
            }

            mAudioManager.handleBluetoothActiveDeviceChanged(mActiveAudioOutDevice,
                    previousOutDevice,
                    getLeAudioOutputProfile(suppressNoisyIntent, volume));
            return true;
        }
        Log.d(TAG, "updateActiveOutDevice: Nothing to do.");
        return false;
    }

    private void notifyActiveDeviceChanged() {
        Intent intent = new Intent(BluetoothLeAudio.ACTION_LE_AUDIO_ACTIVE_DEVICE_CHANGED);
        intent.putExtra(BluetoothDevice.EXTRA_DEVICE,
                mActiveAudioOutDevice != null ? mActiveAudioOutDevice : mActiveAudioInDevice);
        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
                | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
        sendBroadcast(intent, BLUETOOTH_CONNECT);
    }

    /* Notifications of audio device disconnection events. */
    private class AudioManagerRemoveAudioDeviceCallback extends AudioDeviceCallback {
        @Override
        public void onAudioDevicesRemoved(AudioDeviceInfo[] removedDevices) {
            for (AudioDeviceInfo deviceInfo : removedDevices) {
                if (deviceInfo.getType() == AudioDeviceInfo.TYPE_BLE_HEADSET
                        || deviceInfo.getType() == AudioDeviceInfo.TYPE_BLE_SPEAKER) {
                    notifyActiveDeviceChanged();
                    if (DBG) {
                        Log.d(TAG, " onAudioDevicesRemoved: device type: " + deviceInfo.getType());
                    }
                    mAudioManager.unregisterAudioDeviceCallback(this);
                }
            }
        }
    }

    /* Notifications of audio device connection events. */
    private class AudioManagerAddAudioDeviceCallback extends AudioDeviceCallback {
        @Override
        public void onAudioDevicesAdded(AudioDeviceInfo[] addedDevices) {
            for (AudioDeviceInfo deviceInfo : addedDevices) {
                if (deviceInfo.getType() == AudioDeviceInfo.TYPE_BLE_HEADSET
                        || deviceInfo.getType() == AudioDeviceInfo.TYPE_BLE_SPEAKER) {
                    notifyActiveDeviceChanged();
                    if (DBG) {
                        Log.d(TAG, " onAudioDevicesAdded: device type: " + deviceInfo.getType());
                    }
                    mAudioManager.unregisterAudioDeviceCallback(this);
                }
            }
        }
    }

    /**
     * Report the active devices change to the active device manager and the media framework.
     * @param groupId id of group which devices should be updated
@@ -909,24 +944,57 @@ public class LeAudioService extends ProfileService {
    private boolean updateActiveDevices(Integer groupId, Integer oldSupportedAudioDirections,
            Integer newSupportedAudioDirections, boolean isActive) {
        BluetoothDevice device = null;
        BluetoothDevice previousActiveOutDevice = mActiveAudioOutDevice;
        BluetoothDevice previousActiveInDevice = mActiveAudioInDevice;

        if (isActive) {
            device = getFirstDeviceFromGroup(groupId);
        }

        boolean outReplaced =
                updateActiveOutDevice(device, groupId, oldSupportedAudioDirections,
                        newSupportedAudioDirections);
        boolean inReplaced =
                updateActiveInDevice(device, groupId, oldSupportedAudioDirections,
                        newSupportedAudioDirections);
        boolean isNewActiveOutDevice = updateActiveOutDevice(device, groupId,
                oldSupportedAudioDirections, newSupportedAudioDirections);
        boolean isNewActiveInDevice = updateActiveInDevice(device, groupId,
                oldSupportedAudioDirections, newSupportedAudioDirections);

        if (outReplaced || inReplaced) {
            Intent intent = new Intent(BluetoothLeAudio.ACTION_LE_AUDIO_ACTIVE_DEVICE_CHANGED);
            intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mActiveAudioOutDevice);
            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
                    | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
            sendBroadcast(intent, BLUETOOTH_CONNECT);
        if (DBG) {
            Log.d(TAG, " isNewActiveOutDevice: " + isNewActiveOutDevice + ", "
                    + mActiveAudioOutDevice + ", isNewActiveInDevice: " + isNewActiveInDevice
                    + ", " + mActiveAudioInDevice);
        }

        /* Active device changed, there is need to inform about new active LE Audio device */
        if (isNewActiveOutDevice || isNewActiveInDevice) {
            /* Register for new device connection/disconnection in Audio Manager */
            if (mActiveAudioOutDevice != null || mActiveAudioInDevice != null) {
                /* Register for any device connection in case if any of devices become connected */
                mAudioManager.registerAudioDeviceCallback(mAudioManagerAddAudioDeviceCallback,
                        mHandler);
            } else {
                /* Register for disconnection if active devices become non-active */
                mAudioManager.registerAudioDeviceCallback(mAudioManagerRemoveAudioDeviceCallback,
                        mHandler);
            }
        }

        if (isNewActiveOutDevice) {
            int volume = IBluetoothVolumeControl.VOLUME_CONTROL_UNKNOWN_VOLUME;

            if (mActiveAudioOutDevice != null) {
                volume = getAudioDeviceGroupVolume(groupId);
            }

            final boolean suppressNoisyIntent = (mActiveAudioOutDevice != null)
                    || (getConnectionState(previousActiveOutDevice)
                    == BluetoothProfile.STATE_CONNECTED);

            mAudioManager.handleBluetoothActiveDeviceChanged(mActiveAudioOutDevice,
                    previousActiveOutDevice, getLeAudioOutputProfile(suppressNoisyIntent, volume));
        }

        if (isNewActiveInDevice) {
            mAudioManager.handleBluetoothActiveDeviceChanged(mActiveAudioInDevice,
                    previousActiveInDevice, BluetoothProfileConnectionInfo.createLeAudioInfo(false,
                            false));
        }

        return mActiveAudioOutDevice != null;
+3 −2
Original line number Diff line number Diff line
@@ -85,6 +85,7 @@ import java.util.concurrent.TimeoutException;
public class LeAudioServiceTest {
    private static final int ASYNC_CALL_TIMEOUT_MILLIS = 250;
    private static final int TIMEOUT_MS = 1000;
    private static final int AUDIO_MANAGER_DEVICE_ADD_TIMEOUT_MS = 3000;
    private static final int MAX_LE_AUDIO_CONNECTIONS = 5;
    private static final int LE_AUDIO_GROUP_ID_INVALID = -1;

@@ -1328,7 +1329,7 @@ public class LeAudioServiceTest {
                        any(BluetoothProfileConnectionInfo.class));

        doReturn(BluetoothDevice.BOND_BONDED).when(mAdapterService).getBondState(leadDevice);
        verifyActiveDeviceStateIntent(TIMEOUT_MS, leadDevice);
        verifyActiveDeviceStateIntent(AUDIO_MANAGER_DEVICE_ADD_TIMEOUT_MS, leadDevice);
        injectNoVerifyDeviceDisconnected(leadDevice);

        // We should not change the audio device
@@ -1392,7 +1393,7 @@ public class LeAudioServiceTest {
        verify(mAudioManager, times(1)).handleBluetoothActiveDeviceChanged(eq(leadDevice), any(),
                        any(BluetoothProfileConnectionInfo.class));

        verifyActiveDeviceStateIntent(TIMEOUT_MS, leadDevice);
        verifyActiveDeviceStateIntent(AUDIO_MANAGER_DEVICE_ADD_TIMEOUT_MS, leadDevice);
        /* We don't want to distribute DISCONNECTION event, instead will try to reconnect
         * (in native)
         */