Fix 2797185: Re-enable thumbnail generation in framework

This re-enables thumbnail generation code in the framework
with a few improvements.

In addition to enabling the system to capture thumbnails,
it removes padding from the borders to account for space
overlapped by system widgets (status bar, etc.). Thus,
the contents of the bitmap are only those pixels unique to
the activity.

It also maximizes resolution of the bitmap by capturing the
image in the application's current orientation. In landscape
mode, it captures a bitmap with dimensions w x h.  In portrait,
it captures a bitmap with dimensions h x w. Where w and h are
thumbnail_width and thumbnail_height as defined in dimens.xml.

Though enabled, the change is not currently used in this
branch.  The work is being checked in here to avoid
complicated downstream merges.

Change-Id: Ifc8a4e0075d7d0697d8159589be3816ace31d70c
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 985f591..f7ccc12 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -67,6 +67,8 @@
 import android.view.ViewGroup.LayoutParams;
 import android.view.accessibility.AccessibilityEvent;
 import android.widget.AdapterView;
+import android.widget.FrameLayout;
+import android.widget.LinearLayout;
 
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -1204,19 +1206,37 @@
      * @see #onPause
      */
     public boolean onCreateThumbnail(Bitmap outBitmap, Canvas canvas) {
-        final View view = mDecor;
-        if (view == null) {
+        if (mDecor == null) {
             return false;
         }
 
-        final int vw = view.getWidth();
-        final int vh = view.getHeight();
-        final int dw = outBitmap.getWidth();
-        final int dh = outBitmap.getHeight();
+        int paddingLeft = 0;
+        int paddingRight = 0;
+        int paddingTop = 0;
+        int paddingBottom = 0;
+
+        // Find System window and use padding so we ignore space reserved for decorations
+        // like the status bar and such.
+        final FrameLayout top = (FrameLayout) mDecor;
+        for (int i = 0; i < top.getChildCount(); i++) {
+            View child = top.getChildAt(i);
+            if (child.isFitsSystemWindowsFlagSet()) {
+                paddingLeft = child.getPaddingLeft();
+                paddingRight = child.getPaddingRight();
+                paddingTop = child.getPaddingTop();
+                paddingBottom = child.getPaddingBottom();
+                break;
+            }
+        }
+        
+        final int visibleWidth = mDecor.getWidth() - paddingLeft - paddingRight;
+        final int visibleHeight = mDecor.getHeight() - paddingTop - paddingBottom;
 
         canvas.save();
-        canvas.scale(((float)dw)/vw, ((float)dh)/vh);
-        view.draw(canvas);
+        canvas.scale( (float) outBitmap.getWidth() / visibleWidth,
+                (float) outBitmap.getHeight() / visibleHeight);
+        canvas.translate(-paddingLeft, -paddingTop);
+        mDecor.draw(canvas);
         canvas.restore();
 
         return true;
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index eb7520f..d66e98b 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -285,24 +285,54 @@
      * @param maxNum The maximum number of entries to return in the list.  The
      * actual number returned may be smaller, depending on how many tasks the
      * user has started.
-     * 
+     *
+     * @param flags Optional flags
+     * @param receiver Optional receiver for delayed thumbnails
+     *
      * @return Returns a list of RunningTaskInfo records describing each of
      * the running tasks.
      * 
+     * Some thumbnails may not be available at the time of this call. The optional
+     * receiver may be used to receive those thumbnails.
+     *
      * @throws SecurityException Throws SecurityException if the caller does
      * not hold the {@link android.Manifest.permission#GET_TASKS} permission.
+     *
+     * @hide
      */
-    public List<RunningTaskInfo> getRunningTasks(int maxNum)
+    public List<RunningTaskInfo> getRunningTasks(int maxNum, int flags, IThumbnailReceiver receiver)
             throws SecurityException {
         try {
-            return (List<RunningTaskInfo>)ActivityManagerNative.getDefault()
-                    .getTasks(maxNum, 0, null);
+            return ActivityManagerNative.getDefault().getTasks(maxNum, flags, receiver);
         } catch (RemoteException e) {
             // System dead, we will be dead too soon!
             return null;
         }
     }
-    
+
+    /**
+     * Return a list of the tasks that are currently running, with
+     * the most recent being first and older ones after in order.  Note that
+     * "running" does not mean any of the task's code is currently loaded or
+     * activity -- the task may have been frozen by the system, so that it
+     * can be restarted in its previous state when next brought to the
+     * foreground.
+     *
+     * @param maxNum The maximum number of entries to return in the list.  The
+     * actual number returned may be smaller, depending on how many tasks the
+     * user has started.
+     *
+     * @return Returns a list of RunningTaskInfo records describing each of
+     * the running tasks.
+     *
+     * @throws SecurityException Throws SecurityException if the caller does
+     * not hold the {@link android.Manifest.permission#GET_TASKS} permission.
+     */
+    public List<RunningTaskInfo> getRunningTasks(int maxNum)
+            throws SecurityException {
+        return getRunningTasks(maxNum, 0, null);
+    }
+
     /**
      * Information you can retrieve about a particular Service that is
      * currently running in the system.
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 883366b..0fb2b49 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -115,6 +115,7 @@
  */
 public final class ActivityThread {
     static final String TAG = "ActivityThread";
+    private static final android.graphics.Bitmap.Config THUMBNAIL_FORMAT = Bitmap.Config.RGB_565;
     private static final boolean DEBUG = false;
     static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
     static final boolean DEBUG_BROADCAST = false;
@@ -2210,13 +2211,24 @@
                 h = mThumbnailHeight;
             }
 
-            // XXX Only set hasAlpha if needed?
-            thumbnail = Bitmap.createBitmap(w, h, Bitmap.Config.RGB_565);
-            thumbnail.eraseColor(0);
-            Canvas cv = new Canvas(thumbnail);
-            if (!r.activity.onCreateThumbnail(thumbnail, cv)) {
-                thumbnail = null;
+            // On platforms where we don't want thumbnails, set dims to (0,0)
+            if ((w > 0) && (h > 0)) {
+                View topView = r.activity.getWindow().getDecorView();
+
+                // Maximize bitmap by capturing in native aspect.
+                if (topView.getWidth() >= topView.getHeight()) {
+                    thumbnail = Bitmap.createBitmap(w, h, THUMBNAIL_FORMAT);
+                } else {
+                    thumbnail = Bitmap.createBitmap(h, w, THUMBNAIL_FORMAT);
+                }
+
+                thumbnail.eraseColor(0);
+                Canvas cv = new Canvas(thumbnail);
+                if (!r.activity.onCreateThumbnail(thumbnail, cv)) {
+                    thumbnail = null;
+                }
             }
+
         } catch (Exception e) {
             if (!mInstrumentation.onException(r.activity, e)) {
                 throw new RuntimeException(
@@ -2347,7 +2359,7 @@
             if (info != null) {
                 try {
                     // First create a thumbnail for the activity...
-                    //info.thumbnail = createThumbnailBitmap(r);
+                    info.thumbnail = createThumbnailBitmap(r);
                     info.description = r.activity.onCreateDescription();
                 } catch (Exception e) {
                     if (!mInstrumentation.onException(r.activity, e)) {
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 11e5ad1..329b2e7 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -3005,6 +3005,16 @@
     }
 
     /**
+     * Determine if this view has the FITS_SYSTEM_WINDOWS flag set.
+     * @return True if window has FITS_SYSTEM_WINDOWS set
+     *
+     * @hide
+     */
+    public boolean isFitsSystemWindowsFlagSet() {
+        return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
+    }
+
+    /**
      * Returns the visibility status for this view.
      *
      * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 99c0b3d..11f3e50 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -19,9 +19,9 @@
 -->
 <resources>
     <!-- The width that is used when creating thumbnails of applications. -->
-    <dimen name="thumbnail_width">84dp</dimen>
+    <dimen name="thumbnail_width">0dp</dimen>
     <!-- The height that is used when creating thumbnails of applications. -->
-    <dimen name="thumbnail_height">63dp</dimen>
+    <dimen name="thumbnail_height">0dp</dimen>
     <!-- The standard size (both width and height) of an application icon that
          will be displayed in the app launcher and elsewhere. -->
     <dimen name="app_icon_size">48dip</dimen>