diff --git a/src/com/android/launcher3/InstallShortcutReceiver.java b/src/com/android/launcher3/InstallShortcutReceiver.java index 0370777d17..df1eec6610 100644 --- a/src/com/android/launcher3/InstallShortcutReceiver.java +++ b/src/com/android/launcher3/InstallShortcutReceiver.java @@ -27,7 +27,9 @@ import android.content.pm.LauncherActivityInfo; import android.content.pm.PackageManager; import android.graphics.Bitmap; import android.graphics.BitmapFactory; +import android.os.Handler; import android.os.Looper; +import android.os.Message; import android.os.Parcelable; import android.os.Process; import android.os.UserHandle; @@ -61,6 +63,9 @@ import java.util.Set; public class InstallShortcutReceiver extends BroadcastReceiver { + private static final int MSG_ADD_TO_QUEUE = 1; + private static final int MSG_FLUSH_QUEUE = 2; + public static final int FLAG_ACTIVITY_PAUSED = 1; public static final int FLAG_LOADER_RUNNING = 2; public static final int FLAG_DRAG_AND_DROP = 4; @@ -93,73 +98,98 @@ public class InstallShortcutReceiver extends BroadcastReceiver { public static final int NEW_SHORTCUT_BOUNCE_DURATION = 450; public static final int NEW_SHORTCUT_STAGGER_DELAY = 85; - private static final Object sLock = new Object(); + private static final Handler sHandler = new Handler(LauncherModel.getWorkerLooper()) { - private static void addToInstallQueue( - SharedPreferences sharedPrefs, PendingInstallShortcutInfo info) { - synchronized(sLock) { - String encoded = info.encodeToString(); - if (encoded != null) { - Set strings = sharedPrefs.getStringSet(APPS_PENDING_INSTALL, null); - strings = (strings != null) ? new HashSet<>(strings) : new HashSet(1); - strings.add(encoded); - sharedPrefs.edit().putStringSet(APPS_PENDING_INSTALL, strings).apply(); + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case MSG_ADD_TO_QUEUE: { + Pair pair = + (Pair) msg.obj; + String encoded = pair.second.encodeToString(); + SharedPreferences prefs = Utilities.getPrefs(pair.first); + Set strings = prefs.getStringSet(APPS_PENDING_INSTALL, null); + strings = (strings != null) ? new HashSet<>(strings) : new HashSet(1); + strings.add(encoded); + prefs.edit().putStringSet(APPS_PENDING_INSTALL, strings).apply(); + return; + } + case MSG_FLUSH_QUEUE: { + Context context = (Context) msg.obj; + LauncherModel model = LauncherAppState.getInstance(context).getModel(); + if (model.getCallback() == null) { + // Launcher not loaded + return; + } + + ArrayList> installQueue = new ArrayList<>(); + SharedPreferences prefs = Utilities.getPrefs(context); + Set strings = prefs.getStringSet(APPS_PENDING_INSTALL, null); + if (DBG) Log.d(TAG, "Getting and clearing APPS_PENDING_INSTALL: " + strings); + if (strings == null) { + return; + } + + LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(context); + for (String encoded : strings) { + PendingInstallShortcutInfo info = decode(encoded, context); + if (info == null) { + continue; + } + + String pkg = getIntentPackage(info.launchIntent); + if (!TextUtils.isEmpty(pkg) + && !launcherApps.isPackageEnabledForProfile(pkg, info.user)) { + if (DBG) Log.d(TAG, "Ignoring shortcut for absent package: " + + info.launchIntent); + continue; + } + + // Generate a shortcut info to add into the model + installQueue.add(info.getItemInfo()); + } + prefs.edit().remove(APPS_PENDING_INSTALL).apply(); + if (!installQueue.isEmpty()) { + model.addAndBindAddedWorkspaceItems(installQueue); + } + return; + } } } - } + }; public static void removeFromInstallQueue(Context context, HashSet packageNames, UserHandle user) { if (packageNames.isEmpty()) { return; } + Preconditions.assertWorkerThread(); + SharedPreferences sp = Utilities.getPrefs(context); - synchronized(sLock) { - Set strings = sp.getStringSet(APPS_PENDING_INSTALL, null); - if (DBG) { - Log.d(TAG, "APPS_PENDING_INSTALL: " + strings - + ", removing packages: " + packageNames); - } - if (Utilities.isEmpty(strings)) { - return; - } - Set newStrings = new HashSet<>(strings); - Iterator newStringsIter = newStrings.iterator(); - while (newStringsIter.hasNext()) { - String encoded = newStringsIter.next(); - try { - Decoder decoder = new Decoder(encoded, context); - if (packageNames.contains(getIntentPackage(decoder.launcherIntent)) && - user.equals(decoder.user)) { - newStringsIter.remove(); - } - } catch (JSONException | URISyntaxException e) { - Log.d(TAG, "Exception reading shortcut to add: " + e); + Set strings = sp.getStringSet(APPS_PENDING_INSTALL, null); + if (DBG) { + Log.d(TAG, "APPS_PENDING_INSTALL: " + strings + + ", removing packages: " + packageNames); + } + if (Utilities.isEmpty(strings)) { + return; + } + Set newStrings = new HashSet<>(strings); + Iterator newStringsIter = newStrings.iterator(); + while (newStringsIter.hasNext()) { + String encoded = newStringsIter.next(); + try { + Decoder decoder = new Decoder(encoded, context); + if (packageNames.contains(getIntentPackage(decoder.launcherIntent)) && + user.equals(decoder.user)) { newStringsIter.remove(); } + } catch (JSONException | URISyntaxException e) { + Log.d(TAG, "Exception reading shortcut to add: " + e); + newStringsIter.remove(); } - sp.edit().putStringSet(APPS_PENDING_INSTALL, newStrings).apply(); - } - } - - private static ArrayList getAndClearInstallQueue(Context context) { - SharedPreferences sharedPrefs = Utilities.getPrefs(context); - synchronized(sLock) { - ArrayList infos = new ArrayList<>(); - Set strings = sharedPrefs.getStringSet(APPS_PENDING_INSTALL, null); - if (DBG) Log.d(TAG, "Getting and clearing APPS_PENDING_INSTALL: " + strings); - if (strings == null) { - return infos; - } - for (String encoded : strings) { - PendingInstallShortcutInfo info = decode(encoded, context); - if (info != null) { - infos.add(info); - } - } - sharedPrefs.edit().putStringSet(APPS_PENDING_INSTALL, new HashSet()).apply(); - return infos; } + sp.edit().putStringSet(APPS_PENDING_INSTALL, newStrings).apply(); } public void onReceive(Context context, Intent data) { @@ -256,7 +286,7 @@ public class InstallShortcutReceiver extends BroadcastReceiver { private static void queuePendingShortcutInfo(PendingInstallShortcutInfo info, Context context) { // Queue the item up for adding if launcher has not loaded properly yet - addToInstallQueue(Utilities.getPrefs(context), info); + Message.obtain(sHandler, MSG_ADD_TO_QUEUE, Pair.create(context, info)).sendToTarget(); flushInstallQueue(context); } @@ -269,17 +299,10 @@ public class InstallShortcutReceiver extends BroadcastReceiver { } static void flushInstallQueue(Context context) { - LauncherModel model = LauncherAppState.getInstance(context).getModel(); - boolean launcherNotLoaded = model.getCallback() == null; - if (sInstallQueueDisabledFlags != 0 || launcherNotLoaded) { + if (sInstallQueueDisabledFlags != 0) { return; } - - ArrayList items = getAndClearInstallQueue(context); - if (!items.isEmpty()) { - model.addAndBindAddedWorkspaceItems( - new LazyShortcutsProvider(context.getApplicationContext(), items)); - } + Message.obtain(sHandler, MSG_FLUSH_QUEUE, context.getApplicationContext()).sendToTarget(); } /** @@ -601,42 +624,6 @@ public class InstallShortcutReceiver extends BroadcastReceiver { return new PendingInstallShortcutInfo(info, original.mContext); } - private static class LazyShortcutsProvider extends Provider>> { - - private final Context mContext; - private final ArrayList mPendingItems; - - public LazyShortcutsProvider(Context context, ArrayList items) { - mContext = context; - mPendingItems = items; - } - - /** - * This must be called on the background thread as this requires multiple calls to - * packageManager and icon cache. - */ - @Override - public ArrayList> get() { - Preconditions.assertNonUiThread(); - ArrayList> installQueue = new ArrayList<>(); - LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(mContext); - for (PendingInstallShortcutInfo pendingInfo : mPendingItems) { - // If the intent specifies a package, make sure the package exists - String packageName = getIntentPackage(pendingInfo.launchIntent); - if (!TextUtils.isEmpty(packageName) && !launcherApps.isPackageEnabledForProfile( - packageName, pendingInfo.user)) { - if (DBG) Log.d(TAG, "Ignoring shortcut for absent package: " - + pendingInfo.launchIntent); - continue; - } - - // Generate a shortcut info to add into the model - installQueue.add(pendingInfo.getItemInfo()); - } - return installQueue; - } - } - private static ShortcutInfo createShortcutInfo(Intent data, LauncherAppState app) { Intent intent = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT); String name = data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME); diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java index 74a5bac995..3e2236682c 100644 --- a/src/com/android/launcher3/LauncherModel.java +++ b/src/com/android/launcher3/LauncherModel.java @@ -192,9 +192,8 @@ public class LauncherModel extends BroadcastReceiver /** * Adds the provided items to the workspace. */ - public void addAndBindAddedWorkspaceItems( - Provider>> appsProvider) { - enqueueModelUpdateTask(new AddWorkspaceItemsTask(appsProvider)); + public void addAndBindAddedWorkspaceItems(List> itemList) { + enqueueModelUpdateTask(new AddWorkspaceItemsTask(itemList)); } public ModelWriter getWriter(boolean hasVerticalHotseat) { diff --git a/src/com/android/launcher3/model/AddWorkspaceItemsTask.java b/src/com/android/launcher3/model/AddWorkspaceItemsTask.java index 42926fa3ea..a33a039c0e 100644 --- a/src/com/android/launcher3/model/AddWorkspaceItemsTask.java +++ b/src/com/android/launcher3/model/AddWorkspaceItemsTask.java @@ -38,7 +38,6 @@ import com.android.launcher3.ShortcutInfo; import com.android.launcher3.Utilities; import com.android.launcher3.util.GridOccupancy; import com.android.launcher3.util.ManagedProfileHeuristic.UserFolderInfo; -import com.android.launcher3.util.Provider; import java.util.ArrayList; import java.util.List; @@ -47,19 +46,18 @@ import java.util.List; */ public class AddWorkspaceItemsTask extends BaseModelUpdateTask { - private final Provider>> mAppsProvider; + private final List> mItemList; /** - * @param appsProvider items to add on the workspace + * @param itemList items to add on the workspace */ - public AddWorkspaceItemsTask(Provider>> appsProvider) { - mAppsProvider = appsProvider; + public AddWorkspaceItemsTask(List> itemList) { + mItemList = itemList; } @Override public void execute(LauncherAppState app, BgDataModel dataModel, AllAppsList apps) { - List> workspaceApps = mAppsProvider.get(); - if (workspaceApps.isEmpty()) { + if (mItemList.isEmpty()) { return; } Context context = app.getContext(); @@ -75,7 +73,7 @@ public class AddWorkspaceItemsTask extends BaseModelUpdateTask { synchronized(dataModel) { List filteredItems = new ArrayList<>(); - for (Pair entry : workspaceApps) { + for (Pair entry : mItemList) { ItemInfo item = entry.first; if (item.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION || item.itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT) { diff --git a/tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.java b/tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.java index 82f34e43de..a486cebc25 100644 --- a/tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.java +++ b/tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.java @@ -55,7 +55,7 @@ public class AddWorkspaceItemsTaskTest extends BaseModelUpdateTaskTestCase { for (ItemInfo item : items) { list.add(Pair.create(item, null)); } - return new AddWorkspaceItemsTask(Provider.of(list)) { + return new AddWorkspaceItemsTask(list) { @Override protected void updateScreens(Context context, ArrayList workspaceScreens) { }