diff --git a/src/com/android/settings/homepage/contextualcards/slices/ConnectedDeviceSlice.java b/src/com/android/settings/homepage/contextualcards/slices/ConnectedDeviceSlice.java index 4ee8ff5cf50..b5d58b6176c 100644 --- a/src/com/android/settings/homepage/contextualcards/slices/ConnectedDeviceSlice.java +++ b/src/com/android/settings/homepage/contextualcards/slices/ConnectedDeviceSlice.java @@ -41,6 +41,7 @@ import com.android.settings.R; import com.android.settings.SubSettings; import com.android.settings.Utils; import com.android.settings.bluetooth.BluetoothDeviceDetailsFragment; +import com.android.settings.bluetooth.BluetoothPairingDetail; import com.android.settings.connecteddevice.ConnectedDeviceDashboardFragment; import com.android.settings.core.SubSettingLauncher; import com.android.settings.slices.CustomSliceRegistry; @@ -73,6 +74,12 @@ public class ConnectedDeviceSlice implements CustomSliceable { private static final Comparator COMPARATOR = Comparator.naturalOrder(); + /** + * Add the "Pair new device" in the end of slice, when the number of Bluetooth devices is less + * than {@link #DEFAULT_EXPANDED_ROW_COUNT}. + */ + private static final int DEFAULT_EXPANDED_ROW_COUNT = 3; + private static final String TAG = "ConnectedDeviceSlice"; private final Context mContext; @@ -131,10 +138,16 @@ public class ConnectedDeviceSlice implements CustomSliceable { .setSubtitle(getSubTitle(rows.size())) .setPrimaryAction(primarySliceAction)); - // Add rows. + // Add bluetooth device rows. for (ListBuilder.RowBuilder rowBuilder : rows) { listBuilder.addRow(rowBuilder); } + + // Add "Pair new device" if need. + if (rows.size() < DEFAULT_EXPANDED_ROW_COUNT) { + listBuilder.addRow(getPairNewDeviceRowBuilder()); + } + return listBuilder.build(); } @@ -244,4 +257,28 @@ public class ConnectedDeviceSlice implements CustomSliceable { return mContext.getResources().getQuantityString(R.plurals.show_connected_devices, deviceCount, deviceCount); } + + private ListBuilder.RowBuilder getPairNewDeviceRowBuilder() { + final CharSequence title = mContext.getText(R.string.bluetooth_pairing_pref_title); + final IconCompat icon = IconCompat.createWithResource(mContext, R.drawable.ic_menu_add); + final SliceAction sliceAction = SliceAction.createDeeplink( + getPairNewDeviceIntent(), + IconCompat.createWithResource(mContext, R.drawable.ic_settings), + ListBuilder.ICON_IMAGE, title); + + return new ListBuilder.RowBuilder() + .setTitleItem(icon, ListBuilder.ICON_IMAGE) + .setTitle(title) + .setPrimaryAction(sliceAction); + } + + private PendingIntent getPairNewDeviceIntent() { + final Intent intent = new SubSettingLauncher(mContext) + .setDestination(BluetoothPairingDetail.class.getName()) + .setTitleRes(R.string.bluetooth_pairing_page_title) + .setSourceMetricsCategory(SettingsEnums.BLUETOOTH_PAIRING) + .toIntent(); + + return PendingIntent.getActivity(mContext, 0 /* requestCode */, intent, 0 /* flags */); + } } \ No newline at end of file diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/ConnectedDeviceSliceTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/ConnectedDeviceSliceTest.java index 472d2caf9f7..14a2c477668 100644 --- a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/ConnectedDeviceSliceTest.java +++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/ConnectedDeviceSliceTest.java @@ -16,6 +16,8 @@ package com.android.settings.homepage.contextualcards.slices; +import static com.google.common.truth.Truth.assertThat; + import static org.mockito.Matchers.any; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.spy; @@ -24,10 +26,12 @@ import static org.mockito.Mockito.when; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; +import android.text.TextUtils; import androidx.core.graphics.drawable.IconCompat; import androidx.slice.Slice; import androidx.slice.SliceItem; +import androidx.slice.SliceMetadata; import androidx.slice.SliceProvider; import androidx.slice.widget.SliceLiveData; @@ -50,8 +54,8 @@ import java.util.List; @RunWith(SettingsRobolectricTestRunner.class) public class ConnectedDeviceSliceTest { - private static final String BLUETOOTH_SUMMARY = "BluetoothSummary"; - private static final String BLUETOOTH_TITLE = "BluetoothTitle"; + private static final String BLUETOOTH_MOCK_SUMMARY = "BluetoothSummary"; + private static final String BLUETOOTH_MOCK_TITLE = "BluetoothTitle"; @Mock private CachedBluetoothDevice mCachedBluetoothDevice; @@ -90,7 +94,7 @@ public class ConnectedDeviceSliceTest { } @Test - public void getSlice_hasConnectedDevices_shouldHaveCorrectTitle() { + public void getSlice_hasConnectedDevices_shouldHaveConnectedDeviceTitle() { mockBluetoothDeviceList(); doReturn(mBluetoothConnectedDeviceList).when( mConnectedDeviceSlice).getBluetoothConnectedDevices(); @@ -103,7 +107,7 @@ public class ConnectedDeviceSliceTest { } @Test - public void getSlice_hasConnectedDevices_shouldHaveCorrectContent() { + public void getSlice_hasConnectedDevices_shouldMatchBluetoothMockTitle() { mockBluetoothDeviceList(); doReturn(mBluetoothConnectedDeviceList).when( mConnectedDeviceSlice).getBluetoothConnectedDevices(); @@ -111,11 +115,24 @@ public class ConnectedDeviceSliceTest { final Slice slice = mConnectedDeviceSlice.getSlice(); final List sliceItems = slice.getItems(); - SliceTester.assertTitle(sliceItems, BLUETOOTH_TITLE); + SliceTester.assertTitle(sliceItems, BLUETOOTH_MOCK_TITLE); } @Test - public void getSlice_noConnectedDevices_shouldHaveCorrectTitle() { + public void getSlice_hasConnectedDevices_shouldHavePairNewDevice() { + mockBluetoothDeviceList(); + doReturn(mBluetoothConnectedDeviceList).when( + mConnectedDeviceSlice).getBluetoothConnectedDevices(); + + final Slice slice = mConnectedDeviceSlice.getSlice(); + + final List sliceItems = slice.getItems(); + SliceTester.assertTitle(sliceItems, + mContext.getString(R.string.bluetooth_pairing_pref_title)); + } + + @Test + public void getSlice_noConnectedDevices_shouldHaveNoConnectedDeviceTitle() { doReturn(mBluetoothConnectedDeviceList).when( mConnectedDeviceSlice).getBluetoothConnectedDevices(); @@ -125,9 +142,26 @@ public class ConnectedDeviceSliceTest { SliceTester.assertTitle(sliceItems, mContext.getString(R.string.no_connected_devices)); } + @Test + public void getSlice_noConnectedDevices_shouldNotHavePairNewDevice() { + doReturn(mBluetoothConnectedDeviceList).when( + mConnectedDeviceSlice).getBluetoothConnectedDevices(); + + final Slice slice = mConnectedDeviceSlice.getSlice(); + + final SliceMetadata metadata = SliceMetadata.from(mContext, slice); + assertThat(hasTitle(metadata, + mContext.getString(R.string.bluetooth_pairing_pref_title))).isFalse(); + } + private void mockBluetoothDeviceList() { - doReturn(BLUETOOTH_TITLE).when(mCachedBluetoothDevice).getName(); - doReturn(BLUETOOTH_SUMMARY).when(mCachedBluetoothDevice).getConnectionSummary(); + doReturn(BLUETOOTH_MOCK_TITLE).when(mCachedBluetoothDevice).getName(); + doReturn(BLUETOOTH_MOCK_SUMMARY).when(mCachedBluetoothDevice).getConnectionSummary(); mBluetoothConnectedDeviceList.add(mCachedBluetoothDevice); } + + private boolean hasTitle(SliceMetadata metadata, String title) { + final CharSequence sliceTitle = metadata.getTitle(); + return TextUtils.equals(sliceTitle, title); + } } \ No newline at end of file diff --git a/tests/robotests/src/com/android/settings/testutils/SliceTester.java b/tests/robotests/src/com/android/settings/testutils/SliceTester.java index 26eeb7196e1..c0ffdcde4a0 100644 --- a/tests/robotests/src/com/android/settings/testutils/SliceTester.java +++ b/tests/robotests/src/com/android/settings/testutils/SliceTester.java @@ -236,6 +236,7 @@ public class SliceTester { assertKeywords(metadata, sliceData); } + // TODO(b/120592507): Clean up method of SliceTester public static void assertTitle(List sliceItems, String title) { boolean hasTitle = false; for (SliceItem item : sliceItems) { @@ -255,6 +256,7 @@ public class SliceTester { assertThat(hasTitle).isTrue(); } + // TODO(b/120592507): Clean up method of SliceTester private static void assertKeywords(SliceMetadata metadata, SliceData data) { final List keywords = metadata.getSliceKeywords(); final Set expectedKeywords = Arrays.stream(data.getKeywords().split(","))