diff --git a/src/com/android/settings/CreateShortcut.java b/src/com/android/settings/CreateShortcut.java
index 73177384325..befc9e0b97a 100644
--- a/src/com/android/settings/CreateShortcut.java
+++ b/src/com/android/settings/CreateShortcut.java
@@ -59,14 +59,14 @@ public class CreateShortcut extends LauncherActivity {
ResolveInfo resolveInfo = itemForPosition(position).resolveInfo;
ActivityInfo activityInfo = resolveInfo.activityInfo;
if (activityInfo.icon != 0) {
- intent.putExtra(Intent.EXTRA_SHORTCUT_ICON, createIcon(activityInfo.icon));
+ intent.putExtra(Intent.EXTRA_SHORTCUT_ICON, createIcon(this, activityInfo.icon));
}
setResult(RESULT_OK, intent);
finish();
}
- private Bitmap createIcon(int resource) {
- Context context = new ContextThemeWrapper(this, android.R.style.Theme_Material);
+ static Bitmap createIcon(Context ctx, int resource) {
+ Context context = new ContextThemeWrapper(ctx, android.R.style.Theme_Material);
View view = LayoutInflater.from(context).inflate(R.layout.shortcut_badge, null);
((ImageView) view.findViewById(android.R.id.icon)).setImageResource(resource);
diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java
index 3209b51b1f4..b3df4a49430 100644
--- a/src/com/android/settings/SettingsActivity.java
+++ b/src/com/android/settings/SettingsActivity.java
@@ -43,6 +43,7 @@ import android.transition.TransitionManager;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
+
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
@@ -536,6 +537,8 @@ public class SettingsActivity extends SettingsDrawerActivity
final ComponentName cn = intent.getComponent();
final String className = cn.getClassName();
+ publishShortcuts();
+
mIsShowingDashboard = className.equals(Settings.class.getName())
|| className.equals(Settings.WirelessSettings.class.getName())
|| className.equals(Settings.DeviceSettings.class.getName())
@@ -1016,6 +1019,18 @@ public class SettingsActivity extends SettingsDrawerActivity
return f;
}
+ private void publishShortcuts() {
+ AsyncTask.execute(new Runnable() {
+ @Override
+ public void run() {
+ if (!getSharedPreferences(ShortcutInfoPublisher.PREF_FILE, Context.MODE_PRIVATE)
+ .getBoolean(ShortcutInfoPublisher.PREF_KEY, false)) {
+ ShortcutInfoPublisher.setDynamicShortcuts(SettingsActivity.this, getTileCache());
+ }
+ }
+ });
+ }
+
private void updateTilesList() {
// Generally the items that are will be changing from these updates will
// not be in the top list of tiles, so run it in the background and the
diff --git a/src/com/android/settings/ShortcutInfoPublisher.java b/src/com/android/settings/ShortcutInfoPublisher.java
new file mode 100644
index 00000000000..893292ea881
--- /dev/null
+++ b/src/com/android/settings/ShortcutInfoPublisher.java
@@ -0,0 +1,134 @@
+package com.android.settings;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.pm.ShortcutInfo;
+import android.content.pm.ShortcutManager;
+import android.graphics.drawable.Icon;
+import android.util.Log;
+import android.util.Pair;
+import com.android.settingslib.drawer.Tile;
+import com.android.settingslib.drawer.TileUtils;
+
+import java.util.*;
+
+/**
+ * Helper class that publish top 5 tiles to the {@link ShortcutManager}.
+ *
+ * Assumptions:
+ *
+ * Intent short class name is used as unique identifier for creating {@link ShortcutInfo}.
+ * {@link Tile}s are sorted in ascending order of the priority field.
+ *
+ */
+public class ShortcutInfoPublisher {
+ private static boolean DBG = false;
+ private static String TAG = "ShortcutInfoPublisher";
+
+ public static String PREF_FILE = "shortcut_publisher";
+ public static String PREF_KEY = "shortcut_published";
+
+ /**
+ * For any {@param dShortcutMap} if any of them requires updating because {@link Tile} is different, update.
+ *
+ * Note: Once ShortcutInfo.getTitle supports res id, this will NOT be required on Locale change.
+ * TODO: call on ACTION_LOCALE_CHANGED broadcast intent.
+ */
+ public static void updateShortcuts(Context context, Collection tileList) {
+ ShortcutManager sm = context.getSystemService(ShortcutManager.class);
+ HashMap updateShortcutsMap = new HashMap<>();
+ for (ShortcutInfo s: sm.getDynamicShortcuts()) {
+ updateShortcutsMap.put(s.getId(), s);
+ }
+ for (ShortcutInfo s: sm.getPinnedShortcuts()) {
+ updateShortcutsMap.put(s.getId(), s);
+ }
+ ArrayList updateShortcuts = new ArrayList<>();
+ for(Tile t: tileList) {
+ if (publishedButChanged(updateShortcutsMap, t)){
+ ShortcutInfo s = buildShortcutInfo(context, t);
+ updateShortcuts.add(s);
+ if (DBG) Log.d(TAG, "update: " + s.getId());
+ }
+ }
+ // This check is not required if being called from foreground activity.
+ if (sm.getRemainingCallCount() > 0 && updateShortcuts.size() > 0) {
+ sm.updateShortcuts(updateShortcuts);
+ if (DBG) Log.d(TAG, "ShortcutManager.updateshortcuts: " + updateShortcuts.size());
+ }
+ }
+
+ /**
+ * Set the 5 top Tile as {@link ShortcutInfo}.
+ *
+ * Note: once one time loading of static list is supported, this will NOT be required.
+ */
+ public static void setDynamicShortcuts(Context context, Map, Tile> tiles) {
+ ShortcutManager sm = context.getSystemService(ShortcutManager.class);
+ // Sort the tiles so that tiles with higher priority is at the beginning.
+ ArrayList tileList = new ArrayList<>();
+ tileList.addAll(tiles.values());
+ Collections.sort(tileList, TileUtils.TILE_COMPARATOR);
+
+ int max = sm.getMaxDynamicShortcutCount();
+ ArrayList dShortcutList = new ArrayList<>();
+ for(Tile t: tileList) {
+ ShortcutInfo s = buildShortcutInfo(context, t);
+ dShortcutList.add(s);
+ if (DBG) Log.d(TAG, "add new shortcut: " + s.getId());
+ if (dShortcutList.size() >= max) {
+ break;
+ }
+ }
+ // This check is not required if being called from foreground activity.
+ if (sm.getRemainingCallCount() > 0) {
+ sm.setDynamicShortcuts(dShortcutList);
+ if (DBG) Log.d(TAG, "ShortcutManager.setDynamicShortcuts");
+ SharedPreferences sharedPref = context.getSharedPreferences(PREF_FILE, Context.MODE_PRIVATE);
+ SharedPreferences.Editor editor = sharedPref.edit();
+ editor.putBoolean(PREF_KEY, true);
+ editor.commit();
+ }
+ }
+
+ /**
+ * Extract string from {@link Tile} that should be used for shortcut id.
+ */
+ private static String getShortcutInfoId(Tile t) {
+ return t.intent.getComponent().getShortClassName();
+ }
+
+ /**
+ * Build ShortcutInfo from given Tile.
+ */
+ private static ShortcutInfo buildShortcutInfo(Context context, Tile t) {
+ return new ShortcutInfo.Builder(context)
+ .setId(getShortcutInfoId(t))
+ .setTitle(t.title.toString())
+ .setIntent(t.intent)
+ .setIcon(Icon.createWithBitmap(CreateShortcut.createIcon(context, t.icon.getResId())))
+ .setWeight(t.priority)
+ .build();
+ }
+
+ private static boolean publishedButChanged(Map shortcutMap, Tile t) {
+ ShortcutInfo s = shortcutMap.get(getShortcutInfoId(t));
+ if (s == null) {
+ return false; // never published.
+ }
+ if (t.priority != s.getWeight()) {
+ if (DBG) Log.d(TAG, s.getId() + " *weight* diff s:" + s.getWeight() + "t:" + t.priority);
+ return true;
+ } else if (!t.intent.equals(s.getIntent())) {
+ if (DBG) Log.d(TAG, s.getId() + " *intent* diff s:" + s.getIntent() + "t:" + t.intent);
+ return true;
+ } else if (!t.title.equals(s.getTitle())) {
+ if (DBG) Log.d(TAG, s.getId() + " *title* diff s:" + s.getTitle() + "t:" + t.title);
+ return true;
+ } else if (!t.icon.sameAs(s.getIcon())) {
+ if (DBG) Log.d(TAG, s.getId() + " *icon* diff s:" + s.getIcon() + "t:" + t.icon);
+ return true;
+ }
+ return false;
+ }
+}