OSDN Git Service

Fix bug where apps weren't appearing on workspace after being installed
authorMichael Jurka <mikejurka@google.com>
Tue, 14 May 2013 18:17:58 +0000 (20:17 +0200)
committerMichael Jurka <mikejurka@google.com>
Tue, 14 May 2013 18:45:36 +0000 (20:45 +0200)
Bug: 8707110

Change-Id: Ib50e0c600a4a77450127f3947aa894346dc99a5a

src/com/android/launcher2/InstallShortcutReceiver.java
src/com/android/launcher2/LauncherModel.java

index 20a1966..23c8964 100644 (file)
@@ -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<PendingInstallShortcutInfo> mInstallQueue =
             new ArrayList<PendingInstallShortcutInfo>();
 
+    private static void addToStringSet(SharedPreferences sharedPrefs,
+            SharedPreferences.Editor editor, String key, String value) {
+        Set<String> strings = sharedPrefs.getStringSet(key, null);
+        if (strings == null) {
+            strings = new HashSet<String>(0);
+        } else {
+            strings = new HashSet<String>(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<ItemInfo> 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<ItemInfo> 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<String> newApps = new HashSet<String>();
-                    if (newAppsScreen == screen) {
-                        newApps = sharedPrefs.getStringSet(NEW_APPS_LIST_KEY, newApps);
-                    }
-                    synchronized (newApps) {
-                        newApps.add(intent.toUri(0).toString());
-                    }
-                    final Set<String> 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();
index 00770b2..99ebd96 100644 (file)
@@ -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 <container, screen, cellX, cellY>
      */
@@ -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
                     }