Loading src/com/android/settings/homepage/contextualcards/slices/BluetoothDevicesSlice.java +43 −24 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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(); Loading Loading @@ -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()) { Loading @@ -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); } Loading @@ -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 Loading @@ -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; Loading @@ -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 Loading Loading @@ -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), Loading tests/robotests/src/com/android/settings/homepage/contextualcards/slices/BluetoothDevicesSliceTest.java +22 −5 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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"; Loading Loading @@ -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(); Loading @@ -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(); Loading @@ -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(); Loading @@ -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(); Loading @@ -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(); Loading @@ -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); } Loading Loading
src/com/android/settings/homepage/contextualcards/slices/BluetoothDevicesSlice.java +43 −24 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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(); Loading Loading @@ -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()) { Loading @@ -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); } Loading @@ -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 Loading @@ -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; Loading @@ -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 Loading Loading @@ -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), Loading
tests/robotests/src/com/android/settings/homepage/contextualcards/slices/BluetoothDevicesSliceTest.java +22 −5 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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"; Loading Loading @@ -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(); Loading @@ -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(); Loading @@ -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(); Loading @@ -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(); Loading @@ -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(); Loading @@ -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); } Loading