OSDN Git Service

Fix suggestion crash if parser fails to parse dismiss rule
authorFan Zhang <zhfan@google.com>
Fri, 21 Jul 2017 17:21:36 +0000 (10:21 -0700)
committerFan Zhang <zhfan@google.com>
Fri, 21 Jul 2017 19:57:14 +0000 (12:57 -0700)
We store a index value in shared pref to figure out when a suggestion
should be displayed next time. However the rule can change due to
various reasons. When the index and the rule itself go out of sync, we
should not crash.

Merged-In: Id3ea88b6d321434e20ac0cd3e2670524c237e24e
Change-Id: Ied4a0359f9bc22ee94ec79c0591d2671a9c31b86
Fix: 63908636
Test: robotests

packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionParser.java
packages/SettingsLib/tests/robotests/src/com/android/settingslib/suggestions/SuggestionParserTest.java

index 167ffe6..7f82a1c 100644 (file)
@@ -91,7 +91,8 @@ public class SuggestionParser {
 
     // Shared prefs keys for storing dismissed state.
     // Index into current dismissed state.
-    private static final String DISMISS_INDEX = "_dismiss_index";
+    @VisibleForTesting
+    static final String DISMISS_INDEX = "_dismiss_index";
     private static final String SETUP_TIME = "_setup_time";
     private static final String IS_DISMISSED = "_is_dismissed";
 
@@ -355,7 +356,8 @@ public class SuggestionParser {
         return elapsedTime > category.exclusiveExpireDaysInMillis;
     }
 
-    private boolean isDismissed(Tile suggestion, boolean isSmartSuggestionEnabled) {
+    @VisibleForTesting
+    boolean isDismissed(Tile suggestion, boolean isSmartSuggestionEnabled) {
         String dismissControl = getDismissControl(suggestion, isSmartSuggestionEnabled);
         if (dismissControl == null) {
             return false;
@@ -372,7 +374,11 @@ public class SuggestionParser {
             return false;
         }
         int index = mSharedPrefs.getInt(keyBase + DISMISS_INDEX, 0);
-        int currentDismiss = parseDismissString(dismissControl)[index];
+        int[] dismissRules = parseDismissString(dismissControl);
+        if (dismissRules.length <= index) {
+            return true;
+        }
+        int currentDismiss = dismissRules[index];
         long time = getEndTime(mSharedPrefs.getLong(keyBase + SETUP_TIME, 0), currentDismiss);
         if (System.currentTimeMillis() >= time) {
             // Dismiss timeout has passed, undismiss it.
index 60933cf..8391136 100644 (file)
@@ -16,6 +16,8 @@
 
 package com.android.settingslib.suggestions;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -42,8 +44,6 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
-import static com.google.common.truth.Truth.assertThat;
-
 @RunWith(SettingLibRobolectricTestRunner.class)
 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class SuggestionParserTest {
@@ -190,6 +190,24 @@ public class SuggestionParserTest {
         assertThat(sl.getSuggestionForCategory("category2")).hasSize(1);
     }
 
+    @Test
+    public void isSuggestionDismissed_mismatchRule_shouldDismiss() {
+        final Tile suggestion = new Tile();
+        suggestion.metaData = new Bundle();
+        suggestion.metaData.putString(SuggestionParser.META_DATA_DISMISS_CONTROL, "1,2,3");
+        suggestion.intent = new Intent().setComponent(new ComponentName("pkg", "cls"));
+
+        // Dismiss suggestion when smart suggestion is not enabled.
+        mSuggestionParser.dismissSuggestion(suggestion, false /* isSmartSuggestionEnabled */);
+        final String suggestionKey = suggestion.intent.getComponent().flattenToShortString();
+        // And point to last rule in dismiss control
+        mPrefs.edit().putInt(suggestionKey + SuggestionParser.DISMISS_INDEX, 2).apply();
+
+        // Turn on smart suggestion, and check if suggestion is enabled.
+        assertThat(mSuggestionParser.isDismissed(suggestion, true /* isSmartSuggestionEnabled */))
+                .isTrue();
+    }
+
     private void readAndDismissSuggestion(boolean isSmartSuggestionEnabled) {
         mSuggestionsBeforeDismiss = new ArrayList<>();
         mSuggestionsAfterDismiss = new ArrayList<>();