diff --git a/res/layout/horizontal_divider.xml b/res/layout/horizontal_divider.xml index a13442337ee..969854ea973 100644 --- a/res/layout/horizontal_divider.xml +++ b/res/layout/horizontal_divider.xml @@ -20,6 +20,4 @@ android:id="@+id/divider" android:layout_width="match_parent" android:layout_height="@dimen/horizontal_divider_height" - android:layout_marginTop="@dimen/horizontal_divider_margin_top" - android:layout_marginBottom="@dimen/horizontal_divider_margin_bottom" android:background="?android:attr/dividerHorizontal"/> \ No newline at end of file diff --git a/res/layout/settings_homepage.xml b/res/layout/settings_homepage.xml index 0140cedc117..f027d655349 100644 --- a/res/layout/settings_homepage.xml +++ b/res/layout/settings_homepage.xml @@ -27,5 +27,4 @@ android:layout_height="match_parent" android:layoutAnimation="@anim/layout_animation_fall_down"/> - diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java b/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java index f3fbf06310d..adfaf201cd6 100644 --- a/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java +++ b/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java @@ -33,6 +33,8 @@ import androidx.annotation.VisibleForTesting; import androidx.slice.Slice; import com.android.settings.homepage.contextualcards.deviceinfo.BatterySlice; +import com.android.settings.homepage.contextualcards.slices.ConnectedDeviceSlice; +import com.android.settings.wifi.WifiSlice; import com.android.settingslib.utils.AsyncLoaderCompat; import java.util.ArrayList; @@ -40,9 +42,13 @@ import java.util.List; import java.util.stream.Collectors; public class ContextualCardLoader extends AsyncLoaderCompat> { - private static final String TAG = "ContextualCardLoader"; + + @VisibleForTesting + static final int DEFAULT_CARD_COUNT = 4; static final int CARD_CONTENT_LOADER_ID = 1; + private static final String TAG = "ContextualCardLoader"; + private Context mContext; public interface CardContentLoaderListener { @@ -77,7 +83,30 @@ public class ContextualCardLoader extends AsyncLoaderCompat } } } - return filterEligibleCards(result); + return getFinalDisplayableCards(result); + } + + @VisibleForTesting + List getFinalDisplayableCards(List candidates) { + List eligibleCards = filterEligibleCards(candidates); + eligibleCards = eligibleCards.stream().limit(DEFAULT_CARD_COUNT).collect( + Collectors.toList()); + + if (eligibleCards.size() <= 2 || getNumberOfLargeCard(eligibleCards) == 0) { + return eligibleCards; + } + + if (eligibleCards.size() == DEFAULT_CARD_COUNT) { + eligibleCards.remove(eligibleCards.size() - 1); + } + + if (getNumberOfLargeCard(eligibleCards) == 1) { + return eligibleCards; + } + + eligibleCards.remove(eligibleCards.size() - 1); + + return eligibleCards; } @VisibleForTesting @@ -139,6 +168,13 @@ public class ContextualCardLoader extends AsyncLoaderCompat return true; } + private int getNumberOfLargeCard(List cards) { + return (int) cards.stream() + .filter(card -> card.getSliceUri().equals(WifiSlice.WIFI_URI) + || card.getSliceUri().equals(ConnectedDeviceSlice.CONNECTED_DEVICE_URI)) + .count(); + } + private long getAppVersionCode() { try { return mContext.getPackageManager().getPackageInfo(mContext.getPackageName(), diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java index e98e36f56f4..598e23f6f7c 100644 --- a/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java +++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java @@ -16,21 +16,31 @@ package com.android.settings.homepage.contextualcards; +import static com.android.settings.homepage.contextualcards.ContextualCardLoader.DEFAULT_CARD_COUNT; + 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 android.content.Context; import android.net.Uri; import com.android.settings.homepage.contextualcards.deviceinfo.BatterySlice; +import com.android.settings.homepage.contextualcards.slices.ConnectedDeviceSlice; import com.android.settings.slices.SettingsSliceProvider; import com.android.settings.testutils.SettingsRobolectricTestRunner; +import com.android.settings.wifi.WifiSlice; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.RuntimeEnvironment; import org.robolectric.shadows.ShadowContentResolver; +import org.robolectric.shadows.ShadowLog; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; @@ -45,7 +55,7 @@ public class ContextualCardLoaderTest { @Before public void setUp() { mContext = RuntimeEnvironment.application; - mContextualCardLoader = new ContextualCardLoader(mContext); + mContextualCardLoader = spy(new ContextualCardLoader(mContext)); mProvider = new SettingsSliceProvider(); ShadowContentResolver.registerProviderInternal(SettingsSliceProvider.SLICE_AUTHORITY, mProvider); @@ -92,6 +102,57 @@ public class ContextualCardLoaderTest { getContextualCard(sliceUri))).isFalse(); } + @Test + public void getFinalDisplayableCards_twoEligibleCards_shouldShowAll() { + final List cards = getContextualCardList().stream().limit(2) + .collect(Collectors.toList()); + doReturn(cards).when(mContextualCardLoader).filterEligibleCards(any(List.class)); + + final List result = mContextualCardLoader.getFinalDisplayableCards(cards); + + assertThat(result).hasSize(cards.size()); + } + + @Test + public void getFinalDisplayableCards_fiveEligibleCardsNoLarge_shouldShowDefaultCardCount() { + final List fiveCards = getContextualCardListWithNoLargeCard(); + doReturn(fiveCards).when(mContextualCardLoader).filterEligibleCards(any(List.class)); + + final List result = mContextualCardLoader.getFinalDisplayableCards( + fiveCards); + + assertThat(result).hasSize(DEFAULT_CARD_COUNT); + } + + @Test + public void getFinalDisplayableCards_threeEligibleCardsOneLarge_shouldShowThreeCards() { + final List cards = getContextualCardList().stream().limit(2) + .collect(Collectors.toList()); + cards.add(new ContextualCard.Builder() + .setName("test_gesture") + .setCardType(ContextualCard.CardType.SLICE) + .setSliceUri(Uri.parse( + "content://com.android.settings.test.slices/action/gesture_pick_up")) + .build()); + doReturn(cards).when(mContextualCardLoader).filterEligibleCards(any(List.class)); + + final List result = mContextualCardLoader.getFinalDisplayableCards(cards); + + assertThat(result).hasSize(3); + } + + @Test + public void getFinalDisplayableCards_threeEligibleCardsTwoLarge_shouldShowTwoCards() { + final List threeCards = getContextualCardList().stream().limit(3) + .collect(Collectors.toList()); + doReturn(threeCards).when(mContextualCardLoader).filterEligibleCards(any(List.class)); + + final List result = mContextualCardLoader.getFinalDisplayableCards( + threeCards); + + assertThat(result).hasSize(2); + } + private ContextualCard getContextualCard(String sliceUri) { return new ContextualCard.Builder() .setName("test_card") @@ -99,4 +160,69 @@ public class ContextualCardLoaderTest { .setSliceUri(Uri.parse(sliceUri)) .build(); } + + private List getContextualCardList() { + final List cards = new ArrayList<>(); + cards.add(new ContextualCard.Builder() + .setName("test_wifi") + .setCardType(ContextualCard.CardType.SLICE) + .setSliceUri(WifiSlice.WIFI_URI) + .build()); + cards.add(new ContextualCard.Builder() + .setName("test_flashlight") + .setCardType(ContextualCard.CardType.SLICE) + .setSliceUri( + Uri.parse("content://com.android.settings.test.slices/action/flashlight")) + .build()); + cards.add(new ContextualCard.Builder() + .setName("test_connected") + .setCardType(ContextualCard.CardType.SLICE) + .setSliceUri(ConnectedDeviceSlice.CONNECTED_DEVICE_URI) + .build()); + cards.add(new ContextualCard.Builder() + .setName("test_gesture") + .setCardType(ContextualCard.CardType.SLICE) + .setSliceUri(Uri.parse( + "content://com.android.settings.test.slices/action/gesture_pick_up")) + .build()); + cards.add(new ContextualCard.Builder() + .setName("test_battery") + .setCardType(ContextualCard.CardType.SLICE) + .setSliceUri(BatterySlice.BATTERY_CARD_URI) + .build()); + return cards; + } + + private List getContextualCardListWithNoLargeCard() { + final List cards = new ArrayList<>(); + cards.add(new ContextualCard.Builder() + .setName("test_rotate") + .setCardType(ContextualCard.CardType.SLICE) + .setSliceUri( + Uri.parse("content://com.android.settings.test.slices/action/auto_rotate")) + .build()); + cards.add(new ContextualCard.Builder() + .setName("test_flashlight") + .setCardType(ContextualCard.CardType.SLICE) + .setSliceUri( + Uri.parse("content://com.android.settings.test.slices/action/flashlight")) + .build()); + cards.add(new ContextualCard.Builder() + .setName("test_bt") + .setCardType(ContextualCard.CardType.SLICE) + .setSliceUri(Uri.parse("content://android.settings.test.slices/action/bluetooth")) + .build()); + cards.add(new ContextualCard.Builder() + .setName("test_gesture") + .setCardType(ContextualCard.CardType.SLICE) + .setSliceUri(Uri.parse( + "content://com.android.settings.test.slices/action/gesture_pick_up")) + .build()); + cards.add(new ContextualCard.Builder() + .setName("test_battery") + .setCardType(ContextualCard.CardType.SLICE) + .setSliceUri(BatterySlice.BATTERY_CARD_URI) + .build()); + return cards; + } }