From 6f6e9563b07b760748665709dc362faf17047a48 Mon Sep 17 00:00:00 2001 From: Fan Zhang Date: Mon, 18 Jun 2018 11:30:00 -0700 Subject: [PATCH] Remove old suggestion code. Change-Id: I2ab9b32ea7622228b0d61b3a16f0695ab04597d7 Fixes: 110361022 Test: robotests --- .../android/settingslib/drawer/TileUtils.java | 23 +- .../suggestions/SuggestionCategory.java | 25 - .../suggestions/SuggestionList.java | 85 --- .../suggestions/SuggestionParser.java | 498 ------------------ .../robotests/res/xml/suggestion_ordering.xml | 31 -- .../settingslib/drawer/TileUtilsTest.java | 136 ----- .../suggestions/SuggestionParserTest.java | 200 ------- 7 files changed, 1 insertion(+), 997 deletions(-) delete mode 100644 packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionCategory.java delete mode 100644 packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionList.java delete mode 100644 packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionParser.java delete mode 100644 packages/SettingsLib/tests/robotests/res/xml/suggestion_ordering.xml delete mode 100644 packages/SettingsLib/tests/robotests/src/com/android/settingslib/suggestions/SuggestionParserTest.java diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java b/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java index 0f0e4e57886c8..3549abc493400 100644 --- a/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java +++ b/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java @@ -34,7 +34,6 @@ import android.provider.Settings.Global; import android.text.TextUtils; import android.util.Log; import android.util.Pair; -import android.widget.RemoteViews; import java.util.ArrayList; import java.util.Collections; @@ -96,11 +95,7 @@ public class TileUtils { /** * The key used to get the category from metadata of activities of action * {@link #EXTRA_SETTINGS_ACTION} - * The value must be one of: - *
  • com.android.settings.category.wireless
  • - *
  • com.android.settings.category.device
  • - *
  • com.android.settings.category.personal
  • - *
  • com.android.settings.category.system
  • + * The value must be from {@link CategoryKey}. */ private static final String EXTRA_CATEGORY_KEY = "com.android.settings.category"; @@ -171,17 +166,6 @@ public class TileUtils { public static final String META_DATA_PREFERENCE_SUMMARY_URI = "com.android.settings.summary_uri"; - /** - * Name of the meta-data item that should be set in the AndroidManifest.xml to specify the - * custom view which should be displayed for the preference. The custom view will be inflated - * as a remote view. - * - * This also can be used with {@link #META_DATA_PREFERENCE_SUMMARY_URI}, by setting the id - * of the summary TextView to '@android:id/summary'. - */ - public static final String META_DATA_PREFERENCE_CUSTOM_VIEW = - "com.android.settings.custom_view"; - public static final String SETTING_PKG = "com.android.settings"; /** @@ -442,11 +426,6 @@ public class TileUtils { keyHint = metaData.getString(META_DATA_PREFERENCE_KEYHINT); } } - if (metaData.containsKey(META_DATA_PREFERENCE_CUSTOM_VIEW)) { - int layoutId = metaData.getInt(META_DATA_PREFERENCE_CUSTOM_VIEW); - tile.remoteViews = new RemoteViews(applicationInfo.packageName, layoutId); - updateSummaryAndTitle(context, providerMap, tile); - } } } catch (PackageManager.NameNotFoundException | Resources.NotFoundException e) { if (DEBUG) Log.d(LOG_TAG, "Couldn't find info", e); diff --git a/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionCategory.java b/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionCategory.java deleted file mode 100644 index 19e556ad55bbf..0000000000000 --- a/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionCategory.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * 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; -} diff --git a/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionList.java b/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionList.java deleted file mode 100644 index a89092040e717..0000000000000 --- a/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionList.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * 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.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> mSuggestions; - - // A flatten list of all suggestions. - private List mSuggestionList; - - public SuggestionList() { - mSuggestions = new ArrayMap<>(); - } - - public void addSuggestions(SuggestionCategory category, List suggestions) { - mSuggestions.put(category, suggestions); - } - - public List getSuggestions() { - if (mSuggestionList != null) { - return mSuggestionList; - } - mSuggestionList = new ArrayList<>(); - for (List 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; - } - - /** - * Filter suggestions list so they are all unique. - */ - private void dedupeSuggestions(List suggestions) { - final Set 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); - } - } - } -} diff --git a/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionParser.java b/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionParser.java deleted file mode 100644 index 8705c9846a6f8..0000000000000 --- a/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionParser.java +++ /dev/null @@ -1,498 +0,0 @@ -/* - * 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.Manifest; -import android.accounts.Account; -import android.accounts.AccountManager; -import android.annotation.RequiresPermission; -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; -import android.content.pm.PackageManager; -import android.content.pm.UserInfo; -import android.content.res.Resources; -import android.net.ConnectivityManager; -import android.net.NetworkInfo; -import android.os.UserHandle; -import android.os.UserManager; -import android.provider.Settings; -import androidx.annotation.VisibleForTesting; -import android.text.TextUtils; -import android.text.format.DateUtils; -import android.util.ArrayMap; -import android.util.AttributeSet; -import android.util.Log; -import android.util.Pair; -import android.util.Xml; -import android.view.InflateException; - -import com.android.settingslib.drawer.Tile; -import com.android.settingslib.drawer.TileUtils; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -public class SuggestionParser { - - private static final String TAG = "SuggestionParser"; - - // If defined, only returns this suggestion if the feature is supported. - public static final String META_DATA_REQUIRE_FEATURE = "com.android.settings.require_feature"; - - // If defined, only display this optional step if an account of that type exists. - private static final String META_DATA_REQUIRE_ACCOUNT = "com.android.settings.require_account"; - - // If defined and not true, do not should optional step. - private static final String META_DATA_IS_SUPPORTED = "com.android.settings.is_supported"; - - // If defined, only display this optional step if the current user is of that type. - private static final String META_DATA_REQUIRE_USER_TYPE = - "com.android.settings.require_user_type"; - - // If defined, only display this optional step if a connection is available. - private static final String META_DATA_IS_CONNECTION_REQUIRED = - "com.android.settings.require_connection"; - - // The valid values that setup wizard recognizes for differentiating user types. - private static final String META_DATA_PRIMARY_USER_TYPE_VALUE = "primary"; - private static final String META_DATA_ADMIN_USER_TYPE_VALUE = "admin"; - private static final String META_DATA_GUEST_USER_TYPE_VALUE = "guest"; - private static final String META_DATA_RESTRICTED_USER_TYPE_VALUE = "restricted"; - - /** - * Allows suggestions to appear after a certain number of days, and to re-appear if dismissed. - * For instance: - * 0,10 - * Will appear immediately, but if the user removes it, it will come back after 10 days. - * - * Another example: - * 10,30 - * Will only show up after 10 days, and then again after 30. - */ - public static final String META_DATA_DISMISS_CONTROL = "com.android.settings.dismiss"; - - // Shared prefs keys for storing dismissed state. - // Index into current dismissed state. - public static final String SETUP_TIME = "_setup_time"; - private static final String IS_DISMISSED = "_is_dismissed"; - - // Default dismiss control for smart suggestions. - private static final String DEFAULT_SMART_DISMISS_CONTROL = "0"; - - private final Context mContext; - private final List mSuggestionList; - private final ArrayMap, Tile> mAddCache = new ArrayMap<>(); - private final SharedPreferences mSharedPrefs; - private final String mDefaultDismissControl; - - public SuggestionParser(Context context, SharedPreferences sharedPrefs, int orderXml, - String defaultDismissControl) { - this( - context, - sharedPrefs, - (List) new SuggestionOrderInflater(context).parse(orderXml), - defaultDismissControl); - } - - public SuggestionParser(Context context, SharedPreferences sharedPrefs, int orderXml) { - this(context, sharedPrefs, orderXml, DEFAULT_SMART_DISMISS_CONTROL); - } - - @VisibleForTesting - public SuggestionParser( - Context context, - SharedPreferences sharedPrefs, - List suggestionList, - String defaultDismissControl) { - mContext = context; - mSuggestionList = suggestionList; - mSharedPrefs = sharedPrefs; - mDefaultDismissControl = defaultDismissControl; - } - - 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); - if (category.exclusive && !isExclusiveCategoryExpired(category)) { - // If suggestions from an exclusive category are present, parsing is stopped - // and only suggestions from that category are displayed. Note that subsequent - // exclusive categories are also ignored. - final List exclusiveSuggestions = new ArrayList<>(); - - // Read suggestion and force isSmartSuggestion to be false so the rule defined - // from each suggestion itself is used. - readSuggestions(category, exclusiveSuggestions, false /* isSmartSuggestion */); - if (!exclusiveSuggestions.isEmpty()) { - 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 suggestions = new ArrayList<>(); - readSuggestions(category, suggestions, isSmartSuggestionEnabled); - suggestionList.addSuggestions(category, suggestions); - } - } - return suggestionList; - } - - /** - * Dismisses a suggestion, returns true if the suggestion has no more dismisses left and should - * be disabled. - */ - public boolean dismissSuggestion(Tile suggestion) { - final String keyBase = suggestion.intent.getComponent().flattenToShortString(); - mSharedPrefs.edit() - .putBoolean(keyBase + IS_DISMISSED, true) - .commit(); - return true; - } - - @VisibleForTesting - public void filterSuggestions( - List suggestions, int countBefore, boolean isSmartSuggestionEnabled) { - for (int i = countBefore; i < suggestions.size(); i++) { - if (!isAvailable(suggestions.get(i)) || - !isSupported(suggestions.get(i)) || - !satisifesRequiredUserType(suggestions.get(i)) || - !satisfiesRequiredAccount(suggestions.get(i)) || - !satisfiesConnectivity(suggestions.get(i)) || - isDismissed(suggestions.get(i), isSmartSuggestionEnabled)) { - suggestions.remove(i--); - } - } - } - - @VisibleForTesting - void readSuggestions( - SuggestionCategory category, List suggestions, boolean isSmartSuggestionEnabled) { - int countBefore = suggestions.size(); - Intent intent = new Intent(Intent.ACTION_MAIN); - intent.addCategory(category.category); - if (category.pkg != null) { - intent.setPackage(category.pkg); - } - TileUtils.getTilesForIntent(mContext, new UserHandle(UserHandle.myUserId()), intent, - mAddCache, null, suggestions, true, false, false, true /* shouldUpdateTiles */); - filterSuggestions(suggestions, countBefore, isSmartSuggestionEnabled); - if (!category.multiple && suggestions.size() > (countBefore + 1)) { - // If there are too many, remove them all and only re-add the one with the highest - // priority. - Tile item = suggestions.remove(suggestions.size() - 1); - while (suggestions.size() > countBefore) { - Tile last = suggestions.remove(suggestions.size() - 1); - if (last.priority > item.priority) { - item = last; - } - } - // If category is marked as done, do not add any item. - if (!isCategoryDone(category.category)) { - suggestions.add(item); - } - } - } - - private boolean isAvailable(Tile suggestion) { - final String featuresRequired = suggestion.metaData.getString(META_DATA_REQUIRE_FEATURE); - if (featuresRequired != null) { - for (String feature : featuresRequired.split(",")) { - if (TextUtils.isEmpty(feature)) { - Log.w(TAG, "Found empty substring when parsing required features: " - + featuresRequired); - } else if (!mContext.getPackageManager().hasSystemFeature(feature)) { - Log.i(TAG, suggestion.title + " requires unavailable feature " + feature); - return false; - } - } - } - return true; - } - - @RequiresPermission(Manifest.permission.MANAGE_USERS) - private boolean satisifesRequiredUserType(Tile suggestion) { - final String requiredUser = suggestion.metaData.getString(META_DATA_REQUIRE_USER_TYPE); - if (requiredUser != null) { - final UserManager userManager = mContext.getSystemService(UserManager.class); - UserInfo userInfo = userManager.getUserInfo(UserHandle.myUserId()); - for (String userType : requiredUser.split("\\|")) { - final boolean primaryUserCondtionMet = userInfo.isPrimary() - && META_DATA_PRIMARY_USER_TYPE_VALUE.equals(userType); - final boolean adminUserConditionMet = userInfo.isAdmin() - && META_DATA_ADMIN_USER_TYPE_VALUE.equals(userType); - final boolean guestUserCondtionMet = userInfo.isGuest() - && META_DATA_GUEST_USER_TYPE_VALUE.equals(userType); - final boolean restrictedUserCondtionMet = userInfo.isRestricted() - && META_DATA_RESTRICTED_USER_TYPE_VALUE.equals(userType); - if (primaryUserCondtionMet || adminUserConditionMet || guestUserCondtionMet - || restrictedUserCondtionMet) { - return true; - } - } - Log.i(TAG, suggestion.title + " requires user type " + requiredUser); - return false; - } - return true; - } - - public boolean satisfiesRequiredAccount(Tile suggestion) { - final String requiredAccountType = suggestion.metaData.getString(META_DATA_REQUIRE_ACCOUNT); - if (requiredAccountType == null) { - return true; - } - AccountManager accountManager = mContext.getSystemService(AccountManager.class); - Account[] accounts = accountManager.getAccountsByType(requiredAccountType); - boolean satisfiesRequiredAccount = accounts.length > 0; - if (!satisfiesRequiredAccount) { - Log.i(TAG, suggestion.title + " requires unavailable account type " - + requiredAccountType); - } - return satisfiesRequiredAccount; - } - - public boolean isSupported(Tile suggestion) { - final int isSupportedResource = suggestion.metaData.getInt(META_DATA_IS_SUPPORTED); - try { - if (suggestion.intent == null) { - return false; - } - final Resources res = mContext.getPackageManager().getResourcesForActivity( - suggestion.intent.getComponent()); - boolean isSupported = - isSupportedResource != 0 ? res.getBoolean(isSupportedResource) : true; - if (!isSupported) { - Log.i(TAG, suggestion.title + " requires unsupported resource " - + isSupportedResource); - } - return isSupported; - } catch (PackageManager.NameNotFoundException e) { - Log.w(TAG, "Cannot find resources for " + suggestion.intent.getComponent()); - return false; - } catch (Resources.NotFoundException e) { - Log.w(TAG, "Cannot find resources for " + suggestion.intent.getComponent(), e); - return false; - } - } - - private boolean satisfiesConnectivity(Tile suggestion) { - final boolean isConnectionRequired = - suggestion.metaData.getBoolean(META_DATA_IS_CONNECTION_REQUIRED); - if (!isConnectionRequired) { - return true; - } - ConnectivityManager cm = - (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE); - NetworkInfo netInfo = cm.getActiveNetworkInfo(); - boolean satisfiesConnectivity = netInfo != null && netInfo.isConnectedOrConnecting(); - if (!satisfiesConnectivity) { - Log.i(TAG, suggestion.title + " is missing required connection."); - } - return satisfiesConnectivity; - } - - public boolean isCategoryDone(String category) { - String name = Settings.Secure.COMPLETED_CATEGORY_PREFIX + category; - return Settings.Secure.getInt(mContext.getContentResolver(), name, 0) != 0; - } - - public void markCategoryDone(String category) { - String name = Settings.Secure.COMPLETED_CATEGORY_PREFIX + category; - Settings.Secure.putInt(mContext.getContentResolver(), name, 1); - } - - /** - * Whether or not the category's exclusiveness has expired. - */ - private boolean isExclusiveCategoryExpired(SuggestionCategory category) { - final String keySetupTime = category.category + SETUP_TIME; - final long currentTime = System.currentTimeMillis(); - if (!mSharedPrefs.contains(keySetupTime)) { - mSharedPrefs.edit() - .putLong(keySetupTime, currentTime) - .commit(); - } - if (category.exclusiveExpireDaysInMillis < 0) { - // negative means never expires - return false; - } - final long setupTime = mSharedPrefs.getLong(keySetupTime, 0); - final long elapsedTime = currentTime - setupTime; - Log.d(TAG, "Day " + elapsedTime / DateUtils.DAY_IN_MILLIS + " for " + category.category); - return elapsedTime > category.exclusiveExpireDaysInMillis; - } - - @VisibleForTesting - boolean isDismissed(Tile suggestion, boolean isSmartSuggestionEnabled) { - String dismissControl = getDismissControl(suggestion, isSmartSuggestionEnabled); - String keyBase = suggestion.intent.getComponent().flattenToShortString(); - if (!mSharedPrefs.contains(keyBase + SETUP_TIME)) { - mSharedPrefs.edit() - .putLong(keyBase + SETUP_TIME, System.currentTimeMillis()) - .commit(); - } - // Check if it's already manually dismissed - final boolean isDismissed = mSharedPrefs.getBoolean(keyBase + IS_DISMISSED, false); - if (isDismissed) { - return true; - } - if (dismissControl == null) { - return false; - } - // Parse when suggestion should first appear. return true to artificially hide suggestion - // before then. - int firstAppearDay = parseDismissString(dismissControl); - long firstAppearDayInMs = getEndTime(mSharedPrefs.getLong(keyBase + SETUP_TIME, 0), - firstAppearDay); - if (System.currentTimeMillis() >= firstAppearDayInMs) { - // Dismiss timeout has passed, undismiss it. - mSharedPrefs.edit() - .putBoolean(keyBase + IS_DISMISSED, false) - .commit(); - return false; - } - return true; - } - - private long getEndTime(long startTime, int daysDelay) { - long days = daysDelay * DateUtils.DAY_IN_MILLIS; - return startTime + days; - } - - /** - * Parse the first int from a string formatted as "0,1,2..." - * The value means suggestion should first appear on Day X. - */ - private int parseDismissString(String dismissControl) { - final String[] dismissStrs = dismissControl.split(","); - return Integer.parseInt(dismissStrs[0]); - } - - private String getDismissControl(Tile suggestion, boolean isSmartSuggestionEnabled) { - if (isSmartSuggestionEnabled) { - return mDefaultDismissControl; - } else { - return suggestion.metaData.getString(META_DATA_DISMISS_CONTROL); - } - } - - private static class SuggestionOrderInflater { - private static final String TAG_LIST = "optional-steps"; - private static final String TAG_ITEM = "step"; - - private static final String ATTR_CATEGORY = "category"; - private static final String ATTR_PACKAGE = "package"; - private static final String ATTR_MULTIPLE = "multiple"; - private static final String ATTR_EXCLUSIVE = "exclusive"; - private static final String ATTR_EXCLUSIVE_EXPIRE_DAYS = "exclusiveExpireDays"; - - private final Context mContext; - - public SuggestionOrderInflater(Context context) { - mContext = context; - } - - public Object parse(int resource) { - XmlPullParser parser = mContext.getResources().getXml(resource); - final AttributeSet attrs = Xml.asAttributeSet(parser); - try { - // Look for the root node. - int type; - do { - type = parser.next(); - } while (type != XmlPullParser.START_TAG && type != XmlPullParser.END_DOCUMENT); - - if (type != XmlPullParser.START_TAG) { - throw new InflateException(parser.getPositionDescription() - + ": No start tag found!"); - } - - // Temp is the root that was found in the xml - Object xmlRoot = onCreateItem(parser.getName(), attrs); - - // Inflate all children under temp - rParse(parser, xmlRoot, attrs); - return xmlRoot; - } catch (XmlPullParserException | IOException e) { - Log.w(TAG, "Problem parser resource " + resource, e); - return null; - } - } - - /** - * Recursive method used to descend down the xml hierarchy and instantiate - * items, instantiate their children. - */ - private void rParse(XmlPullParser parser, Object parent, final AttributeSet attrs) - throws XmlPullParserException, IOException { - final int depth = parser.getDepth(); - - int type; - while (((type = parser.next()) != XmlPullParser.END_TAG || - parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) { - if (type != XmlPullParser.START_TAG) { - continue; - } - - final String name = parser.getName(); - - Object item = onCreateItem(name, attrs); - onAddChildItem(parent, item); - rParse(parser, item, attrs); - } - } - - protected void onAddChildItem(Object parent, Object child) { - if (parent instanceof List && child instanceof SuggestionCategory) { - ((List) parent).add((SuggestionCategory) child); - } else { - throw new IllegalArgumentException("Parent was not a list"); - } - } - - protected Object onCreateItem(String name, AttributeSet attrs) { - if (name.equals(TAG_LIST)) { - return new ArrayList(); - } else if (name.equals(TAG_ITEM)) { - SuggestionCategory category = new SuggestionCategory(); - category.category = attrs.getAttributeValue(null, ATTR_CATEGORY); - category.pkg = attrs.getAttributeValue(null, ATTR_PACKAGE); - String multiple = attrs.getAttributeValue(null, ATTR_MULTIPLE); - category.multiple = !TextUtils.isEmpty(multiple) && Boolean.parseBoolean(multiple); - String exclusive = attrs.getAttributeValue(null, ATTR_EXCLUSIVE); - category.exclusive = - !TextUtils.isEmpty(exclusive) && Boolean.parseBoolean(exclusive); - String expireDaysAttr = attrs.getAttributeValue(null, - ATTR_EXCLUSIVE_EXPIRE_DAYS); - long expireDays = !TextUtils.isEmpty(expireDaysAttr) - ? Integer.parseInt(expireDaysAttr) - : -1; - category.exclusiveExpireDaysInMillis = DateUtils.DAY_IN_MILLIS * expireDays; - return category; - } else { - throw new IllegalArgumentException("Unknown item " + name); - } - } - } -} - diff --git a/packages/SettingsLib/tests/robotests/res/xml/suggestion_ordering.xml b/packages/SettingsLib/tests/robotests/res/xml/suggestion_ordering.xml deleted file mode 100644 index f02ac15fbd193..0000000000000 --- a/packages/SettingsLib/tests/robotests/res/xml/suggestion_ordering.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java index fc1b22385b49f..6e66805795b0f 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java @@ -28,7 +28,6 @@ import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.robolectric.RuntimeEnvironment.application; -import static org.robolectric.shadow.api.Shadow.extract; import android.app.ActivityManager; import android.content.ContentResolver; @@ -52,9 +51,6 @@ import android.util.ArrayMap; import android.util.Pair; import android.widget.RemoteViews; -import com.android.settingslib.R; -import com.android.settingslib.suggestions.SuggestionParser; - import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -67,7 +63,6 @@ import org.robolectric.annotation.Implementation; import org.robolectric.annotation.Implements; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.Map; @@ -163,35 +158,6 @@ public class TileUtilsTest { assertThat(outTiles.isEmpty()).isTrue(); } - @Test - public void getTilesForIntent_shouldSkipFilteredApps() { - Intent intent = new Intent(); - Map, Tile> addedCache = new ArrayMap<>(); - List outTiles = new ArrayList<>(); - List info = new ArrayList<>(); - ResolveInfo resolveInfo = newInfo(true, null /* category */, null, URI_GET_ICON, - URI_GET_SUMMARY); - addMetadataToInfo(resolveInfo, "com.android.settings.require_account", "com.google"); - addMetadataToInfo(resolveInfo, "com.android.settings.require_connection", "true"); - info.add(resolveInfo); - - when(mPackageManager.queryIntentActivitiesAsUser(eq(intent), anyInt(), anyInt())) - .thenReturn(info); - - TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache, - null /* defaultCategory */, outTiles, false /* usePriority */, - false /* checkCategory */, true /* forceTintExternalIcon */); - - assertThat(outTiles.size()).isEqualTo(1); - SuggestionParser parser = new SuggestionParser( - mContext, - null, - Collections.emptyList(), - "0,10"); - parser.filterSuggestions(outTiles, 0, false); - assertThat(outTiles.size()).isEqualTo(0); - } - @Test public void getCategories_shouldHandleExtraIntentAction() { final String testCategory = "category1"; @@ -392,108 +358,6 @@ public class TileUtilsTest { assertThat(outTiles.size()).isEqualTo(1); } - @Test - public void getTilesForIntent_shouldShowRemoteViewIfSpecified() { - Intent intent = new Intent(); - Map, Tile> addedCache = new ArrayMap<>(); - List outTiles = new ArrayList<>(); - List info = new ArrayList<>(); - ResolveInfo resolveInfo = newInfo(true, null /* category */); - resolveInfo.activityInfo.metaData.putInt("com.android.settings.custom_view", - R.layout.user_preference); - info.add(resolveInfo); - - when(mPackageManager.queryIntentActivitiesAsUser(eq(intent), anyInt(), anyInt())) - .thenReturn(info); - - TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache, - null /* defaultCategory */, outTiles, false /* usePriority */, - false /* checkCategory */, true /* forceTintExternalIcon */); - - assertThat(outTiles.size()).isEqualTo(1); - Tile tile = outTiles.get(0); - assertThat(tile.remoteViews).isNotNull(); - assertThat(tile.remoteViews.getLayoutId()).isEqualTo(R.layout.user_preference); - } - - @Test - public void getTilesForIntent_summaryUriSpecified_shouldOverrideRemoteViewSummary() - throws RemoteException { - Intent intent = new Intent(); - Map, Tile> addedCache = new ArrayMap<>(); - List outTiles = new ArrayList<>(); - List info = new ArrayList<>(); - ResolveInfo resolveInfo = newInfo(true, null /* category */, null, - null, URI_GET_SUMMARY); - resolveInfo.activityInfo.metaData.putInt("com.android.settings.custom_view", - R.layout.user_preference); - info.add(resolveInfo); - - when(mPackageManager.queryIntentActivitiesAsUser(eq(intent), anyInt(), anyInt())) - .thenReturn(info); - - // Mock the content provider interaction. - Bundle bundle = new Bundle(); - bundle.putString(TileUtils.META_DATA_PREFERENCE_SUMMARY, "new summary text"); - when(mIContentProvider.call(anyString(), - eq(TileUtils.getMethodFromUri(Uri.parse(URI_GET_SUMMARY))), eq(URI_GET_SUMMARY), - any())).thenReturn(bundle); - when(mContentResolver.acquireUnstableProvider(anyString())) - .thenReturn(mIContentProvider); - when(mContentResolver.acquireUnstableProvider(any(Uri.class))) - .thenReturn(mIContentProvider); - - TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache, - null /* defaultCategory */, outTiles, false /* usePriority */, - false /* checkCategory */, true /* forceTintExternalIcon */); - - assertThat(outTiles.size()).isEqualTo(1); - Tile tile = outTiles.get(0); - assertThat(tile.remoteViews).isNotNull(); - assertThat(tile.remoteViews.getLayoutId()).isEqualTo(R.layout.user_preference); - // Make sure the summary TextView got a new text string. - TileUtilsShadowRemoteViews shadowRemoteViews = extract(tile.remoteViews); - assertThat(shadowRemoteViews.overrideViewId).isEqualTo(android.R.id.summary); - assertThat(shadowRemoteViews.overrideText).isEqualTo("new summary text"); - } - - @Test - public void getTilesForIntent_providerUnavailable_shouldNotOverrideRemoteViewSummary() - throws RemoteException { - Intent intent = new Intent(); - Map, Tile> addedCache = new ArrayMap<>(); - List outTiles = new ArrayList<>(); - List info = new ArrayList<>(); - ResolveInfo resolveInfo = newInfo(true, null /* category */, null, - null, URI_GET_SUMMARY); - resolveInfo.activityInfo.metaData.putInt("com.android.settings.custom_view", - R.layout.user_preference); - info.add(resolveInfo); - - when(mPackageManager.queryIntentActivitiesAsUser(eq(intent), anyInt(), anyInt())) - .thenReturn(info); - - // Mock the content provider interaction. - Bundle bundle = new Bundle(); - bundle.putString(TileUtils.META_DATA_PREFERENCE_SUMMARY, "new summary text"); - when(mIContentProvider.call(anyString(), - eq(TileUtils.getMethodFromUri(Uri.parse(URI_GET_SUMMARY))), eq(URI_GET_SUMMARY), - any())).thenReturn(bundle); - - TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache, - null /* defaultCategory */, outTiles, false /* usePriority */, - false /* checkCategory */, true /* forceTintExternalIcon */); - - assertThat(outTiles.size()).isEqualTo(1); - Tile tile = outTiles.get(0); - assertThat(tile.remoteViews).isNotNull(); - assertThat(tile.remoteViews.getLayoutId()).isEqualTo(R.layout.user_preference); - // Make sure the summary TextView didn't get any text view updates. - TileUtilsShadowRemoteViews shadowRemoteViews = extract(tile.remoteViews); - assertThat(shadowRemoteViews.overrideViewId).isNull(); - assertThat(shadowRemoteViews.overrideText).isNull(); - } - public static ResolveInfo newInfo(boolean systemApp, String category) { return newInfo(systemApp, category, null); } diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/suggestions/SuggestionParserTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/suggestions/SuggestionParserTest.java deleted file mode 100644 index d05bcfd316858..0000000000000 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/suggestions/SuggestionParserTest.java +++ /dev/null @@ -1,200 +0,0 @@ -/* - * 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 static com.google.common.truth.Truth.assertThat; -import static org.robolectric.RuntimeEnvironment.application; -import static org.robolectric.shadow.api.Shadow.extract; - -import android.content.ComponentName; -import android.content.Intent; -import android.content.SharedPreferences; -import android.content.pm.ResolveInfo; -import android.os.Bundle; -import android.preference.PreferenceManager; - -import com.android.settingslib.SettingsLibRobolectricTestRunner; -import com.android.settingslib.drawer.Tile; -import com.android.settingslib.drawer.TileUtilsTest; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.robolectric.shadows.ShadowPackageManager; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -@RunWith(SettingsLibRobolectricTestRunner.class) -public class SuggestionParserTest { - - private ShadowPackageManager mPackageManager; - private SuggestionParser mSuggestionParser; - private SuggestionCategory mMultipleCategory; - private SuggestionCategory mExclusiveCategory; - private SuggestionCategory mExpiredExclusiveCategory; - private List mSuggestionsBeforeDismiss; - private List mSuggestionsAfterDismiss; - private SharedPreferences mPrefs; - private Tile mSuggestion; - - @Before - public void setUp() { - mPackageManager = extract(application.getPackageManager()); - mPrefs = PreferenceManager.getDefaultSharedPreferences(application); - mSuggestion = new Tile(); - mSuggestion.intent = new Intent("action"); - mSuggestion.intent.setComponent(new ComponentName("pkg", "cls")); - mSuggestion.metaData = new Bundle(); - mMultipleCategory = new SuggestionCategory(); - mMultipleCategory.category = "category1"; - mMultipleCategory.multiple = true; - mExclusiveCategory = new SuggestionCategory(); - mExclusiveCategory.category = "category2"; - mExclusiveCategory.exclusive = true; - mExpiredExclusiveCategory = new SuggestionCategory(); - mExpiredExclusiveCategory.category = "category3"; - mExpiredExclusiveCategory.exclusive = true; - mExpiredExclusiveCategory.exclusiveExpireDaysInMillis = 0; - - mSuggestionParser = new SuggestionParser(application, mPrefs, - Arrays.asList(mMultipleCategory, mExclusiveCategory, mExpiredExclusiveCategory), - "0"); - - ResolveInfo info1 = TileUtilsTest.newInfo(true, null); - info1.activityInfo.packageName = "pkg"; - ResolveInfo infoDupe1 = TileUtilsTest.newInfo(true, null); - infoDupe1.activityInfo.packageName = "pkg"; - - ResolveInfo info2 = TileUtilsTest.newInfo(true, null); - info2.activityInfo.packageName = "pkg2"; - ResolveInfo info3 = TileUtilsTest.newInfo(true, null); - info3.activityInfo.packageName = "pkg3"; - ResolveInfo info4 = TileUtilsTest.newInfo(true, null); - info4.activityInfo.packageName = "pkg4"; - - Intent intent1 = new Intent(Intent.ACTION_MAIN).addCategory("category1"); - Intent intent2 = new Intent(Intent.ACTION_MAIN).addCategory("category2"); - Intent intent3 = new Intent(Intent.ACTION_MAIN).addCategory("category3"); - - mPackageManager.addResolveInfoForIntent(intent1, info1); - mPackageManager.addResolveInfoForIntent(intent1, info2); - mPackageManager.addResolveInfoForIntent(intent1, infoDupe1); - mPackageManager.addResolveInfoForIntent(intent2, info3); - mPackageManager.addResolveInfoForIntent(intent3, info4); - } - - @Test - public void dismissSuggestion_shouldDismiss() { - assertThat(mSuggestionParser.dismissSuggestion(mSuggestion)).isTrue(); - } - - @Test - public void testGetSuggestions_withoutSmartSuggestions_shouldDismiss() { - readAndDismissSuggestion(false); - mSuggestionParser.readSuggestions(mMultipleCategory, mSuggestionsAfterDismiss, false); - assertThat(mSuggestionsBeforeDismiss).hasSize(2); - assertThat(mSuggestionsAfterDismiss).hasSize(1); - assertThat(mSuggestionsBeforeDismiss.get(1)).isEqualTo(mSuggestionsAfterDismiss.get(0)); - } - - @Test - public void testGetSuggestions_withSmartSuggestions_shouldDismiss() { - readAndDismissSuggestion(true); - assertThat(mSuggestionsBeforeDismiss).hasSize(2); - assertThat(mSuggestionsAfterDismiss).hasSize(1); - } - - @Test - public void testGetSuggestion_exclusiveNotAvailable_onlyRegularCategoryAndNoDupe() { - mPackageManager.removeResolveInfosForIntent( - new Intent(Intent.ACTION_MAIN).addCategory("category2"), - "pkg3"); - mPackageManager.removeResolveInfosForIntent( - new Intent(Intent.ACTION_MAIN).addCategory("category3"), - "pkg4"); - - // If exclusive item is not available, the other categories should be shown - final SuggestionList sl = - mSuggestionParser.getSuggestions(false /* isSmartSuggestionEnabled */); - final List suggestions = sl.getSuggestions(); - assertThat(suggestions).hasSize(2); - - assertThat(suggestions.get(0).intent.getComponent().getPackageName()).isEqualTo("pkg"); - assertThat(suggestions.get(1).intent.getComponent().getPackageName()).isEqualTo("pkg2"); - } - - @Test - public void testGetSuggestion_exclusiveExpiredAvailable_shouldLoadWithRegularCategory() { - // First remove permanent exclusive - mPackageManager.removeResolveInfosForIntent( - new Intent(Intent.ACTION_MAIN).addCategory("category2"), - "pkg3"); - // Set the other exclusive to be expired. - mPrefs.edit() - .putLong(mExpiredExclusiveCategory.category + "_setup_time", - System.currentTimeMillis() - 1000) - .commit(); - - // If exclusive is expired, they should be shown together with the other categories - final SuggestionList sl = - mSuggestionParser.getSuggestions(true /* isSmartSuggestionEnabled */); - final List suggestions = sl.getSuggestions(); - - assertThat(suggestions).hasSize(3); - } - - @Test - public void testGetSuggestions_exclusive() { - final SuggestionList sl = - mSuggestionParser.getSuggestions(false /* isSmartSuggestionEnabled */); - final List suggestions = sl.getSuggestions(); - - assertThat(suggestions).hasSize(1); - } - - @Test - public void isSuggestionDismissed_dismissedSuggestion_shouldReturnTrue() { - 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); - - assertThat(mSuggestionParser.isDismissed(suggestion, true /* isSmartSuggestionEnabled */)) - .isTrue(); - } - - private void readAndDismissSuggestion(boolean isSmartSuggestionEnabled) { - mSuggestionsBeforeDismiss = new ArrayList<>(); - mSuggestionsAfterDismiss = new ArrayList<>(); - mSuggestionParser.readSuggestions( - mMultipleCategory, mSuggestionsBeforeDismiss, isSmartSuggestionEnabled); - - final Tile suggestion = mSuggestionsBeforeDismiss.get(0); - if (mSuggestionParser.dismissSuggestion(suggestion)) { - mPackageManager.removeResolveInfosForIntent( - new Intent(Intent.ACTION_MAIN).addCategory(mMultipleCategory.category), - suggestion.intent.getComponent().getPackageName()); - } - mSuggestionParser.readSuggestions( - mMultipleCategory, mSuggestionsAfterDismiss, isSmartSuggestionEnabled); - } -}