Merge "Support Bluetooth activation in BluetoothDevicesSlice"

This commit is contained in:
Yanting Yang
2018-12-21 03:44:42 +00:00
committed by Android (Google) Code Review
2 changed files with 65 additions and 29 deletions

View File

@@ -46,6 +46,7 @@ import com.android.settings.connecteddevice.ConnectedDeviceDashboardFragment;
import com.android.settings.core.SubSettingLauncher; import com.android.settings.core.SubSettingLauncher;
import com.android.settings.slices.CustomSliceRegistry; import com.android.settings.slices.CustomSliceRegistry;
import com.android.settings.slices.CustomSliceable; import com.android.settings.slices.CustomSliceable;
import com.android.settings.slices.SliceBroadcastReceiver;
import com.android.settings.slices.SliceBuilderUtils; import com.android.settings.slices.SliceBuilderUtils;
import com.android.settingslib.bluetooth.BluetoothUtils; import com.android.settingslib.bluetooth.BluetoothUtils;
import com.android.settingslib.bluetooth.CachedBluetoothDevice; import com.android.settingslib.bluetooth.CachedBluetoothDevice;
@@ -59,10 +60,12 @@ import java.util.stream.Collectors;
public class BluetoothDevicesSlice implements CustomSliceable { 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 * Refer {@link com.android.settings.bluetooth.BluetoothDevicePreference#compareTo} to sort the
* Re-design sorting for new rule: * Bluetooth devices by {@link CachedBluetoothDevice}.
* Sorting rule: Audio Streaming > Last connected > Recently connected.
*/ */
private static final Comparator<CachedBluetoothDevice> COMPARATOR private static final Comparator<CachedBluetoothDevice> COMPARATOR
= Comparator.naturalOrder(); = Comparator.naturalOrder();
@@ -109,12 +112,11 @@ public class BluetoothDevicesSlice implements CustomSliceable {
final SliceAction primarySliceAction = SliceAction.createDeeplink(primaryActionIntent, icon, final SliceAction primarySliceAction = SliceAction.createDeeplink(primaryActionIntent, icon,
ListBuilder.ICON_IMAGE, title); ListBuilder.ICON_IMAGE, title);
final ListBuilder listBuilder = final ListBuilder listBuilder =
new ListBuilder(mContext, CustomSliceRegistry.BLUETOOTH_DEVICES_SLICE_URI, new ListBuilder(mContext, getUri(), ListBuilder.INFINITY)
ListBuilder.INFINITY)
.setAccentColor(Utils.getColorAccentDefaultColor(mContext)); .setAccentColor(Utils.getColorAccentDefaultColor(mContext));
// Get row builders by Bluetooth devices. // 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. // Return a header with IsError flag, if no Bluetooth devices.
if (rows.isEmpty()) { if (rows.isEmpty()) {
@@ -131,7 +133,7 @@ public class BluetoothDevicesSlice implements CustomSliceable {
.setSubtitle(getSubTitle(rows.size())) .setSubtitle(getSubTitle(rows.size()))
.setPrimaryAction(primarySliceAction)); .setPrimaryAction(primarySliceAction));
// Add bluetooth device rows. // Add Bluetooth device rows.
for (ListBuilder.RowBuilder rowBuilder : rows) { for (ListBuilder.RowBuilder rowBuilder : rows) {
listBuilder.addRow(rowBuilder); listBuilder.addRow(rowBuilder);
} }
@@ -154,11 +156,19 @@ public class BluetoothDevicesSlice implements CustomSliceable {
screenTitle, screenTitle,
MetricsProto.MetricsEvent.SLICE) MetricsProto.MetricsEvent.SLICE)
.setClassName(mContext.getPackageName(), SubSettings.class.getName()) .setClassName(mContext.getPackageName(), SubSettings.class.getName())
.setData(CustomSliceRegistry.BLUETOOTH_DEVICES_SLICE_URI); .setData(getUri());
} }
@Override @Override
public void onNotifyChange(Intent intent) { 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 @Override
@@ -167,10 +177,10 @@ public class BluetoothDevicesSlice implements CustomSliceable {
} }
@VisibleForTesting @VisibleForTesting
List<CachedBluetoothDevice> getBluetoothDevices() { List<CachedBluetoothDevice> getConnectedBluetoothDevices() {
final List<CachedBluetoothDevice> bluetoothDeviceList = new ArrayList<>(); 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()) { if (!BluetoothAdapter.getDefaultAdapter().isEnabled()) {
Log.i(TAG, "Cannot get Bluetooth devices, Bluetooth is disabled."); Log.i(TAG, "Cannot get Bluetooth devices, Bluetooth is disabled.");
return bluetoothDeviceList; return bluetoothDeviceList;
@@ -188,12 +198,13 @@ public class BluetoothDevicesSlice implements CustomSliceable {
/** /**
* TODO(b/114807655): Contextual Home Page - Connected Device * TODO(b/114807655): Contextual Home Page - Connected Device
* Re-design to get all Bluetooth devices and sort them by new rule: * It's under discussion for including available media devices and currently connected
* Sorting rule: Audio Streaming > Last connected > Recently connected. * devices from Bluetooth. Will update the devices list or remove TODO later.
*/ */
// Get connected Bluetooth devices and sort them. // Get available media device list and sort them.
return cachedDevices.stream().filter(device -> device.isConnected()).sorted( return cachedDevices.stream()
COMPARATOR).collect(Collectors.toList()); .filter(device -> device.isConnected() && device.isConnectedA2dpDevice())
.sorted(COMPARATOR).collect(Collectors.toList());
} }
@VisibleForTesting @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<>(); final List<ListBuilder.RowBuilder> bluetoothRows = new ArrayList<>();
final List<CachedBluetoothDevice> bluetoothDevices = getConnectedBluetoothDevices();
/**
* 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();
for (CachedBluetoothDevice bluetoothDevice : bluetoothDevices) { for (CachedBluetoothDevice bluetoothDevice : bluetoothDevices) {
bluetoothRows.add(new ListBuilder.RowBuilder() bluetoothRows.add(new ListBuilder.RowBuilder()
.setTitleItem(getBluetoothDeviceIcon(bluetoothDevice), ListBuilder.ICON_IMAGE) .setTitleItem(getBluetoothDeviceIcon(bluetoothDevice), ListBuilder.ICON_IMAGE)
.setTitle(bluetoothDevice.getName()) .setTitle(bluetoothDevice.getName())
.setSubtitle(bluetoothDevice.getConnectionSummary()) .setSubtitle(bluetoothDevice.getConnectionSummary())
.setPrimaryAction(primarySliceAction) .setPrimaryAction(buildBluetoothDeviceAction(bluetoothDevice))
.addEndItem(buildBluetoothDetailDeepLinkAction(bluetoothDevice))); .addEndItem(buildBluetoothDetailDeepLinkAction(bluetoothDevice)));
} }
return bluetoothRows; 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) { private SliceAction buildBluetoothDetailDeepLinkAction(CachedBluetoothDevice bluetoothDevice) {
return SliceAction.createDeeplink( return SliceAction.createDeeplink(
getBluetoothDetailIntent(bluetoothDevice), getBluetoothDetailIntent(bluetoothDevice),

View File

@@ -21,6 +21,7 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy; import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import android.app.PendingIntent; import android.app.PendingIntent;
@@ -54,6 +55,7 @@ import java.util.List;
@RunWith(RobolectricTestRunner.class) @RunWith(RobolectricTestRunner.class)
public class BluetoothDevicesSliceTest { 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_SUMMARY = "BluetoothSummary";
private static final String BLUETOOTH_MOCK_TITLE = "BluetoothTitle"; private static final String BLUETOOTH_MOCK_TITLE = "BluetoothTitle";
@@ -96,7 +98,7 @@ public class BluetoothDevicesSliceTest {
@Test @Test
public void getSlice_hasBluetoothDevices_shouldHaveBluetoothDevicesTitle() { public void getSlice_hasBluetoothDevices_shouldHaveBluetoothDevicesTitle() {
mockBluetoothDeviceList(); mockBluetoothDeviceList();
doReturn(mBluetoothDeviceList).when(mBluetoothDevicesSlice).getBluetoothDevices(); doReturn(mBluetoothDeviceList).when(mBluetoothDevicesSlice).getConnectedBluetoothDevices();
final Slice slice = mBluetoothDevicesSlice.getSlice(); final Slice slice = mBluetoothDevicesSlice.getSlice();
@@ -107,7 +109,7 @@ public class BluetoothDevicesSliceTest {
@Test @Test
public void getSlice_hasBluetoothDevices_shouldMatchBluetoothMockTitle() { public void getSlice_hasBluetoothDevices_shouldMatchBluetoothMockTitle() {
mockBluetoothDeviceList(); mockBluetoothDeviceList();
doReturn(mBluetoothDeviceList).when(mBluetoothDevicesSlice).getBluetoothDevices(); doReturn(mBluetoothDeviceList).when(mBluetoothDevicesSlice).getConnectedBluetoothDevices();
final Slice slice = mBluetoothDevicesSlice.getSlice(); final Slice slice = mBluetoothDevicesSlice.getSlice();
@@ -118,7 +120,7 @@ public class BluetoothDevicesSliceTest {
@Test @Test
public void getSlice_hasBluetoothDevices_shouldHavePairNewDevice() { public void getSlice_hasBluetoothDevices_shouldHavePairNewDevice() {
mockBluetoothDeviceList(); mockBluetoothDeviceList();
doReturn(mBluetoothDeviceList).when(mBluetoothDevicesSlice).getBluetoothDevices(); doReturn(mBluetoothDeviceList).when(mBluetoothDevicesSlice).getConnectedBluetoothDevices();
final Slice slice = mBluetoothDevicesSlice.getSlice(); final Slice slice = mBluetoothDevicesSlice.getSlice();
@@ -129,7 +131,7 @@ public class BluetoothDevicesSliceTest {
@Test @Test
public void getSlice_noBluetoothDevices_shouldHaveNoBluetoothDevicesTitle() { public void getSlice_noBluetoothDevices_shouldHaveNoBluetoothDevicesTitle() {
doReturn(mBluetoothDeviceList).when(mBluetoothDevicesSlice).getBluetoothDevices(); doReturn(mBluetoothDeviceList).when(mBluetoothDevicesSlice).getConnectedBluetoothDevices();
final Slice slice = mBluetoothDevicesSlice.getSlice(); final Slice slice = mBluetoothDevicesSlice.getSlice();
@@ -139,7 +141,7 @@ public class BluetoothDevicesSliceTest {
@Test @Test
public void getSlice_noBluetoothDevices_shouldNotHavePairNewDevice() { public void getSlice_noBluetoothDevices_shouldNotHavePairNewDevice() {
doReturn(mBluetoothDeviceList).when(mBluetoothDevicesSlice).getBluetoothDevices(); doReturn(mBluetoothDeviceList).when(mBluetoothDevicesSlice).getConnectedBluetoothDevices();
final Slice slice = mBluetoothDevicesSlice.getSlice(); final Slice slice = mBluetoothDevicesSlice.getSlice();
@@ -148,9 +150,24 @@ public class BluetoothDevicesSliceTest {
mContext.getString(R.string.bluetooth_pairing_pref_title))).isFalse(); 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() { private void mockBluetoothDeviceList() {
doReturn(BLUETOOTH_MOCK_TITLE).when(mCachedBluetoothDevice).getName(); doReturn(BLUETOOTH_MOCK_TITLE).when(mCachedBluetoothDevice).getName();
doReturn(BLUETOOTH_MOCK_SUMMARY).when(mCachedBluetoothDevice).getConnectionSummary(); doReturn(BLUETOOTH_MOCK_SUMMARY).when(mCachedBluetoothDevice).getConnectionSummary();
doReturn(BLUETOOTH_MOCK_ADDRESS).when(mCachedBluetoothDevice).getAddress();
doReturn(true).when(mCachedBluetoothDevice).isConnectedA2dpDevice();
mBluetoothDeviceList.add(mCachedBluetoothDevice); mBluetoothDeviceList.add(mCachedBluetoothDevice);
} }