diff options
6 files changed, 310 insertions, 46 deletions
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryKey.java b/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryKey.java new file mode 100644 index 000000000000..9821fb8b18fa --- /dev/null +++ b/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryKey.java @@ -0,0 +1,34 @@ +/** + * Copyright (C) 2016 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.drawer; + +public final class CategoryKey { + + // Activities in this category shows up in Settings homepage. + public static final String CATEGORY_HOMEPAGE = "com.android.settings.category.homepage"; + + // Top level categor. + public static final String CATEGORY_NETWORK = "com.android.settings.category.wireless"; + public static final String CATEGORY_DEVICE = "com.android.settings.category.device"; + public static final String CATEGORY_APPS = "com.android.settings.category.apps"; + public static final String CATEGORY_BATTERY = "com.android.settings.category.battery"; + public static final String CATEGORY_DISPLAY = "com.android.settings.category.display"; + public static final String CATEGORY_SOUND = "com.android.settings.category.sound"; + public static final String CATEGORY_STORAGE = "com.android.settings.category.storage"; + public static final String CATEGORY_SECURITY = "com.android.settings.category.security"; + public static final String CATEGORY_ACCOUNT = "com.android.settings.category.accounts"; + public static final String CATEGORY_SYSTEM = "com.android.settings.category.system"; +} diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryManager.java b/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryManager.java new file mode 100644 index 000000000000..a8f286d774c6 --- /dev/null +++ b/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryManager.java @@ -0,0 +1,108 @@ +/** + * Copyright (C) 2016 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.drawer; + +import android.content.ComponentName; +import android.content.Context; +import android.util.ArrayMap; +import android.util.Log; +import android.util.Pair; + +import com.android.settingslib.applications.InterestingConfigChanges; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +public class CategoryManager { + + private static final String TAG = "CategoryManager"; + + private static CategoryManager sInstance; + + private final InterestingConfigChanges mInterestingConfigChanges; + + // Tile cache (key: <packageName, activityName>, value: tile) + private final Map<Pair<String, String>, Tile> mTileByComponentCache; + + // Tile cache (key: category key, value: category) + private final Map<String, DashboardCategory> mCategoryByKeyMap; + + private List<DashboardCategory> mCategories; + + public static CategoryManager get() { + if (sInstance == null) { + sInstance = new CategoryManager(); + } + return sInstance; + } + + CategoryManager() { + mInterestingConfigChanges = new InterestingConfigChanges(); + mTileByComponentCache = new ArrayMap<>(); + mCategoryByKeyMap = new ArrayMap<>(); + } + + public DashboardCategory getTilesByCategory(Context context, String categoryKey) { + tryInitCategories(context); + + final DashboardCategory category = mCategoryByKeyMap.get(categoryKey); + if (category == null) { + throw new IllegalStateException("Can't find category with key " + categoryKey); + } + return category; + } + + public List<DashboardCategory> getCategories(Context context) { + tryInitCategories(context); + return mCategories; + } + + public void reloadAllCategoriesForConfigChange(Context context) { + if (mInterestingConfigChanges.applyNewConfig(context.getResources())) { + mCategories = null; + tryInitCategories(context); + } + } + + public void updateCategoryFromBlacklist(Set<ComponentName> tileBlacklist) { + if (mCategories == null) { + Log.w(TAG, "Category is null, skipping blacklist update"); + } + for (int i = 0; i < mCategories.size(); i++) { + DashboardCategory category = mCategories.get(i); + for (int j = 0; j < category.tiles.size(); j++) { + Tile tile = category.tiles.get(j); + if (tileBlacklist.contains(tile.intent.getComponent())) { + category.tiles.remove(j--); + } + } + } + } + + private void tryInitCategories(Context context) { + if (mCategories == null) { + mTileByComponentCache.clear(); + mCategoryByKeyMap.clear(); + mCategories = TileUtils.getCategories(context, mTileByComponentCache, + false /* categoryDefinedInManifest */); + for (DashboardCategory category : mCategories) { + mCategoryByKeyMap.put(category.key, category); + } + } + } + +} diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/DashboardCategory.java b/packages/SettingsLib/src/com/android/settingslib/drawer/DashboardCategory.java index 53be0e6c116c..3fc999fb903a 100644 --- a/packages/SettingsLib/src/com/android/settingslib/drawer/DashboardCategory.java +++ b/packages/SettingsLib/src/com/android/settingslib/drawer/DashboardCategory.java @@ -16,15 +16,20 @@ package com.android.settingslib.drawer; +import android.content.ComponentName; import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; +import android.util.Log; import java.util.ArrayList; import java.util.List; public class DashboardCategory implements Parcelable { + private static final String TAG = "DashboardCategory"; + private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); + /** * Title of the category that is shown to the user. */ @@ -74,6 +79,22 @@ public class DashboardCategory implements Parcelable { return tiles.get(n); } + public boolean containsComponent(ComponentName component) { + for (Tile tile : tiles) { + if (TextUtils.equals(tile.intent.getComponent().getClassName(), + component.getClassName())) { + if (DEBUG) { + Log.d(TAG, "category " + key + "contains component" + component); + } + return true; + } + } + if (DEBUG) { + Log.d(TAG, "category " + key + " does not contain component" + component); + } + return false; + } + @Override public int describeContents() { return 0; diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java index 05585e53e2a2..50867eb28e0a 100644 --- a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java +++ b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java @@ -33,7 +33,6 @@ import android.os.UserManager; import android.provider.Settings; import android.support.annotation.VisibleForTesting; import android.support.v4.widget.DrawerLayout; -import android.text.TextUtils; import android.util.ArraySet; import android.util.Log; import android.util.Pair; @@ -64,12 +63,9 @@ public class SettingsDrawerActivity extends Activity { public static final String EXTRA_SHOW_MENU = "show_drawer_menu"; - private static List<DashboardCategory> sDashboardCategories; - private static HashMap<Pair<String, String>, Tile> sTileCache; // Serves as a temporary list of tiles to ignore until we heard back from the PM that they // are disabled. private static ArraySet<ComponentName> sTileBlacklist = new ArraySet<>(); - private static InterestingConfigChanges sConfigTracker; private final PackageReceiver mPackageReceiver = new PackageReceiver(); private final List<CategoryListener> mCategoryListeners = new ArrayList<>(); @@ -80,6 +76,15 @@ public class SettingsDrawerActivity extends Activity { private boolean mShowingMenu; private UserManager mUserManager; + // Remove below after new IA + @Deprecated + private static List<DashboardCategory> sDashboardCategories; + @Deprecated + private static HashMap<Pair<String, String>, Tile> sTileCache; + @Deprecated + private static InterestingConfigChanges sConfigTracker; + // Remove above after new IA + @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -105,7 +110,9 @@ public class SettingsDrawerActivity extends Activity { mDrawerLayout = null; return; } - getDashboardCategories(); + if (!isDashboardFeatureEnabled()) { + getDashboardCategories(); + } setActionBar(toolbar); mDrawerAdapter = new SettingsDrawerAdapter(this); ListView listView = (ListView) findViewById(R.id.left_drawer); @@ -144,7 +151,11 @@ public class SettingsDrawerActivity extends Activity { filter.addDataScheme("package"); registerReceiver(mPackageReceiver, filter); - new CategoriesUpdater().execute(); + if (isDashboardFeatureEnabled()) { + new CategoriesUpdateTask().execute(); + } else { + new CategoriesUpdater().execute(); + } } final Intent intent = getIntent(); if (intent != null) { @@ -173,23 +184,23 @@ public class SettingsDrawerActivity extends Activity { if (componentName == null) { return false; } - // Look for a tile that has the same component as incoming intent - final List<DashboardCategory> categories = getDashboardCategories(); - for (DashboardCategory category : categories) { - for (Tile tile : category.tiles) { - if (TextUtils.equals(tile.intent.getComponent().getClassName(), - componentName.getClassName())) { - if (DEBUG) { - Log.d(TAG, "intent is for top level tile: " + tile.title); - } + if (isDashboardFeatureEnabled()) { + final DashboardCategory homepageCategories = CategoryManager.get() + .getTilesByCategory(this, CategoryKey.CATEGORY_HOMEPAGE); + return homepageCategories.containsComponent(componentName); + } else { + // Look for a tile that has the same component as incoming intent + final List<DashboardCategory> categories = getDashboardCategories(); + for (DashboardCategory category : categories) { + if (category.containsComponent(componentName)) { return true; } } + if (DEBUG) { + Log.d(TAG, "Intent is not for top level settings " + intent); + } + return false; } - if (DEBUG) { - Log.d(TAG, "Intent is not for top level settings " + intent); - } - return false; } public void addCategoryListener(CategoryListener listener) { @@ -255,7 +266,11 @@ public class SettingsDrawerActivity extends Activity { return; } // TODO: Do this in the background with some loading. - mDrawerAdapter.updateCategories(); + if (isDashboardFeatureEnabled()) { + mDrawerAdapter.updateHomepageCategories(); + } else { + mDrawerAdapter.updateCategories(); + } if (mDrawerAdapter.getCount() != 0) { mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED); } else { @@ -343,13 +358,6 @@ public class SettingsDrawerActivity extends Activity { } } - public HashMap<Pair<String, String>, Tile> getTileCache() { - if (sTileCache == null) { - getDashboardCategories(); - } - return sTileCache; - } - public void onProfileTileOpen() { finish(); } @@ -368,7 +376,11 @@ public class SettingsDrawerActivity extends Activity { ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED : PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP); - new CategoriesUpdater().execute(); + if (isDashboardFeatureEnabled()) { + new CategoriesUpdateTask().execute(); + } else { + new CategoriesUpdater().execute(); + } } } @@ -376,6 +388,10 @@ public class SettingsDrawerActivity extends Activity { void onCategoriesChanged(); } + /** + * @deprecated remove after new IA + */ + @Deprecated private class CategoriesUpdater extends AsyncTask<Void, Void, List<DashboardCategory>> { @Override protected List<DashboardCategory> doInBackground(Void... params) { @@ -408,10 +424,39 @@ public class SettingsDrawerActivity extends Activity { } } + private class CategoriesUpdateTask extends AsyncTask<Void, Void, Void> { + + private final CategoryManager mCategoryManager; + + public CategoriesUpdateTask() { + mCategoryManager = CategoryManager.get(); + } + + @Override + protected Void doInBackground(Void... params) { + mCategoryManager.reloadAllCategoriesForConfigChange(SettingsDrawerActivity.this); + return null; + } + + @Override + protected void onPostExecute(Void result) { + mCategoryManager.updateCategoryFromBlacklist(sTileBlacklist); + onCategoriesChanged(); + } + } + + protected boolean isDashboardFeatureEnabled() { + return false; + } + private class PackageReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { - new CategoriesUpdater().execute(); + if (isDashboardFeatureEnabled()) { + new CategoriesUpdateTask().execute(); + } else { + new CategoriesUpdater().execute(); + } } } } diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerAdapter.java b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerAdapter.java index 1d6197a9333f..e1216a1c7e18 100644 --- a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerAdapter.java +++ b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerAdapter.java @@ -37,6 +37,10 @@ public class SettingsDrawerAdapter extends BaseAdapter { mActivity = activity; } + /** + * @deprecated Remove after new IA + */ + @Deprecated void updateCategories() { List<DashboardCategory> categories = mActivity.getDashboardCategories(); mItems.clear(); @@ -64,6 +68,27 @@ public class SettingsDrawerAdapter extends BaseAdapter { notifyDataSetChanged(); } + public void updateHomepageCategories() { + DashboardCategory category = + CategoryManager.get().getTilesByCategory(mActivity, CategoryKey.CATEGORY_HOMEPAGE); + mItems.clear(); + // Spacer. + mItems.add(null); + Item tile = new Item(); + tile.label = mActivity.getString(R.string.home); + tile.icon = Icon.createWithResource(mActivity, R.drawable.home); + mItems.add(tile); + for (int j = 0; j < category.tiles.size(); j++) { + tile = new Item(); + Tile dashboardTile = category.tiles.get(j); + tile.label = dashboardTile.title; + tile.icon = dashboardTile.icon; + tile.tile = dashboardTile; + mItems.add(tile); + } + notifyDataSetChanged(); + } + public Tile getTile(int position) { return mItems.get(position) != null ? mItems.get(position).tile : null; } diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java b/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java index e70cc29a7744..81f0e84903f7 100644 --- a/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java +++ b/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java @@ -94,6 +94,13 @@ public class TileUtils { private static final String EXTRA_CATEGORY_KEY = "com.android.settings.category"; /** + * The key used to get the category from metadata of activities of action + * {@link #EXTRA_SETTINGS_ACTION} + * The value must be one of constants defined in {@code CategoryKey}. + */ + private static final String EXTRA_IA_CATEGORY_KEY = "com.android.settings.iacategory"; + + /** * Name of the meta-data item that should be set in the AndroidManifest.xml * to specify the icon that should be displayed for the preference. */ @@ -113,8 +120,24 @@ public class TileUtils { private static final String SETTING_PKG = "com.android.settings"; + /** + * Build a list of DashboardCategory. Each category must be defined in manifest. + * eg: .Settings$DeviceSettings + * @deprecated + */ + @Deprecated + public static List<DashboardCategory> getCategories(Context context, + Map<Pair<String, String>, Tile> cache) { + return getCategories(context, cache, true /*categoryDefinedInManifest*/); + } + + /** + * Build a list of DashboardCategory. + * @param categoryDefinedInManifest If true, an dummy activity must exists in manifest to + * represent this category (eg: .Settings$DeviceSettings) + */ public static List<DashboardCategory> getCategories(Context context, - HashMap<Pair<String, String>, Tile> cache) { + Map<Pair<String, String>, Tile> cache, boolean categoryDefinedInManifest) { final long startTime = System.currentTimeMillis(); boolean setup = Global.getInt(context.getContentResolver(), Global.DEVICE_PROVISIONED, 0) != 0; @@ -134,11 +157,12 @@ public class TileUtils { getTilesForAction(context, user, EXTRA_SETTINGS_ACTION, cache, null, tiles, false); } } + HashMap<String, DashboardCategory> categoryMap = new HashMap<>(); for (Tile tile : tiles) { DashboardCategory category = categoryMap.get(tile.category); if (category == null) { - category = createCategory(context, tile.category); + category = createCategory(context, tile.category, categoryDefinedInManifest); if (category == null) { Log.w(LOG_TAG, "Couldn't find category " + tile.category); continue; @@ -157,9 +181,21 @@ public class TileUtils { return categories; } - private static DashboardCategory createCategory(Context context, String categoryKey) { + /** + * Create a new DashboardCategory from key. + * + * @param context Context to query intent + * @param categoryKey The category key + * @param categoryDefinedInManifest If true, an dummy activity must exists in manifest to + * represent this category (eg: .Settings$DeviceSettings) + */ + private static DashboardCategory createCategory(Context context, String categoryKey, + boolean categoryDefinedInManifest) { DashboardCategory category = new DashboardCategory(); category.key = categoryKey; + if (!categoryDefinedInManifest) { + return category; + } PackageManager pm = context.getPackageManager(); List<ResolveInfo> results = pm.queryIntentActivities(new Intent(categoryKey), 0); if (results.size() == 0) { @@ -204,14 +240,19 @@ public class TileUtils { ActivityInfo activityInfo = resolved.activityInfo; Bundle metaData = activityInfo.metaData; String categoryKey = defaultCategory; - if (checkCategory && ((metaData == null) || !metaData.containsKey(EXTRA_CATEGORY_KEY)) - && categoryKey == null) { + if (metaData != null && categoryKey == null) { + // categoryKey is null, try to get it from metadata. + if (metaData.containsKey(EXTRA_IA_CATEGORY_KEY)) { + categoryKey = metaData.getString(EXTRA_IA_CATEGORY_KEY); + } else if (metaData.containsKey(EXTRA_CATEGORY_KEY)) { + categoryKey = metaData.getString(EXTRA_CATEGORY_KEY); + } + } + if (checkCategory && categoryKey == null) { Log.w(LOG_TAG, "Found " + resolved.activityInfo.name + " for intent " + intent + " missing metadata " + (metaData == null ? "" : EXTRA_CATEGORY_KEY)); continue; - } else { - categoryKey = metaData.getString(EXTRA_CATEGORY_KEY); } Pair<String, String> key = new Pair<String, String>(activityInfo.packageName, activityInfo.name); @@ -238,16 +279,6 @@ public class TileUtils { } } - private static DashboardCategory getCategory(List<DashboardCategory> target, - String categoryKey) { - for (DashboardCategory category : target) { - if (categoryKey.equals(category.key)) { - return category; - } - } - return null; - } - private static boolean updateTileData(Context context, Tile tile, ActivityInfo activityInfo, ApplicationInfo applicationInfo, PackageManager pm) { if (applicationInfo.isSystemApp()) { |