Merge "Add pragma on java package name, for reflection purpose."
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index 36dd82b..5b46c59 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -31,7 +31,7 @@
     <string name="rename_folder_title" msgid="4544573104191526550">"Cambiar nombre de carpeta"</string>
     <string name="rename_action" msgid="6016003384693240896">"Aceptar"</string>
     <string name="cancel_action" msgid="3811860427489435048">"Cancelar"</string>
-    <string name="menu_item_add_item" msgid="6233177331075781114">"Añadir a pantalla principal"</string>
+    <string name="menu_item_add_item" msgid="6233177331075781114">"Añadir al escritorio"</string>
     <string name="group_applications" msgid="4118484163419674240">"Aplicaciones"</string>
     <string name="group_shortcuts" msgid="9133529424900391877">"Accesos directos"</string>
     <string name="group_folder" msgid="5143593791798929193">"Nueva carpeta"</string>
@@ -41,7 +41,7 @@
     <string name="add_folder" msgid="3521088587367839879">"Carpeta"</string>
     <string name="add_clock" msgid="2337943840175865746">"Reloj"</string>
     <string name="add_photo_frame" msgid="3154058437359487954">"Picture frame"</string>
-    <string name="out_of_space" msgid="8365249326091984698">"No queda espacio en esta pantalla de inicio."</string>
+    <string name="out_of_space" msgid="8365249326091984698">"No queda espacio en el escritorio."</string>
     <string name="shortcut_installed" msgid="7071557296331322355">"Se ha creado el acceso directo \"<xliff:g id="NAME">%s</xliff:g>\"."</string>
     <string name="shortcut_uninstalled" msgid="2129499669449749995">"Se ha eliminado el acceso directo \"<xliff:g id="NAME">%s</xliff:g>\"."</string>
     <string name="shortcut_duplicate" msgid="4757756326465060694">"El acceso directo \"<xliff:g id="NAME">%s</xliff:g>\" ya existe."</string>
@@ -59,9 +59,9 @@
     <string name="permdesc_install_shortcut" msgid="7429365847558984148">"Permite que una aplicación añada accesos directos sin intervención del usuario."</string>
     <string name="permlab_uninstall_shortcut" msgid="7696645932555926449">"desinstalar accesos directos"</string>
     <string name="permdesc_uninstall_shortcut" msgid="959972195916090900">"Permite que una aplicación elimine accesos directos sin intervención del usuario."</string>
-    <string name="permlab_read_settings" msgid="3452408290738106747">"leer información de accesos directos y de configuración de la página de inicio"</string>
-    <string name="permdesc_read_settings" msgid="8377434937176025492">"Permite que una aplicación lea la información de configuración y accesos directos de la página de inicio."</string>
-    <string name="permlab_write_settings" msgid="1360567537236705628">"escribir información de accesos directos y de configuración de la página de inicio"</string>
+    <string name="permlab_read_settings" msgid="3452408290738106747">"leer información de accesos directos y de configuración del escritorio"</string>
+    <string name="permdesc_read_settings" msgid="8377434937176025492">"Permite que una aplicación lea la información de configuración y accesos directos del escritorio."</string>
+    <string name="permlab_write_settings" msgid="1360567537236705628">"escribir información de accesos directos y de configuración del escritorio"</string>
     <string name="permdesc_write_settings" msgid="1098648778383349818">"Permite que una aplicación modifique la configuración y los accesos directos de la página de inicio."</string>
     <string name="gadget_error_text" msgid="8359351016167075858">"Problema al cargar el widget"</string>
 </resources>
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index 9ffc89c..0705787 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -19,7 +19,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="application_name" msgid="8424725141379931883">"启动程序"</string>
+    <string name="application_name" msgid="8424725141379931883">"启动器"</string>
     <string name="uid_name" msgid="3371120195364560632">"Android 核心应用程序"</string>
     <string name="folder_name" msgid="4588446541914685904">"文件夹"</string>
     <string name="chooser_wallpaper" msgid="5988031014201479733">"选择壁纸来源"</string>
diff --git a/src/com/android/launcher2/AllApps3D.java b/src/com/android/launcher2/AllApps3D.java
index 36e19ce..1279ff8 100644
--- a/src/com/android/launcher2/AllApps3D.java
+++ b/src/com/android/launcher2/AllApps3D.java
@@ -148,7 +148,6 @@
         super(context, attrs);
         setFocusable(true);
         setSoundEffectsEnabled(false);
-        getHolder().setFormat(PixelFormat.TRANSLUCENT);
         final ViewConfiguration config = ViewConfiguration.get(context);
         mSlop = config.getScaledTouchSlop();
         mMaxFlingVelocity = config.getScaledMaximumFlingVelocity();
@@ -939,7 +938,23 @@
         public void run() {
             sRollo.mScrollPos = ((float)mData[0]) / (1 << 16);
             mVelocity = ((float)mData[1]) / (1 << 16);
+
+            boolean lastVisible = isVisible();
             mZoom = ((float)mData[2]) / (1 << 16);
+
+            final boolean visible = isVisible();
+            if (visible != lastVisible) {
+                post(new Runnable() {
+                    public void run() {
+                        if (visible) {
+                            showSurface();
+                        } else {
+                            hideSurface();
+                        }
+                    }
+                });
+            }
+
             sZoomDirty = false;
         }
     }
diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java
index 52f1224..6bd915a 100644
--- a/src/com/android/launcher2/Launcher.java
+++ b/src/com/android/launcher2/Launcher.java
@@ -49,6 +49,7 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Parcelable;
+import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.provider.LiveFolders;
 import android.text.Selection;
@@ -94,7 +95,7 @@
     static final boolean LOGD = false;
 
     static final boolean PROFILE_STARTUP = false;
-    static final boolean PROFILE_ROTATE = false;
+    static final boolean DEBUG_WIDGETS = false;
     static final boolean DEBUG_USER_INTERFACE = false;
 
     private static final int WALLPAPER_SCREENS_SPAN = 2;
@@ -246,11 +247,6 @@
             android.os.Debug.stopMethodTracing();
         }
 
-        // We have a new AllAppsView, we need to re-bind everything, and it could have
-        // changed in our absence.
-        mModel.setAllAppsDirty();
-        mModel.setWorkspaceDirty();
-
         if (!mRestoring) {
             mModel.startLoader(this, true);
         }
@@ -586,10 +582,6 @@
         // Flag the loader to stop early before switching
         mModel.stopLoader();
         mAllAppsGrid.surrender();
-
-        if (PROFILE_ROTATE) {
-            android.os.Debug.startMethodTracing("/sdcard/launcher-rotate");
-        }
         return Boolean.TRUE;
     }
 
@@ -1859,7 +1851,6 @@
 
                 if (mWorkspaceLoading) {
                     lockAllApps();
-                    mModel.setWorkspaceDirty();
                     mModel.startLoader(Launcher.this, false);
                 } else {
                     final FolderIcon folderIcon = (FolderIcon)
@@ -1869,7 +1860,6 @@
                         getWorkspace().requestLayout();
                     } else {
                         lockAllApps();
-                        mModel.setWorkspaceDirty();
                         mWorkspaceLoading = true;
                         mModel.startLoader(Launcher.this, false);
                     }
@@ -1885,8 +1875,9 @@
         }
     }
 
-    boolean isAllAppsVisible() {
-        return mAllAppsGrid.isVisible();
+    // Now a part of LauncherModel.Callbacks. Used to reorder loading steps.
+    public boolean isAllAppsVisible() {
+        return (mAllAppsGrid != null) ? mAllAppsGrid.isVisible() : false;
     }
 
     // AllAppsView.Watcher
@@ -2102,7 +2093,11 @@
      * Implementation of the method from LauncherModel.Callbacks.
      */
     public int getCurrentWorkspaceScreen() {
-        return mWorkspace.getCurrentScreen();
+        if (mWorkspace != null) {
+            return mWorkspace.getCurrentScreen();
+        } else {
+            return SCREEN_COUNT / 2;
+        }
     }
 
     /**
@@ -2185,10 +2180,18 @@
      * Implementation of the method from LauncherModel.Callbacks.
      */
     public void bindAppWidget(LauncherAppWidgetInfo item) {
+        final long start = DEBUG_WIDGETS ? SystemClock.uptimeMillis() : 0;
+        if (DEBUG_WIDGETS) {
+            Log.d(TAG, "bindAppWidget: " + item);
+        }
         final Workspace workspace = mWorkspace;
 
         final int appWidgetId = item.appWidgetId;
         final AppWidgetProviderInfo appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(appWidgetId);
+        if (DEBUG_WIDGETS) {
+            Log.d(TAG, "bindAppWidget: id=" + item.appWidgetId + " belongs to component " + appWidgetInfo.provider);
+        }
+
         item.hostView = mAppWidgetHost.createView(this, appWidgetId, appWidgetInfo);
 
         item.hostView.setAppWidget(appWidgetId, appWidgetInfo);
@@ -2200,6 +2203,11 @@
         workspace.requestLayout();
 
         mDesktopItems.add(item);
+
+        if (DEBUG_WIDGETS) {
+            Log.d(TAG, "bound widget id="+item.appWidgetId+" in "
+                    + (SystemClock.uptimeMillis()-start) + "ms");
+        }
     }
 
     /**
diff --git a/src/com/android/launcher2/LauncherApplication.java b/src/com/android/launcher2/LauncherApplication.java
index be448a8..eda92d9 100644
--- a/src/com/android/launcher2/LauncherApplication.java
+++ b/src/com/android/launcher2/LauncherApplication.java
@@ -73,8 +73,6 @@
     private final ContentObserver mFavoritesObserver = new ContentObserver(new Handler()) {
         @Override
         public void onChange(boolean selfChange) {
-            // TODO: lockAllApps();
-            mModel.setWorkspaceDirty();
             mModel.startLoader(LauncherApplication.this, false);
         }
     };
diff --git a/src/com/android/launcher2/LauncherModel.java b/src/com/android/launcher2/LauncherModel.java
index d2cebc0..17f7573 100644
--- a/src/com/android/launcher2/LauncherModel.java
+++ b/src/com/android/launcher2/LauncherModel.java
@@ -60,6 +60,7 @@
  */
 public class LauncherModel extends BroadcastReceiver {
     static final boolean DEBUG_LOADERS = false;
+    static final boolean PROFILE_LOADERS = false;
     static final String TAG = "Launcher.Model";
 
     private int mBatchSize; // 0 is all apps at once
@@ -70,6 +71,12 @@
     private DeferredHandler mHandler = new DeferredHandler();
     private Loader mLoader = new Loader();
 
+    // We start off with everything not loaded.  After that, we assume that
+    // our monitoring of the package manager provides all updates and we never
+    // need to do a requery.  These are only ever touched from the loader thread.
+    private boolean mWorkspaceLoaded;
+    private boolean mAllAppsLoaded;
+
     private boolean mBeforeFirstLoad = true; // only access this from main thread
     private WeakReference<Callbacks> mCallbacks;
 
@@ -90,6 +97,7 @@
         public void bindAppsAdded(ArrayList<ApplicationInfo> apps);
         public void bindAppsUpdated(ArrayList<ApplicationInfo> apps);
         public void bindAppsRemoved(ArrayList<ApplicationInfo> apps);
+        public boolean isAllAppsVisible();
     }
 
     LauncherModel(LauncherApplication app, IconCache iconCache) {
@@ -285,17 +293,6 @@
     }
 
     /**
-     * We pick up most of the changes to all apps.
-     */
-    public void setAllAppsDirty() {
-        mLoader.setAllAppsDirty();
-    }
-
-    public void setWorkspaceDirty() {
-        mLoader.setWorkspaceDirty();
-    }
-
-    /**
      * Call from the handler for ACTION_PACKAGE_ADDED, ACTION_PACKAGE_REMOVED and
      * ACTION_PACKAGE_CHANGED.
      */
@@ -307,13 +304,13 @@
         ArrayList<ApplicationInfo> removed = null;
         ArrayList<ApplicationInfo> modified = null;
 
-        synchronized (mAllAppsListLock) {
-            if (mBeforeFirstLoad) {
-                // If we haven't even loaded yet, don't bother, since we'll just pick
-                // up the changes.
-                return;
-            }
+        if (mBeforeFirstLoad) {
+            // If we haven't even loaded yet, don't bother, since we'll just pick
+            // up the changes.
+            return;
+        }
 
+        synchronized (mAllAppsListLock) {
             final String action = intent.getAction();
 
             if (Intent.ACTION_PACKAGE_CHANGED.equals(action)
@@ -396,8 +393,9 @@
                      if (packages == null || packages.length == 0) {
                          return;
                      }
-                     setAllAppsDirty();
-                     setWorkspaceDirty();
+                     synchronized (this) {
+                         mAllAppsLoaded = mWorkspaceLoaded = false;
+                     }
                      startLoader(context, false);
                 } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) {
                      String packages[] = intent.getStringArrayExtra(
@@ -405,8 +403,9 @@
                      if (packages == null || packages.length == 0) {
                          return;
                      }
-                     setAllAppsDirty();
-                     setWorkspaceDirty();
+                     synchronized (this) {
+                         mAllAppsLoaded = mWorkspaceLoaded = false;
+                     }
                      startLoader(context, false);
                 }
             }
@@ -418,12 +417,6 @@
 
         private LoaderThread mLoaderThread;
 
-        private int mLastWorkspaceSeq = 0;
-        private int mWorkspaceSeq = 1;
-
-        private int mLastAllAppsSeq = 0;
-        private int mAllAppsSeq = 1;
-
         final ArrayList<ItemInfo> mItems = new ArrayList<ItemInfo>();
         final ArrayList<LauncherAppWidgetInfo> mAppWidgets = new ArrayList<LauncherAppWidgetInfo>();
         final HashMap<Long, FolderInfo> mFolders = new HashMap<Long, FolderInfo>();
@@ -439,6 +432,7 @@
                 if (DEBUG_LOADERS) {
                     Log.d(TAG, "startLoader isLaunching=" + isLaunching);
                 }
+
                 // Don't bother to start the thread if we know it's not going to do anything
                 if (mCallbacks != null && mCallbacks.get() != null) {
                     LoaderThread oldThread = mLoaderThread;
@@ -463,18 +457,6 @@
             }
         }
 
-        public void setWorkspaceDirty() {
-            synchronized (mLock) {
-                mWorkspaceSeq++;
-            }
-        }
-
-        public void setAllAppsDirty() {
-            synchronized (mLock) {
-                mAllAppsSeq++;
-            }
-        }
-
         /**
          * Runnable for the thread that loads the contents of the launcher:
          *   - workspace icons
@@ -486,7 +468,7 @@
             private Thread mWaitThread;
             private boolean mIsLaunching;
             private boolean mStopped;
-            private boolean mWorkspaceDoneBinding;
+            private boolean mLoadAndBindStepFinished;
 
             LoaderThread(Context context, Thread waitThread, boolean isLaunching) {
                 mContext = context;
@@ -520,9 +502,77 @@
                 }
             }
 
+            private void loadAndBindWorkspace() {
+                // Load the workspace
+
+                // Other other threads can unset mWorkspaceLoaded, so atomically set it,
+                // and then if they unset it, or we unset it because of mStopped, it will
+                // be unset.
+                boolean loaded;
+                synchronized (this) {
+                    loaded = mWorkspaceLoaded;
+                    mWorkspaceLoaded = true;
+                }
+
+                // For now, just always reload the workspace.  It's ~100 ms vs. the
+                // binding which takes many hundreds of ms.
+                // We can reconsider.
+                if (DEBUG_LOADERS) Log.d(TAG, "loadAndBindWorkspace loaded=" + loaded);
+                if (true || !loaded) {
+                    loadWorkspace();
+                    if (mStopped) {
+                        mWorkspaceLoaded = false;
+                        return;
+                    }
+                }
+
+                // Bind the workspace
+                bindWorkspace();
+            }
+
+            private void waitForIdle() {
+                // Wait until the either we're stopped or the other threads are done.
+                // This way we don't start loading all apps until the workspace has settled
+                // down.
+                synchronized (LoaderThread.this) {
+                    final long workspaceWaitTime = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;
+
+                    mHandler.postIdle(new Runnable() {
+                            public void run() {
+                                synchronized (LoaderThread.this) {
+                                    mLoadAndBindStepFinished = true;
+                                    if (DEBUG_LOADERS) {
+                                        Log.d(TAG, "done with previous binding step");
+                                    }
+                                    LoaderThread.this.notify();
+                                }
+                            }
+                        });
+
+                    while (!mStopped && !mLoadAndBindStepFinished) {
+                        try {
+                            this.wait();
+                        } catch (InterruptedException ex) {
+                            // Ignore
+                        }
+                    }
+                    if (DEBUG_LOADERS) {
+                        Log.d(TAG, "waited "
+                                + (SystemClock.uptimeMillis()-workspaceWaitTime) 
+                                + "ms for previous step to finish binding");
+                    }
+                }
+            }
+
             public void run() {
                 waitForOtherThread();
 
+                // Optimize for end-user experience: if the Launcher is up and // running with the
+                // All Apps interface in the foreground, load All Apps first. Otherwise, load the
+                // workspace first (default).
+                final Callbacks cbk = mCallbacks.get();
+                final boolean loadWorkspaceFirst = cbk != null ? (!cbk.isAllAppsVisible()) : true;
+
                 // Elevate priority when Home launches for the first time to avoid
                 // starving at boot time. Staring at a blank home is not cool.
                 synchronized (mLock) {
@@ -530,57 +580,16 @@
                             ? Process.THREAD_PRIORITY_DEFAULT : Process.THREAD_PRIORITY_BACKGROUND);
                 }
 
-                // Load the workspace only if it's dirty.
-                int workspaceSeq;
-                boolean workspaceDirty;
-                synchronized (mLock) {
-                    workspaceSeq = mWorkspaceSeq;
-                    workspaceDirty = mWorkspaceSeq != mLastWorkspaceSeq;
+                if (PROFILE_LOADERS) {
+                    android.os.Debug.startMethodTracing("/sdcard/launcher-loaders");
                 }
-                if (workspaceDirty) {
-                    loadWorkspace();
-                }
-                synchronized (mLock) {
-                    // If we're not stopped, and nobody has incremented mWorkspaceSeq.
-                    if (mStopped) {
-                        return;
-                    }
-                    if (workspaceSeq == mWorkspaceSeq) {
-                        mLastWorkspaceSeq = mWorkspaceSeq;
-                    }
-                }
-
-                // Bind the workspace
-                bindWorkspace();
                 
-                // Wait until the either we're stopped or the other threads are done.
-                // This way we don't start loading all apps until the workspace has settled
-                // down.
-                synchronized (LoaderThread.this) {
-                    mHandler.postIdle(new Runnable() {
-                            public void run() {
-                                synchronized (LoaderThread.this) {
-                                    mWorkspaceDoneBinding = true;
-                                    if (DEBUG_LOADERS) {
-                                        Log.d(TAG, "done with workspace");
-                                        }
-                                    LoaderThread.this.notify();
-                                }
-                            }
-                        });
-                    if (DEBUG_LOADERS) {
-                        Log.d(TAG, "waiting to be done with workspace");
-                    }
-                    while (!mStopped && !mWorkspaceDoneBinding) {
-                        try {
-                            this.wait();
-                        } catch (InterruptedException ex) {
-                            // Ignore
-                        }
-                    }
-                    if (DEBUG_LOADERS) {
-                        Log.d(TAG, "done waiting to be done with workspace");
-                    }
+                if (loadWorkspaceFirst) {
+                    if (DEBUG_LOADERS) Log.d(TAG, "step 1: loading workspace");
+                    loadAndBindWorkspace();
+                } else {
+                    if (DEBUG_LOADERS) Log.d(TAG, "step 1: special: loading all apps");
+                    loadAndBindAllApps();
                 }
 
                 // Whew! Hard work done.
@@ -590,28 +599,13 @@
                     }
                 }
 
-                // Load all apps if they're dirty
-                int allAppsSeq;
-                boolean allAppsDirty;
-                synchronized (mLock) {
-                    allAppsSeq = mAllAppsSeq;
-                    allAppsDirty = mAllAppsSeq != mLastAllAppsSeq;
-                    if (DEBUG_LOADERS) {
-                        Log.d(TAG, "mAllAppsSeq=" + mAllAppsSeq
-                                + " mLastAllAppsSeq=" + mLastAllAppsSeq + " allAppsDirty");
-                    }
-                }
-                if (allAppsDirty) {
+                // second step
+                if (loadWorkspaceFirst) {
+                    if (DEBUG_LOADERS) Log.d(TAG, "step 2: loading all apps");
                     loadAndBindAllApps();
-                }
-                synchronized (mLock) {
-                    // If we're not stopped, and nobody has incremented mAllAppsSeq.
-                    if (mStopped) {
-                        return;
-                    }
-                    if (allAppsSeq == mAllAppsSeq) {
-                        mLastAllAppsSeq = mAllAppsSeq;
-                    }
+                } else {
+                    if (DEBUG_LOADERS) Log.d(TAG, "step 2: special: loading workspace");
+                    loadAndBindWorkspace();
                 }
 
                 // Clear out this reference, otherwise we end up holding it until all of the
@@ -624,8 +618,12 @@
                     mLoaderThread = null;
                 }
 
+                if (PROFILE_LOADERS) {
+                    android.os.Debug.stopMethodTracing();
+                }
+
                 // Trigger a gc to try to clean up after the stuff is done, since the
-                // renderscript allocations aren't charge to the java heap.
+                // renderscript allocations aren't charged to the java heap.
                 mHandler.post(new Runnable() {
                         public void run() {
                             System.gc();
@@ -697,7 +695,7 @@
             }
 
             private void loadWorkspace() {
-                long t = SystemClock.uptimeMillis();
+                final long t = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;
 
                 final Context context = mContext;
                 final ContentResolver contentResolver = context.getContentResolver();
@@ -1028,7 +1026,7 @@
                     }
                 });
                 // Wait until the queue goes empty.
-                mHandler.postIdle(new Runnable() {
+                mHandler.post(new Runnable() {
                     public void run() {
                         if (DEBUG_LOADERS) {
                             Log.d(TAG, "Going to start binding widgets soon.");
@@ -1086,14 +1084,60 @@
                             Log.d(TAG, "bound workspace in "
                                 + (SystemClock.uptimeMillis()-t) + "ms");
                         }
-                        if (Launcher.PROFILE_ROTATE) {
-                            android.os.Debug.stopMethodTracing();
-                        }
                     }
                 });
             }
 
             private void loadAndBindAllApps() {
+                // Other other threads can unset mAllAppsLoaded, so atomically set it,
+                // and then if they unset it, or we unset it because of mStopped, it will
+                // be unset.
+                boolean loaded;
+                synchronized (this) {
+                    loaded = mAllAppsLoaded;
+                    mAllAppsLoaded = true;
+                }
+
+                if (DEBUG_LOADERS) Log.d(TAG, "loadAndBindAllApps loaded=" + loaded);
+                if (!loaded) {
+                    loadAllAppsByBatch();
+                    if (mStopped) {
+                        mAllAppsLoaded = false;
+                        return;
+                    }
+                } else {
+                    onlyBindAllApps();
+                }
+            }
+
+            private void onlyBindAllApps() {
+                final Callbacks oldCallbacks = mCallbacks.get();
+                if (oldCallbacks == null) {
+                    // This launcher has exited and nobody bothered to tell us.  Just bail.
+                    Log.w(TAG, "LoaderThread running with no launcher (onlyBindAllApps)");
+                    return;
+                }
+
+                // shallow copy
+                final ArrayList<ApplicationInfo> list
+                        = (ArrayList<ApplicationInfo>)mAllAppsList.data.clone();
+                mHandler.post(new Runnable() {
+                    public void run() {
+                        final long t = SystemClock.uptimeMillis();
+                        final Callbacks callbacks = tryGetCallbacks(oldCallbacks);
+                        if (callbacks != null) {
+                            callbacks.bindAllApplications(list);
+                        }
+                        if (DEBUG_LOADERS) {
+                            Log.d(TAG, "bound all " + list.size() + " apps from cache in "
+                                    + (SystemClock.uptimeMillis()-t) + "ms");
+                        }
+                    }
+                });
+
+            }
+
+            private void loadAllAppsByBatch() {
                 final long t = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;
 
                 // Don't use these two variables in any of the callback runnables.
@@ -1101,7 +1145,7 @@
                 final Callbacks oldCallbacks = mCallbacks.get();
                 if (oldCallbacks == null) {
                     // This launcher has exited and nobody bothered to tell us.  Just bail.
-                    Log.w(TAG, "LoaderThread running with no launcher (loadAndBindAllApps)");
+                    Log.w(TAG, "LoaderThread running with no launcher (loadAllAppsByBatch)");
                     return;
                 }
 
@@ -1152,7 +1196,7 @@
                                     new ResolveInfo.DisplayNameComparator(packageManager));
                             if (DEBUG_LOADERS) {
                                 Log.d(TAG, "sort took "
-                                        + (SystemClock.uptimeMillis()-qiaTime) + "ms");
+                                        + (SystemClock.uptimeMillis()-sortTime) + "ms");
                             }
                         }
 
@@ -1218,15 +1262,11 @@
                 Log.d(TAG, "mLoader.mLoaderThread.mWaitThread=" + mWaitThread);
                 Log.d(TAG, "mLoader.mLoaderThread.mIsLaunching=" + mIsLaunching);
                 Log.d(TAG, "mLoader.mLoaderThread.mStopped=" + mStopped);
-                Log.d(TAG, "mLoader.mLoaderThread.mWorkspaceDoneBinding=" + mWorkspaceDoneBinding);
+                Log.d(TAG, "mLoader.mLoaderThread.mLoadAndBindStepFinished=" + mLoadAndBindStepFinished);
             }
         }
 
         public void dumpState() {
-            Log.d(TAG, "mLoader.mLastWorkspaceSeq=" + mLoader.mLastWorkspaceSeq);
-            Log.d(TAG, "mLoader.mWorkspaceSeq=" + mLoader.mWorkspaceSeq);
-            Log.d(TAG, "mLoader.mLastAllAppsSeq=" + mLoader.mLastAllAppsSeq);
-            Log.d(TAG, "mLoader.mAllAppsSeq=" + mLoader.mAllAppsSeq);
             Log.d(TAG, "mLoader.mItems size=" + mLoader.mItems.size());
             if (mLoaderThread != null) {
                 mLoaderThread.dumpState();