1744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk/* 2744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk * Copyright (C) 2015 The Android Open Source Project 3744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk * 4f509d7e65a062957be86619b3cb894e99268c4aeJason Monk * Licensed under the Apache License, Version 2.0 (the "License"); 5f509d7e65a062957be86619b3cb894e99268c4aeJason Monk * you may not use this file except in compliance with the License. 6f509d7e65a062957be86619b3cb894e99268c4aeJason Monk * You may obtain a copy of the License at 7744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk * 8744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk * http://www.apache.org/licenses/LICENSE-2.0 9744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk * 10f509d7e65a062957be86619b3cb894e99268c4aeJason Monk * Unless required by applicable law or agreed to in writing, software 11f509d7e65a062957be86619b3cb894e99268c4aeJason Monk * distributed under the License is distributed on an "AS IS" BASIS, 12f509d7e65a062957be86619b3cb894e99268c4aeJason Monk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f509d7e65a062957be86619b3cb894e99268c4aeJason Monk * See the License for the specific language governing permissions and 14f509d7e65a062957be86619b3cb894e99268c4aeJason Monk * limitations under the License 15744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk */ 16744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monkpackage com.android.settingslib.drawer; 17744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk 180d72d20c2f2a3c5c98a73e97914e96a82b04eff8Jason Monkimport android.app.ActivityManager; 19744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monkimport android.content.Context; 20744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monkimport android.content.Intent; 21744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monkimport android.content.pm.ActivityInfo; 22e79790b26803ee338b2fdc3404344094d7f94476Jason Monkimport android.content.pm.ApplicationInfo; 23744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monkimport android.content.pm.PackageManager; 24744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monkimport android.content.pm.ResolveInfo; 25744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monkimport android.content.res.Resources; 26744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monkimport android.graphics.drawable.Icon; 27744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monkimport android.os.Bundle; 28744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monkimport android.os.UserHandle; 29744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monkimport android.os.UserManager; 30744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monkimport android.text.TextUtils; 31744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monkimport android.util.Log; 32744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monkimport android.util.Pair; 33744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk 34744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monkimport java.util.ArrayList; 35744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monkimport java.util.Collections; 36744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monkimport java.util.Comparator; 37744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monkimport java.util.HashMap; 38744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monkimport java.util.List; 39744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monkimport java.util.Map; 40744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk 41744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monkpublic class TileUtils { 42744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk 430d72d20c2f2a3c5c98a73e97914e96a82b04eff8Jason Monk private static final boolean DEBUG = false; 4493dcff01227abae7172c0da2bbb09d8f6221f296Joe Onorato private static final boolean DEBUG_TIMING = false; 45744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk 46744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk private static final String LOG_TAG = "TileUtils"; 47744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk 48744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk /** 49744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk * Settings will search for system activities of this action and add them as a top level 50744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk * settings tile using the following parameters. 51744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk * 52744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk * <p>A category must be specified in the meta-data for the activity named 53744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk * {@link #EXTRA_CATEGORY_KEY} 54744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk * 55744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk * <p>The title may be defined by meta-data named {@link #META_DATA_PREFERENCE_TITLE} 56744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk * otherwise the label for the activity will be used. 57744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk * 58744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk * <p>The icon may be defined by meta-data named {@link #META_DATA_PREFERENCE_ICON} 59744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk * otherwise the icon for the activity will be used. 60744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk * 61744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk * <p>A summary my be defined by meta-data named {@link #META_DATA_PREFERENCE_SUMMARY} 62744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk */ 63744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk private static final String EXTRA_SETTINGS_ACTION = 64744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk "com.android.settings.action.EXTRA_SETTINGS"; 65744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk 66744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk /** 67744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk * Same as #EXTRA_SETTINGS_ACTION but used for the platform Settings activities. 68744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk */ 69744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk private static final String SETTINGS_ACTION = 70744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk "com.android.settings.action.SETTINGS"; 71744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk 72744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk private static final String OPERATOR_SETTINGS = 73744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk "com.android.settings.OPERATOR_APPLICATION_SETTING"; 74744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk 75744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk private static final String OPERATOR_DEFAULT_CATEGORY = 76744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk "com.android.settings.category.wireless"; 77744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk 78744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk private static final String MANUFACTURER_SETTINGS = 79744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk "com.android.settings.MANUFACTURER_APPLICATION_SETTING"; 80744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk 81744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk private static final String MANUFACTURER_DEFAULT_CATEGORY = 82744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk "com.android.settings.category.device"; 83744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk 84744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk /** 85744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk * The key used to get the category from metadata of activities of action 86744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk * {@link #EXTRA_SETTINGS_ACTION} 87744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk * The value must be one of: 88744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk * <li>com.android.settings.category.wireless</li> 89744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk * <li>com.android.settings.category.device</li> 90744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk * <li>com.android.settings.category.personal</li> 91744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk * <li>com.android.settings.category.system</li> 92744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk */ 93744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk private static final String EXTRA_CATEGORY_KEY = "com.android.settings.category"; 94744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk 95744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk /** 96744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk * Name of the meta-data item that should be set in the AndroidManifest.xml 97744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk * to specify the icon that should be displayed for the preference. 98744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk */ 99744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk public static final String META_DATA_PREFERENCE_ICON = "com.android.settings.icon"; 100744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk 101744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk /** 102744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk * Name of the meta-data item that should be set in the AndroidManifest.xml 103744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk * to specify the title that should be displayed for the preference. 104744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk */ 105744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk public static final String META_DATA_PREFERENCE_TITLE = "com.android.settings.title"; 106744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk 107744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk /** 108744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk * Name of the meta-data item that should be set in the AndroidManifest.xml 109744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk * to specify the summary text that should be displayed for the preference. 110744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk */ 111744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk public static final String META_DATA_PREFERENCE_SUMMARY = "com.android.settings.summary"; 112744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk 113744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk private static final String SETTING_PKG = "com.android.settings"; 114744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk 115744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk public static List<DashboardCategory> getCategories(Context context, 116f509d7e65a062957be86619b3cb894e99268c4aeJason Monk HashMap<Pair<String, String>, Tile> cache) { 117e79790b26803ee338b2fdc3404344094d7f94476Jason Monk final long startTime = System.currentTimeMillis(); 118f509d7e65a062957be86619b3cb894e99268c4aeJason Monk ArrayList<Tile> tiles = new ArrayList<>(); 119744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk UserManager userManager = UserManager.get(context); 120744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk for (UserHandle user : userManager.getUserProfiles()) { 121744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk // TODO: Needs much optimization, too many PM queries going on here. 1220d72d20c2f2a3c5c98a73e97914e96a82b04eff8Jason Monk if (user.getIdentifier() == ActivityManager.getCurrentUser()) { 1230d72d20c2f2a3c5c98a73e97914e96a82b04eff8Jason Monk // Only add Settings for this user. 1240d72d20c2f2a3c5c98a73e97914e96a82b04eff8Jason Monk getTilesForAction(context, user, SETTINGS_ACTION, cache, null, tiles, true); 1250d72d20c2f2a3c5c98a73e97914e96a82b04eff8Jason Monk getTilesForAction(context, user, OPERATOR_SETTINGS, cache, 1260d72d20c2f2a3c5c98a73e97914e96a82b04eff8Jason Monk OPERATOR_DEFAULT_CATEGORY, tiles, false); 1270d72d20c2f2a3c5c98a73e97914e96a82b04eff8Jason Monk getTilesForAction(context, user, MANUFACTURER_SETTINGS, cache, 1280d72d20c2f2a3c5c98a73e97914e96a82b04eff8Jason Monk MANUFACTURER_DEFAULT_CATEGORY, tiles, false); 1290d72d20c2f2a3c5c98a73e97914e96a82b04eff8Jason Monk } 130744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk getTilesForAction(context, user, EXTRA_SETTINGS_ACTION, cache, null, tiles, false); 131744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk } 132744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk HashMap<String, DashboardCategory> categoryMap = new HashMap<>(); 133f509d7e65a062957be86619b3cb894e99268c4aeJason Monk for (Tile tile : tiles) { 134744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk DashboardCategory category = categoryMap.get(tile.category); 135744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk if (category == null) { 136744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk category = createCategory(context, tile.category); 137744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk if (category == null) { 138744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk Log.w(LOG_TAG, "Couldn't find category " + tile.category); 139744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk continue; 140744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk } 141744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk categoryMap.put(category.key, category); 142744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk } 143744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk category.addTile(tile); 144744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk } 145744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk ArrayList<DashboardCategory> categories = new ArrayList<>(categoryMap.values()); 146744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk for (DashboardCategory category : categories) { 147744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk Collections.sort(category.tiles, TILE_COMPARATOR); 148744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk } 149744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk Collections.sort(categories, CATEGORY_COMPARATOR); 150e79790b26803ee338b2fdc3404344094d7f94476Jason Monk if (DEBUG_TIMING) Log.d(LOG_TAG, "getCategories took " 151e79790b26803ee338b2fdc3404344094d7f94476Jason Monk + (System.currentTimeMillis() - startTime) + " ms"); 152744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk return categories; 153744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk } 154744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk 155744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk private static DashboardCategory createCategory(Context context, String categoryKey) { 156744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk DashboardCategory category = new DashboardCategory(); 157744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk category.key = categoryKey; 158744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk PackageManager pm = context.getPackageManager(); 159744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk List<ResolveInfo> results = pm.queryIntentActivities(new Intent(categoryKey), 0); 160744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk if (results.size() == 0) { 161744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk return null; 162744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk } 163744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk for (ResolveInfo resolved : results) { 164744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk if (!resolved.system) { 165744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk // Do not allow any app to add to settings, only system ones. 166744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk continue; 167744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk } 168744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk category.title = resolved.activityInfo.loadLabel(pm); 169744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk category.priority = SETTING_PKG.equals( 170744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk resolved.activityInfo.applicationInfo.packageName) ? resolved.priority : 0; 171744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk if (DEBUG) Log.d(LOG_TAG, "Adding category " + category.title); 172744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk } 173744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk 174744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk return category; 175744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk } 176744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk 177744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk private static void getTilesForAction(Context context, 178f509d7e65a062957be86619b3cb894e99268c4aeJason Monk UserHandle user, String action, Map<Pair<String, String>, Tile> addedCache, 179f509d7e65a062957be86619b3cb894e99268c4aeJason Monk String defaultCategory, ArrayList<Tile> outTiles, boolean requireSettings) { 180744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk Intent intent = new Intent(action); 181f509d7e65a062957be86619b3cb894e99268c4aeJason Monk if (requireSettings) { 182f509d7e65a062957be86619b3cb894e99268c4aeJason Monk intent.setPackage(SETTING_PKG); 183f509d7e65a062957be86619b3cb894e99268c4aeJason Monk } 184f509d7e65a062957be86619b3cb894e99268c4aeJason Monk getTilesForIntent(context, user, intent, addedCache, defaultCategory, outTiles, 185f509d7e65a062957be86619b3cb894e99268c4aeJason Monk requireSettings, true); 186f509d7e65a062957be86619b3cb894e99268c4aeJason Monk } 187f509d7e65a062957be86619b3cb894e99268c4aeJason Monk 188f509d7e65a062957be86619b3cb894e99268c4aeJason Monk public static void getTilesForIntent(Context context, UserHandle user, Intent intent, 189f509d7e65a062957be86619b3cb894e99268c4aeJason Monk Map<Pair<String, String>, Tile> addedCache, String defaultCategory, List<Tile> outTiles, 190f509d7e65a062957be86619b3cb894e99268c4aeJason Monk boolean usePriority, boolean checkCategory) { 191f509d7e65a062957be86619b3cb894e99268c4aeJason Monk PackageManager pm = context.getPackageManager(); 192744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk List<ResolveInfo> results = pm.queryIntentActivitiesAsUser(intent, 193744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk PackageManager.GET_META_DATA, user.getIdentifier()); 194744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk for (ResolveInfo resolved : results) { 195f509d7e65a062957be86619b3cb894e99268c4aeJason Monk if (!resolved.system) { 196f509d7e65a062957be86619b3cb894e99268c4aeJason Monk // Do not allow any app to add to settings, only system ones. 197f509d7e65a062957be86619b3cb894e99268c4aeJason Monk continue; 198744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk } 199744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk ActivityInfo activityInfo = resolved.activityInfo; 200744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk Bundle metaData = activityInfo.metaData; 201744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk String categoryKey = defaultCategory; 202f509d7e65a062957be86619b3cb894e99268c4aeJason Monk if (checkCategory && ((metaData == null) || !metaData.containsKey(EXTRA_CATEGORY_KEY)) 203744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk && categoryKey == null) { 204f509d7e65a062957be86619b3cb894e99268c4aeJason Monk Log.w(LOG_TAG, "Found " + resolved.activityInfo.name + " for intent " 205f509d7e65a062957be86619b3cb894e99268c4aeJason Monk + intent + " missing metadata " 206744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk + (metaData == null ? "" : EXTRA_CATEGORY_KEY)); 207744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk continue; 208744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk } else { 209744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk categoryKey = metaData.getString(EXTRA_CATEGORY_KEY); 210744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk } 211744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk Pair<String, String> key = new Pair<String, String>(activityInfo.packageName, 212744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk activityInfo.name); 213f509d7e65a062957be86619b3cb894e99268c4aeJason Monk Tile tile = addedCache.get(key); 214744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk if (tile == null) { 215f509d7e65a062957be86619b3cb894e99268c4aeJason Monk tile = new Tile(); 216744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk tile.intent = new Intent().setClassName( 217744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk activityInfo.packageName, activityInfo.name); 218744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk tile.category = categoryKey; 219f509d7e65a062957be86619b3cb894e99268c4aeJason Monk tile.priority = usePriority ? resolved.priority : 0; 220e79790b26803ee338b2fdc3404344094d7f94476Jason Monk tile.metaData = activityInfo.metaData; 221e79790b26803ee338b2fdc3404344094d7f94476Jason Monk updateTileData(context, tile, activityInfo, activityInfo.applicationInfo, 222e79790b26803ee338b2fdc3404344094d7f94476Jason Monk pm); 223744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk if (DEBUG) Log.d(LOG_TAG, "Adding tile " + tile.title); 224744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk 225744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk addedCache.put(key, tile); 226744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk } 227744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk if (!tile.userHandle.contains(user)) { 228744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk tile.userHandle.add(user); 229744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk } 230744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk if (!outTiles.contains(tile)) { 231744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk outTiles.add(tile); 232744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk } 233744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk } 234744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk } 235744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk 236744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk private static DashboardCategory getCategory(List<DashboardCategory> target, 237744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk String categoryKey) { 238744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk for (DashboardCategory category : target) { 239744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk if (categoryKey.equals(category.key)) { 240744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk return category; 241744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk } 242744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk } 243744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk return null; 244744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk } 245744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk 246f509d7e65a062957be86619b3cb894e99268c4aeJason Monk private static boolean updateTileData(Context context, Tile tile, 247e79790b26803ee338b2fdc3404344094d7f94476Jason Monk ActivityInfo activityInfo, ApplicationInfo applicationInfo, PackageManager pm) { 248e79790b26803ee338b2fdc3404344094d7f94476Jason Monk if (applicationInfo.isSystemApp()) { 249e79790b26803ee338b2fdc3404344094d7f94476Jason Monk int icon = 0; 250e79790b26803ee338b2fdc3404344094d7f94476Jason Monk CharSequence title = null; 251e79790b26803ee338b2fdc3404344094d7f94476Jason Monk String summary = null; 252e79790b26803ee338b2fdc3404344094d7f94476Jason Monk 253e79790b26803ee338b2fdc3404344094d7f94476Jason Monk // Get the activity's meta-data 254e79790b26803ee338b2fdc3404344094d7f94476Jason Monk try { 255e79790b26803ee338b2fdc3404344094d7f94476Jason Monk Resources res = pm.getResourcesForApplication( 256e79790b26803ee338b2fdc3404344094d7f94476Jason Monk applicationInfo.packageName); 257e79790b26803ee338b2fdc3404344094d7f94476Jason Monk Bundle metaData = activityInfo.metaData; 258e79790b26803ee338b2fdc3404344094d7f94476Jason Monk 259e79790b26803ee338b2fdc3404344094d7f94476Jason Monk if (res != null && metaData != null) { 260e79790b26803ee338b2fdc3404344094d7f94476Jason Monk if (metaData.containsKey(META_DATA_PREFERENCE_ICON)) { 261e79790b26803ee338b2fdc3404344094d7f94476Jason Monk icon = metaData.getInt(META_DATA_PREFERENCE_ICON); 262744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk } 263e79790b26803ee338b2fdc3404344094d7f94476Jason Monk if (metaData.containsKey(META_DATA_PREFERENCE_TITLE)) { 264f509d7e65a062957be86619b3cb894e99268c4aeJason Monk if (metaData.get(META_DATA_PREFERENCE_TITLE) instanceof Integer) { 265f509d7e65a062957be86619b3cb894e99268c4aeJason Monk title = res.getString(metaData.getInt(META_DATA_PREFERENCE_TITLE)); 266f509d7e65a062957be86619b3cb894e99268c4aeJason Monk } else { 267f509d7e65a062957be86619b3cb894e99268c4aeJason Monk title = metaData.getString(META_DATA_PREFERENCE_TITLE); 268f509d7e65a062957be86619b3cb894e99268c4aeJason Monk } 269744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk } 270e79790b26803ee338b2fdc3404344094d7f94476Jason Monk if (metaData.containsKey(META_DATA_PREFERENCE_SUMMARY)) { 271f509d7e65a062957be86619b3cb894e99268c4aeJason Monk if (metaData.get(META_DATA_PREFERENCE_SUMMARY) instanceof Integer) { 272f509d7e65a062957be86619b3cb894e99268c4aeJason Monk summary = res.getString(metaData.getInt(META_DATA_PREFERENCE_SUMMARY)); 273f509d7e65a062957be86619b3cb894e99268c4aeJason Monk } else { 274f509d7e65a062957be86619b3cb894e99268c4aeJason Monk summary = metaData.getString(META_DATA_PREFERENCE_SUMMARY); 275f509d7e65a062957be86619b3cb894e99268c4aeJason Monk } 276744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk } 277744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk } 278e79790b26803ee338b2fdc3404344094d7f94476Jason Monk } catch (PackageManager.NameNotFoundException | Resources.NotFoundException e) { 279e79790b26803ee338b2fdc3404344094d7f94476Jason Monk if (DEBUG) Log.d(LOG_TAG, "Couldn't find info", e); 280744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk } 281e79790b26803ee338b2fdc3404344094d7f94476Jason Monk 282e79790b26803ee338b2fdc3404344094d7f94476Jason Monk // Set the preference title to the activity's label if no 283e79790b26803ee338b2fdc3404344094d7f94476Jason Monk // meta-data is found 284e79790b26803ee338b2fdc3404344094d7f94476Jason Monk if (TextUtils.isEmpty(title)) { 285e79790b26803ee338b2fdc3404344094d7f94476Jason Monk title = activityInfo.loadLabel(pm).toString(); 286e79790b26803ee338b2fdc3404344094d7f94476Jason Monk } 287e79790b26803ee338b2fdc3404344094d7f94476Jason Monk if (icon == 0) { 288e79790b26803ee338b2fdc3404344094d7f94476Jason Monk icon = activityInfo.icon; 289e79790b26803ee338b2fdc3404344094d7f94476Jason Monk } 290e79790b26803ee338b2fdc3404344094d7f94476Jason Monk 291e79790b26803ee338b2fdc3404344094d7f94476Jason Monk // Set icon, title and summary for the preference 292e79790b26803ee338b2fdc3404344094d7f94476Jason Monk tile.icon = Icon.createWithResource(activityInfo.packageName, icon); 293e79790b26803ee338b2fdc3404344094d7f94476Jason Monk tile.title = title; 294e79790b26803ee338b2fdc3404344094d7f94476Jason Monk tile.summary = summary; 295e79790b26803ee338b2fdc3404344094d7f94476Jason Monk // Replace the intent with this specific activity 296e79790b26803ee338b2fdc3404344094d7f94476Jason Monk tile.intent = new Intent().setClassName(activityInfo.packageName, 297e79790b26803ee338b2fdc3404344094d7f94476Jason Monk activityInfo.name); 298e79790b26803ee338b2fdc3404344094d7f94476Jason Monk 299e79790b26803ee338b2fdc3404344094d7f94476Jason Monk return true; 300744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk } 301744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk 302744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk return false; 303744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk } 304744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk 305f509d7e65a062957be86619b3cb894e99268c4aeJason Monk private static final Comparator<Tile> TILE_COMPARATOR = 306f509d7e65a062957be86619b3cb894e99268c4aeJason Monk new Comparator<Tile>() { 307744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk @Override 308f509d7e65a062957be86619b3cb894e99268c4aeJason Monk public int compare(Tile lhs, Tile rhs) { 309744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk return rhs.priority - lhs.priority; 310744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk } 311744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk }; 312744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk 313744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk private static final Comparator<DashboardCategory> CATEGORY_COMPARATOR = 314744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk new Comparator<DashboardCategory>() { 315744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk @Override 316744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk public int compare(DashboardCategory lhs, DashboardCategory rhs) { 317744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk return rhs.priority - lhs.priority; 318744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk } 319744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk }; 320744b63632a0d41eabf60e95a7b61e235e43f6d07Jason Monk} 321