diff options
author | Sunny Goyal <sunnygoyal@google.com> | 2016-03-15 09:16:30 -0700 |
---|---|---|
committer | Sunny Goyal <sunnygoyal@google.com> | 2016-03-18 15:13:28 -0700 |
commit | 3bbbabc54ac73a4451b0a862a3faac6426b1b7b4 (patch) | |
tree | d3833e7eb292d4137ec87c0f481d2c59139916fd /src/com/android | |
parent | b8f00da8deec7f65002830261042da0140cbead0 (diff) | |
download | android_packages_apps_Trebuchet-3bbbabc54ac73a4451b0a862a3faac6426b1b7b4.tar.gz android_packages_apps_Trebuchet-3bbbabc54ac73a4451b0a862a3faac6426b1b7b4.tar.bz2 android_packages_apps_Trebuchet-3bbbabc54ac73a4451b0a862a3faac6426b1b7b4.zip |
Fixing model being updated on UI thread
> When package gets unavailable or suspended, the disabled flag was getting
updated on the UI thread. This could lead to inconsistent model if launcher
activity didn't exist.
> Fixing: When unsuspending one work profile apps, all work profile apps get
unsuspended
Bug: 27673573,27673373,27403236
Change-Id: I7fde3f79c36204e73ca66ccf8431fa0f0cce3d08
Diffstat (limited to 'src/com/android')
-rw-r--r-- | src/com/android/launcher3/AllAppsList.java | 11 | ||||
-rw-r--r-- | src/com/android/launcher3/InstallShortcutReceiver.java | 2 | ||||
-rw-r--r-- | src/com/android/launcher3/Launcher.java | 49 | ||||
-rw-r--r-- | src/com/android/launcher3/LauncherModel.java | 112 | ||||
-rw-r--r-- | src/com/android/launcher3/Workspace.java | 35 | ||||
-rw-r--r-- | src/com/android/launcher3/dragndrop/DragController.java | 2 | ||||
-rw-r--r-- | src/com/android/launcher3/util/FlagOp.java | 30 |
7 files changed, 125 insertions, 116 deletions
diff --git a/src/com/android/launcher3/AllAppsList.java b/src/com/android/launcher3/AllAppsList.java index f76c18512..962396c3b 100644 --- a/src/com/android/launcher3/AllAppsList.java +++ b/src/com/android/launcher3/AllAppsList.java @@ -22,6 +22,7 @@ import android.content.Context; import com.android.launcher3.compat.LauncherActivityInfoCompat; import com.android.launcher3.compat.LauncherAppsCompat; import com.android.launcher3.compat.UserHandleCompat; +import com.android.launcher3.util.FlagOp; import java.util.ArrayList; import java.util.HashSet; @@ -119,19 +120,15 @@ class AllAppsList { } /** - * Suspend the apps for the given apk identified by packageName. + * Updates the apps for the given packageName and user based on {@param op}. */ - public void suspendPackage(String packageName, UserHandleCompat user, boolean suspend) { + public void updatePackageFlags(String packageName, UserHandleCompat user, FlagOp op) { final List<AppInfo> data = this.data; for (int i = data.size() - 1; i >= 0; i--) { AppInfo info = data.get(i); final ComponentName component = info.intent.getComponent(); if (info.user.equals(user) && packageName.equals(component.getPackageName())) { - if (suspend) { - info.isDisabled |= ShortcutInfo.FLAG_DISABLED_SUSPENDED; - } else { - info.isDisabled &= ~ShortcutInfo.FLAG_DISABLED_SUSPENDED; - } + info.isDisabled = op.apply(info.isDisabled); modified.add(info); } } diff --git a/src/com/android/launcher3/InstallShortcutReceiver.java b/src/com/android/launcher3/InstallShortcutReceiver.java index 46b9b7d78..921e90ced 100644 --- a/src/com/android/launcher3/InstallShortcutReceiver.java +++ b/src/com/android/launcher3/InstallShortcutReceiver.java @@ -87,7 +87,7 @@ public class InstallShortcutReceiver extends BroadcastReceiver { } } - public static void removeFromInstallQueue(Context context, ArrayList<String> packageNames, + public static void removeFromInstallQueue(Context context, HashSet<String> packageNames, UserHandleCompat user) { if (packageNames.isEmpty()) { return; diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 5a1f99a65..36b9ab024 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -4322,7 +4322,7 @@ public class Launcher extends Activity } mWorkspace.removeItemsByComponentName(removedComponents, user); // Notify the drag controller - mDragController.onAppsRemoved(new ArrayList<String>(), removedComponents); + mDragController.onAppsRemoved(new HashSet<String>(), removedComponents); } } @@ -4346,43 +4346,44 @@ public class Launcher extends Activity } /** - * A package was uninstalled. We take both the super set of packageNames + * A package was uninstalled/updated. We take both the super set of packageNames * in addition to specific applications to remove, the reason being that * this can be called when a package is updated as well. In that scenario, - * we only remove specific components from the workspace, where as + * we only remove specific components from the workspace and hotseat, where as * package-removal should clear all items by package name. - * - * @param reason if non-zero, the icons are not permanently removed, rather marked as disabled. - * Implementation of the method from LauncherModel.Callbacks. */ @Override - public void bindComponentsRemoved(final ArrayList<String> packageNames, - final ArrayList<AppInfo> appInfos, final UserHandleCompat user, final int reason) { + public void bindWorkspaceComponentsRemoved( + final HashSet<String> packageNames, final HashSet<ComponentName> components, + final UserHandleCompat user) { Runnable r = new Runnable() { public void run() { - bindComponentsRemoved(packageNames, appInfos, user, reason); + bindWorkspaceComponentsRemoved(packageNames, components, user); } }; if (waitUntilResume(r)) { return; } + if (!packageNames.isEmpty()) { + mWorkspace.removeItemsByPackageName(packageNames, user); + } + if (!components.isEmpty()) { + mWorkspace.removeItemsByComponentName(components, user); + } + // Notify the drag controller + mDragController.onAppsRemoved(packageNames, components); - 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 (!removedComponents.isEmpty()) { - mWorkspace.removeItemsByComponentName(removedComponents, user); - } - // Notify the drag controller - mDragController.onAppsRemoved(packageNames, removedComponents); + } - } else { - mWorkspace.disableShortcutsByPackageName(packageNames, user, reason); + @Override + public void bindAppInfosRemoved(final ArrayList<AppInfo> appInfos) { + Runnable r = new Runnable() { + public void run() { + bindAppInfosRemoved(appInfos); + } + }; + if (waitUntilResume(r)) { + return; } // Update AllApps diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java index 3877b9496..4c2dec592 100644 --- a/src/com/android/launcher3/LauncherModel.java +++ b/src/com/android/launcher3/LauncherModel.java @@ -60,6 +60,7 @@ import com.android.launcher3.model.GridSizeMigrationTask; import com.android.launcher3.model.WidgetsModel; import com.android.launcher3.util.ComponentKey; import com.android.launcher3.util.CursorIconInfo; +import com.android.launcher3.util.FlagOp; import com.android.launcher3.util.LongArrayMap; import com.android.launcher3.util.ManagedProfileHeuristic; import com.android.launcher3.util.Thunk; @@ -195,8 +196,10 @@ public class LauncherModel extends BroadcastReceiver ArrayList<ShortcutInfo> removed, UserHandleCompat user); public void bindWidgetsRestored(ArrayList<LauncherAppWidgetInfo> widgets); public void bindRestoreItemsChange(HashSet<ItemInfo> updates); - public void bindComponentsRemoved(ArrayList<String> packageNames, - ArrayList<AppInfo> appInfos, UserHandleCompat user, int reason); + public void bindWorkspaceComponentsRemoved( + HashSet<String> packageNames, HashSet<ComponentName> components, + UserHandleCompat user); + public void bindAppInfosRemoved(ArrayList<AppInfo> appInfos); public void notifyWidgetProvidersChanged(); public void bindWidgetsModel(WidgetsModel model); public void bindSearchProviderChanged(); @@ -2928,6 +2931,7 @@ public class LauncherModel extends BroadcastReceiver final String[] packages = mPackages; final int N = packages.length; + FlagOp flagOp = FlagOp.NO_OP; switch (mOp) { case OP_ADD: { for (int i=0; i<N; i++) { @@ -2949,6 +2953,8 @@ public class LauncherModel extends BroadcastReceiver mBgAllAppsList.updatePackage(context, packages[i], mUser); mApp.getWidgetCache().removePackage(packages[i], mUser); } + // Since package was just updated, the target must be available now. + flagOp = FlagOp.removeFlag(ShortcutInfo.FLAG_DISABLED_NOT_AVAILABLE); break; case OP_REMOVE: { ManagedProfileHeuristic heuristic = ManagedProfileHeuristic.get(context, mUser); @@ -2967,14 +2973,16 @@ public class LauncherModel extends BroadcastReceiver mBgAllAppsList.removePackage(packages[i], mUser); mApp.getWidgetCache().removePackage(packages[i], mUser); } + flagOp = FlagOp.addFlag(ShortcutInfo.FLAG_DISABLED_NOT_AVAILABLE); break; case OP_SUSPEND: case OP_UNSUSPEND: - boolean suspend = mOp == OP_SUSPEND; + flagOp = mOp == OP_SUSPEND ? + FlagOp.addFlag(ShortcutInfo.FLAG_DISABLED_SUSPENDED) : + FlagOp.removeFlag(ShortcutInfo.FLAG_DISABLED_SUSPENDED); for (int i=0; i<N; i++) { - if (DEBUG_LOADERS) Log.d(TAG, "mAllAppsList.suspendPackage " - + suspend + " " + packages[i]); - mBgAllAppsList.suspendPackage(packages[i], mUser, suspend); + if (DEBUG_LOADERS) Log.d(TAG, "mAllAppsList.(un)suspend " + packages[i]); + mBgAllAppsList.updatePackageFlags(packages[i], mUser, flagOp); } break; } @@ -2984,11 +2992,11 @@ public class LauncherModel extends BroadcastReceiver final ArrayList<AppInfo> removedApps = new ArrayList<AppInfo>(); if (mBgAllAppsList.added.size() > 0) { - added = new ArrayList<AppInfo>(mBgAllAppsList.added); + added = new ArrayList<>(mBgAllAppsList.added); mBgAllAppsList.added.clear(); } if (mBgAllAppsList.modified.size() > 0) { - modified = new ArrayList<AppInfo>(mBgAllAppsList.modified); + modified = new ArrayList<>(mBgAllAppsList.modified); mBgAllAppsList.modified.clear(); } if (mBgAllAppsList.removed.size() > 0) { @@ -2996,14 +3004,7 @@ public class LauncherModel extends BroadcastReceiver mBgAllAppsList.removed.clear(); } - final Callbacks callbacks = getCallback(); - if (callbacks == null) { - Log.w(TAG, "Nobody to tell about the new app. Launcher is probably loading."); - return; - } - - final HashMap<ComponentName, AppInfo> addedOrUpdatedApps = - new HashMap<ComponentName, AppInfo>(); + final HashMap<ComponentName, AppInfo> addedOrUpdatedApps = new HashMap<>(); if (added != null) { addAppsToAllApps(context, added); @@ -3013,6 +3014,7 @@ public class LauncherModel extends BroadcastReceiver } if (modified != null) { + final Callbacks callbacks = getCallback(); final ArrayList<AppInfo> modifiedFinal = modified; for (AppInfo ai : modified) { addedOrUpdatedApps.put(ai.componentName, ai); @@ -3029,7 +3031,7 @@ public class LauncherModel extends BroadcastReceiver } // Update shortcut infos - if (mOp == OP_ADD || mOp == OP_UPDATE || mOp == OP_UNSUSPEND) { + if (mOp == OP_ADD || flagOp != FlagOp.NO_OP) { final ArrayList<ShortcutInfo> updatedShortcuts = new ArrayList<ShortcutInfo>(); final ArrayList<ShortcutInfo> removedShortcuts = new ArrayList<ShortcutInfo>(); final ArrayList<LauncherAppWidgetInfo> widgets = new ArrayList<LauncherAppWidgetInfo>(); @@ -3042,11 +3044,6 @@ public class LauncherModel extends BroadcastReceiver boolean infoUpdated = false; boolean shortcutUpdated = false; - if (mOp == OP_UNSUSPEND) { - si.isDisabled &= ~ ShortcutInfo.FLAG_DISABLED_SUSPENDED; - infoUpdated = true; - } - // Update shortcuts which use iconResource. if ((si.iconResource != null) && packageSet.contains(si.iconResource.packageName)) { @@ -3109,9 +3106,9 @@ public class LauncherModel extends BroadcastReceiver 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; + int oldDisabledFlags = si.isDisabled; + si.isDisabled = flagOp.apply(si.isDisabled); + if (si.isDisabled != oldDisabledFlags) { shortcutUpdated = true; } } @@ -3144,6 +3141,7 @@ public class LauncherModel extends BroadcastReceiver } if (!updatedShortcuts.isEmpty() || !removedShortcuts.isEmpty()) { + final Callbacks callbacks = getCallback(); mHandler.post(new Runnable() { public void run() { @@ -3159,6 +3157,7 @@ public class LauncherModel extends BroadcastReceiver } } if (!widgets.isEmpty()) { + final Callbacks callbacks = getCallback(); mHandler.post(new Runnable() { public void run() { Callbacks cb = getCallback(); @@ -3170,48 +3169,60 @@ public class LauncherModel extends BroadcastReceiver } } - final ArrayList<String> removedPackageNames = - new ArrayList<String>(); - if (mOp == OP_REMOVE || mOp == OP_UNAVAILABLE || mOp == OP_SUSPEND) { + final HashSet<String> removedPackages = new HashSet<>(); + final HashSet<ComponentName> removedComponents = new HashSet<>(); + if (mOp == OP_REMOVE) { // Mark all packages in the broadcast to be removed - removedPackageNames.addAll(Arrays.asList(packages)); + Collections.addAll(removedPackages, packages); + + // No need to update the removedComponents as + // removedPackages is a super-set of removedComponents } else if (mOp == OP_UPDATE) { // Mark disabled packages in the broadcast to be removed for (int i=0; i<N; i++) { if (isPackageDisabled(context, packages[i], mUser)) { - removedPackageNames.add(packages[i]); + removedPackages.add(packages[i]); } } + + // Update removedComponents as some components can get removed during package update + for (AppInfo info : removedApps) { + removedComponents.add(info.componentName); + } } - if (!removedPackageNames.isEmpty() || !removedApps.isEmpty()) { - final int removeReason; - if (mOp == OP_UNAVAILABLE) { - removeReason = ShortcutInfo.FLAG_DISABLED_NOT_AVAILABLE; - } else if (mOp == OP_SUSPEND) { - removeReason = ShortcutInfo.FLAG_DISABLED_SUSPENDED; - } else { - // Remove all the components associated with this package - for (String pn : removedPackageNames) { - deletePackageFromDatabase(context, pn, mUser); - } - // Remove all the specific components - for (AppInfo a : removedApps) { - ArrayList<ItemInfo> infos = getItemInfoForComponentName(a.componentName, mUser); - deleteItemsFromDatabase(context, infos); - } - removeReason = 0; + if (!removedPackages.isEmpty() || !removedComponents.isEmpty()) { + for (String pn : removedPackages) { + deletePackageFromDatabase(context, pn, mUser); + } + for (ComponentName cn : removedComponents) { + deleteItemsFromDatabase(context, getItemInfoForComponentName(cn, mUser)); } // Remove any queued items from the install queue - InstallShortcutReceiver.removeFromInstallQueue(context, removedPackageNames, mUser); + InstallShortcutReceiver.removeFromInstallQueue(context, removedPackages, mUser); + // Call the components-removed callback + final Callbacks callbacks = getCallback(); + mHandler.post(new Runnable() { + public void run() { + Callbacks cb = getCallback(); + if (callbacks == cb && cb != null) { + callbacks.bindWorkspaceComponentsRemoved( + removedPackages, removedComponents, mUser); + } + } + }); + } + + if (!removedApps.isEmpty()) { + // Remove corresponding apps from All-Apps + final Callbacks callbacks = getCallback(); mHandler.post(new Runnable() { public void run() { Callbacks cb = getCallback(); if (callbacks == cb && cb != null) { - callbacks.bindComponentsRemoved( - removedPackageNames, removedApps, mUser, removeReason); + callbacks.bindAppInfosRemoved(removedApps); } } }); @@ -3221,6 +3232,7 @@ public class LauncherModel extends BroadcastReceiver // get widget update signals. if (!Utilities.ATLEAST_MARSHMALLOW && (mOp == OP_ADD || mOp == OP_REMOVE || mOp == OP_UPDATE)) { + final Callbacks callbacks = getCallback(); mHandler.post(new Runnable() { public void run() { Callbacks cb = getCallback(); diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java index 44a17cce8..89779d540 100644 --- a/src/com/android/launcher3/Workspace.java +++ b/src/com/android/launcher3/Workspace.java @@ -3922,41 +3922,10 @@ public class Workspace extends PagedView }); } - public void disableShortcutsByPackageName(final ArrayList<String> packages, - final UserHandleCompat user, final int reason) { - final HashSet<String> packageNames = new HashSet<String>(); - packageNames.addAll(packages); - - 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(); - if (user.equals(shortcutInfo.user) && cn != null - && packageNames.contains(cn.getPackageName())) { - shortcutInfo.isDisabled |= reason; - BubbleTextView shortcut = (BubbleTextView) v; - shortcut.applyFromShortcutInfo(shortcutInfo, mIconCache); - - if (parent != null) { - parent.invalidate(); - } - } - } - // process all the shortcuts - return false; - } - }); - } - // Removes ALL items that match a given package name, this is usually called when a package // has been removed and we want to remove all components (widgets, shortcuts, apps) that // belong to that package. - void removeItemsByPackageName(final ArrayList<String> packages, final UserHandleCompat user) { - final HashSet<String> packageNames = new HashSet<String>(); - packageNames.addAll(packages); - + void removeItemsByPackageName(final HashSet<String> packageNames, final UserHandleCompat user) { // Filter out all the ItemInfos that this is going to affect final HashSet<ItemInfo> infos = new HashSet<ItemInfo>(); final HashSet<ComponentName> cns = new HashSet<ComponentName>(); @@ -4138,7 +4107,7 @@ public class Workspace extends PagedView } public void removeAbandonedPromise(String packageName, UserHandleCompat user) { - ArrayList<String> packages = new ArrayList<String>(1); + HashSet<String> packages = new HashSet<>(1); packages.add(packageName); LauncherModel.deletePackageFromDatabase(mLauncher, packageName, user); removeItemsByPackageName(packages, user); diff --git a/src/com/android/launcher3/dragndrop/DragController.java b/src/com/android/launcher3/dragndrop/DragController.java index 80f9e4665..7524128d4 100644 --- a/src/com/android/launcher3/dragndrop/DragController.java +++ b/src/com/android/launcher3/dragndrop/DragController.java @@ -314,7 +314,7 @@ public class DragController implements DragDriver.EventListener { endDrag(); } - public void onAppsRemoved(final ArrayList<String> packageNames, HashSet<ComponentName> cns) { + public void onAppsRemoved(final HashSet<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; diff --git a/src/com/android/launcher3/util/FlagOp.java b/src/com/android/launcher3/util/FlagOp.java new file mode 100644 index 000000000..5e26ed12f --- /dev/null +++ b/src/com/android/launcher3/util/FlagOp.java @@ -0,0 +1,30 @@ +package com.android.launcher3.util; + +public abstract class FlagOp { + + public static FlagOp NO_OP = new FlagOp() {}; + + private FlagOp() {} + + public int apply(int flags) { + return flags; + } + + public static FlagOp addFlag(final int flag) { + return new FlagOp() { + @Override + public int apply(int flags) { + return flags | flag; + } + }; + } + + public static FlagOp removeFlag(final int flag) { + return new FlagOp() { + @Override + public int apply(int flags) { + return flags & ~flag; + } + }; + } +} |