Ensuring that unbind calls are not queued in the worker thread and executed subsequently on the main thread.  (Bug 7001531)

Change-Id: I677242c0952d6385ca229ba300fdd5a2a7908a8a
diff --git a/src/com/android/launcher2/DeferredHandler.java b/src/com/android/launcher2/DeferredHandler.java
index b7e48b1..cee27df 100644
--- a/src/com/android/launcher2/DeferredHandler.java
+++ b/src/com/android/launcher2/DeferredHandler.java
@@ -16,12 +16,13 @@
 
 package com.android.launcher2;
 
-import java.util.LinkedList;
-
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
 import android.os.MessageQueue;
+import android.util.Pair;
+import java.util.LinkedList;
+import java.util.ListIterator;
 
 /**
  * Queue of things to run on a looper thread.  Items posted with {@link #post} will not
@@ -31,18 +32,20 @@
  * This class is fifo.
  */
 public class DeferredHandler {
-    private LinkedList<Runnable> mQueue = new LinkedList<Runnable>();
+    private LinkedList<Pair<Runnable, Integer>> mQueue = new LinkedList<Pair<Runnable, Integer>>();
     private MessageQueue mMessageQueue = Looper.myQueue();
     private Impl mHandler = new Impl();
 
     private class Impl extends Handler implements MessageQueue.IdleHandler {
         public void handleMessage(Message msg) {
+            Pair<Runnable, Integer> p;
             Runnable r;
             synchronized (mQueue) {
                 if (mQueue.size() == 0) {
                     return;
                 }
-                r = mQueue.removeFirst();
+                p = mQueue.removeFirst();
+                r = p.first;
             }
             r.run();
             synchronized (mQueue) {
@@ -73,8 +76,11 @@
 
     /** Schedule runnable to run after everything that's on the queue right now. */
     public void post(Runnable runnable) {
+        post(runnable, 0);
+    }
+    public void post(Runnable runnable, int type) {
         synchronized (mQueue) {
-            mQueue.add(runnable);
+            mQueue.add(new Pair<Runnable, Integer>(runnable, type));
             if (mQueue.size() == 1) {
                 scheduleNextLocked();
             }
@@ -83,7 +89,10 @@
 
     /** Schedule runnable to run when the queue goes idle. */
     public void postIdle(final Runnable runnable) {
-        post(new IdleRunnable(runnable));
+        postIdle(runnable, 0);
+    }
+    public void postIdle(final Runnable runnable, int type) {
+        post(new IdleRunnable(runnable), type);
     }
 
     public void cancelRunnable(Runnable runnable) {
@@ -91,6 +100,18 @@
             while (mQueue.remove(runnable)) { }
         }
     }
+    public void cancelAllRunnablesOfType(int type) {
+        synchronized (mQueue) {
+            ListIterator<Pair<Runnable, Integer>> iter = mQueue.listIterator();
+            Pair<Runnable, Integer> p;
+            while (iter.hasNext()) {
+                p = iter.next();
+                if (p.second == type) {
+                    iter.remove();
+                }
+            }
+        }
+    }
 
     public void cancel() {
         synchronized (mQueue) {
@@ -100,19 +121,20 @@
 
     /** Runs all queued Runnables from the calling thread. */
     public void flush() {
-        LinkedList<Runnable> queue = new LinkedList<Runnable>();
+        LinkedList<Pair<Runnable, Integer>> queue = new LinkedList<Pair<Runnable, Integer>>();
         synchronized (mQueue) {
             queue.addAll(mQueue);
             mQueue.clear();
         }
-        for (Runnable r : queue) {
-            r.run();
+        for (Pair<Runnable, Integer> p : queue) {
+            p.first.run();
         }
     }
 
     void scheduleNextLocked() {
         if (mQueue.size() > 0) {
-            Runnable peek = mQueue.getFirst();
+            Pair<Runnable, Integer> p = mQueue.getFirst();
+            Runnable peek = p.first;
             if (peek instanceof IdleRunnable) {
                 mMessageQueue.addIdleHandler(mHandler);
             } else {