From c7700af21f7b1df939fce22f4ab5072b3ea29b66 Mon Sep 17 00:00:00 2001 From: Michael Jurka Date: Tue, 14 May 2013 20:17:58 +0200 Subject: [PATCH] Fix bug where apps weren't appearing on workspace after being installed Bug: 8707110 Change-Id: Ib50e0c600a4a77450127f3947aa894346dc99a5a --- .../launcher2/InstallShortcutReceiver.java | 47 ++++++++++++------- src/com/android/launcher2/LauncherModel.java | 36 +++++++++++++- 2 files changed, 64 insertions(+), 19 deletions(-) diff --git a/src/com/android/launcher2/InstallShortcutReceiver.java b/src/com/android/launcher2/InstallShortcutReceiver.java index 20a19660e3..23c8964181 100644 --- a/src/com/android/launcher2/InstallShortcutReceiver.java +++ b/src/com/android/launcher2/InstallShortcutReceiver.java @@ -48,10 +48,23 @@ public class InstallShortcutReceiver extends BroadcastReceiver { public static final String SHORTCUT_MIMETYPE = "com.android.launcher/shortcut"; + private static Object sLock = new Object(); + // The set of shortcuts that are pending install private static ArrayList mInstallQueue = new ArrayList(); + private static void addToStringSet(SharedPreferences sharedPrefs, + SharedPreferences.Editor editor, String key, String value) { + Set strings = sharedPrefs.getStringSet(key, null); + if (strings == null) { + strings = new HashSet(0); + } else { + strings = new HashSet(strings); + } + strings.add(value); + editor.putStringSet(key, strings); + } // Determines whether to defer installing shortcuts immediately until // processAllPendingInstalls() is called. private static boolean mUseInstallQueue = false; @@ -131,6 +144,10 @@ public class InstallShortcutReceiver extends BroadcastReceiver { final int[] result = {INSTALL_SHORTCUT_SUCCESSFUL}; boolean found = false; synchronized (app) { + // Flush the LauncherModel worker thread, so that if we just did another + // processInstallShortcut, we give it time for its shortcut to get added to the + // database (getItemsInLocalCoordinates reads the database) + app.getModel().flushWorkerThread(); final ArrayList items = LauncherModel.getItemsInLocalCoordinates(context); final boolean exists = LauncherModel.shortcutExists(context, name, intent); @@ -160,7 +177,7 @@ public class InstallShortcutReceiver extends BroadcastReceiver { } private static boolean installShortcut(Context context, Intent data, ArrayList items, - String name, Intent intent, final int screen, boolean shortcutExists, + String name, final Intent intent, final int screen, boolean shortcutExists, final SharedPreferences sharedPrefs, int[] result) { int[] tmpCoordinates = new int[2]; if (findEmptyCell(context, items, tmpCoordinates, screen)) { @@ -178,24 +195,20 @@ public class InstallShortcutReceiver extends BroadcastReceiver { // different places) boolean duplicate = data.getBooleanExtra(Launcher.EXTRA_SHORTCUT_DUPLICATE, true); if (duplicate || !shortcutExists) { - // If the new app is going to fall into the same page as before, then just - // continue adding to the current page - int newAppsScreen = sharedPrefs.getInt(NEW_APPS_PAGE_KEY, screen); - Set newApps = new HashSet(); - if (newAppsScreen == screen) { - newApps = sharedPrefs.getStringSet(NEW_APPS_LIST_KEY, newApps); - } - synchronized (newApps) { - newApps.add(intent.toUri(0).toString()); - } - final Set savedNewApps = newApps; new Thread("setNewAppsThread") { public void run() { - synchronized (savedNewApps) { - sharedPrefs.edit() - .putInt(NEW_APPS_PAGE_KEY, screen) - .putStringSet(NEW_APPS_LIST_KEY, savedNewApps) - .commit(); + synchronized (sLock) { + // If the new app is going to fall into the same page as before, + // then just continue adding to the current page + final int newAppsScreen = sharedPrefs.getInt( + NEW_APPS_PAGE_KEY, screen); + SharedPreferences.Editor editor = sharedPrefs.edit(); + if (newAppsScreen == screen) { + addToStringSet(sharedPrefs, + editor, NEW_APPS_LIST_KEY, intent.toUri(0)); + } + editor.putInt(NEW_APPS_PAGE_KEY, screen); + editor.commit(); } } }.start(); diff --git a/src/com/android/launcher2/LauncherModel.java b/src/com/android/launcher2/LauncherModel.java index 00770b28ac..99ebd962e7 100644 --- a/src/com/android/launcher2/LauncherModel.java +++ b/src/com/android/launcher2/LauncherModel.java @@ -82,6 +82,7 @@ public class LauncherModel extends BroadcastReceiver { private DeferredHandler mHandler = new DeferredHandler(); private LoaderTask mLoaderTask; private boolean mIsLoaderTaskRunning; + private volatile boolean mFlushingWorkerThread; // Specific runnable types that are run on the main thread deferred handler, this allows us to // clear all queued binding runnables when the Launcher activity is destroyed. @@ -375,6 +376,35 @@ public class LauncherModel extends BroadcastReceiver { runOnWorkerThread(r); } + public void flushWorkerThread() { + mFlushingWorkerThread = true; + Runnable waiter = new Runnable() { + public void run() { + synchronized (this) { + notifyAll(); + mFlushingWorkerThread = false; + } + } + }; + + synchronized(waiter) { + runOnWorkerThread(waiter); + if (mLoaderTask != null) { + synchronized(mLoaderTask) { + mLoaderTask.notify(); + } + } + boolean success = false; + while (!success) { + try { + waiter.wait(); + success = true; + } catch (InterruptedException e) { + } + } + } + } + /** * Move an item in the DB to a new */ @@ -1004,9 +1034,11 @@ public class LauncherModel extends BroadcastReceiver { } }); - while (!mStopped && !mLoadAndBindStepFinished) { + while (!mStopped && !mLoadAndBindStepFinished && !mFlushingWorkerThread) { try { - this.wait(); + // Just in case mFlushingWorkerThread changes but we aren't woken up, + // wait no longer than 1sec at a time + this.wait(1000); } catch (InterruptedException ex) { // Ignore }