Merge "Fixing backup restore" into ub-launcher3-burnaby

This commit is contained in:
Sunny Goyal 2015-06-26 01:34:44 +00:00 committed by Android (Google) Code Review
commit 187f9665f6
8 changed files with 178 additions and 98 deletions

View File

@ -46,10 +46,12 @@ import com.android.launcher3.model.PackageItemInfo;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.Thunk;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.Stack;
/**
@ -215,7 +217,7 @@ public class IconCache {
new String[] {packageName + "/%", Long.toString(userSerial)});
}
public void updateDbIcons() {
public void updateDbIcons(Set<String> ignorePackagesForMainUser) {
// Remove all active icon update tasks.
mWorkerHandler.removeCallbacksAndMessages(ICON_UPDATE_TOKEN);
@ -231,7 +233,8 @@ public class IconCache {
// Update icon cache. This happens in segments and {@link #onPackageIconsUpdated}
// is called by the icon cache when the job is complete.
updateDBIcons(user, apps);
updateDBIcons(user, apps, UserHandleCompat.myUserHandle().equals(user)
? ignorePackagesForMainUser : Collections.<String>emptySet());
}
}
@ -240,7 +243,8 @@ public class IconCache {
* the DB and are updated.
* @return The set of packages for which icons have updated.
*/
private void updateDBIcons(UserHandleCompat user, List<LauncherActivityInfoCompat> apps) {
private void updateDBIcons(UserHandleCompat user, List<LauncherActivityInfoCompat> apps,
Set<String> ignorePackages) {
long userSerial = mUserManager.getSerialNumberForUser(user);
PackageManager pm = mContext.getPackageManager();
HashMap<String, PackageInfo> pkgInfoMap = new HashMap<String, PackageInfo>();
@ -275,8 +279,10 @@ public class IconCache {
ComponentName component = ComponentName.unflattenFromString(cn);
PackageInfo info = pkgInfoMap.get(component.getPackageName());
if (info == null) {
if (!ignorePackages.contains(component.getPackageName())) {
remove(component, user);
itemsToRemove.add(c.getInt(rowIndex));
}
continue;
}
if ((info.applicationInfo.flags & ApplicationInfo.FLAG_IS_DATA_ONLY) != 0) {

View File

@ -432,10 +432,4 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
.fromResolveInfo(info, original.mContext);
return new PendingInstallShortcutInfo(launcherInfo, original.mContext);
}
public static boolean isLauncherActivity(Intent intent, Context context) {
Intent data = new Intent().putExtra(Intent.EXTRA_SHORTCUT_INTENT, intent);
PendingInstallShortcutInfo info = new PendingInstallShortcutInfo(data, context);
return convertToLauncherActivityIfPossible(info).isLuncherActivity();
}
}

View File

@ -771,22 +771,7 @@ public class LauncherBackupHelper implements BackupHelper {
favorite.spanX = c.getInt(SPANX_INDEX);
favorite.spanY = c.getInt(SPANY_INDEX);
favorite.iconType = c.getInt(ICON_TYPE_INDEX);
if (favorite.iconType == Favorites.ICON_TYPE_RESOURCE) {
String iconPackage = c.getString(ICON_PACKAGE_INDEX);
if (!TextUtils.isEmpty(iconPackage)) {
favorite.iconPackage = iconPackage;
}
String iconResource = c.getString(ICON_RESOURCE_INDEX);
if (!TextUtils.isEmpty(iconResource)) {
favorite.iconResource = iconResource;
}
}
if (favorite.iconType == Favorites.ICON_TYPE_BITMAP) {
byte[] blob = c.getBlob(ICON_INDEX);
if (blob != null && blob.length > 0) {
favorite.icon = blob;
}
}
String title = c.getString(TITLE_INDEX);
if (!TextUtils.isEmpty(title)) {
favorite.title = title;
@ -809,6 +794,22 @@ public class LauncherBackupHelper implements BackupHelper {
if (!TextUtils.isEmpty(appWidgetProvider)) {
favorite.appWidgetProvider = appWidgetProvider;
}
} else if (favorite.itemType == Favorites.ITEM_TYPE_SHORTCUT) {
if (favorite.iconType == Favorites.ICON_TYPE_RESOURCE) {
String iconPackage = c.getString(ICON_PACKAGE_INDEX);
if (!TextUtils.isEmpty(iconPackage)) {
favorite.iconPackage = iconPackage;
}
String iconResource = c.getString(ICON_RESOURCE_INDEX);
if (!TextUtils.isEmpty(iconResource)) {
favorite.iconResource = iconResource;
}
}
byte[] blob = c.getBlob(ICON_INDEX);
if (blob != null && blob.length > 0) {
favorite.icon = blob;
}
}
if (isReplaceableHotseatItem(favorite)) {
@ -852,14 +853,16 @@ public class LauncherBackupHelper implements BackupHelper {
values.put(Favorites.CELLY, favorite.cellY);
values.put(Favorites.SPANX, favorite.spanX);
values.put(Favorites.SPANY, favorite.spanY);
if (favorite.itemType == Favorites.ITEM_TYPE_SHORTCUT) {
values.put(Favorites.ICON_TYPE, favorite.iconType);
if (favorite.iconType == Favorites.ICON_TYPE_RESOURCE) {
values.put(Favorites.ICON_PACKAGE, favorite.iconPackage);
values.put(Favorites.ICON_RESOURCE, favorite.iconResource);
}
if (favorite.iconType == Favorites.ICON_TYPE_BITMAP) {
values.put(Favorites.ICON, favorite.icon);
}
if (!TextUtils.isEmpty(favorite.title)) {
values.put(Favorites.TITLE, favorite.title);
} else {

View File

@ -57,6 +57,7 @@ import com.android.launcher3.compat.UserHandleCompat;
import com.android.launcher3.compat.UserManagerCompat;
import com.android.launcher3.model.WidgetsModel;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.CursorIconInfo;
import com.android.launcher3.util.LongArrayMap;
import com.android.launcher3.util.ManagedProfileHeuristic;
import com.android.launcher3.util.Thunk;
@ -903,11 +904,10 @@ public class LauncherModel extends BroadcastReceiver
@Thunk boolean shortcutExists(Context context, Intent intent, UserHandleCompat user) {
assertWorkspaceLoaded();
final String intentWithPkg, intentWithoutPkg;
final String packageName;
if (intent.getComponent() != null) {
// If component is not null, an intent with null package will produce
// the same result and should also be a match.
packageName = intent.getComponent().getPackageName();
String packageName = intent.getComponent().getPackageName();
if (intent.getPackage() != null) {
intentWithPkg = intent.toUri(0);
intentWithoutPkg = new Intent(intent).setPackage(null).toUri(0);
@ -918,15 +918,16 @@ public class LauncherModel extends BroadcastReceiver
} else {
intentWithPkg = intent.toUri(0);
intentWithoutPkg = intent.toUri(0);
packageName = intent.getPackage();
}
synchronized (sBgLock) {
for (ItemInfo item : sBgItemsIdMap) {
if (item instanceof ShortcutInfo) {
ShortcutInfo info = (ShortcutInfo) item;
if (info.getIntent() != null && info.user.equals(user)) {
String s = info.getIntent().toUri(0);
Intent targetIntent = info.promisedIntent == null
? info.intent : info.promisedIntent;
if (targetIntent != null && info.user.equals(user)) {
String s = targetIntent.toUri(0);
if (intentWithPkg.equals(s) || intentWithoutPkg.equals(s)) {
return true;
}
@ -1793,13 +1794,6 @@ public class LauncherModel extends BroadcastReceiver
(LauncherSettings.Favorites.INTENT);
final int titleIndex = c.getColumnIndexOrThrow
(LauncherSettings.Favorites.TITLE);
final int iconTypeIndex = c.getColumnIndexOrThrow(
LauncherSettings.Favorites.ICON_TYPE);
final int iconIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON);
final int iconPackageIndex = c.getColumnIndexOrThrow(
LauncherSettings.Favorites.ICON_PACKAGE);
final int iconResourceIndex = c.getColumnIndexOrThrow(
LauncherSettings.Favorites.ICON_RESOURCE);
final int containerIndex = c.getColumnIndexOrThrow(
LauncherSettings.Favorites.CONTAINER);
final int itemTypeIndex = c.getColumnIndexOrThrow(
@ -1826,6 +1820,7 @@ public class LauncherModel extends BroadcastReceiver
LauncherSettings.Favorites.PROFILE_ID);
final int optionsIndex = c.getColumnIndexOrThrow(
LauncherSettings.Favorites.OPTIONS);
final CursorIconInfo cursorIconInfo = new CursorIconInfo(c);
final LongSparseArray<UserHandleCompat> allUsers = new LongSparseArray<>();
for (UserHandleCompat user : mUserManager.getUserProfiles()) {
@ -1991,7 +1986,8 @@ public class LauncherModel extends BroadcastReceiver
if (itemReplaced) {
if (user.equals(UserHandleCompat.myUserHandle())) {
info = getAppShortcutInfo(manager, intent, user, context, null,
iconIndex, titleIndex, false, useLowResIcon);
cursorIconInfo.iconIndex, titleIndex,
false, useLowResIcon);
} else {
// Don't replace items for other profiles.
itemsToRemove.add(id);
@ -2003,7 +1999,7 @@ public class LauncherModel extends BroadcastReceiver
"constructing info for partially restored package",
true);
info = getRestoredItemInfo(c, titleIndex, intent,
promiseType);
promiseType, cursorIconInfo, context);
intent = getRestoredItemIntent(c, context, intent);
} else {
// Don't restore items for other profiles.
@ -2013,11 +2009,10 @@ public class LauncherModel extends BroadcastReceiver
} else if (itemType ==
LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
info = getAppShortcutInfo(manager, intent, user, context, c,
iconIndex, titleIndex, allowMissingTarget, useLowResIcon);
cursorIconInfo.iconIndex, titleIndex,
allowMissingTarget, useLowResIcon);
} else {
info = getShortcutInfo(c, context, iconTypeIndex,
iconPackageIndex, iconResourceIndex, iconIndex,
titleIndex);
info = getShortcutInfo(c, context, titleIndex, cursorIconInfo);
// App shortcuts that used to be automatically added to Launcher
// didn't always have the correct intent flags set, so do that
@ -2043,6 +2038,9 @@ public class LauncherModel extends BroadcastReceiver
info.spanX = 1;
info.spanY = 1;
info.intent.putExtra(ItemInfo.EXTRA_PROFILE, serialNumber);
if (info.promisedIntent != null) {
info.promisedIntent.putExtra(ItemInfo.EXTRA_PROFILE, serialNumber);
}
info.isDisabled = disabledState;
if (isSafeMode && !Utilities.isSystemApp(context, intent)) {
info.isDisabled |= ShortcutInfo.FLAG_DISABLED_SAFEMODE;
@ -2687,7 +2685,7 @@ public class LauncherModel extends BroadcastReceiver
return;
}
}
mIconCache.updateDbIcons();
updateIconCache();
synchronized (LoaderTask.this) {
if (mStopped) {
return;
@ -2699,6 +2697,27 @@ public class LauncherModel extends BroadcastReceiver
}
}
private void updateIconCache() {
// Ignore packages which have a promise icon.
HashSet<String> packagesToIgnore = new HashSet<>();
synchronized (sBgLock) {
for (ItemInfo info : sBgItemsIdMap) {
if (info instanceof ShortcutInfo) {
ShortcutInfo si = (ShortcutInfo) info;
if (si.isPromise() && si.getTargetComponent() != null) {
packagesToIgnore.add(si.getTargetComponent().getPackageName());
}
} else if (info instanceof LauncherAppWidgetInfo) {
LauncherAppWidgetInfo lawi = (LauncherAppWidgetInfo) info;
if (lawi.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY)) {
packagesToIgnore.add(lawi.providerName.getPackageName());
}
}
}
}
mIconCache.updateDbIcons(packagesToIgnore);
}
private void onlyBindAllApps() {
final Callbacks oldCallbacks = mCallbacks.get();
if (oldCallbacks == null) {
@ -3360,20 +3379,27 @@ 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,
int promiseType) {
public ShortcutInfo getRestoredItemInfo(Cursor c, int titleIndex, Intent intent,
int promiseType, CursorIconInfo iconInfo, Context context) {
final ShortcutInfo info = new ShortcutInfo();
info.user = UserHandleCompat.myUserHandle();
Bitmap icon = iconInfo.loadIcon(c, info, context);
// the fallback icon
if (icon == null) {
mIconCache.getTitleAndIcon(info, intent, info.user, false /* useLowResIcon */);
} else {
info.setIcon(icon);
}
if ((promiseType & ShortcutInfo.FLAG_RESTORED_ICON) != 0) {
String title = (cursor != null) ? cursor.getString(titleIndex) : null;
String title = (c != null) ? c.getString(titleIndex) : null;
if (!TextUtils.isEmpty(title)) {
info.title = Utilities.trim(title);
}
} else if ((promiseType & ShortcutInfo.FLAG_AUTOINTALL_ICON) != 0) {
if (TextUtils.isEmpty(info.title)) {
info.title = (cursor != null) ? Utilities.trim(cursor.getString(titleIndex)) : "";
info.title = (c != null) ? Utilities.trim(c.getString(titleIndex)) : "";
}
} else {
throw new InvalidParameterException("Invalid restoreType " + promiseType);
@ -3506,10 +3532,7 @@ public class LauncherModel extends BroadcastReceiver
* Make an ShortcutInfo object for a shortcut that isn't an application.
*/
@Thunk ShortcutInfo getShortcutInfo(Cursor c, Context context,
int iconTypeIndex, int iconPackageIndex, int iconResourceIndex, int iconIndex,
int titleIndex) {
Bitmap icon = null;
int titleIndex, CursorIconInfo iconInfo) {
final ShortcutInfo info = new ShortcutInfo();
// Non-app shortcuts are only supported for current user.
info.user = UserHandleCompat.myUserHandle();
@ -3519,40 +3542,12 @@ public class LauncherModel extends BroadcastReceiver
info.title = Utilities.trim(c.getString(titleIndex));
int iconType = c.getInt(iconTypeIndex);
switch (iconType) {
case LauncherSettings.Favorites.ICON_TYPE_RESOURCE:
String packageName = c.getString(iconPackageIndex);
String resourceName = c.getString(iconResourceIndex);
info.customIcon = false;
// the resource
icon = Utilities.createIconBitmap(packageName, resourceName, context);
// the db
if (icon == null) {
icon = Utilities.createIconBitmap(c, iconIndex, context);
}
Bitmap icon = iconInfo.loadIcon(c, info, context);
// the fallback icon
if (icon == null) {
icon = mIconCache.getDefaultIcon(info.user);
info.usingFallbackIcon = true;
}
break;
case LauncherSettings.Favorites.ICON_TYPE_BITMAP:
icon = Utilities.createIconBitmap(c, iconIndex, context);
if (icon == null) {
icon = mIconCache.getDefaultIcon(info.user);
info.customIcon = false;
info.usingFallbackIcon = true;
} else {
info.customIcon = true;
}
break;
default:
icon = mIconCache.getDefaultIcon(info.user);
info.usingFallbackIcon = true;
info.customIcon = false;
break;
}
info.setIcon(icon);
return info;
}

View File

@ -766,7 +766,7 @@ public class LauncherProvider extends ContentProvider {
continue;
}
if (!InstallShortcutReceiver.isLauncherActivity(intent, mContext)) {
if (!Utilities.isLauncherAppTarget(intent)) {
continue;
}

View File

@ -76,8 +76,9 @@ public class ShortcutInfo extends ItemInfo {
/**
* Indicates whether the icon comes from an application's resource (if false)
* or from a custom Bitmap (if true.)
* TODO: remove this flag
*/
boolean customIcon;
public boolean customIcon;
/**
* Indicates whether we're using the default fallback icon instead of something from the
@ -94,7 +95,7 @@ public class ShortcutInfo extends ItemInfo {
* If isShortcut=true and customIcon=false, this contains a reference to the
* shortcut icon as an application's resource.
*/
Intent.ShortcutIconResource iconResource;
public Intent.ShortcutIconResource iconResource;
/**
* The application icon.

View File

@ -45,6 +45,7 @@ import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.PaintDrawable;
import android.os.Build;
import android.os.Bundle;
import android.os.Process;
import android.text.TextUtils;
import android.util.DisplayMetrics;
@ -62,6 +63,7 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Locale;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -676,14 +678,23 @@ public final class Utilities {
* @param launchIntent The intent that will be launched when the shortcut is clicked.
*/
public static boolean isLauncherAppTarget(Intent launchIntent) {
return launchIntent != null
if (launchIntent != null
&& Intent.ACTION_MAIN.equals(launchIntent.getAction())
&& launchIntent.getComponent() != null
&& launchIntent.getCategories() != null
&& launchIntent.getCategories().size() == 1
&& launchIntent.hasCategory(Intent.CATEGORY_LAUNCHER)
&& launchIntent.getExtras() == null
&& TextUtils.isEmpty(launchIntent.getDataString());
&& TextUtils.isEmpty(launchIntent.getDataString())) {
// An app target can either have no extra or have ItemInfo.EXTRA_PROFILE.
Bundle extras = launchIntent.getExtras();
if (extras == null) {
return true;
} else {
Set<String> keys = extras.keySet();
return keys.size() == 1 && keys.contains(ItemInfo.EXTRA_PROFILE);
}
};
return false;
}
public static float dpiFromPx(int size, DisplayMetrics metrics){

View File

@ -0,0 +1,70 @@
/*
* Copyright (C) 2015 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.launcher3.util;
import android.content.Context;
import android.content.Intent.ShortcutIconResource;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.text.TextUtils;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.ShortcutInfo;
import com.android.launcher3.Utilities;
/**
* Utility class to load icon from a cursor.
*/
public class CursorIconInfo {
public final int iconTypeIndex;
public final int iconPackageIndex;
public final int iconResourceIndex;
public final int iconIndex;
public CursorIconInfo(Cursor c) {
iconTypeIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON_TYPE);
iconIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON);
iconPackageIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON_PACKAGE);
iconResourceIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON_RESOURCE);
}
public Bitmap loadIcon(Cursor c, ShortcutInfo info, Context context) {
Bitmap icon = null;
int iconType = c.getInt(iconTypeIndex);
switch (iconType) {
case LauncherSettings.Favorites.ICON_TYPE_RESOURCE:
String packageName = c.getString(iconPackageIndex);
String resourceName = c.getString(iconResourceIndex);
if (!TextUtils.isEmpty(packageName) || !TextUtils.isEmpty(resourceName)) {
info.iconResource = new ShortcutIconResource();
info.iconResource.packageName = packageName;
info.iconResource.resourceName = resourceName;
icon = Utilities.createIconBitmap(packageName, resourceName, context);
}
if (icon == null) {
// Failed to load from resource, try loading from DB.
icon = Utilities.createIconBitmap(c, iconIndex, context);
}
break;
case LauncherSettings.Favorites.ICON_TYPE_BITMAP:
icon = Utilities.createIconBitmap(c, iconIndex, context);
info.customIcon = icon != null;
break;
}
return icon;
}
}