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

Commit 040124cc authored by Yanting Yang's avatar Yanting Yang Committed by Android (Google) Code Review
Browse files

Merge "Support Bluetooth activation in BluetoothDevicesSlice"

parents 0b974088 54163423
Loading
Loading
Loading
Loading
+43 −24
Original line number Diff line number Diff line
@@ -46,6 +46,7 @@ import com.android.settings.connecteddevice.ConnectedDeviceDashboardFragment;
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.slices.CustomSliceRegistry;
import com.android.settings.slices.CustomSliceable;
import com.android.settings.slices.SliceBroadcastReceiver;
import com.android.settings.slices.SliceBuilderUtils;
import com.android.settingslib.bluetooth.BluetoothUtils;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
@@ -59,10 +60,12 @@ import java.util.stream.Collectors;

public class BluetoothDevicesSlice implements CustomSliceable {

    @VisibleForTesting
    static final String BLUETOOTH_DEVICE_HASH_CODE = "bluetooth_device_hash_code";

    /**
     * TODO(b/114807655): Contextual Home Page - Connected Device
     * Re-design sorting for new rule:
     * Sorting rule: Audio Streaming > Last connected > Recently connected.
     * Refer {@link com.android.settings.bluetooth.BluetoothDevicePreference#compareTo} to sort the
     * Bluetooth devices by {@link CachedBluetoothDevice}.
     */
    private static final Comparator<CachedBluetoothDevice> COMPARATOR
            = Comparator.naturalOrder();
@@ -109,12 +112,11 @@ public class BluetoothDevicesSlice implements CustomSliceable {
        final SliceAction primarySliceAction = SliceAction.createDeeplink(primaryActionIntent, icon,
                ListBuilder.ICON_IMAGE, title);
        final ListBuilder listBuilder =
                new ListBuilder(mContext, CustomSliceRegistry.BLUETOOTH_DEVICES_SLICE_URI,
                        ListBuilder.INFINITY)
                new ListBuilder(mContext, getUri(), ListBuilder.INFINITY)
                        .setAccentColor(Utils.getColorAccentDefaultColor(mContext));

        // Get row builders by Bluetooth devices.
        final List<ListBuilder.RowBuilder> rows = getBluetoothRowBuilder(primarySliceAction);
        final List<ListBuilder.RowBuilder> rows = getBluetoothRowBuilder();

        // Return a header with IsError flag, if no Bluetooth devices.
        if (rows.isEmpty()) {
@@ -131,7 +133,7 @@ public class BluetoothDevicesSlice implements CustomSliceable {
                .setSubtitle(getSubTitle(rows.size()))
                .setPrimaryAction(primarySliceAction));

        // Add bluetooth device rows.
        // Add Bluetooth device rows.
        for (ListBuilder.RowBuilder rowBuilder : rows) {
            listBuilder.addRow(rowBuilder);
        }
@@ -154,11 +156,19 @@ public class BluetoothDevicesSlice implements CustomSliceable {
                screenTitle,
                MetricsProto.MetricsEvent.SLICE)
                .setClassName(mContext.getPackageName(), SubSettings.class.getName())
                .setData(CustomSliceRegistry.BLUETOOTH_DEVICES_SLICE_URI);
                .setData(getUri());
    }

    @Override
    public void onNotifyChange(Intent intent) {
        // Activate available media device.
        final int bluetoothDeviceHashCode = intent.getIntExtra(BLUETOOTH_DEVICE_HASH_CODE, -1);
        for (CachedBluetoothDevice cachedBluetoothDevice : getConnectedBluetoothDevices()) {
            if (cachedBluetoothDevice.hashCode() == bluetoothDeviceHashCode) {
                cachedBluetoothDevice.setActive();
                return;
            }
        }
    }

    @Override
@@ -167,10 +177,10 @@ public class BluetoothDevicesSlice implements CustomSliceable {
    }

    @VisibleForTesting
    List<CachedBluetoothDevice> getBluetoothDevices() {
    List<CachedBluetoothDevice> getConnectedBluetoothDevices() {
        final List<CachedBluetoothDevice> bluetoothDeviceList = new ArrayList<>();

        // If Bluetooth is disable, skip to get the bluetooth devices.
        // If Bluetooth is disable, skip to get the Bluetooth devices.
        if (!BluetoothAdapter.getDefaultAdapter().isEnabled()) {
            Log.i(TAG, "Cannot get Bluetooth devices, Bluetooth is disabled.");
            return bluetoothDeviceList;
@@ -188,12 +198,13 @@ public class BluetoothDevicesSlice implements CustomSliceable {

        /**
         * TODO(b/114807655): Contextual Home Page - Connected Device
         * Re-design to get all Bluetooth devices and sort them by new rule:
         * Sorting rule: Audio Streaming > Last connected > Recently connected.
         * It's under discussion for including available media devices and currently connected
         * devices from Bluetooth. Will update the devices list or remove TODO later.
         */
        // Get connected Bluetooth devices and sort them.
        return cachedDevices.stream().filter(device -> device.isConnected()).sorted(
                COMPARATOR).collect(Collectors.toList());
        // Get available media device list and sort them.
        return cachedDevices.stream()
                .filter(device -> device.isConnected() && device.isConnectedA2dpDevice())
                .sorted(COMPARATOR).collect(Collectors.toList());
    }

    @VisibleForTesting
@@ -226,27 +237,35 @@ public class BluetoothDevicesSlice implements CustomSliceable {
        }
    }

    private List<ListBuilder.RowBuilder> getBluetoothRowBuilder(SliceAction primarySliceAction) {
    private List<ListBuilder.RowBuilder> getBluetoothRowBuilder() {
        // According Bluetooth devices to create row builders.
        final List<ListBuilder.RowBuilder> bluetoothRows = new ArrayList<>();

        /**
         * TODO(b/114807655): Contextual Home Page - Connected Device
         * Re-design to do action "activating" in primary action.
         */
        // According Bluetooth device to create row builders.
        final List<CachedBluetoothDevice> bluetoothDevices = getBluetoothDevices();
        final List<CachedBluetoothDevice> bluetoothDevices = getConnectedBluetoothDevices();
        for (CachedBluetoothDevice bluetoothDevice : bluetoothDevices) {
            bluetoothRows.add(new ListBuilder.RowBuilder()
                    .setTitleItem(getBluetoothDeviceIcon(bluetoothDevice), ListBuilder.ICON_IMAGE)
                    .setTitle(bluetoothDevice.getName())
                    .setSubtitle(bluetoothDevice.getConnectionSummary())
                    .setPrimaryAction(primarySliceAction)
                    .setPrimaryAction(buildBluetoothDeviceAction(bluetoothDevice))
                    .addEndItem(buildBluetoothDetailDeepLinkAction(bluetoothDevice)));
        }

        return bluetoothRows;
    }

    private SliceAction buildBluetoothDeviceAction(CachedBluetoothDevice bluetoothDevice) {
        // Send broadcast to activate available media device.
        final Intent intent = new Intent(getUri().toString())
                .setClass(mContext, SliceBroadcastReceiver.class)
                .putExtra(BLUETOOTH_DEVICE_HASH_CODE, bluetoothDevice.hashCode());

        return SliceAction.create(
                PendingIntent.getBroadcast(mContext, bluetoothDevice.hashCode(), intent, 0),
                getBluetoothDeviceIcon(bluetoothDevice),
                ListBuilder.ICON_IMAGE,
                bluetoothDevice.getName());
    }

    private SliceAction buildBluetoothDetailDeepLinkAction(CachedBluetoothDevice bluetoothDevice) {
        return SliceAction.createDeeplink(
                getBluetoothDetailIntent(bluetoothDevice),
+22 −5
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.app.PendingIntent;
@@ -54,6 +55,7 @@ import java.util.List;
@RunWith(RobolectricTestRunner.class)
public class BluetoothDevicesSliceTest {

    private static final String BLUETOOTH_MOCK_ADDRESS = "00:11:00:11:00:11";
    private static final String BLUETOOTH_MOCK_SUMMARY = "BluetoothSummary";
    private static final String BLUETOOTH_MOCK_TITLE = "BluetoothTitle";

@@ -96,7 +98,7 @@ public class BluetoothDevicesSliceTest {
    @Test
    public void getSlice_hasBluetoothDevices_shouldHaveBluetoothDevicesTitle() {
        mockBluetoothDeviceList();
        doReturn(mBluetoothDeviceList).when(mBluetoothDevicesSlice).getBluetoothDevices();
        doReturn(mBluetoothDeviceList).when(mBluetoothDevicesSlice).getConnectedBluetoothDevices();

        final Slice slice = mBluetoothDevicesSlice.getSlice();

@@ -107,7 +109,7 @@ public class BluetoothDevicesSliceTest {
    @Test
    public void getSlice_hasBluetoothDevices_shouldMatchBluetoothMockTitle() {
        mockBluetoothDeviceList();
        doReturn(mBluetoothDeviceList).when(mBluetoothDevicesSlice).getBluetoothDevices();
        doReturn(mBluetoothDeviceList).when(mBluetoothDevicesSlice).getConnectedBluetoothDevices();

        final Slice slice = mBluetoothDevicesSlice.getSlice();

@@ -118,7 +120,7 @@ public class BluetoothDevicesSliceTest {
    @Test
    public void getSlice_hasBluetoothDevices_shouldHavePairNewDevice() {
        mockBluetoothDeviceList();
        doReturn(mBluetoothDeviceList).when(mBluetoothDevicesSlice).getBluetoothDevices();
        doReturn(mBluetoothDeviceList).when(mBluetoothDevicesSlice).getConnectedBluetoothDevices();

        final Slice slice = mBluetoothDevicesSlice.getSlice();

@@ -129,7 +131,7 @@ public class BluetoothDevicesSliceTest {

    @Test
    public void getSlice_noBluetoothDevices_shouldHaveNoBluetoothDevicesTitle() {
        doReturn(mBluetoothDeviceList).when(mBluetoothDevicesSlice).getBluetoothDevices();
        doReturn(mBluetoothDeviceList).when(mBluetoothDevicesSlice).getConnectedBluetoothDevices();

        final Slice slice = mBluetoothDevicesSlice.getSlice();

@@ -139,7 +141,7 @@ public class BluetoothDevicesSliceTest {

    @Test
    public void getSlice_noBluetoothDevices_shouldNotHavePairNewDevice() {
        doReturn(mBluetoothDeviceList).when(mBluetoothDevicesSlice).getBluetoothDevices();
        doReturn(mBluetoothDeviceList).when(mBluetoothDevicesSlice).getConnectedBluetoothDevices();

        final Slice slice = mBluetoothDevicesSlice.getSlice();

@@ -148,9 +150,24 @@ public class BluetoothDevicesSliceTest {
                mContext.getString(R.string.bluetooth_pairing_pref_title))).isFalse();
    }

    @Test
    public void onNotifyChange_mediaDevice_shouldActivateDevice() {
        mockBluetoothDeviceList();
        doReturn(mBluetoothDeviceList).when(mBluetoothDevicesSlice).getConnectedBluetoothDevices();
        final Intent intent = new Intent().putExtra(
                BluetoothDevicesSlice.BLUETOOTH_DEVICE_HASH_CODE,
                mCachedBluetoothDevice.hashCode());

        mBluetoothDevicesSlice.onNotifyChange(intent);

        verify(mCachedBluetoothDevice).setActive();
    }

    private void mockBluetoothDeviceList() {
        doReturn(BLUETOOTH_MOCK_TITLE).when(mCachedBluetoothDevice).getName();
        doReturn(BLUETOOTH_MOCK_SUMMARY).when(mCachedBluetoothDevice).getConnectionSummary();
        doReturn(BLUETOOTH_MOCK_ADDRESS).when(mCachedBluetoothDevice).getAddress();
        doReturn(true).when(mCachedBluetoothDevice).isConnectedA2dpDevice();
        mBluetoothDeviceList.add(mCachedBluetoothDevice);
    }