Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4d37a1a1 authored by Fan Zhang's avatar Fan Zhang
Browse files

Fix suggestion crash if parser fails to parse dismiss rule

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.

Change-Id: Id3ea88b6d321434e20ac0cd3e2670524c237e24e
Bug: 63908636
Test: robotests
parent 4486a431
Loading
Loading
Loading
Loading
+9 −3
Original line number Diff line number Diff line
@@ -91,8 +91,9 @@ public class SuggestionParser {

    // Shared prefs keys for storing dismissed state.
    // Index into current dismissed state.
    @VisibleForTesting
    static final String DISMISS_INDEX = "_dismiss_index";
    public static final String SETUP_TIME = "_setup_time";
    private static final String DISMISS_INDEX = "_dismiss_index";
    private static final String IS_DISMISSED = "_is_dismissed";

    // Default dismiss control for smart suggestions.
@@ -353,7 +354,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;
@@ -370,7 +372,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.
+20 −2
Original line number Diff line number Diff line
@@ -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<>();