summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSunny Goyal <sunnygoyal@google.com>2014-09-05 07:42:31 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2014-09-05 07:42:32 +0000
commit1c13ff569170bec075ab9961fbc0eb1ca395696b (patch)
tree8291513e3e8c9a072e23cce1f4dd9f0c95fb86ae
parent66205ce9ceb46a821c9a2d93745226d67f1b119a (diff)
parent349426234e8c5a0e5bcf2c8d94dbb9844b5f724a (diff)
downloadandroid_packages_apps_Trebuchet-1c13ff569170bec075ab9961fbc0eb1ca395696b.tar.gz
android_packages_apps_Trebuchet-1c13ff569170bec075ab9961fbc0eb1ca395696b.tar.bz2
android_packages_apps_Trebuchet-1c13ff569170bec075ab9961fbc0eb1ca395696b.zip
Merge "Handling label and icon from SessionInfo." into ub-now-porkchop
-rw-r--r--src/com/android/launcher3/AutoInstallsLayout.java2
-rw-r--r--src/com/android/launcher3/BubbleTextView.java49
-rw-r--r--src/com/android/launcher3/IconCache.java52
-rw-r--r--src/com/android/launcher3/ItemInfo.java4
-rw-r--r--src/com/android/launcher3/Launcher.java6
-rw-r--r--src/com/android/launcher3/LauncherAppState.java2
-rw-r--r--src/com/android/launcher3/LauncherModel.java131
-rw-r--r--src/com/android/launcher3/PreloadIconDrawable.java6
-rw-r--r--src/com/android/launcher3/ShortcutInfo.java98
-rw-r--r--src/com/android/launcher3/Workspace.java129
-rw-r--r--src/com/android/launcher3/compat/PackageInstallerCompat.java6
-rw-r--r--src/com/android/launcher3/compat/PackageInstallerCompatV16.java8
-rw-r--r--src/com/android/launcher3/compat/PackageInstallerCompatVL.java30
13 files changed, 317 insertions, 206 deletions
diff --git a/src/com/android/launcher3/AutoInstallsLayout.java b/src/com/android/launcher3/AutoInstallsLayout.java
index 4ea7b3d78..931501c6a 100644
--- a/src/com/android/launcher3/AutoInstallsLayout.java
+++ b/src/com/android/launcher3/AutoInstallsLayout.java
@@ -298,7 +298,7 @@ public class AutoInstallsLayout implements WorkspaceLoader {
return -1;
}
- mValues.put(Favorites.RESTORED, 1);
+ mValues.put(Favorites.RESTORED, ShortcutInfo.FLAG_AUTOINTALL_ICON);
final Intent intent = new Intent(Intent.ACTION_MAIN, null)
.addCategory(Intent.CATEGORY_LAUNCHER)
.setComponent(new ComponentName(packageName, className))
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index d83f81dab..a368796bd 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -26,7 +26,6 @@ import android.graphics.Canvas;
import android.graphics.Region;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
-import android.util.Log;
import android.util.SparseArray;
import android.util.TypedValue;
import android.view.KeyEvent;
@@ -50,10 +49,6 @@ public class BubbleTextView extends TextView {
private static final int SHADOW_SMALL_COLOUR = 0xCC000000;
static final float PADDING_V = 3.0f;
- private static final String TAG = "BubbleTextView";
-
- private static final boolean DEBUG = false;
-
private HolographicOutlineHelper mOutlineHelper;
private Bitmap mPressedBackground;
@@ -118,6 +113,11 @@ public class BubbleTextView extends TextView {
public void applyFromShortcutInfo(ShortcutInfo info, IconCache iconCache,
boolean setDefaultPadding) {
+ applyFromShortcutInfo(info, iconCache, setDefaultPadding, false);
+ }
+
+ public void applyFromShortcutInfo(ShortcutInfo info, IconCache iconCache,
+ boolean setDefaultPadding, boolean promiseStateChanged) {
Bitmap b = info.getIcon(iconCache);
LauncherAppState app = LauncherAppState.getInstance();
@@ -135,8 +135,8 @@ public class BubbleTextView extends TextView {
setText(info.title);
setTag(info);
- if (info.wasPromise) {
- applyState();
+ if (promiseStateChanged || info.isPromise()) {
+ applyState(promiseStateChanged);
}
}
@@ -377,31 +377,13 @@ public class BubbleTextView extends TextView {
mLongPressHelper.cancelLongPress();
}
- public void applyState() {
+ public void applyState(boolean promiseStateChanged) {
if (getTag() instanceof ShortcutInfo) {
ShortcutInfo info = (ShortcutInfo) getTag();
- final int state = info.getState();
-
- final int progressLevel;
- if (DEBUG) Log.d(TAG, "applying icon state: " + state);
-
- switch(state) {
- case ShortcutInfo.PACKAGE_STATE_DEFAULT:
- progressLevel = 100;
- break;
-
- case ShortcutInfo.PACKAGE_STATE_INSTALLING:
- setText(R.string.package_state_installing);
- progressLevel = info.getProgress();
- break;
-
- case ShortcutInfo.PACKAGE_STATE_ERROR:
- case ShortcutInfo.PACKAGE_STATE_UNKNOWN:
- default:
- progressLevel = 0;
- setText(R.string.package_state_unknown);
- break;
- }
+ final boolean isPromise = info.isPromise();
+ final int progressLevel = isPromise ?
+ ((info.hasStatusFlag(ShortcutInfo.FLAG_INSTALL_SESSION_ACTIVE) ?
+ info.getInstallProgress() : 0)) : 100;
Drawable[] drawables = getCompoundDrawables();
Drawable top = drawables[1];
@@ -415,12 +397,9 @@ public class BubbleTextView extends TextView {
}
preloadDrawable.setLevel(progressLevel);
- if ((state == ShortcutInfo.PACKAGE_STATE_DEFAULT) && info.wasPromise) {
- // Clear the promise flag as it is no longer different than a normal shortcut,
- // once the animation has been run.
- info.wasPromise = !preloadDrawable.maybePerformFinishedAnimation();
+ if (promiseStateChanged) {
+ preloadDrawable.maybePerformFinishedAnimation();
}
-
}
}
}
diff --git a/src/com/android/launcher3/IconCache.java b/src/com/android/launcher3/IconCache.java
index 76a85caae..75be83638 100644
--- a/src/com/android/launcher3/IconCache.java
+++ b/src/com/android/launcher3/IconCache.java
@@ -30,6 +30,7 @@ import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
+import android.text.TextUtils;
import android.util.Log;
import com.android.launcher3.compat.LauncherActivityInfoCompat;
@@ -254,18 +255,16 @@ public class IconCache {
return getIcon(intent, null, user, true);
}
- public Bitmap getIcon(Intent intent, String title, UserHandleCompat user, boolean usePkgIcon) {
+ private Bitmap getIcon(Intent intent, String title, UserHandleCompat user, boolean usePkgIcon) {
synchronized (mCache) {
- LauncherActivityInfoCompat launcherActInfo =
- mLauncherApps.resolveActivity(intent, user);
ComponentName component = intent.getComponent();
-
// null info means not installed, but if we have a component from the intent then
// we should still look in the cache for restored app icons.
if (component == null) {
return getDefaultIcon(user);
}
+ LauncherActivityInfoCompat launcherActInfo = mLauncherApps.resolveActivity(intent, user);
CacheEntry entry = cacheLocked(component, launcherActInfo, null, user, usePkgIcon);
if (title != null) {
entry.title = title;
@@ -275,6 +274,32 @@ public class IconCache {
}
}
+ /**
+ * Fill in "shortcutInfo" with the icon and label for "info."
+ */
+ public void getTitleAndIcon(ShortcutInfo shortcutInfo, Intent intent, UserHandleCompat user,
+ boolean usePkgIcon) {
+ synchronized (mCache) {
+ ComponentName component = intent.getComponent();
+ // null info means not installed, but if we have a component from the intent then
+ // we should still look in the cache for restored app icons.
+ if (component == null) {
+ shortcutInfo.setIcon(getDefaultIcon(user));
+ shortcutInfo.title = "";
+ shortcutInfo.usingFallbackIcon = true;
+ } else {
+ LauncherActivityInfoCompat launcherActInfo =
+ mLauncherApps.resolveActivity(intent, user);
+ CacheEntry entry = cacheLocked(component, launcherActInfo, null, user, usePkgIcon);
+
+ shortcutInfo.setIcon(entry.icon);
+ shortcutInfo.title = entry.title;
+ shortcutInfo.usingFallbackIcon = isDefaultIcon(entry.icon, user);
+ }
+ }
+ }
+
+
public Bitmap getDefaultIcon(UserHandleCompat user) {
if (!mDefaultIcons.containsKey(user)) {
mDefaultIcons.put(user, makeDefaultIcon(user));
@@ -332,10 +357,11 @@ public class IconCache {
if (usePackageIcon) {
CacheEntry packageEntry = getEntryForPackage(
componentName.getPackageName(), user);
- if (packageEntry != null && packageEntry.icon != null) {
+ if (packageEntry != null) {
if (DEBUG) Log.d(TAG, "using package default icon for " +
componentName.toShortString());
entry.icon = packageEntry.icon;
+ entry.title = packageEntry.title;
}
}
if (entry.icon == null) {
@@ -350,6 +376,21 @@ public class IconCache {
}
/**
+ * Adds a default package entry in the cache. This entry is not persisted and will be removed
+ * when the cache is flushed.
+ */
+ public void cachePackageInstallInfo(String packageName, UserHandleCompat user,
+ Bitmap icon, CharSequence title) {
+ CacheEntry entry = getEntryForPackage(packageName, user);
+ if (!TextUtils.isEmpty(title)) {
+ entry.title = title;
+ }
+ if (icon != null) {
+ entry.icon = Utilities.createIconBitmap(icon, mContext);
+ }
+ }
+
+ /**
* Gets an entry for the package, which can be used as a fallback entry for various components.
*/
private CacheEntry getEntryForPackage(String packageName, UserHandleCompat user) {
@@ -358,6 +399,7 @@ public class IconCache {
CacheEntry entry = mCache.get(cacheKey);
if (entry == null) {
entry = new CacheEntry();
+ entry.title = "";
mCache.put(cacheKey, entry);
try {
diff --git a/src/com/android/launcher3/ItemInfo.java b/src/com/android/launcher3/ItemInfo.java
index 8f96f74eb..09b77f756 100644
--- a/src/com/android/launcher3/ItemInfo.java
+++ b/src/com/android/launcher3/ItemInfo.java
@@ -146,10 +146,6 @@ public class ItemInfo {
throw new RuntimeException("Unexpected Intent");
}
- protected Intent getRestoredIntent() {
- throw new RuntimeException("Unexpected Intent");
- }
-
/**
* Write the fields of this item to the DB
*
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index ffce116b9..309ab46c9 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -2600,9 +2600,11 @@ public class Launcher extends Activity
}
// Check for abandoned promise
- if (shortcut.isAbandoned() && v instanceof BubbleTextView) {
+ if ((v instanceof BubbleTextView)
+ && shortcut.isPromise()
+ && !shortcut.hasStatusFlag(ShortcutInfo.FLAG_INSTALL_SESSION_ACTIVE)) {
showBrokenAppInstallDialog(
- shortcut.getRestoredIntent().getComponent().getPackageName(),
+ shortcut.getTargetComponent().getPackageName(),
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
startAppShortcutOrInfoActivity(v);
diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java
index 4ab4e4bea..2657b6e65 100644
--- a/src/com/android/launcher3/LauncherAppState.java
+++ b/src/com/android/launcher3/LauncherAppState.java
@@ -161,7 +161,7 @@ public class LauncherAppState implements DeviceProfile.DeviceProfileCallbacks {
return mModel;
}
- IconCache getIconCache() {
+ public IconCache getIconCache() {
return mIconCache;
}
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index 5e8e2ad0e..b44433d8d 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -54,12 +54,14 @@ import android.util.Pair;
import com.android.launcher3.compat.AppWidgetManagerCompat;
import com.android.launcher3.compat.LauncherActivityInfoCompat;
import com.android.launcher3.compat.LauncherAppsCompat;
+import com.android.launcher3.compat.PackageInstallerCompat;
import com.android.launcher3.compat.PackageInstallerCompat.PackageInstallInfo;
import com.android.launcher3.compat.UserHandleCompat;
import com.android.launcher3.compat.UserManagerCompat;
import java.lang.ref.WeakReference;
import java.net.URISyntaxException;
+import java.security.InvalidParameterException;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Arrays;
@@ -359,7 +361,7 @@ public class LauncherModel extends BroadcastReceiver
Iterator<AppInfo> iter = allAppsApps.iterator();
while (iter.hasNext()) {
ItemInfo a = iter.next();
- if (LauncherModel.appWasRestored(ctx, a.getIntent(), a.user)) {
+ if (LauncherModel.appWasPromise(ctx, a.getIntent(), a.user)) {
restoredAppsFinal.add((AppInfo) a);
}
}
@@ -428,7 +430,7 @@ public class LauncherModel extends BroadcastReceiver
if (LauncherModel.shortcutExists(context, name, launchIntent)) {
// Only InstallShortcutReceiver sends us shortcutInfos, ignore them
if (a instanceof AppInfo &&
- LauncherModel.appWasRestored(context, launchIntent, a.user)) {
+ LauncherModel.appWasPromise(context, launchIntent, a.user)) {
restoredAppsFinal.add((AppInfo) a);
}
continue;
@@ -884,33 +886,14 @@ public class LauncherModel extends BroadcastReceiver
}
/**
- * Returns true if the shortcuts already exists in the database.
- * we identify a shortcut by the component name of the intent
- * and the user.
+ * Returns true if the promise shortcuts with the same package name exists on the workspace.
*/
- static boolean appWasRestored(Context context, Intent intent, UserHandleCompat user) {
- final ContentResolver cr = context.getContentResolver();
+ static boolean appWasPromise(Context context, Intent intent, UserHandleCompat user) {
final ComponentName component = intent.getComponent();
if (component == null) {
return false;
}
- String componentName = component.flattenToString();
- String shortName = component.flattenToShortString();
- long serialNumber = UserManagerCompat.getInstance(context)
- .getSerialNumberForUser(user);
- final String where = "(intent glob \"*component=" + componentName + "*\" or " +
- "intent glob \"*component=" + shortName + "*\")" +
- "and restored = 1 and profileId = " + serialNumber;
- Cursor c = cr.query(LauncherSettings.Favorites.CONTENT_URI,
- new String[]{"intent", "restored", "profileId"}, where, null, null);
- boolean result = false;
- try {
- result = c.moveToFirst();
- } finally {
- c.close();
- }
- Log.d(TAG, "shortcutWasRestored is " + result + " for " + componentName);
- return result;
+ return !getItemsByPackageName(component.getPackageName(), user).isEmpty();
}
/**
@@ -1077,19 +1060,23 @@ public class LauncherModel extends BroadcastReceiver
| ((int) screen & 0xFF) << 16 | (localCellX & 0xFF) << 8 | (localCellY & 0xFF);
}
- /**
- * Removes all the items from the database corresponding to the specified package.
- */
- static void deletePackageFromDatabase(Context context, final String pn,
- final UserHandleCompat user) {
+ private static ArrayList<ItemInfo> getItemsByPackageName(
+ final String pn, final UserHandleCompat user) {
ItemInfoFilter filter = new ItemInfoFilter() {
@Override
public boolean filterItem(ItemInfo parent, ItemInfo info, ComponentName cn) {
return cn.getPackageName().equals(pn) && info.user.equals(user);
}
};
- ArrayList<ItemInfo> infos = filterItemInfos(sBgItemsIdMap.values(), filter);
- deleteItemsFromDatabase(context, infos);
+ return filterItemInfos(sBgItemsIdMap.values(), filter);
+ }
+
+ /**
+ * Removes all the items from the database corresponding to the specified package.
+ */
+ static void deletePackageFromDatabase(Context context, final String pn,
+ final UserHandleCompat user) {
+ deleteItemsFromDatabase(context, getItemsByPackageName(pn, user));
}
/**
@@ -1898,6 +1885,7 @@ public class LauncherModel extends BroadcastReceiver
synchronized (sBgLock) {
clearSBgDataStructures();
+ PackageInstallerCompat.getInstance(mContext).updateActiveSessionCache();
final ArrayList<Long> itemsToRemove = new ArrayList<Long>();
final ArrayList<Long> restoredRows = new ArrayList<Long>();
@@ -1971,6 +1959,7 @@ public class LauncherModel extends BroadcastReceiver
intentDescription = c.getString(intentIndex);
long serialNumber = c.getInt(profileIdIndex);
user = mUserManager.getUserForSerialNumber(serialNumber);
+ int promiseType = c.getInt(restoredIndex);
if (user == null) {
// User has been deleted remove the item.
itemsToRemove.add(id);
@@ -1992,12 +1981,34 @@ public class LauncherModel extends BroadcastReceiver
restored = false;
}
} else if (validPkg) {
- // The app is installed but the component is no
- // longer available.
- Launcher.addDumpLog(TAG,
- "Invalid component removed: " + cn, true);
- itemsToRemove.add(id);
- continue;
+ intent = null;
+ if ((promiseType & ShortcutInfo.FLAG_AUTOINTALL_ICON) != 0) {
+ // We allow auto install apps to have their intent
+ // updated after an install.
+ intent = manager.getLaunchIntentForPackage(
+ cn.getPackageName());
+ if (intent != null) {
+ ContentValues values = new ContentValues();
+ values.put(LauncherSettings.Favorites.INTENT,
+ intent.toUri(0));
+ String where = BaseColumns._ID + "= ?";
+ String[] args = {Long.toString(id)};
+ contentResolver.update(contentUri, values, where, args);
+ }
+ }
+
+ if (intent == null) {
+ // The app is installed but the component is no
+ // longer available.
+ Launcher.addDumpLog(TAG,
+ "Invalid component removed: " + cn, true);
+ itemsToRemove.add(id);
+ continue;
+ } else {
+ // no special handling necessary for this item
+ restoredRows.add(id);
+ restored = false;
+ }
} else if (restored) {
// Package is not yet available but might be
// installed later.
@@ -2036,7 +2047,7 @@ public class LauncherModel extends BroadcastReceiver
Launcher.addDumpLog(TAG,
"constructing info for partially restored package",
true);
- info = getRestoredItemInfo(c, titleIndex, intent);
+ info = getRestoredItemInfo(c, titleIndex, intent, promiseType);
intent = getRestoredItemIntent(c, context, intent);
} else {
// Don't restore items for other profiles.
@@ -2299,7 +2310,7 @@ public class LauncherModel extends BroadcastReceiver
selectionBuilder.append(")");
ContentValues values = new ContentValues();
values.put(LauncherSettings.Favorites.RESTORED, 0);
- updater.update(LauncherSettings.Favorites.CONTENT_URI,
+ updater.update(LauncherSettings.Favorites.CONTENT_URI_NO_NOTIFICATION,
values, selectionBuilder.toString(), null);
} catch (RemoteException e) {
Log.w(TAG, "Could not update restored rows");
@@ -2879,7 +2890,7 @@ public class LauncherModel extends BroadcastReceiver
packagesRemoved.toArray(new String[packagesRemoved.size()]), user));
}
}
- sPendingPackages.clear();
+ sPendingPackages.clear();
}
}
}
@@ -3101,21 +3112,31 @@ public class LauncherModel extends BroadcastReceiver
* Make an ShortcutInfo object for a restored application or shortcut item that points
* to a package that is not yet installed on the system.
*/
- public ShortcutInfo getRestoredItemInfo(Cursor cursor, int titleIndex, Intent intent) {
+ public ShortcutInfo getRestoredItemInfo(Cursor cursor, int titleIndex, Intent intent,
+ int promiseType) {
final ShortcutInfo info = new ShortcutInfo();
- if (cursor != null) {
- info.title = cursor.getString(titleIndex);
+ info.user = UserHandleCompat.myUserHandle();
+ mIconCache.getTitleAndIcon(info, intent, info.user, true);
+
+ if ((promiseType & ShortcutInfo.FLAG_RESTORED_ICON) != 0) {
+ String title = (cursor != null) ? cursor.getString(titleIndex) : null;
+ if (!TextUtils.isEmpty(title)) {
+ info.title = title;
+ }
+ info.status = ShortcutInfo.FLAG_RESTORED_ICON;
+ } else if ((promiseType & ShortcutInfo.FLAG_AUTOINTALL_ICON) != 0) {
+ if (TextUtils.isEmpty(info.title)) {
+ info.title = (cursor != null) ? cursor.getString(titleIndex) : "";
+ }
+ info.status = ShortcutInfo.FLAG_AUTOINTALL_ICON;
} else {
- info.title = "";
+ throw new InvalidParameterException("Invalid restoreType " + promiseType);
}
- info.user = UserHandleCompat.myUserHandle();
+
info.contentDescription = mUserManager.getBadgedLabelForUser(
info.title.toString(), info.user);
- info.setIcon(mIconCache.getIcon(intent, info.title.toString(), info.user, false));
info.itemType = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
- info.restoredIntent = intent;
- info.wasPromise = true;
- info.setState(ShortcutInfo.PACKAGE_STATE_UNKNOWN);
+ info.promisedIntent = intent;
return info;
}
@@ -3230,20 +3251,14 @@ public class LauncherModel extends BroadcastReceiver
for (ItemInfo i : infos) {
if (i instanceof ShortcutInfo) {
ShortcutInfo info = (ShortcutInfo) i;
- ComponentName cn = info.intent.getComponent();
- if (info.restoredIntent != null) {
- cn = info.restoredIntent.getComponent();
- }
+ ComponentName cn = info.getTargetComponent();
if (cn != null && f.filterItem(null, info, cn)) {
filtered.add(info);
}
} else if (i instanceof FolderInfo) {
FolderInfo info = (FolderInfo) i;
for (ShortcutInfo s : info.contents) {
- ComponentName cn = s.intent.getComponent();
- if (s.restoredIntent != null) {
- cn = s.restoredIntent.getComponent();
- }
+ ComponentName cn = s.getTargetComponent();
if (cn != null && f.filterItem(info, s, cn)) {
filtered.add(s);
}
@@ -3287,7 +3302,7 @@ public class LauncherModel extends BroadcastReceiver
return true;
}
// placeholder shortcuts get special treatment, let them through too.
- if (info.getRestoredIntent() != null) {
+ if (info.isPromise()) {
return true;
}
}
diff --git a/src/com/android/launcher3/PreloadIconDrawable.java b/src/com/android/launcher3/PreloadIconDrawable.java
index 1b2d5a4e3..2972c4f9b 100644
--- a/src/com/android/launcher3/PreloadIconDrawable.java
+++ b/src/com/android/launcher3/PreloadIconDrawable.java
@@ -189,11 +189,10 @@ class PreloadIconDrawable extends Drawable {
/**
* Runs the finish animation if it is has not been run after last level change.
- * @return true if the animation was run.
*/
- public boolean maybePerformFinishedAnimation() {
+ public void maybePerformFinishedAnimation() {
if (mAnimationProgress > ANIMATION_PROGRESS_STOPPED) {
- return false;
+ return;
}
if (mAnimator != null) {
mAnimator.cancel();
@@ -202,7 +201,6 @@ class PreloadIconDrawable extends Drawable {
mAnimator = ObjectAnimator.ofFloat(this, "animationProgress",
ANIMATION_PROGRESS_STARTED, ANIMATION_PROGRESS_COMPLETED);
mAnimator.start();
- return true;
}
public void setAnimationProgress(float progress) {
diff --git a/src/com/android/launcher3/ShortcutInfo.java b/src/com/android/launcher3/ShortcutInfo.java
index 612b0a5aa..9abfb7f86 100644
--- a/src/com/android/launcher3/ShortcutInfo.java
+++ b/src/com/android/launcher3/ShortcutInfo.java
@@ -16,6 +16,7 @@
package com.android.launcher3;
+import android.content.ComponentName;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
@@ -32,17 +33,26 @@ import java.util.Arrays;
*/
public class ShortcutInfo extends ItemInfo {
- /** {@link #mState} meaning this package is not installed, and there is no other information. */
- public static final int PACKAGE_STATE_UNKNOWN = -2;
+ public static final int DEFAULT = 0;
- /** {@link #mState} meaning this package is not installed, because installation failed. */
- public static final int PACKAGE_STATE_ERROR = -1;
+ /**
+ * The shortcut was restored from a backup and it not ready to be used. This is automatically
+ * set during backup/restore
+ */
+ public static final int FLAG_RESTORED_ICON = 1;
- /** {@link #mState} meaning this package is installed. This is the typical case. */
- public static final int PACKAGE_STATE_DEFAULT = 0;
+ /**
+ * The icon was added as an auto-install app, and is not ready to be used. This flag can't
+ * be present along with {@link #FLAG_RESTORED_ICON}, and is set during default layout
+ * parsing.
+ */
+ public static final int FLAG_AUTOINTALL_ICON = 2;
- /** {@link #mState} meaning some external entity has promised to install this package. */
- public static final int PACKAGE_STATE_INSTALLING = 1;
+ /**
+ * The icon is being installed. If {@link FLAG_RESTORED_ICON} or {@link FLAG_AUTOINTALL_ICON}
+ * is set, then the icon is either being installed or is in a broken state.
+ */
+ public static final int FLAG_INSTALL_SESSION_ACTIVE = 4;
/**
* The intent used to start the application.
@@ -78,29 +88,29 @@ public class ShortcutInfo extends ItemInfo {
*/
boolean isDisabled = false;
- /**
- * The installation state of the package that this shortcut represents.
- */
- protected int mState;
+ int status;
/**
* The installation progress [0-100] of the package that this shortcut represents.
*/
- protected int mProgress;
+ private int mInstallProgress;
+ /**
+ * Refer {@link AppInfo#firstInstallTime}.
+ */
long firstInstallTime;
- int flags = 0;
/**
- * If this shortcut is a placeholder, then intent will be a market intent for the package, and
- * this will hold the original intent from the database. Otherwise, null.
+ * TODO move this to {@link status}
*/
- Intent restoredIntent;
+ int flags = 0;
/**
- * This is set once to indicate that it was a promise info at some point of its life.
+ * If this shortcut is a placeholder, then intent will be a market intent for the package, and
+ * this will hold the original intent from the database. Otherwise, null.
+ * Refer {@link #FLAG_RESTORE_PENDING}, {@link #FLAG_INSTALL_PENDING}
*/
- boolean wasPromise = false;
+ Intent promisedIntent;
ShortcutInfo() {
itemType = LauncherSettings.BaseLauncherColumns.ITEM_TYPE_SHORTCUT;
@@ -110,21 +120,6 @@ public class ShortcutInfo extends ItemInfo {
return intent;
}
- protected Intent getRestoredIntent() {
- return restoredIntent;
- }
-
- /**
- * Overwrite placeholder data with restored data, or do nothing if this is not a placeholder.
- */
- public void restore() {
- if (restoredIntent != null) {
- intent = restoredIntent;
- restoredIntent = null;
- mState = PACKAGE_STATE_DEFAULT;
- }
- }
-
ShortcutInfo(Intent intent, CharSequence title, CharSequence contentDescription,
Bitmap icon, UserHandleCompat user) {
this();
@@ -149,6 +144,7 @@ public class ShortcutInfo extends ItemInfo {
flags = info.flags;
firstInstallTime = info.firstInstallTime;
user = info.user;
+ status = info.status;
}
/** TODO: Remove this. It's only called by ApplicationInfo.makeShortcut. */
@@ -184,7 +180,7 @@ public class ShortcutInfo extends ItemInfo {
String titleStr = title != null ? title.toString() : null;
values.put(LauncherSettings.BaseLauncherColumns.TITLE, titleStr);
- String uri = restoredIntent != null ? restoredIntent.toUri(0)
+ String uri = promisedIntent != null ? promisedIntent.toUri(0)
: (intent != null ? intent.toUri(0) : null);
values.put(LauncherSettings.BaseLauncherColumns.INTENT, uri);
@@ -224,36 +220,26 @@ public class ShortcutInfo extends ItemInfo {
}
}
- public boolean isPromise() {
- return restoredIntent != null;
+ public ComponentName getTargetComponent() {
+ return promisedIntent != null ? promisedIntent.getComponent() : intent.getComponent();
}
- public boolean isPromiseFor(String pkgName) {
- return restoredIntent != null
- && pkgName != null
- && pkgName.equals(restoredIntent.getComponent().getPackageName());
+ public boolean hasStatusFlag(int flag) {
+ return (status & flag) != 0;
}
- public boolean isAbandoned() {
- return isPromise()
- && (mState == PACKAGE_STATE_ERROR
- || mState == PACKAGE_STATE_UNKNOWN);
- }
-
- public int getProgress() {
- return mProgress;
- }
- public void setProgress(int progress) {
- mProgress = progress;
+ public final boolean isPromise() {
+ return hasStatusFlag(FLAG_RESTORED_ICON | FLAG_AUTOINTALL_ICON);
}
- public void setState(int state) {
- mState = state;
+ public int getInstallProgress() {
+ return mInstallProgress;
}
- public int getState() {
- return mState;
+ public void setInstallProgress(int progress) {
+ mInstallProgress = progress;
+ status |= FLAG_INSTALL_SESSION_ACTIVE;
}
}
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 2e966de0b..f7a0df681 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -31,7 +31,10 @@ import android.appwidget.AppWidgetHostView;
import android.appwidget.AppWidgetProviderInfo;
import android.content.ComponentName;
import android.content.Context;
+import android.content.Intent;
import android.content.SharedPreferences;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
@@ -65,6 +68,7 @@ import android.widget.TextView;
import com.android.launcher3.FolderIcon.FolderRingAnimator;
import com.android.launcher3.Launcher.CustomContentCallbacks;
import com.android.launcher3.LauncherSettings.Favorites;
+import com.android.launcher3.compat.PackageInstallerCompat;
import com.android.launcher3.compat.PackageInstallerCompat.PackageInstallInfo;
import com.android.launcher3.compat.UserHandleCompat;
@@ -72,6 +76,7 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
+import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
@@ -4746,26 +4751,6 @@ public class Workspace extends SmoothPagedView
stripEmptyScreens();
}
- private void updateShortcut(HashMap<ComponentName, AppInfo> appsMap, ItemInfo info,
- View child) {
- ComponentName cn = info.getIntent().getComponent();
- if (info.getRestoredIntent() != null) {
- cn = info.getRestoredIntent().getComponent();
- }
- if (cn != null) {
- AppInfo appInfo = appsMap.get(cn);
- if ((appInfo != null) && LauncherModel.isShortcutInfoUpdateable(info)) {
- ShortcutInfo shortcutInfo = (ShortcutInfo) info;
- BubbleTextView shortcut = (BubbleTextView) child;
- shortcutInfo.restore();
- shortcutInfo.updateIcon(mIconCache);
- shortcutInfo.title = appInfo.title.toString();
- shortcutInfo.contentDescription = appInfo.contentDescription;
- shortcut.applyFromShortcutInfo(shortcutInfo, mIconCache, true);
- }
- }
- }
-
interface ItemOperator {
/**
* Process the next itemInfo, possibly with side-effect on {@link ItemOperator#value}.
@@ -4824,13 +4809,83 @@ public class Workspace extends SmoothPagedView
pkgNames.add(ai.componentName.getPackageName());
}
+ final HashMap<UserHandleCompat, HashSet<ComponentName>> iconsToRemove =
+ new HashMap<UserHandleCompat, HashSet<ComponentName>>();
mapOverItems(MAP_RECURSE, new ItemOperator() {
@Override
public boolean evaluate(ItemInfo info, View v, View parent) {
- if (info instanceof ShortcutInfo) {
- updateShortcut(appsMap, info, v);
- if (parent != null) {
- parent.invalidate();
+ if (info instanceof ShortcutInfo && v instanceof BubbleTextView) {
+ ShortcutInfo shortcutInfo = (ShortcutInfo) info;
+ ComponentName cn = shortcutInfo.getTargetComponent();
+ AppInfo appInfo = appsMap.get(cn);
+ if (cn != null && LauncherModel.isShortcutInfoUpdateable(info)
+ && pkgNames.contains(cn.getPackageName())) {
+ boolean promiseStateChanged = false;
+ boolean infoUpdated = false;
+ if (shortcutInfo.isPromise()) {
+ if (shortcutInfo.hasStatusFlag(ShortcutInfo.FLAG_AUTOINTALL_ICON)) {
+ // Auto install icon
+ PackageManager pm = getContext().getPackageManager();
+ ResolveInfo matched = pm.resolveActivity(
+ new Intent(Intent.ACTION_MAIN)
+ .setComponent(cn).addCategory(Intent.CATEGORY_LAUNCHER),
+ PackageManager.MATCH_DEFAULT_ONLY);
+ if (matched == null) {
+ // Try to find the best match activity.
+ Intent intent = pm.getLaunchIntentForPackage(
+ cn.getPackageName());
+ if (intent != null) {
+ cn = intent.getComponent();
+ appInfo = appsMap.get(cn);
+ }
+
+ if ((intent == null) || (appsMap == null)) {
+ // Could not find a default activity. Remove this item.
+ HashSet<ComponentName> cnSet = iconsToRemove
+ .get(shortcutInfo.user);
+ if (cnSet == null) {
+ cnSet = new HashSet<>();
+ iconsToRemove.put(shortcutInfo.user, cnSet);
+ }
+ cnSet.add(shortcutInfo.getTargetComponent());
+
+ // process next shortcut.
+ return false;
+ }
+ shortcutInfo.promisedIntent = intent;
+ }
+ }
+
+ // Restore the shortcut.
+ shortcutInfo.intent = shortcutInfo.promisedIntent;
+ shortcutInfo.promisedIntent = null;
+ shortcutInfo.status &= ~ShortcutInfo.FLAG_RESTORED_ICON
+ & ~ShortcutInfo.FLAG_AUTOINTALL_ICON
+ & ~ShortcutInfo.FLAG_INSTALL_SESSION_ACTIVE;
+
+ promiseStateChanged = true;
+ infoUpdated = true;
+ shortcutInfo.updateIcon(mIconCache);
+ LauncherModel.updateItemInDatabase(getContext(), shortcutInfo);
+ }
+
+
+ if (appInfo != null) {
+ shortcutInfo.updateIcon(mIconCache);
+ shortcutInfo.title = appInfo.title.toString();
+ shortcutInfo.contentDescription = appInfo.contentDescription;
+ infoUpdated = true;
+ }
+
+ if (infoUpdated) {
+ BubbleTextView shortcut = (BubbleTextView) v;
+ shortcut.applyFromShortcutInfo(shortcutInfo,
+ mIconCache, true, promiseStateChanged);
+
+ if (parent != null) {
+ parent.invalidate();
+ }
+ }
}
}
// process all the shortcuts
@@ -4838,6 +4893,12 @@ public class Workspace extends SmoothPagedView
}
});
+ if (!iconsToRemove.isEmpty()) {
+ for (Map.Entry<UserHandleCompat, HashSet<ComponentName>> entry :
+ iconsToRemove.entrySet()) {
+ removeItemsByComponentName(entry.getValue(), entry.getKey());
+ }
+ }
restorePendingWidgets(pkgNames);
}
@@ -4855,12 +4916,18 @@ public class Workspace extends SmoothPagedView
mapOverItems(MAP_RECURSE, new ItemOperator() {
@Override
public boolean evaluate(ItemInfo info, View v, View parent) {
- if (info instanceof ShortcutInfo
- && ((ShortcutInfo) info).isPromiseFor(installInfo.packageName)
- && v instanceof BubbleTextView) {
- ((ShortcutInfo) info).setProgress(installInfo.progress);
- ((ShortcutInfo) info).setState(installInfo.state);
- ((BubbleTextView)v).applyState();
+ if (info instanceof ShortcutInfo && v instanceof BubbleTextView) {
+ ShortcutInfo si = (ShortcutInfo) info;
+ ComponentName cn = si.getTargetComponent();
+ if (si.isPromise() && (cn != null)
+ && installInfo.packageName.equals(cn.getPackageName())) {
+ si.setInstallProgress(installInfo.progress);
+ if (installInfo.state == PackageInstallerCompat.STATUS_FAILED) {
+ // Mark this info as broken.
+ si.status &= ~ShortcutInfo.FLAG_INSTALL_SESSION_ACTIVE;
+ }
+ ((BubbleTextView)v).applyState(false);
+ }
} else if (v instanceof PendingAppWidgetHostView
&& info instanceof LauncherAppWidgetInfo
&& ((LauncherAppWidgetInfo) info).providerName.getPackageName()
@@ -4874,7 +4941,7 @@ public class Workspace extends SmoothPagedView
}
});
- if (installInfo.state == ShortcutInfo.PACKAGE_STATE_DEFAULT) {
+ if (installInfo.state == PackageInstallerCompat.STATUS_INSTALLED) {
completedPackages.add(installInfo.packageName);
}
}
diff --git a/src/com/android/launcher3/compat/PackageInstallerCompat.java b/src/com/android/launcher3/compat/PackageInstallerCompat.java
index 89a2157eb..0ae52bd23 100644
--- a/src/com/android/launcher3/compat/PackageInstallerCompat.java
+++ b/src/com/android/launcher3/compat/PackageInstallerCompat.java
@@ -22,6 +22,10 @@ import com.android.launcher3.Utilities;
public abstract class PackageInstallerCompat {
+ public static final int STATUS_INSTALLED = 0;
+ public static final int STATUS_INSTALLING = 1;
+ public static final int STATUS_FAILED = 2;
+
private static final Object sInstanceLock = new Object();
private static PackageInstallerCompat sInstance;
@@ -38,6 +42,8 @@ public abstract class PackageInstallerCompat {
}
}
+ public abstract void updateActiveSessionCache();
+
public abstract void onPause();
public abstract void onResume();
diff --git a/src/com/android/launcher3/compat/PackageInstallerCompatV16.java b/src/com/android/launcher3/compat/PackageInstallerCompatV16.java
index 6a2a02e48..4cc6fc12f 100644
--- a/src/com/android/launcher3/compat/PackageInstallerCompatV16.java
+++ b/src/com/android/launcher3/compat/PackageInstallerCompatV16.java
@@ -22,7 +22,6 @@ import android.text.TextUtils;
import android.util.Log;
import com.android.launcher3.LauncherAppState;
-import com.android.launcher3.ShortcutInfo;
import org.json.JSONException;
import org.json.JSONObject;
@@ -77,6 +76,9 @@ public class PackageInstallerCompatV16 extends PackageInstallerCompat {
@Override
public void onStop() { }
+ @Override
+ public void updateActiveSessionCache() { }
+
private void replayUpdates() {
if (DEBUG) Log.d(TAG, "updates resumed");
LauncherAppState app = LauncherAppState.getInstanceNoCreate();
@@ -107,7 +109,7 @@ public class PackageInstallerCompatV16 extends PackageInstallerCompat {
PackageInstallInfo installInfo = new PackageInstallInfo(packageName);
installInfo.progress = progress;
installInfo.state = state;
- if (state == ShortcutInfo.PACKAGE_STATE_DEFAULT) {
+ if (state == STATUS_INSTALLED) {
// no longer necessary to track this package
editor.remove(packageName);
if (DEBUG) Log.d(TAG, "no longer tracking " + packageName);
@@ -123,7 +125,7 @@ public class PackageInstallerCompatV16 extends PackageInstallerCompat {
if (!mUseQueue) {
if (mReplayPending) {
replayUpdates();
- } else {
+ } else if (state != STATUS_INSTALLED) {
LauncherAppState app = LauncherAppState.getInstanceNoCreate();
ArrayList<PackageInstallInfo> update = new ArrayList<PackageInstallInfo>();
update.add(installInfo);
diff --git a/src/com/android/launcher3/compat/PackageInstallerCompatVL.java b/src/com/android/launcher3/compat/PackageInstallerCompatVL.java
index c78ab9900..5d016a838 100644
--- a/src/com/android/launcher3/compat/PackageInstallerCompatVL.java
+++ b/src/com/android/launcher3/compat/PackageInstallerCompatVL.java
@@ -23,8 +23,8 @@ import android.content.pm.PackageInstaller.SessionInfo;
import android.util.Log;
import android.util.SparseArray;
+import com.android.launcher3.IconCache;
import com.android.launcher3.LauncherAppState;
-import com.android.launcher3.ShortcutInfo;
import java.util.ArrayList;
@@ -35,12 +35,14 @@ public class PackageInstallerCompatVL extends PackageInstallerCompat {
private final SparseArray<SessionInfo> mPendingReplays = new SparseArray<SessionInfo>();
private final PackageInstaller mInstaller;
+ private final IconCache mCache;
private boolean mResumed;
private boolean mBound;
PackageInstallerCompatVL(Context context) {
mInstaller = context.getPackageManager().getPackageInstaller();
+ mCache = LauncherAppState.getInstance().getIconCache();
mResumed = false;
mBound = false;
@@ -53,6 +55,22 @@ public class PackageInstallerCompatVL extends PackageInstallerCompat {
}
@Override
+ public void updateActiveSessionCache() {
+ UserHandleCompat user = UserHandleCompat.myUserHandle();
+ for (SessionInfo info : mInstaller.getAllSessions()) {
+ addSessionInfoToCahce(info, user);
+ }
+ }
+
+ private void addSessionInfoToCahce(SessionInfo info, UserHandleCompat user) {
+ String packageName = info.getAppPackageName();
+ if (packageName != null) {
+ mCache.cachePackageInstallInfo(packageName, user, info.getAppIcon(),
+ info.getAppLabel());
+ }
+ }
+
+ @Override
public void onStop() {
mInstaller.removeSessionCallback(mCallback);
}
@@ -98,14 +116,14 @@ public class PackageInstallerCompatVL extends PackageInstallerCompat {
}
ArrayList<PackageInstallInfo> updates = new ArrayList<PackageInstallInfo>();
- if (newInfo != null) {
+ if ((newInfo != null) && (newInfo.state != STATUS_INSTALLED)) {
updates.add(newInfo);
}
- for (int i = mPendingReplays.size() - 1; i > 0; i--) {
+ for (int i = mPendingReplays.size() - 1; i >= 0; i--) {
SessionInfo session = mPendingReplays.valueAt(i);
if (session.getAppPackageName() != null) {
updates.add(new PackageInstallInfo(session.getAppPackageName(),
- ShortcutInfo.PACKAGE_STATE_INSTALLING,
+ STATUS_INSTALLING,
(int) (session.getProgress() * 100)));
}
}
@@ -121,6 +139,7 @@ public class PackageInstallerCompatVL extends PackageInstallerCompat {
public void onCreated(int sessionId) {
SessionInfo session = mInstaller.getSessionInfo(sessionId);
if (session != null) {
+ addSessionInfoToCahce(session, UserHandleCompat.myUserHandle());
mPendingReplays.put(sessionId, session);
replayUpdates(null);
}
@@ -135,8 +154,7 @@ public class PackageInstallerCompatVL extends PackageInstallerCompat {
// need to store this record for future updates, as the app list will get
// refreshed on resume.
replayUpdates(new PackageInstallInfo(session.getAppPackageName(),
- success ? ShortcutInfo.PACKAGE_STATE_DEFAULT
- : ShortcutInfo.PACKAGE_STATE_ERROR, 0));
+ success ? STATUS_INSTALLED : STATUS_FAILED, 0));
}
}