diff --git a/res/layout/suggestion_tile.xml b/res/layout/suggestion_tile.xml
index 80de8ff4937..9e17e38be5a 100644
--- a/res/layout/suggestion_tile.xml
+++ b/res/layout/suggestion_tile.xml
@@ -55,11 +55,4 @@
-
-
\ No newline at end of file
diff --git a/src/com/android/settings/applications/AppStorageSettings.java b/src/com/android/settings/applications/AppStorageSettings.java
index 0ea9515ed16..aa35328c030 100644
--- a/src/com/android/settings/applications/AppStorageSettings.java
+++ b/src/com/android/settings/applications/AppStorageSettings.java
@@ -30,7 +30,6 @@ import android.content.pm.IPackageDataObserver;
import android.content.pm.PackageManager;
import android.content.pm.ProviderInfo;
import android.os.Bundle;
-import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.os.RemoteException;
@@ -39,7 +38,6 @@ import android.os.storage.StorageManager;
import android.os.storage.VolumeInfo;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceCategory;
-import android.text.format.Formatter;
import android.util.Log;
import android.util.MutableInt;
import android.view.View;
@@ -51,8 +49,6 @@ import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.deviceinfo.StorageWizardMoveConfirm;
import com.android.settingslib.RestrictedLockUtils;
-import com.android.settingslib.applications.ApplicationsState;
-import com.android.settingslib.applications.ApplicationsState.AppEntry;
import com.android.settingslib.applications.ApplicationsState.Callbacks;
import com.android.settingslib.applications.StorageStatsSource;
import com.android.settingslib.applications.StorageStatsSource.AppStorageStats;
diff --git a/src/com/android/settings/dashboard/DashboardAdapter.java b/src/com/android/settings/dashboard/DashboardAdapter.java
index 07d48062955..f968cd0f040 100644
--- a/src/com/android/settings/dashboard/DashboardAdapter.java
+++ b/src/com/android/settings/dashboard/DashboardAdapter.java
@@ -17,21 +17,17 @@ package com.android.settings.dashboard;
import android.app.Activity;
import android.content.Context;
-import android.content.pm.PackageManager;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
import android.os.Bundle;
import android.support.annotation.VisibleForTesting;
import android.support.v7.util.DiffUtil;
-import android.support.v7.widget.PopupMenu;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Log;
-import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
-import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
@@ -43,18 +39,17 @@ import com.android.settings.SettingsActivity;
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
import com.android.settings.dashboard.conditional.Condition;
import com.android.settings.dashboard.conditional.ConditionAdapterUtils;
+import com.android.settings.dashboard.suggestions.SuggestionDismissController;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.SuggestionParser;
import com.android.settingslib.drawer.DashboardCategory;
import com.android.settingslib.drawer.Tile;
import java.util.ArrayList;
-import java.util.HashSet;
import java.util.List;
-import java.util.Set;
public class DashboardAdapter extends RecyclerView.Adapter
- implements SummaryLoader.SummaryConsumer {
+ implements SummaryLoader.SummaryConsumer, SuggestionDismissController.Callback {
public static final String TAG = "DashboardAdapter";
private static final String STATE_SUGGESTION_LIST = "suggestion_list";
private static final String STATE_CATEGORY_LIST = "category_list";
@@ -66,7 +61,6 @@ public class DashboardAdapter extends RecyclerView.Adapter mSuggestionsShownLogged;
- private SuggestionParser mSuggestionParser;
private boolean mFirstFrameDrawn;
@VisibleForTesting
@@ -115,7 +109,6 @@ public class DashboardAdapter extends RecyclerView.Adapter suggestions = mDashboardData.getSuggestions();
- suggestions.remove(suggestion);
+ @Override
+ public Tile getSuggestionForPosition(int position) {
+ return (Tile) mDashboardData.getItemEntityByPosition(position);
+ }
- DashboardData prevData = mDashboardData;
- mDashboardData = new DashboardData.Builder(prevData)
- .setSuggestions(suggestions)
- .build();
- notifyDashboardDataChanged(prevData);
+ @Override
+ public void onSuggestionDismissed(Tile suggestion) {
+ final List suggestions = mDashboardData.getSuggestions();
+ if (suggestions == null) {
+ return;
+ }
+ suggestions.remove(suggestion);
- return true;
- }
- });
- popup.show();
+ final DashboardData prevData = mDashboardData;
+ mDashboardData = new DashboardData.Builder(prevData)
+ .setSuggestions(suggestions)
+ .build();
+ notifyDashboardDataChanged(prevData);
}
@VisibleForTesting
@@ -513,9 +477,9 @@ public class DashboardAdapter extends RecyclerView.Adapter mConditions;
private List mSuggestions;
-
public Builder() {
}
@@ -359,7 +370,7 @@ public class DashboardData {
return "condition"; // return anything but null to mark the payload
}
return null;
- }
+ }
}
/**
@@ -433,11 +444,11 @@ public class DashboardData {
switch (type) {
case TYPE_DASHBOARD_CATEGORY:
// Only check title for dashboard category
- return TextUtils.equals(((DashboardCategory)entity).title,
+ return TextUtils.equals(((DashboardCategory) entity).title,
((DashboardCategory) targetItem.entity).title);
case TYPE_DASHBOARD_TILE:
- final Tile localTile = (Tile)entity;
- final Tile targetTile = (Tile)targetItem.entity;
+ final Tile localTile = (Tile) entity;
+ final Tile targetTile = (Tile) targetItem.entity;
// Only check title and summary for dashboard tile
return TextUtils.equals(localTile.title, targetTile.title)
diff --git a/src/com/android/settings/dashboard/DashboardSummary.java b/src/com/android/settings/dashboard/DashboardSummary.java
index 6482672e3d9..4e2baa9d1ff 100644
--- a/src/com/android/settings/dashboard/DashboardSummary.java
+++ b/src/com/android/settings/dashboard/DashboardSummary.java
@@ -35,6 +35,7 @@ import com.android.settings.dashboard.conditional.Condition;
import com.android.settings.dashboard.conditional.ConditionAdapterUtils;
import com.android.settings.dashboard.conditional.ConditionManager;
import com.android.settings.dashboard.conditional.FocusRecyclerView;
+import com.android.settings.dashboard.suggestions.SuggestionDismissController;
import com.android.settings.dashboard.suggestions.SuggestionFeatureProvider;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.SuggestionParser;
@@ -70,6 +71,7 @@ public class DashboardSummary extends InstrumentedFragment
private DashboardFeatureProvider mDashboardFeatureProvider;
private SuggestionFeatureProvider mSuggestionFeatureProvider;
private boolean isOnCategoriesChangedCalled;
+ private SuggestionDismissController mSuggestionDismissHandler;
@Override
public int getMetricsCategory() {
@@ -119,8 +121,7 @@ public class DashboardSummary extends InstrumentedFragment
}
}
if (DEBUG_TIMING) {
- Log.d(TAG, "onResume took " + (System.currentTimeMillis() - startTime)
- + " ms");
+ Log.d(TAG, "onResume took " + (System.currentTimeMillis() - startTime) + " ms");
}
}
@@ -177,7 +178,7 @@ public class DashboardSummary extends InstrumentedFragment
@Override
public void onViewCreated(View view, Bundle bundle) {
long startTime = System.currentTimeMillis();
- mDashboard = (FocusRecyclerView) view.findViewById(R.id.dashboard_container);
+ mDashboard = view.findViewById(R.id.dashboard_container);
mLayoutManager = new LinearLayoutManager(getContext());
mLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
if (bundle != null) {
@@ -192,6 +193,8 @@ public class DashboardSummary extends InstrumentedFragment
mAdapter = new DashboardAdapter(getContext(), mSuggestionParser, mMetricsFeatureProvider,
bundle, mConditionManager.getConditions());
mDashboard.setAdapter(mAdapter);
+ mSuggestionDismissHandler = new SuggestionDismissController(
+ getContext(), mDashboard, mSuggestionParser, mAdapter);
mDashboard.setItemAnimator(new DashboardItemAnimator());
mSummaryLoader.setSummaryConsumer(mAdapter);
ConditionAdapterUtils.addDismiss(mDashboard);
@@ -243,7 +246,7 @@ public class DashboardSummary extends InstrumentedFragment
List suggestionIds = new ArrayList<>(suggestions.size());
for (Tile suggestion : suggestions) {
suggestionIds.add(
- DashboardAdapter.getSuggestionIdentifier(context, suggestion));
+ DashboardAdapter.getSuggestionIdentifier(context, suggestion));
}
// TODO: create a Suggestion class to maintain the id and other info
mSuggestionFeatureProvider.rankSuggestions(suggestions, suggestionIds);
@@ -251,7 +254,8 @@ public class DashboardSummary extends InstrumentedFragment
for (int i = 0; i < suggestions.size(); i++) {
Tile suggestion = suggestions.get(i);
if (mSuggestionsChecks.isSuggestionComplete(suggestion)) {
- mAdapter.disableSuggestion(suggestion);
+ mSuggestionFeatureProvider.dismissSuggestion(
+ context, mSuggestionParser, suggestion);
suggestions.remove(i--);
}
}
@@ -277,7 +281,7 @@ public class DashboardSummary extends InstrumentedFragment
// API that takes a single category.
List categories = new ArrayList<>();
categories.add(mDashboardFeatureProvider.getTilesForCategory(
- CategoryKey.CATEGORY_HOMEPAGE));
+ CategoryKey.CATEGORY_HOMEPAGE));
if (suggestions != null) {
mAdapter.setCategoriesAndSuggestions(categories, suggestions);
} else {
diff --git a/src/com/android/settings/dashboard/conditional/ConditionAdapterUtils.java b/src/com/android/settings/dashboard/conditional/ConditionAdapterUtils.java
index b58ac39b9fe..aebbf931c81 100644
--- a/src/com/android/settings/dashboard/conditional/ConditionAdapterUtils.java
+++ b/src/com/android/settings/dashboard/conditional/ConditionAdapterUtils.java
@@ -15,16 +15,11 @@
*/
package com.android.settings.dashboard.conditional;
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ObjectAnimator;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;
import android.util.Log;
import android.view.View;
-import android.view.View.OnLayoutChangeListener;
-import android.view.ViewGroup.LayoutParams;
import android.widget.Button;
import android.widget.ImageView;
@@ -126,12 +121,6 @@ public class ConditionAdapterUtils {
}
}
- private static void setHeight(View detailGroup, int height) {
- final LayoutParams params = detailGroup.getLayoutParams();
- params.height = height;
- detailGroup.setLayoutParams(params);
- }
-
private static void setViewVisibility(View containerView, int viewId, boolean visible) {
View view = containerView.findViewById(viewId);
if (view != null) {
diff --git a/src/com/android/settings/dashboard/suggestions/SuggestionDismissController.java b/src/com/android/settings/dashboard/suggestions/SuggestionDismissController.java
new file mode 100644
index 00000000000..708aadb8e7a
--- /dev/null
+++ b/src/com/android/settings/dashboard/suggestions/SuggestionDismissController.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.dashboard.suggestions;
+
+import android.content.Context;
+import android.support.v7.widget.RecyclerView;
+import android.support.v7.widget.helper.ItemTouchHelper;
+
+import com.android.settings.R;
+import com.android.settings.overlay.FeatureFactory;
+import com.android.settingslib.SuggestionParser;
+import com.android.settingslib.drawer.Tile;
+
+public class SuggestionDismissController extends ItemTouchHelper.SimpleCallback {
+
+ public interface Callback {
+
+ /**
+ * Returns suggestion tile data from the callback
+ */
+ Tile getSuggestionForPosition(int position);
+
+ /**
+ * Called when a suggestion is dismissed.
+ */
+ void onSuggestionDismissed(Tile suggestion);
+ }
+
+ private final Context mContext;
+ private final SuggestionFeatureProvider mSuggestionFeatureProvider;
+ private final SuggestionParser mSuggestionParser;
+ private final Callback mCallback;
+
+ public SuggestionDismissController(Context context, RecyclerView recyclerView,
+ SuggestionParser parser, Callback callback) {
+ super(0, ItemTouchHelper.START | ItemTouchHelper.END);
+ mContext = context;
+ mSuggestionParser = parser;
+ mSuggestionFeatureProvider = FeatureFactory.getFactory(context)
+ .getSuggestionFeatureProvider(context);
+ mCallback = callback;
+ final ItemTouchHelper itemTouchHelper = new ItemTouchHelper(this);
+ itemTouchHelper.attachToRecyclerView(recyclerView);
+ }
+
+ @Override
+ public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder,
+ RecyclerView.ViewHolder target) {
+ return true;
+ }
+
+ @Override
+ public int getSwipeDirs(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
+ if (viewHolder.getItemViewType() == R.layout.suggestion_tile) {
+ // Only return swipe direction for suggestion tiles. All other types are not swipeable.
+ return super.getSwipeDirs(recyclerView, viewHolder);
+ }
+ return 0;
+ }
+
+ @Override
+ public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
+ if (mCallback == null) {
+ return;
+ }
+ final Tile suggestion = mCallback.getSuggestionForPosition(viewHolder.getAdapterPosition());
+ mSuggestionFeatureProvider.dismissSuggestion(mContext, mSuggestionParser, suggestion);
+ mCallback.onSuggestionDismissed(suggestion);
+ }
+}
diff --git a/src/com/android/settings/dashboard/suggestions/SuggestionFeatureProvider.java b/src/com/android/settings/dashboard/suggestions/SuggestionFeatureProvider.java
index 18fbd90815e..806d6f880f5 100644
--- a/src/com/android/settings/dashboard/suggestions/SuggestionFeatureProvider.java
+++ b/src/com/android/settings/dashboard/suggestions/SuggestionFeatureProvider.java
@@ -18,6 +18,7 @@ package com.android.settings.dashboard.suggestions;
import android.content.Context;
+import com.android.settingslib.SuggestionParser;
import com.android.settingslib.drawer.Tile;
import java.util.List;
@@ -38,8 +39,14 @@ public interface SuggestionFeatureProvider {
/**
* Ranks the list of suggestions in place.
- * @param suggestions: List of suggestion Tiles
- * @param suggestionIds: List of suggestion ids corresponding to the suggestion tiles.
+ *
+ * @param suggestions List of suggestion Tiles
+ * @param suggestionIds List of suggestion ids corresponding to the suggestion tiles.
*/
void rankSuggestions(final List suggestions, List suggestionIds);
+
+ /**
+ * Dismisses a suggestion.
+ */
+ void dismissSuggestion(Context context, SuggestionParser parser, Tile suggestion);
}
diff --git a/src/com/android/settings/dashboard/suggestions/SuggestionFeatureProviderImpl.java b/src/com/android/settings/dashboard/suggestions/SuggestionFeatureProviderImpl.java
index 3a4d5456bf7..9231037e2f4 100644
--- a/src/com/android/settings/dashboard/suggestions/SuggestionFeatureProviderImpl.java
+++ b/src/com/android/settings/dashboard/suggestions/SuggestionFeatureProviderImpl.java
@@ -17,7 +17,13 @@
package com.android.settings.dashboard.suggestions;
import android.content.Context;
+import android.content.pm.PackageManager;
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.settings.core.instrumentation.MetricsFeatureProvider;
+import com.android.settings.dashboard.DashboardAdapter;
+import com.android.settings.overlay.FeatureFactory;
+import com.android.settingslib.SuggestionParser;
import com.android.settingslib.drawer.Tile;
import java.util.List;
@@ -25,6 +31,7 @@ import java.util.List;
public class SuggestionFeatureProviderImpl implements SuggestionFeatureProvider {
private final SuggestionRanker mSuggestionRanker;
+ private final MetricsFeatureProvider mMetricsFeatureProvider;
@Override
public boolean isSmartSuggestionEnabled(Context context) {
@@ -45,6 +52,8 @@ public class SuggestionFeatureProviderImpl implements SuggestionFeatureProvider
public SuggestionFeatureProviderImpl(Context context) {
mSuggestionRanker = new SuggestionRanker(
new SuggestionFeaturizer(new EventStore(context.getApplicationContext())));
+ mMetricsFeatureProvider = FeatureFactory.getFactory(context)
+ .getMetricsFeatureProvider();
}
@Override
@@ -52,4 +61,24 @@ public class SuggestionFeatureProviderImpl implements SuggestionFeatureProvider
mSuggestionRanker.rankSuggestions(suggestions, suggestionIds);
}
+ @Override
+ public void dismissSuggestion(Context context, SuggestionParser parser, Tile suggestion) {
+ if (parser == null || suggestion == null) {
+ return;
+ }
+ mMetricsFeatureProvider.action(
+ context, MetricsProto.MetricsEvent.ACTION_SETTINGS_DISMISS_SUGGESTION,
+ DashboardAdapter.getSuggestionIdentifier(context, suggestion));
+
+ final boolean isSmartSuggestionEnabled = isSmartSuggestionEnabled(context);
+ if (!parser.dismissSuggestion(suggestion, isSmartSuggestionEnabled)) {
+ return;
+ }
+ context.getPackageManager().setComponentEnabledSetting(
+ suggestion.intent.getComponent(),
+ PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
+ PackageManager.DONT_KILL_APP);
+ parser.markCategoryDone(suggestion.category);
+ }
+
}
diff --git a/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionDismissControllerTest.java b/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionDismissControllerTest.java
new file mode 100644
index 00000000000..4a41ede188c
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionDismissControllerTest.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.dashboard.suggestions;
+
+import android.content.Context;
+import android.support.v7.widget.RecyclerView;
+import android.support.v7.widget.helper.ItemTouchHelper;
+
+import com.android.settings.R;
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settingslib.SuggestionParser;
+import com.android.settingslib.drawer.Tile;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Answers;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.annotation.Config;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class SuggestionDismissControllerTest {
+
+ @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+ private Context mContext;
+ @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+ private RecyclerView mRecyclerView;
+ @Mock
+ private SuggestionParser mSuggestionParser;
+ @Mock
+ private SuggestionDismissController.Callback mCallback;
+
+ private FakeFeatureFactory mFactory;
+ private SuggestionDismissController mController;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ FakeFeatureFactory.setupForTest(mContext);
+ mFactory = (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext);
+
+ when(mRecyclerView.getResources().getDimension(anyInt())).thenReturn(50F);
+
+ mController = new SuggestionDismissController(mContext, mRecyclerView,
+ mSuggestionParser, mCallback);
+ }
+
+ @Test
+ public void onMove_alwaysReturnTrue() {
+ assertThat(mController.onMove(null, null, null)).isTrue();
+ }
+
+ @Test
+ public void getSwipeDirs_isSuggestionTile_shouldReturnDirection() {
+ final RecyclerView.ViewHolder vh = mock(RecyclerView.ViewHolder.class);
+ when(vh.getItemViewType()).thenReturn(R.layout.suggestion_tile);
+
+ assertThat(mController.getSwipeDirs(mRecyclerView, vh))
+ .isEqualTo(ItemTouchHelper.START | ItemTouchHelper.END);
+ }
+
+ @Test
+ public void getSwipeDirs_isNotSuggestionTile_shouldReturn0() {
+ final RecyclerView.ViewHolder vh = mock(RecyclerView.ViewHolder.class);
+ when(vh.getItemViewType()).thenReturn(R.layout.condition_card);
+
+ assertThat(mController.getSwipeDirs(mRecyclerView, vh))
+ .isEqualTo(0);
+ }
+
+ @Test
+ public void onSwiped_shouldTriggerDismissSuggestion() {
+ final RecyclerView.ViewHolder vh = mock(RecyclerView.ViewHolder.class);
+
+ mController.onSwiped(vh, ItemTouchHelper.START);
+
+ verify(mFactory.suggestionsFeatureProvider).dismissSuggestion(
+ eq(mContext), eq(mSuggestionParser), any(Tile.class));
+ verify(mCallback).onSuggestionDismissed(any(Tile.class));
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionFeatureProviderImplTest.java
new file mode 100644
index 00000000000..912947ab3d8
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionFeatureProviderImplTest.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.dashboard.suggestions;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settingslib.SuggestionParser;
+import com.android.settingslib.drawer.Tile;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Answers;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyBoolean;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class SuggestionFeatureProviderImplTest {
+
+ @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+ private Context mContext;
+ @Mock
+ private SuggestionParser mSuggestionParser;
+ @Mock
+ private Tile mSuggestion;
+
+ private FakeFeatureFactory mFactory;
+ private SuggestionFeatureProviderImpl mProvider;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ FakeFeatureFactory.setupForTest(mContext);
+ mFactory = (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext);
+ when(mContext.getApplicationContext()).thenReturn(RuntimeEnvironment.application);
+ mSuggestion.intent = new Intent().setClassName("pkg", "cls");
+ mSuggestion.category = "category";
+
+ mProvider = new SuggestionFeatureProviderImpl(mContext);
+ }
+
+ @Test
+ public void dismissSuggestion_noParserOrSuggestion_noop() {
+ mProvider.dismissSuggestion(mContext, null, null);
+ mProvider.dismissSuggestion(mContext, mSuggestionParser, null);
+ mProvider.dismissSuggestion(mContext, null, mSuggestion);
+
+ verifyZeroInteractions(mFactory.metricsFeatureProvider);
+ }
+
+ @Test
+ public void dismissSuggestion_hasMoreDismissCount_shouldNotDisableComponent() {
+ when(mSuggestionParser.dismissSuggestion(any(Tile.class), anyBoolean()))
+ .thenReturn(false);
+ mProvider.dismissSuggestion(mContext, mSuggestionParser, mSuggestion);
+
+ verify(mFactory.metricsFeatureProvider).action(
+ eq(mContext),
+ eq(MetricsProto.MetricsEvent.ACTION_SETTINGS_DISMISS_SUGGESTION),
+ anyString());
+ verify(mContext, never()).getPackageManager();
+ }
+
+ @Test
+ public void dismissSuggestion_hasNoMoreDismissCount_shouldDisableComponent() {
+ when(mSuggestionParser.dismissSuggestion(any(Tile.class), anyBoolean()))
+ .thenReturn(true);
+
+ mProvider.dismissSuggestion(mContext, mSuggestionParser, mSuggestion);
+
+ verify(mFactory.metricsFeatureProvider).action(
+ eq(mContext),
+ eq(MetricsProto.MetricsEvent.ACTION_SETTINGS_DISMISS_SUGGESTION),
+ anyString());
+
+ verify(mContext.getPackageManager())
+ .setComponentEnabledSetting(mSuggestion.intent.getComponent(),
+ PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
+ PackageManager.DONT_KILL_APP);
+ verify(mSuggestionParser).markCategoryDone(mSuggestion.category);
+ }
+}