Merge "Updating ItemInfo objects in the worker thread" into ub-now-queens
This commit is contained in:
@@ -26,10 +26,16 @@ import android.graphics.Rect;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.util.Log;
|
||||
import android.view.*;
|
||||
import android.view.HapticFeedbackConstants;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.VelocityTracker;
|
||||
import android.view.View;
|
||||
import android.view.ViewConfiguration;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
|
||||
/**
|
||||
* Class for initiating a drag within a view or across multiple views.
|
||||
@@ -318,18 +324,17 @@ public class DragController {
|
||||
}
|
||||
endDrag();
|
||||
}
|
||||
public void onAppsRemoved(final ArrayList<String> packageNames, ArrayList<AppInfo> appInfos) {
|
||||
public void onAppsRemoved(final ArrayList<String> packageNames, HashSet<ComponentName> cns) {
|
||||
// Cancel the current drag if we are removing an app that we are dragging
|
||||
if (mDragObject != null) {
|
||||
Object rawDragInfo = mDragObject.dragInfo;
|
||||
if (rawDragInfo instanceof ShortcutInfo) {
|
||||
ShortcutInfo dragInfo = (ShortcutInfo) rawDragInfo;
|
||||
for (AppInfo info : appInfos) {
|
||||
for (ComponentName componentName : cns) {
|
||||
// Added null checks to prevent NPE we've seen in the wild
|
||||
if (dragInfo != null &&
|
||||
dragInfo.intent != null && info != null) {
|
||||
if (dragInfo != null && dragInfo.intent != null) {
|
||||
ComponentName cn = dragInfo.intent.getComponent();
|
||||
boolean isSameComponent = cn != null && (cn.equals(info.componentName) ||
|
||||
boolean isSameComponent = cn != null && (cn.equals(componentName) ||
|
||||
packageNames.contains(cn.getPackageName()));
|
||||
if (isSameComponent) {
|
||||
cancelDrag();
|
||||
|
||||
@@ -125,6 +125,7 @@ import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
@@ -2063,7 +2064,6 @@ public class Launcher extends Activity
|
||||
mWorkspace = null;
|
||||
mDragController = null;
|
||||
|
||||
PackageInstallerCompat.getInstance(this).onStop();
|
||||
LauncherAnimUtils.onDestroyActivity();
|
||||
|
||||
if (mLauncherCallbacks != null) {
|
||||
@@ -4858,33 +4858,54 @@ public class Launcher extends Activity
|
||||
return;
|
||||
}
|
||||
|
||||
if (mWorkspace != null) {
|
||||
mWorkspace.updateShortcutsAndWidgets(apps);
|
||||
}
|
||||
|
||||
if (!LauncherAppState.isDisableAllApps() &&
|
||||
mAppsCustomizeContent != null) {
|
||||
mAppsCustomizeContent.updateApps(apps);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindWidgetsRestored(final ArrayList<LauncherAppWidgetInfo> widgets) {
|
||||
Runnable r = new Runnable() {
|
||||
public void run() {
|
||||
bindWidgetsRestored(widgets);
|
||||
}
|
||||
};
|
||||
if (waitUntilResume(r)) {
|
||||
return;
|
||||
}
|
||||
mWorkspace.widgetsRestored(widgets);
|
||||
}
|
||||
|
||||
/**
|
||||
* Some shortcuts were updated in the background.
|
||||
*
|
||||
* Implementation of the method from LauncherModel.Callbacks.
|
||||
*/
|
||||
public void bindShortcutsUpdated(final ArrayList<ShortcutInfo> shortcuts) {
|
||||
@Override
|
||||
public void bindShortcutsChanged(final ArrayList<ShortcutInfo> updated,
|
||||
final ArrayList<ShortcutInfo> removed, final UserHandleCompat user) {
|
||||
Runnable r = new Runnable() {
|
||||
public void run() {
|
||||
bindShortcutsUpdated(shortcuts);
|
||||
bindShortcutsChanged(updated, removed, user);
|
||||
}
|
||||
};
|
||||
if (waitUntilResume(r)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mWorkspace != null) {
|
||||
mWorkspace.updateShortcuts(shortcuts);
|
||||
if (!updated.isEmpty()) {
|
||||
mWorkspace.updateShortcuts(updated);
|
||||
}
|
||||
|
||||
if (!removed.isEmpty()) {
|
||||
HashSet<ComponentName> removedComponents = new HashSet<ComponentName>();
|
||||
for (ShortcutInfo si : removed) {
|
||||
removedComponents.add(si.getTargetComponent());
|
||||
}
|
||||
mWorkspace.removeItemsByComponentName(removedComponents, user);
|
||||
// Notify the drag controller
|
||||
mDragController.onAppsRemoved(new ArrayList<String>(), removedComponents);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4935,19 +4956,23 @@ public class Launcher extends Activity
|
||||
}
|
||||
|
||||
if (reason == 0) {
|
||||
HashSet<ComponentName> removedComponents = new HashSet<ComponentName>();
|
||||
for (AppInfo info : appInfos) {
|
||||
removedComponents.add(info.componentName);
|
||||
}
|
||||
if (!packageNames.isEmpty()) {
|
||||
mWorkspace.removeItemsByPackageName(packageNames, user);
|
||||
}
|
||||
if (!appInfos.isEmpty()) {
|
||||
mWorkspace.removeItemsByApplicationInfo(appInfos, user);
|
||||
if (!removedComponents.isEmpty()) {
|
||||
mWorkspace.removeItemsByComponentName(removedComponents, user);
|
||||
}
|
||||
// Notify the drag controller
|
||||
mDragController.onAppsRemoved(packageNames, removedComponents);
|
||||
|
||||
} else {
|
||||
mWorkspace.disableShortcutsByPackageName(packageNames, user, reason);
|
||||
}
|
||||
|
||||
// Notify the drag controller
|
||||
mDragController.onAppsRemoved(packageNames, appInfos);
|
||||
|
||||
// Update AllApps
|
||||
if (!LauncherAppState.isDisableAllApps() &&
|
||||
mAppsCustomizeContent != null) {
|
||||
|
||||
@@ -29,6 +29,7 @@ import android.os.Handler;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.launcher3.compat.LauncherAppsCompat;
|
||||
import com.android.launcher3.compat.PackageInstallerCompat;
|
||||
import com.android.launcher3.compat.PackageInstallerCompat.PackageInstallInfo;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
@@ -134,6 +135,7 @@ public class LauncherAppState implements DeviceProfile.DeviceProfileCallbacks {
|
||||
sContext.unregisterReceiver(mModel);
|
||||
final LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(sContext);
|
||||
launcherApps.removeOnAppsChangedCallback(mModel);
|
||||
PackageInstallerCompat.getInstance(sContext).onStop();
|
||||
|
||||
ContentResolver resolver = sContext.getContentResolver();
|
||||
resolver.unregisterContentObserver(mFavoritesObserver);
|
||||
|
||||
@@ -198,7 +198,9 @@ public class LauncherModel extends BroadcastReceiver
|
||||
ArrayList<ItemInfo> addAnimated,
|
||||
ArrayList<AppInfo> addedApps);
|
||||
public void bindAppsUpdated(ArrayList<AppInfo> apps);
|
||||
public void bindShortcutsUpdated(ArrayList<ShortcutInfo> shortcuts);
|
||||
public void bindShortcutsChanged(ArrayList<ShortcutInfo> updated,
|
||||
ArrayList<ShortcutInfo> removed, UserHandleCompat user);
|
||||
public void bindWidgetsRestored(ArrayList<LauncherAppWidgetInfo> widgets);
|
||||
public void updatePackageState(ArrayList<PackageInstallInfo> installInfo);
|
||||
public void updatePackageBadge(String packageName);
|
||||
public void bindComponentsRemoved(ArrayList<String> packageNames,
|
||||
@@ -373,15 +375,6 @@ public class LauncherModel extends BroadcastReceiver
|
||||
return;
|
||||
}
|
||||
|
||||
final ArrayList<AppInfo> restoredAppsFinal = new ArrayList<AppInfo>();
|
||||
Iterator<AppInfo> iter = allAppsApps.iterator();
|
||||
while (iter.hasNext()) {
|
||||
ItemInfo a = iter.next();
|
||||
if (LauncherModel.appWasPromise(ctx, a.getIntent(), a.user)) {
|
||||
restoredAppsFinal.add((AppInfo) a);
|
||||
}
|
||||
}
|
||||
|
||||
// Process the newly added applications and add them to the database first
|
||||
Runnable r = new Runnable() {
|
||||
public void run() {
|
||||
@@ -389,16 +382,6 @@ public class LauncherModel extends BroadcastReceiver
|
||||
public void run() {
|
||||
Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;
|
||||
if (callbacks == cb && cb != null) {
|
||||
if (!restoredAppsFinal.isEmpty()) {
|
||||
for (AppInfo info : restoredAppsFinal) {
|
||||
final Intent intent = info.getIntent();
|
||||
if (intent != null) {
|
||||
mIconCache.deletePreloadedIcon(intent.getComponent(),
|
||||
info.user);
|
||||
}
|
||||
}
|
||||
callbacks.bindAppsUpdated(restoredAppsFinal);
|
||||
}
|
||||
callbacks.bindAppsAdded(null, null, null, allAppsApps);
|
||||
}
|
||||
}
|
||||
@@ -423,7 +406,6 @@ public class LauncherModel extends BroadcastReceiver
|
||||
public void run() {
|
||||
final ArrayList<ItemInfo> addedShortcutsFinal = new ArrayList<ItemInfo>();
|
||||
final ArrayList<Long> addedWorkspaceScreensFinal = new ArrayList<Long>();
|
||||
final ArrayList<AppInfo> restoredAppsFinal = new ArrayList<AppInfo>();
|
||||
|
||||
// Get the list of workspace screens. We need to append to this list and
|
||||
// can not use sBgWorkspaceScreens because loadWorkspace() may not have been
|
||||
@@ -443,12 +425,7 @@ public class LauncherModel extends BroadcastReceiver
|
||||
final Intent launchIntent = a.getIntent();
|
||||
|
||||
// Short-circuit this logic if the icon exists somewhere on the workspace
|
||||
if (LauncherModel.shortcutExists(context, name, launchIntent)) {
|
||||
// Only InstallShortcutReceiver sends us shortcutInfos, ignore them
|
||||
if (a instanceof AppInfo &&
|
||||
LauncherModel.appWasPromise(context, launchIntent, a.user)) {
|
||||
restoredAppsFinal.add((AppInfo) a);
|
||||
}
|
||||
if (shortcutExists(context, name, launchIntent)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -524,9 +501,6 @@ public class LauncherModel extends BroadcastReceiver
|
||||
}
|
||||
callbacks.bindAppsAdded(addedWorkspaceScreensFinal,
|
||||
addNotAnimated, addAnimated, null);
|
||||
if (!restoredAppsFinal.isEmpty()) {
|
||||
callbacks.bindAppsUpdated(restoredAppsFinal);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -901,17 +875,6 @@ public class LauncherModel extends BroadcastReceiver
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the promise shortcuts with the same package name exists on the workspace.
|
||||
*/
|
||||
static boolean appWasPromise(Context context, Intent intent, UserHandleCompat user) {
|
||||
final ComponentName component = intent.getComponent();
|
||||
if (component == null) {
|
||||
return false;
|
||||
}
|
||||
return !getItemsByPackageName(component.getPackageName(), user).isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an ItemInfo array containing all the items in the LauncherModel.
|
||||
* The ItemInfo.id is not set through this function.
|
||||
@@ -1111,7 +1074,7 @@ public class LauncherModel extends BroadcastReceiver
|
||||
* @param context
|
||||
* @param item
|
||||
*/
|
||||
static void deleteItemsFromDatabase(Context context, final ArrayList<ItemInfo> items) {
|
||||
static void deleteItemsFromDatabase(Context context, final ArrayList<? extends ItemInfo> items) {
|
||||
final ContentResolver cr = context.getContentResolver();
|
||||
|
||||
Runnable r = new Runnable() {
|
||||
@@ -3048,6 +3011,9 @@ public class LauncherModel extends BroadcastReceiver
|
||||
return;
|
||||
}
|
||||
|
||||
final HashMap<ComponentName, AppInfo> addedOrUpdatedApps =
|
||||
new HashMap<ComponentName, AppInfo>();
|
||||
|
||||
if (added != null) {
|
||||
// Ensure that we add all the workspace applications to the db
|
||||
if (LauncherAppState.isDisableAllApps()) {
|
||||
@@ -3056,23 +3022,15 @@ public class LauncherModel extends BroadcastReceiver
|
||||
} else {
|
||||
addAppsToAllApps(context, added);
|
||||
}
|
||||
for (AppInfo ai : added) {
|
||||
addedOrUpdatedApps.put(ai.componentName, ai);
|
||||
}
|
||||
}
|
||||
|
||||
if (modified != null) {
|
||||
final ArrayList<AppInfo> modifiedFinal = modified;
|
||||
|
||||
// Update the launcher db to reflect the changes
|
||||
for (AppInfo a : modifiedFinal) {
|
||||
ArrayList<ItemInfo> infos =
|
||||
getItemInfoForComponentName(a.componentName, mUser);
|
||||
for (ItemInfo i : infos) {
|
||||
if (i instanceof ShortcutInfo && isShortcutAppTarget((ShortcutInfo) i)) {
|
||||
ShortcutInfo info = (ShortcutInfo) i;
|
||||
info.title = a.title.toString();
|
||||
info.contentDescription = a.contentDescription;
|
||||
updateItemInDatabase(context, info);
|
||||
}
|
||||
}
|
||||
for (AppInfo ai : modified) {
|
||||
addedOrUpdatedApps.put(ai.componentName, ai);
|
||||
}
|
||||
|
||||
mHandler.post(new Runnable() {
|
||||
@@ -3085,37 +3043,128 @@ public class LauncherModel extends BroadcastReceiver
|
||||
});
|
||||
}
|
||||
|
||||
// Update shortcuts which use an iconResource
|
||||
// Update shortcut infos
|
||||
if (mOp == OP_ADD || mOp == OP_UPDATE) {
|
||||
final ArrayList<ShortcutInfo> iconsChanged = new ArrayList<ShortcutInfo>();
|
||||
final ArrayList<ShortcutInfo> updatedShortcuts = new ArrayList<ShortcutInfo>();
|
||||
final ArrayList<ShortcutInfo> removedShortcuts = new ArrayList<ShortcutInfo>();
|
||||
final ArrayList<LauncherAppWidgetInfo> widgets = new ArrayList<LauncherAppWidgetInfo>();
|
||||
|
||||
HashSet<String> packageSet = new HashSet<String>(Arrays.asList(packages));
|
||||
// We need to iterate over the items here, so that we can avoid new Bitmap
|
||||
// creation on the UI thread.
|
||||
synchronized (sBgLock) {
|
||||
for (ItemInfo info : sBgWorkspaceItems) {
|
||||
for (ItemInfo info : sBgItemsIdMap.values()) {
|
||||
if (info instanceof ShortcutInfo && mUser.equals(info.user)) {
|
||||
ShortcutInfo si = (ShortcutInfo) info;
|
||||
boolean infoUpdated = false;
|
||||
boolean shortcutUpdated = false;
|
||||
|
||||
// Update shortcuts which use iconResource.
|
||||
if ((si.iconResource != null)
|
||||
&& packageSet.contains(si.getTargetComponent().getPackageName())){
|
||||
&& packageSet.contains(si.iconResource.packageName)) {
|
||||
Bitmap icon = Utilities.createIconBitmap(si.iconResource.packageName,
|
||||
si.iconResource.resourceName, mIconCache, context);
|
||||
if (icon != null) {
|
||||
si.setIcon(icon);
|
||||
si.usingFallbackIcon = false;
|
||||
iconsChanged.add(si);
|
||||
updateItemInDatabase(context, si);
|
||||
infoUpdated = true;
|
||||
}
|
||||
}
|
||||
|
||||
ComponentName cn = si.getTargetComponent();
|
||||
if (cn != null && packageSet.contains(cn.getPackageName())) {
|
||||
AppInfo appInfo = addedOrUpdatedApps.get(cn);
|
||||
|
||||
if (si.isPromise()) {
|
||||
mIconCache.deletePreloadedIcon(cn, mUser);
|
||||
if (si.hasStatusFlag(ShortcutInfo.FLAG_AUTOINTALL_ICON)) {
|
||||
// Auto install icon
|
||||
PackageManager pm = context.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 = addedOrUpdatedApps.get(cn);
|
||||
}
|
||||
|
||||
if ((intent == null) || (appInfo == null)) {
|
||||
removedShortcuts.add(si);
|
||||
continue;
|
||||
}
|
||||
si.promisedIntent = intent;
|
||||
}
|
||||
}
|
||||
|
||||
// Restore the shortcut.
|
||||
si.intent = si.promisedIntent;
|
||||
si.promisedIntent = null;
|
||||
si.status &= ~ShortcutInfo.FLAG_RESTORED_ICON
|
||||
& ~ShortcutInfo.FLAG_AUTOINTALL_ICON
|
||||
& ~ShortcutInfo.FLAG_INSTALL_SESSION_ACTIVE;
|
||||
|
||||
infoUpdated = true;
|
||||
si.updateIcon(mIconCache);
|
||||
}
|
||||
|
||||
if (appInfo != null && Intent.ACTION_MAIN.equals(si.intent.getAction())
|
||||
&& si.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
|
||||
si.updateIcon(mIconCache);
|
||||
si.title = appInfo.title.toString();
|
||||
si.contentDescription = appInfo.contentDescription;
|
||||
infoUpdated = true;
|
||||
}
|
||||
|
||||
if ((si.isDisabled & ShortcutInfo.FLAG_DISABLED_NOT_AVAILABLE) != 0) {
|
||||
// Since package was just updated, the target must be available now.
|
||||
si.isDisabled &= ~ShortcutInfo.FLAG_DISABLED_NOT_AVAILABLE;
|
||||
shortcutUpdated = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (infoUpdated || shortcutUpdated) {
|
||||
updatedShortcuts.add(si);
|
||||
}
|
||||
if (infoUpdated) {
|
||||
updateItemInDatabase(context, si);
|
||||
}
|
||||
} else if (info instanceof LauncherAppWidgetInfo) {
|
||||
LauncherAppWidgetInfo widgetInfo = (LauncherAppWidgetInfo) info;
|
||||
if (mUser.equals(widgetInfo.user)
|
||||
&& widgetInfo.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY)
|
||||
&& packageSet.contains(widgetInfo.providerName.getPackageName())) {
|
||||
widgetInfo.restoreStatus &= ~LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY;
|
||||
widgets.add(widgetInfo);
|
||||
updateItemInDatabase(context, widgetInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!iconsChanged.isEmpty()) {
|
||||
if (!updatedShortcuts.isEmpty() || !removedShortcuts.isEmpty()) {
|
||||
mHandler.post(new Runnable() {
|
||||
|
||||
public void run() {
|
||||
Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;
|
||||
if (callbacks == cb && cb != null) {
|
||||
callbacks.bindShortcutsChanged(
|
||||
updatedShortcuts, removedShortcuts, mUser);
|
||||
}
|
||||
}
|
||||
});
|
||||
if (!removedShortcuts.isEmpty()) {
|
||||
deleteItemsFromDatabase(context, removedShortcuts);
|
||||
}
|
||||
}
|
||||
if (!widgets.isEmpty()) {
|
||||
mHandler.post(new Runnable() {
|
||||
public void run() {
|
||||
Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;
|
||||
if (callbacks == cb && cb != null) {
|
||||
callbacks.bindShortcutsUpdated(iconsChanged);
|
||||
callbacks.bindWidgetsRestored(widgets);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -3414,20 +3463,6 @@ public class LauncherModel extends BroadcastReceiver
|
||||
return filterItemInfos(sBgItemsIdMap.values(), filter);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the ShortcutInfo points to an app shortcut target, i.e. it has been added by
|
||||
* dragging from AllApps list.
|
||||
*/
|
||||
public static boolean isShortcutAppTarget(ShortcutInfo info) {
|
||||
// We need to check for ACTION_MAIN otherwise getComponent() might
|
||||
// return null for some shortcuts (for instance, for shortcuts to
|
||||
// web pages.)
|
||||
Intent intent = info.promisedIntent != null ? info.promisedIntent : info.intent;
|
||||
ComponentName name = intent.getComponent();
|
||||
return info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION &&
|
||||
Intent.ACTION_MAIN.equals(intent.getAction()) && name != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make an ShortcutInfo object for a shortcut that isn't an application.
|
||||
*/
|
||||
|
||||
@@ -4693,20 +4693,11 @@ public class Workspace extends SmoothPagedView
|
||||
removeItemsByComponentName(cns, user);
|
||||
}
|
||||
|
||||
// Removes items that match the application info specified, when applications are removed
|
||||
// as a part of an update, this is called to ensure that other widgets and application
|
||||
// shortcuts are not removed.
|
||||
void removeItemsByApplicationInfo(final ArrayList<AppInfo> appInfos, UserHandleCompat user) {
|
||||
// Just create a hash table of all the specific components that this will affect
|
||||
HashSet<ComponentName> cns = new HashSet<ComponentName>();
|
||||
for (AppInfo info : appInfos) {
|
||||
cns.add(info.componentName);
|
||||
}
|
||||
|
||||
// Remove all the things
|
||||
removeItemsByComponentName(cns, user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes items that match the item info specified. When applications are removed
|
||||
* as a part of an update, this is called to ensure that other widgets and application
|
||||
* shortcuts are not removed.
|
||||
*/
|
||||
void removeItemsByComponentName(final HashSet<ComponentName> componentNames,
|
||||
final UserHandleCompat user) {
|
||||
ArrayList<CellLayout> cellLayouts = getWorkspaceAndHotseatCellLayouts();
|
||||
@@ -4827,7 +4818,6 @@ public class Workspace extends SmoothPagedView
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void updateShortcuts(ArrayList<ShortcutInfo> shortcuts) {
|
||||
final HashSet<ShortcutInfo> updates = new HashSet<ShortcutInfo>(shortcuts);
|
||||
mapOverItems(MAP_RECURSE, new ItemOperator() {
|
||||
@@ -4835,9 +4825,12 @@ public class Workspace extends SmoothPagedView
|
||||
public boolean evaluate(ItemInfo info, View v, View parent) {
|
||||
if (info instanceof ShortcutInfo && v instanceof BubbleTextView &&
|
||||
updates.contains(info)) {
|
||||
ShortcutInfo shortcutInfo = (ShortcutInfo) info;
|
||||
ShortcutInfo si = (ShortcutInfo) info;
|
||||
BubbleTextView shortcut = (BubbleTextView) v;
|
||||
shortcut.applyFromShortcutInfo(shortcutInfo, mIconCache, true, false);
|
||||
boolean oldPromiseState = shortcut.getCompoundDrawables()[1]
|
||||
instanceof PreloadIconDrawable;
|
||||
shortcut.applyFromShortcutInfo(si, mIconCache, true,
|
||||
si.isPromise() != oldPromiseState);
|
||||
|
||||
if (parent != null) {
|
||||
parent.invalidate();
|
||||
@@ -4849,125 +4842,6 @@ public class Workspace extends SmoothPagedView
|
||||
});
|
||||
}
|
||||
|
||||
void updateShortcutsAndWidgets(ArrayList<AppInfo> apps) {
|
||||
// Break the appinfo list per user
|
||||
final HashMap<UserHandleCompat, ArrayList<AppInfo>> appsPerUser =
|
||||
new HashMap<UserHandleCompat, ArrayList<AppInfo>>();
|
||||
for (AppInfo info : apps) {
|
||||
ArrayList<AppInfo> filtered = appsPerUser.get(info.user);
|
||||
if (filtered == null) {
|
||||
filtered = new ArrayList<AppInfo>();
|
||||
appsPerUser.put(info.user, filtered);
|
||||
}
|
||||
filtered.add(info);
|
||||
}
|
||||
|
||||
for (Map.Entry<UserHandleCompat, ArrayList<AppInfo>> entry : appsPerUser.entrySet()) {
|
||||
updateShortcutsAndWidgetsPerUser(entry.getValue(), entry.getKey());
|
||||
}
|
||||
}
|
||||
|
||||
private void updateShortcutsAndWidgetsPerUser(ArrayList<AppInfo> apps,
|
||||
final UserHandleCompat user) {
|
||||
// Create a map of the apps to test against
|
||||
final HashMap<ComponentName, AppInfo> appsMap = new HashMap<ComponentName, AppInfo>();
|
||||
final HashSet<String> pkgNames = new HashSet<String>();
|
||||
for (AppInfo ai : apps) {
|
||||
appsMap.put(ai.componentName, ai);
|
||||
pkgNames.add(ai.componentName.getPackageName());
|
||||
}
|
||||
final HashSet<ComponentName> iconsToRemove = new HashSet<ComponentName>();
|
||||
|
||||
mapOverItems(MAP_RECURSE, new ItemOperator() {
|
||||
@Override
|
||||
public boolean evaluate(ItemInfo info, View v, View parent) {
|
||||
if (info instanceof ShortcutInfo && v instanceof BubbleTextView) {
|
||||
ShortcutInfo shortcutInfo = (ShortcutInfo) info;
|
||||
ComponentName cn = shortcutInfo.getTargetComponent();
|
||||
AppInfo appInfo = appsMap.get(cn);
|
||||
if (user.equals(shortcutInfo.user) && cn != null
|
||||
&& 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.
|
||||
iconsToRemove.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 ((shortcutInfo.isDisabled & ShortcutInfo.FLAG_DISABLED_NOT_AVAILABLE) != 0) {
|
||||
// Since package was just updated, the target must be available now.
|
||||
shortcutInfo.isDisabled &= ~ShortcutInfo.FLAG_DISABLED_NOT_AVAILABLE;
|
||||
infoUpdated = true;
|
||||
}
|
||||
|
||||
// Only update the icon and labels if the shortcuts points to an app target
|
||||
if ((appInfo != null) && LauncherModel.isShortcutAppTarget(shortcutInfo)) {
|
||||
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
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
if (!iconsToRemove.isEmpty()) {
|
||||
removeItemsByComponentName(iconsToRemove, user);
|
||||
}
|
||||
if (user.equals(UserHandleCompat.myUserHandle())) {
|
||||
restorePendingWidgets(pkgNames);
|
||||
}
|
||||
}
|
||||
|
||||
public void removeAbandonedPromise(String packageName, UserHandleCompat user) {
|
||||
ArrayList<String> packages = new ArrayList<String>(1);
|
||||
packages.add(packageName);
|
||||
@@ -5008,9 +4882,11 @@ public class Workspace extends SmoothPagedView
|
||||
}
|
||||
|
||||
public void updatePackageState(ArrayList<PackageInstallInfo> installInfos) {
|
||||
HashSet<String> completedPackages = new HashSet<String>();
|
||||
|
||||
for (final PackageInstallInfo installInfo : installInfos) {
|
||||
if (installInfo.state == PackageInstallerCompat.STATUS_INSTALLED) {
|
||||
continue;
|
||||
}
|
||||
|
||||
mapOverItems(MAP_RECURSE, new ItemOperator() {
|
||||
@Override
|
||||
public boolean evaluate(ItemInfo info, View v, View parent) {
|
||||
@@ -5038,42 +4914,10 @@ public class Workspace extends SmoothPagedView
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
if (installInfo.state == PackageInstallerCompat.STATUS_INSTALLED) {
|
||||
completedPackages.add(installInfo.packageName);
|
||||
}
|
||||
}
|
||||
|
||||
// Note that package states are sent only for myUser
|
||||
if (!completedPackages.isEmpty()) {
|
||||
restorePendingWidgets(completedPackages);
|
||||
}
|
||||
}
|
||||
|
||||
private void restorePendingWidgets(final Set<String> installedPackaged) {
|
||||
final ArrayList<LauncherAppWidgetInfo> changedInfo = new ArrayList<LauncherAppWidgetInfo>();
|
||||
|
||||
// Iterate non recursively as widgets can't be inside a folder.
|
||||
mapOverItems(MAP_NO_RECURSE, new ItemOperator() {
|
||||
|
||||
@Override
|
||||
public boolean evaluate(ItemInfo info, View v, View parent) {
|
||||
if (info instanceof LauncherAppWidgetInfo) {
|
||||
LauncherAppWidgetInfo widgetInfo = (LauncherAppWidgetInfo) info;
|
||||
if (widgetInfo.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY)
|
||||
&& installedPackaged.contains(widgetInfo.providerName.getPackageName())) {
|
||||
|
||||
changedInfo.add(widgetInfo);
|
||||
|
||||
// Remove the provider not ready flag
|
||||
widgetInfo.restoreStatus &= ~LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY;
|
||||
LauncherModel.updateItemInDatabase(getContext(), widgetInfo);
|
||||
}
|
||||
}
|
||||
// process all the widget
|
||||
return false;
|
||||
}
|
||||
});
|
||||
void widgetsRestored(ArrayList<LauncherAppWidgetInfo> changedInfo) {
|
||||
if (!changedInfo.isEmpty()) {
|
||||
DeferredWidgetRefresh widgetRefresh = new DeferredWidgetRefresh(changedInfo,
|
||||
mLauncher.getAppWidgetHost());
|
||||
@@ -5083,6 +4927,13 @@ public class Workspace extends SmoothPagedView
|
||||
widgetRefresh.run();
|
||||
} else {
|
||||
// widgetRefresh will automatically run when the packages are updated.
|
||||
// For now just update the progress bars
|
||||
for (LauncherAppWidgetInfo info : changedInfo) {
|
||||
if (info.hostView instanceof PendingAppWidgetHostView) {
|
||||
info.installProgress = 100;
|
||||
((PendingAppWidgetHostView) info.hostView).applyState();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user