Merge change 1209 into donut

* changes:
  Make Launcher request BIND_APPWIDGET.
diff --git a/res/drawable/wallpaper_lake.jpg b/res/drawable/wallpaper_lake.jpg
new file mode 100644
index 0000000..5ba522f
--- /dev/null
+++ b/res/drawable/wallpaper_lake.jpg
Binary files differ
diff --git a/res/values/strings.xml b/res/values/strings.xml
index db9e658..3e8cb7c 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -68,7 +68,7 @@
     <string name="add_clock">Clock</string>
     <!-- Options in "Add to Home" dialog box; Name of the Picture frame widget-->
     <string name="add_photo_frame">Picture frame</string>
-    <!-- Options in "Add to Home" dialog box; Name of the Google Search widget-->
+    <!-- Options in "Add to Home" dialog box; Name of the global search widget-->
     <string name="add_search">Search</string>
     <!-- Error message when user has filled a home screen, possibly not used -->
     <string name="out_of_space">No more room on this Home screen.</string>
@@ -90,7 +90,7 @@
     <string name="menu_add">Add</string>
     <!-- Noun, menu item used to set the desktop's wallpaper -->
     <string name="menu_wallpaper">Wallpaper</string>
-    <!-- Verb, menu item used to initiate a Google Search -->
+    <!-- Verb, menu item used to initiate global search -->
     <string name="menu_search">Search</string>
     <!-- Noun, menu item used to bring down the notifications shade -->
     <string name="menu_notifications">Notifications</string>
@@ -113,7 +113,9 @@
 
     <!-- Widgets: -->
     <skip />    
-    <!-- This is the hint text shown in the search widget, before text is entered.
+
+    <!-- TODO: Determine if this can be removed.
+         This is the hint text shown in the search widget, before text is entered.
          This translation SHOULD MATCH the string "search_hint" which is found in 
          GoogleSearch/res/values/strings.xml -->
     <string name="search_hint">Google Search</string>
diff --git a/src/com/android/launcher/CellLayout.java b/src/com/android/launcher/CellLayout.java
index 157bf56..058b22c 100644
--- a/src/com/android/launcher/CellLayout.java
+++ b/src/com/android/launcher/CellLayout.java
@@ -98,6 +98,18 @@
         }
     }
 
+    @Override
+    public void cancelLongPress() {
+        super.cancelLongPress();
+
+        // Cancel long press for all children
+        final int count = getChildCount();
+        for (int i = 0; i < count; i++) {
+            final View child = getChildAt(i);
+            child.cancelLongPress();
+        }
+    }
+
     int getCountX() {
         return mPortrait ? mShortAxisCells : mLongAxisCells;
     }
@@ -927,7 +939,7 @@
         int maxVacantSpanYSpanX;
         final Rect current = new Rect();
 
-        private void clearVacantCells() {
+        void clearVacantCells() {
             final ArrayList<VacantCell> list = vacantCells;
             final int count = list.size();
 
@@ -968,6 +980,10 @@
          * @return True if a vacant cell of the specified dimension was found, false otherwise.
          */
         boolean findCellForSpan(int[] cellXY, int spanX, int spanY) {
+            return findCellForSpan(cellXY, spanX, spanY, true);
+        }
+
+        boolean findCellForSpan(int[] cellXY, int spanX, int spanY, boolean clear) {
             final ArrayList<VacantCell> list = vacantCells;
             final int count = list.size();
 
@@ -1001,7 +1017,7 @@
                 }
             }
 
-            clearVacantCells();
+            if (clear) clearVacantCells();
 
             return found;
         }
diff --git a/src/com/android/launcher/LauncherAppWidgetHostView.java b/src/com/android/launcher/LauncherAppWidgetHostView.java
index 1e21a19..da5b3a0 100644
--- a/src/com/android/launcher/LauncherAppWidgetHostView.java
+++ b/src/com/android/launcher/LauncherAppWidgetHostView.java
@@ -98,4 +98,14 @@
         mPendingCheckForLongPress.rememberWindowAttachCount();
         postDelayed(mPendingCheckForLongPress, ViewConfiguration.getLongPressTimeout());
     }
+
+    @Override
+    public void cancelLongPress() {
+        super.cancelLongPress();
+
+        mHasPerformedLongPress = false;
+        if (mPendingCheckForLongPress != null) {
+            removeCallbacks(mPendingCheckForLongPress);
+        }
+    }
 }
diff --git a/src/com/android/launcher/LauncherModel.java b/src/com/android/launcher/LauncherModel.java
index da41f14..19f6e9b 100644
--- a/src/com/android/launcher/LauncherModel.java
+++ b/src/com/android/launcher/LauncherModel.java
@@ -174,7 +174,7 @@
 
                 for (ResolveInfo info : matches) {
                     adapter.setNotifyOnChange(false);
-                    adapter.add(makeAndCacheApplicationInfo(packageManager, cache, info));
+                    adapter.add(makeAndCacheApplicationInfo(packageManager, cache, info, launcher));
                 }
 
                 adapter.sort(new ApplicationInfoComparator());
@@ -239,7 +239,7 @@
                 final ApplicationInfo applicationInfo = findIntent(adapter,
                         info.activityInfo.applicationInfo.packageName, info.activityInfo.name);
                 if (applicationInfo != null) {
-                    updateAndCacheApplicationInfo(packageManager, info, applicationInfo);
+                    updateAndCacheApplicationInfo(packageManager, info, applicationInfo, launcher);
                     changed = true;
                 }
             }
@@ -252,9 +252,9 @@
     }
 
     private void updateAndCacheApplicationInfo(PackageManager packageManager, ResolveInfo info,
-            ApplicationInfo applicationInfo) {
+            ApplicationInfo applicationInfo, Context context) {
 
-        updateApplicationInfoTitleAndIcon(packageManager, info, applicationInfo);
+        updateApplicationInfoTitleAndIcon(packageManager, info, applicationInfo, context);
 
         ComponentName componentName = new ComponentName(
                 info.activityInfo.applicationInfo.packageName, info.activityInfo.name);
@@ -326,10 +326,11 @@
                     info.activityInfo.applicationInfo.packageName, info.activityInfo.name);
             if (applicationInfo == null) {
                 toAdd.add(makeAndCacheApplicationInfo(launcher.getPackageManager(),
-                        mAppInfoCache, info));
+                        mAppInfoCache, info, launcher));
                 changed = true;
             } else {
-                updateAndCacheApplicationInfo(launcher.getPackageManager(), info, applicationInfo);
+                updateAndCacheApplicationInfo(
+                        launcher.getPackageManager(), info, applicationInfo, launcher);
                 changed = true;
             }
         }
@@ -419,7 +420,8 @@
     }
 
     private static ApplicationInfo makeAndCacheApplicationInfo(PackageManager manager,
-            HashMap<ComponentName, ApplicationInfo> appInfoCache, ResolveInfo info) {
+            HashMap<ComponentName, ApplicationInfo> appInfoCache, ResolveInfo info,
+            Context context) {
 
         ComponentName componentName = new ComponentName(
                 info.activityInfo.applicationInfo.packageName,
@@ -430,7 +432,7 @@
             application = new ApplicationInfo();
             application.container = ItemInfo.NO_ID;
 
-            updateApplicationInfoTitleAndIcon(manager, info, application);
+            updateApplicationInfoTitleAndIcon(manager, info, application, context);
 
             application.setActivity(componentName,
                     Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
@@ -442,14 +444,15 @@
     }
 
     private static void updateApplicationInfoTitleAndIcon(PackageManager manager, ResolveInfo info,
-            ApplicationInfo application) {
+            ApplicationInfo application, Context context) {
 
         application.title = info.loadLabel(manager);
         if (application.title == null) {
             application.title = info.activityInfo.name;
         }
 
-        application.icon = info.activityInfo.loadIcon(manager);
+        application.icon =
+                Utilities.createIconThumbnail(info.activityInfo.loadIcon(manager), context);
         application.filtered = false;
     }
 
@@ -495,7 +498,7 @@
                 for (int i = 0; i < count && !mStopped; i++) {
                     ResolveInfo info = apps.get(i);
                     ApplicationInfo application =
-                            makeAndCacheApplicationInfo(manager, appInfoCache, info);
+                        makeAndCacheApplicationInfo(manager, appInfoCache, info, launcher);
 
                     if (action.add(application) && !mStopped) {
                         launcher.runOnUiThread(action);
@@ -765,7 +768,7 @@
                             }
 
                             if (itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
-                                info = getApplicationInfo(manager, intent);
+                                info = getApplicationInfo(manager, intent, launcher);
                             } else {
                                 info = getApplicationInfoShortcut(c, launcher, iconTypeIndex,
                                         iconPackageIndex, iconResourceIndex, iconIndex);
@@ -1116,7 +1119,8 @@
     /**
      * Make an ApplicationInfo object for an application
      */
-    private static ApplicationInfo getApplicationInfo(PackageManager manager, Intent intent) {
+    private static ApplicationInfo getApplicationInfo(PackageManager manager, Intent intent,
+                                                      Context context) {
         final ResolveInfo resolveInfo = manager.resolveActivity(intent, 0);
 
         if (resolveInfo == null) {
@@ -1125,7 +1129,7 @@
         
         final ApplicationInfo info = new ApplicationInfo();
         final ActivityInfo activityInfo = resolveInfo.activityInfo;
-        info.icon = activityInfo.loadIcon(manager);
+        info.icon = Utilities.createIconThumbnail(activityInfo.loadIcon(manager), context);
         if (info.title == null || info.title.length() == 0) {
             info.title = activityInfo.loadLabel(manager);
         }
@@ -1154,7 +1158,7 @@
                 try {
                     Resources resources = packageManager.getResourcesForApplication(packageName);
                     final int id = resources.getIdentifier(resourceName, null, null);
-                    info.icon = resources.getDrawable(id);
+                    info.icon = Utilities.createIconThumbnail(resources.getDrawable(id), launcher);
                 } catch (Exception e) {
                     info.icon = packageManager.getDefaultActivityIcon();
                 }
@@ -1165,9 +1169,14 @@
                 break;
             case LauncherSettings.Favorites.ICON_TYPE_BITMAP:
                 byte[] data = c.getBlob(iconIndex);
-                Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
-                info.icon = new FastBitmapDrawable(
-                        Utilities.createBitmapThumbnail(bitmap, launcher));
+                try {
+                    Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
+                    info.icon = new FastBitmapDrawable(
+                            Utilities.createBitmapThumbnail(bitmap, launcher));
+                } catch (Exception e) {
+                    packageManager = launcher.getPackageManager();
+                    info.icon = packageManager.getDefaultActivityIcon();
+                }
                 info.filtered = true;
                 info.customIcon = true;
                 break;
diff --git a/src/com/android/launcher/LiveFolderIcon.java b/src/com/android/launcher/LiveFolderIcon.java
index 33cb0b7..14a4ee6 100644
--- a/src/com/android/launcher/LiveFolderIcon.java
+++ b/src/com/android/launcher/LiveFolderIcon.java
@@ -41,8 +41,8 @@
         final Resources resources = launcher.getResources();
         Drawable d = folderInfo.icon;
         if (d == null) {
-            resources.getDrawable(R.drawable.ic_launcher_folder);
-            d = Utilities.createIconThumbnail(d, launcher);
+            d = Utilities.createIconThumbnail(
+                    resources.getDrawable(R.drawable.ic_launcher_folder), launcher);
             folderInfo.filtered = true;
         }
         icon.setCompoundDrawablesWithIntrinsicBounds(null, d, null, null);
diff --git a/src/com/android/launcher/Utilities.java b/src/com/android/launcher/Utilities.java
index cb8976c..33b084b 100644
--- a/src/com/android/launcher/Utilities.java
+++ b/src/com/android/launcher/Utilities.java
@@ -16,6 +16,7 @@
 
 package com.android.launcher;
 
+import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.PaintDrawable;
 import android.graphics.Bitmap;
@@ -80,24 +81,35 @@
     static Drawable createIconThumbnail(Drawable icon, Context context) {
         if (sIconWidth == -1) {
             final Resources resources = context.getResources();
-            sIconWidth = sIconHeight = (int) resources.getDimension(
-                    android.R.dimen.app_icon_size);
+            sIconWidth = sIconHeight = (int) resources.getDimension(android.R.dimen.app_icon_size);
         }
 
         int width = sIconWidth;
         int height = sIconHeight;
 
-        final int iconWidth = icon.getIntrinsicWidth();
-        final int iconHeight = icon.getIntrinsicHeight();
-
+        float scale = 1.0f;
         if (icon instanceof PaintDrawable) {
             PaintDrawable painter = (PaintDrawable) icon;
             painter.setIntrinsicWidth(width);
             painter.setIntrinsicHeight(height);
+        } else if (icon instanceof BitmapDrawable) {
+            float displayDensity = context.getResources().getDisplayMetrics().density;
+            BitmapDrawable bitmapDrawable = (BitmapDrawable) icon;
+            Bitmap bitmap = bitmapDrawable.getBitmap();
+            float iconDensity = bitmap.getDensityScale();
+            scale = displayDensity / iconDensity;
+
+            // Scale the bitmap to the screen density size if it's not loaded at the same density.
+            if (scale != 1.0f) {
+                icon = bitmapDrawable = new BitmapDrawable(bitmap);
+                bitmapDrawable.setDensityScale(scale);
+            }
         }
+        int iconWidth = icon.getIntrinsicWidth();
+        int iconHeight = icon.getIntrinsicHeight();
 
         if (width > 0 && height > 0) {
-            if (width < iconWidth || height < iconHeight) {
+            if (width < iconWidth || height < iconHeight || scale != 1.0f) {
                 final float ratio = (float) iconWidth / iconHeight;
 
                 if (iconWidth > iconHeight) {
diff --git a/src/com/android/launcher/WallpaperChooser.java b/src/com/android/launcher/WallpaperChooser.java
index 9ac922c..c88a02a 100644
--- a/src/com/android/launcher/WallpaperChooser.java
+++ b/src/com/android/launcher/WallpaperChooser.java
@@ -60,7 +60,7 @@
     };
 
     private static final Integer[] IMAGE_IDS = {
-            com.android.internal.R.drawable.default_wallpaper,
+            R.drawable.wallpaper_lake,
             R.drawable.wallpaper_sunset,
             R.drawable.wallpaper_beach,
             R.drawable.wallpaper_snow_leopard,
diff --git a/src/com/android/launcher/Workspace.java b/src/com/android/launcher/Workspace.java
index f20572e..fe309de 100644
--- a/src/com/android/launcher/Workspace.java
+++ b/src/com/android/launcher/Workspace.java
@@ -272,6 +272,7 @@
      * @param currentScreen
      */
     void setCurrentScreen(int currentScreen) {
+        clearVacantCache();
         mCurrentScreen = Math.max(0, Math.min(currentScreen, getChildCount() - 1));
         scrollTo(mCurrentScreen * getWidth(), 0);
         invalidate();
@@ -345,6 +346,8 @@
             throw new IllegalStateException("The screen must be >= 0 and < " + getChildCount());
         }
 
+        clearVacantCache();
+
         final CellLayout group = (CellLayout) getChildAt(screen);
         CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
         if (lp == null) {
@@ -379,6 +382,13 @@
         return null;
     }
 
+    private void clearVacantCache() {
+        if (mVacantCache != null) {
+            mVacantCache.clearVacantCells();
+            mVacantCache = null;
+        }
+    }
+    
     /**
      * Returns the coordinate of a vacant cell for the current screen.
      */
@@ -457,6 +467,11 @@
     }
 
     @Override
+    public boolean isOpaque() {
+        return !mWallpaper.hasAlpha();
+    }
+
+    @Override
     protected void dispatchDraw(Canvas canvas) {
         boolean restore = false;
 
@@ -835,6 +850,7 @@
     void snapToScreen(int whichScreen) {
         if (!mScroller.isFinished()) return;
 
+        clearVacantCache();
         enableChildrenCache();
 
         whichScreen = Math.max(0, Math.min(whichScreen, getChildCount() - 1));
@@ -915,7 +931,7 @@
                     originalCellLayout.removeView(cell);
                     cellLayout.addView(cell);
                 }
-                mTargetCell = estimateDropCell(source, x - xOffset, y - yOffset,
+                mTargetCell = estimateDropCell(x - xOffset, y - yOffset,
                         mDragInfo.spanX, mDragInfo.spanY, cell, cellLayout, mTargetCell);
                 cellLayout.onDropChild(cell, mTargetCell);
 
@@ -929,7 +945,7 @@
 
     public void onDragEnter(DragSource source, int x, int y, int xOffset, int yOffset,
             Object dragInfo) {
-        mVacantCache = null;
+        clearVacantCache();
     }
 
     public void onDragOver(DragSource source, int x, int y, int xOffset, int yOffset,
@@ -938,7 +954,7 @@
 
     public void onDragExit(DragSource source, int x, int y, int xOffset, int yOffset,
             Object dragInfo) {
-        mVacantCache = null;
+        clearVacantCache();
     }
 
     private void onDropExternal(int x, int y, Object dragInfo, CellLayout cellLayout) {
@@ -972,7 +988,7 @@
 
         cellLayout.addView(view, insertAtFirst ? 0 : -1);
         view.setOnLongClickListener(mLongClickListener);
-        mTargetCell = estimateDropCell(null, x, y, 1, 1, view, cellLayout, mTargetCell);
+        mTargetCell = estimateDropCell(x, y, 1, 1, view, cellLayout, mTargetCell);
         cellLayout.onDropChild(view, mTargetCell);
         CellLayout.LayoutParams lp = (CellLayout.LayoutParams) view.getLayoutParams();
 
@@ -996,8 +1012,17 @@
      */
     public boolean acceptDrop(DragSource source, int x, int y,
             int xOffset, int yOffset, Object dragInfo) {
-        // Workspaces accept everything
-        return true;
+        final CellLayout layout = getCurrentDropLayout();
+        final CellLayout.CellInfo cellInfo = mDragInfo;
+        final int spanX = cellInfo == null ? 1 : cellInfo.spanX;
+        final int spanY = cellInfo == null ? 1 : cellInfo.spanY;
+
+        if (mVacantCache == null) {
+            final View ignoreView = cellInfo == null ? null : cellInfo.cell;
+            mVacantCache = layout.findAllVacantCells(null, ignoreView);
+        }
+
+        return mVacantCache.findCellForSpan(mTempEstimate, spanX, spanY, false);
     }
     
     /**
@@ -1015,7 +1040,7 @@
         final Rect location = recycle != null ? recycle : new Rect();
         
         // Find drop cell and convert into rectangle
-        int[] dropCell = estimateDropCell(source, x - xOffset, y - yOffset,
+        int[] dropCell = estimateDropCell(x - xOffset, y - yOffset,
                 spanX, spanY, ignoreView, layout, mTempCell);
         
         if (dropCell == null) {
@@ -1036,7 +1061,7 @@
     /**
      * Calculate the nearest cell where the given object would be dropped.
      */
-    private int[] estimateDropCell(DragSource source, int pixelX, int pixelY,
+    private int[] estimateDropCell(int pixelX, int pixelY,
             int spanX, int spanY, View ignoreView, CellLayout layout, int[] recycle) {
         // Create vacant cell cache if none exists
         if (mVacantCache == null) {
@@ -1075,14 +1100,14 @@
     }
 
     public void scrollLeft() {
-        mVacantCache = null;
+        clearVacantCache();
         if (mNextScreen == INVALID_SCREEN && mCurrentScreen > 0 && mScroller.isFinished()) {
             snapToScreen(mCurrentScreen - 1);
         }
     }
 
     public void scrollRight() {
-        mVacantCache = null;
+        clearVacantCache();
         if (mNextScreen == INVALID_SCREEN && mCurrentScreen < getChildCount() -1 &&
                 mScroller.isFinished()) {
             snapToScreen(mCurrentScreen + 1);
@@ -1264,10 +1289,6 @@
         }
     }
 
-    // TODO: remove widgets when appwidgetmanager tells us they're gone
-//    void removeAppWidgetsForProvider() {
-//    }
-
     void moveToDefaultScreen() {
         snapToScreen(mDefaultScreen);
         getChildAt(mDefaultScreen).requestFocus();