Merge "Revert "Rename DisplayList->RenderNode""
diff --git a/api/current.txt b/api/current.txt
index c739dea..4f71a80 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -6849,6 +6849,7 @@
     field public static final int FLAG_ACTIVITY_FORWARD_RESULT = 33554432; // 0x2000000
     field public static final int FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY = 1048576; // 0x100000
     field public static final int FLAG_ACTIVITY_MULTIPLE_TASK = 134217728; // 0x8000000
+    field public static final int FLAG_ACTIVITY_NEW_DOCUMENT = 268959744; // 0x10080000
     field public static final int FLAG_ACTIVITY_NEW_TASK = 268435456; // 0x10000000
     field public static final int FLAG_ACTIVITY_NO_ANIMATION = 65536; // 0x10000
     field public static final int FLAG_ACTIVITY_NO_HISTORY = 1073741824; // 0x40000000
@@ -7645,6 +7646,7 @@
     field public static final java.lang.String FEATURE_FAKETOUCH_MULTITOUCH_JAZZHAND = "android.hardware.faketouch.multitouch.jazzhand";
     field public static final java.lang.String FEATURE_HOME_SCREEN = "android.software.home_screen";
     field public static final java.lang.String FEATURE_INPUT_METHODS = "android.software.input_methods";
+    field public static final java.lang.String FEATURE_LEANBACK = "android.software.leanback";
     field public static final java.lang.String FEATURE_LIVE_WALLPAPER = "android.software.live_wallpaper";
     field public static final java.lang.String FEATURE_LOCATION = "android.hardware.location";
     field public static final java.lang.String FEATURE_LOCATION_GPS = "android.hardware.location.gps";
@@ -7668,7 +7670,7 @@
     field public static final java.lang.String FEATURE_TELEPHONY = "android.hardware.telephony";
     field public static final java.lang.String FEATURE_TELEPHONY_CDMA = "android.hardware.telephony.cdma";
     field public static final java.lang.String FEATURE_TELEPHONY_GSM = "android.hardware.telephony.gsm";
-    field public static final java.lang.String FEATURE_TELEVISION = "android.hardware.type.television";
+    field public static final deprecated java.lang.String FEATURE_TELEVISION = "android.hardware.type.television";
     field public static final java.lang.String FEATURE_TOUCHSCREEN = "android.hardware.touchscreen";
     field public static final java.lang.String FEATURE_TOUCHSCREEN_MULTITOUCH = "android.hardware.touchscreen.multitouch";
     field public static final java.lang.String FEATURE_TOUCHSCREEN_MULTITOUCH_DISTINCT = "android.hardware.touchscreen.multitouch.distinct";
@@ -11294,6 +11296,7 @@
     field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AWB_AVAILABLE_MODES;
     field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_MAX_REGIONS;
     field public static final android.hardware.camera2.CameraMetadata.Key FLASH_INFO_AVAILABLE;
+    field public static final android.hardware.camera2.CameraMetadata.Key HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES;
     field public static final android.hardware.camera2.CameraMetadata.Key INFO_SUPPORTED_HARDWARE_LEVEL;
     field public static final android.hardware.camera2.CameraMetadata.Key JPEG_AVAILABLE_THUMBNAIL_SIZES;
     field public static final android.hardware.camera2.CameraMetadata.Key LENS_FACING;
@@ -11334,6 +11337,7 @@
     field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_ORIENTATION;
     field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_PROFILE_HUE_SAT_MAP_DIMENSIONS;
     field public static final android.hardware.camera2.CameraMetadata.Key STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES;
+    field public static final android.hardware.camera2.CameraMetadata.Key STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES;
     field public static final android.hardware.camera2.CameraMetadata.Key STATISTICS_INFO_MAX_FACE_COUNT;
     field public static final android.hardware.camera2.CameraMetadata.Key SYNC_MAX_LATENCY;
     field public static final android.hardware.camera2.CameraMetadata.Key TONEMAP_MAX_CURVE_POINTS;
@@ -11628,6 +11632,7 @@
     field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_TEST_PATTERN_MODE;
     field public static final android.hardware.camera2.CameraMetadata.Key SHADING_MODE;
     field public static final android.hardware.camera2.CameraMetadata.Key STATISTICS_FACE_DETECT_MODE;
+    field public static final android.hardware.camera2.CameraMetadata.Key STATISTICS_HOT_PIXEL_MAP_MODE;
     field public static final android.hardware.camera2.CameraMetadata.Key STATISTICS_LENS_SHADING_MAP_MODE;
     field public static final android.hardware.camera2.CameraMetadata.Key TONEMAP_CURVE_BLUE;
     field public static final android.hardware.camera2.CameraMetadata.Key TONEMAP_CURVE_GREEN;
@@ -11665,7 +11670,6 @@
     field public static final android.hardware.camera2.CameraMetadata.Key EDGE_MODE;
     field public static final android.hardware.camera2.CameraMetadata.Key FLASH_MODE;
     field public static final android.hardware.camera2.CameraMetadata.Key FLASH_STATE;
-    field public static final android.hardware.camera2.CameraMetadata.Key HOT_PIXEL_MAP;
     field public static final android.hardware.camera2.CameraMetadata.Key HOT_PIXEL_MODE;
     field public static final android.hardware.camera2.CameraMetadata.Key JPEG_GPS_COORDINATES;
     field public static final android.hardware.camera2.CameraMetadata.Key JPEG_GPS_PROCESSING_METHOD;
@@ -11702,6 +11706,8 @@
     field public static final android.hardware.camera2.CameraMetadata.Key SHADING_MODE;
     field public static final android.hardware.camera2.CameraMetadata.Key STATISTICS_FACES;
     field public static final android.hardware.camera2.CameraMetadata.Key STATISTICS_FACE_DETECT_MODE;
+    field public static final android.hardware.camera2.CameraMetadata.Key STATISTICS_HOT_PIXEL_MAP;
+    field public static final android.hardware.camera2.CameraMetadata.Key STATISTICS_HOT_PIXEL_MAP_MODE;
     field public static final android.hardware.camera2.CameraMetadata.Key STATISTICS_LENS_SHADING_MAP;
     field public static final android.hardware.camera2.CameraMetadata.Key STATISTICS_SCENE_FLICKER;
     field public static final android.hardware.camera2.CameraMetadata.Key TONEMAP_CURVE_BLUE;
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index e71d47d..079cf7a 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -878,7 +878,7 @@
     }
 
     /**
-     * Like {@link #checkOp but instead of throwing a {@link SecurityException} it
+     * Like {@link #checkOp} but instead of throwing a {@link SecurityException} it
      * returns {@link #MODE_ERRORED}.
      */
     public int checkOpNoThrow(String op, int uid, String packageName) {
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 96479e2..0175d62 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -3457,7 +3457,16 @@
      */
     public static final int FLAG_ACTIVITY_NEW_TASK = 0x10000000;
     /**
-     * <strong>Do not use this flag unless you are implementing your own
+     * This flag is used to create a new task and launch an activity into it.
+     * This flag is always paired with either {@link #FLAG_ACTIVITY_NEW_DOCUMENT}
+     * or {@link #FLAG_ACTIVITY_NEW_TASK}. In both cases these flags alone would
+     * search through existing tasks for ones matching this Intent. Only if no such
+     * task is found would a new task be created. When paired with
+     * FLAG_ACTIVITY_MULTIPLE_TASK both of these behaviors are modified to skip
+     * the search for a matching task and unconditionally start a new task.
+     *
+     * <strong>When used with {@link #FLAG_ACTIVITY_NEW_TASK} do not use this
+     * flag unless you are implementing your own
      * top-level application launcher.</strong>  Used in conjunction with
      * {@link #FLAG_ACTIVITY_NEW_TASK} to disable the
      * behavior of bringing an existing task to the foreground.  When set,
@@ -3469,12 +3478,18 @@
      * you should not use this flag unless you provide some way for a user to
      * return back to the tasks you have launched.</strong>
      *
-     * <p>This flag is ignored if
-     * {@link #FLAG_ACTIVITY_NEW_TASK} is not set.
+     * See {@link #FLAG_ACTIVITY_NEW_DOCUMENT} for details of this flag's use for
+     * creating new document tasks.
+     *
+     * <p>This flag is ignored if one of {@link #FLAG_ACTIVITY_NEW_TASK} or
+     * {@link #FLAG_ACTIVITY_NEW_TASK} is not also set.
      *
      * <p>See
      * <a href="{@docRoot}guide/topics/fundamentals/tasks-and-back-stack.html">Tasks and Back
      * Stack</a> for more information about tasks.
+     *
+     * @see #FLAG_ACTIVITY_NEW_DOCUMENT
+     * @see #FLAG_ACTIVITY_NEW_TASK
      */
     public static final int FLAG_ACTIVITY_MULTIPLE_TASK = 0x08000000;
     /**
@@ -3581,6 +3596,34 @@
      */
     public static final int FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET = 0x00080000;
     /**
+     * This flag is used to break out "documents" into separate tasks that can
+     * be reached via the Recents mechanism. Such a document is any kind of
+     * item for which an application may want to maintain multiple simultaneous
+     * instances. Examples might be text files, web pages, spreadsheets, or
+     * emails. Each such document will be in a separate task in the Recents list.
+     *
+     * <p>When set, the activity specified by this Intent will launch into a
+     * separate task rooted at that activity. The activity launched must be
+     * defined with {@link android.R.attr#launchMode} "standard" or "singleTop".
+     *
+     * <p>If FLAG_ACTIVITY_NEW_DOCUMENT is used without
+     * {@link #FLAG_ACTIVITY_MULTIPLE_TASK} then the activity manager will
+     * search for an existing task with a matching target activity and Intent
+     * data URI and relaunch that task, first finishing all activities down to
+     * the root activity and then calling the root activity's
+     * {@link android.app.Activity#onNewIntent(Intent)} method. If no existing
+     * task's root activity matches the Intent's data URI then a new task will
+     * be launched with the target activity as root.
+     *
+     * <p>When paired with {@link #FLAG_ACTIVITY_MULTIPLE_TASK} this will
+     * always create a new task. Thus the same document may be made to appear
+     * more than one time in Recents.
+     *
+     * @see #FLAG_ACTIVITY_MULTIPLE_TASK
+     */
+    public static final int FLAG_ACTIVITY_NEW_DOCUMENT =
+            FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET | FLAG_ACTIVITY_NEW_TASK;
+    /**
      * If set, this flag will prevent the normal {@link android.app.Activity#onUserLeaveHint}
      * callback from occurring on the current frontmost activity before it is
      * paused as the newly-started activity is brought to the front.
@@ -6246,6 +6289,7 @@
      * @see #FLAG_ACTIVITY_FORWARD_RESULT
      * @see #FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY
      * @see #FLAG_ACTIVITY_MULTIPLE_TASK
+     * @see #FLAG_ACTIVITY_NEW_DOCUMENT
      * @see #FLAG_ACTIVITY_NEW_TASK
      * @see #FLAG_ACTIVITY_NO_ANIMATION
      * @see #FLAG_ACTIVITY_NO_HISTORY
@@ -7342,4 +7386,9 @@
         String htmlText = htmlTexts != null ? htmlTexts.get(which) : null;
         return new ClipData.Item(text, htmlText, null, uri);
     }
+
+    /** @hide */
+    public boolean isDocument() {
+        return (mFlags & FLAG_ACTIVITY_NEW_DOCUMENT) == FLAG_ACTIVITY_NEW_DOCUMENT;
+    }
 }
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 2facef6..e86833b 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -1233,6 +1233,26 @@
 
     /**
      * Feature for {@link #getSystemAvailableFeatures} and
+     * {@link #hasSystemFeature}: The device supports leanback UI. This is
+     * typically used in a living room television experience, but is a software
+     * feature unlike {@link #FEATURE_TELEVISION}. Devices running with this
+     * feature will use resources associated with the "television" UI mode.
+     */
+    @SdkConstant(SdkConstantType.FEATURE)
+    public static final String FEATURE_LEANBACK = "android.software.leanback";
+
+    /**
+     * Feature for {@link #getSystemAvailableFeatures} and
+     * {@link #hasSystemFeature}: The device supports only leanback UI. Only
+     * applications designed for this experience should be run, though this is
+     * not enforced by the system.
+     * @hide
+     */
+    @SdkConstant(SdkConstantType.FEATURE)
+    public static final String FEATURE_LEANBACK_ONLY = "android.software.leanback_only";
+
+    /**
+     * Feature for {@link #getSystemAvailableFeatures} and
      * {@link #hasSystemFeature}: The device supports WiFi (802.11) networking.
      */
     @SdkConstant(SdkConstantType.FEATURE)
@@ -1252,6 +1272,7 @@
      * room television experience: displayed on a big screen, where the user
      * is sitting far away from it, and the dominant form of input will be
      * something like a DPAD, not through touch or mouse.
+     * @deprecated use {@link #FEATURE_LEANBACK} instead.
      */
     @SdkConstant(SdkConstantType.FEATURE)
     public static final String FEATURE_TELEVISION = "android.hardware.type.television";
diff --git a/core/java/android/content/pm/RegisteredServicesCache.java b/core/java/android/content/pm/RegisteredServicesCache.java
index 875e8de..4a743a5 100644
--- a/core/java/android/content/pm/RegisteredServicesCache.java
+++ b/core/java/android/content/pm/RegisteredServicesCache.java
@@ -140,12 +140,33 @@
         mContext.registerReceiver(mExternalReceiver, sdFilter);
     }
 
+    private final void handlePackageEvent(Intent intent, int userId) {
+        // Don't regenerate the services map when the package is removed or its
+        // ASEC container unmounted as a step in replacement.  The subsequent
+        // _ADDED / _AVAILABLE call will regenerate the map in the final state.
+        final String action = intent.getAction();
+        // it's a new-component action if it isn't some sort of removal
+        final boolean isRemoval = Intent.ACTION_PACKAGE_REMOVED.equals(action)
+                || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action);
+        // if it's a removal, is it part of an update-in-place step?
+        final boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
+
+        if (isRemoval && replacing) {
+            // package is going away, but it's the middle of an upgrade: keep the current
+            // state and do nothing here.  This clause is intentionally empty.
+        } else {
+            // either we're adding/changing, or it's a removal without replacement, so
+            // we need to recalculate the set of available services
+            generateServicesMap(userId);
+        }
+    }
+
     private final BroadcastReceiver mPackageReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
             final int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
             if (uid != -1) {
-                generateServicesMap(UserHandle.getUserId(uid));
+                handlePackageEvent(intent, UserHandle.getUserId(uid));
             }
         }
     };
@@ -154,7 +175,7 @@
         @Override
         public void onReceive(Context context, Intent intent) {
             // External apps can't coexist with multi-user, so scan owner
-            generateServicesMap(UserHandle.USER_OWNER);
+            handlePackageEvent(intent, UserHandle.USER_OWNER);
         }
     };
 
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index d27485b..4c04caa 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -148,7 +148,7 @@
      * <p>All camera devices support ON, and all camera devices with
      * flash units support ON_AUTO_FLASH and
      * ON_ALWAYS_FLASH.</p>
-     * <p>Full-capability camera devices always support OFF mode,
+     * <p>FULL mode camera devices always support OFF mode,
      * which enables application control of camera exposure time,
      * sensitivity, and frame duration.</p>
      *
@@ -244,7 +244,7 @@
      * given camera device. This entry lists the valid modes for
      * {@link CaptureRequest#CONTROL_AWB_MODE android.control.awbMode} for this camera device.</p>
      * <p>All camera devices will support ON mode.</p>
-     * <p>Full-capability camera devices will always support OFF mode,
+     * <p>FULL mode camera devices will always support OFF mode,
      * which enables application control of white balance, by using
      * {@link CaptureRequest#COLOR_CORRECTION_TRANSFORM android.colorCorrection.transform} and {@link CaptureRequest#COLOR_CORRECTION_GAINS android.colorCorrection.gains}({@link CaptureRequest#COLOR_CORRECTION_MODE android.colorCorrection.mode} must be set to TRANSFORM_MATRIX).</p>
      *
@@ -280,6 +280,17 @@
             new Key<Boolean>("android.flash.info.available", boolean.class);
 
     /**
+     * <p>The set of hot pixel correction modes that are supported by this
+     * camera device.</p>
+     * <p>This tag lists valid modes for {@link CaptureRequest#HOT_PIXEL_MODE android.hotPixel.mode}.</p>
+     * <p>FULL mode camera devices will always support FAST.</p>
+     *
+     * @see CaptureRequest#HOT_PIXEL_MODE
+     */
+    public static final Key<byte[]> HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES =
+            new Key<byte[]>("android.hotPixel.availableHotPixelModes", byte[].class);
+
+    /**
      * <p>Supported resolutions for the JPEG thumbnail</p>
      * <p>Below condiditions will be satisfied for this size list:</p>
      * <ul>
@@ -1088,6 +1099,18 @@
             new Key<Integer>("android.statistics.info.maxFaceCount", int.class);
 
     /**
+     * <p>The set of hot pixel map output modes supported by this camera device.</p>
+     * <p>This tag lists valid output modes for {@link CaptureRequest#STATISTICS_HOT_PIXEL_MAP_MODE android.statistics.hotPixelMapMode}.</p>
+     * <p>If no hotpixel map is available for this camera device, this will contain
+     * only OFF.  If the hotpixel map is available, this should include both
+     * the ON and OFF options.</p>
+     *
+     * @see CaptureRequest#STATISTICS_HOT_PIXEL_MAP_MODE
+     */
+    public static final Key<boolean[]> STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES =
+            new Key<boolean[]>("android.statistics.info.availableHotPixelMapModes", boolean[].class);
+
+    /**
      * <p>Maximum number of supported points in the
      * tonemap curve that can be used for {@link CaptureRequest#TONEMAP_CURVE_RED android.tonemap.curveRed}, or
      * {@link CaptureRequest#TONEMAP_CURVE_GREEN android.tonemap.curveGreen}, or {@link CaptureRequest#TONEMAP_CURVE_BLUE android.tonemap.curveBlue}.</p>
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index a62df0f..a3fbfbe 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -1199,7 +1199,10 @@
     /**
      * <p>The frame rate must not be reduced relative to sensor raw output
      * for this option.</p>
-     * <p>No hot pixel correction is applied.</p>
+     * <p>No hot pixel correction is applied.
+     * The hotpixel map may be returned in {@link CaptureResult#STATISTICS_HOT_PIXEL_MAP android.statistics.hotPixelMap}.</p>
+     *
+     * @see CaptureResult#STATISTICS_HOT_PIXEL_MAP
      * @see CaptureRequest#HOT_PIXEL_MODE
      */
     public static final int HOT_PIXEL_MODE_OFF = 0;
@@ -1207,7 +1210,10 @@
     /**
      * <p>The frame rate must not be reduced relative to sensor raw output
      * for this option.</p>
-     * <p>Hot pixel correction is applied.</p>
+     * <p>Hot pixel correction is applied.
+     * The hotpixel map may be returned in {@link CaptureResult#STATISTICS_HOT_PIXEL_MAP android.statistics.hotPixelMap}.</p>
+     *
+     * @see CaptureResult#STATISTICS_HOT_PIXEL_MAP
      * @see CaptureRequest#HOT_PIXEL_MODE
      */
     public static final int HOT_PIXEL_MODE_FAST = 1;
@@ -1215,7 +1221,10 @@
     /**
      * <p>The frame rate may be reduced relative to sensor raw output
      * for this option.</p>
-     * <p>A high-quality hot pixel correction is applied.</p>
+     * <p>A high-quality hot pixel correction is applied.
+     * The hotpixel map may be returned in {@link CaptureResult#STATISTICS_HOT_PIXEL_MAP android.statistics.hotPixelMap}.</p>
+     *
+     * @see CaptureResult#STATISTICS_HOT_PIXEL_MAP
      * @see CaptureRequest#HOT_PIXEL_MODE
      */
     public static final int HOT_PIXEL_MODE_HIGH_QUALITY = 2;
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index a8caba0..fbac529 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -876,9 +876,13 @@
 
     /**
      * <p>Set operational mode for hot pixel correction.</p>
+     * <p>Valid modes for this camera device are listed in
+     * {@link CameraCharacteristics#HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES android.hotPixel.availableHotPixelModes}.</p>
      * <p>Hotpixel correction interpolates out, or otherwise removes, pixels
      * that do not accurately encode the incoming light (i.e. pixels that
      * are stuck at an arbitrary value).</p>
+     *
+     * @see CameraCharacteristics#HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES
      * @see #HOT_PIXEL_MODE_OFF
      * @see #HOT_PIXEL_MODE_FAST
      * @see #HOT_PIXEL_MODE_HIGH_QUALITY
@@ -1286,6 +1290,18 @@
             new Key<Integer>("android.statistics.faceDetectMode", int.class);
 
     /**
+     * <p>Operating mode for hotpixel map generation.</p>
+     * <p>If set to ON, a hotpixel map is returned in {@link CaptureResult#STATISTICS_HOT_PIXEL_MAP android.statistics.hotPixelMap}.
+     * If set to OFF, no hotpixel map should be returned.</p>
+     * <p>This must be set to a valid mode from {@link CameraCharacteristics#STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES android.statistics.info.availableHotPixelMapModes}.</p>
+     *
+     * @see CaptureResult#STATISTICS_HOT_PIXEL_MAP
+     * @see CameraCharacteristics#STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES
+     */
+    public static final Key<Boolean> STATISTICS_HOT_PIXEL_MAP_MODE =
+            new Key<Boolean>("android.statistics.hotPixelMapMode", boolean.class);
+
+    /**
      * <p>Whether the camera device will output the lens
      * shading map in output result metadata.</p>
      * <p>When set to ON,
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index 0f2c7f7..ab1525e 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -1166,24 +1166,14 @@
             new Key<Integer>("android.flash.state", int.class);
 
     /**
-     * <p>List of <code>(x, y)</code> coordinates of hot/defective pixels on the
-     * sensor, where <code>(x, y)</code> lies between <code>(0, 0)</code>, which is the top-left
-     * of the pixel array, and the width,height of the pixel array given in
-     * {@link CameraCharacteristics#SENSOR_INFO_PIXEL_ARRAY_SIZE android.sensor.info.pixelArraySize}.  This may include hot pixels
-     * that lie outside of the active array bounds given by
-     * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.</p>
-     *
-     * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
-     * @see CameraCharacteristics#SENSOR_INFO_PIXEL_ARRAY_SIZE
-     */
-    public static final Key<int[]> HOT_PIXEL_MAP =
-            new Key<int[]>("android.hotPixel.map", int[].class);
-
-    /**
      * <p>Set operational mode for hot pixel correction.</p>
+     * <p>Valid modes for this camera device are listed in
+     * {@link CameraCharacteristics#HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES android.hotPixel.availableHotPixelModes}.</p>
      * <p>Hotpixel correction interpolates out, or otherwise removes, pixels
      * that do not accurately encode the incoming light (i.e. pixels that
      * are stuck at an arbitrary value).</p>
+     *
+     * @see CameraCharacteristics#HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES
      * @see #HOT_PIXEL_MODE_OFF
      * @see #HOT_PIXEL_MODE_FAST
      * @see #HOT_PIXEL_MODE_HIGH_QUALITY
@@ -1971,6 +1961,33 @@
             new Key<Integer>("android.statistics.sceneFlicker", int.class);
 
     /**
+     * <p>Operating mode for hotpixel map generation.</p>
+     * <p>If set to ON, a hotpixel map is returned in {@link CaptureResult#STATISTICS_HOT_PIXEL_MAP android.statistics.hotPixelMap}.
+     * If set to OFF, no hotpixel map should be returned.</p>
+     * <p>This must be set to a valid mode from {@link CameraCharacteristics#STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES android.statistics.info.availableHotPixelMapModes}.</p>
+     *
+     * @see CaptureResult#STATISTICS_HOT_PIXEL_MAP
+     * @see CameraCharacteristics#STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES
+     */
+    public static final Key<Boolean> STATISTICS_HOT_PIXEL_MAP_MODE =
+            new Key<Boolean>("android.statistics.hotPixelMapMode", boolean.class);
+
+    /**
+     * <p>List of <code>(x, y)</code> coordinates of hot/defective pixels on the sensor.</p>
+     * <p>A coordinate <code>(x, y)</code> must lie between <code>(0, 0)</code>, and
+     * <code>(width - 1, height - 1)</code> (inclusive), which are the top-left and
+     * bottom-right of the pixel array, respectively. The width and
+     * height dimensions are given in {@link CameraCharacteristics#SENSOR_INFO_PIXEL_ARRAY_SIZE android.sensor.info.pixelArraySize}.
+     * This may include hot pixels that lie outside of the active array
+     * bounds given by {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.</p>
+     *
+     * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
+     * @see CameraCharacteristics#SENSOR_INFO_PIXEL_ARRAY_SIZE
+     */
+    public static final Key<int[]> STATISTICS_HOT_PIXEL_MAP =
+            new Key<int[]>("android.statistics.hotPixelMap", int[].class);
+
+    /**
      * <p>Tonemapping / contrast / gamma curve for the blue
      * channel, to use when {@link CaptureRequest#TONEMAP_MODE android.tonemap.mode} is
      * CONTRAST_CURVE.</p>
diff --git a/core/java/android/print/PrinterCapabilitiesInfo.java b/core/java/android/print/PrinterCapabilitiesInfo.java
index b615600..806a89d8 100644
--- a/core/java/android/print/PrinterCapabilitiesInfo.java
+++ b/core/java/android/print/PrinterCapabilitiesInfo.java
@@ -475,6 +475,12 @@
          * @param colorModes The color mode bit mask.
          * @param defaultColorMode The default color mode.
          * @return This builder.
+         * <p>
+         * <strong>Note:</strong> On platform version 19 (Kitkat) specifying
+         * only PrintAttributes#COLOR_MODE_MONOCHROME leads to a print spooler
+         * crash. Hence, you should declare either both color modes or
+         * PrintAttributes#COLOR_MODE_COLOR.
+         * </p>
          *
          * @throws IllegalArgumentException If color modes contains an invalid
          *         mode bit or if the default color mode is invalid.
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 94c3f44..d8cf18e 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -435,6 +435,14 @@
  * Various arguments, most determined by system properties, are passed in.
  * The "mOptions" vector is updated.
  *
+ * CAUTION: when adding options in here, be careful not to put the
+ * char buffer inside a nested scope.  Adding the buffer to the
+ * options using mOptions.add() does not copy the buffer, so if the
+ * buffer goes out of scope the option may be overwritten.  It's best
+ * to put the buffer at the top of the function so that it is more
+ * unlikely that someone will surround it in a scope at a later time
+ * and thus introduce a bug.
+ *
  * Returns 0 on success.
  */
 int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv)
@@ -469,7 +477,15 @@
       kEMIntFast,
       kEMJitCompiler,
     } executionMode = kEMDefault;
-
+    char profile_period[sizeof("-Xprofile-period:") + PROPERTY_VALUE_MAX];
+    char profile_duration[sizeof("-Xprofile-duration:") + PROPERTY_VALUE_MAX];
+    char profile_interval[sizeof("-Xprofile-interval:") + PROPERTY_VALUE_MAX];
+    char profile_backoff[sizeof("-Xprofile-backoff:") + PROPERTY_VALUE_MAX];
+    char langOption[sizeof("-Duser.language=") + 3];
+    char regionOption[sizeof("-Duser.region=") + 3];
+    char lockProfThresholdBuf[sizeof("-Xlockprofthreshold:") + sizeof(propBuf)];
+    char jitOpBuf[sizeof("-Xjitop:") + PROPERTY_VALUE_MAX];
+    char jitMethodBuf[sizeof("-Xjitmethod:") + PROPERTY_VALUE_MAX];
 
     property_get("dalvik.vm.checkjni", propBuf, "");
     if (strcmp(propBuf, "true") == 0) {
@@ -670,7 +686,6 @@
         //mOptions.add(opt);
     }
 
-    char lockProfThresholdBuf[sizeof("-Xlockprofthreshold:") + sizeof(propBuf)];
     property_get("dalvik.vm.lockprof.threshold", propBuf, "");
     if (strlen(propBuf) > 0) {
       strcpy(lockProfThresholdBuf, "-Xlockprofthreshold:");
@@ -680,7 +695,6 @@
     }
 
     /* Force interpreter-only mode for selected opcodes. Eg "1-0a,3c,f1-ff" */
-    char jitOpBuf[sizeof("-Xjitop:") + PROPERTY_VALUE_MAX];
     property_get("dalvik.vm.jit.op", propBuf, "");
     if (strlen(propBuf) > 0) {
         strcpy(jitOpBuf, "-Xjitop:");
@@ -690,7 +704,6 @@
     }
 
     /* Force interpreter-only mode for selected methods */
-    char jitMethodBuf[sizeof("-Xjitmethod:") + PROPERTY_VALUE_MAX];
     property_get("dalvik.vm.jit.method", propBuf, "");
     if (strlen(propBuf) > 0) {
         strcpy(jitMethodBuf, "-Xjitmethod:");
@@ -770,8 +783,6 @@
 
     /* Set the properties for locale */
     {
-        char langOption[sizeof("-Duser.language=") + 3];
-        char regionOption[sizeof("-Duser.region=") + 3];
         strcpy(langOption, "-Duser.language=");
         strcpy(regionOption, "-Duser.region=");
         readLocale(langOption, regionOption);
@@ -786,35 +797,30 @@
      * Set profiler options
      */
     if (libart) {
-      char period[sizeof("-Xprofile-period:") + PROPERTY_VALUE_MAX];
-      char duration[sizeof("-Xprofile-duration:") + PROPERTY_VALUE_MAX];
-      char interval[sizeof("-Xprofile-interval:") + PROPERTY_VALUE_MAX];
-      char backoff[sizeof("-Xprofile-backoff:") + PROPERTY_VALUE_MAX];
-
       // Number of seconds during profile runs.
-      strcpy(period, "-Xprofile-period:");
-      property_get("dalvik.vm.profile.period_secs", period+17, "10");
-      opt.optionString = period;
+      strcpy(profile_period, "-Xprofile-period:");
+      property_get("dalvik.vm.profile.period_secs", profile_period+17, "10");
+      opt.optionString = profile_period;
       mOptions.add(opt);
 
       // Length of each profile run (seconds).
-      strcpy(duration, "-Xprofile-duration:");
-      property_get("dalvik.vm.profile.duration_secs", duration+19, "30");
-      opt.optionString = duration;
+      strcpy(profile_duration, "-Xprofile-duration:");
+      property_get("dalvik.vm.profile.duration_secs", profile_duration+19, "30");
+      opt.optionString = profile_duration;
       mOptions.add(opt);
 
 
       // Polling interval during profile run (microseconds).
-      strcpy(interval, "-Xprofile-interval:");
-      property_get("dalvik.vm.profile.interval_us", interval+19, "10000");
-      opt.optionString = interval;
+      strcpy(profile_interval, "-Xprofile-interval:");
+      property_get("dalvik.vm.profile.interval_us", profile_interval+19, "10000");
+      opt.optionString = profile_interval;
       mOptions.add(opt);
 
       // Coefficient for period backoff.  The the period is multiplied
       // by this value after each profile run.
-      strcpy(backoff, "-Xprofile-backoff:");
-      property_get("dalvik.vm.profile.backoff_coeff", backoff+18, "2.0");
-      opt.optionString = backoff;
+      strcpy(profile_backoff, "-Xprofile-backoff:");
+      property_get("dalvik.vm.profile.backoff_coeff", profile_backoff+18, "2.0");
+      opt.optionString = profile_backoff;
       mOptions.add(opt);
     }
 
diff --git a/docs/html/images/screens_support/avds-config.png b/docs/html/images/screens_support/avds-config.png
index 97bd5f6..e609447 100644
--- a/docs/html/images/screens_support/avds-config.png
+++ b/docs/html/images/screens_support/avds-config.png
Binary files differ
diff --git a/docs/html/images/tools/as-camera-icon.png b/docs/html/images/tools/as-camera-icon.png
new file mode 100644
index 0000000..419a88d
--- /dev/null
+++ b/docs/html/images/tools/as-camera-icon.png
Binary files differ
diff --git a/docs/html/images/tools/as-error.png b/docs/html/images/tools/as-error.png
new file mode 100644
index 0000000..8865f54
--- /dev/null
+++ b/docs/html/images/tools/as-error.png
Binary files differ
diff --git a/docs/html/images/tools/as-fr-device.png b/docs/html/images/tools/as-fr-device.png
new file mode 100644
index 0000000..aec3bce
--- /dev/null
+++ b/docs/html/images/tools/as-fr-device.png
Binary files differ
diff --git a/docs/html/images/tools/as-fr-icon.png b/docs/html/images/tools/as-fr-icon.png
new file mode 100644
index 0000000..9252ca1
--- /dev/null
+++ b/docs/html/images/tools/as-fr-icon.png
Binary files differ
diff --git a/docs/html/images/tools/as-frag-ex.png b/docs/html/images/tools/as-frag-ex.png
new file mode 100644
index 0000000..775fa5e
--- /dev/null
+++ b/docs/html/images/tools/as-frag-ex.png
Binary files differ
diff --git a/docs/html/images/tools/as-grid-layout.png b/docs/html/images/tools/as-grid-layout.png
new file mode 100644
index 0000000..41b933a
--- /dev/null
+++ b/docs/html/images/tools/as-grid-layout.png
Binary files differ
diff --git a/docs/html/images/tools/as-i18n-icon.png b/docs/html/images/tools/as-i18n-icon.png
new file mode 100644
index 0000000..d35568f
--- /dev/null
+++ b/docs/html/images/tools/as-i18n-icon.png
Binary files differ
diff --git a/docs/html/images/tools/as-preview-chrome.png b/docs/html/images/tools/as-preview-chrome.png
new file mode 100644
index 0000000..716b8d7
--- /dev/null
+++ b/docs/html/images/tools/as-preview-chrome.png
Binary files differ
diff --git a/docs/html/images/tools/as-preview-icon.png b/docs/html/images/tools/as-preview-icon.png
new file mode 100644
index 0000000..59c7644
--- /dev/null
+++ b/docs/html/images/tools/as-preview-icon.png
Binary files differ
diff --git a/docs/html/images/tools/as-preview-nochrome.png b/docs/html/images/tools/as-preview-nochrome.png
new file mode 100644
index 0000000..1011e08
--- /dev/null
+++ b/docs/html/images/tools/as-preview-nochrome.png
Binary files differ
diff --git a/docs/html/images/tools/as-theme-db.png b/docs/html/images/tools/as-theme-db.png
new file mode 100644
index 0000000..beade0d
--- /dev/null
+++ b/docs/html/images/tools/as-theme-db.png
Binary files differ
diff --git a/docs/html/images/tools/as-theme-icon.png b/docs/html/images/tools/as-theme-icon.png
new file mode 100644
index 0000000..0e5fdf0
--- /dev/null
+++ b/docs/html/images/tools/as-theme-icon.png
Binary files differ
diff --git a/docs/html/images/training/firstapp/adt-firstapp-setup.png b/docs/html/images/training/firstapp/adt-firstapp-setup.png
index bf95285..05e147d 100644
--- a/docs/html/images/training/firstapp/adt-firstapp-setup.png
+++ b/docs/html/images/training/firstapp/adt-firstapp-setup.png
Binary files differ
diff --git a/docs/html/images/training/firstapp/adt-new-activity.png b/docs/html/images/training/firstapp/adt-new-activity.png
index c396793..2c32dcc 100644
--- a/docs/html/images/training/firstapp/adt-new-activity.png
+++ b/docs/html/images/training/firstapp/adt-new-activity.png
Binary files differ
diff --git a/docs/html/images/training/firstapp/edittext_gravity.png b/docs/html/images/training/firstapp/edittext_gravity.png
index f78e676..bc4f7ee 100644
--- a/docs/html/images/training/firstapp/edittext_gravity.png
+++ b/docs/html/images/training/firstapp/edittext_gravity.png
Binary files differ
diff --git a/docs/html/images/training/firstapp/edittext_wrap.png b/docs/html/images/training/firstapp/edittext_wrap.png
index 156776d..fe56731 100644
--- a/docs/html/images/training/firstapp/edittext_wrap.png
+++ b/docs/html/images/training/firstapp/edittext_wrap.png
Binary files differ
diff --git a/docs/html/images/training/firstapp/firstapp.png b/docs/html/images/training/firstapp/firstapp.png
index d69cd20..581e000 100644
--- a/docs/html/images/training/firstapp/firstapp.png
+++ b/docs/html/images/training/firstapp/firstapp.png
Binary files differ
diff --git a/docs/html/index.jd b/docs/html/index.jd
index 5d1788a..e901652 100644
--- a/docs/html/index.jd
+++ b/docs/html/index.jd
@@ -22,12 +22,13 @@
                       <script src="//ajax.googleapis.com/ajax/libs/swfobject/2.2/swfobject.js"></script>
                       <div style="box-shadow: 3px 10px 18px 1px #999;width:600px;height:336px">
                         <div id="ytapiplayer">
-                          <a href="http://www.youtube.com/watch?v=WWArLD6nqrk"><img width=600 src="{@docRoot}images/video-kiwi.jpg"></a><!--You need Flash player 8+ and JavaScript enabled to view this video. -->
+                          <a href="http://www.youtube.com/watch?v=i2uvYI6blEE"><img width=600 
+                          src="https://i1.ytimg.com/vi/i2uvYI6blEE/maxresdefault.jpg"></a><!--You need Flash player 8+ and JavaScript enabled to view this video. -->
                         </div>
                         <script type="text/javascript">
                             var params = { allowScriptAccess: "always" };
                             var atts = { id: "ytapiplayer" };
-                            swfobject.embedSWF("//www.youtube.com/v/WWArLD6nqrk?enablejsapi=1&playerapiid=ytplayer&version=3&HD=1;rel=0;showinfo=0;modestbranding;origin=developer.android.com;autohide=1",
+                            swfobject.embedSWF("//www.youtube.com/v/i2uvYI6blEE?enablejsapi=1&playerapiid=ytplayer&version=3&HD=1;rel=0;showinfo=0;modestbranding;origin=developer.android.com;autohide=1",
                               "ytapiplayer", "600", "336", "8", null, null, params, atts);
 
                             // Callback used to pause/resume carousel based on video state
@@ -56,9 +57,8 @@
                       </div>
                     </div>
                     <div class="content-right col-4">
-                    <h1 style="white-space:nowrap;line-height:1.2em;">Developer Story: <br />Kiwi, Inc.</h1>
-                    <p>Game developer Kiwi has had five titles in the top 25 grossing on Google Play. Hear how Google Play
-                      has helped them double revenue every six months.</p>
+                    <h1 style="white-space:nowrap;line-height:1.2em;">Developer Story: <br />Box Inc.</h1>
+                    <p>Box is a cloud-based platform and app for users to share business information. See how they got over 5 million downloads by leveraging the flexibility in the Android platform.</p>
                       <p><a href="{@docRoot}distribute/googleplay/spotlight/index.html" class="button">Watch more videos </a></p>
                     </div>
                 </li>
diff --git a/docs/html/sdk/installing/studio-layout.jd b/docs/html/sdk/installing/studio-layout.jd
new file mode 100644
index 0000000..f0e5d59
--- /dev/null
+++ b/docs/html/sdk/installing/studio-layout.jd
@@ -0,0 +1,148 @@
+page.title=Using the Layout Editor
+
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+<h2>See also</h2>
+<ul>
+<li><a href="{@docRoot}sdk/installing/studio.html">
+Getting Started with Android Studio</a></li>
+<li><a href="{@docRoot}sdk/installing/studio-tips.html">
+Android Studio Tips and Tricks</a></li>
+<li><a href="{@docRoot}sdk/installing/migrate.html">
+Migrating from Eclipse</a></li>
+</div>
+</div>
+
+<a class="notice-developers-video"
+href="https://developers.google.com/events/io/sessions/324603352">
+<div>
+    <h3>Video</h3>
+    <p>What's New in Android Developer Tools</p>
+</div>
+</a>
+
+<p>Android Studio offers an advanced layout editor that allows you to drag-and-drop widgets
+into your layout and preview your layout while editing the XML.</p>
+
+<p>Within the layout editor, you can switch between the <strong>Text</strong> view, where
+you edit the XML file as text, and the <strong>Design</strong> view. Just click the
+appropriate tab at the bottom of the window to display the desired editor.</p>
+
+<h2>Editing in the Text View</h2>
+
+<p>You can use the <strong>Text</strong> view to edit your layout file. This section describes
+some of the features that are available in the <strong>Text</strong> view.</p>
+
+<h3>Preview</h3>
+
+<p>While editing in the <strong>Text</strong> view, you can preview the layout on devices
+by opening the <strong>Preview</strong> pane available on the right side of the window.
+Within the <strong>Preview</strong> pane, you can modify the preview by changing various
+options at the top of the pane, including the preview device, layout theme, platform
+version and more. To see a preview of how your app would look with a particular device
+skin, click the preview icon
+<img src="{@docRoot}images/tools/as-preview-icon.png" style="vertical-align:bottom;margin:0;height:19px" />
+and choose the desired device, such as Nexus 4:</p>
+
+<img src="{@docRoot}images/tools/as-preview-chrome.png" alt="" />
+<p class="img-caption"><strong>Figure 1.</strong> Previewing your app.</p>
+
+<p>To preview the layout on multiple devices simultaneously, select <strong>Preview All
+Screen Sizes</strong> from the device drop-down. </p>
+
+<p>When you click in the preview image, the layout editor highlights the corresponding
+section in the XML, and vice-versa.</p>
+
+<h3>Interactive error detection and recovery</h3>
+
+<p>As you edit the <strong>Text</strong> view of your layout XML file, Android Studio flags
+typos and offers assistance.</p>
+
+<p>For example, suppose you are adding a button, and you misspell it as &quot;Buttonn&quot;.
+Android Studio helps you to correct it by displaying an error such as the following,
+where you can click on &quot;Change to Button&quot; to fix the error in the XML file:</p>
+
+<img src="{@docRoot}images/tools/as-error.png" alt="" />
+
+<p class="img-caption"><strong>Figure 2.</strong> Flagging errors.</p>
+
+<p>Android Studio also prompts you to supply missing information. For example, suppose you
+start adding a fragment to your layout XML file. First of all, Android Studio displays
+auto-complete suggestions as you type. Once it becomes clear that you are adding a fragment,
+Android Studio displays an error panel with links that you can click to supply the missing
+attributes. Clicking &quot;Automatically add all missing attributes&quot; in this case
+does just that&mdash;it completes the fragment definition in your layout XML file:</p>
+
+<img src="{@docRoot}images/tools/as-frag-ex.png" alt="" />
+
+<p class="img-caption"><strong>Figure 3.</strong> Supplying missing information</p>
+
+<h3>Picking a theme</h3>
+
+<p>To pick a theme for your app, click the Theme icon
+<img src="{@docRoot}images/tools/as-theme-icon.png" style="vertical-align:bottom;margin:0;height:19px" />.
+</p>
+
+<p>This displays the <strong>Select Theme</strong> dialog, where you can search for a
+particular theme and/or select one from the list on the right hand side. The theme you
+choose will be reflected in the previewed image.</p>
+
+<img src="{@docRoot}images/tools/as-theme-db.png" alt="" />
+
+<p class="img-caption"><strong>Figure 4.</strong> Specifying a theme.</p>
+
+<h3>Localization</h3>
+
+<p>Android Studio provides built-in localization support. When you click the
+localization icon
+<img src="{@docRoot}images/tools/as-i18n-icon.png" style="vertical-align:bottom;margin:0;height:19px" />,
+you can select a particular locale, add and edit translations, preview the locales your
+app supports (all locales or just a single locale), and preview right-to-left layout for
+languages that are RTL.</p>
+
+<p>See <a href="{@docRoot}training/basics/supporting-devices/languages.html">Supporting
+Different Languages</a> for a description of how to support different locales in your app.</p>
+<p>For example, here is a preview of a &quot;Hello World&quot; app for the
+<img src="{@docRoot}images/tools/as-fr-icon.png" style="vertical-align:bottom;margin:0;height:19px" />
+locale:</p>
+
+<img src="{@docRoot}images/tools/as-fr-device.png" alt="" />
+<p class="img-caption"><strong>Figure 5.</strong> Previewing locales.</p>
+
+<h2>Editing in the Design View</h2>
+
+<p>You can switch to the graphical editor by clicking <strong>Design</strong> at the
+bottom of the window. While editing in the <strong>Design</strong> view, you can show and
+hide the widgets available to drag-and-drop by clicking <strong>Palette</strong> on the
+left side of the window. Clicking <strong>Designer</strong> on the right side of the
+window reveals a panel with a layout hierarchy and a list of properties for each view in
+the layout.</p>
+
+<p>When you drag a widget into the graphical layout for your app, the display changes to
+help you place the widget. What you see depends on the type of layout. For example, if
+you're dragging a widget into a {@link android.widget.FrameLayout}, it displays a grid to
+help you place the widget, as shown in figure 6:</p>
+
+<img src="{@docRoot}images/tools/as-grid-layout.png" alt="" />
+
+<p class="img-caption"><strong>Figure 6.</strong> Using the grid layout to place a widget.</p>
+
+<p>Within the graphical editor, you can rearrange your app's UI by dragging widgets to
+the desired location.</p>
+
+<h3>Taking a snapshot</h3>
+
+<p>When you run your app on a connected device, you can take a snapshot of it by clicking
+the camera icon
+<img src="{@docRoot}images/tools/as-camera-icon.png" style="vertical-align:bottom;margin:0;height:19px" />
+to the left of the logging
+panel (at the bottom of the window by default). This takes a snapshot of your running app
+(or whatever is currently displayed on your device) and displays it in a window. Check
+<strong>Frame Screenshot</strong> to show your screenshot within the device skin of your
+choice. You can also specify whether you want the image to have screen glare and/or a drop
+shadow. Once you have the desired effect, you can save the image.</p>
+
+<p>You can use the same process to create a snapshot of your app's preview. Just click the
+camera icon in the preview area and follow the steps for adding a device skin.</p>
diff --git a/docs/html/sdk/installing/studio.jd b/docs/html/sdk/installing/studio.jd
index 5a7e270..feb7a6e 100644
--- a/docs/html/sdk/installing/studio.jd
+++ b/docs/html/sdk/installing/studio.jd
@@ -318,6 +318,12 @@
 
 
 <h2 id="Installing">Installing Android Studio</h2>
+<p>Android Studio requires JDK 6 or greater (JRE alone is not sufficient). To check if you 
+have JDK installed (and which version), open a terminal and type <code>javac -version</code>.
+If JDK is not available or the version is lower than 6,
+<a href="http://www.oracle.com/technetwork/java/javase/downloads/index.html">download
+JDK from here</a>.</p>
+<p>To install Android Studio:</p>
 <ol>
 <li>Download the <strong>Android Studio</strong> package from above.</li>
 <li>Install Android Studio and the SDK tools:
diff --git a/docs/html/tools/help/logcat.jd b/docs/html/tools/help/logcat.jd
index ede1905..b30971e 100644
--- a/docs/html/tools/help/logcat.jd
+++ b/docs/html/tools/help/logcat.jd
@@ -45,7 +45,7 @@
     <tr>
       <td><code>-b&nbsp;&lt;buffer&gt;</code></td>
 
-      <td>Loads an alternate log buffer for viewing, such as <code>event</code> or
+      <td>Loads an alternate log buffer for viewing, such as <code>events</code> or
       <code>radio</code>. The <code>main</code> buffer is used by default. See <a href= 
       "{@docRoot}tools/debugging/debugging-log.html#alternativeBuffers">Viewing Alternative Log Buffers</a>.</td>
     </tr>
diff --git a/docs/html/tools/tools_toc.cs b/docs/html/tools/tools_toc.cs
index a8424e6..382165c 100644
--- a/docs/html/tools/tools_toc.cs
+++ b/docs/html/tools/tools_toc.cs
@@ -34,7 +34,9 @@
               Migrating from Eclipse</a></li>
           <li><a href="<?cs var:toroot ?>sdk/installing/studio-tips.html">
               Tips and Tricks</a></li>
-        </ul>
+          <li><a href="<?cs var:toroot ?>sdk/installing/studio-layout.html">
+              Using the Layout Editor</a></li>
+          </ul>
       </li>
       <li><a href="<?cs var:toroot ?>sdk/exploring.html">
           <span class="en">Exploring the SDK</span></a></li>
diff --git a/docs/html/training/basics/firstapp/building-ui.jd b/docs/html/training/basics/firstapp/building-ui.jd
index 2615bee..179b3ac 100644
--- a/docs/html/training/basics/firstapp/building-ui.jd
+++ b/docs/html/training/basics/firstapp/building-ui.jd
@@ -75,16 +75,16 @@
 
 <h2 id="LinearLayout">Create a Linear Layout</h2>
 
-<p>Open the <code>activity_main.xml</code> file from the <code>res/layout/</code>
+<p>Open the <code>fragment_main.xml</code> file from the <code>res/layout/</code>
 directory.</p>
 
 <p class="note"><strong>Note:</strong> In Eclipse, when you open a layout file, you’re first shown
 the Graphical Layout editor. This is an editor that helps you build layouts using WYSIWYG tools. For this
-lesson, you’re going to work directly with the XML, so click the <em>activity_main.xml</em> tab at
+lesson, you’re going to work directly with the XML, so click the <em>fragment_main.xml</em> tab at
 the bottom of the screen to open the XML editor.</p>
 
 <p>The BlankActivity template you chose when you created this project includes the
-<code>activity_main.xml</code> file with a {@link
+<code>fragment_main.xml</code> file with a {@link
 android.widget.RelativeLayout} root view and a {@link android.widget.TextView} child view.</p>
 
 <p>First, delete the {@link android.widget.TextView &lt;TextView>} element and change the {@link
@@ -95,7 +95,6 @@
 The result looks like this:</p>
 
 <pre>
-&lt;?xml version="1.0" encoding="utf-8"?>
 &lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:tools="http://schemas.android.com/tools"
     android:layout_width="match_parent"
diff --git a/docs/html/training/basics/firstapp/creating-project.jd b/docs/html/training/basics/firstapp/creating-project.jd
index 9516e37..50485db 100644
--- a/docs/html/training/basics/firstapp/creating-project.jd
+++ b/docs/html/training/basics/firstapp/creating-project.jd
@@ -120,8 +120,8 @@
     <strong>Finish</strong>.</li>
 </ol>
 
-<p>Your Android project is now set up with some default files and you’re ready to begin
-building the app. Continue to the <a href="running-app.html">next lesson</a>.</p>
+<p>Your Android project is now a basic "Hello World" app that contains some default files. 
+To run the app, continue to the <a href="running-app.html">next lesson</a>.</p>
 
 
 
@@ -155,8 +155,8 @@
 projects.</p></li>
 </ol>
 
-<p>Your Android project is now set up with several default configurations and you’re ready to begin
-building the app. Continue to the <a href="running-app.html">next lesson</a>.</p>
+<p>Your Android project is now a basic "Hello World" app that contains some default files. 
+To run the app, continue to the <a href="running-app.html">next lesson</a>.</p>
 
 <p class="note"><strong>Tip:</strong> Add the <code>platform-tools/</code> as well as the
 <code>tools/</code> directory to your <code>PATH</code> environment variable.</p>
diff --git a/docs/html/training/basics/firstapp/running-app.jd b/docs/html/training/basics/firstapp/running-app.jd
index 999d399..23cedba 100644
--- a/docs/html/training/basics/firstapp/running-app.jd
+++ b/docs/html/training/basics/firstapp/running-app.jd
@@ -62,7 +62,7 @@
 attributes. For your first app, it should look like this:</p>
 <pre>
 &lt;manifest xmlns:android="http://schemas.android.com/apk/res/android" ... >
-    &lt;uses-sdk android:minSdkVersion="8" android:targetSdkVersion="17" />
+    &lt;uses-sdk android:minSdkVersion="8" android:targetSdkVersion="19" />
     ...
 &lt;/manifest>
 </pre>
diff --git a/docs/html/training/basics/firstapp/starting-activity.jd b/docs/html/training/basics/firstapp/starting-activity.jd
index 712eabc..9aa25a3 100644
--- a/docs/html/training/basics/firstapp/starting-activity.jd
+++ b/docs/html/training/basics/firstapp/starting-activity.jd
@@ -45,7 +45,7 @@
 
 <h2 id="RespondToButton">Respond to the Send Button</h2>
 
-<p>To respond to the button's on-click event, open the <code>activity_main.xml</code>
+<p>To respond to the button's on-click event, open the <code>fragment_main.xml</code>
 layout file and add the <a
 href="{@docRoot}reference/android/view/View.html#attr_android:onClick">{@code android:onClick}</a>
 attribute to the {@link android.widget.Button &lt;Button>} element:</p>
@@ -73,14 +73,6 @@
 }
 </pre>
 
-<p>This requires that you import the {@link android.view.View} class:</p>
-<pre>
-import android.view.View;
-</pre>
-
-<p class="note"><strong>Tip:</strong> In Eclipse, press Ctrl + Shift + O to import missing classes
-(Cmd + Shift + O on Mac).</p>
-
 <p>In order for the system to match this method to the method name given to <a
 href="{@docRoot}reference/android/view/View.html#attr_android:onClick">{@code android:onClick}</a>,
 the signature must be exactly as shown. Specifically, the method must:</p>
@@ -111,6 +103,14 @@
 Intent intent = new Intent(this, DisplayMessageActivity.class);
 </pre>
 
+<p>This requires that you import the {@link android.content.Intent} class:</p>
+<pre>
+import android.content.Intent;
+</pre>
+
+<p class="note"><strong>Tip:</strong> In Eclipse, press Ctrl + Shift + O to import missing classes
+(Cmd + Shift + O on Mac).</p>
+
 <p>The constructor used here takes two parameters:</p>
 <ul>
   <li>A {@link
@@ -151,9 +151,8 @@
 </pre>
 
 <p class="note"><strong>Note:</strong>
-You now need import statements for <code>android.content.Intent</code>
-and <code>android.widget.EditText</code>. You'll define the <code>EXTRA_MESSAGE</code>
-constant in a moment.</p>
+You now need an import statement for <code>android.widget.EditText</code>. 
+You'll define the <code>EXTRA_MESSAGE</code> constant in a moment.</p>
 
 <p>An {@link android.content.Intent} can carry a collection of various data types as key-value
 pairs called <em>extras</em>. The {@link android.content.Intent#putExtra putExtra()} method takes the
@@ -165,7 +164,7 @@
 MainActivity} class:</p>
 
 <pre>
-public class MainActivity extends Activity {
+public class MainActivity extends ActionBarActivity {
     public final static String EXTRA_MESSAGE = "com.example.myfirstapp.MESSAGE";
     ...
 }
@@ -223,6 +222,7 @@
       <li><strong>Project</strong>: MyFirstApp</li>
       <li><strong>Activity Name</strong>: DisplayMessageActivity</li>
       <li><strong>Layout Name</strong>: activity_display_message</li>
+      <li><strong>Fragment Layout Name</strong>: fragment_display_message</li>
       <li><strong>Title</strong>: My Message</li>
       <li><strong>Hierarchial Parent</strong>: com.example.myfirstapp.MainActivity</li>
       <li><strong>Navigation Type</strong>: None</li>
@@ -240,49 +240,65 @@
 <ul>
   <li>The class
 already includes an implementation of the required {@link android.app.Activity#onCreate onCreate()}
-method.</li>
+method. You will update the implementation of this method later.</li>
   <li>There's also an implementation of the {@link android.app.Activity#onCreateOptionsMenu
 onCreateOptionsMenu()} method, but
 you won't need it for this app so you can remove it.</li>
   <li>There's also an implementation of {@link android.app.Activity#onOptionsItemSelected
   onOptionsItemSelected()} which handles the behavior for the action bar's <em>Up</em> behavior.
   Keep this one the way it is.</li>
+  <li>There's also a <code>PlaceholderFragment</code> class that extends 
+{@link android.app.Fragment}. You will not need this class in the final version of this
+activity.</li>
 </ul>
 
-<p>Because the {@link android.app.ActionBar} APIs are available only on {@link
-android.os.Build.VERSION_CODES#HONEYCOMB} (API level 11) and higher, you must add a condition
-around the {@link android.app.Activity#getActionBar()} method to check the current platform version.
-Additionally, you must add the {@code &#64;SuppressLint("NewApi")} tag to the
-{@link android.app.Activity#onCreate onCreate()} method to avoid <a
-href="{@docRoot}tools/help/lint.html">lint</a> errors.</p>
+<p>Fragments decompose application functionality and UI into reusable modules. For more 
+information on fragments, see the <a href="{@docRoot}guide/components/fragments.html">Fragments 
+API Guide</a>. The final version of this activity does not use fragments.</p>
 
 <p>The {@code DisplayMessageActivity} class should now look like this:</p>
 
 <pre>
-public class DisplayMessageActivity extends Activity {
+public class DisplayMessageActivity extends ActionBarActivity {
 
-    &#64;SuppressLint("NewApi")
     &#64;Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_display_message);
 
-        // Make sure we're running on Honeycomb or higher to use ActionBar APIs
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
-            // Show the Up button in the action bar.
-            getActionBar().setDisplayHomeAsUpEnabled(true);
+        if (savedInstanceState == null) {
+            getSupportFragmentManager().beginTransaction()
+                .add(R.id.container, new PlaceholderFragment()).commit();
         }
     }
 
     &#64;Override
     public boolean onOptionsItemSelected(MenuItem item) {
-        switch (item.getItemId()) {
-        case android.R.id.home:
-            NavUtils.navigateUpFromSameTask(this);
+        // Handle action bar item clicks here. The action bar will
+        // automatically handle clicks on the Home/Up button, so long
+        // as you specify a parent activity in AndroidManifest.xml.
+        int id = item.getItemId();
+        if (id == R.id.action_settings) {
             return true;
         }
         return super.onOptionsItemSelected(item);
     }
+
+    /**
+     * A placeholder fragment containing a simple view.
+     */
+    public static class PlaceholderFragment extends Fragment {
+
+        public PlaceholderFragment() { }
+
+        &#64;Override
+        public View onCreateView(LayoutInflater inflater, ViewGroup container,
+                  Bundle savedInstanceState) {
+              View rootView = inflater.inflate(R.layout.fragment_display_message,
+                      container, false);
+              return rootView;
+        }
+    }
 }
 </pre>
 
@@ -422,7 +438,7 @@
 
 <img src="{@docRoot}images/training/firstapp/firstapp.png" />
 <p class="img-caption"><strong>Figure 2.</strong> Both activities in the final app, running
-on Android 4.0.
+on Android 4.4.
 
 <p>That's it, you've built your first Android app!</p>
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Console.java b/packages/SystemUI/src/com/android/systemui/recents/Console.java
index b3d9ccf..db95193 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Console.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Console.java
@@ -17,6 +17,7 @@
 package com.android.systemui.recents;
 
 
+import android.content.ComponentCallbacks2;
 import android.content.Context;
 import android.util.Log;
 import android.view.MotionEvent;
@@ -36,20 +37,20 @@
 
     /** Logs a key */
     public static void log(String key) {
-        Console.log(true, key, "", AnsiReset);
+        log(true, key, "", AnsiReset);
     }
 
     /** Logs a conditioned key */
     public static void log(boolean condition, String key) {
         if (condition) {
-            Console.log(condition, key, "", AnsiReset);
+            log(condition, key, "", AnsiReset);
         }
     }
 
     /** Logs a key in a specific color */
     public static void log(boolean condition, String key, Object data) {
         if (condition) {
-            Console.log(condition, key, data, AnsiReset);
+            log(condition, key, data, AnsiReset);
         }
     }
 
@@ -74,6 +75,50 @@
         }
     }
 
+    /** Logs a stack trace */
+    public static void logStackTrace() {
+        logStackTrace("", 99);
+    }
+
+    /** Logs a stack trace to a certain depth */
+    public static void logStackTrace(int depth) {
+        logStackTrace("", depth);
+    }
+
+    /** Logs a stack trace to a certain depth with a key */
+    public static void logStackTrace(String key, int depth) {
+        int offset = 0;
+        StackTraceElement[] callStack = Thread.currentThread().getStackTrace();
+        String tinyStackTrace = "";
+        // Skip over the known stack trace classes
+        for (int i = 0; i < callStack.length; i++) {
+            StackTraceElement el = callStack[i];
+            String className = el.getClassName();
+            if (className.indexOf("dalvik.system.VMStack") == -1 &&
+                className.indexOf("java.lang.Thread") == -1 &&
+                className.indexOf("recents.Console") == -1) {
+                break;
+            } else {
+                offset++;
+            }
+        }
+        // Build the pretty stack trace
+        int start = Math.min(offset + depth, callStack.length);
+        int end = offset;
+        String indent = "";
+        for (int i = start - 1; i >= end; i--) {
+            StackTraceElement el = callStack[i];
+            tinyStackTrace += indent + " -> " + el.getClassName() +
+                    "[" + el.getLineNumber() + "]." + el.getMethodName();
+            if (i > end) {
+                tinyStackTrace += "\n";
+                indent += "  ";
+            }
+        }
+        log(true, key, tinyStackTrace, AnsiRed);
+    }
+
+
     /** Returns the stringified MotionEvent action */
     public static String motionEventActionToString(int action) {
         switch (action) {
@@ -93,4 +138,25 @@
                 return "" + action;
         }
     }
+
+    public static String trimMemoryLevelToString(int level) {
+        switch (level) {
+            case ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN:
+                return "UI Hidden";
+            case ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE:
+                return "Running Moderate";
+            case ComponentCallbacks2.TRIM_MEMORY_BACKGROUND:
+                return "Background";
+            case ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW:
+                return "Running Low";
+            case ComponentCallbacks2.TRIM_MEMORY_MODERATE:
+                return "Moderate";
+            case ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL:
+                return "Critical";
+            case ComponentCallbacks2.TRIM_MEMORY_COMPLETE:
+                return "Complete";
+            default:
+                return "" + level;
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Constants.java b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
index aeae4ab..57ebbc2 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Constants.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
@@ -30,9 +30,11 @@
             public static final boolean EnableTaskStackClipping = false;
             public static final boolean EnableBackgroundTaskLoading = true;
             public static final boolean ForceDisableBackgroundCache = false;
+
             public static final boolean TaskDataLoader = false;
             public static final boolean SystemUIHandshake = false;
             public static final boolean TimeSystemCalls = false;
+            public static final boolean Memory = false;
         }
 
         public static class UI {
@@ -41,7 +43,7 @@
             public static final boolean TouchEvents = false;
             public static final boolean MeasureAndLayout = false;
             public static final boolean Clipping = false;
-            public static final boolean HwLayers = true;
+            public static final boolean HwLayers = false;
         }
 
         public static class TaskStack {
@@ -55,13 +57,16 @@
 
     public static class Values {
         public static class Window {
+            // The dark background dim is set behind the empty recents view
             public static final float DarkBackgroundDim = 0.5f;
+            // The background dim is set behind the card stack
             public static final float BackgroundDim = 0.35f;
         }
 
         public static class RecentsTaskLoader {
             // XXX: This should be calculated on the first load
             public static final int PreloadFirstTasksCount = 5;
+            // For debugging, this allows us to multiply the number of cards for each task
             public static final int TaskEntryMultiplier = 1;
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index d050847..fc4d819 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -23,6 +23,7 @@
 import android.view.View;
 import android.view.WindowManager;
 import android.widget.FrameLayout;
+import com.android.systemui.recent.RecentTasksLoader;
 import com.android.systemui.recents.model.SpaceNode;
 import com.android.systemui.recents.model.TaskStack;
 import com.android.systemui.recents.views.RecentsView;
@@ -168,6 +169,14 @@
     }
 
     @Override
+    public void onTrimMemory(int level) {
+        RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
+        if (loader != null) {
+            loader.onTrimMemory(level);
+        }
+    }
+
+    @Override
     public void onBackPressed() {
         if (!mRecentsView.unfilterFilteredStacks()) {
             super.onBackPressed();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
index f3881ae..ed981ed 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
@@ -30,7 +30,6 @@
 
     DisplayMetrics mDisplayMetrics;
 
-    public boolean layoutVerticalStack;
     public Rect systemInsets = new Rect();
 
     /** Private constructor */
@@ -56,7 +55,6 @@
 
         boolean isPortrait = context.getResources().getConfiguration().orientation ==
                 Configuration.ORIENTATION_PORTRAIT;
-        layoutVerticalStack = isPortrait || Constants.LANDSCAPE_LAYOUT_VERTICAL_STACK;
     }
 
     public void updateSystemInsets(Rect insets) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java
index 522ab0f..13a3424 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java
@@ -57,8 +57,9 @@
                     tsv.computeRects(windowRect.width(), windowRect.height() - systemInsets.top);
                     tsv.boundScroll();
                     TaskViewTransform transform = tsv.getStackTransform(0);
+                    Rect taskRect = new Rect(transform.rect);
 
-                    data.putParcelable("taskRect", transform.rect);
+                    data.putParcelable("taskRect", taskRect);
                     Message reply = Message.obtain(null, MSG_UPDATE_RECENTS_FOR_CONFIGURATION, 0, 0);
                     reply.setData(data);
                     msg.replyTo.send(reply);
@@ -100,4 +101,12 @@
         Console.log(Constants.DebugFlags.App.SystemUIHandshake, "[RecentsService|onDestroy]");
         super.onDestroy();
     }
+
+    @Override
+    public void onTrimMemory(int level) {
+        RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
+        if (loader != null) {
+            loader.onTrimMemory(level);
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
index c303ca7..96efed4 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
@@ -17,6 +17,7 @@
 package com.android.systemui.recents;
 
 import android.app.ActivityManager;
+import android.content.ComponentCallbacks2;
 import android.content.Context;
 import android.content.pm.ActivityInfo;
 import android.content.pm.PackageManager;
@@ -35,6 +36,7 @@
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 import java.util.concurrent.ConcurrentLinkedQueue;
 
 
@@ -233,7 +235,7 @@
     @Override
     protected int sizeOf(Task t, Bitmap bitmap) {
         // The cache size will be measured in kilobytes rather than number of items
-        return bitmap.getByteCount() / 1024;
+        return bitmap.getAllocationByteCount() / 1024;
     }
 }
 
@@ -247,17 +249,28 @@
     TaskResourceLoadQueue mLoadQueue;
     TaskResourceLoader mLoader;
 
+    int mMaxThumbnailCacheSize;
+    int mMaxIconCacheSize;
+
     BitmapDrawable mDefaultIcon;
     Bitmap mDefaultThumbnail;
 
     /** Private Constructor */
     private RecentsTaskLoader(Context context) {
+        // Calculate the cache sizes
         int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
-        int iconCacheSize = Constants.DebugFlags.App.ForceDisableBackgroundCache ? 1 : maxMemory / 16;
-        int thumbnailCacheSize = Constants.DebugFlags.App.ForceDisableBackgroundCache ? 1 : maxMemory / 8;
-        Console.log(Constants.DebugFlags.App.SystemUIHandshake,
+        mMaxThumbnailCacheSize = maxMemory / 8;
+        mMaxIconCacheSize = mMaxThumbnailCacheSize / 4;
+        int iconCacheSize = Constants.DebugFlags.App.ForceDisableBackgroundCache ? 1 :
+                mMaxIconCacheSize;
+        int thumbnailCacheSize = Constants.DebugFlags.App.ForceDisableBackgroundCache ? 1 :
+                mMaxThumbnailCacheSize;
+
+        Console.log(Constants.DebugFlags.App.EnableBackgroundTaskLoading,
                 "[RecentsTaskLoader|init]", "thumbnailCache: " + thumbnailCacheSize +
                 " iconCache: " + iconCacheSize);
+
+        // Initialize the cache and loaders
         mLoadQueue = new TaskResourceLoadQueue();
         mIconCache = new DrawableLruCache(iconCacheSize);
         mThumbnailCache = new BitmapLruCache(thumbnailCacheSize);
@@ -293,7 +306,7 @@
 
     /** Reload the set of recent tasks */
     SpaceNode reload(Context context, int preloadCount) {
-        Console.log(Constants.DebugFlags.App.SystemUIHandshake, "[RecentsTaskLoader|reload]");
+        Console.log(Constants.DebugFlags.App.TaskDataLoader, "[RecentsTaskLoader|reload]");
         TaskStack stack = new TaskStack(context);
         SpaceNode root = new SpaceNode(context);
         root.setStack(stack);
@@ -310,7 +323,7 @@
             Console.log(Constants.DebugFlags.App.TimeSystemCalls,
                     "[RecentsTaskLoader|getRecentTasks]",
                     "" + (System.currentTimeMillis() - t1) + "ms");
-            Console.log(Constants.DebugFlags.App.SystemUIHandshake,
+            Console.log(Constants.DebugFlags.App.TaskDataLoader,
                     "[RecentsTaskLoader|tasks]", "" + tasks.size());
 
             // Remove home/recents tasks
@@ -335,35 +348,51 @@
             int taskCount = tasks.size();
             for (int i = 0; i < taskCount; i++) {
                 ActivityManager.RecentTaskInfo t = tasks.get(i);
-
-                // Load the label, icon and thumbnail
                 ActivityInfo info = pm.getActivityInfo(t.baseIntent.getComponent(),
                         PackageManager.GET_META_DATA);
                 String title = info.loadLabel(pm).toString();
-                Drawable icon = null;
-                Bitmap thumbnail = null;
                 Task task;
-                if (i >= (taskCount - preloadCount) || !Constants.DebugFlags.App.EnableBackgroundTaskLoading) {
-                    Console.log(Constants.DebugFlags.App.SystemUIHandshake,
+                // Preload the specified number of apps
+                if (i >= (taskCount - preloadCount) ||
+                        !Constants.DebugFlags.App.EnableBackgroundTaskLoading) {
+                    Console.log(Constants.DebugFlags.App.TaskDataLoader,
                             "[RecentsTaskLoader|preloadTask]",
                             "i: " + i + " task: " + t.baseIntent.getComponent().getPackageName());
-                    icon = info.loadIcon(pm);
-                    thumbnail = am.getTaskTopThumbnail(t.id);
-                    for (int j = 0; j < Constants.Values.RecentsTaskLoader.TaskEntryMultiplier; j++) {
-                        Console.log(Constants.DebugFlags.App.SystemUIHandshake,
-                                "  [RecentsTaskLoader|task]", t.baseIntent.getComponent().getPackageName());
-                        task = new Task(t.persistentId, t.baseIntent, title, icon, thumbnail);
+
+                    task = new Task(t.persistentId, t.baseIntent, title, null, null);
+
+                    // Load the icon (if possible from the cache)
+                    if (Constants.DebugFlags.App.EnableBackgroundTaskLoading) {
+                        task.icon = mIconCache.get(task);
+                    }
+                    if (task.icon == null) {
+                        task.icon = info.loadIcon(pm);
                         if (Constants.DebugFlags.App.EnableBackgroundTaskLoading) {
-                            if (thumbnail != null) mThumbnailCache.put(task, thumbnail);
-                            if (icon != null) {
-                                mIconCache.put(task, icon);
-                            }
+                            mIconCache.put(task, task.icon);
                         }
+                    }
+
+                    // Load the thumbnail (if possible from the cache)
+                    if (Constants.DebugFlags.App.EnableBackgroundTaskLoading) {
+                        task.thumbnail = mThumbnailCache.get(task);
+                    }
+                    if (task.thumbnail == null) {
+                        task.thumbnail = am.getTaskTopThumbnail(t.id);
+                        if (Constants.DebugFlags.App.EnableBackgroundTaskLoading) {
+                            mThumbnailCache.put(task, task.thumbnail);
+                        }
+                    }
+
+                    // Create as many tasks a we want to multiply by
+                    for (int j = 0; j < Constants.Values.RecentsTaskLoader.TaskEntryMultiplier; j++) {
+                        Console.log(Constants.DebugFlags.App.TaskDataLoader,
+                                "  [RecentsTaskLoader|task]", t.baseIntent.getComponent().getPackageName());
                         stack.addTask(task);
                     }
                 } else {
+                    // Create as many tasks a we want to multiply by
                     for (int j = 0; j < Constants.Values.RecentsTaskLoader.TaskEntryMultiplier; j++) {
-                        Console.log(Constants.DebugFlags.App.SystemUIHandshake,
+                        Console.log(Constants.DebugFlags.App.TaskDataLoader,
                                 "  [RecentsTaskLoader|task]", t.baseIntent.getComponent().getPackageName());
                         task = new Task(t.persistentId, t.baseIntent, title, null, null);
                         stack.addTask(task);
@@ -388,9 +417,9 @@
             t1 = System.currentTimeMillis();
             List<ActivityManager.StackInfo> stackInfos = ams.getAllStackInfos();
             Console.log(Constants.DebugFlags.App.TimeSystemCalls, "[RecentsTaskLoader|getAllStackInfos]", "" + (System.currentTimeMillis() - t1) + "ms");
-            Console.log(Constants.DebugFlags.App.SystemUIHandshake, "[RecentsTaskLoader|stacks]", "" + tasks.size());
+            Console.log(Constants.DebugFlags.App.TaskDataLoader, "[RecentsTaskLoader|stacks]", "" + tasks.size());
             for (ActivityManager.StackInfo s : stackInfos) {
-                Console.log(Constants.DebugFlags.App.SystemUIHandshake, "  [RecentsTaskLoader|stack]", s.toString());
+                Console.log(Constants.DebugFlags.App.TaskDataLoader, "  [RecentsTaskLoader|stack]", s.toString());
                 if (stacks.containsKey(s.stackId)) {
                     stacks.get(s.stackId).setRect(s.bounds);
                 }
@@ -403,45 +432,46 @@
         return root;
     }
 
-    /** Acquires the task resource data from the pool.
-     * XXX: Move this into Task? */
+    /** Acquires the task resource data from the pool. */
     public void loadTaskData(Task t) {
         if (Constants.DebugFlags.App.EnableBackgroundTaskLoading) {
-            t.icon = mIconCache.get(t);
-            t.thumbnail = mThumbnailCache.get(t);
+            Drawable icon = mIconCache.get(t);
+            Bitmap thumbnail = mThumbnailCache.get(t);
 
             Console.log(Constants.DebugFlags.App.TaskDataLoader, "[RecentsTaskLoader|loadTask]",
-                    t + " icon: " + t.icon + " thumbnail: " + t.thumbnail);
+                    t + " icon: " + icon + " thumbnail: " + thumbnail +
+                            " thumbnailCacheSize: " + mThumbnailCache.size());
 
             boolean requiresLoad = false;
-            if (t.icon == null) {
-                t.icon = mDefaultIcon;
+            if (icon == null) {
+                icon = mDefaultIcon;
                 requiresLoad = true;
             }
-            if (t.thumbnail == null) {
-                t.thumbnail = mDefaultThumbnail;
+            if (thumbnail == null) {
+                thumbnail = mDefaultThumbnail;
                 requiresLoad = true;
             }
             if (requiresLoad) {
                 mLoadQueue.addTask(t);
             }
+            t.notifyTaskLoaded(thumbnail, icon);
         }
     }
 
-    /** Releases the task resource data back into the pool.
-     * XXX: Move this into Task? */
+    /** Releases the task resource data back into the pool. */
     public void unloadTaskData(Task t) {
         if (Constants.DebugFlags.App.EnableBackgroundTaskLoading) {
             Console.log(Constants.DebugFlags.App.TaskDataLoader,
-                    "[RecentsTaskLoader|unloadTask]", t);
+                    "[RecentsTaskLoader|unloadTask]", t +
+                    " thumbnailCacheSize: " + mThumbnailCache.size());
             mLoadQueue.removeTask(t);
-            t.icon = mDefaultIcon;
-            t.thumbnail = mDefaultThumbnail;
+            t.notifyTaskUnloaded(mDefaultThumbnail, mDefaultIcon);
+        } else {
+            t.notifyTaskUnloaded(null, null);
         }
     }
 
-    /** Completely removes the resource data from the pool.
-     * XXX: Move this into Task? */
+    /** Completely removes the resource data from the pool. */
     public void deleteTaskData(Task t) {
         if (Constants.DebugFlags.App.EnableBackgroundTaskLoading) {
             Console.log(Constants.DebugFlags.App.TaskDataLoader,
@@ -449,9 +479,10 @@
             mLoadQueue.removeTask(t);
             mThumbnailCache.remove(t);
             mIconCache.remove(t);
+            t.notifyTaskUnloaded(mDefaultThumbnail, mDefaultIcon);
+        } else {
+            t.notifyTaskUnloaded(null, null);
         }
-        t.icon = mDefaultIcon;
-        t.thumbnail = mDefaultThumbnail;
     }
 
     /** Stops the task loader */
@@ -460,4 +491,51 @@
         mLoader.stop();
         mLoadQueue.clearTasks();
     }
+
+    void onTrimMemory(int level) {
+        Console.log(Constants.DebugFlags.App.Memory, "[RecentsTaskLoader|onTrimMemory]",
+                Console.trimMemoryLevelToString(level));
+
+        if (Constants.DebugFlags.App.EnableBackgroundTaskLoading) {
+            // If we are hidden, then we should unload each of the task keys
+            if (level == ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) {
+                Console.log(Constants.DebugFlags.App.Memory, "[RecentsTaskLoader|unloadTasks]"
+                );
+                // Unload each of the keys in the thumbnail cache
+                Map<Task, Bitmap> thumbnailCache = mThumbnailCache.snapshot();
+                for (Task t : thumbnailCache.keySet()) {
+                    unloadTaskData(t);
+                }
+                // As well as the keys in the icon cache
+                Map<Task, Drawable> iconCache = mIconCache.snapshot();
+                for (Task t : iconCache.keySet()) {
+                    unloadTaskData(t);
+                }
+            }
+
+            switch (level) {
+                case ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN:
+                case ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE:
+                case ComponentCallbacks2.TRIM_MEMORY_BACKGROUND:
+                    // We are leaving recents, so trim the data a bit
+                    mThumbnailCache.trimToSize(mMaxThumbnailCacheSize / 2);
+                    mIconCache.trimToSize(mMaxIconCacheSize / 2);
+                    break;
+                case ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW:
+                case ComponentCallbacks2.TRIM_MEMORY_MODERATE:
+                    // We are going to be low on memory
+                    mThumbnailCache.trimToSize(mMaxThumbnailCacheSize / 4);
+                    mIconCache.trimToSize(mMaxIconCacheSize / 4);
+                    break;
+                case ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL:
+                case ComponentCallbacks2.TRIM_MEMORY_COMPLETE:
+                    // We are low on memory, so release everything
+                    mThumbnailCache.evictAll();
+                    mIconCache.evictAll();
+                    break;
+                default:
+                    break;
+            }
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
index 9b03c5d..378984c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
@@ -54,6 +54,24 @@
         }
     }
 
+    /** Notifies the callback listeners that this task has been loaded */
+    public void notifyTaskLoaded(Bitmap thumbnail, Drawable icon) {
+        this.icon = icon;
+        this.thumbnail = thumbnail;
+        if (mCb != null) {
+            mCb.onTaskBound();
+        }
+    }
+
+    /** Notifies the callback listeners that this task has been unloaded */
+    public void notifyTaskUnloaded(Bitmap defaultThumbnail, Drawable defaultIcon) {
+        icon = defaultIcon;
+        thumbnail = defaultThumbnail;
+        if (mCb != null) {
+            mCb.onTaskUnbound();
+        }
+    }
+
     @Override
     public boolean equals(Object o) {
         // If we have multiple task entries for the same task, then we do the simple object
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/TaskCallbacks.java b/packages/SystemUI/src/com/android/systemui/recents/model/TaskCallbacks.java
index 169f56c..712580d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/TaskCallbacks.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/TaskCallbacks.java
@@ -20,4 +20,8 @@
 public interface TaskCallbacks {
     /* Notifies when a task's data has been updated */
     public void onTaskDataChanged(Task task);
+    /* Notifies when a task has been bound */
+    public void onTaskBound();
+    /* Notifies when a task has been unbound */
+    public void onTaskUnbound();
 }
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/recents/views/SwipeHelper.java
index fe661bc..21ef9ff 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/SwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/SwipeHelper.java
@@ -28,6 +28,8 @@
 import android.view.VelocityTracker;
 import android.view.View;
 import android.view.animation.LinearInterpolator;
+import com.android.systemui.recents.Console;
+import com.android.systemui.recents.Constants;
 
 /**
  * This class facilitates swipe to dismiss. It defines an interface to be implemented by the
@@ -176,6 +178,9 @@
     }
 
     public boolean onInterceptTouchEvent(MotionEvent ev) {
+        Console.log(Constants.DebugFlags.UI.TouchEvents,
+                "[SwipeHelper|interceptTouchEvent]",
+                Console.motionEventActionToString(ev.getAction()), Console.AnsiBlue);
         final int action = ev.getAction();
 
         switch (action) {
@@ -200,7 +205,7 @@
                     if (Math.abs(delta) > mPagingTouchSlop) {
                         mCallback.onBeginDrag(mCurrView);
                         mDragging = true;
-                        mInitialTouchPos = getPos(ev) - getTranslation(mCurrView);
+                        mInitialTouchPos = pos - getTranslation(mCurrView);
                     }
                 }
                 break;
@@ -286,6 +291,10 @@
     }
 
     public boolean onTouchEvent(MotionEvent ev) {
+        Console.log(Constants.DebugFlags.UI.TouchEvents,
+                "[SwipeHelper|touchEvent]",
+                Console.motionEventActionToString(ev.getAction()), Console.AnsiBlue);
+
         if (!mDragging) {
             if (!onInterceptTouchEvent(ev)) {
                 return mCanCurrViewBeDimissed;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index 9dd6c0b..7753d69 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -435,19 +435,12 @@
         mStackRectSansPeek.top += Constants.Values.TaskStackView.StackPeekHeightPct * mStackRect.height();
 
         // Compute the task rect
-        if (RecentsConfiguration.getInstance().layoutVerticalStack) {
-            int minHeight = (int) (mStackRect.height() -
-                    (Constants.Values.TaskStackView.StackPeekHeightPct * mStackRect.height()));
-            int size = Math.min(minHeight, Math.min(mStackRect.width(), mStackRect.height()));
-            int centerX = mStackRect.centerX();
-            mTaskRect.set(centerX - size / 2, mStackRectSansPeek.top,
-                    centerX + size / 2, mStackRectSansPeek.top + size);
-        } else {
-            int size = Math.min(mStackRect.width(), mStackRect.height());
-            int centerY = mStackRect.centerY();
-            mTaskRect.set(mStackRectSansPeek.top, centerY - size / 2,
-                    mStackRectSansPeek.top + size, centerY + size / 2);
-        }
+        int minHeight = (int) (mStackRect.height() -
+                (Constants.Values.TaskStackView.StackPeekHeightPct * mStackRect.height()));
+        int size = Math.min(minHeight, Math.min(mStackRect.width(), mStackRect.height()));
+        int centerX = mStackRect.centerX();
+        mTaskRect.set(centerX - size / 2, mStackRectSansPeek.top,
+                centerX + size / 2, mStackRectSansPeek.top + size);
 
         // Update the scroll bounds
         updateMinMaxScroll(false);
@@ -589,7 +582,6 @@
         // Report that this tasks's data is no longer being used
         RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
         loader.unloadTaskData(task);
-        tv.unbindFromTask();
 
         // Detach the view from the hierarchy
         detachViewFromParent(tv);
@@ -610,7 +602,6 @@
         // Request that this tasks's data be filled
         RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
         loader.loadTaskData(task);
-        tv.syncToTask();
 
         // Find the index where this task should be placed in the children
         int insertIndex = -1;
@@ -678,14 +669,13 @@
 }
 
 /* Handles touch events */
-class TaskStackViewTouchHandler {
+class TaskStackViewTouchHandler implements SwipeHelper.Callback {
     static int INACTIVE_POINTER_ID = -1;
 
     TaskStackView mSv;
     VelocityTracker mVelocityTracker;
 
     boolean mIsScrolling;
-    boolean mIsSwiping;
 
     int mInitialMotionX, mInitialMotionY;
     int mLastMotionX, mLastMotionY;
@@ -697,21 +687,24 @@
     int mMaximumVelocity;
     // The scroll touch slop is used to calculate when we start scrolling
     int mScrollTouchSlop;
-    // The swipe touch slop is used to calculate when we start swiping left/right, this takes
-    // precendence over the scroll touch slop in case the user makes a gesture that starts scrolling
-    // but is intended to be a swipe
-    int mSwipeTouchSlop;
-    // After a certain amount of scrolling, we should start ignoring checks for swiping
-    int mMaxScrollMotionToRejectSwipe;
+    // The page touch slop is used to calculate when we start swiping
+    float mPagingTouchSlop;
+
+    SwipeHelper mSwipeHelper;
+    boolean mInterceptedBySwipeHelper;
 
     public TaskStackViewTouchHandler(Context context, TaskStackView sv) {
         ViewConfiguration configuration = ViewConfiguration.get(context);
         mMinimumVelocity = configuration.getScaledMinimumFlingVelocity();
         mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
         mScrollTouchSlop = configuration.getScaledTouchSlop();
-        mSwipeTouchSlop = 2 * mScrollTouchSlop;
-        mMaxScrollMotionToRejectSwipe = 4 * mScrollTouchSlop;
+        mPagingTouchSlop = configuration.getScaledPagingTouchSlop();
         mSv = sv;
+
+
+        float densityScale = context.getResources().getDisplayMetrics().density;
+        mSwipeHelper = new SwipeHelper(SwipeHelper.X, this, densityScale, mPagingTouchSlop);
+        mSwipeHelper.setMinAlpha(1f);
     }
 
     /** Velocity tracker helpers */
@@ -754,11 +747,18 @@
                 "[TaskStackViewTouchHandler|interceptTouchEvent]",
                 Console.motionEventActionToString(ev.getAction()), Console.AnsiBlue);
 
+        // Return early if we have no children
         boolean hasChildren = (mSv.getChildCount() > 0);
         if (!hasChildren) {
             return false;
         }
 
+        // Pass through to swipe helper if we are swiping
+        mInterceptedBySwipeHelper = mSwipeHelper.onInterceptTouchEvent(ev);
+        if (mInterceptedBySwipeHelper) {
+            return true;
+        }
+
         boolean wasScrolling = !mSv.mScroller.isFinished() ||
                 (mSv.mScrollAnimator != null && mSv.mScrollAnimator.isRunning());
         int action = ev.getAction();
@@ -777,7 +777,8 @@
                 mVelocityTracker.addMovement(ev);
                 // Check if the scroller is finished yet
                 mIsScrolling = !mSv.mScroller.isFinished();
-                mIsSwiping = false;
+                // Enable HW layers
+                mSv.addHwLayersRefCount();
                 break;
             }
             case MotionEvent.ACTION_MOVE: {
@@ -786,25 +787,7 @@
                 int activePointerIndex = ev.findPointerIndex(mActivePointerId);
                 int y = (int) ev.getY(activePointerIndex);
                 int x = (int) ev.getX(activePointerIndex);
-                if (mActiveTaskView != null &&
-                        mTotalScrollMotion < mMaxScrollMotionToRejectSwipe &&
-                        Math.abs(x - mInitialMotionX) > Math.abs(y - mInitialMotionY) &&
-                        Math.abs(x - mInitialMotionX) > mSwipeTouchSlop) {
-                    // Start swiping and stop scrolling
-                    mIsScrolling = false;
-                    mIsSwiping = true;
-                    System.out.println("SWIPING: " + mActiveTaskView);
-                    // Initialize the velocity tracker if necessary
-                    initOrResetVelocityTracker();
-                    mVelocityTracker.addMovement(ev);
-                    // Disallow parents from intercepting touch events
-                    final ViewParent parent = mSv.getParent();
-                    if (parent != null) {
-                        parent.requestDisallowInterceptTouchEvent(true);
-                    }
-                    // Enable HW layers
-                    mSv.addHwLayersRefCount();
-                } else if (Math.abs(y - mInitialMotionY) > mScrollTouchSlop) {
+                if (Math.abs(y - mInitialMotionY) > mScrollTouchSlop) {
                     // Save the touch move info
                     mIsScrolling = true;
                     // Initialize the velocity tracker if necessary
@@ -815,8 +798,6 @@
                     if (parent != null) {
                         parent.requestDisallowInterceptTouchEvent(true);
                     }
-                    // Enable HW layers
-                    mSv.addHwLayersRefCount();
                 }
 
                 mLastMotionX = x;
@@ -829,16 +810,17 @@
                 mSv.animateBoundScroll(Constants.Values.TaskStackView.Animation.SnapScrollBackDuration);
                 // Reset the drag state and the velocity tracker
                 mIsScrolling = false;
-                mIsSwiping = false;
                 mActivePointerId = INACTIVE_POINTER_ID;
                 mActiveTaskView = null;
                 mTotalScrollMotion = 0;
                 recycleVelocityTracker();
+                // Disable HW layers
+                mSv.decHwLayersRefCount();
                 break;
             }
         }
 
-        return wasScrolling || mIsScrolling || mIsSwiping;
+        return wasScrolling || mIsScrolling;
     }
 
     /** Handles touch events once we have intercepted them */
@@ -853,6 +835,11 @@
             return false;
         }
 
+        // Pass through to swipe helper if we are swiping
+        if (mInterceptedBySwipeHelper && mSwipeHelper.onTouchEvent(ev)) {
+            return true;
+        }
+
         // Update the velocity tracker
         initVelocityTrackerIfNotExists();
         mVelocityTracker.addMovement(ev);
@@ -871,7 +858,6 @@
                 // Initialize the velocity tracker
                 initOrResetVelocityTracker();
                 mVelocityTracker.addMovement(ev);
-                // XXX: Set mIsScrolling or mIsSwiping?
                 // Disallow parents from intercepting touch events
                 final ViewParent parent = mSv.getParent();
                 if (parent != null) {
@@ -886,28 +872,7 @@
                 int x = (int) ev.getX(activePointerIndex);
                 int y = (int) ev.getY(activePointerIndex);
                 int deltaY = mLastMotionY - y;
-                int deltaX = x - mLastMotionX;
-                if (!mIsSwiping) {
-                    if (mActiveTaskView != null &&
-                            mTotalScrollMotion < mMaxScrollMotionToRejectSwipe &&
-                            Math.abs(x - mInitialMotionX) > Math.abs(y - mInitialMotionY) &&
-                            Math.abs(x - mInitialMotionX) > mSwipeTouchSlop) {
-                        mIsScrolling = false;
-                        mIsSwiping = true;
-                        System.out.println("SWIPING: " + mActiveTaskView);
-                        // Initialize the velocity tracker if necessary
-                        initOrResetVelocityTracker();
-                        mVelocityTracker.addMovement(ev);
-                        // Disallow parents from intercepting touch events
-                        final ViewParent parent = mSv.getParent();
-                        if (parent != null) {
-                            parent.requestDisallowInterceptTouchEvent(true);
-                        }
-                        // Enable HW layers
-                        mSv.addHwLayersRefCount();
-                    }
-                }
-                if (!mIsSwiping && !mIsScrolling) {
+                if (!mIsScrolling) {
                     if (Math.abs(y - mInitialMotionY) > mScrollTouchSlop) {
                         mIsScrolling = true;
                         // Initialize the velocity tracker
@@ -927,8 +892,6 @@
                     if (mSv.isScrollOutOfBounds()) {
                         mVelocityTracker.clear();
                     }
-                } else if (mIsSwiping) {
-                    mActiveTaskView.setTranslationX(mActiveTaskView.getTranslationX() + deltaX);
                 }
                 mLastMotionX = x;
                 mLastMotionY = y;
@@ -936,107 +899,33 @@
                 break;
             }
             case MotionEvent.ACTION_UP: {
-                if (mIsScrolling || mIsSwiping) {
-                    final TaskView activeTv = mActiveTaskView;
-                    final VelocityTracker velocityTracker = mVelocityTracker;
-                    velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
+                final VelocityTracker velocityTracker = mVelocityTracker;
+                velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
+                int velocity = (int) velocityTracker.getYVelocity(mActivePointerId);
 
-                    if (mIsSwiping) {
-                        int initialVelocity = (int) velocityTracker.getXVelocity(mActivePointerId);
-                        if ((Math.abs(initialVelocity) > mMinimumVelocity)) {
-                            // Fling to dismiss
-                            int newScrollX = (int) (Math.signum(initialVelocity) *
-                                    activeTv.getMeasuredWidth());
-                            int duration = Math.min(Constants.Values.TaskStackView.Animation.SwipeDismissDuration,
-                                    (int) (Math.abs(newScrollX - activeTv.getScrollX()) *
-                                            1000f / Math.abs(initialVelocity)));
-                            activeTv.animate()
-                                    .translationX(newScrollX)
-                                    .alpha(0f)
-                                    .setDuration(duration)
-                                    .setListener(new AnimatorListenerAdapter() {
-                                        @Override
-                                        public void onAnimationEnd(Animator animation) {
-                                            Task task = activeTv.getTask();
-                                            Activity activity = (Activity) mSv.getContext();
-
-                                            // We have to disable the listener to ensure that we
-                                            // don't hit this again
-                                            activeTv.animate().setListener(null);
-
-                                            // Remove the task from the view
-                                            mSv.mStack.removeTask(task);
-
-                                            // Remove any stored data from the loader
-                                            RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
-                                            loader.deleteTaskData(task);
-
-                                            // Remove the task from activity manager
-                                            final ActivityManager am = (ActivityManager)
-                                                activity.getSystemService(Context.ACTIVITY_SERVICE);
-                                            if (am != null) {
-                                                am.removeTask(activeTv.getTask().id,
-                                                        ActivityManager.REMOVE_TASK_KILL_PROCESS);
-                                            }
-
-                                            // If there are no remaining tasks, then just close the activity
-                                            if (mSv.mStack.getTaskCount() == 0) {
-                                                activity.finish();
-                                            }
-
-                                            // Disable HW layers
-                                            mSv.decHwLayersRefCount();
-                                        }
-                                    })
-                                    .start();
-                            // Enable HW layers
-                            mSv.addHwLayersRefCount();
-                        } else {
-                            // Animate it back into place
-                            // XXX: Make this animation a function of the velocity OR distance
-                            int duration = Constants.Values.TaskStackView.Animation.SwipeSnapBackDuration;
-                            activeTv.animate()
-                                    .translationX(0)
-                                    .setDuration(duration)
-                                    .setListener(new AnimatorListenerAdapter() {
-                                        @Override
-                                        public void onAnimationEnd(Animator animation) {
-                                            // Disable HW layers
-                                            mSv.decHwLayersRefCount();
-                                        }
-                                    })
-                                    .start();
-                            // Enable HW layers
-                            mSv.addHwLayersRefCount();
-                        }
-                    } else {
-                        int velocity = (int) velocityTracker.getYVelocity(mActivePointerId);
-                        if ((Math.abs(velocity) > mMinimumVelocity)) {
-                            Console.log(Constants.DebugFlags.UI.TouchEvents,
-                                "[TaskStackViewTouchHandler|fling]",
-                                "scroll: " + mSv.getStackScroll() + " velocity: " + velocity,
-                                    Console.AnsiGreen);
-                            // Enable HW layers on the stack
-                            mSv.addHwLayersRefCount();
-                            // Fling scroll
-                            mSv.mScroller.fling(0, mSv.getStackScroll(),
-                                    0, -velocity,
-                                    0, 0,
-                                    mSv.mMinScroll, mSv.mMaxScroll,
-                                    0, 0);
-                            // Invalidate to kick off computeScroll
-                            mSv.invalidate();
-                        } else if (mSv.isScrollOutOfBounds()) {
-                            // Animate the scroll back into bounds
-                            // XXX: Make this animation a function of the velocity OR distance
-                            mSv.animateBoundScroll(Constants.Values.TaskStackView.Animation.SnapScrollBackDuration);
-                        }
-                    }
+                if (mIsScrolling && (Math.abs(velocity) > mMinimumVelocity)) {
+                    Console.log(Constants.DebugFlags.UI.TouchEvents,
+                        "[TaskStackViewTouchHandler|fling]",
+                        "scroll: " + mSv.getStackScroll() + " velocity: " + velocity,
+                            Console.AnsiGreen);
+                    // Enable HW layers on the stack
+                    mSv.addHwLayersRefCount();
+                    // Fling scroll
+                    mSv.mScroller.fling(0, mSv.getStackScroll(),
+                            0, -velocity,
+                            0, 0,
+                            mSv.mMinScroll, mSv.mMaxScroll,
+                            0, 0);
+                    // Invalidate to kick off computeScroll
+                    mSv.invalidate();
+                } else if (mSv.isScrollOutOfBounds()) {
+                    // Animate the scroll back into bounds
+                    // XXX: Make this animation a function of the velocity OR distance
+                    mSv.animateBoundScroll(Constants.Values.TaskStackView.Animation.SnapScrollBackDuration);
                 }
 
                 mActivePointerId = INACTIVE_POINTER_ID;
                 mIsScrolling = false;
-                mIsSwiping = false;
                 mTotalScrollMotion = 0;
                 recycleVelocityTracker();
                 // Disable HW layers
@@ -1044,25 +933,14 @@
                 break;
             }
             case MotionEvent.ACTION_CANCEL: {
-                if (mIsScrolling || mIsSwiping) {
-                    if (mIsSwiping) {
-                        // Animate it back into place
-                        // XXX: Make this animation a function of the velocity OR distance
-                        int duration = Constants.Values.TaskStackView.Animation.SwipeSnapBackDuration;
-                        mActiveTaskView.animate()
-                                .translationX(0)
-                                .setDuration(duration)
-                                .start();
-                    } else {
-                        // Animate the scroll back into bounds
-                        // XXX: Make this animation a function of the velocity OR distance
-                        mSv.animateBoundScroll(Constants.Values.TaskStackView.Animation.SnapScrollBackDuration);
-                    }
+                if (mSv.isScrollOutOfBounds()) {
+                    // Animate the scroll back into bounds
+                    // XXX: Make this animation a function of the velocity OR distance
+                    mSv.animateBoundScroll(Constants.Values.TaskStackView.Animation.SnapScrollBackDuration);
                 }
 
                 mActivePointerId = INACTIVE_POINTER_ID;
                 mIsScrolling = false;
-                mIsSwiping = false;
                 mTotalScrollMotion = 0;
                 recycleVelocityTracker();
                 // Disable HW layers
@@ -1072,4 +950,72 @@
         }
         return true;
     }
+
+    /**** SwipeHelper Implementation ****/
+
+    @Override
+    public View getChildAtPosition(MotionEvent ev) {
+        return findViewAtPoint((int) ev.getX(), (int) ev.getY());
+    }
+
+    @Override
+    public boolean canChildBeDismissed(View v) {
+        return true;
+    }
+
+    @Override
+    public void onBeginDrag(View v) {
+        // Enable HW layers
+        mSv.addHwLayersRefCount();
+        // Disallow parents from intercepting touch events
+        final ViewParent parent = mSv.getParent();
+        if (parent != null) {
+            parent.requestDisallowInterceptTouchEvent(true);
+        }
+    }
+
+    @Override
+    public void onChildDismissed(View v) {
+        TaskView tv = (TaskView) v;
+        Task task = tv.getTask();
+        Activity activity = (Activity) mSv.getContext();
+
+        // We have to disable the listener to ensure that we
+        // don't hit this again
+        tv.animate().setListener(null);
+
+        // Remove the task from the view
+        mSv.mStack.removeTask(task);
+
+        // Remove any stored data from the loader
+        RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
+        loader.deleteTaskData(task);
+
+        // Remove the task from activity manager
+        final ActivityManager am = (ActivityManager)
+                activity.getSystemService(Context.ACTIVITY_SERVICE);
+        if (am != null) {
+            am.removeTask(tv.getTask().id,
+                    ActivityManager.REMOVE_TASK_KILL_PROCESS);
+        }
+
+        // If there are no remaining tasks, then just close the activity
+        if (mSv.mStack.getTaskCount() == 0) {
+            activity.finish();
+        }
+
+        // Disable HW layers
+        mSv.decHwLayersRefCount();
+    }
+
+    @Override
+    public void onSnapBackCompleted(View v) {
+        // Do Nothing
+    }
+
+    @Override
+    public void onDragCancelled(View v) {
+        // Disable HW layers
+        mSv.decHwLayersRefCount();
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
index b1d0d13..9ef74ca 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -255,13 +255,13 @@
     }
 
     /** Actually synchronizes the model data into the views */
-    void syncToTask() {
+    private void syncToTask() {
         mThumbnailView.rebindToTask(mTask, false);
         mIconView.rebindToTask(mTask, false);
     }
 
     /** Unset the task and callback */
-    void unbindFromTask() {
+    private void unbindFromTask() {
         mTask.setCallbacks(null);
         mThumbnailView.unbindFromTask();
         mIconView.unbindFromTask();
@@ -357,16 +357,16 @@
 
     /** Enable the hw layers on this task view */
     void enableHwLayers() {
-        Console.log(Constants.DebugFlags.UI.HwLayers, "[TaskView|enableHwLayers]");
         mThumbnailView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
     }
 
     /** Disable the hw layers on this task view */
     void disableHwLayers() {
-        Console.log(Constants.DebugFlags.UI.HwLayers, "[TaskView|disableHwLayers]");
         mThumbnailView.setLayerType(View.LAYER_TYPE_NONE, null);
     }
 
+    /**** TaskCallbacks Implementation ****/
+
     @Override
     public void onTaskDataChanged(Task task) {
         Console.log(Constants.DebugFlags.App.EnableBackgroundTaskLoading,
@@ -380,6 +380,16 @@
     }
 
     @Override
+    public void onTaskBound() {
+        syncToTask();
+    }
+
+    @Override
+    public void onTaskUnbound() {
+        unbindFromTask();
+    }
+
+    @Override
     public void onClick(View v) {
         mCb.onTaskIconClicked(this);
     }
diff --git a/packages/WallpaperCropper/src/com/android/wallpapercropper/WallpaperCropActivity.java b/packages/WallpaperCropper/src/com/android/wallpapercropper/WallpaperCropActivity.java
index b9b87b1..e45b98c 100644
--- a/packages/WallpaperCropper/src/com/android/wallpapercropper/WallpaperCropActivity.java
+++ b/packages/WallpaperCropper/src/com/android/wallpapercropper/WallpaperCropActivity.java
@@ -340,6 +340,13 @@
                 getWindowManager());
         // Get the crop
         RectF cropRect = mCropView.getCrop();
+
+        // Due to rounding errors in the cropview renderer the edges can be slightly offset
+        // therefore we ensure that the boundaries are sanely defined
+        cropRect.left = Math.max(0, cropRect.left);
+        cropRect.right = Math.min(mCropView.getWidth(), cropRect.right);
+        cropRect.top = Math.max(0, cropRect.top);
+        cropRect.bottom = Math.min(mCropView.getHeight(), cropRect.bottom);
         int cropRotation = mCropView.getImageRotation();
         float cropScale = mCropView.getWidth() / (float) cropRect.width();
 
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 15a68ef..1cca164 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -3417,18 +3417,22 @@
                         && attrs.height == WindowManager.LayoutParams.MATCH_PARENT) {
                     if (DEBUG_LAYOUT) Slog.v(TAG, "Fullscreen window: " + win);
                     mTopFullscreenOpaqueWindowState = win;
-                    if (showWhenLocked && !mHideWindowBehindKeyguard) {
-                        if (DEBUG_LAYOUT) Slog.v(TAG, "Setting mHideLockScreen to true by win " + win);
-                        mHideLockScreen = true;
-                        mForceStatusBarFromKeyguard = false;
-                    }
-                    if ((fl & FLAG_DISMISS_KEYGUARD) != 0
-                            && mDismissKeyguard == DISMISS_KEYGUARD_NONE) {
-                        if (DEBUG_LAYOUT) Slog.v(TAG, "Setting mDismissKeyguard true by win " + win);
-                        mDismissKeyguard = mWinDismissingKeyguard == win ?
-                                DISMISS_KEYGUARD_CONTINUE : DISMISS_KEYGUARD_START;
-                        mWinDismissingKeyguard = win;
-                        mForceStatusBarFromKeyguard = mShowingLockscreen && isKeyguardSecure();
+                    if (!mHideWindowBehindKeyguard) {
+                        if (showWhenLocked) {
+                            if (DEBUG_LAYOUT) Slog.v(TAG,
+                                    "Setting mHideLockScreen to true by win " + win);
+                            mHideLockScreen = true;
+                            mForceStatusBarFromKeyguard = false;
+                        }
+                        if ((fl & FLAG_DISMISS_KEYGUARD) != 0
+                                && mDismissKeyguard == DISMISS_KEYGUARD_NONE) {
+                            if (DEBUG_LAYOUT) Slog.v(TAG,
+                                    "Setting mDismissKeyguard true by win " + win);
+                            mDismissKeyguard = mWinDismissingKeyguard == win ?
+                                    DISMISS_KEYGUARD_CONTINUE : DISMISS_KEYGUARD_START;
+                            mWinDismissingKeyguard = win;
+                            mForceStatusBarFromKeyguard = mShowingLockscreen && isKeyguardSecure();
+                        }
                     }
                     if ((fl & FLAG_ALLOW_LOCK_WHILE_SCREEN_ON) != 0) {
                         mAllowLockscreenWhenOn = true;
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index 3dcb488..e6163bd 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -457,6 +457,9 @@
      * @param userId the new active user's UserId
      */
     private void switchUser(int userId) {
+        if (mCurrentUserId == userId) {
+            return;
+        }
         mBlacklist.switchUser(userId);
         mLocationHandler.removeMessages(MSG_LOCATION_CHANGED);
         synchronized (mLock) {
diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java
index ad693d0..94f699f 100644
--- a/services/core/java/com/android/server/UiModeManagerService.java
+++ b/services/core/java/com/android/server/UiModeManagerService.java
@@ -173,7 +173,9 @@
         mDeskModeKeepsScreenOn = (context.getResources().getInteger(
                 com.android.internal.R.integer.config_deskDockKeepsScreenOn) == 1);
         mTelevision = context.getPackageManager().hasSystemFeature(
-                PackageManager.FEATURE_TELEVISION);
+                PackageManager.FEATURE_TELEVISION) ||
+            context.getPackageManager().hasSystemFeature(
+                    PackageManager.FEATURE_LEANBACK);
 
         mNightMode = Settings.Secure.getInt(context.getContentResolver(),
                 Settings.Secure.UI_NIGHT_MODE, UiModeManager.MODE_NIGHT_AUTO);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index cd9c920..ab7d60a 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -3319,20 +3319,35 @@
             return;
         }
         // Remove any existing entries that are the same kind of task.
+        final Intent intent = task.intent;
+        final boolean document = intent != null && intent.isDocument();
         for (int i=0; i<N; i++) {
             TaskRecord tr = mRecentTasks.get(i);
-            if (task.userId == tr.userId
-                    && ((task.affinity != null && task.affinity.equals(tr.affinity))
-                    || (task.intent != null && task.intent.filterEquals(tr.intent)))) {
-                tr.disposeThumbnail();
-                mRecentTasks.remove(i);
-                i--;
-                N--;
-                if (task.intent == null) {
-                    // If the new recent task we are adding is not fully
-                    // specified, then replace it with the existing recent task.
-                    task = tr;
+            if (task != tr) {
+                if (task.userId != tr.userId) {
+                    continue;
                 }
+                final Intent trIntent = tr.intent;
+                if ((task.affinity == null || !task.affinity.equals(tr.affinity)) &&
+                    (intent == null || !intent.filterEquals(trIntent))) {
+                    continue;
+                }
+                if (document || trIntent != null && trIntent.isDocument()) {
+                    // Document tasks do not match other tasks.
+                    continue;
+                }
+            }
+
+            // Either task and tr are the same or, their affinities match or their intents match
+            // and neither of them is a document.
+            tr.disposeThumbnail();
+            mRecentTasks.remove(i);
+            i--;
+            N--;
+            if (task.intent == null) {
+                // If the new recent task we are adding is not fully
+                // specified, then replace it with the existing recent task.
+                task = tr;
             }
         }
         if (N >= MAX_RECENT_TASKS) {
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 34cc22a..25292a0 100755
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -492,6 +492,9 @@
             cls = new ComponentName(info.packageName, info.targetActivity);
         }
         final int userId = UserHandle.getUserId(info.applicationInfo.uid);
+        boolean isDocument = intent != null & intent.isDocument();
+        // If documentData is non-null then it must match the existing task data.
+        Uri documentData = isDocument ? intent.getData() : null;
 
         if (DEBUG_TASKS) Slog.d(TAG, "Looking for task of " + target + " in " + this);
         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
@@ -508,23 +511,39 @@
                 continue;
             }
 
+            final Intent taskIntent = task.intent;
+            final Intent affinityIntent = task.affinityIntent;
+            final boolean taskIsDocument;
+            final Uri taskDocumentData;
+            if (taskIntent != null && taskIntent.isDocument()) {
+                taskIsDocument = true;
+                taskDocumentData = taskIntent.getData();
+            } else if (affinityIntent != null && affinityIntent.isDocument()) {
+                taskIsDocument = true;
+                taskDocumentData = affinityIntent.getData();
+            } else {
+                taskIsDocument = false;
+                taskDocumentData = null;
+            }
+
             if (DEBUG_TASKS) Slog.d(TAG, "Comparing existing cls="
-                    + r.task.intent.getComponent().flattenToShortString()
+                    + taskIntent.getComponent().flattenToShortString()
                     + "/aff=" + r.task.affinity + " to new cls="
                     + intent.getComponent().flattenToShortString() + "/aff=" + info.taskAffinity);
-            if (task.affinity != null) {
-                if (task.affinity.equals(info.taskAffinity)) {
+            if (!isDocument && !taskIsDocument && task.affinity != null) {
+                if (task.affinity.equals(target.taskAffinity)) {
                     if (DEBUG_TASKS) Slog.d(TAG, "Found matching affinity!");
                     return r;
                 }
-            } else if (task.intent != null && task.intent.getComponent().equals(cls)) {
+            } else if (taskIntent != null && taskIntent.getComponent().equals(cls) &&
+                    Objects.equals(documentData, taskDocumentData)) {
                 if (DEBUG_TASKS) Slog.d(TAG, "Found matching class!");
                 //dump();
                 if (DEBUG_TASKS) Slog.d(TAG, "For Intent " + intent + " bringing to top: "
                         + r.intent);
                 return r;
-            } else if (task.affinityIntent != null
-                    && task.affinityIntent.getComponent().equals(cls)) {
+            } else if (affinityIntent != null && affinityIntent.getComponent().equals(cls) &&
+                    Objects.equals(documentData, taskDocumentData)) {
                 if (DEBUG_TASKS) Slog.d(TAG, "Found matching class!");
                 //dump();
                 if (DEBUG_TASKS) Slog.d(TAG, "For Intent " + intent + " bringing to top: "
@@ -1857,7 +1876,7 @@
                 // If the caller has requested that the target task be
                 // reset, then do so.
                 if ((r.intent.getFlags()
-                        &Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
+                        & Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
                     resetTaskIfNeededLocked(r, r);
                     doShow = topRunningNonDelayedActivityLocked(null) == r;
                 }
@@ -2006,14 +2025,7 @@
                             + " out to new task " + target.task);
                 }
 
-                if (clearWhenTaskReset) {
-                    // This is the start of a new sub-task.
-                    if (target.thumbHolder == null) {
-                        target.thumbHolder = new ThumbnailHolder();
-                    }
-                } else {
-                    target.thumbHolder = newThumbHolder;
-                }
+                target.thumbHolder = newThumbHolder;
 
                 final int targetTaskId = targetTask.taskId;
                 mWindowManager.setAppGroupId(target.appToken, targetTaskId);
@@ -2484,7 +2496,7 @@
         final int index = activities.indexOf(r);
         if (index < (activities.size() - 1)) {
             task.setFrontOfTask();
-            if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
+            if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
                 // If the caller asked that this activity (and all above it)
                 // be cleared when the task is reset, don't lose that information,
                 // but propagate it up to the next activity.
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 9315648..3555993 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -17,6 +17,7 @@
 package com.android.server.am;
 
 import static android.Manifest.permission.START_ANY_ACTIVITY;
+import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
 import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
@@ -1202,6 +1203,19 @@
                 resultRecord.removeResultsLocked(
                     sourceRecord, resultWho, requestCode);
             }
+            if (sourceRecord.launchedFromUid == callingUid) {
+                // The new activity is being launched from the same uid as the previous
+                // activity in the flow, and asking to forward its result back to the
+                // previous.  In this case the activity is serving as a trampoline between
+                // the two, so we also want to update its launchedFromPackage to be the
+                // same as the previous activity.  Note that this is safe, since we know
+                // these two packages come from the same uid; the caller could just as
+                // well have supplied that same package name itself.  This specifially
+                // deals with the case of an intent picker/chooser being launched in the app
+                // flow to redirect to an activity picked by the user, where we want the final
+                // activity to consider it to have been launched by the previous app activity.
+                callingPackage = sourceRecord.launchedFromPackage;
+            }
         }
 
         if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
@@ -1430,14 +1444,20 @@
             }
         }
 
+        final boolean newDocument = intent.isDocument();
         if (sourceRecord == null) {
             // This activity is not being started from another...  in this
             // case we -always- start a new task.
-            if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
+            if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
                 Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
                         "Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent);
                 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
             }
+        } else if (newDocument) {
+            if (r.launchMode != ActivityInfo.LAUNCH_MULTIPLE) {
+                Slog.w(TAG, "FLAG_ACTIVITY_NEW_DOCUMENT and launchMode != \"standard\"");
+                r.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
+            }
         } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
             // The original activity who is starting us is running as a single
             // instance...  this new activity it is starting must go on its
@@ -1460,7 +1480,7 @@
                 // so we don't want to blindly throw it in to that task.  Instead we will take
                 // the NEW_TASK flow and try to find a task for it. But save the task information
                 // so it can be used when creating the new task.
-                if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
+                if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
                     Slog.w(TAG, "startActivity called from finishing " + sourceRecord
                             + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent);
                     launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
@@ -1476,7 +1496,7 @@
             sourceStack = null;
         }
 
-        if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
+        if (r.resultTo != null && (launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
             // For whatever reason this activity is being launched into a new
             // task...  yet the caller has requested a result back.  Well, that
             // is pretty messed up, so instead immediately send back a cancel
@@ -1493,8 +1513,8 @@
         boolean movedHome = false;
         TaskRecord reuseTask = null;
         ActivityStack targetStack;
-        if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
-                (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
+        if (((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
+                (launchFlags & Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
                 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
                 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
             // If bring to front is requested, and no result is requested, and
@@ -1683,7 +1703,7 @@
             if (top != null && r.resultTo == null) {
                 if (top.realActivity.equals(r.realActivity) && top.userId == r.userId) {
                     if (top.app != null && top.app.thread != null) {
-                        if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
+                        if ((launchFlags & Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
                             || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP
                             || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
                             ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, top,
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index b925856..efbfb33 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -90,6 +90,7 @@
     private static final int MSG_SYSTEM_READY = 3;
     private static final int MSG_BOOT_COMPLETED = 4;
     private static final int MSG_USER_SWITCHED = 5;
+    private static final int MSG_START_ACCESSORY_MODE = 6;
 
     private static final int AUDIO_MODE_NONE = 0;
     private static final int AUDIO_MODE_SOURCE = 1;
@@ -152,7 +153,7 @@
                 mHandler.updateState(state);
             } else if ("START".equals(accessory)) {
                 if (DEBUG) Slog.d(TAG, "got accessory start");
-                startAccessoryMode();
+                 mHandler.sendEmptyMessage(MSG_START_ACCESSORY_MODE);
             }
         }
     };
@@ -170,7 +171,7 @@
 
         if (nativeIsStartRequested()) {
             if (DEBUG) Slog.d(TAG, "accessory attached at boot");
-            startAccessoryMode();
+             mHandler.sendEmptyMessage(MSG_START_ACCESSORY_MODE);
         }
 
         boolean secureAdbEnabled = SystemProperties.getBoolean("ro.adb.secure", false);
@@ -232,6 +233,8 @@
             functions = UsbManager.USB_FUNCTION_AUDIO_SOURCE;
         }
 
+        if (DEBUG) Slog.d(TAG, "startAccessoryMode: " + functions);
+
         if (functions != null) {
             mAccessoryModeRequestTime = SystemClock.elapsedRealtime();
             setCurrentFunctions(functions, false);
@@ -306,6 +309,7 @@
         // current USB state
         private boolean mConnected;
         private boolean mConfigured;
+        private boolean mAccessoryStartPending;
         private String mCurrentFunctions;
         private String mDefaultFunctions;
         private UsbAccessory mCurrentAccessory;
@@ -612,6 +616,11 @@
                 case MSG_UPDATE_STATE:
                     mConnected = (msg.arg1 == 1);
                     mConfigured = (msg.arg2 == 1);
+
+                    if (!mConnected) {
+                        mAccessoryStartPending = false;
+                    }
+
                     updateUsbNotification();
                     updateAdbNotification();
                     if (containsFunction(mCurrentFunctions,
@@ -625,6 +634,10 @@
                         updateUsbState();
                         updateAudioSourceFunction();
                     }
+                    if (mConnected && mConfigured && mAccessoryStartPending) {
+                        startAccessoryMode();
+                        mAccessoryStartPending = false;
+                    }
                     break;
                 case MSG_ENABLE_ADB:
                     setAdbEnabled(msg.arg1 == 1);
@@ -661,6 +674,16 @@
                     mCurrentUser = msg.arg1;
                     break;
                 }
+                case MSG_START_ACCESSORY_MODE:
+                    if (mConnected && mConfigured) {
+                        startAccessoryMode();
+                    } else {
+                        // we sometimes receive the kernel "accessory start" uevent
+                        // before the "configured" uevent. In this case we need to defer
+                        // handling this event until after we received the configured event
+                        mAccessoryStartPending = true;
+                    }
+                    break;
             }
         }
 
diff --git a/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
index 6666385..b235408 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
@@ -142,6 +142,13 @@
     }
 
     @LayoutlibDelegate
+    /*package*/ static boolean native_isConvex(long nPath) {
+        Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
+                "Path.isConvex is not supported.", null, null);
+        return true;
+    }
+
+    @LayoutlibDelegate
     /*package*/ static int native_getFillType(long nPath) {
         Path_Delegate pathDelegate = sManager.getDelegate(nPath);
         if (pathDelegate == null) {
diff --git a/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java b/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java
index d40352f..b16b4aa 100644
--- a/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java
+++ b/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java
@@ -18,6 +18,7 @@
 
 import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
 import com.ibm.icu.text.DateTimePatternGenerator;
+import com.ibm.icu.util.Currency;
 import com.ibm.icu.util.ULocale;
 
 import java.util.Locale;
@@ -117,6 +118,11 @@
     }
 
     @LayoutlibDelegate
+    /*package*/ static int getCurrencyNumericCode(String currencyCode) {
+        return Currency.getInstance(currencyCode).getNumericCode();
+    }
+
+    @LayoutlibDelegate
     /*package*/ static String getCurrencySymbol(String locale, String currencyCode) {
         return "";
     }
@@ -231,7 +237,7 @@
         result.percent = '%';
         result.perMill = '\u2030';
         result.monetarySeparator = ' ';
-        result.minusSign = '-';
+        result.minusSign = "-";
         result.exponentSeparator = "e";
         result.infinity = "\u221E";
         result.NaN = "NaN";