Merge "Get the view to be used as qsb bar from the launcher directly." into jb-ub-gel-agar
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index a78e313..477c4e1 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -91,19 +91,9 @@
         </activity>
 
         <activity
-            android:name="com.android.launcher3.WidgetAdder"
-            android:label="@string/widget_adder"
-            android:icon="@mipmap/ic_launcher_home">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <category android:name="android.intent.category.LAUNCHER" />
-            </intent-filter>
-        </activity>
-
-        <activity
             android:name="com.android.launcher3.ToggleWeightWatcher"
             android:label="@string/toggle_weight_watcher"
+            android:enabled="@bool/debug_memory_enabled"
             android:icon="@mipmap/ic_launcher_home">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
diff --git a/res/values/config.xml b/res/values/config.xml
index 14e5a56..2027640 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -80,5 +80,5 @@
     <bool name="hotseat_transpose_layout_with_orientation">true</bool>
 
     <!-- Memory debugging, including a memory dump icon -->
-    <bool name="debug_memory_enabled">true</bool>
+    <bool name="debug_memory_enabled">false</bool>
 </resources>
diff --git a/src/com/android/launcher3/CropView.java b/src/com/android/launcher3/CropView.java
index 5b49282..f904643 100644
--- a/src/com/android/launcher3/CropView.java
+++ b/src/com/android/launcher3/CropView.java
@@ -17,12 +17,13 @@
 package com.android.launcher3;
 
 import android.content.Context;
-import android.graphics.Bitmap;
 import android.graphics.RectF;
 import android.util.AttributeSet;
 import android.view.MotionEvent;
 import android.view.ScaleGestureDetector;
 import android.view.ScaleGestureDetector.OnScaleGestureListener;
+import android.view.ViewTreeObserver;
+import android.view.ViewTreeObserver.OnGlobalLayoutListener;
 
 import com.android.photos.views.TiledImageRenderer.TileSource;
 import com.android.photos.views.TiledImageView;
@@ -32,6 +33,8 @@
     private ScaleGestureDetector mScaleGestureDetector;
     private float mLastX, mLastY;
     private float mMinScale;
+    private boolean mTouchEnabled = true;
+    private RectF mTempEdges = new RectF();
 
     public CropView(Context context) {
         this(context, null);
@@ -42,7 +45,7 @@
         mScaleGestureDetector = new ScaleGestureDetector(context, this);
     }
 
-    public RectF getCrop() {
+    private void getEdgesHelper(RectF edgesOut) {
         final float width = getWidth();
         final float height = getHeight();
         final float imageWidth = mRenderer.source.getImageWidth();
@@ -53,13 +56,25 @@
         float centerY = (height / 2f - mRenderer.centerY + (imageHeight - height) / 2f)
                 * scale + height / 2f;
         float leftEdge = centerX - imageWidth / 2f * scale;
+        float rightEdge = centerX + imageWidth / 2f * scale;
         float topEdge = centerY - imageHeight / 2f * scale;
+        float bottomEdge = centerY + imageHeight / 2f * scale;
 
-        float cropLeft = -leftEdge / scale;
-        float cropTop = -topEdge / scale;
-        float cropRight = cropLeft + width / scale;
-        float cropBottom = cropTop + height / scale;
-        RectF cropRect = new RectF(cropLeft, cropTop, cropRight, cropBottom);
+        edgesOut.left = leftEdge;
+        edgesOut.right = rightEdge;
+        edgesOut.top = topEdge;
+        edgesOut.bottom = bottomEdge;
+    }
+
+    public RectF getCrop() {
+        final RectF edges = mTempEdges;
+        getEdgesHelper(edges);
+        final float scale = mRenderer.scale;
+
+        float cropLeft = -edges.left / scale;
+        float cropTop = -edges.top / scale;
+        float cropRight = cropLeft + getWidth() / scale;
+        float cropBottom = cropTop + getHeight() / scale;
 
         return new RectF(cropLeft, cropTop, cropRight, cropBottom);
     }
@@ -102,8 +117,32 @@
     public void onScaleEnd(ScaleGestureDetector detector) {
     }
 
+    public void moveToUpperLeft() {
+        if (getWidth() == 0 || getHeight() == 0) {
+            final ViewTreeObserver observer = getViewTreeObserver();
+            observer.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
+                    public void onGlobalLayout() {
+                        moveToUpperLeft();
+                        getViewTreeObserver().removeOnGlobalLayoutListener(this);
+                    }
+                });
+        }
+        final RectF edges = mTempEdges;
+        getEdgesHelper(edges);
+        final float scale = mRenderer.scale;
+        mRenderer.centerX += Math.ceil(edges.left / scale);
+        mRenderer.centerY += Math.ceil(edges.top / scale);
+    }
+
+    public void setTouchEnabled(boolean enabled) {
+        mTouchEnabled = enabled;
+    }
+
     @Override
     public boolean onTouchEvent(MotionEvent event) {
+        if (!mTouchEnabled) {
+            return true;
+        }
         int action = event.getActionMasked();
         final boolean pointerUp = action == MotionEvent.ACTION_POINTER_UP;
         final int skipIndex = pointerUp ? event.getActionIndex() : -1;
@@ -133,30 +172,20 @@
             if (mRenderer.source != null) {
                 // Adjust position so that the wallpaper covers the entire area
                 // of the screen
-                final float width = getWidth();
-                final float height = getHeight();
-                final float imageWidth = mRenderer.source.getImageWidth();
-                final float imageHeight = mRenderer.source.getImageHeight();
+                final RectF edges = mTempEdges;
+                getEdgesHelper(edges);
                 final float scale = mRenderer.scale;
-                float centerX = (width / 2f - mRenderer.centerX + (imageWidth - width) / 2f)
-                        * scale + width / 2f;
-                float centerY = (height / 2f - mRenderer.centerY + (imageHeight - height) / 2f)
-                        * scale + height / 2f;
-                float leftEdge = centerX - imageWidth / 2f * scale;
-                float rightEdge = centerX + imageWidth / 2f * scale;
-                float topEdge = centerY - imageHeight / 2f * scale;
-                float bottomEdge = centerY + imageHeight / 2f * scale;
-                if (leftEdge > 0) {
-                    mRenderer.centerX += Math.ceil(leftEdge / scale);
+                if (edges.left > 0) {
+                    mRenderer.centerX += Math.ceil(edges.left / scale);
                 }
-                if (rightEdge < getWidth()) {
-                    mRenderer.centerX += (rightEdge - getWidth()) / scale;
+                if (edges.right < getWidth()) {
+                    mRenderer.centerX += (edges.right - getWidth()) / scale;
                 }
-                if (topEdge > 0) {
-                    mRenderer.centerY += Math.ceil(topEdge / scale);
+                if (edges.top > 0) {
+                    mRenderer.centerY += Math.ceil(edges.top / scale);
                 }
-                if (bottomEdge < getHeight()) {
-                    mRenderer.centerY += (bottomEdge - getHeight()) / scale;
+                if (edges.bottom < getHeight()) {
+                    mRenderer.centerY += (edges.bottom - getHeight()) / scale;
                 }
             }
         }
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 85bcdc0..70727c9 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -50,7 +50,6 @@
 import android.database.ContentObserver;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
-import android.graphics.Color;
 import android.graphics.Point;
 import android.graphics.PorterDuff;
 import android.graphics.Rect;
@@ -107,12 +106,8 @@
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.List;
-import java.util.Set;
 
 /**
  * Default launcher application.
@@ -1897,7 +1892,7 @@
             Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_CONFIGURE);
             intent.setComponent(appWidgetInfo.configure);
             intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
-            startActivityForResultSafely(intent, REQUEST_CREATE_APPWIDGET);
+            Utilities.startActivityForResultSafely(this, intent, REQUEST_CREATE_APPWIDGET);
         } else {
             // Otherwise just add it
             completeAddAppWidget(appWidgetId, info.container, info.screenId, boundWidget,
@@ -2003,9 +1998,9 @@
             Intent pickIntent = new Intent(Intent.ACTION_PICK_ACTIVITY);
             pickIntent.putExtra(Intent.EXTRA_INTENT, mainIntent);
             pickIntent.putExtra(Intent.EXTRA_TITLE, getText(R.string.title_select_application));
-            startActivityForResultSafely(pickIntent, REQUEST_PICK_APPLICATION);
+            Utilities.startActivityForResultSafely(this, pickIntent, REQUEST_PICK_APPLICATION);
         } else {
-            startActivityForResultSafely(intent, REQUEST_CREATE_SHORTCUT);
+            Utilities.startActivityForResultSafely(this, intent, REQUEST_CREATE_SHORTCUT);
         }
     }
 
@@ -2321,19 +2316,6 @@
         return success;
     }
 
-    void startActivityForResultSafely(Intent intent, int requestCode) {
-        try {
-            startActivityForResult(intent, requestCode);
-        } catch (ActivityNotFoundException e) {
-            Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
-        } catch (SecurityException e) {
-            Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
-            Log.e(TAG, "Launcher does not have the permission to launch " + intent +
-                    ". Make sure to create a MAIN intent-filter for the corresponding activity " +
-                    "or use the exported attribute for this activity.", e);
-        }
-    }
-
     private void handleFolderClick(FolderIcon folderIcon) {
         final FolderInfo info = folderIcon.getFolderInfo();
         Folder openFolder = mWorkspace.getFolderForTag(info);
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index e8103f5..d80c2ac 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -784,8 +784,8 @@
                 ItemInfo item = new ItemInfo();
                 item.cellX = c.getInt(cellXIndex);
                 item.cellY = c.getInt(cellYIndex);
-                item.spanX = c.getInt(spanXIndex);
-                item.spanY = c.getInt(spanYIndex);
+                item.spanX = Math.max(1, c.getInt(spanXIndex));
+                item.spanY = Math.max(1, c.getInt(spanYIndex));
                 item.container = c.getInt(containerIndex);
                 item.itemType = c.getInt(itemTypeIndex);
                 item.screenId = c.getInt(screenIndex);
diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java
index 0529cfb..90db5ab 100644
--- a/src/com/android/launcher3/Utilities.java
+++ b/src/com/android/launcher3/Utilities.java
@@ -16,9 +16,10 @@
 
 package com.android.launcher3;
 
-import java.util.Random;
-
+import android.app.Activity;
+import android.content.ActivityNotFoundException;
 import android.content.Context;
+import android.content.Intent;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.BlurMaskFilter;
@@ -28,19 +29,17 @@
 import android.graphics.Matrix;
 import android.graphics.Paint;
 import android.graphics.PaintFlagsDrawFilter;
-import android.graphics.PorterDuff;
 import android.graphics.Rect;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.PaintDrawable;
 import android.util.DisplayMetrics;
+import android.util.Log;
 import android.view.View;
-import android.view.ViewGroup;
+import android.widget.Toast;
 
 import java.util.ArrayList;
 
-import com.android.launcher3.R;
-
 /**
  * Various utilities shared amongst the Launcher's classes.
  */
@@ -298,4 +297,18 @@
         sIconWidth = sIconHeight = widthPx;
         sIconTextureWidth = sIconTextureHeight = widthPx;
     }
+
+    public static void startActivityForResultSafely(
+            Activity activity, Intent intent, int requestCode) {
+        try {
+            activity.startActivityForResult(intent, requestCode);
+        } catch (ActivityNotFoundException e) {
+            Toast.makeText(activity, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
+        } catch (SecurityException e) {
+            Toast.makeText(activity, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
+            Log.e(TAG, "Launcher does not have the permission to launch " + intent +
+                    ". Make sure to create a MAIN intent-filter for the corresponding activity " +
+                    "or use the exported attribute for this activity.", e);
+        }
+    }
 }
diff --git a/src/com/android/launcher3/WallpaperPickerActivity.java b/src/com/android/launcher3/WallpaperPickerActivity.java
index 0327421..bad8460 100644
--- a/src/com/android/launcher3/WallpaperPickerActivity.java
+++ b/src/com/android/launcher3/WallpaperPickerActivity.java
@@ -61,6 +61,7 @@
     private static final String TAG = "Launcher.WallpaperPickerActivity";
 
     private static final int IMAGE_PICK = 5;
+    private static final int PICK_WALLPAPER_THIRD_PARTY_ACTIVITY = 6;
     private static final float WALLPAPER_SCREENS_SPAN = 2f;
 
     private ArrayList<Integer> mThumbs;
@@ -91,13 +92,17 @@
             if (meta.mLaunchesGallery) {
                 Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
                 intent.setType("image/*");
-                startActivityForResult(intent, IMAGE_PICK);
+                Utilities.startActivityForResultSafely(
+                        WallpaperPickerActivity.this, intent, IMAGE_PICK);
             } else if (meta.mGalleryImageUri != null) {
                 mCropView.setTileSource(new BitmapRegionTileSource(WallpaperPickerActivity.this,
                         meta.mGalleryImageUri, 1024, 0), null);
+                mCropView.setTouchEnabled(true);
             } else {
                 mCropView.setTileSource(new BitmapRegionTileSource(WallpaperPickerActivity.this,
                         meta.mWallpaperResId, 1024, 0), null);
+                mCropView.setTouchEnabled(false);
+                mCropView.moveToUpperLeft();
             }
         }
     };
@@ -150,6 +155,10 @@
             meta.mGalleryImageUri = uri;
             pickedImageThumbnail.setTag(meta);
             mThumbnailOnClickListener.onClick(pickedImageThumbnail);
+        } else if (requestCode == PICK_WALLPAPER_THIRD_PARTY_ACTIVITY) {
+            // No result code is returned; just return
+            setResult(RESULT_OK);
+            finish();
         }
     }
 
@@ -242,6 +251,16 @@
         frameLayout.setForeground(new ZeroPaddingDrawable(frameLayout.getForeground()));
     }
 
+    public boolean onMenuItemSelected(int featureId, MenuItem item) {
+        if (item.getIntent() == null) {
+            return super.onMenuItemSelected(featureId, item);
+        } else {
+            Utilities.startActivityForResultSafely(
+                    this, item.getIntent(), PICK_WALLPAPER_THIRD_PARTY_ACTIVITY);
+            return true;
+        }
+    }
+
     @Override
     public boolean onCreateOptionsMenu(Menu menu) {
         final Intent pickWallpaperIntent = new Intent(Intent.ACTION_SET_WALLPAPER);
@@ -266,21 +285,25 @@
 
         outerLoop:
         for (ResolveInfo info : apps) {
-            final ComponentName componentName =
+            final ComponentName itemComponentName =
                     new ComponentName(info.activityInfo.packageName, info.activityInfo.name);
+            final String itemPackageName = itemComponentName.getPackageName();
             // Exclude anything from our own package, and the old Launcher
-            if (componentName.getPackageName().equals(getPackageName()) ||
-                    componentName.getPackageName().equals("com.android.launcher")) {
+            if (itemPackageName.equals(getPackageName()) ||
+                    itemPackageName.equals("com.android.launcher")) {
                 continue;
             }
             // Exclude any package that already responds to the image picker intent
             for (ResolveInfo imagePickerActivityInfo : imagePickerActivities) {
-                if (componentName.getPackageName().equals(
+                if (itemPackageName.equals(
                         imagePickerActivityInfo.activityInfo.packageName)) {
                     continue outerLoop;
                 }
             }
             MenuItem mi = sub.add(info.loadLabel(pm));
+            Intent launchIntent = new Intent(Intent.ACTION_SET_WALLPAPER);
+            launchIntent.setComponent(itemComponentName);
+            mi.setIntent(launchIntent);
             Drawable icon = info.loadIcon(pm);
             if (icon != null) {
                 mi.setIcon(icon);