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

Commit 1d046a4b authored by Treehugger Robot's avatar Treehugger Robot Committed by Automerger Merge Worker
Browse files

Merge "BluetoothLeAudio: Replace Intents by callbacks" am: 6f7d9739 am:...

Merge "BluetoothLeAudio: Replace Intents by callbacks" am: 6f7d9739 am: f549dbe5 am: 9f70182a am: a268b268

Original change: https://android-review.googlesource.com/c/platform/packages/modules/Bluetooth/+/2020087

Change-Id: Ia114c741c3b741d4abaf5fbf93a6b343655ed861
parents 22fc1e52 a268b268
Loading
Loading
Loading
Loading
+61 −25
Original line number Diff line number Diff line
@@ -832,8 +832,9 @@ public class LeAudioService extends ProfileService {
     * @param newActiveContexts new active contexts for group of devices
     * @param oldActiveContexts old active contexts for group of devices
     * @param isActive if there is new active group
     * @return true if group is active after change false otherwise.
     */
    private void updateActiveDevices(Integer groupId, Integer oldActiveContexts,
    private boolean updateActiveDevices(Integer groupId, Integer oldActiveContexts,
            Integer newActiveContexts, boolean isActive) {
        BluetoothDevice device = null;

@@ -853,6 +854,8 @@ public class LeAudioService extends ProfileService {
                    | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
            sendBroadcast(intent, BLUETOOTH_CONNECT);
        }

        return mActiveAudioOutDevice != null;
    }

    /**
@@ -1014,21 +1017,18 @@ public class LeAudioService extends ProfileService {
                    if (descriptor == null) {
                        mGroupDescriptors.put(group_id, new LeAudioGroupDescriptor());
                    }
                    notifyGroupNodeAdded(device, group_id);
                    break;
                case LeAudioStackEvent.GROUP_NODE_REMOVED:
                    mDeviceGroupIdMap.remove(device);
                    if (mDeviceGroupIdMap.containsValue(group_id) == false) {
                        mGroupDescriptors.remove(group_id);
                    }
                    notifyGroupNodeRemoved(device, group_id);
                    break;
                default:
                    break;
            }

            intent = new Intent(BluetoothLeAudio.ACTION_LE_AUDIO_GROUP_NODE_STATUS_CHANGED);
            intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
            intent.putExtra(BluetoothLeAudio.EXTRA_LE_AUDIO_GROUP_ID, group_id);
            intent.putExtra(BluetoothLeAudio.EXTRA_LE_AUDIO_GROUP_NODE_STATUS, node_status);
        } else if (stackEvent.type == LeAudioStackEvent.EVENT_TYPE_AUDIO_CONF_CHANGED) {
            int direction = stackEvent.valueInt1;
            int group_id = stackEvent.valueInt2;
@@ -1039,21 +1039,17 @@ public class LeAudioService extends ProfileService {
            LeAudioGroupDescriptor descriptor = mGroupDescriptors.get(group_id);
            if (descriptor != null) {
                if (descriptor.mIsActive) {
                    descriptor.mIsActive =
                        updateActiveDevices(group_id, descriptor.mActiveContexts,
                                        available_contexts, descriptor.mIsActive);
                    if (!descriptor.mIsActive) {
                        notifyGroupStatusChanged(group_id, BluetoothLeAudio.GROUP_STATUS_INACTIVE);
                    }
                }
                descriptor.mActiveContexts = available_contexts;
            } else {
                Log.e(TAG, "no descriptors for group: " + group_id);
            }

            intent = new Intent(BluetoothLeAudio.ACTION_LE_AUDIO_CONF_CHANGED);
            intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
            intent.putExtra(BluetoothLeAudio.EXTRA_LE_AUDIO_GROUP_ID, group_id);
            intent.putExtra(BluetoothLeAudio.EXTRA_LE_AUDIO_DIRECTION, direction);
            intent.putExtra(BluetoothLeAudio.EXTRA_LE_AUDIO_SINK_LOCATION, snk_audio_location);
            intent.putExtra(BluetoothLeAudio.EXTRA_LE_AUDIO_SOURCE_LOCATION, src_audio_location);
            intent.putExtra(BluetoothLeAudio.EXTRA_LE_AUDIO_AVAILABLE_CONTEXTS, available_contexts);
        } else if (stackEvent.type == LeAudioStackEvent.EVENT_TYPE_SINK_AUDIO_LOCATION_AVAILABLE) {
            Objects.requireNonNull(stackEvent.device,
                    "Device should never be null, event: " + stackEvent);
@@ -1068,17 +1064,17 @@ public class LeAudioService extends ProfileService {
        } else if (stackEvent.type == LeAudioStackEvent.EVENT_TYPE_GROUP_STATUS_CHANGED) {
            int group_id = stackEvent.valueInt1;
            int group_status = stackEvent.valueInt2;
            boolean send_intent = false;
            boolean notifyGroupStatus = false;

            switch (group_status) {
                case LeAudioStackEvent.GROUP_STATUS_ACTIVE: {
                    LeAudioGroupDescriptor descriptor = mGroupDescriptors.get(group_id);
                    if (descriptor != null) {
                        if (!descriptor.mIsActive) {
                            descriptor.mIsActive = true;
                            updateActiveDevices(group_id, ACTIVE_CONTEXTS_NONE,
                                                descriptor.mActiveContexts, descriptor.mIsActive);
                            send_intent = true;
                            descriptor.mIsActive = updateActiveDevices(group_id,
                                                ACTIVE_CONTEXTS_NONE,
                                                descriptor.mActiveContexts, true);
                            notifyGroupStatus = descriptor.mIsActive;
                        }
                    } else {
                        Log.e(TAG, "no descriptors for group: " + group_id);
@@ -1092,7 +1088,7 @@ public class LeAudioService extends ProfileService {
                            descriptor.mIsActive = false;
                            updateActiveDevices(group_id, descriptor.mActiveContexts,
                                    ACTIVE_CONTEXTS_NONE, descriptor.mIsActive);
                            send_intent = true;
                            notifyGroupStatus = true;
                        }
                    } else {
                        Log.e(TAG, "no descriptors for group: " + group_id);
@@ -1103,10 +1099,8 @@ public class LeAudioService extends ProfileService {
                    break;
            }

            if (send_intent) {
                intent = new Intent(BluetoothLeAudio.ACTION_LE_AUDIO_GROUP_STATUS_CHANGED);
                intent.putExtra(BluetoothLeAudio.EXTRA_LE_AUDIO_GROUP_ID, group_id);
                intent.putExtra(BluetoothLeAudio.EXTRA_LE_AUDIO_GROUP_STATUS, group_status);
            if (notifyGroupStatus) {
                notifyGroupStatusChanged(group_id, group_status);
            }

        } else if (stackEvent.type == LeAudioStackEvent.EVENT_TYPE_BROADCAST_CREATED) {
@@ -1539,6 +1533,48 @@ public class LeAudioService extends ProfileService {
        }
    }

    private void notifyGroupNodeAdded(BluetoothDevice device, int groupId) {
        if (mLeAudioCallbacks != null) {
            int n = mLeAudioCallbacks.beginBroadcast();
            for (int i = 0; i < n; i++) {
                try {
                    mLeAudioCallbacks.getBroadcastItem(i).onGroupNodeAdded(device, groupId);
                } catch (RemoteException e) {
                    continue;
                }
            }
            mLeAudioCallbacks.finishBroadcast();
        }
    }

    private void notifyGroupNodeRemoved(BluetoothDevice device, int groupId) {
        if (mLeAudioCallbacks != null) {
            int n = mLeAudioCallbacks.beginBroadcast();
            for (int i = 0; i < n; i++) {
                try {
                    mLeAudioCallbacks.getBroadcastItem(i).onGroupNodeRemoved(device, groupId);
                } catch (RemoteException e) {
                    continue;
                }
            }
            mLeAudioCallbacks.finishBroadcast();
        }
    }

    private void notifyGroupStatusChanged(int groupId, int status) {
        if (mLeAudioCallbacks != null) {
            int n = mLeAudioCallbacks.beginBroadcast();
            for (int i = 0; i < n; i++) {
                try {
                    mLeAudioCallbacks.getBroadcastItem(i).onGroupStatusChanged(groupId, status);
                } catch (RemoteException e) {
                    continue;
                }
            }
            mLeAudioCallbacks.finishBroadcast();
        }
    }

    private void notifyUnicastCodecConfigChanged(int groupId,
                                                 BluetoothLeAudioCodecStatus status) {
        if (mLeAudioCallbacks != null) {
+93 −52
Original line number Diff line number Diff line
@@ -34,8 +34,10 @@ import static org.mockito.Mockito.eq;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothLeAudio;
import android.bluetooth.BluetoothLeAudioCodecStatus;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothUuid;
import android.bluetooth.IBluetoothLeAudioCallback;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -90,6 +92,7 @@ public class LeAudioServiceTest {
    private HashMap<BluetoothDevice, LinkedBlockingQueue<Intent>> mDeviceQueueMap;
    private LinkedBlockingQueue<Intent> mGroupIntentQueue = new LinkedBlockingQueue<>();
    private int testGroupId = 1;
    private boolean onGroupStatusCallbackCalled = false;

    private BroadcastReceiver mLeAudioIntentReceiver;

@@ -133,8 +136,7 @@ public class LeAudioServiceTest {
        // Set up the Connection State Changed receiver
        IntentFilter filter = new IntentFilter();
        filter.addAction(BluetoothLeAudio.ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED);
        filter.addAction(BluetoothLeAudio.ACTION_LE_AUDIO_CONF_CHANGED);
        filter.addAction(BluetoothLeAudio.ACTION_LE_AUDIO_GROUP_STATUS_CHANGED);
        filter.addAction(BluetoothLeAudio.ACTION_LE_AUDIO_ACTIVE_DEVICE_CHANGED);
        mLeAudioIntentReceiver = new LeAudioIntentReceiver();
        mTargetContext.registerReceiver(mLeAudioIntentReceiver, filter);

@@ -198,23 +200,15 @@ public class LeAudioServiceTest {
                            + e.getMessage()).fail();
                }
            }
            if (BluetoothLeAudio.ACTION_LE_AUDIO_CONF_CHANGED.equals(intent.getAction())) {
            if (BluetoothLeAudio.ACTION_LE_AUDIO_ACTIVE_DEVICE_CHANGED.equals(intent.getAction())) {
                try {
                    BluetoothDevice device = intent.getParcelableExtra(
                            BluetoothDevice.EXTRA_DEVICE);
                    assertThat(device).isNotNull();
                    if (device != null) {
                        LinkedBlockingQueue<Intent> queue = mDeviceQueueMap.get(device);
                        assertThat(queue).isNotNull();
                        queue.put(intent);
                } catch (InterruptedException e) {
                    assertWithMessage("Cannot add Le Audio Intent to the Connection State queue: "
                            + e.getMessage()).fail();
                }
                    }

            if (BluetoothLeAudio.ACTION_LE_AUDIO_GROUP_STATUS_CHANGED.equals(intent.getAction())) {
                try {
                    mGroupIntentQueue.put(intent);
                } catch (InterruptedException e) {
                    assertWithMessage("Cannot add Le Audio Intent to the Connection State queue: "
                            + e.getMessage()).fail();
@@ -986,18 +980,19 @@ public class LeAudioServiceTest {
        assertThat(mService.getActiveDevices().contains(mSingleDevice)).isTrue();
    }

    /**
     * Test native interface audio configuration changed message handling
     */
    @Test
    public void testMessageFromNativeAudioConfChanged() {
    private void injectGroupStatusChange(int groupId, int groupStatus) {
        int eventType = LeAudioStackEvent.EVENT_TYPE_GROUP_STATUS_CHANGED;
        LeAudioStackEvent groupStatusChangedEvent = new LeAudioStackEvent(eventType);
        groupStatusChangedEvent.valueInt1 = groupId;
        groupStatusChangedEvent.valueInt2 = groupStatus;
        mService.messageFromNative(groupStatusChangedEvent);
    }

    private void injectAudioConfChanged(int groupId, Integer availableContexts) {
        int direction = 1;
        int groupId = 2;
        int snkAudioLocation = 3;
        int srcAudioLocation = 4;
        int availableContexts = 5;
        int eventType = LeAudioStackEvent.EVENT_TYPE_AUDIO_CONF_CHANGED;
        String action = BluetoothLeAudio.ACTION_LE_AUDIO_CONF_CHANGED;

        // Add device to group
        LeAudioStackEvent audioConfChangedEvent = new LeAudioStackEvent(eventType);
@@ -1008,45 +1003,87 @@ public class LeAudioServiceTest {
        audioConfChangedEvent.valueInt4 = srcAudioLocation;
        audioConfChangedEvent.valueInt5 = availableContexts;
        mService.messageFromNative(audioConfChangedEvent);
    }
    /**
     * Test native interface audio configuration changed message handling
     */
    @Test
    public void testMessageFromNativeAudioConfChangedActiveGroup() {
        doReturn(true).when(mNativeInterface).connectLeAudio(any(BluetoothDevice.class));
        connectTestDevice(mSingleDevice, testGroupId);
        injectAudioConfChanged(testGroupId, BluetoothLeAudio.CONTEXT_TYPE_MEDIA |
                         BluetoothLeAudio.CONTEXT_TYPE_COMMUNICATION);
        injectGroupStatusChange(testGroupId, BluetoothLeAudio.GROUP_STATUS_ACTIVE);

        String action = BluetoothLeAudio.ACTION_LE_AUDIO_ACTIVE_DEVICE_CHANGED;

        Intent intent = TestUtils.waitForIntent(TIMEOUT_MS, mDeviceQueueMap.get(mSingleDevice));
        assertThat(intent).isNotNull();
        assertThat(action).isEqualTo(intent.getAction());
        assertThat(mSingleDevice)
                .isEqualTo(intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE));
        assertThat(groupId)
                .isEqualTo(intent.getIntExtra(BluetoothLeAudio.EXTRA_LE_AUDIO_GROUP_ID, -groupId));
        assertThat(direction)
                .isEqualTo(intent
                .getIntExtra(BluetoothLeAudio.EXTRA_LE_AUDIO_DIRECTION, -direction));
        assertThat(snkAudioLocation)
                .isEqualTo(intent
                .getIntExtra(BluetoothLeAudio.EXTRA_LE_AUDIO_SINK_LOCATION, -snkAudioLocation));
        assertThat(srcAudioLocation)
                .isEqualTo(intent
                .getIntExtra(BluetoothLeAudio.EXTRA_LE_AUDIO_SOURCE_LOCATION, srcAudioLocation));
        assertThat(availableContexts)
                .isEqualTo(intent
                .getIntExtra(BluetoothLeAudio.EXTRA_LE_AUDIO_AVAILABLE_CONTEXTS, availableContexts));
    }
    /**
     * Test native interface audio configuration changed message handling
     */
    @Test
    public void testMessageFromNativeAudioConfChangedInactiveGroup() {
        doReturn(true).when(mNativeInterface).connectLeAudio(any(BluetoothDevice.class));
        connectTestDevice(mSingleDevice, testGroupId);

        String action = BluetoothLeAudio.ACTION_LE_AUDIO_ACTIVE_DEVICE_CHANGED;
        Integer contexts = BluetoothLeAudio.CONTEXT_TYPE_MEDIA |
        BluetoothLeAudio.CONTEXT_TYPE_COMMUNICATION;
        injectAudioConfChanged(testGroupId, contexts);

        Intent intent = TestUtils.waitForNoIntent(TIMEOUT_MS, mDeviceQueueMap.get(mSingleDevice));
        assertThat(intent).isNull();
    }
    /**
     * Test native interface audio configuration changed message handling
     */
    @Test
    public void testMessageFromNativeAudioConfChangedNoGroupChanged() {
        doReturn(true).when(mNativeInterface).connectLeAudio(any(BluetoothDevice.class));
        connectTestDevice(mSingleDevice, testGroupId);

        String action = BluetoothLeAudio.ACTION_LE_AUDIO_ACTIVE_DEVICE_CHANGED;

        injectAudioConfChanged(testGroupId, 0);
        Intent intent = TestUtils.waitForNoIntent(TIMEOUT_MS, mDeviceQueueMap.get(mSingleDevice));
        assertThat(intent).isNull();
    }


    private void sendEventAndVerifyIntentForGroupStatusChanged(int groupId, int groupStatus) {
        int eventType = LeAudioStackEvent.EVENT_TYPE_GROUP_STATUS_CHANGED;
        String action = BluetoothLeAudio.ACTION_LE_AUDIO_GROUP_STATUS_CHANGED;

        LeAudioStackEvent groupStatusChangedEvent = new LeAudioStackEvent(eventType);
        groupStatusChangedEvent.valueInt1 = groupId;
        groupStatusChangedEvent.valueInt2 = groupStatus;
        mService.messageFromNative(groupStatusChangedEvent);
        onGroupStatusCallbackCalled = false;

        Intent intent = TestUtils.waitForIntent(TIMEOUT_MS, mGroupIntentQueue);
        assertThat(intent).isNotNull();
        assertThat(action).isEqualTo(intent.getAction());
        assertThat(groupId)
                .isEqualTo(intent.getIntExtra(BluetoothLeAudio.EXTRA_LE_AUDIO_GROUP_ID, -groupId));
        assertThat(groupStatus)
                .isEqualTo(intent
                .getIntExtra(BluetoothLeAudio.EXTRA_LE_AUDIO_GROUP_STATUS, -groupStatus));
        IBluetoothLeAudioCallback leAudioCallbacks =
        new IBluetoothLeAudioCallback.Stub() {
            @Override
            public void onCodecConfigChanged(int gid, BluetoothLeAudioCodecStatus status) {}
            @Override
            public void onGroupStatusChanged(int gid, int gStatus) {
                onGroupStatusCallbackCalled = true;
                assertThat(gid == groupId).isTrue();
                assertThat(gStatus == groupStatus).isTrue();
            }
            @Override
            public void onGroupNodeAdded(BluetoothDevice device, int gid) {}
            @Override
            public void onGroupNodeRemoved(BluetoothDevice device, int gid) {}
        };

        mService.mLeAudioCallbacks.register(leAudioCallbacks);

        injectGroupStatusChange(groupId, groupStatus);

        TestUtils.waitForLooperToFinishScheduledTask(mService.getMainLooper());
        assertThat(onGroupStatusCallbackCalled).isTrue();

        onGroupStatusCallbackCalled = false;
        mService.mLeAudioCallbacks.unregister(leAudioCallbacks);
    }

    /**
@@ -1057,7 +1094,11 @@ public class LeAudioServiceTest {
        doReturn(true).when(mNativeInterface).connectLeAudio(any(BluetoothDevice.class));
        connectTestDevice(mSingleDevice, testGroupId);

        injectAudioConfChanged(testGroupId, BluetoothLeAudio.CONTEXT_TYPE_MEDIA |
                                 BluetoothLeAudio.CONTEXT_TYPE_COMMUNICATION);

        sendEventAndVerifyIntentForGroupStatusChanged(testGroupId, LeAudioStackEvent.GROUP_STATUS_ACTIVE);
        sendEventAndVerifyIntentForGroupStatusChanged(testGroupId, LeAudioStackEvent.GROUP_STATUS_INACTIVE);
    }

}
+3 −6
Original line number Diff line number Diff line
@@ -351,8 +351,6 @@ package android.bluetooth {
    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public void setVolume(@IntRange(from=0, to=255) int);
    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public void unregisterCallback(@NonNull android.bluetooth.BluetoothLeAudio.Callback);
    field @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public static final String ACTION_LE_AUDIO_ACTIVE_DEVICE_CHANGED = "android.bluetooth.action.LE_AUDIO_ACTIVE_DEVICE_CHANGED";
    field @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public static final String ACTION_LE_AUDIO_GROUP_NODE_STATUS_CHANGED = "android.bluetooth.action.LE_AUDIO_GROUP_NODE_STATUS_CHANGED";
    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public static final String ACTION_LE_AUDIO_GROUP_STATUS_CHANGED = "android.bluetooth.action.LE_AUDIO_GROUP_STATUS_CHANGED";
    field public static final int AUDIO_LOCATION_BACK_CENTER = 256; // 0x100
    field public static final int AUDIO_LOCATION_BACK_LEFT = 16; // 0x10
    field public static final int AUDIO_LOCATION_BACK_RIGHT = 32; // 0x20
@@ -383,14 +381,13 @@ package android.bluetooth {
    field public static final int AUDIO_LOCATION_TOP_SIDE_LEFT = 262144; // 0x40000
    field public static final int AUDIO_LOCATION_TOP_SIDE_RIGHT = 524288; // 0x80000
    field public static final String EXTRA_LE_AUDIO_GROUP_ID = "android.bluetooth.extra.LE_AUDIO_GROUP_ID";
    field public static final String EXTRA_LE_AUDIO_GROUP_NODE_STATUS = "android.bluetooth.extra.LE_AUDIO_GROUP_NODE_STATUS";
    field public static final String EXTRA_LE_AUDIO_GROUP_STATUS = "android.bluetooth.extra.LE_AUDIO_GROUP_STATUS";
    field public static final int GROUP_NODE_ADDED = 1; // 0x1
    field public static final int GROUP_NODE_REMOVED = 2; // 0x2
  }

  public static interface BluetoothLeAudio.Callback {
    method public void onCodecConfigChanged(int, @NonNull android.bluetooth.BluetoothLeAudioCodecStatus);
    method public void onGroupNodeAdded(@NonNull android.bluetooth.BluetoothDevice, int);
    method public void onGroupNodeRemoved(@NonNull android.bluetooth.BluetoothDevice, int);
    method public void onGroupStatusChanged(int, int);
  }

  public final class BluetoothLeAudioCodecConfigMetadata implements android.os.Parcelable {
+81 −108

File changed.

Preview size limit exceeded, changes collapsed.

+3 −0
Original line number Diff line number Diff line
@@ -28,4 +28,7 @@ import java.util.List;
 */
oneway interface IBluetoothLeAudioCallback {
    void onCodecConfigChanged(in int groupId, in BluetoothLeAudioCodecStatus status);
    void onGroupNodeAdded(in BluetoothDevice device, int groupId);
    void onGroupNodeRemoved(in BluetoothDevice device, int groupId);
    void onGroupStatusChanged(int groupId, int groupStatus);
}