Loading src/com/android/settings/homepage/contextualcards/ContextualCardManager.java +13 −8 Original line number Diff line number Diff line Loading @@ -72,26 +72,29 @@ public class ContextualCardManager implements ContextualCardLoader.CardContentLo 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"; @VisibleForTesting static final String KEY_CONTEXTUAL_CARDS = "key_contextual_cards"; private static final String KEY_CONTEXTUAL_CARDS = "key_contextual_cards"; private static final String TAG = "ContextualCardManager"; //The list for Settings Custom Card private static final int[] SETTINGS_CARDS = {ContextualCard.CardType.CONDITIONAL, ContextualCard.CardType.LEGACY_SUGGESTION}; @VisibleForTesting final List<ContextualCard> mContextualCards; private final Context mContext; private final ControllerRendererPool mControllerRendererPool; private final Lifecycle mLifecycle; private final List<LifecycleObserver> mLifecycleObservers; private ContextualCardUpdateListener mListener; @VisibleForTesting final List<ContextualCard> mContextualCards; @VisibleForTesting long mStartTime; @VisibleForTesting boolean mIsFirstLaunch; @VisibleForTesting List<String> mSavedCards; private ContextualCardUpdateListener mListener; public ContextualCardManager(Context context, Lifecycle lifecycle, Bundle savedInstanceState) { mContext = context; Loading Loading @@ -128,7 +131,8 @@ public class ContextualCardManager implements ContextualCardLoader.CardContentLo } } private void setupController(@ContextualCard.CardType int cardType) { @VisibleForTesting void setupController(@ContextualCard.CardType int cardType) { final ContextualCardController controller = mControllerRendererPool.getController(mContext, cardType); if (controller == null) { Loading Loading @@ -211,7 +215,7 @@ public class ContextualCardManager implements ContextualCardLoader.CardContentLo final MetricsFeatureProvider metricsFeatureProvider = FeatureFactory.getFactory(mContext).getMetricsFeatureProvider(); final long timeoutLimit = getCardLoaderTimeout(mContext); final long timeoutLimit = getCardLoaderTimeout(); if (loadTime <= timeoutLimit) { onContextualCardUpdated(cards.stream() .collect(groupingBy(ContextualCard::getCardType))); Loading Loading @@ -275,7 +279,7 @@ public class ContextualCardManager implements ContextualCardLoader.CardContentLo } @VisibleForTesting long getCardLoaderTimeout(Context context) { long getCardLoaderTimeout() { // 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(), Loading Loading @@ -317,7 +321,8 @@ public class ContextualCardManager implements ContextualCardLoader.CardContentLo return result; } private List<ContextualCard> getCardsToKeep(List<ContextualCard> cards) { @VisibleForTesting List<ContextualCard> getCardsToKeep(List<ContextualCard> cards) { if (mSavedCards != null) { //screen rotate final List<ContextualCard> cardsToKeep = cards.stream() Loading tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardManagerTest.java +100 −7 Original line number Diff line number Diff line Loading @@ -16,21 +16,25 @@ package com.android.settings.homepage.contextualcards; import static com.android.settings.homepage.contextualcards.ContextualCardManager.KEY_CONTEXTUAL_CARDS; import static com.android.settings.homepage.contextualcards.slices.SliceContextualCardRenderer.VIEW_TYPE_DEFERRED_SETUP; import static com.android.settings.homepage.contextualcards.slices.SliceContextualCardRenderer.VIEW_TYPE_FULL_WIDTH; import static com.android.settings.homepage.contextualcards.slices.SliceContextualCardRenderer.VIEW_TYPE_HALF_WIDTH; import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyMap; import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import android.content.Context; import android.net.Uri; import android.os.Bundle; import android.provider.Settings; import android.util.ArrayMap; Loading @@ -39,6 +43,8 @@ import com.android.settings.homepage.contextualcards.conditional.ConditionHeader import com.android.settings.homepage.contextualcards.conditional.ConditionalContextualCard; import com.android.settings.intelligence.ContextualCardProto; import com.android.settings.slices.CustomSliceRegistry; import com.android.settingslib.core.lifecycle.Lifecycle; import com.android.settingslib.core.lifecycle.LifecycleObserver; import org.junit.Before; import org.junit.Test; Loading @@ -62,6 +68,8 @@ public class ContextualCardManagerTest { @Mock ContextualCardUpdateListener mListener; @Mock Lifecycle mLifecycle; private Context mContext; private ContextualCardManager mManager; Loading @@ -70,9 +78,71 @@ public class ContextualCardManagerTest { public void setUp() { MockitoAnnotations.initMocks(this); mContext = RuntimeEnvironment.application; final ContextualCardsFragment fragment = new ContextualCardsFragment(); mManager = new ContextualCardManager(mContext, fragment.getSettingsLifecycle(), null /* bundle */); mManager = new ContextualCardManager(mContext, mLifecycle, null /* bundle */); } @Test public void constructor_noSavedInstanceState_shouldSetFirstLaunch() { assertThat(mManager.mIsFirstLaunch).isTrue(); } @Test public void constructor_noSavedInstanceState_shouldNotHaveSavedCards() { assertThat(mManager.mSavedCards).isNull(); } @Test public void constructor_hasSavedInstanceState_shouldContainExpectedSavedCards() { final Bundle outState = new Bundle(); final ArrayList<String> cards = getContextualCardList().stream() .map(ContextualCard::getName) .collect(Collectors.toCollection(ArrayList::new)); outState.putStringArrayList(KEY_CONTEXTUAL_CARDS, cards); mManager = new ContextualCardManager(mContext, mLifecycle, outState); final List<String> actualCards = mManager.mSavedCards.stream().collect(Collectors.toList()); final List<String> expectedCards = Arrays.asList("test_wifi", "test_flashlight", "test_connected", "test_gesture", "test_battery"); assertThat(actualCards).containsExactlyElementsIn(expectedCards); } @Test public void constructor_hasSettingsCustomCards_shouldSetUpCustomControllers() { final ControllerRendererPool pool = mManager.getControllerRendererPool(); final List<Integer> actual = pool.getControllers().stream() .map(ContextualCardController::getCardType) .collect(Collectors.toList()); final List<Integer> expected = Arrays.asList(ContextualCard.CardType.CONDITIONAL, ContextualCard.CardType.LEGACY_SUGGESTION); assertThat(actual).containsExactlyElementsIn(expected); } @Test public void setupController_notLifecycleObserverInstance_shouldNotAttachToLifecycle() { // 3 invocations in constructor(ContextualCardManager, Conditional and LegacySuggestion) verify(mLifecycle, times(3)).addObserver(any(LifecycleObserver.class)); mManager.setupController(ContextualCard.CardType.SLICE); // After 3 times call in the constructor, addObserver() shouldn't be called again. verify(mLifecycle, times(3)).addObserver(any(LifecycleObserver.class)); } @Test public void sortCards_shouldBeDescendingOrder() { final List<ContextualCard> cards = new ArrayList<>(); final ContextualCard card1 = buildContextualCard(TEST_SLICE_URI).mutate().setRankingScore(99.0).build(); final ContextualCard card2 = buildContextualCard("context://test/test2").mutate().setRankingScore(88.0).build(); cards.add(card1); cards.add(card2); final List<ContextualCard> sortedCards = mManager.sortCards(cards); assertThat(sortedCards.get(0).getSliceUri()).isEqualTo(Uri.parse(TEST_SLICE_URI)); } @Test Loading Loading @@ -128,7 +198,7 @@ public class ContextualCardManagerTest { @Test public void getCardLoaderTimeout_noConfiguredTimeout_shouldReturnDefaultTimeout() { final long timeout = mManager.getCardLoaderTimeout(mContext); final long timeout = mManager.getCardLoaderTimeout(); assertThat(timeout).isEqualTo(ContextualCardManager.CARD_CONTENT_LOADER_TIMEOUT_MS); } Loading @@ -139,7 +209,7 @@ public class ContextualCardManagerTest { Settings.Global.putLong(mContext.getContentResolver(), ContextualCardManager.KEY_GLOBAL_CARD_LOADER_TIMEOUT, configuredTimeout); final long timeout = mManager.getCardLoaderTimeout(mContext); final long timeout = mManager.getCardLoaderTimeout(); assertThat(timeout).isEqualTo(configuredTimeout); } Loading @@ -151,6 +221,7 @@ public class ContextualCardManagerTest { doNothing().when(manager).onContextualCardUpdated(anyMap()); manager.onFinishCardLoading(new ArrayList<>()); verify(manager).onContextualCardUpdated(nullable(Map.class)); } Loading @@ -161,6 +232,7 @@ public class ContextualCardManagerTest { doNothing().when(manager).onContextualCardUpdated(anyMap()); manager.onFinishCardLoading(new ArrayList<>()); verify(manager, never()).onContextualCardUpdated(anyMap()); } Loading @@ -177,8 +249,18 @@ public class ContextualCardManagerTest { assertThat(mManager.mContextualCards).hasSize(2); } @Test public void onFinishCardLoading_newLaunch_shouldSetIsFirstLaunchBackToFalse() { assertThat(mManager.mIsFirstLaunch).isTrue(); mManager.onFinishCardLoading(new ArrayList<>()); assertThat(mManager.mIsFirstLaunch).isFalse(); } @Test public void onFinishCardLoading_hasSavedCard_shouldOnlyShowSavedCard() { // test screen rotation mManager.setListener(mListener); final List<String> savedCardNames = new ArrayList<>(); savedCardNames.add(TEST_SLICE_NAME); Loading @@ -204,7 +286,8 @@ public class ContextualCardManagerTest { } @Test public void onFinishCardLoading_reloadData_shouldOnlyShowOldCard() { public void onFinishCardLoading_reloadData_hasNewCard_shouldOnlyShowOldCard() { // test card dismissal cases mManager.setListener(mListener); mManager.mIsFirstLaunch = false; //old card Loading @@ -228,7 +311,6 @@ public class ContextualCardManagerTest { assertThat(actualCards).containsExactlyElementsIn(expectedCards); } @Test public void getCardsWithViewType_noSuggestionCards_shouldNotHaveHalfCards() { final List<Integer> categories = Arrays.asList( Loading Loading @@ -411,6 +493,17 @@ public class ContextualCardManagerTest { } } @Test public void getCardsToKeep_hasSavedCard_shouldResetSavedCards() { final List<String> savedCardNames = new ArrayList<>(); savedCardNames.add(TEST_SLICE_NAME); mManager.mSavedCards = savedCardNames; mManager.getCardsToKeep(getContextualCardList()); assertThat(mManager.mSavedCards).isNull(); } private ContextualCard buildContextualCard(String sliceUri) { return new ContextualCard.Builder() .setName(TEST_SLICE_NAME) Loading Loading
src/com/android/settings/homepage/contextualcards/ContextualCardManager.java +13 −8 Original line number Diff line number Diff line Loading @@ -72,26 +72,29 @@ public class ContextualCardManager implements ContextualCardLoader.CardContentLo 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"; @VisibleForTesting static final String KEY_CONTEXTUAL_CARDS = "key_contextual_cards"; private static final String KEY_CONTEXTUAL_CARDS = "key_contextual_cards"; private static final String TAG = "ContextualCardManager"; //The list for Settings Custom Card private static final int[] SETTINGS_CARDS = {ContextualCard.CardType.CONDITIONAL, ContextualCard.CardType.LEGACY_SUGGESTION}; @VisibleForTesting final List<ContextualCard> mContextualCards; private final Context mContext; private final ControllerRendererPool mControllerRendererPool; private final Lifecycle mLifecycle; private final List<LifecycleObserver> mLifecycleObservers; private ContextualCardUpdateListener mListener; @VisibleForTesting final List<ContextualCard> mContextualCards; @VisibleForTesting long mStartTime; @VisibleForTesting boolean mIsFirstLaunch; @VisibleForTesting List<String> mSavedCards; private ContextualCardUpdateListener mListener; public ContextualCardManager(Context context, Lifecycle lifecycle, Bundle savedInstanceState) { mContext = context; Loading Loading @@ -128,7 +131,8 @@ public class ContextualCardManager implements ContextualCardLoader.CardContentLo } } private void setupController(@ContextualCard.CardType int cardType) { @VisibleForTesting void setupController(@ContextualCard.CardType int cardType) { final ContextualCardController controller = mControllerRendererPool.getController(mContext, cardType); if (controller == null) { Loading Loading @@ -211,7 +215,7 @@ public class ContextualCardManager implements ContextualCardLoader.CardContentLo final MetricsFeatureProvider metricsFeatureProvider = FeatureFactory.getFactory(mContext).getMetricsFeatureProvider(); final long timeoutLimit = getCardLoaderTimeout(mContext); final long timeoutLimit = getCardLoaderTimeout(); if (loadTime <= timeoutLimit) { onContextualCardUpdated(cards.stream() .collect(groupingBy(ContextualCard::getCardType))); Loading Loading @@ -275,7 +279,7 @@ public class ContextualCardManager implements ContextualCardLoader.CardContentLo } @VisibleForTesting long getCardLoaderTimeout(Context context) { long getCardLoaderTimeout() { // 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(), Loading Loading @@ -317,7 +321,8 @@ public class ContextualCardManager implements ContextualCardLoader.CardContentLo return result; } private List<ContextualCard> getCardsToKeep(List<ContextualCard> cards) { @VisibleForTesting List<ContextualCard> getCardsToKeep(List<ContextualCard> cards) { if (mSavedCards != null) { //screen rotate final List<ContextualCard> cardsToKeep = cards.stream() Loading
tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardManagerTest.java +100 −7 Original line number Diff line number Diff line Loading @@ -16,21 +16,25 @@ package com.android.settings.homepage.contextualcards; import static com.android.settings.homepage.contextualcards.ContextualCardManager.KEY_CONTEXTUAL_CARDS; import static com.android.settings.homepage.contextualcards.slices.SliceContextualCardRenderer.VIEW_TYPE_DEFERRED_SETUP; import static com.android.settings.homepage.contextualcards.slices.SliceContextualCardRenderer.VIEW_TYPE_FULL_WIDTH; import static com.android.settings.homepage.contextualcards.slices.SliceContextualCardRenderer.VIEW_TYPE_HALF_WIDTH; import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyMap; import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import android.content.Context; import android.net.Uri; import android.os.Bundle; import android.provider.Settings; import android.util.ArrayMap; Loading @@ -39,6 +43,8 @@ import com.android.settings.homepage.contextualcards.conditional.ConditionHeader import com.android.settings.homepage.contextualcards.conditional.ConditionalContextualCard; import com.android.settings.intelligence.ContextualCardProto; import com.android.settings.slices.CustomSliceRegistry; import com.android.settingslib.core.lifecycle.Lifecycle; import com.android.settingslib.core.lifecycle.LifecycleObserver; import org.junit.Before; import org.junit.Test; Loading @@ -62,6 +68,8 @@ public class ContextualCardManagerTest { @Mock ContextualCardUpdateListener mListener; @Mock Lifecycle mLifecycle; private Context mContext; private ContextualCardManager mManager; Loading @@ -70,9 +78,71 @@ public class ContextualCardManagerTest { public void setUp() { MockitoAnnotations.initMocks(this); mContext = RuntimeEnvironment.application; final ContextualCardsFragment fragment = new ContextualCardsFragment(); mManager = new ContextualCardManager(mContext, fragment.getSettingsLifecycle(), null /* bundle */); mManager = new ContextualCardManager(mContext, mLifecycle, null /* bundle */); } @Test public void constructor_noSavedInstanceState_shouldSetFirstLaunch() { assertThat(mManager.mIsFirstLaunch).isTrue(); } @Test public void constructor_noSavedInstanceState_shouldNotHaveSavedCards() { assertThat(mManager.mSavedCards).isNull(); } @Test public void constructor_hasSavedInstanceState_shouldContainExpectedSavedCards() { final Bundle outState = new Bundle(); final ArrayList<String> cards = getContextualCardList().stream() .map(ContextualCard::getName) .collect(Collectors.toCollection(ArrayList::new)); outState.putStringArrayList(KEY_CONTEXTUAL_CARDS, cards); mManager = new ContextualCardManager(mContext, mLifecycle, outState); final List<String> actualCards = mManager.mSavedCards.stream().collect(Collectors.toList()); final List<String> expectedCards = Arrays.asList("test_wifi", "test_flashlight", "test_connected", "test_gesture", "test_battery"); assertThat(actualCards).containsExactlyElementsIn(expectedCards); } @Test public void constructor_hasSettingsCustomCards_shouldSetUpCustomControllers() { final ControllerRendererPool pool = mManager.getControllerRendererPool(); final List<Integer> actual = pool.getControllers().stream() .map(ContextualCardController::getCardType) .collect(Collectors.toList()); final List<Integer> expected = Arrays.asList(ContextualCard.CardType.CONDITIONAL, ContextualCard.CardType.LEGACY_SUGGESTION); assertThat(actual).containsExactlyElementsIn(expected); } @Test public void setupController_notLifecycleObserverInstance_shouldNotAttachToLifecycle() { // 3 invocations in constructor(ContextualCardManager, Conditional and LegacySuggestion) verify(mLifecycle, times(3)).addObserver(any(LifecycleObserver.class)); mManager.setupController(ContextualCard.CardType.SLICE); // After 3 times call in the constructor, addObserver() shouldn't be called again. verify(mLifecycle, times(3)).addObserver(any(LifecycleObserver.class)); } @Test public void sortCards_shouldBeDescendingOrder() { final List<ContextualCard> cards = new ArrayList<>(); final ContextualCard card1 = buildContextualCard(TEST_SLICE_URI).mutate().setRankingScore(99.0).build(); final ContextualCard card2 = buildContextualCard("context://test/test2").mutate().setRankingScore(88.0).build(); cards.add(card1); cards.add(card2); final List<ContextualCard> sortedCards = mManager.sortCards(cards); assertThat(sortedCards.get(0).getSliceUri()).isEqualTo(Uri.parse(TEST_SLICE_URI)); } @Test Loading Loading @@ -128,7 +198,7 @@ public class ContextualCardManagerTest { @Test public void getCardLoaderTimeout_noConfiguredTimeout_shouldReturnDefaultTimeout() { final long timeout = mManager.getCardLoaderTimeout(mContext); final long timeout = mManager.getCardLoaderTimeout(); assertThat(timeout).isEqualTo(ContextualCardManager.CARD_CONTENT_LOADER_TIMEOUT_MS); } Loading @@ -139,7 +209,7 @@ public class ContextualCardManagerTest { Settings.Global.putLong(mContext.getContentResolver(), ContextualCardManager.KEY_GLOBAL_CARD_LOADER_TIMEOUT, configuredTimeout); final long timeout = mManager.getCardLoaderTimeout(mContext); final long timeout = mManager.getCardLoaderTimeout(); assertThat(timeout).isEqualTo(configuredTimeout); } Loading @@ -151,6 +221,7 @@ public class ContextualCardManagerTest { doNothing().when(manager).onContextualCardUpdated(anyMap()); manager.onFinishCardLoading(new ArrayList<>()); verify(manager).onContextualCardUpdated(nullable(Map.class)); } Loading @@ -161,6 +232,7 @@ public class ContextualCardManagerTest { doNothing().when(manager).onContextualCardUpdated(anyMap()); manager.onFinishCardLoading(new ArrayList<>()); verify(manager, never()).onContextualCardUpdated(anyMap()); } Loading @@ -177,8 +249,18 @@ public class ContextualCardManagerTest { assertThat(mManager.mContextualCards).hasSize(2); } @Test public void onFinishCardLoading_newLaunch_shouldSetIsFirstLaunchBackToFalse() { assertThat(mManager.mIsFirstLaunch).isTrue(); mManager.onFinishCardLoading(new ArrayList<>()); assertThat(mManager.mIsFirstLaunch).isFalse(); } @Test public void onFinishCardLoading_hasSavedCard_shouldOnlyShowSavedCard() { // test screen rotation mManager.setListener(mListener); final List<String> savedCardNames = new ArrayList<>(); savedCardNames.add(TEST_SLICE_NAME); Loading @@ -204,7 +286,8 @@ public class ContextualCardManagerTest { } @Test public void onFinishCardLoading_reloadData_shouldOnlyShowOldCard() { public void onFinishCardLoading_reloadData_hasNewCard_shouldOnlyShowOldCard() { // test card dismissal cases mManager.setListener(mListener); mManager.mIsFirstLaunch = false; //old card Loading @@ -228,7 +311,6 @@ public class ContextualCardManagerTest { assertThat(actualCards).containsExactlyElementsIn(expectedCards); } @Test public void getCardsWithViewType_noSuggestionCards_shouldNotHaveHalfCards() { final List<Integer> categories = Arrays.asList( Loading Loading @@ -411,6 +493,17 @@ public class ContextualCardManagerTest { } } @Test public void getCardsToKeep_hasSavedCard_shouldResetSavedCards() { final List<String> savedCardNames = new ArrayList<>(); savedCardNames.add(TEST_SLICE_NAME); mManager.mSavedCards = savedCardNames; mManager.getCardsToKeep(getContextualCardList()); assertThat(mManager.mSavedCards).isNull(); } private ContextualCard buildContextualCard(String sliceUri) { return new ContextualCard.Builder() .setName(TEST_SLICE_NAME) Loading