private void runOnIcThread(Handler icHandler, final Runnable runnable) {
   if (DEBUG) {
     ThreadUtils.assertOnUiThread();
     Log.d(LOGTAG, "runOnIcThread() on thread " + icHandler.getLooper().getThread().getName());
   }
   Runnable runner =
       new Runnable() {
         @Override
         public void run() {
           try {
             Runnable queuedRunnable = mIcRunnableSync.take();
             if (DEBUG && queuedRunnable != runnable) {
               throw new IllegalThreadStateException("sync error");
             }
             queuedRunnable.run();
           } catch (InterruptedException e) {
           }
         }
       };
   try {
     // if we are not inside waitForUiThread(), runner will call the runnable
     icHandler.post(runner);
     // runnable will be called by either runner from above or waitForUiThread()
     mIcRunnableSync.put(runnable);
   } catch (InterruptedException e) {
   } finally {
     // if waitForUiThread() already called runnable, runner should not call it again
     icHandler.removeCallbacks(runner);
   }
 }
 public void endWaitForUiThread() {
   if (DEBUG) {
     ThreadUtils.assertOnUiThread();
     Log.d(LOGTAG, "endWaitForUiThread()");
   }
   try {
     mIcRunnableSync.put(mIcSignalRunnable);
   } catch (InterruptedException e) {
   }
 }