Merge branch 'froyo' into froyo-release
diff --git a/src/com/android/launcher2/AllApps2D.java b/src/com/android/launcher2/AllApps2D.java
index 86571cf..7ad5e49 100644
--- a/src/com/android/launcher2/AllApps2D.java
+++ b/src/com/android/launcher2/AllApps2D.java
@@ -109,7 +109,6 @@
             }
             info.iconBitmap.setDensity(Bitmap.DENSITY_NONE);
             textView.setCompoundDrawablesWithIntrinsicBounds(null, new BitmapDrawable(info.iconBitmap), null, null);
-            textView.setBackgroundColor(Color.BLACK);
             textView.setText(info.title);
 
             return convertView;
diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java
index 52f1224..62aaa8b 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;
@@ -91,10 +92,10 @@
 public final class Launcher extends Activity
         implements View.OnClickListener, OnLongClickListener, LauncherModel.Callbacks, AllAppsView.Watcher {
     static final String TAG = "Launcher";
-    static final boolean LOGD = false;
+    static final boolean LOGD = true;
 
     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;
@@ -586,10 +587,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;
     }
 
@@ -1885,8 +1882,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
@@ -2185,10 +2183,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 +2206,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/LauncherModel.java b/src/com/android/launcher2/LauncherModel.java
index d2cebc0..96ceb74 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
@@ -90,6 +91,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) {
@@ -439,6 +441,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;
@@ -486,7 +489,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,16 +523,7 @@
                 }
             }
 
-            public void run() {
-                waitForOtherThread();
-
-                // 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) {
-                    android.os.Process.setThreadPriority(mIsLaunching
-                            ? Process.THREAD_PRIORITY_DEFAULT : Process.THREAD_PRIORITY_BACKGROUND);
-                }
-
+            private void loadAndBindWorkspace() {
                 // Load the workspace only if it's dirty.
                 int workspaceSeq;
                 boolean workspaceDirty;
@@ -543,6 +537,10 @@
                 synchronized (mLock) {
                     // If we're not stopped, and nobody has incremented mWorkspaceSeq.
                     if (mStopped) {
+                        if (PROFILE_LOADERS) {
+                            android.os.Debug.stopMethodTracing();
+                        }
+
                         return;
                     }
                     if (workspaceSeq == mWorkspaceSeq) {
@@ -552,44 +550,9 @@
 
                 // 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");
-                    }
-                }
+            }
 
-                // Whew! Hard work done.
-                synchronized (mLock) {
-                    if (mIsLaunching) {
-                        android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
-                    }
-                }
-
+            private void loadAndBindAllAppsIfDirty() {
                 // Load all apps if they're dirty
                 int allAppsSeq;
                 boolean allAppsDirty;
@@ -613,6 +576,85 @@
                         mLastAllAppsSeq = mAllAppsSeq;
                     }
                 }
+            }
+
+            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) {
+                    android.os.Process.setThreadPriority(mIsLaunching
+                            ? Process.THREAD_PRIORITY_DEFAULT : Process.THREAD_PRIORITY_BACKGROUND);
+                }
+
+                if (PROFILE_LOADERS) {
+                    android.os.Debug.startMethodTracing("/sdcard/launcher-loaders");
+                }
+                
+                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");
+                    loadAndBindAllAppsIfDirty();
+                }
+
+                // Whew! Hard work done.
+                synchronized (mLock) {
+                    if (mIsLaunching) {
+                        android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
+                    }
+                }
+
+                // second step
+                if (loadWorkspaceFirst) {
+                    if (DEBUG_LOADERS) Log.d(TAG, "step 2: loading all apps");
+                    loadAndBindAllAppsIfDirty();
+                } 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
                 // callback runnables are done.
@@ -624,6 +666,10 @@
                     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.
                 mHandler.post(new Runnable() {
@@ -672,10 +718,6 @@
 
             // check & update map of what's occupied; used to discard overlapping/invalid items
             private boolean checkItemPlacement(ItemInfo occupied[][][], ItemInfo item) {
-                if (item.container != LauncherSettings.Favorites.CONTAINER_DESKTOP) {
-                    return true;
-                }
-
                 for (int x = item.cellX; x < (item.cellX+item.spanX); x++) {
                     for (int y = item.cellY; y < (item.cellY+item.spanY); y++) {
                         if (occupied[item.screen][x][y] != null) {
@@ -697,7 +739,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 +1070,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,9 +1128,6 @@
                             Log.d(TAG, "bound workspace in "
                                 + (SystemClock.uptimeMillis()-t) + "ms");
                         }
-                        if (Launcher.PROFILE_ROTATE) {
-                            android.os.Debug.stopMethodTracing();
-                        }
                     }
                 });
             }
@@ -1152,7 +1191,7 @@
                                     new ResolveInfo.DisplayNameComparator(packageManager));
                             if (DEBUG_LOADERS) {
                                 Log.d(TAG, "sort took "
-                                        + (SystemClock.uptimeMillis()-qiaTime) + "ms");
+                                        + (SystemClock.uptimeMillis()-sortTime) + "ms");
                             }
                         }
 
@@ -1218,7 +1257,7 @@
                 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);
             }
         }