OSDN Git Service

Encapsulate AppFilter and its display label into 1 class
authorFan Zhang <zhfan@google.com>
Thu, 12 Oct 2017 18:09:24 +0000 (11:09 -0700)
committerFan Zhang <zhfan@google.com>
Fri, 13 Oct 2017 21:33:11 +0000 (14:33 -0700)
Bug: 64804294
Test: robotests
Change-Id: I2a752794ded4ccb8510adf37d41afa4514d8c4c0

src/com/android/settings/applications/manageapplications/AppFilterItem.java [new file with mode: 0644]
src/com/android/settings/applications/manageapplications/AppFilterRegistry.java [new file with mode: 0644]
src/com/android/settings/applications/manageapplications/ManageApplications.java
tests/robotests/src/com/android/settings/applications/manageapplications/AppFilterItemTest.java [new file with mode: 0644]
tests/robotests/src/com/android/settings/applications/manageapplications/AppFilterRegistryTest.java [new file with mode: 0644]
tests/robotests/src/com/android/settings/applications/manageapplications/ManageApplicationsTest.java

diff --git a/src/com/android/settings/applications/manageapplications/AppFilterItem.java b/src/com/android/settings/applications/manageapplications/AppFilterItem.java
new file mode 100644 (file)
index 0000000..c6f5639
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * 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.applications.manageapplications;
+
+import android.support.annotation.StringRes;
+
+import com.android.settingslib.applications.ApplicationsState;
+
+import java.util.Objects;
+
+/**
+ * Data model for a displayable app filter.
+ */
+public class AppFilterItem implements Comparable<AppFilterItem> {
+
+    @StringRes
+    private final int mTitle;
+    @AppFilterRegistry.FilterType
+    private final int mFilterType;
+    private final ApplicationsState.AppFilter mFilter;
+
+    public AppFilterItem(ApplicationsState.AppFilter filter,
+            @AppFilterRegistry.FilterType int filterType,
+            @StringRes int title) {
+        mTitle = title;
+        mFilterType = filterType;
+        mFilter = filter;
+    }
+
+    public int getTitle() {
+        return mTitle;
+    }
+
+    public ApplicationsState.AppFilter getFilter() {
+        return mFilter;
+    }
+
+    public int getFilterType() {
+        return mFilterType;
+    }
+
+    @Override
+    public int compareTo(AppFilterItem appFilter) {
+        if (appFilter == null) {
+            return 1;
+        }
+        if (this == appFilter) {
+            return 0;
+        }
+        return mFilterType - appFilter.mFilterType;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (o == null || !(o instanceof AppFilterItem)) {
+            return false;
+        }
+        if (this == o) {
+            return true;
+        }
+        final AppFilterItem other = (AppFilterItem) o;
+        return mTitle == other.mTitle
+                && mFilterType == other.mFilterType
+                && mFilter == other.mFilter;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mFilter, mTitle, mFilterType);
+    }
+}
diff --git a/src/com/android/settings/applications/manageapplications/AppFilterRegistry.java b/src/com/android/settings/applications/manageapplications/AppFilterRegistry.java
new file mode 100644 (file)
index 0000000..01d2cb8
--- /dev/null
@@ -0,0 +1,188 @@
+/*
+ * 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.applications.manageapplications;
+
+import android.support.annotation.IntDef;
+
+import com.android.settings.R;
+import com.android.settings.applications.AppStateInstallAppsBridge;
+import com.android.settings.applications.AppStateNotificationBridge;
+import com.android.settings.applications.AppStateOverlayBridge;
+import com.android.settings.applications.AppStatePowerBridge;
+import com.android.settings.applications.AppStateUsageBridge;
+import com.android.settings.applications.AppStateWriteSettingsBridge;
+import com.android.settingslib.applications.ApplicationsState;
+
+/**
+ * A registry and helper class that manages all {@link AppFilterItem}s for ManageApplications UI.
+ */
+public class AppFilterRegistry {
+
+    @IntDef(value = {
+            FILTER_APPS_POWER_WHITELIST,
+            FILTER_APPS_POWER_WHITELIST_ALL,
+            FILTER_APPS_ALL,
+            FILTER_APPS_ENABLED,
+            FILTER_APPS_INSTANT,
+            FILTER_APPS_DISABLED,
+            FILTER_APPS_BLOCKED,
+            FILTER_APPS_PERSONAL,
+            FILTER_APPS_WORK,
+            FILTER_APPS_USAGE_ACCESS,
+            FILTER_APPS_WITH_OVERLAY,
+            FILTER_APPS_WRITE_SETTINGS,
+            FILTER_APPS_INSTALL_SOURCES,
+    })
+    @interface FilterType {
+    }
+
+    // Filter options used for displayed list of applications
+    // Filters will appear sorted based on their value defined here.
+    public static final int FILTER_APPS_POWER_WHITELIST = 0;
+    public static final int FILTER_APPS_POWER_WHITELIST_ALL = 1;
+    public static final int FILTER_APPS_ALL = 2;
+    public static final int FILTER_APPS_ENABLED = 3;
+    public static final int FILTER_APPS_INSTANT = 4;
+    public static final int FILTER_APPS_DISABLED = 5;
+    public static final int FILTER_APPS_BLOCKED = 6;
+    public static final int FILTER_APPS_PERSONAL = 7;
+    public static final int FILTER_APPS_WORK = 8;
+    public static final int FILTER_APPS_USAGE_ACCESS = 9;
+    public static final int FILTER_APPS_WITH_OVERLAY = 10;
+    public static final int FILTER_APPS_WRITE_SETTINGS = 11;
+    public static final int FILTER_APPS_INSTALL_SOURCES = 12;
+    // Next id: 13
+
+    private static AppFilterRegistry sRegistry;
+
+    private final AppFilterItem[] mFilters;
+
+    private AppFilterRegistry() {
+        mFilters = new AppFilterItem[13];
+
+        // High power whitelist, on
+        mFilters[FILTER_APPS_POWER_WHITELIST] = new AppFilterItem(
+                new ApplicationsState.CompoundFilter(
+                        AppStatePowerBridge.FILTER_POWER_WHITELISTED,
+                        ApplicationsState.FILTER_ALL_ENABLED),
+                FILTER_APPS_POWER_WHITELIST,
+                R.string.high_power_filter_on);
+
+        // Without disabled until used
+        mFilters[FILTER_APPS_POWER_WHITELIST_ALL] = new AppFilterItem(
+                new ApplicationsState.CompoundFilter(
+                        ApplicationsState.FILTER_WITHOUT_DISABLED_UNTIL_USED,
+                        ApplicationsState.FILTER_ALL_ENABLED),
+                FILTER_APPS_POWER_WHITELIST_ALL,
+                R.string.filter_all_apps);
+
+        // All apps
+        mFilters[FILTER_APPS_ALL] = new AppFilterItem(
+                ApplicationsState.FILTER_EVERYTHING,
+                FILTER_APPS_ALL,
+                R.string.filter_all_apps);
+
+        // Enabled
+        mFilters[FILTER_APPS_ENABLED] = new AppFilterItem(
+                ApplicationsState.FILTER_ALL_ENABLED,
+                FILTER_APPS_ENABLED,
+                R.string.filter_enabled_apps);
+
+        // Disabled
+        mFilters[FILTER_APPS_DISABLED] = new AppFilterItem(
+                ApplicationsState.FILTER_DISABLED,
+                FILTER_APPS_DISABLED,
+                R.string.filter_apps_disabled);
+
+        // Instant
+        mFilters[FILTER_APPS_INSTANT] = new AppFilterItem(
+                ApplicationsState.FILTER_INSTANT,
+                FILTER_APPS_INSTANT,
+                R.string.filter_instant_apps);
+
+        // Blocked Notifications
+        mFilters[FILTER_APPS_BLOCKED] = new AppFilterItem(
+                AppStateNotificationBridge.FILTER_APP_NOTIFICATION_BLOCKED,
+                FILTER_APPS_BLOCKED,
+                R.string.filter_notif_blocked_apps);
+
+        // Personal
+        mFilters[FILTER_APPS_PERSONAL] = new AppFilterItem(
+                ApplicationsState.FILTER_PERSONAL,
+                FILTER_APPS_PERSONAL,
+                R.string.filter_personal_apps);
+
+        // Work
+        mFilters[FILTER_APPS_WORK] = new AppFilterItem(
+                ApplicationsState.FILTER_WORK,
+                FILTER_APPS_WORK,
+                R.string.filter_work_apps);
+
+        // Usage access screen, never displayed.
+        mFilters[FILTER_APPS_USAGE_ACCESS] = new AppFilterItem(
+                AppStateUsageBridge.FILTER_APP_USAGE,
+                FILTER_APPS_USAGE_ACCESS,
+                R.string.filter_all_apps);
+
+        // Apps that can draw overlays
+        mFilters[FILTER_APPS_WITH_OVERLAY] = new AppFilterItem(
+                AppStateOverlayBridge.FILTER_SYSTEM_ALERT_WINDOW,
+                FILTER_APPS_WITH_OVERLAY,
+                R.string.filter_overlay_apps);
+
+        // Apps that can write system settings
+        mFilters[FILTER_APPS_WRITE_SETTINGS] = new AppFilterItem(
+                AppStateWriteSettingsBridge.FILTER_WRITE_SETTINGS,
+                FILTER_APPS_WRITE_SETTINGS,
+                R.string.filter_write_settings_apps);
+
+        // Apps that are trusted sources of apks
+        mFilters[FILTER_APPS_INSTALL_SOURCES] = new AppFilterItem(
+                AppStateInstallAppsBridge.FILTER_APP_SOURCES,
+                FILTER_APPS_INSTALL_SOURCES,
+                R.string.filter_install_sources_apps);
+    }
+
+    public static AppFilterRegistry getInstance() {
+        if (sRegistry == null) {
+            sRegistry = new AppFilterRegistry();
+        }
+        return sRegistry;
+    }
+
+    @FilterType
+    public int getDefaultFilterType(int listType) {
+        switch (listType) {
+            case ManageApplications.LIST_TYPE_USAGE_ACCESS:
+                return FILTER_APPS_USAGE_ACCESS;
+            case ManageApplications.LIST_TYPE_HIGH_POWER:
+                return FILTER_APPS_POWER_WHITELIST;
+            case ManageApplications.LIST_TYPE_OVERLAY:
+                return FILTER_APPS_WITH_OVERLAY;
+            case ManageApplications.LIST_TYPE_WRITE_SETTINGS:
+                return FILTER_APPS_WRITE_SETTINGS;
+            case ManageApplications.LIST_TYPE_MANAGE_SOURCES:
+                return FILTER_APPS_INSTALL_SOURCES;
+            default:
+                return FILTER_APPS_ALL;
+        }
+    }
+
+    public AppFilterItem get(@FilterType int filterType) {
+        return mFilters[filterType];
+    }
+}
index c0732f5..932b2dd 100644 (file)
 
 package com.android.settings.applications.manageapplications;
 
-import android.annotation.IdRes;
+import static com.android.settings.applications.manageapplications.AppFilterRegistry
+        .FILTER_APPS_BLOCKED;
+import static com.android.settings.applications.manageapplications.AppFilterRegistry
+        .FILTER_APPS_DISABLED;
+import static com.android.settings.applications.manageapplications.AppFilterRegistry
+        .FILTER_APPS_ENABLED;
+import static com.android.settings.applications.manageapplications.AppFilterRegistry
+        .FILTER_APPS_INSTANT;
+import static com.android.settings.applications.manageapplications.AppFilterRegistry
+        .FILTER_APPS_PERSONAL;
+import static com.android.settings.applications.manageapplications.AppFilterRegistry
+        .FILTER_APPS_POWER_WHITELIST;
+import static com.android.settings.applications.manageapplications.AppFilterRegistry
+        .FILTER_APPS_POWER_WHITELIST_ALL;
+import static com.android.settings.applications.manageapplications.AppFilterRegistry
+        .FILTER_APPS_WORK;
+
 import android.annotation.Nullable;
 import android.annotation.StringRes;
 import android.app.Activity;
@@ -152,88 +168,6 @@ public class ManageApplications extends InstrumentedPreferenceFragment
     public static final int SIZE_INTERNAL = 1;
     public static final int SIZE_EXTERNAL = 2;
 
-    // Filter options used for displayed list of applications
-    // Filters will appear sorted based on their value defined here.
-    public static final int FILTER_APPS_POWER_WHITELIST = 0;
-    public static final int FILTER_APPS_POWER_WHITELIST_ALL = 1;
-    public static final int FILTER_APPS_ALL = 2;
-    public static final int FILTER_APPS_ENABLED = 3;
-    public static final int FILTER_APPS_INSTANT = 4;
-    public static final int FILTER_APPS_DISABLED = 5;
-    public static final int FILTER_APPS_BLOCKED = 6;
-    public static final int FILTER_APPS_PERSONAL = 7;
-    public static final int FILTER_APPS_WORK = 8;
-    public static final int FILTER_APPS_USAGE_ACCESS = 9;
-    public static final int FILTER_APPS_WITH_OVERLAY = 10;
-    public static final int FILTER_APPS_WRITE_SETTINGS = 11;
-    public static final int FILTER_APPS_INSTALL_SOURCES = 12;
-    public static final int FILTER_APPS_COUNT = 13;  // This should always be the last entry
-
-    // Mapping to string labels for the FILTER_APPS_* constants above.
-    @IdRes
-    public static final int[] FILTER_LABELS = new int[FILTER_APPS_COUNT];
-
-    // Mapping to filters for the FILTER_APPS_* constants above.
-    public static final AppFilter[] FILTERS = new AppFilter[FILTER_APPS_COUNT];
-
-    static {
-        // High power whitelist, on
-        FILTER_LABELS[FILTER_APPS_POWER_WHITELIST] = R.string.high_power_filter_on;
-        FILTERS[FILTER_APPS_POWER_WHITELIST] = new CompoundFilter(
-                AppStatePowerBridge.FILTER_POWER_WHITELISTED,
-                ApplicationsState.FILTER_ALL_ENABLED);
-
-        // Without disabled until used
-        FILTER_LABELS[FILTER_APPS_POWER_WHITELIST_ALL] = R.string.filter_all_apps;
-        FILTERS[FILTER_APPS_POWER_WHITELIST_ALL] = new CompoundFilter(
-                ApplicationsState.FILTER_WITHOUT_DISABLED_UNTIL_USED,
-                ApplicationsState.FILTER_ALL_ENABLED);
-
-        // All apps
-        FILTER_LABELS[FILTER_APPS_ALL] = R.string.filter_all_apps;
-        FILTERS[FILTER_APPS_ALL] = ApplicationsState.FILTER_EVERYTHING;
-
-        // Enabled
-        FILTER_LABELS[FILTER_APPS_ENABLED] = R.string.filter_enabled_apps;
-        FILTERS[FILTER_APPS_ENABLED] = ApplicationsState.FILTER_ALL_ENABLED;
-
-        // Disabled
-        FILTER_LABELS[FILTER_APPS_DISABLED] = R.string.filter_apps_disabled;
-        FILTERS[FILTER_APPS_DISABLED] = ApplicationsState.FILTER_DISABLED;
-
-        // Instant
-        FILTER_LABELS[FILTER_APPS_INSTANT] = R.string.filter_instant_apps;
-        FILTERS[FILTER_APPS_INSTANT] = ApplicationsState.FILTER_INSTANT;
-
-        // Blocked Notifications
-        FILTER_LABELS[FILTER_APPS_BLOCKED] = R.string.filter_notif_blocked_apps;
-        FILTERS[FILTER_APPS_BLOCKED] = AppStateNotificationBridge.FILTER_APP_NOTIFICATION_BLOCKED;
-
-        // Personal
-        FILTER_LABELS[FILTER_APPS_PERSONAL] = R.string.filter_personal_apps;
-        FILTERS[FILTER_APPS_PERSONAL] = ApplicationsState.FILTER_PERSONAL;
-
-        // Work
-        FILTER_LABELS[FILTER_APPS_WORK] = R.string.filter_work_apps;
-        FILTERS[FILTER_APPS_WORK] = ApplicationsState.FILTER_WORK;
-
-        // Usage access screen, never displayed.
-        FILTER_LABELS[FILTER_APPS_USAGE_ACCESS] = R.string.filter_all_apps;
-        FILTERS[FILTER_APPS_USAGE_ACCESS] = AppStateUsageBridge.FILTER_APP_USAGE;
-
-        // Apps that can draw overlays
-        FILTER_LABELS[FILTER_APPS_WITH_OVERLAY] = R.string.filter_overlay_apps;
-        FILTERS[FILTER_APPS_WITH_OVERLAY] = AppStateOverlayBridge.FILTER_SYSTEM_ALERT_WINDOW;
-
-        // Apps that can write system settings
-        FILTER_LABELS[FILTER_APPS_WRITE_SETTINGS] = R.string.filter_write_settings_apps;
-        FILTERS[FILTER_APPS_WRITE_SETTINGS] = AppStateWriteSettingsBridge.FILTER_WRITE_SETTINGS;
-
-        // Apps that are trusted sources of apks
-        FILTER_LABELS[FILTER_APPS_INSTALL_SOURCES] = R.string.filter_install_sources_apps;
-        FILTERS[FILTER_APPS_INSTALL_SOURCES] = AppStateInstallAppsBridge.FILTER_APP_SOURCES;
-    }
-
     // Storage types. Used to determine what the extra item in the list of preferences is.
     public static final int STORAGE_TYPE_DEFAULT = 0; // Show all apps that are not categorized.
     public static final int STORAGE_TYPE_MUSIC = 1;
@@ -251,7 +185,7 @@ public class ManageApplications extends InstrumentedPreferenceFragment
     private ApplicationsState mApplicationsState;
 
     public int mListType;
-    public int mFilter;
+    public AppFilterItem mFilter;
 
     public ApplicationsAdapter mApplications;
 
@@ -285,14 +219,12 @@ public class ManageApplications extends InstrumentedPreferenceFragment
     public static final int LIST_TYPE_MOVIES = 10;
     public static final int LIST_TYPE_PHOTOGRAPHY = 11;
 
-
     // List types that should show instant apps.
     public static final Set<Integer> LIST_TYPES_WITH_INSTANT = new ArraySet<>(Arrays.asList(
             LIST_TYPE_MAIN,
             LIST_TYPE_STORAGE));
 
     private View mRootView;
-
     private View mSpinnerHeader;
     private Spinner mFilterSpinner;
     private FilterSpinnerAdapter mFilterAdapter;
@@ -354,7 +286,8 @@ public class ManageApplications extends InstrumentedPreferenceFragment
         } else {
             mListType = LIST_TYPE_MAIN;
         }
-        mFilter = getDefaultFilter();
+        final AppFilterRegistry appFilterRegistry = AppFilterRegistry.getInstance();
+        mFilter = appFilterRegistry.get(appFilterRegistry.getDefaultFilterType(mListType));
         mIsWorkOnly = args != null ? args.getBoolean(EXTRA_WORK_ONLY) : false;
         mWorkUserId = args != null ? args.getInt(EXTRA_WORK_ID) : NO_USER_SPECIFIED;
 
@@ -380,7 +313,7 @@ public class ManageApplications extends InstrumentedPreferenceFragment
         if (mListContainer != null) {
             // Create adapter and list view here
             View emptyView = mListContainer.findViewById(com.android.internal.R.id.empty);
-            ListView lv = (ListView) mListContainer.findViewById(android.R.id.list);
+            ListView lv = mListContainer.findViewById(android.R.id.list);
             if (emptyView != null) {
                 lv.setEmptyView(emptyView);
             }
@@ -436,17 +369,18 @@ public class ManageApplications extends InstrumentedPreferenceFragment
 
     @VisibleForTesting
     void createHeader() {
-        Activity activity = getActivity();
-        FrameLayout pinnedHeader = (FrameLayout) mRootView.findViewById(R.id.pinned_header);
+        final Activity activity = getActivity();
+        final FrameLayout pinnedHeader = mRootView.findViewById(R.id.pinned_header);
         mSpinnerHeader = activity.getLayoutInflater()
                 .inflate(R.layout.apps_filter_spinner, pinnedHeader, false);
-        mFilterSpinner = (Spinner) mSpinnerHeader.findViewById(R.id.filter_spinner);
+        mFilterSpinner = mSpinnerHeader.findViewById(R.id.filter_spinner);
         mFilterAdapter = new FilterSpinnerAdapter(this);
         mFilterSpinner.setAdapter(mFilterAdapter);
         mFilterSpinner.setOnItemSelectedListener(this);
         pinnedHeader.addView(mSpinnerHeader, 0);
 
-        mFilterAdapter.enableFilter(getDefaultFilter());
+        final AppFilterRegistry appFilterRegistry = AppFilterRegistry.getInstance();
+        mFilterAdapter.enableFilter(appFilterRegistry.getDefaultFilterType(mListType));
         if (mListType == LIST_TYPE_MAIN) {
             if (UserManager.get(getActivity()).getUserProfiles().size() > 1) {
                 mFilterAdapter.enableFilter(FILTER_APPS_PERSONAL);
@@ -462,7 +396,8 @@ public class ManageApplications extends InstrumentedPreferenceFragment
 
         AppFilter compositeFilter = getCompositeFilter(mListType, mStorageType, mVolumeUuid);
         if (mIsWorkOnly) {
-            compositeFilter = new CompoundFilter(compositeFilter, FILTERS[FILTER_APPS_WORK]);
+            final AppFilter workFilter = appFilterRegistry.get(FILTER_APPS_WORK).getFilter();
+            compositeFilter = new CompoundFilter(compositeFilter, workFilter);
         }
         if (compositeFilter != null) {
             mApplications.setCompositeFilter(compositeFilter);
@@ -492,23 +427,6 @@ public class ManageApplications extends InstrumentedPreferenceFragment
         return null;
     }
 
-    private int getDefaultFilter() {
-        switch (mListType) {
-            case LIST_TYPE_USAGE_ACCESS:
-                return FILTER_APPS_USAGE_ACCESS;
-            case LIST_TYPE_HIGH_POWER:
-                return FILTER_APPS_POWER_WHITELIST;
-            case LIST_TYPE_OVERLAY:
-                return FILTER_APPS_WITH_OVERLAY;
-            case LIST_TYPE_WRITE_SETTINGS:
-                return FILTER_APPS_WRITE_SETTINGS;
-            case LIST_TYPE_MANAGE_SOURCES:
-                return FILTER_APPS_INSTALL_SOURCES;
-            default:
-                return FILTER_APPS_ALL;
-        }
-    }
-
     private boolean isFastScrollEnabled() {
         switch (mListType) {
             case LIST_TYPE_MAIN:
@@ -723,7 +641,7 @@ public class ManageApplications extends InstrumentedPreferenceFragment
             case R.id.show_system:
             case R.id.hide_system:
                 mShowSystem = !mShowSystem;
-                mApplications.rebuild(false);
+                mApplications.rebuild();
                 break;
             case R.id.reset_app_preferences:
                 mResetAppsHelper.buildResetDialog();
@@ -800,22 +718,24 @@ public class ManageApplications extends InstrumentedPreferenceFragment
     static class FilterSpinnerAdapter extends ArrayAdapter<CharSequence> {
 
         private final ManageApplications mManageApplications;
+        private final Context mContext;
 
         // Use ArrayAdapter for view logic, but have our own list for managing
         // the options available.
-        private final ArrayList<Integer> mFilterOptions = new ArrayList<>();
+        private final ArrayList<AppFilterItem> mFilterOptions = new ArrayList<>();
 
         public FilterSpinnerAdapter(ManageApplications manageApplications) {
-            super(manageApplications.mFilterSpinner.getContext(), R.layout.filter_spinner_item);
-            setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+            super(manageApplications.getContext(), R.layout.filter_spinner_item);
+            mContext = manageApplications.getContext();
             mManageApplications = manageApplications;
+            setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
         }
 
-        public int getFilter(int position) {
+        public AppFilterItem getFilter(int position) {
             return mFilterOptions.get(position);
         }
 
-        public void setFilterEnabled(int filter, boolean enabled) {
+        public void setFilterEnabled(@AppFilterRegistry.FilterType int filter, boolean enabled) {
             if (enabled) {
                 enableFilter(filter);
             } else {
@@ -823,9 +743,14 @@ public class ManageApplications extends InstrumentedPreferenceFragment
             }
         }
 
-        public void enableFilter(int filter) {
-            if (mFilterOptions.contains(filter)) return;
-            if (DEBUG) Log.d(TAG, "Enabling filter " + filter);
+        public void enableFilter(@AppFilterRegistry.FilterType int filterType) {
+            final AppFilterItem filter = AppFilterRegistry.getInstance().get(filterType);
+            if (mFilterOptions.contains(filter)) {
+                return;
+            }
+            if (DEBUG) {
+                Log.d(TAG, "Enabling filter " + filter);
+            }
             mFilterOptions.add(filter);
             Collections.sort(mFilterOptions);
             mManageApplications.mSpinnerHeader.setVisibility(
@@ -838,11 +763,14 @@ public class ManageApplications extends InstrumentedPreferenceFragment
             }
         }
 
-        public void disableFilter(int filter) {
-            if (!mFilterOptions.remove((Integer) filter)) {
+        public void disableFilter(@AppFilterRegistry.FilterType int filterType) {
+            final AppFilterItem filter = AppFilterRegistry.getInstance().get(filterType);
+            if (!mFilterOptions.remove(filter)) {
                 return;
             }
-            if (DEBUG) Log.d(TAG, "Disabling filter " + filter);
+            if (DEBUG) {
+                Log.d(TAG, "Disabling filter " + filter);
+            }
             Collections.sort(mFilterOptions);
             mManageApplications.mSpinnerHeader.setVisibility(
                     mFilterOptions.size() > 1 ? View.VISIBLE : View.GONE);
@@ -863,11 +791,7 @@ public class ManageApplications extends InstrumentedPreferenceFragment
 
         @Override
         public CharSequence getItem(int position) {
-            return getFilterString(mFilterOptions.get(position));
-        }
-
-        private CharSequence getFilterString(int filter) {
-            return mManageApplications.getString(FILTER_LABELS[filter]);
+            return mContext.getText(mFilterOptions.get(position).getTitle());
         }
     }
 
@@ -890,13 +814,13 @@ public class ManageApplications extends InstrumentedPreferenceFragment
         private final ApplicationsState.Session mSession;
         private final ManageApplications mManageApplications;
         private final Context mContext;
-        private final ArrayList<View> mActive = new ArrayList<View>();
+        private final ArrayList<View> mActive = new ArrayList<>();
         private final AppStateBaseBridge mExtraInfoBridge;
         private final Handler mBgHandler;
         private final Handler mFgHandler;
         private final LoadingViewController mLoadingViewController;
 
-        private int mFilterMode;
+        private AppFilterItem mAppFilter;
         private ArrayList<ApplicationsState.AppEntry> mBaseEntries;
         private ArrayList<ApplicationsState.AppEntry> mEntries;
         private boolean mResumed;
@@ -941,7 +865,7 @@ public class ManageApplications extends InstrumentedPreferenceFragment
 
 
         public ApplicationsAdapter(ApplicationsState state, ManageApplications manageApplications,
-                int filterMode) {
+                AppFilterItem appFilter) {
             mState = state;
             mFgHandler = new Handler();
             mBgHandler = new Handler(mState.getBackgroundLooper());
@@ -952,7 +876,7 @@ public class ManageApplications extends InstrumentedPreferenceFragment
                     mManageApplications.mListContainer
             );
             mContext = manageApplications.getActivity();
-            mFilterMode = filterMode;
+            mAppFilter = appFilter;
             if (mManageApplications.mListType == LIST_TYPE_NOTIFICATION) {
                 mExtraInfoBridge = new AppStateNotificationBridge(mContext, mState, this,
                         manageApplications.mNotifBackend);
@@ -973,12 +897,12 @@ public class ManageApplications extends InstrumentedPreferenceFragment
 
         public void setCompositeFilter(AppFilter compositeFilter) {
             mCompositeFilter = compositeFilter;
-            rebuild(true);
+            rebuild();
         }
 
-        public void setFilter(int filter) {
-            mFilterMode = filter;
-            rebuild(true);
+        public void setFilter(AppFilterItem appFilter) {
+            mAppFilter = appFilter;
+            rebuild();
         }
 
         public void setExtraViewController(FileViewHolderController extraViewController) {
@@ -1000,7 +924,7 @@ public class ManageApplications extends InstrumentedPreferenceFragment
                 if (mExtraInfoBridge != null) {
                     mExtraInfoBridge.resume();
                 }
-                rebuild(false);
+                rebuild();
             } else {
                 rebuild(sort);
             }
@@ -1033,10 +957,10 @@ public class ManageApplications extends InstrumentedPreferenceFragment
                 return;
             }
             mLastSortMode = sort;
-            rebuild(true);
+            rebuild();
         }
 
-        public void rebuild(boolean eraseold) {
+        public void rebuild() {
             if (!mHasReceivedLoadEntries
                     || (mExtraInfoBridge != null && !mHasReceivedBridgeCallback)) {
                 // Don't rebuild the list until all the app entries are loaded.
@@ -1050,7 +974,7 @@ public class ManageApplications extends InstrumentedPreferenceFragment
             } else {
                 mWhichSize = SIZE_INTERNAL;
             }
-            filterObj = FILTERS[mFilterMode];
+            filterObj = mAppFilter.getFilter();
             if (mCompositeFilter != null) {
                 filterObj = new CompoundFilter(filterObj, mCompositeFilter);
             }
@@ -1126,8 +1050,9 @@ public class ManageApplications extends InstrumentedPreferenceFragment
 
         @Override
         public void onRebuildComplete(ArrayList<AppEntry> entries) {
-            if (mFilterMode == FILTER_APPS_POWER_WHITELIST ||
-                    mFilterMode == FILTER_APPS_POWER_WHITELIST_ALL) {
+            final int filterType = mAppFilter.getFilterType();
+            if (filterType == FILTER_APPS_POWER_WHITELIST ||
+                    filterType == FILTER_APPS_POWER_WHITELIST_ALL) {
                 entries = removeDuplicateIgnoringUser(entries);
             }
             mBaseEntries = entries;
@@ -1169,7 +1094,7 @@ public class ManageApplications extends InstrumentedPreferenceFragment
                     if (locales.size() == 0) {
                         locales = new LocaleList(Locale.ENGLISH);
                     }
-                    AlphabeticIndex<Locale> index = new AlphabeticIndex<>(locales.get(0));
+                    AlphabeticIndex<Locale> index = new AlphabeticIndex(locales.get(0));
                     int localeCount = locales.size();
                     for (int i = 1; i < localeCount; i++) {
                         index.addLabels(locales.get(i));
@@ -1233,7 +1158,7 @@ public class ManageApplications extends InstrumentedPreferenceFragment
         @Override
         public void onExtraInfoUpdated() {
             mHasReceivedBridgeCallback = true;
-            rebuild(false);
+            rebuild();
         }
 
         @Override
@@ -1243,7 +1168,7 @@ public class ManageApplications extends InstrumentedPreferenceFragment
 
         @Override
         public void onPackageListChanged() {
-            rebuild(false);
+            rebuild();
         }
 
         @Override
@@ -1256,7 +1181,7 @@ public class ManageApplications extends InstrumentedPreferenceFragment
         public void onLoadEntriesCompleted() {
             mHasReceivedLoadEntries = true;
             // We may have been skipping rebuilds until this came in, trigger one now.
-            rebuild(false);
+            rebuild();
         }
 
         @Override
@@ -1280,7 +1205,7 @@ public class ManageApplications extends InstrumentedPreferenceFragment
                         // user viewed, and are sorting by size...  they may
                         // have cleared data, so we immediately want to resort
                         // the list with the new size to reflect it to the user.
-                        rebuild(false);
+                        rebuild();
                     }
                     return;
                 }
@@ -1290,14 +1215,14 @@ public class ManageApplications extends InstrumentedPreferenceFragment
         @Override
         public void onLauncherInfoChanged() {
             if (!mManageApplications.mShowSystem) {
-                rebuild(false);
+                rebuild();
             }
         }
 
         @Override
         public void onAllSizesComputed() {
             if (mLastSortMode == R.id.sort_order_size) {
-                rebuild(false);
+                rebuild();
             }
         }
 
diff --git a/tests/robotests/src/com/android/settings/applications/manageapplications/AppFilterItemTest.java b/tests/robotests/src/com/android/settings/applications/manageapplications/AppFilterItemTest.java
new file mode 100644 (file)
index 0000000..982fb56
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * 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.applications.manageapplications;
+
+import static com.android.settings.applications.manageapplications.AppFilterRegistry
+        .FILTER_APPS_BLOCKED;
+import static com.android.settings.applications.manageapplications.AppFilterRegistry
+        .FILTER_APPS_ENABLED;
+import static com.android.settings.applications.manageapplications.AppFilterRegistry
+        .FILTER_APPS_USAGE_ACCESS;
+import static com.google.common.truth.Truth.assertThat;
+
+import com.android.settings.R;
+import com.android.settings.TestConfig;
+import com.android.settings.applications.AppStateUsageBridge;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settingslib.applications.ApplicationsState;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class AppFilterItemTest {
+
+    @Test
+    public void equals_sameContent_true() {
+        final AppFilterItem item = AppFilterRegistry.getInstance().get(FILTER_APPS_USAGE_ACCESS);
+        final AppFilterItem item2 = new AppFilterItem(
+                AppStateUsageBridge.FILTER_APP_USAGE,
+                FILTER_APPS_USAGE_ACCESS,
+                R.string.filter_all_apps);
+
+        // Same instance, should be same
+        assertThat(item).isEqualTo(item);
+
+        // Same content, should be same
+        assertThat(item).isEqualTo(item2);
+    }
+
+    @Test
+    public void compare_sameContent_return0() {
+        final AppFilterItem item = AppFilterRegistry.getInstance().get(FILTER_APPS_USAGE_ACCESS);
+        final AppFilterItem item2 = new AppFilterItem(
+                AppStateUsageBridge.FILTER_APP_USAGE,
+                FILTER_APPS_USAGE_ACCESS,
+                R.string.filter_all_apps);
+
+        assertThat(item.compareTo(item)).isEqualTo(0);
+        assertThat(item.compareTo(item2)).isEqualTo(0);
+        assertThat(item2.compareTo(item)).isEqualTo(0);
+    }
+
+    @Test
+    public void compare_toNull_return1() {
+        final AppFilterItem item = AppFilterRegistry.getInstance().get(FILTER_APPS_USAGE_ACCESS);
+        assertThat(item.compareTo(null)).isEqualTo(1);
+    }
+
+    @Test
+    public void compare_differentFilter_returnFilterDiff() {
+        final AppFilterItem item = AppFilterRegistry.getInstance().get(FILTER_APPS_USAGE_ACCESS);
+        final AppFilterItem item2 = new AppFilterItem(
+                ApplicationsState.FILTER_ALL_ENABLED,
+                FILTER_APPS_ENABLED,
+                R.string.filter_enabled_apps);
+        assertThat(item.compareTo(item2)).isNotEqualTo(0);
+    }
+
+    @Test
+    public void hash_differentItem_differentHash() {
+        final AppFilterItem item = AppFilterRegistry.getInstance().get(FILTER_APPS_USAGE_ACCESS);
+        final AppFilterItem item2 = AppFilterRegistry.getInstance().get(FILTER_APPS_BLOCKED);
+
+        assertThat(item.hashCode()).isNotEqualTo(item2.hashCode());
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/applications/manageapplications/AppFilterRegistryTest.java b/tests/robotests/src/com/android/settings/applications/manageapplications/AppFilterRegistryTest.java
new file mode 100644 (file)
index 0000000..3fe5e67
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * 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.applications.manageapplications;
+
+import static com.android.settings.applications.manageapplications.AppFilterRegistry
+        .FILTER_APPS_ALL;
+import static com.android.settings.applications.manageapplications.AppFilterRegistry
+        .FILTER_APPS_INSTALL_SOURCES;
+import static com.android.settings.applications.manageapplications.AppFilterRegistry
+        .FILTER_APPS_POWER_WHITELIST;
+import static com.android.settings.applications.manageapplications.AppFilterRegistry
+        .FILTER_APPS_USAGE_ACCESS;
+import static com.android.settings.applications.manageapplications.AppFilterRegistry
+        .FILTER_APPS_WITH_OVERLAY;
+import static com.android.settings.applications.manageapplications.AppFilterRegistry
+        .FILTER_APPS_WRITE_SETTINGS;
+import static com.android.settings.applications.manageapplications.ManageApplications
+        .LIST_TYPE_GAMES;
+import static com.android.settings.applications.manageapplications.ManageApplications
+        .LIST_TYPE_HIGH_POWER;
+import static com.android.settings.applications.manageapplications.ManageApplications
+        .LIST_TYPE_MAIN;
+import static com.android.settings.applications.manageapplications.ManageApplications
+        .LIST_TYPE_MANAGE_SOURCES;
+import static com.android.settings.applications.manageapplications.ManageApplications
+        .LIST_TYPE_MOVIES;
+import static com.android.settings.applications.manageapplications.ManageApplications
+        .LIST_TYPE_NOTIFICATION;
+import static com.android.settings.applications.manageapplications.ManageApplications
+        .LIST_TYPE_OVERLAY;
+import static com.android.settings.applications.manageapplications.ManageApplications
+        .LIST_TYPE_PHOTOGRAPHY;
+import static com.android.settings.applications.manageapplications.ManageApplications
+        .LIST_TYPE_STORAGE;
+import static com.android.settings.applications.manageapplications.ManageApplications
+        .LIST_TYPE_USAGE_ACCESS;
+import static com.android.settings.applications.manageapplications.ManageApplications
+        .LIST_TYPE_WRITE_SETTINGS;
+import static com.google.common.truth.Truth.assertThat;
+
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class AppFilterRegistryTest {
+
+    @Test
+    public void getDefaultType_shouldMatchForAllListType() {
+        final AppFilterRegistry registry = AppFilterRegistry.getInstance();
+        assertThat(registry.getDefaultFilterType(LIST_TYPE_USAGE_ACCESS))
+                .isEqualTo(FILTER_APPS_USAGE_ACCESS);
+        assertThat(registry.getDefaultFilterType(LIST_TYPE_HIGH_POWER))
+                .isEqualTo(FILTER_APPS_POWER_WHITELIST);
+        assertThat(registry.getDefaultFilterType(LIST_TYPE_OVERLAY)).isEqualTo(
+                FILTER_APPS_WITH_OVERLAY);
+        assertThat(registry.getDefaultFilterType(LIST_TYPE_WRITE_SETTINGS)).isEqualTo(
+                FILTER_APPS_WRITE_SETTINGS);
+        assertThat(registry.getDefaultFilterType(LIST_TYPE_MANAGE_SOURCES)).isEqualTo(
+                FILTER_APPS_INSTALL_SOURCES);
+
+        assertThat(registry.getDefaultFilterType(LIST_TYPE_MAIN))
+                .isEqualTo(FILTER_APPS_ALL);
+        assertThat(registry.getDefaultFilterType(LIST_TYPE_NOTIFICATION))
+                .isEqualTo(FILTER_APPS_ALL);
+        assertThat(registry.getDefaultFilterType(LIST_TYPE_STORAGE)).isEqualTo(FILTER_APPS_ALL);
+
+        assertThat(registry.getDefaultFilterType(LIST_TYPE_GAMES)).isEqualTo(FILTER_APPS_ALL);
+        assertThat(registry.getDefaultFilterType(LIST_TYPE_MOVIES)).isEqualTo(FILTER_APPS_ALL);
+        assertThat(registry.getDefaultFilterType(LIST_TYPE_PHOTOGRAPHY)).isEqualTo(FILTER_APPS_ALL);
+    }
+}
+
index 5f3c992..9afaf1f 100644 (file)
@@ -16,6 +16,8 @@
 
 package com.android.settings.applications.manageapplications;
 
+import static com.android.settings.applications.manageapplications.AppFilterRegistry
+        .FILTER_APPS_ALL;
 import static com.google.common.truth.Truth.assertThat;
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyInt;
@@ -116,7 +118,8 @@ public class ManageApplicationsTest {
         ManageApplications fragment = mock(ManageApplications.class);
         when(fragment.getActivity()).thenReturn(mock(Activity.class));
         final ManageApplications.ApplicationsAdapter adapter =
-                new ManageApplications.ApplicationsAdapter(mState, fragment, 0);
+                new ManageApplications.ApplicationsAdapter(mState, fragment,
+                        AppFilterRegistry.getInstance().get(FILTER_APPS_ALL));
 
         adapter.updateDisableView(view, info);
 
@@ -169,7 +172,8 @@ public class ManageApplicationsTest {
         when(fragment.getActivity()).thenReturn(mock(Activity.class));
         final Handler handler = mock(Handler.class);
         final ManageApplications.ApplicationsAdapter adapter =
-            spy(new ManageApplications.ApplicationsAdapter(mState, fragment, 0));
+            spy(new ManageApplications.ApplicationsAdapter(mState, fragment,
+                    AppFilterRegistry.getInstance().get(FILTER_APPS_ALL)));
         final LoadingViewController loadingViewController =
                 mock(LoadingViewController.class);
         ReflectionHelpers.setField(adapter, "mLoadingViewController", loadingViewController);
@@ -195,7 +199,8 @@ public class ManageApplicationsTest {
 
         final Handler handler = mock(Handler.class);
         final ManageApplications.ApplicationsAdapter adapter =
-            spy(new ManageApplications.ApplicationsAdapter(mState, fragment, 0));
+            spy(new ManageApplications.ApplicationsAdapter(mState, fragment,
+                    AppFilterRegistry.getInstance().get(FILTER_APPS_ALL)));
         final LoadingViewController loadingViewController =
                 mock(LoadingViewController.class);
         ReflectionHelpers.setField(adapter, "mLoadingViewController", loadingViewController);
@@ -223,12 +228,14 @@ public class ManageApplicationsTest {
         when(fragment.getActivity()).thenReturn(mock(Activity.class));
         final Handler handler = mock(Handler.class);
         final ManageApplications.ApplicationsAdapter adapter =
-            spy(new ManageApplications.ApplicationsAdapter(mState, fragment, 0));
+            spy(new ManageApplications.ApplicationsAdapter(mState, fragment,
+                    AppFilterRegistry.getInstance().get(FILTER_APPS_ALL)));
         final LoadingViewController loadingViewController =
                 mock(LoadingViewController.class);
         ReflectionHelpers.setField(adapter, "mLoadingViewController", loadingViewController);
         ReflectionHelpers.setField(adapter, "mFgHandler", handler);
-        ReflectionHelpers.setField(adapter, "mFilterMode", -1);
+        ReflectionHelpers.setField(adapter, "mAppFilter",
+                AppFilterRegistry.getInstance().get(FILTER_APPS_ALL));
 
         // app loading not yet completed
         ReflectionHelpers.setField(adapter, "mHasReceivedLoadEntries", false);