Merge "Do not allow draw on top for App notification settings"
diff --git a/res/layout/homepage_slice_tile.xml b/res/layout/homepage_slice_tile.xml
index 807c26b..e95129e 100644
--- a/res/layout/homepage_slice_tile.xml
+++ b/res/layout/homepage_slice_tile.xml
@@ -31,6 +31,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
+ android:animateLayoutChanges="true"
style="@style/SliceViewStyle"/>
<!--dismissal view-->
diff --git a/res/xml/language_and_input.xml b/res/xml/language_and_input.xml
index b04bdf8..e3690a9 100644
--- a/res/xml/language_and_input.xml
+++ b/res/xml/language_and_input.xml
@@ -94,7 +94,8 @@
<com.android.settings.widget.WorkOnlyCategory
android:key="language_and_input_for_work_category"
- android:title="@string/language_and_input_for_work_category_title">
+ android:title="@string/language_and_input_for_work_category_title"
+ settings:searchable="false">
<Preference
android:key="virtual_keyboards_for_work_pref"
diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java b/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java
index ea6ac43..13564b5 100644
--- a/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java
+++ b/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java
@@ -26,7 +26,6 @@
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
-import android.text.format.DateUtils;
import android.util.Log;
import androidx.annotation.NonNull;
@@ -50,7 +49,6 @@
@VisibleForTesting
static final int DEFAULT_CARD_COUNT = 4;
static final int CARD_CONTENT_LOADER_ID = 1;
- static final long CARD_CONTENT_LOADER_TIMEOUT_MS = DateUtils.SECOND_IN_MILLIS;
private static final String TAG = "ContextualCardLoader";
private static final long ELIGIBILITY_CHECKER_TIMEOUT_MS = 250;
diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java b/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java
index 3b8aacd..c829015 100644
--- a/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java
+++ b/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java
@@ -24,6 +24,8 @@
import android.content.Context;
import android.os.Bundle;
+import android.provider.Settings;
+import android.text.format.DateUtils;
import android.util.ArrayMap;
import android.util.Log;
import android.widget.BaseAdapter;
@@ -62,8 +64,12 @@
public class ContextualCardManager implements ContextualCardLoader.CardContentLoaderListener,
ContextualCardUpdateListener, LifecycleObserver, OnSaveInstanceState {
- private static final String KEY_CONTEXTUAL_CARDS = "key_contextual_cards";
+ @VisibleForTesting
+ static final long CARD_CONTENT_LOADER_TIMEOUT_MS = DateUtils.SECOND_IN_MILLIS;
+ @VisibleForTesting
+ static final String KEY_GLOBAL_CARD_LOADER_TIMEOUT = "global_card_loader_timeout_key";
+ private static final String KEY_CONTEXTUAL_CARDS = "key_contextual_cards";
private static final String TAG = "ContextualCardManager";
//The list for Settings Custom Card
@@ -201,7 +207,8 @@
}
//only log homepage display upon a fresh launch
- if (loadTime <= ContextualCardLoader.CARD_CONTENT_LOADER_TIMEOUT_MS) {
+ final long timeoutLimit = getCardLoaderTimeout(mContext);
+ if (loadTime <= timeoutLimit) {
onContextualCardUpdated(cards.stream()
.collect(groupingBy(ContextualCard::getCardType)));
}
@@ -239,6 +246,14 @@
return getCardsWithSuggestionViewType(result);
}
+ @VisibleForTesting
+ long getCardLoaderTimeout(Context context) {
+ // Return the timeout limit if Settings.Global has the KEY_GLOBAL_CARD_LOADER_TIMEOUT key,
+ // else return default timeout.
+ return Settings.Global.getLong(mContext.getContentResolver(),
+ KEY_GLOBAL_CARD_LOADER_TIMEOUT, CARD_CONTENT_LOADER_TIMEOUT_MS);
+ }
+
private List<ContextualCard> getCardsWithSuggestionViewType(List<ContextualCard> cards) {
// Shows as half cards if 2 suggestion type of cards are next to each other.
// Shows as full card if 1 suggestion type of card lives alone.
diff --git a/src/com/android/settings/homepage/contextualcards/slices/BluetoothDevicesSlice.java b/src/com/android/settings/homepage/contextualcards/slices/BluetoothDevicesSlice.java
index 95412a8..3320be0 100644
--- a/src/com/android/settings/homepage/contextualcards/slices/BluetoothDevicesSlice.java
+++ b/src/com/android/settings/homepage/contextualcards/slices/BluetoothDevicesSlice.java
@@ -179,14 +179,9 @@
final Collection<CachedBluetoothDevice> cachedDevices =
bluetoothManager.getCachedDeviceManager().getCachedDevicesCopy();
- /**
- * TODO(b/114807655): Contextual Home Page - Connected Device
- * 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 available media device list and sort them.
+ // Get all connected devices and sort them.
return cachedDevices.stream()
- .filter(device -> device.isConnected() && device.isConnectedA2dpDevice())
+ .filter(device -> device.getDevice().isConnected())
.sorted(COMPARATOR).collect(Collectors.toList());
}
@@ -217,7 +212,7 @@
return Utils.createIconWithDrawable(pair.first);
} else {
return IconCompat.createWithResource(mContext,
- com.android.internal.R.drawable.ic_settings_bluetooth);
+ com.android.internal.R.drawable.ic_settings_bluetooth);
}
}
@@ -226,18 +221,29 @@
final List<ListBuilder.RowBuilder> bluetoothRows = new ArrayList<>();
final List<CachedBluetoothDevice> bluetoothDevices = getConnectedBluetoothDevices();
for (CachedBluetoothDevice bluetoothDevice : bluetoothDevices) {
- bluetoothRows.add(new ListBuilder.RowBuilder()
+ final ListBuilder.RowBuilder rowBuilder = new ListBuilder.RowBuilder()
.setTitleItem(getBluetoothDeviceIcon(bluetoothDevice), ListBuilder.ICON_IMAGE)
.setTitle(bluetoothDevice.getName())
- .setSubtitle(bluetoothDevice.getConnectionSummary())
- .setPrimaryAction(buildBluetoothDeviceAction(bluetoothDevice))
- .addEndItem(buildBluetoothDetailDeepLinkAction(bluetoothDevice)));
+ .setSubtitle(bluetoothDevice.getConnectionSummary());
+
+ if (bluetoothDevice.isConnectedA2dpDevice()) {
+ // For available media devices, the primary action is to active audio stream and
+ // add setting icon to the end to link detail page.
+ rowBuilder.setPrimaryAction(buildMediaBluetoothAction(bluetoothDevice));
+ rowBuilder.addEndItem(buildBluetoothDetailDeepLinkAction(bluetoothDevice));
+ } else {
+ // For other devices, the primary action is to link detail page.
+ rowBuilder.setPrimaryAction(buildBluetoothDetailDeepLinkAction(bluetoothDevice));
+ }
+
+ bluetoothRows.add(rowBuilder);
}
return bluetoothRows;
}
- private SliceAction buildBluetoothDeviceAction(CachedBluetoothDevice bluetoothDevice) {
+ @VisibleForTesting
+ SliceAction buildMediaBluetoothAction(CachedBluetoothDevice bluetoothDevice) {
// Send broadcast to activate available media device.
final Intent intent = new Intent(getUri().toString())
.setClass(mContext, SliceBroadcastReceiver.class)
@@ -250,7 +256,8 @@
bluetoothDevice.getName());
}
- private SliceAction buildBluetoothDetailDeepLinkAction(CachedBluetoothDevice bluetoothDevice) {
+ @VisibleForTesting
+ SliceAction buildBluetoothDetailDeepLinkAction(CachedBluetoothDevice bluetoothDevice) {
return SliceAction.createDeeplink(
getBluetoothDetailIntent(bluetoothDevice),
IconCompat.createWithResource(mContext, R.drawable.ic_settings_24dp),
diff --git a/src/com/android/settings/homepage/contextualcards/slices/SliceFullCardRendererHelper.java b/src/com/android/settings/homepage/contextualcards/slices/SliceFullCardRendererHelper.java
index ef0a67d..ee63536 100644
--- a/src/com/android/settings/homepage/contextualcards/slices/SliceFullCardRendererHelper.java
+++ b/src/com/android/settings/homepage/contextualcards/slices/SliceFullCardRendererHelper.java
@@ -16,6 +16,7 @@
package com.android.settings.homepage.contextualcards.slices;
+import android.animation.LayoutTransition;
import android.content.Context;
import android.view.View;
@@ -94,6 +95,7 @@
public SliceViewHolder(View view) {
super(view);
sliceView = view.findViewById(R.id.slice_view);
+ sliceView.getLayoutTransition().enableTransitionType(LayoutTransition.CHANGING);
}
}
}
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardManagerTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardManagerTest.java
index 1a0539c..eb9a461 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardManagerTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardManagerTest.java
@@ -31,6 +31,7 @@
import android.content.Context;
import android.net.Uri;
+import android.provider.Settings;
import android.util.ArrayMap;
import com.android.settings.homepage.contextualcards.conditional.ConditionFooterContextualCard;
@@ -126,6 +127,24 @@
}
@Test
+ public void getCardLoaderTimeout_noConfiguredTimeout_shouldReturnDefaultTimeout() {
+ final long timeout = mManager.getCardLoaderTimeout(mContext);
+
+ assertThat(timeout).isEqualTo(ContextualCardManager.CARD_CONTENT_LOADER_TIMEOUT_MS);
+ }
+
+ @Test
+ public void getCardLoaderTimeout_hasConfiguredTimeout_shouldReturnConfiguredTimeout() {
+ final long configuredTimeout = 5000L;
+ Settings.Global.putLong(mContext.getContentResolver(),
+ ContextualCardManager.KEY_GLOBAL_CARD_LOADER_TIMEOUT, configuredTimeout);
+
+ final long timeout = mManager.getCardLoaderTimeout(mContext);
+
+ assertThat(timeout).isEqualTo(configuredTimeout);
+ }
+
+ @Test
public void onFinishCardLoading_fastLoad_shouldCallOnContextualCardUpdated() {
mManager.mStartTime = System.currentTimeMillis();
final ContextualCardManager manager = spy(mManager);
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/BluetoothDevicesSliceTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/BluetoothDevicesSliceTest.java
index 77fc5d9..4a23c33 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/BluetoothDevicesSliceTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/BluetoothDevicesSliceTest.java
@@ -23,6 +23,7 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -83,7 +84,7 @@
// Mock the icon and detail intent of Bluetooth.
mIcon = IconCompat.createWithResource(mContext,
- com.android.internal.R.drawable.ic_settings_bluetooth);
+ com.android.internal.R.drawable.ic_settings_bluetooth);
mDetailIntent = PendingIntent.getActivity(mContext, 0, new Intent("test action"), 0);
doReturn(mIcon).when(mBluetoothDevicesSlice).getBluetoothDeviceIcon(any());
doReturn(mDetailIntent).when(mBluetoothDevicesSlice).getBluetoothDetailIntent(any());
@@ -122,6 +123,27 @@
}
@Test
+ public void getSlice_hasMediaBluetoothDevice_shouldBuildMediaBluetoothAction() {
+ mockBluetoothDeviceList(1 /* deviceCount */);
+ doReturn(true).when(mBluetoothDeviceList.get(0)).isConnectedA2dpDevice();
+ doReturn(mBluetoothDeviceList).when(mBluetoothDevicesSlice).getConnectedBluetoothDevices();
+
+ mBluetoothDevicesSlice.getSlice();
+
+ verify(mBluetoothDevicesSlice).buildMediaBluetoothAction(any());
+ }
+
+ @Test
+ public void getSlice_noMediaBluetoothDevice_shouldNotBuildMediaBluetoothAction() {
+ mockBluetoothDeviceList(1 /* deviceCount */);
+ doReturn(mBluetoothDeviceList).when(mBluetoothDevicesSlice).getConnectedBluetoothDevices();
+
+ mBluetoothDevicesSlice.getSlice();
+
+ verify(mBluetoothDevicesSlice, never()).buildMediaBluetoothAction(any());
+ }
+
+ @Test
public void getSlice_noBluetoothDevices_shouldHaveNoBluetoothDevicesTitle() {
doReturn(mBluetoothDeviceList).when(mBluetoothDevicesSlice).getConnectedBluetoothDevices();
@@ -175,7 +197,6 @@
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();
for (int i = 0; i < deviceCount; i++) {
mBluetoothDeviceList.add(mCachedBluetoothDevice);
}