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

Commit 095b1838 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Refactor suggestion parser."

parents 776b782f e138ef1d
Loading
Loading
Loading
Loading
+25 −0
Original line number Diff line number Diff line
/*
 * 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.settingslib.suggestions;

public class SuggestionCategory {
    public String category;
    public String pkg;
    public boolean multiple;
    public boolean exclusive;
    public long exclusiveExpireDaysInMillis;
}
+95 −0
Original line number Diff line number Diff line
/*
 * 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.settingslib.suggestions;

import android.content.Intent;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;

import com.android.settingslib.drawer.Tile;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class SuggestionList {
    // Category -> list of suggestion map
    private final Map<SuggestionCategory, List<Tile>> mSuggestions;

    // A flatten list of all suggestions.
    private List<Tile> mSuggestionList;

    public SuggestionList() {
        mSuggestions = new ArrayMap<>();
    }

    public void addSuggestions(SuggestionCategory category, List<Tile> suggestions) {
        mSuggestions.put(category, suggestions);
    }

    public List<Tile> getSuggestions() {
        if (mSuggestionList != null) {
            return mSuggestionList;
        }
        mSuggestionList = new ArrayList<>();
        for (List<Tile> suggestions : mSuggestions.values()) {
            mSuggestionList.addAll(suggestions);
        }
        dedupeSuggestions(mSuggestionList);
        return mSuggestionList;
    }

    public boolean isExclusiveSuggestionCategory() {
        if (mSuggestions.size() != 1) {
            // If there is no category, or more than 1 category, it's not exclusive by definition.
            return false;
        }
        for (SuggestionCategory category : mSuggestions.keySet()) {
            if (category.exclusive) {
                return true;
            }
        }
        return false;
    }

    public List<Tile> getSuggestionForCategory(String category) {
        for (Map.Entry<SuggestionCategory, List<Tile>> entry : mSuggestions.entrySet()) {
            if (TextUtils.equals(entry.getKey().category, category)) {
                return entry.getValue();
            }
        }
        return null;
    }

    /**
     * Filter suggestions list so they are all unique.
     */
    private void dedupeSuggestions(List<Tile> suggestions) {
        final Set<String> intents = new ArraySet<>();
        for (int i = suggestions.size() - 1; i >= 0; i--) {
            final Tile suggestion = suggestions.get(i);
            final String intentUri = suggestion.intent.toUri(Intent.URI_INTENT_SCHEME);
            if (intents.contains(intentUri)) {
                suggestions.remove(i);
            } else {
                intents.add(intentUri);
            }
        }
    }
}
+11 −37
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016 The Android Open Source Project
 * 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.
@@ -11,9 +11,9 @@
 * 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
 * limitations under the License.
 */
package com.android.settingslib;
package com.android.settingslib.suggestions;

import android.Manifest;
import android.accounts.Account;
@@ -134,12 +134,8 @@ public class SuggestionParser {
        mSmartDismissControl = smartDismissControl;
    }

    public List<Tile> getSuggestions() {
        return getSuggestions(false);
    }

    public List<Tile> getSuggestions(boolean isSmartSuggestionEnabled) {
        List<Tile> suggestions = new ArrayList<>();
    public SuggestionList getSuggestions(boolean isSmartSuggestionEnabled) {
        final SuggestionList suggestionList = new SuggestionList();
        final int N = mSuggestionList.size();
        for (int i = 0; i < N; i++) {
            final SuggestionCategory category = mSuggestionList.get(i);
@@ -153,16 +149,19 @@ public class SuggestionParser {
                // from each suggestion itself is used.
                readSuggestions(category, exclusiveSuggestions, false /* isSmartSuggestion */);
                if (!exclusiveSuggestions.isEmpty()) {
                    return exclusiveSuggestions;
                    final SuggestionList exclusiveList = new SuggestionList();
                    exclusiveList.addSuggestions(category, exclusiveSuggestions);
                    return exclusiveList;
                }
            } else {
                // Either the category is not exclusive, or the exclusiveness expired so we should
                // treat it as a normal category.
                final List<Tile> suggestions = new ArrayList<>();
                readSuggestions(category, suggestions, isSmartSuggestionEnabled);
                suggestionList.addSuggestions(category, suggestions);
            }
        }
        dedupeSuggestions(suggestions);
        return suggestions;
        return suggestionList;
    }

    public boolean dismissSuggestion(Tile suggestion) {
@@ -201,22 +200,6 @@ public class SuggestionParser {
        }
    }

    /**
     * Filter suggestions list so they are all unique.
     */
    private void dedupeSuggestions(List<Tile> suggestions) {
        final Set<String> intents = new ArraySet<>();
        for (int i = suggestions.size() - 1; i >= 0; i--) {
            final Tile suggestion = suggestions.get(i);
            final String intentUri = suggestion.intent.toUri(Intent.URI_INTENT_SCHEME);
            if (intents.contains(intentUri)) {
                suggestions.remove(i);
            } else {
                intents.add(intentUri);
            }
        }
    }

    @VisibleForTesting
    void readSuggestions(
            SuggestionCategory category, List<Tile> suggestions, boolean isSmartSuggestionEnabled) {
@@ -424,15 +407,6 @@ public class SuggestionParser {
        }
    }

    @VisibleForTesting
    static class SuggestionCategory {
        public String category;
        public String pkg;
        public boolean multiple;
        public boolean exclusive;
        public long exclusiveExpireDaysInMillis;
    }

    private static class SuggestionOrderInflater {
        private static final String TAG_LIST = "optional-steps";
        private static final String TAG_ITEM = "step";
+18 −19
Original line number Diff line number Diff line
@@ -16,18 +16,6 @@

package com.android.settingslib.drawer;

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.anyString;
import static org.mockito.Matchers.argThat;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.app.ActivityManager;
import android.content.ContentResolver;
import android.content.Context;
@@ -50,8 +38,8 @@ import android.util.ArrayMap;
import android.util.Pair;

import com.android.settingslib.R;
import com.android.settingslib.SuggestionParser;
import com.android.settingslib.TestConfig;
import com.android.settingslib.suggestions.SuggestionParser;

import org.junit.Before;
import org.junit.Test;
@@ -69,6 +57,17 @@ import java.util.Collections;
import java.util.List;
import java.util.Map;

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.anyString;
import static org.mockito.Matchers.argThat;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;


@RunWith(RobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+35 −23
Original line number Diff line number Diff line
@@ -14,7 +14,7 @@
 * limitations under the License.
 */

package com.android.settingslib;
package com.android.settingslib.suggestions;

import android.content.ComponentName;
import android.content.Context;
@@ -24,6 +24,8 @@ import android.content.pm.ResolveInfo;
import android.os.Bundle;
import android.preference.PreferenceManager;

import com.android.settingslib.SettingLibRobolectricTestRunner;
import com.android.settingslib.TestConfig;
import com.android.settingslib.drawer.Tile;
import com.android.settingslib.drawer.TileUtilsTest;

@@ -49,9 +51,9 @@ public class SuggestionParserTest {
    private Context mContext;
    private RobolectricPackageManager mPackageManager;
    private SuggestionParser mSuggestionParser;
    private SuggestionParser.SuggestionCategory mMultipleCategory;
    private SuggestionParser.SuggestionCategory mExclusiveCategory;
    private SuggestionParser.SuggestionCategory mExpiredExclusiveCategory;
    private SuggestionCategory mMultipleCategory;
    private SuggestionCategory mExclusiveCategory;
    private SuggestionCategory mExpiredExclusiveCategory;
    private List<Tile> mSuggestionsBeforeDismiss;
    private List<Tile> mSuggestionsAfterDismiss;
    private SharedPreferences mPrefs;
@@ -68,13 +70,13 @@ public class SuggestionParserTest {
        mSuggestion.intent = new Intent("action");
        mSuggestion.intent.setComponent(new ComponentName("pkg", "cls"));
        mSuggestion.metaData = new Bundle();
        mMultipleCategory = new SuggestionParser.SuggestionCategory();
        mMultipleCategory = new SuggestionCategory();
        mMultipleCategory.category = "category1";
        mMultipleCategory.multiple = true;
        mExclusiveCategory = new SuggestionParser.SuggestionCategory();
        mExclusiveCategory = new SuggestionCategory();
        mExclusiveCategory.category = "category2";
        mExclusiveCategory.exclusive = true;
        mExpiredExclusiveCategory = new SuggestionParser.SuggestionCategory();
        mExpiredExclusiveCategory = new SuggestionCategory();
        mExpiredExclusiveCategory.category = "category3";
        mExpiredExclusiveCategory.exclusive = true;
        mExpiredExclusiveCategory.exclusiveExpireDaysInMillis = 0;
@@ -83,16 +85,16 @@ public class SuggestionParserTest {
                Arrays.asList(mMultipleCategory, mExclusiveCategory, mExpiredExclusiveCategory),
                "0,0");

        ResolveInfo info1 = TileUtilsTest.newInfo(true, "category1");
        ResolveInfo info1 = TileUtilsTest.newInfo(true, null);
        info1.activityInfo.packageName = "pkg";
        ResolveInfo infoDupe1 = TileUtilsTest.newInfo(true, "category1");
        ResolveInfo infoDupe1 = TileUtilsTest.newInfo(true, null);
        infoDupe1.activityInfo.packageName = "pkg";

        ResolveInfo info2 = TileUtilsTest.newInfo(true, "category1");
        ResolveInfo info2 = TileUtilsTest.newInfo(true, null);
        info2.activityInfo.packageName = "pkg2";
        ResolveInfo info3 = TileUtilsTest.newInfo(true, "category2");
        ResolveInfo info3 = TileUtilsTest.newInfo(true, null);
        info3.activityInfo.packageName = "pkg3";
        ResolveInfo info4 = TileUtilsTest.newInfo(true, "category3");
        ResolveInfo info4 = TileUtilsTest.newInfo(true, null);
        info4.activityInfo.packageName = "pkg4";

        Intent intent1 = new Intent(Intent.ACTION_MAIN).addCategory("category1");
@@ -143,12 +145,12 @@ public class SuggestionParserTest {
                "pkg4");

        // If exclusive item is not available, the other categories should be shown
        final List<Tile> suggestions = mSuggestionParser.getSuggestions();

        final SuggestionList sl =
                mSuggestionParser.getSuggestions(false /* isSmartSuggestionEnabled */);
        final List<Tile> suggestions = sl.getSuggestions();
        assertThat(suggestions).hasSize(2);
        assertThat(suggestions.get(0).category).isEqualTo("category1");

        assertThat(suggestions.get(0).intent.getComponent().getPackageName()).isEqualTo("pkg");
        assertThat(suggestions.get(1).category).isEqualTo("category1");
        assertThat(suggestions.get(1).intent.getComponent().getPackageName()).isEqualTo("pkg2");
    }

@@ -165,18 +167,27 @@ public class SuggestionParserTest {
                .commit();

        // If exclusive is expired, they should be shown together with the other categories
        final List<Tile> suggestions = mSuggestionParser.getSuggestions();
        final SuggestionList sl =
                mSuggestionParser.getSuggestions(true /* isSmartSuggestionEnabled */);
        final List<Tile> suggestions = sl.getSuggestions();

        assertThat(suggestions).hasSize(3);
        assertThat(suggestions.get(0).category).isEqualTo("category1");
        assertThat(suggestions.get(1).category).isEqualTo("category1");
        assertThat(suggestions.get(2).category).isEqualTo("category3");

        final List<Tile> category1Suggestions = sl.getSuggestionForCategory("category1");
        final List<Tile> category3Suggestions = sl.getSuggestionForCategory("category3");

        assertThat(category1Suggestions).hasSize(2);
        assertThat(category3Suggestions).hasSize(1);
    }

    @Test
    public void testGetSuggestions_exclusive() {
        final List<Tile> suggestions = mSuggestionParser.getSuggestions();
        final SuggestionList sl =
                mSuggestionParser.getSuggestions(false /* isSmartSuggestionEnabled */);
        final List<Tile> suggestions = sl.getSuggestions();

        assertThat(suggestions).hasSize(1);
        assertThat(suggestions.get(0).category).isEqualTo("category2");
        assertThat(sl.getSuggestionForCategory("category2")).hasSize(1);
    }

    private void readAndDismissSuggestion(boolean isSmartSuggestionEnabled) {
@@ -184,10 +195,11 @@ public class SuggestionParserTest {
        mSuggestionsAfterDismiss = new ArrayList<>();
        mSuggestionParser.readSuggestions(
                mMultipleCategory, mSuggestionsBeforeDismiss, isSmartSuggestionEnabled);

        final Tile suggestion = mSuggestionsBeforeDismiss.get(0);
        if (mSuggestionParser.dismissSuggestion(suggestion, isSmartSuggestionEnabled)) {
            RuntimeEnvironment.getRobolectricPackageManager().removeResolveInfosForIntent(
                    new Intent(Intent.ACTION_MAIN).addCategory(suggestion.category),
                    new Intent(Intent.ACTION_MAIN).addCategory(mMultipleCategory.category),
                    suggestion.intent.getComponent().getPackageName());
        }
        mSuggestionParser.readSuggestions(