Merge "Show more logs when switching users and IMMS#DEBUG==true." into mnc-dev
diff --git a/api/current.txt b/api/current.txt
index 3c878c8..481e651 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -4384,6 +4384,7 @@
     method public void setSharedElementReturnTransition(android.transition.Transition);
     method public void setTargetFragment(android.app.Fragment, int);
     method public void setUserVisibleHint(boolean);
+    method public boolean shouldShowRequestPermissionRationale(java.lang.String);
     method public void startActivity(android.content.Intent);
     method public void startActivity(android.content.Intent, android.os.Bundle);
     method public void startActivityForResult(android.content.Intent, int);
@@ -13191,6 +13192,7 @@
     method public abstract void close();
     method public abstract android.hardware.camera2.CameraDevice getDevice();
     method public abstract android.view.Surface getInputSurface();
+    method public abstract boolean isConstrainedHighSpeed();
     method public abstract boolean isReprocessable();
     method public abstract void prepare(android.view.Surface) throws android.hardware.camera2.CameraAccessException;
     method public abstract int setRepeatingBurst(java.util.List<android.hardware.camera2.CaptureRequest>, android.hardware.camera2.CameraCaptureSession.CaptureCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
@@ -13311,6 +13313,8 @@
     method public abstract void close();
     method public abstract android.hardware.camera2.CaptureRequest.Builder createCaptureRequest(int) throws android.hardware.camera2.CameraAccessException;
     method public abstract void createCaptureSession(java.util.List<android.view.Surface>, android.hardware.camera2.CameraCaptureSession.StateCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
+    method public abstract void createConstrainedHighSpeedCaptureSession(java.util.List<android.view.Surface>, android.hardware.camera2.CameraCaptureSession.StateCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
+    method public abstract java.util.List<android.hardware.camera2.CaptureRequest> createConstrainedHighSpeedRequestList(android.hardware.camera2.CaptureRequest) throws android.hardware.camera2.CameraAccessException;
     method public abstract android.hardware.camera2.CaptureRequest.Builder createReprocessCaptureRequest(android.hardware.camera2.TotalCaptureResult) throws android.hardware.camera2.CameraAccessException;
     method public abstract void createReprocessableCaptureSession(android.hardware.camera2.params.InputConfiguration, java.util.List<android.view.Surface>, android.hardware.camera2.CameraCaptureSession.StateCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
     method public abstract java.lang.String getId();
@@ -13441,7 +13445,7 @@
     field public static final int CONTROL_SCENE_MODE_FACE_PRIORITY = 1; // 0x1
     field public static final int CONTROL_SCENE_MODE_FIREWORKS = 12; // 0xc
     field public static final int CONTROL_SCENE_MODE_HDR = 18; // 0x12
-    field public static final int CONTROL_SCENE_MODE_HIGH_SPEED_VIDEO = 17; // 0x11
+    field public static final deprecated int CONTROL_SCENE_MODE_HIGH_SPEED_VIDEO = 17; // 0x11
     field public static final int CONTROL_SCENE_MODE_LANDSCAPE = 4; // 0x4
     field public static final int CONTROL_SCENE_MODE_NIGHT = 5; // 0x5
     field public static final int CONTROL_SCENE_MODE_NIGHT_PORTRAIT = 6; // 0x6
@@ -13488,6 +13492,7 @@
     field public static final int NOISE_REDUCTION_MODE_OFF = 0; // 0x0
     field public static final int REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE = 0; // 0x0
     field public static final int REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE = 6; // 0x6
+    field public static final int REQUEST_AVAILABLE_CAPABILITIES_CONSTRAINED_HIGH_SPEED_VIDEO = 9; // 0x9
     field public static final int REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT = 8; // 0x8
     field public static final int REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING = 2; // 0x2
     field public static final int REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR = 1; // 0x1
@@ -32454,7 +32459,7 @@
     method public android.text.StaticLayout.Builder setLineSpacing(float, float);
     method public android.text.StaticLayout.Builder setMaxLines(int);
     method public android.text.StaticLayout.Builder setText(java.lang.CharSequence);
-    method public android.text.StaticLayout.Builder setTextDir(android.text.TextDirectionHeuristic);
+    method public android.text.StaticLayout.Builder setTextDirection(android.text.TextDirectionHeuristic);
   }
 
   public abstract interface TextDirectionHeuristic {
diff --git a/api/system-current.txt b/api/system-current.txt
index 65ca29a..32af01c 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -4480,6 +4480,7 @@
     method public void setSharedElementReturnTransition(android.transition.Transition);
     method public void setTargetFragment(android.app.Fragment, int);
     method public void setUserVisibleHint(boolean);
+    method public boolean shouldShowRequestPermissionRationale(java.lang.String);
     method public void startActivity(android.content.Intent);
     method public void startActivity(android.content.Intent, android.os.Bundle);
     method public void startActivityForResult(android.content.Intent, int);
@@ -13509,6 +13510,7 @@
     method public abstract void close();
     method public abstract android.hardware.camera2.CameraDevice getDevice();
     method public abstract android.view.Surface getInputSurface();
+    method public abstract boolean isConstrainedHighSpeed();
     method public abstract boolean isReprocessable();
     method public abstract void prepare(android.view.Surface) throws android.hardware.camera2.CameraAccessException;
     method public abstract int setRepeatingBurst(java.util.List<android.hardware.camera2.CaptureRequest>, android.hardware.camera2.CameraCaptureSession.CaptureCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
@@ -13629,6 +13631,8 @@
     method public abstract void close();
     method public abstract android.hardware.camera2.CaptureRequest.Builder createCaptureRequest(int) throws android.hardware.camera2.CameraAccessException;
     method public abstract void createCaptureSession(java.util.List<android.view.Surface>, android.hardware.camera2.CameraCaptureSession.StateCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
+    method public abstract void createConstrainedHighSpeedCaptureSession(java.util.List<android.view.Surface>, android.hardware.camera2.CameraCaptureSession.StateCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
+    method public abstract java.util.List<android.hardware.camera2.CaptureRequest> createConstrainedHighSpeedRequestList(android.hardware.camera2.CaptureRequest) throws android.hardware.camera2.CameraAccessException;
     method public abstract android.hardware.camera2.CaptureRequest.Builder createReprocessCaptureRequest(android.hardware.camera2.TotalCaptureResult) throws android.hardware.camera2.CameraAccessException;
     method public abstract void createReprocessableCaptureSession(android.hardware.camera2.params.InputConfiguration, java.util.List<android.view.Surface>, android.hardware.camera2.CameraCaptureSession.StateCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
     method public abstract java.lang.String getId();
@@ -13759,7 +13763,7 @@
     field public static final int CONTROL_SCENE_MODE_FACE_PRIORITY = 1; // 0x1
     field public static final int CONTROL_SCENE_MODE_FIREWORKS = 12; // 0xc
     field public static final int CONTROL_SCENE_MODE_HDR = 18; // 0x12
-    field public static final int CONTROL_SCENE_MODE_HIGH_SPEED_VIDEO = 17; // 0x11
+    field public static final deprecated int CONTROL_SCENE_MODE_HIGH_SPEED_VIDEO = 17; // 0x11
     field public static final int CONTROL_SCENE_MODE_LANDSCAPE = 4; // 0x4
     field public static final int CONTROL_SCENE_MODE_NIGHT = 5; // 0x5
     field public static final int CONTROL_SCENE_MODE_NIGHT_PORTRAIT = 6; // 0x6
@@ -13806,6 +13810,7 @@
     field public static final int NOISE_REDUCTION_MODE_OFF = 0; // 0x0
     field public static final int REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE = 0; // 0x0
     field public static final int REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE = 6; // 0x6
+    field public static final int REQUEST_AVAILABLE_CAPABILITIES_CONSTRAINED_HIGH_SPEED_VIDEO = 9; // 0x9
     field public static final int REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT = 8; // 0x8
     field public static final int REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING = 2; // 0x2
     field public static final int REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR = 1; // 0x1
@@ -34719,7 +34724,7 @@
     method public android.text.StaticLayout.Builder setLineSpacing(float, float);
     method public android.text.StaticLayout.Builder setMaxLines(int);
     method public android.text.StaticLayout.Builder setText(java.lang.CharSequence);
-    method public android.text.StaticLayout.Builder setTextDir(android.text.TextDirectionHeuristic);
+    method public android.text.StaticLayout.Builder setTextDirection(android.text.TextDirectionHeuristic);
   }
 
   public abstract interface TextDirectionHeuristic {
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index 40c5c64..26d4fd4 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -1223,6 +1223,33 @@
     }
 
     /**
+     * Gets whether you should show UI with rationale for requesting a permission.
+     * You should do this only if you do not have the permission and the context in
+     * which the permission is requested does not clearly communicate to the user
+     * what would be the benefit from granting this permission.
+     * <p>
+     * For example, if you write a camera app, requesting the camera permission
+     * would be expected by the user and no rationale for why it is requested is
+     * needed. If however, the app needs location for tagging photos then a non-tech
+     * savvy user may wonder how location is related to taking photos. In this case
+     * you may choose to show UI with rationale of requesting this permission.
+     * </p>
+     *
+     * @param permission A permission your app wants to request.
+     * @return Whether you can show permission rationale UI.
+     *
+     * @see Context#checkSelfPermission(String)
+     * @see #requestPermissions(String[], int)
+     * @see #onRequestPermissionsResult(int, String[], int[])
+     */
+    public boolean shouldShowRequestPermissionRationale(@NonNull String permission) {
+        if (mHost != null) {
+            mHost.getContext().getPackageManager().shouldShowRequestPermissionRationale(permission);
+        }
+        return false;
+    }
+
+    /**
      * @hide Hack so that DialogFragment can make its Dialog before creating
      * its views, and the view construction can use the dialog's context for
      * inflation.  Maybe this should become a public API. Note sure.
diff --git a/core/java/android/hardware/camera2/CameraCaptureSession.java b/core/java/android/hardware/camera2/CameraCaptureSession.java
index c22ee5f..82d40d3 100644
--- a/core/java/android/hardware/camera2/CameraCaptureSession.java
+++ b/core/java/android/hardware/camera2/CameraCaptureSession.java
@@ -471,6 +471,17 @@
     public abstract boolean isReprocessable();
 
     /**
+     * Return if this capture session is constrained high speed session that is created by
+     * {@link CameraDevice#createConstrainedHighSpeedCaptureSession}.
+     *
+     * @return {@code true} if this session is constrained high speed capture session,
+     *         {@code false} otherwise.
+     *
+     * @see CameraDevice#createConstrainedHighSpeedCaptureSession
+     */
+    public abstract boolean isConstrainedHighSpeed();
+
+    /**
      * Get the input Surface associated with a reprocessable capture session.
      *
      * <p>Each reprocessable capture session has an input {@link Surface} where the reprocess
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index d5867a9..85e8827 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -626,35 +626,54 @@
             new Key<Integer>("android.control.maxRegionsAf", int.class);
 
     /**
-     * <p>List of available high speed video size and fps range configurations
-     * supported by the camera device, in the format of (width, height, fps_min, fps_max).</p>
-     * <p>When HIGH_SPEED_VIDEO is supported in {@link CameraCharacteristics#CONTROL_AVAILABLE_SCENE_MODES android.control.availableSceneModes}, this metadata
-     * will list the supported high speed video size and fps range configurations. All the sizes
-     * listed in this configuration will be a subset of the sizes reported by {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputSizes } for processed
-     * non-stalling formats.</p>
-     * <p>For the high speed video use case, where the application will set
-     * {@link CaptureRequest#CONTROL_SCENE_MODE android.control.sceneMode} to HIGH_SPEED_VIDEO in capture requests, the application must
+     * <p>List of available high speed video size, fps range and max batch size configurations
+     * supported by the camera device, in the format of (width, height, fps_min, fps_max, batch_size_max).</p>
+     * <p>When CONSTRAINED_HIGH_SPEED_VIDEO is supported in android.control.availableCapabilities,
+     * this metadata will list the supported high speed video size, fps range and max batch size
+     * configurations. All the sizes listed in this configuration will be a subset of the sizes
+     * reported by {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputSizes }
+     * for processed non-stalling formats.</p>
+     * <p>For the high speed video use case, the application must
      * select the video size and fps range from this metadata to configure the recording and
      * preview streams and setup the recording requests. For example, if the application intends
      * to do high speed recording, it can select the maximum size reported by this metadata to
      * configure output streams. Once the size is selected, application can filter this metadata
      * by selected size and get the supported fps ranges, and use these fps ranges to setup the
      * recording requests. Note that for the use case of multiple output streams, application
-     * must select one unique size from this metadata to use. Otherwise a request error might
-     * occur.</p>
-     * <p>For normal video recording use case, where some application will NOT set
-     * {@link CaptureRequest#CONTROL_SCENE_MODE android.control.sceneMode} to HIGH_SPEED_VIDEO in capture requests, the fps ranges
-     * reported in this metadata must not be used to setup capture requests, or it will cause
-     * request error.</p>
+     * must select one unique size from this metadata to use (e.g., preview and recording streams
+     * must have the same size). Otherwise, the high speed capture session creation will fail.</p>
+     * <p>The min and max fps will be multiple times of 30fps.</p>
+     * <p>High speed video streaming extends significant performance pressue to camera hardware,
+     * to achieve efficient high speed streaming, the camera device may have to aggregate
+     * multiple frames together and send to camera device for processing where the request
+     * controls are same for all the frames in this batch. Max batch size indicates
+     * the max possible number of frames the camera device will group together for this high
+     * speed stream configuration. This max batch size will be used to generate a high speed
+     * recording request list by
+     * {@link android.hardware.camera2.CameraDevice#createConstrainedHighSpeedRequestList }.
+     * The max batch size for each configuration will satisfy below conditions:</p>
+     * <ul>
+     * <li>Each max batch size will be a divisor of its corresponding fps_max / 30. For example,
+     * if max_fps is 300, max batch size will only be 1, 2, 5, or 10.</li>
+     * <li>The camera device may choose smaller internal batch size for each configuration, but
+     * the actual batch size will be a divisor of max batch size. For example, if the max batch
+     * size is 8, the actual batch size used by camera device will only be 1, 2, 4, or 8.</li>
+     * <li>The max batch size in each configuration entry must be no larger than 32.</li>
+     * </ul>
+     * <p>The camera device doesn't have to support batch mode to achieve high speed video recording,
+     * in such case, batch_size_max will be reported as 1 in each configuration entry.</p>
+     * <p>This fps ranges in this configuration list can only be used to create requests
+     * that are submitted to a high speed camera capture session created by
+     * {@link android.hardware.camera2.CameraDevice#createConstrainedHighSpeedCaptureSession }.
+     * The fps ranges reported in this metadata must not be used to setup capture requests for
+     * normal capture session, or it will cause request error.</p>
      * <p><b>Range of valid values:</b><br></p>
-     * <p>For each configuration, the fps_max &gt;= 60fps.</p>
+     * <p>For each configuration, the fps_max &gt;= 120fps.</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
      * <p><b>Limited capability</b> -
      * Present on all camera devices that report being at least {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED HARDWARE_LEVEL_LIMITED} devices in the
      * {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL android.info.supportedHardwareLevel} key</p>
      *
-     * @see CameraCharacteristics#CONTROL_AVAILABLE_SCENE_MODES
-     * @see CaptureRequest#CONTROL_SCENE_MODE
      * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
      * @hide
      */
@@ -1308,7 +1327,8 @@
      * the max pipeline depth.</p>
      * <p>A pipeline depth of X stages is equivalent to a pipeline latency of
      * X frame intervals.</p>
-     * <p>This value will be 8 or less.</p>
+     * <p>This value will normally be 8 or less, however, for high speed capture session,
+     * the max pipeline depth will be up to 8 x size of high speed capture request list.</p>
      * <p>This key is available on all devices.</p>
      *
      * @see CaptureResult#REQUEST_PIPELINE_DEPTH
@@ -1371,6 +1391,7 @@
      *   <li>{@link #REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE BURST_CAPTURE}</li>
      *   <li>{@link #REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING YUV_REPROCESSING}</li>
      *   <li>{@link #REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT DEPTH_OUTPUT}</li>
+     *   <li>{@link #REQUEST_AVAILABLE_CAPABILITIES_CONSTRAINED_HIGH_SPEED_VIDEO CONSTRAINED_HIGH_SPEED_VIDEO}</li>
      * </ul></p>
      * <p>This key is available on all devices.</p>
      *
@@ -1384,6 +1405,7 @@
      * @see #REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE
      * @see #REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING
      * @see #REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT
+     * @see #REQUEST_AVAILABLE_CAPABILITIES_CONSTRAINED_HIGH_SPEED_VIDEO
      */
     @PublicKey
     public static final Key<int[]> REQUEST_AVAILABLE_CAPABILITIES =
diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java
index d02f349..006030c 100644
--- a/core/java/android/hardware/camera2/CameraDevice.java
+++ b/core/java/android/hardware/camera2/CameraDevice.java
@@ -583,6 +583,147 @@
             throws CameraAccessException;
 
     /**
+     * <p>Create a new constrained high speed capture session.</p>
+     *
+     * <p>The application can use normal capture session (created via {@link #createCaptureSession})
+     * for high speed capture if the desired high speed FPS ranges are advertised by
+     * {@link CameraCharacteristics#CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES}, in which case all API
+     * semantics associated with normal capture sessions applies.</p>
+     *
+     * <p>The method creates a specialized capture session that is only targeted at high speed
+     * video recording (>=120fps) use case if the camera device supports high speed video
+     * capability (i.e., {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES} contains
+     * {@link CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_CONSTRAINED_HIGH_SPEED_VIDEO}).
+     * Therefore, it has special characteristics compared with a normal capture session:</p>
+     *
+     * <ul>
+     *
+     * <li>In addition to the output target Surface requirements specified by the
+     *   {@link #createCaptureSession} method, an active high speed capture session will support up
+     *   to 2 output Surfaces, though the application might choose to configure just one Surface
+     *   (e.g., preview only). All Surfaces must be either video encoder surfaces (acquired by
+     *   {@link android.media.MediaRecorder#getSurface} or
+     *   {@link android.media.MediaCodec#createInputSurface}) or preview surfaces (obtained from
+     *   {@link android.view.SurfaceView}, {@link android.graphics.SurfaceTexture} via
+     *   {@link android.view.Surface#Surface(android.graphics.SurfaceTexture)}). The Surface sizes
+     *   must be one of the sizes reported by {@link StreamConfigurationMap#getHighSpeedVideoSizes}.
+     *   When multiple Surfaces are configured, their size must be same.</li>
+     *
+     * <li>An active high speed capture session only accepts request lists created via
+     *   {@link #createConstrainedHighSpeedRequestList}, and the request list can only be submitted
+     *   to this session via {@link CameraCaptureSession#captureBurst captureBurst}, or
+     *   {@link CameraCaptureSession#setRepeatingBurst setRepeatingBurst}.</li>
+     *
+     * <li>The FPS ranges being requested to this session must be selected from
+     *   {@link StreamConfigurationMap#getHighSpeedVideoFpsRangesFor}. The application can still use
+     *   {@link CaptureRequest#CONTROL_AE_TARGET_FPS_RANGE} to control the desired FPS range.
+     *   Switching to an FPS range that has different
+     *   {@link android.util.Range#getUpper() maximum FPS} may trigger some camera device
+     *   reconfigurations, which may introduce extra latency. It is recommended that the
+     *   application avoids unnecessary maximum target FPS changes as much as possible during high
+     *   speed streaming.</li>
+     *
+     * <li>For the request lists submitted to this session, the camera device will override the
+     *   {@link CaptureRequest#CONTROL_MODE control mode}, auto-exposure (AE), auto-white balance
+     *   (AWB) and auto-focus (AF) to {@link CameraMetadata#CONTROL_MODE_AUTO},
+     *   {@link CameraMetadata#CONTROL_AE_MODE_ON}, {@link CameraMetadata#CONTROL_AWB_MODE_AUTO}
+     *   and {@link CameraMetadata#CONTROL_AF_MODE_CONTINUOUS_VIDEO}, respectively. All
+     *   post-processing block mode controls will be overridden to be FAST. Therefore, no manual
+     *   control of capture and post-processing parameters is possible. Beside these, only a subset
+     *   of controls will work, see
+     *   {@link CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_CONSTRAINED_HIGH_SPEED_VIDEO} for
+     *   more details.</li>
+     *
+     * </ul>
+     *
+     * @param outputs The new set of Surfaces that should be made available as
+     *                targets for captured high speed image data.
+     * @param callback The callback to notify about the status of the new capture session.
+     * @param handler The handler on which the callback should be invoked, or {@code null} to use
+     *                the current thread's {@link android.os.Looper looper}.
+     *
+     * @throws IllegalArgumentException if the set of output Surfaces do not meet the requirements,
+     *                                  the callback is null, or the handler is null but the current
+     *                                  thread has no looper, or the camera device doesn't support
+     *                                  high speed video capability.
+     * @throws CameraAccessException if the camera device is no longer connected or has
+     *                               encountered a fatal error
+     * @throws IllegalStateException if the camera device has been closed
+     *
+     * @see #createCaptureSession
+     * @see CaptureRequest#CONTROL_AE_TARGET_FPS_RANGE
+     * @see StreamConfigurationMap#getHighSpeedVideoSizes
+     * @see StreamConfigurationMap#getHighSpeedVideoFpsRangesFor
+     * @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
+     * @see CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_CONSTRAINED_HIGH_SPEED_VIDEO
+     * @see CameraCaptureSession#captureBurst
+     * @see CameraCaptureSession#setRepeatingBurst
+     * @see #createConstrainedHighSpeedRequestList
+     */
+    public abstract void createConstrainedHighSpeedCaptureSession(@NonNull List<Surface> outputs,
+            @NonNull CameraCaptureSession.StateCallback callback,
+            @Nullable Handler handler)
+            throws CameraAccessException;
+
+
+    /**
+     * <p>Create a unmodifiable list of requests that is suitable for constrained high speed capture
+     * session streaming.</p>
+     *
+     * <p>High speed video streaming creates significant performance pressue on the camera device,
+     * so to achieve efficient high speed streaming, the camera device may have to aggregate
+     * multiple frames together. This means requests must be sent in batched groups, with all
+     * requests sharing the same settings. This method takes the list of output target
+     * Surfaces (subject to the output Surface requirements specified by the contrained high speed
+     * session) and a {@link CaptureRequest request}, and generates a request list that has the same
+     * controls for each request. The input {@link CaptureRequest request} must contain the target
+     * output Surfaces and target high speed FPS range that is one of the
+     * {@link StreamConfigurationMap#getHighSpeedVideoFpsRangesFor} for the Surface size.</p>
+     *
+     * <p>If both preview and recording Surfaces are specified in the {@code request}, the
+     * {@link CaptureRequest#CONTROL_AE_TARGET_FPS_RANGE target FPS range} in the input
+     * {@link CaptureRequest request} must be a fixed framerate FPS range, where the
+     * {@link android.util.Range#getLower minimal FPS} ==
+     * {@link android.util.Range#getUpper() maximum FPS}. The created request list will contain
+     * a interleaved request pattern such that the preview output FPS is at least 30fps, the
+     * recording output FPS is {@link android.util.Range#getUpper() maximum FPS} of the requested
+     * FPS range. The application can submit this request list directly to an active high speed
+     * capture session to achieve high speed video recording. When only preview or recording
+     * Surface is specified, this method will return a list of request that have the same controls
+     * and output targets for all requests.</p>
+     *
+     * <p>Submitting a request list created by this method to a normal capture session will result
+     * in an {@link IllegalArgumentException} if the high speed
+     * {@link CaptureRequest#CONTROL_AE_TARGET_FPS_RANGE FPS range} is not supported by
+     * {@link CameraCharacteristics#CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES}.</p>
+     *
+     * @param request The high speed capture request that will be used to generate the high speed
+     *                request list.
+     * @return A unmodifiable CaptureRequest list that is suitable for constrained high speed
+     *         capture.
+     *
+     * @throws IllegalArgumentException if the set of output Surfaces in the request do not meet the
+     *                                  high speed video capability requirements, or the camera
+     *                                  device doesn't support high speed video capability, or the
+     *                                  request doesn't meet the high speed video capability
+     *                                  requirements, or the request doesn't contain the required
+     *                                  controls for high speed capture.
+     * @throws CameraAccessException if the camera device is no longer connected or has
+     *                               encountered a fatal error
+     * @throws IllegalStateException if the camera device has been closed
+     *
+     * @see #createConstrainedHighSpeedCaptureSession
+     * @see CaptureRequest#CONTROL_AE_TARGET_FPS_RANGE
+     * @see StreamConfigurationMap#getHighSpeedVideoSizes
+     * @see StreamConfigurationMap#getHighSpeedVideoFpsRangesFor
+     * @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
+     * @see CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_CONSTRAINED_HIGH_SPEED_VIDEO
+     */
+    @NonNull
+    public abstract List<CaptureRequest> createConstrainedHighSpeedRequestList(
+            @NonNull CaptureRequest request)throws CameraAccessException;
+
+    /**
      * <p>Create a {@link CaptureRequest.Builder} for new capture requests,
      * initialized with template for a target use case. The settings are chosen
      * to be the best options for the specific camera device, so it is not
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index ac29f80..f8db6d9 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -648,6 +648,100 @@
      */
     public static final int REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT = 8;
 
+    /**
+     * <p>The device supports constrained high speed video recording (frame rate &gt;=120fps)
+     * use case. The camera device will support high speed capture session created by
+     * {@link android.hardware.camera2.CameraDevice#createConstrainedHighSpeedCaptureSession }, which
+     * only accepts high speed request list created by
+     * {@link android.hardware.camera2.CameraDevice#createConstrainedHighSpeedRequestList }.</p>
+     * <p>A camera device can still support high speed video streaming by advertising the high speed
+     * FPS ranges in {@link CameraCharacteristics#CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES android.control.aeAvailableTargetFpsRanges}. For this case, all normal
+     * capture request per frame control and synchronization requirements will apply to
+     * the high speed fps ranges, the same as all other fps ranges. This capability describes
+     * the capability of a specialized operating mode with many limitations (see below), which
+     * is only targeted at high speed video recording.</p>
+     * <p>The supported high speed video sizes and fps ranges are specified in
+     * {@link android.hardware.camera2.params.StreamConfigurationMap#getHighSpeedVideoFpsRanges }.
+     * To get desired output frame rates, the application is only allowed to select video size
+     * and FPS range combinations provided by
+     * {@link android.hardware.camera2.params.StreamConfigurationMap#getHighSpeedVideoSizes }.
+     * The fps range can be controlled via {@link CaptureRequest#CONTROL_AE_TARGET_FPS_RANGE android.control.aeTargetFpsRange}.</p>
+     * <p>In this capability, the camera device will override aeMode, awbMode, and afMode to
+     * ON, ON, and CONTINUOUS_VIDEO, respectively. All post-processing block mode
+     * controls will be overridden to be FAST. Therefore, no manual control of capture
+     * and post-processing parameters is possible. All other controls operate the
+     * same as when {@link CaptureRequest#CONTROL_MODE android.control.mode} == AUTO. This means that all other
+     * android.control.* fields continue to work, such as</p>
+     * <ul>
+     * <li>{@link CaptureRequest#CONTROL_AE_TARGET_FPS_RANGE android.control.aeTargetFpsRange}</li>
+     * <li>{@link CaptureRequest#CONTROL_AE_EXPOSURE_COMPENSATION android.control.aeExposureCompensation}</li>
+     * <li>{@link CaptureRequest#CONTROL_AE_LOCK android.control.aeLock}</li>
+     * <li>{@link CaptureRequest#CONTROL_AWB_LOCK android.control.awbLock}</li>
+     * <li>{@link CaptureRequest#CONTROL_EFFECT_MODE android.control.effectMode}</li>
+     * <li>{@link CaptureRequest#CONTROL_AE_REGIONS android.control.aeRegions}</li>
+     * <li>{@link CaptureRequest#CONTROL_AF_REGIONS android.control.afRegions}</li>
+     * <li>{@link CaptureRequest#CONTROL_AWB_REGIONS android.control.awbRegions}</li>
+     * <li>{@link CaptureRequest#CONTROL_AF_TRIGGER android.control.afTrigger}</li>
+     * <li>{@link CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER android.control.aePrecaptureTrigger}</li>
+     * </ul>
+     * <p>Outside of android.control.*, the following controls will work:</p>
+     * <ul>
+     * <li>{@link CaptureRequest#FLASH_MODE android.flash.mode} (TORCH mode only, automatic flash for still capture will not
+     * work since aeMode is ON)</li>
+     * <li>{@link CaptureRequest#LENS_OPTICAL_STABILIZATION_MODE android.lens.opticalStabilizationMode} (if it is supported)</li>
+     * <li>{@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion}</li>
+     * <li>{@link CaptureRequest#STATISTICS_FACE_DETECT_MODE android.statistics.faceDetectMode} (if it is supported)</li>
+     * </ul>
+     * <p>For high speed recording use case, the actual maximum supported frame rate may
+     * be lower than what camera can output, depending on the destination Surfaces for
+     * the image data. For example, if the destination surface is from video encoder,
+     * the application need check if the video encoder is capable of supporting the
+     * high frame rate for a given video size, or it will end up with lower recording
+     * frame rate. If the destination surface is from preview window, the actual preview frame
+     * rate will be bounded by the screen refresh rate.</p>
+     * <p>The camera device will only support up to 2 high speed simultaneous output surfaces
+     * (preview and recording surfaces)
+     * in this mode. Above controls will be effective only if all of below conditions are true:</p>
+     * <ul>
+     * <li>The application creates a camera capture session with no more than 2 surfaces via
+     * {@link android.hardware.camera2.CameraDevice#createConstrainedHighSpeedCaptureSession }. The
+     * targeted surfaces must be preview surface (either from
+     * {@link android.view.SurfaceView } or {@link android.graphics.SurfaceTexture }) or
+     * recording surface(either from {@link android.media.MediaRecorder#getSurface } or
+     * {@link android.media.MediaCodec#createInputSurface }).</li>
+     * <li>The stream sizes are selected from the sizes reported by
+     * {@link android.hardware.camera2.params.StreamConfigurationMap#getHighSpeedVideoSizes }.</li>
+     * <li>The FPS ranges are selected from
+     * {@link android.hardware.camera2.params.StreamConfigurationMap#getHighSpeedVideoFpsRanges }.</li>
+     * </ul>
+     * <p>When above conditions are NOT satistied, the
+     * {@link android.hardware.camera2.CameraDevice#createConstrainedHighSpeedCaptureSession }
+     * and {@link android.hardware.camera2.CameraDevice#createConstrainedHighSpeedRequestList } will fail.</p>
+     * <p>Switching to a FPS range that has different maximum FPS may trigger some camera device
+     * reconfigurations, which may introduce extra latency. It is recommended that
+     * the application avoids unnecessary maximum target FPS changes as much as possible
+     * during high speed streaming.</p>
+     *
+     * @see CameraCharacteristics#CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES
+     * @see CaptureRequest#CONTROL_AE_EXPOSURE_COMPENSATION
+     * @see CaptureRequest#CONTROL_AE_LOCK
+     * @see CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER
+     * @see CaptureRequest#CONTROL_AE_REGIONS
+     * @see CaptureRequest#CONTROL_AE_TARGET_FPS_RANGE
+     * @see CaptureRequest#CONTROL_AF_REGIONS
+     * @see CaptureRequest#CONTROL_AF_TRIGGER
+     * @see CaptureRequest#CONTROL_AWB_LOCK
+     * @see CaptureRequest#CONTROL_AWB_REGIONS
+     * @see CaptureRequest#CONTROL_EFFECT_MODE
+     * @see CaptureRequest#CONTROL_MODE
+     * @see CaptureRequest#FLASH_MODE
+     * @see CaptureRequest#LENS_OPTICAL_STABILIZATION_MODE
+     * @see CaptureRequest#SCALER_CROP_REGION
+     * @see CaptureRequest#STATISTICS_FACE_DETECT_MODE
+     * @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
+     */
+    public static final int REQUEST_AVAILABLE_CAPABILITIES_CONSTRAINED_HIGH_SPEED_VIDEO = 9;
+
     //
     // Enumeration values for CameraCharacteristics#SCALER_CROPPING_TYPE
     //
@@ -1725,6 +1819,10 @@
     public static final int CONTROL_SCENE_MODE_BARCODE = 16;
 
     /**
+     * <p>This is deprecated, please use
+     * {@link android.hardware.camera2.CameraDevice#createConstrainedHighSpeedCaptureSession }
+     * and {@link android.hardware.camera2.CameraDevice#createConstrainedHighSpeedRequestList }
+     * for high speed video recording.</p>
      * <p>Optimized for high speed video recording (frame rate &gt;=60fps) use case.</p>
      * <p>The supported high speed video sizes and fps ranges are specified in
      * android.control.availableHighSpeedVideoConfigurations. To get desired
@@ -1799,6 +1897,7 @@
      * @see CaptureRequest#SCALER_CROP_REGION
      * @see CaptureRequest#STATISTICS_FACE_DETECT_MODE
      * @see CaptureRequest#CONTROL_SCENE_MODE
+     * @deprecated Please refer to this API documentation to find the alternatives
      */
     public static final int CONTROL_SCENE_MODE_HIGH_SPEED_VIDEO = 17;
 
diff --git a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
index 7a39dd5..ab0f607 100644
--- a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
@@ -721,4 +721,10 @@
         }
     }
 
+    @Override
+    public boolean isConstrainedHighSpeed() {
+        // TODO: to be implemented
+        return false;
+    }
+
 }
diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
index e60e266..16701e5 100644
--- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
@@ -1906,4 +1906,18 @@
     private CameraCharacteristics getCharacteristics() {
         return mCharacteristics;
     }
+
+    @Override
+    public void createConstrainedHighSpeedCaptureSession(List<Surface> outputs,
+            android.hardware.camera2.CameraCaptureSession.StateCallback callback, Handler handler)
+            throws CameraAccessException {
+        // TODO: to be implemented
+        throw new UnsupportedOperationException("To be implemented!!!!");
+    }
+
+    @Override
+    public List<CaptureRequest> createConstrainedHighSpeedRequestList(CaptureRequest request)
+            throws CameraAccessException {
+        throw new UnsupportedOperationException("To be implemented!!!!");
+    }
 }
diff --git a/core/java/android/hardware/camera2/marshal/impl/MarshalQueryableHighSpeedVideoConfiguration.java b/core/java/android/hardware/camera2/marshal/impl/MarshalQueryableHighSpeedVideoConfiguration.java
index c03144b..2449abe 100644
--- a/core/java/android/hardware/camera2/marshal/impl/MarshalQueryableHighSpeedVideoConfiguration.java
+++ b/core/java/android/hardware/camera2/marshal/impl/MarshalQueryableHighSpeedVideoConfiguration.java
@@ -33,7 +33,7 @@
  */
 public class MarshalQueryableHighSpeedVideoConfiguration
         implements MarshalQueryable<HighSpeedVideoConfiguration> {
-    private static final int SIZE = SIZEOF_INT32 * 4;
+    private static final int SIZE = SIZEOF_INT32 * 5;
 
     private class MarshalerHighSpeedVideoConfiguration
             extends Marshaler<HighSpeedVideoConfiguration> {
@@ -49,6 +49,7 @@
             buffer.putInt(value.getHeight());
             buffer.putInt(value.getFpsMin());
             buffer.putInt(value.getFpsMax());
+            buffer.putInt(value.getBatchSizeMax());
         }
 
         @Override
@@ -57,8 +58,9 @@
             int height = buffer.getInt();
             int fpsMin = buffer.getInt();
             int fpsMax = buffer.getInt();
+            int batchSizeMax = buffer.getInt();
 
-            return new HighSpeedVideoConfiguration(width, height, fpsMin, fpsMax);
+            return new HighSpeedVideoConfiguration(width, height, fpsMin, fpsMax, batchSizeMax);
         }
 
         @Override
diff --git a/core/java/android/hardware/camera2/params/HighSpeedVideoConfiguration.java b/core/java/android/hardware/camera2/params/HighSpeedVideoConfiguration.java
index 088049f..b469126 100644
--- a/core/java/android/hardware/camera2/params/HighSpeedVideoConfiguration.java
+++ b/core/java/android/hardware/camera2/params/HighSpeedVideoConfiguration.java
@@ -33,6 +33,7 @@
  * @hide
  */
 public final class HighSpeedVideoConfiguration {
+    static final private int HIGH_SPEED_MAX_MINIMAL_FPS = 120;
 
     /**
      * Create a new {@link HighSpeedVideoConfiguration}.
@@ -48,15 +49,18 @@
      * @hide
      */
     public HighSpeedVideoConfiguration(
-            final int width, final int height, final int fpsMin, final int fpsMax) {
-        if (fpsMax < 60) {
-            throw new IllegalArgumentException("fpsMax must be at least 60");
+            final int width, final int height, final int fpsMin, final int fpsMax,
+            final int batchSizeMax) {
+        if (fpsMax < HIGH_SPEED_MAX_MINIMAL_FPS) {
+            throw new IllegalArgumentException("fpsMax must be at least " +
+                    HIGH_SPEED_MAX_MINIMAL_FPS);
         }
         mFpsMax = fpsMax;
         mWidth = checkArgumentPositive(width, "width must be positive");
         mHeight = checkArgumentPositive(height, "height must be positive");
         mFpsMin = checkArgumentPositive(fpsMin, "fpsMin must be positive");
         mSize = new Size(mWidth, mHeight);
+        mBatchSizeMax = checkArgumentPositive(batchSizeMax, "batchSizeMax must be positive");
         mFpsRange = new Range<Integer>(mFpsMin, mFpsMax);
     }
 
@@ -106,9 +110,18 @@
     }
 
     /**
+     * Convenience method to return the max batch size of this high speed video configuration.
+     *
+     * @return the maximal batch size for this high speed video configuration
+     */
+    public int getBatchSizeMax() {
+        return mBatchSizeMax;
+    }
+
+    /**
      * Convenience method to return the FPS range of this high speed video configuration.
      *
-     * @return a Range with high bound >= 60
+     * @return a Range with high bound >= {@value #HIGH_SPEED_MAX_MINIMAL_FPS}
      */
     public Range<Integer> getFpsRange() {
         return mFpsRange;
@@ -135,7 +148,8 @@
             return mWidth == other.mWidth &&
                     mHeight == other.mHeight &&
                     mFpsMin == other.mFpsMin &&
-                    mFpsMax == other.mFpsMax;
+                    mFpsMax == other.mFpsMax &&
+                    mBatchSizeMax == other.mBatchSizeMax;
         }
         return false;
     }
@@ -152,6 +166,7 @@
     private final int mHeight;
     private final int mFpsMin;
     private final int mFpsMax;
+    private final int mBatchSizeMax;
     private final Size mSize;
     private final Range<Integer> mFpsRange;
 }
diff --git a/core/java/android/text/DynamicLayout.java b/core/java/android/text/DynamicLayout.java
index e99a960..5b5cdd2 100644
--- a/core/java/android/text/DynamicLayout.java
+++ b/core/java/android/text/DynamicLayout.java
@@ -291,7 +291,7 @@
         b.setText(text, where, where + after)
                 .setPaint(getPaint())
                 .setWidth(getWidth())
-                .setTextDir(getTextDirectionHeuristic())
+                .setTextDirection(getTextDirectionHeuristic())
                 .setLineSpacing(getSpacingAdd(), getSpacingMultiplier())
                 .setEllipsizedWidth(mEllipsizedWidth)
                 .setEllipsize(mEllipsizeAt)
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index d6d046b..464710b 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -184,7 +184,7 @@
          * @param textDir text direction heuristic for resolving BiDi behavior.
          * @return this builder, useful for chaining
          */
-        public Builder setTextDir(TextDirectionHeuristic textDir) {
+        public Builder setTextDirection(TextDirectionHeuristic textDir) {
             mTextDir = textDir;
             return this;
         }
@@ -473,7 +473,7 @@
 
         Builder b = Builder.obtain(source, bufstart, bufend, paint, outerwidth)
             .setAlignment(align)
-            .setTextDir(textDir)
+            .setTextDirection(textDir)
             .setLineSpacing(spacingadd, spacingmult)
             .setIncludePad(includepad)
             .setEllipsizedWidth(ellipsizedWidth)
diff --git a/core/java/android/view/AccessibilityInteractionController.java b/core/java/android/view/AccessibilityInteractionController.java
index 6e2d110..664c02a 100644
--- a/core/java/android/view/AccessibilityInteractionController.java
+++ b/core/java/android/view/AccessibilityInteractionController.java
@@ -19,6 +19,7 @@
 import android.graphics.Point;
 import android.graphics.Rect;
 import android.graphics.Region;
+import android.os.Binder;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
@@ -158,7 +159,9 @@
             try {
                 mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0;
                 applyAppScaleAndMagnificationSpecIfNeeded(infos, spec);
-                if (spec != null) {
+                // Recycle if called from another process. Specs are cached in the
+                // system process and obtained from a pool when read from parcel.
+                if (spec != null && android.os.Process.myPid() != Binder.getCallingPid()) {
                     spec.recycle();
                 }
                 adjustIsVisibleToUserIfNeeded(infos, interactiveRegion);
@@ -167,6 +170,12 @@
             } catch (RemoteException re) {
                 /* ignore - the other side will time out */
             }
+
+            // Recycle if called from the same process. Regions are obtained in
+            // the system process and instantiated  when read from parcel.
+            if (interactiveRegion != null && android.os.Process.myPid() == Binder.getCallingPid()) {
+                interactiveRegion.recycle();
+            }
         }
     }
 
@@ -244,7 +253,9 @@
             try {
                 mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0;
                 applyAppScaleAndMagnificationSpecIfNeeded(infos, spec);
-                if (spec != null) {
+                // Recycle if called from another process. Specs are cached in the
+                // system process and obtained from a pool when read from parcel.
+                if (spec != null && android.os.Process.myPid() != Binder.getCallingPid()) {
                     spec.recycle();
                 }
                 adjustIsVisibleToUserIfNeeded(infos, interactiveRegion);
@@ -252,6 +263,12 @@
             } catch (RemoteException re) {
                 /* ignore - the other side will time out */
             }
+
+            // Recycle if called from the same process. Regions are obtained in
+            // the system process and instantiated  when read from parcel.
+            if (interactiveRegion != null && android.os.Process.myPid() == Binder.getCallingPid()) {
+                interactiveRegion.recycle();
+            }
         }
     }
 
@@ -354,7 +371,9 @@
             try {
                 mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0;
                 applyAppScaleAndMagnificationSpecIfNeeded(infos, spec);
-                if (spec != null) {
+                // Recycle if called from another process. Specs are cached in the
+                // system process and obtained from a pool when read from parcel.
+                if (spec != null && android.os.Process.myPid() != Binder.getCallingPid()) {
                     spec.recycle();
                 }
                 adjustIsVisibleToUserIfNeeded(infos, interactiveRegion);
@@ -362,6 +381,12 @@
             } catch (RemoteException re) {
                 /* ignore - the other side will time out */
             }
+
+            // Recycle if called from the same process. Regions are obtained in
+            // the system process and instantiated  when read from parcel.
+            if (interactiveRegion != null && android.os.Process.myPid() == Binder.getCallingPid()) {
+                interactiveRegion.recycle();
+            }
         }
     }
 
@@ -468,7 +493,9 @@
             try {
                 mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0;
                 applyAppScaleAndMagnificationSpecIfNeeded(focused, spec);
-                if (spec != null) {
+                // Recycle if called from another process. Specs are cached in the
+                // system process and obtained from a pool when read from parcel.
+                if (spec != null && android.os.Process.myPid() != Binder.getCallingPid()) {
                     spec.recycle();
                 }
                 adjustIsVisibleToUserIfNeeded(focused, interactiveRegion);
@@ -476,6 +503,12 @@
             } catch (RemoteException re) {
                 /* ignore - the other side will time out */
             }
+
+            // Recycle if called from the same process. Regions are obtained in
+            // the system process and instantiated  when read from parcel.
+            if (interactiveRegion != null && android.os.Process.myPid() == Binder.getCallingPid()) {
+                interactiveRegion.recycle();
+            }
         }
     }
 
@@ -545,7 +578,9 @@
             try {
                 mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0;
                 applyAppScaleAndMagnificationSpecIfNeeded(next, spec);
-                if (spec != null) {
+                // Recycle if called from another process. Specs are cached in the
+                // system process and obtained from a pool when read from parcel.
+                if (spec != null && android.os.Process.myPid() != Binder.getCallingPid()) {
                     spec.recycle();
                 }
                 adjustIsVisibleToUserIfNeeded(next, interactiveRegion);
@@ -553,6 +588,12 @@
             } catch (RemoteException re) {
                 /* ignore - the other side will time out */
             }
+
+            // Recycle if called from the same process. Regions are obtained in
+            // the system process and instantiated  when read from parcel.
+            if (interactiveRegion != null && android.os.Process.myPid() == Binder.getCallingPid()) {
+                interactiveRegion.recycle();
+            }
         }
     }
 
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 774307f..126540f 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -17115,6 +17115,7 @@
      * Also calls {@link StateListAnimator#jumpToCurrentState()} if there is a StateListAnimator
      * attached to this view.
      */
+    @CallSuper
     public void jumpDrawablesToCurrentState() {
         if (mBackground != null) {
             mBackground.jumpToCurrentState();
@@ -17564,13 +17565,16 @@
      * @see Drawable#setTintMode(PorterDuff.Mode)
      */
     public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) {
-        if (mBackgroundTint == null) {
-            mBackgroundTint = new TintInfo();
+        if (mForegroundInfo == null) {
+            mForegroundInfo = new ForegroundInfo();
         }
-        mBackgroundTint.mTintMode = tintMode;
-        mBackgroundTint.mHasTintMode = true;
+        if (mForegroundInfo.mTintInfo == null) {
+            mForegroundInfo.mTintInfo = new TintInfo();
+        }
+        mForegroundInfo.mTintInfo.mTintMode = tintMode;
+        mForegroundInfo.mTintInfo.mHasTintMode = true;
 
-        applyBackgroundTint();
+        applyForegroundTint();
     }
 
     /**
@@ -17580,7 +17584,7 @@
      * @return the blending mode used to apply the tint to the foreground
      *         drawable
      * @attr ref android.R.styleable#View_foregroundTintMode
-     * @see #setBackgroundTintMode(PorterDuff.Mode)
+     * @see #setForegroundTintMode(PorterDuff.Mode)
      */
     @Nullable
     public PorterDuff.Mode getForegroundTintMode() {
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index f7b6405..ca5f5ad 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -1058,6 +1058,13 @@
     public boolean isKeyguardSecure();
 
     /**
+     * Return whether the keyguard is on.
+     *
+     * @return true if in keyguard is on.
+     */
+    public boolean isKeyguardShowingOrOccluded();
+
+    /**
      * inKeyguardRestrictedKeyInputMode
      *
      * if keyguard screen is showing or in restricted key input mode (i.e. in
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index a0d1930..7f85f5a 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -5309,6 +5309,13 @@
     }
 
     @Override
+    void syncSelectedItem() {
+        if (mDataChanged) {
+            layoutChildren();
+        }
+    }
+
+    @Override
     protected void handleDataChanged() {
         int count = mItemCount;
         int lastHandledItemCount = mLastHandledItemCount;
diff --git a/core/java/android/widget/AdapterView.java b/core/java/android/widget/AdapterView.java
index 6962711..cfe02bd 100644
--- a/core/java/android/widget/AdapterView.java
+++ b/core/java/android/widget/AdapterView.java
@@ -551,37 +551,67 @@
     }
 
     /**
-     * Return the position of the currently selected item within the adapter's data set
+     * Returns the position of the currently selected item within the adapter's
+     * data set, or {@link #INVALID_POSITION} if there is nothing selected.
+     * <p>
+     * <strong>Note:</strong> Prior to {@link android.os.Build.VERSION_CODES#MNC},
+     * calling this method between an adapter data set change and a subsequent
+     * layout pass could return invalid data.
      *
-     * @return int Position (starting at 0), or {@link #INVALID_POSITION} if there is nothing selected.
+     * @return the selected item's position (starting at 0), or
+     *         {@link #INVALID_POSITION} if there is nothing selected
      */
     @ViewDebug.CapturedViewProperty
     public int getSelectedItemPosition() {
+        syncSelectedItem();
         return mNextSelectedPosition;
     }
 
     /**
-     * @return The id corresponding to the currently selected item, or {@link #INVALID_ROW_ID}
-     * if nothing is selected.
+     * Returns the row ID corresponding to the currently selected item, or
+     * {@link #INVALID_ROW_ID} if nothing is selected.
+     * <p>
+     * <strong>Note:</strong> Prior to {@link android.os.Build.VERSION_CODES#MNC},
+     * calling this method between an adapter data set change and a subsequent
+     * layout pass could return invalid data.
+     *
+     * @return the selected item's row ID, or {@link #INVALID_ROW_ID} if
+     *         nothing is selected
      */
     @ViewDebug.CapturedViewProperty
     public long getSelectedItemId() {
+        syncSelectedItem();
         return mNextSelectedRowId;
     }
 
     /**
-     * @return The view corresponding to the currently selected item, or null
-     * if nothing is selected
+     * Returns the view corresponding to the currently selected item, or
+     * {@code null} if nothing is selected.
+     * <p>
+     * <strong>Note:</strong> Prior to {@link android.os.Build.VERSION_CODES#MNC},
+     * calling this method between an adapter data set change and a subsequent
+     * layout pass could return inconsistent data.
+     *
+     * @return the selected item's view, or {@code null} if nothing is selected
      */
+    @Nullable
     public abstract View getSelectedView();
 
     /**
-     * @return The data corresponding to the currently selected item, or
-     * null if there is nothing selected.
+     * Returns the data corresponding to the currently selected item, or
+     * {@code null} if nothing is selected.
+     * <p>
+     * <strong>Note:</strong> Prior to {@link android.os.Build.VERSION_CODES#MNC},
+     * calling this method between an adapter data set change and a subsequent
+     * layout pass could return inconsistent data.
+     *
+     * @return the data corresponding to the currently selected item, or
+     *         {@code null} if there is nothing selected.
      */
+    @Nullable
     public Object getSelectedItem() {
-        T adapter = getAdapter();
-        int selection = getSelectedItemPosition();
+        final T adapter = getAdapter();
+        final int selection = getSelectedItemPosition();
         if (adapter != null && adapter.getCount() > 0 && selection >= 0) {
             return adapter.getItem(selection);
         } else {
@@ -590,6 +620,15 @@
     }
 
     /**
+     * Synchronizes the selected item's position and ID, if necessary.
+     */
+    void syncSelectedItem() {
+        if (mDataChanged) {
+            onLayout(false, mLeft, mTop, mRight, mBottom);
+        }
+    }
+
+    /**
      * @return The number of items owned by the Adapter associated with this
      *         AdapterView. (This is the number of data items, which may be
      *         larger than the number of visible views.)
diff --git a/core/java/android/widget/ArrayAdapter.java b/core/java/android/widget/ArrayAdapter.java
index 260854f..027f6d6 100644
--- a/core/java/android/widget/ArrayAdapter.java
+++ b/core/java/android/widget/ArrayAdapter.java
@@ -52,12 +52,6 @@
  */
 public class ArrayAdapter<T> extends BaseAdapter implements Filterable, ThemedSpinnerAdapter {
     /**
-     * Contains the list of objects that represent the data of this ArrayAdapter.
-     * The content of this list is referred to as "the array" in the documentation.
-     */
-    private List<T> mObjects;
-
-    /**
      * Lock used to modify the content of {@link #mObjects}. Any write operation
      * performed on the array should be synchronized on this lock. This lock is also
      * used by the filter (see {@link #getFilter()} to make a synchronized copy of
@@ -65,6 +59,14 @@
      */
     private final Object mLock = new Object();
 
+    private final LayoutInflater mInflater;
+
+    /**
+     * Contains the list of objects that represent the data of this ArrayAdapter.
+     * The content of this list is referred to as "the array" in the documentation.
+     */
+    private List<T> mObjects;
+
     /**
      * The resource indicating what views to inflate to display the content of this
      * array adapter.
@@ -97,8 +99,6 @@
     private ArrayList<T> mOriginalValues;
     private ArrayFilter mFilter;
 
-    private LayoutInflater mInflater;
-
     /** Layout inflater used for {@link #getDropDownView(int, View, ViewGroup)}. */
     private LayoutInflater mDropDownInflater;
 
@@ -442,9 +442,6 @@
         return mDropDownInflater == null ? null : mDropDownInflater.getContext().getTheme();
     }
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
     public View getDropDownView(int position, View convertView, ViewGroup parent) {
         final LayoutInflater inflater = mDropDownInflater == null ? mInflater : mDropDownInflater;
diff --git a/core/java/android/widget/DatePickerCalendarDelegate.java b/core/java/android/widget/DatePickerCalendarDelegate.java
index d38a225..7e542c9 100755
--- a/core/java/android/widget/DatePickerCalendarDelegate.java
+++ b/core/java/android/widget/DatePickerCalendarDelegate.java
@@ -115,7 +115,8 @@
                 R.styleable.DatePicker_internalLayout, R.layout.date_picker_material);
 
         // Set up and attach container.
-        mContainer = (ViewGroup) inflater.inflate(layoutResourceId, mDelegator);
+        mContainer = (ViewGroup) inflater.inflate(layoutResourceId, mDelegator, false);
+        mDelegator.addView(mContainer);
 
         // Set up header views.
         final ViewGroup header = (ViewGroup) mContainer.findViewById(R.id.date_picker_header);
@@ -471,7 +472,11 @@
 
     @Override
     public void setEnabled(boolean enabled) {
-        mContainer.setEnabled(false);
+        mContainer.setEnabled(enabled);
+        mDayPickerView.setEnabled(enabled);
+        mYearPickerView.setEnabled(enabled);
+        mHeaderYear.setEnabled(enabled);
+        mHeaderMonthDay.setEnabled(enabled);
     }
 
     @Override
@@ -481,8 +486,7 @@
 
     @Override
     public CalendarView getCalendarView() {
-        throw new UnsupportedOperationException(
-                "CalendarView does not exists for the new DatePicker");
+        throw new UnsupportedOperationException("Not supported by calendar-mode DatePicker");
     }
 
     @Override
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 0cac529..56f9b5c 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -1004,14 +1004,14 @@
                 stopSelectionActionMode();
             } else {
                 stopSelectionActionMode();
-                startSelectionActionModeWithSelectionAndStartDrag();
+                selectCurrentWordAndStartDrag();
             }
             handled = true;
         }
 
         // Start a new selection
         if (!handled) {
-            handled = startSelectionActionModeWithSelectionAndStartDrag();
+            handled = selectCurrentWordAndStartDrag();
         }
 
         return handled;
@@ -1724,22 +1724,9 @@
     }
 
     /**
-     * Starts a Selection Action Mode with the current selection and enters drag mode. This should
-     * be used whenever the mode is started from a touch event.
-     *
-     * @return true if the selection mode was actually started.
-     */
-    private boolean startSelectionActionModeWithSelectionAndStartDrag() {
-        boolean selectionStarted = startSelectionActionModeWithSelectionInternal();
-        if (selectionStarted) {
-            getSelectionController().enterDrag();
-        }
-        return selectionStarted;
-    }
-
-    /**
      * Starts a Selection Action Mode with the current selection and ensures the selection handles
-     * are shown. This should be used when the mode is started from a non-touch event.
+     * are shown if there is a selection, otherwise the insertion handle is shown. This should be
+     * used when the mode is started from a non-touch event.
      *
      * @return true if the selection mode was actually started.
      */
@@ -1747,40 +1734,67 @@
         boolean selectionStarted = startSelectionActionModeWithSelectionInternal();
         if (selectionStarted) {
             getSelectionController().show();
+        } else if (getInsertionController() != null) {
+            getInsertionController().show();
         }
         return selectionStarted;
     }
 
-    private boolean startSelectionActionModeWithSelectionInternal() {
+    /**
+     * If the TextView allows text selection, selects the current word when no existing selection
+     * was available and starts a drag.
+     *
+     * @return true if the drag was started.
+     */
+    private boolean selectCurrentWordAndStartDrag() {
         if (extractedTextModeWillBeStarted()) {
             // Cancel the single tap delayed runnable.
             if (mSelectionModeWithoutSelectionRunnable != null) {
                 mTextView.removeCallbacks(mSelectionModeWithoutSelectionRunnable);
             }
+            return false;
+        }
+        if (mSelectionActionMode != null) {
+            mSelectionActionMode.finish();
+        }
+        if (!checkFieldAndSelectCurrentWord()) {
+            return false;
+        }
+        getSelectionController().enterDrag();
+        return true;
+    }
 
+    /**
+     * Checks whether a selection can be performed on the current TextView and if so selects
+     * the current word.
+     *
+     * @return true if there already was a selection or if the current word was selected.
+     */
+    private boolean checkFieldAndSelectCurrentWord() {
+        if (!mTextView.canSelectText() || !mTextView.requestFocus()) {
+            Log.w(TextView.LOG_TAG,
+                    "TextView does not support text selection. Selection cancelled.");
             return false;
         }
 
+        if (!mTextView.hasSelection()) {
+            // There may already be a selection on device rotation
+            return selectCurrentWord();
+        }
+        return true;
+    }
+
+    private boolean startSelectionActionModeWithSelectionInternal() {
         if (mSelectionActionMode != null) {
             // Selection action mode is already started
             mSelectionActionMode.invalidate();
             return false;
         }
 
-        if (!mTextView.canSelectText() || !mTextView.requestFocus()) {
-            Log.w(TextView.LOG_TAG,
-                    "TextView does not support text selection. Action mode cancelled.");
+        if (!checkFieldAndSelectCurrentWord()) {
             return false;
         }
 
-        if (!mTextView.hasSelection()) {
-            // There may already be a selection on device rotation
-            if (!selectCurrentWord()) {
-                // No word found under cursor or text selection not permitted.
-                return false;
-            }
-        }
-
         boolean willExtract = extractedTextModeWillBeStarted();
 
         // Do not start the action mode when extracted text will show up full screen, which would
@@ -1829,12 +1843,18 @@
         }
         if (selectionStart == selectionEnd) {
             // Spans overlap the cursor.
-            return true;
+            for (int i = 0; i < suggestionSpans.length; i++) {
+                if (suggestionSpans[i].getSuggestions().length > 0) {
+                    return true;
+                }
+            }
+            return false;
         }
         int minSpanStart = mTextView.getText().length();
         int maxSpanEnd = 0;
         int unionOfSpansCoveringSelectionStartStart = mTextView.getText().length();
         int unionOfSpansCoveringSelectionStartEnd = 0;
+        boolean hasValidSuggestions = false;
         for (int i = 0; i < suggestionSpans.length; i++) {
             final int spanStart = spannable.getSpanStart(suggestionSpans[i]);
             final int spanEnd = spannable.getSpanEnd(suggestionSpans[i]);
@@ -1844,11 +1864,16 @@
                 // The span doesn't cover the current selection start point.
                 continue;
             }
+            hasValidSuggestions =
+                    hasValidSuggestions || suggestionSpans[i].getSuggestions().length > 0;
             unionOfSpansCoveringSelectionStartStart =
                     Math.min(unionOfSpansCoveringSelectionStartStart, spanStart);
             unionOfSpansCoveringSelectionStartEnd =
                     Math.max(unionOfSpansCoveringSelectionStartEnd, spanEnd);
         }
+        if (!hasValidSuggestions) {
+            return false;
+        }
         if (unionOfSpansCoveringSelectionStartStart >= unionOfSpansCoveringSelectionStartEnd) {
             // No spans cover the selection start point.
             return false;
@@ -4071,12 +4096,17 @@
                     offset = getNextCursorOffset(selectionEnd, false);
                     mTouchWordDelta = 0.0f;
                 }
-                mInWord = !getWordIteratorWithText().isBoundary(offset);
                 positionAtCursorOffset(offset, false);
             }
         }
 
         @Override
+        protected void positionAtCursorOffset(int offset, boolean parentScrolled) {
+            super.positionAtCursorOffset(offset, parentScrolled);
+            mInWord = !getWordIteratorWithText().isBoundary(offset);
+        }
+
+        @Override
         public boolean onTouchEvent(MotionEvent event) {
             boolean superResult = super.onTouchEvent(event);
             if (event.getActionMasked() == MotionEvent.ACTION_UP) {
@@ -4193,12 +4223,17 @@
                     offset = getNextCursorOffset(selectionStart, true);
                     mTouchWordDelta = 0.0f;
                 }
-                mInWord = !getWordIteratorWithText().isBoundary(offset);
                 positionAtCursorOffset(offset, false);
             }
         }
 
         @Override
+        protected void positionAtCursorOffset(int offset, boolean parentScrolled) {
+            super.positionAtCursorOffset(offset, parentScrolled);
+            mInWord = !getWordIteratorWithText().isBoundary(offset);
+        }
+
+        @Override
         public boolean onTouchEvent(MotionEvent event) {
             boolean superResult = super.onTouchEvent(event);
             if (event.getActionMasked() == MotionEvent.ACTION_UP) {
@@ -4377,7 +4412,7 @@
                             boolean stayedInArea = distanceSquared < doubleTapSlop * doubleTapSlop;
 
                             if (stayedInArea && isPositionOnText(eventX, eventY)) {
-                                startSelectionActionModeWithSelectionAndStartDrag();
+                                selectCurrentWordAndStartDrag();
                                 mDiscardNextActionUp = true;
                             }
                         }
@@ -4480,6 +4515,7 @@
                         mEndHandle.showAtLocation(endOffset);
 
                         // No longer the first dragging motion, reset.
+                        startSelectionActionModeWithSelection();
                         mDragAcceleratorActive = false;
                         mStartOffset = -1;
                     }
diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java
index 16dc26d..e7d9226 100644
--- a/core/java/android/widget/NumberPicker.java
+++ b/core/java/android/widget/NumberPicker.java
@@ -16,6 +16,7 @@
 
 package android.widget;
 
+import android.annotation.CallSuper;
 import android.annotation.IntDef;
 import android.annotation.Widget;
 import android.content.Context;
@@ -608,7 +609,16 @@
 
         mSolidColor = attributesArray.getColor(R.styleable.NumberPicker_solidColor, 0);
 
-        mSelectionDivider = attributesArray.getDrawable(R.styleable.NumberPicker_selectionDivider);
+        final Drawable selectionDivider = attributesArray.getDrawable(
+                R.styleable.NumberPicker_selectionDivider);
+        if (selectionDivider != null) {
+            selectionDivider.setCallback(this);
+            selectionDivider.setLayoutDirection(getLayoutDirection());
+            if (selectionDivider.isStateful()) {
+                selectionDivider.setState(getDrawableState());
+            }
+        }
+        mSelectionDivider = selectionDivider;
 
         final int defSelectionDividerHeight = (int) TypedValue.applyDimension(
                 TypedValue.COMPLEX_UNIT_DIP, UNSCALED_DEFAULT_SELECTION_DIVIDER_HEIGHT,
@@ -1499,6 +1509,38 @@
         removeAllCallbacks();
     }
 
+    @CallSuper
+    @Override
+    protected void drawableStateChanged() {
+        super.drawableStateChanged();
+
+        final int[] state = getDrawableState();
+
+        if (mSelectionDivider != null && mSelectionDivider.isStateful()) {
+            mSelectionDivider.setState(state);
+        }
+    }
+
+    @CallSuper
+    @Override
+    public void jumpDrawablesToCurrentState() {
+        super.jumpDrawablesToCurrentState();
+
+        if (mSelectionDivider != null) {
+            mSelectionDivider.jumpToCurrentState();
+        }
+    }
+
+    /** @hide */
+    @Override
+    public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) {
+        super.onResolveDrawables(layoutDirection);
+
+        if (mSelectionDivider != null) {
+            mSelectionDivider.setLayoutDirection(layoutDirection);
+        }
+    }
+
     @Override
     protected void onDraw(Canvas canvas) {
         if (!mHasSelectorWheel) {
diff --git a/core/java/android/widget/SimpleAdapter.java b/core/java/android/widget/SimpleAdapter.java
index e7760ee..3bf9485 100644
--- a/core/java/android/widget/SimpleAdapter.java
+++ b/core/java/android/widget/SimpleAdapter.java
@@ -52,6 +52,8 @@
  * If no appropriate binding can be found, an {@link IllegalStateException} is thrown.
  */
 public class SimpleAdapter extends BaseAdapter implements Filterable, ThemedSpinnerAdapter {
+    private final LayoutInflater mInflater;
+
     private int[] mTo;
     private String[] mFrom;
     private ViewBinder mViewBinder;
@@ -60,7 +62,6 @@
 
     private int mResource;
     private int mDropDownResource;
-    private LayoutInflater mInflater;
 
     /** Layout inflater used for {@link #getDropDownView(int, View, ViewGroup)}. */
     private LayoutInflater mDropDownInflater;
@@ -174,8 +175,8 @@
 
     @Override
     public View getDropDownView(int position, View convertView, ViewGroup parent) {
-        return createViewFromResource(
-                mDropDownInflater, position, convertView, parent, mDropDownResource);
+        final LayoutInflater inflater = mDropDownInflater == null ? mInflater : mDropDownInflater;
+        return createViewFromResource(inflater, position, convertView, parent, mDropDownResource);
     }
 
     private void bindView(int position, View view) {
diff --git a/core/java/android/widget/TabHost.java b/core/java/android/widget/TabHost.java
index c521f72..27fa3b9 100644
--- a/core/java/android/widget/TabHost.java
+++ b/core/java/android/widget/TabHost.java
@@ -188,32 +188,9 @@
         mLocalActivityManager = activityGroup;
     }
 
-
     @Override
-    protected void onAttachedToWindow() {
-        super.onAttachedToWindow();
-        final ViewTreeObserver treeObserver = getViewTreeObserver();
-        treeObserver.addOnTouchModeChangeListener(this);
-    }
-
-    @Override
-    protected void onDetachedFromWindow() {
-        super.onDetachedFromWindow();
-        final ViewTreeObserver treeObserver = getViewTreeObserver();
-        treeObserver.removeOnTouchModeChangeListener(this);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
     public void onTouchModeChanged(boolean isInTouchMode) {
-        if (!isInTouchMode) {
-            // leaving touch mode.. if nothing has focus, let's give it to
-            // the indicator of the current tab
-            if (mCurrentView != null && (!mCurrentView.hasFocus() || mCurrentView.isFocused())) {
-                mTabWidget.getChildTabViewAt(mCurrentTab).requestFocus();
-            }
-        }
+        // No longer used, but kept to maintain API compatibility.
     }
 
     /**
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index e14e39c..3a85476 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -6680,7 +6680,7 @@
                 StaticLayout.Builder builder = StaticLayout.Builder.obtain(mHint, 0,
                         mHint.length(), mTextPaint, hintWidth)
                         .setAlignment(alignment)
-                        .setTextDir(mTextDir)
+                        .setTextDirection(mTextDir)
                         .setLineSpacing(mSpacingAdd, mSpacingMult)
                         .setIncludePad(mIncludePad)
                         .setBreakStrategy(mBreakStrategy)
@@ -6771,7 +6771,7 @@
             StaticLayout.Builder builder = StaticLayout.Builder.obtain(mTransformed,
                     0, mTransformed.length(), mTextPaint, wantWidth)
                     .setAlignment(alignment)
-                    .setTextDir(mTextDir)
+                    .setTextDirection(mTextDir)
                     .setLineSpacing(mSpacingAdd, mSpacingMult)
                     .setIncludePad(mIncludePad)
                     .setBreakStrategy(mBreakStrategy)
diff --git a/core/java/com/android/internal/widget/FloatingToolbar.java b/core/java/com/android/internal/widget/FloatingToolbar.java
index e02d706..c32ba85 100644
--- a/core/java/com/android/internal/widget/FloatingToolbar.java
+++ b/core/java/com/android/internal/widget/FloatingToolbar.java
@@ -37,6 +37,7 @@
 import android.view.ViewGroup;
 import android.view.ViewTreeObserver;
 import android.view.Window;
+import android.view.WindowInsets;
 import android.view.WindowManager;
 import android.view.animation.Animation;
 import android.view.animation.AnimationSet;
@@ -323,6 +324,7 @@
             }
         };
 
+        private final Rect mViewPort = new Rect();
         private final Point mCoords = new Point();
 
         private final Region mTouchableRegion = new Region();
@@ -394,7 +396,7 @@
                 mMainPanel = new FloatingToolbarMainPanel(mParent.getContext(), mOpenOverflow);
             }
             List<MenuItem> overflowMenuItems =
-                    mMainPanel.layoutMenuItems(menuItems, suggestedWidth);
+                    mMainPanel.layoutMenuItems(menuItems, getToolbarWidth(suggestedWidth));
             mMainPanel.setOnMenuItemClickListener(menuItemClickListener);
             if (!overflowMenuItems.isEmpty()) {
                 if (mOverflowPanel == null) {
@@ -430,7 +432,8 @@
                 // The "show" animation will make this visible.
                 mContentContainer.setAlpha(0);
             }
-            updateOverflowHeight(contentRect.top - (mMarginVertical * 2));
+            refreshViewPort();
+            updateOverflowHeight(contentRect.top - (mMarginVertical * 2) - mViewPort.top);
             refreshCoordinatesAndOverflowDirection(contentRect);
             preparePopupContent();
             mPopupWindow.showAtLocation(mParent, Gravity.NO_GRAVITY, mCoords.x, mCoords.y);
@@ -494,6 +497,7 @@
             }
 
             cancelOverflowAnimations();
+            refreshViewPort();
             refreshCoordinatesAndOverflowDirection(contentRect);
             preparePopupContent();
             mPopupWindow.update(mCoords.x, mCoords.y, getWidth(), getHeight());
@@ -521,18 +525,24 @@
         }
 
         private void refreshCoordinatesAndOverflowDirection(Rect contentRect) {
+            // NOTE: Ensure that mViewPort has been refreshed before this.
+
             int x = contentRect.centerX() - getWidth() / 2;
             int y;
-            if (contentRect.top > getHeight()) {
+            if (contentRect.top - getHeight() > mViewPort.top) {
                 y = contentRect.top - getHeight();
                 mOverflowDirection = FloatingToolbarPopup.OVERFLOW_DIRECTION_UP;
-            } else if (contentRect.top > getToolbarHeightWithVerticalMargin()) {
+            } else if (contentRect.top - getToolbarHeightWithVerticalMargin() > mViewPort.top) {
                 y = contentRect.top - getToolbarHeightWithVerticalMargin();
                 mOverflowDirection = FloatingToolbarPopup.OVERFLOW_DIRECTION_DOWN;
             } else {
                 y = contentRect.bottom;
                 mOverflowDirection = FloatingToolbarPopup.OVERFLOW_DIRECTION_DOWN;
             }
+
+            // Update x so that the toolbar isn't rendered behind the nav bar in landscape.
+            x = Math.max(0, Math.min(x, mViewPort.right - getWidth()));
+
             mCoords.set(x, y);
             if (mOverflowPanel != null) {
                 mOverflowPanel.setOverflowDirection(mOverflowDirection);
@@ -821,6 +831,29 @@
             mPopupWindow.setHeight(height + mMarginVertical * 2);
         }
 
+
+        private void refreshViewPort() {
+            mParent.getGlobalVisibleRect(mViewPort);
+            WindowInsets windowInsets = mParent.getRootWindowInsets();
+            mViewPort.set(
+                    mViewPort.left + windowInsets.getStableInsetLeft(),
+                    mViewPort.top + windowInsets.getStableInsetTop(),
+                    mViewPort.right - windowInsets.getStableInsetRight(),
+                    mViewPort.bottom - windowInsets.getStableInsetBottom());
+        }
+
+        private int getToolbarWidth(int suggestedWidth) {
+            int width = suggestedWidth;
+            refreshViewPort();
+            int maximumWidth = mViewPort.width() - 2 * mParent.getResources()
+                    .getDimensionPixelSize(R.dimen.floating_toolbar_horizontal_margin);
+            if (width <= 0) {
+                width = mParent.getResources()
+                        .getDimensionPixelSize(R.dimen.floating_toolbar_preferred_width);
+            }
+            return Math.min(width, maximumWidth);
+        }
+
         /**
          * Sets the touchable region of this popup to be zero. This means that all touch events on
          * this popup will go through to the surface behind it.
@@ -906,12 +939,11 @@
          *
          * @return The menu items that are not included in this main panel.
          */
-        public List<MenuItem> layoutMenuItems(List<MenuItem> menuItems, int suggestedWidth) {
+        public List<MenuItem> layoutMenuItems(List<MenuItem> menuItems, int width) {
             Preconditions.checkNotNull(menuItems);
 
-            final int toolbarWidth = getAdjustedToolbarWidth(mContext, suggestedWidth)
-                    // Reserve space for the "open overflow" button.
-                    - getEstimatedOpenOverflowButtonWidth(mContext);
+            // Reserve space for the "open overflow" button.
+            final int toolbarWidth = width - getEstimatedOpenOverflowButtonWidth(mContext);
 
             int availableWidth = toolbarWidth;
             final LinkedList<MenuItem> remainingMenuItems = new LinkedList<MenuItem>(menuItems);
diff --git a/core/jni/android_os_Trace.cpp b/core/jni/android_os_Trace.cpp
index 52fd111..3fd3b3c 100644
--- a/core/jni/android_os_Trace.cpp
+++ b/core/jni/android_os_Trace.cpp
@@ -111,19 +111,19 @@
             "()J",
             (void*)android_os_Trace_nativeGetEnabledTags },
     { "nativeTraceCounter",
-            "(JLjava/lang/String;I)V",
+            "!(JLjava/lang/String;I)V",
             (void*)android_os_Trace_nativeTraceCounter },
     { "nativeTraceBegin",
-            "(JLjava/lang/String;)V",
+            "!(JLjava/lang/String;)V",
             (void*)android_os_Trace_nativeTraceBegin },
     { "nativeTraceEnd",
-            "(J)V",
+            "!(J)V",
             (void*)android_os_Trace_nativeTraceEnd },
     { "nativeAsyncTraceBegin",
-            "(JLjava/lang/String;I)V",
+            "!(JLjava/lang/String;I)V",
             (void*)android_os_Trace_nativeAsyncTraceBegin },
     { "nativeAsyncTraceEnd",
-            "(JLjava/lang/String;I)V",
+            "!(JLjava/lang/String;I)V",
             (void*)android_os_Trace_nativeAsyncTraceEnd },
     { "nativeSetAppTracingAllowed",
             "(Z)V",
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index 3fa92a8..abd2409 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -499,7 +499,7 @@
     nsecs_t vsync = systemTime(CLOCK_MONOTONIC);
     UiFrameInfoBuilder(proxy->frameInfo())
             .setVsync(vsync, vsync)
-            .addFlag(FrameInfoFlags::kSurfaceCanvas);
+            .addFlag(FrameInfoFlags::SurfaceCanvas);
     proxy->syncAndDrawFrame();
 }
 
diff --git a/core/res/res/drawable/number_picker_divider_material.xml b/core/res/res/drawable/number_picker_divider_material.xml
new file mode 100644
index 0000000..2474be0
--- /dev/null
+++ b/core/res/res/drawable/number_picker_divider_material.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+       android:tint="?attr/colorControlNormal"
+       android:shape="rectangle">
+    <solid android:color="@color/black" />
+</shape>
diff --git a/core/res/res/layout/number_picker_material.xml b/core/res/res/layout/number_picker_material.xml
new file mode 100644
index 0000000..47edec4
--- /dev/null
+++ b/core/res/res/layout/number_picker_material.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<view xmlns:android="http://schemas.android.com/apk/res/android"
+      class="android.widget.NumberPicker$CustomEditText"
+      android:id="@+id/numberpicker_input"
+      android:layout_width="fill_parent"
+      android:layout_height="wrap_content"
+      android:gravity="center"
+      android:singleLine="true"
+      android:background="@null"
+      android:textAppearance="@style/TextAppearance.Material.Caption" />
diff --git a/core/res/res/values/styles_material.xml b/core/res/res/values/styles_material.xml
index f7a42fa..7782ed7 100644
--- a/core/res/res/values/styles_material.xml
+++ b/core/res/res/values/styles_material.xml
@@ -630,13 +630,13 @@
     </style>
 
     <style name="Widget.Material.NumberPicker" parent="Widget.NumberPicker">
-        <item name="internalLayout">@layout/number_picker_with_selector_wheel</item>
+        <item name="internalLayout">@layout/number_picker_material</item>
         <item name="solidColor">@color/transparent</item>
-        <item name="selectionDivider">@drawable/numberpicker_selection_divider</item>
-        <item name="selectionDividerHeight">2dip</item>
-        <item name="selectionDividersDistance">48dip</item>
-        <item name="internalMinWidth">64dip</item>
-        <item name="internalMaxHeight">180dip</item>
+        <item name="selectionDivider">@drawable/number_picker_divider_material</item>
+        <item name="selectionDividerHeight">2dp</item>
+        <item name="selectionDividersDistance">48dp</item>
+        <item name="internalMinWidth">64dp</item>
+        <item name="internalMaxHeight">180dp</item>
         <item name="virtualButtonPressedDrawable">?attr/selectableItemBackground</item>
     </style>
 
diff --git a/graphics/java/android/graphics/ImageFormat.java b/graphics/java/android/graphics/ImageFormat.java
index d6f8cca..7aa0aef 100644
--- a/graphics/java/android/graphics/ImageFormat.java
+++ b/graphics/java/android/graphics/ImageFormat.java
@@ -587,10 +587,29 @@
     public static final int RAW12 = 0x26;
 
     /**
-     * Android dense depth image format.
+     * <p>Android dense depth image format.</p>
      *
-     * Each pixel is 16 bits, representing a depth ranging measurement from
-     * a depth camera or similar sensor.
+     * <p>Each pixel is 16 bits, representing a depth ranging measurement from a depth camera or
+     * similar sensor. The 16-bit sample consists of a confidence value and the actual ranging
+     * measurement.</p>
+     *
+     * <p>The confidence value is an estimate of correctness for this sample.  It is encoded in the
+     * 3 most significant bits of the sample, with a value of 0 representing 100% confidence, a
+     * value of 1 representing 0% confidence, a value of 2 representing 1/7, a value of 3
+     * representing 2/7, and so on.</p>
+     *
+     * <p>As an example, the following sample extracts the range and confidence from the first pixel
+     * of a DEPTH16-format {@link android.media.Image}, and converts the confidence to a
+     * floating-point value between 0 and 1.f inclusive, with 1.f representing maximum confidence:
+     *
+     * <pre>
+     *    ShortBuffer shortDepthBuffer = img.getPlanes()[0].getBuffer().asShortBuffer();
+     *    short depthSample = shortDepthBuffer.get()
+     *    short depthRange = (short) (depthSample & 0x1FFF);
+     *    short depthConfidence = (short) ((depthSample >> 13) & 0x7);
+     *    float depthPercentage = depthConfidence == 0 ? 1.f : (depthConfidence - 1) / 7.f;
+     * </pre>
+     * </p>
      *
      * <p>This format assumes
      * <ul>
@@ -602,19 +621,32 @@
      *
      * <pre> y_size = stride * height </pre>
      *
-     * When produced by a camera, the units are millimeters.
+     * When produced by a camera, the units for the range are millimeters.
      */
     public static final int DEPTH16 = 0x44363159;
 
     /**
      * Android sparse depth point cloud format.
      *
-     * <p>A variable-length list of 3D points, with each point represented
-     * by a triple of floats.</p>
+     * <p>A variable-length list of 3D points plus a confidence value, with each point represented
+     * by four floats; first the X, Y, Z position coordinates, and then the confidence value.</p>
      *
-     * <p>The number of points is {@code (size of the buffer in bytes) / 12}.
+     * <p>The number of points is {@code (size of the buffer in bytes) / 16}.
      *
-     * The coordinate system and units depend on the source of the point cloud data.
+     * <p>The coordinate system and units of the position values depend on the source of the point
+     * cloud data. The confidence value is between 0.f and 1.f, inclusive, with 0 representing 0%
+     * confidence and 1.f representing 100% confidence in the measured position values.</p>
+     *
+     * <p>As an example, the following code extracts the first depth point in a DEPTH_POINT_CLOUD
+     * format {@link android.media.Image}:
+     * <pre>
+     *    FloatBuffer floatDepthBuffer = img.getPlanes()[0].getBuffer().asFloatBuffer();
+     *    float x = floatDepthBuffer.get();
+     *    float y = floatDepthBuffer.get();
+     *    float z = floatDepthBuffer.get();
+     *    float confidence = floatDepthBuffer.get();
+     * </pre>
+     *
      */
     public static final int DEPTH_POINT_CLOUD = 0x101;
 
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreBCWorkaroundProvider.java b/keystore/java/android/security/keystore/AndroidKeyStoreBCWorkaroundProvider.java
index 03be759..aa2b946 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreBCWorkaroundProvider.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreBCWorkaroundProvider.java
@@ -43,13 +43,17 @@
     private static final String PACKAGE_NAME = "android.security.keystore";
     private static final String KEYSTORE_SECRET_KEY_CLASS_NAME =
             PACKAGE_NAME + ".AndroidKeyStoreSecretKey";
+    private static final String KEYSTORE_PRIVATE_KEY_CLASS_NAME =
+            PACKAGE_NAME + ".AndroidKeyStorePrivateKey";
+    private static final String KEYSTORE_PUBLIC_KEY_CLASS_NAME =
+            PACKAGE_NAME + ".AndroidKeyStorePublicKey";
 
     AndroidKeyStoreBCWorkaroundProvider() {
         super("AndroidKeyStoreBCWorkaround",
                 1.0,
                 "Android KeyStore security provider to work around Bouncy Castle");
 
-        // javax.crypto.Mac
+        // --------------------- javax.crypto.Mac
         putMacImpl("HmacSHA1", PACKAGE_NAME + ".AndroidKeyStoreHmacSpi$HmacSHA1");
         put("Alg.Alias.Mac.1.2.840.113549.2.7", "HmacSHA1");
         put("Alg.Alias.Mac.HMAC-SHA1", "HmacSHA1");
@@ -75,7 +79,7 @@
         put("Alg.Alias.Mac.HMAC-SHA512", "HmacSHA512");
         put("Alg.Alias.Mac.HMAC/SHA512", "HmacSHA512");
 
-        // javax.crypto.Cipher
+        // --------------------- javax.crypto.Cipher
         putSymmetricCipherImpl("AES/ECB/NoPadding",
                 PACKAGE_NAME + ".AndroidKeyStoreUnauthenticatedAESCipherSpi$ECB$NoPadding");
         putSymmetricCipherImpl("AES/ECB/PKCS7Padding",
@@ -88,6 +92,36 @@
 
         putSymmetricCipherImpl("AES/CTR/NoPadding",
                 PACKAGE_NAME + ".AndroidKeyStoreUnauthenticatedAESCipherSpi$CTR$NoPadding");
+
+        putAsymmetricCipherImpl("RSA/ECB/NoPadding",
+                PACKAGE_NAME + ".AndroidKeyStoreRSACipherSpi$NoPadding");
+        put("Alg.Alias.Cipher.RSA/None/NoPadding", "RSA/ECB/NoPadding");
+        putAsymmetricCipherImpl("RSA/ECB/PKCS1Padding",
+                PACKAGE_NAME + ".AndroidKeyStoreRSACipherSpi$PKCS1Padding");
+        put("Alg.Alias.Cipher.RSA/None/PKCS1Padding", "RSA/ECB/PKCS1Padding");
+        putAsymmetricCipherImpl("RSA/ECB/OAEPPadding",
+                PACKAGE_NAME + ".AndroidKeyStoreRSACipherSpi$OAEPWithSHA1AndMGF1Padding");
+        put("Alg.Alias.Cipher.RSA/None/OAEPPadding", "RSA/ECB/OAEPPadding");
+        putAsymmetricCipherImpl("RSA/ECB/OAEPWithSHA-1AndMGF1Padding",
+                PACKAGE_NAME + ".AndroidKeyStoreRSACipherSpi$OAEPWithSHA1AndMGF1Padding");
+        put("Alg.Alias.Cipher.RSA/None/OAEPWithSHA-1AndMGF1Padding",
+                "RSA/ECB/OAEPWithSHA-1AndMGF1Padding");
+        putAsymmetricCipherImpl("RSA/ECB/OAEPWithSHA-224AndMGF1Padding",
+                PACKAGE_NAME + ".AndroidKeyStoreRSACipherSpi$OAEPWithSHA224AndMGF1Padding");
+        put("Alg.Alias.Cipher.RSA/None/OAEPWithSHA-224AndMGF1Padding",
+                "RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
+        putAsymmetricCipherImpl("RSA/ECB/OAEPWithSHA-256AndMGF1Padding",
+                PACKAGE_NAME + ".AndroidKeyStoreRSACipherSpi$OAEPWithSHA256AndMGF1Padding");
+        put("Alg.Alias.Cipher.RSA/None/OAEPWithSHA-256AndMGF1Padding",
+                "RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
+        putAsymmetricCipherImpl("RSA/ECB/OAEPWithSHA-384AndMGF1Padding",
+                PACKAGE_NAME + ".AndroidKeyStoreRSACipherSpi$OAEPWithSHA384AndMGF1Padding");
+        put("Alg.Alias.Cipher.RSA/None/OAEPWithSHA-384AndMGF1Padding",
+                "RSA/ECB/OAEPWithSHA-384AndMGF1Padding");
+        putAsymmetricCipherImpl("RSA/ECB/OAEPWithSHA-512AndMGF1Padding",
+                PACKAGE_NAME + ".AndroidKeyStoreRSACipherSpi$OAEPWithSHA512AndMGF1Padding");
+        put("Alg.Alias.Cipher.RSA/None/OAEPWithSHA-512AndMGF1Padding",
+                "RSA/ECB/OAEPWithSHA-512AndMGF1Padding");
     }
 
     private void putMacImpl(String algorithm, String implClass) {
@@ -99,4 +133,10 @@
         put("Cipher." + transformation, implClass);
         put("Cipher." + transformation + " SupportedKeyClasses", KEYSTORE_SECRET_KEY_CLASS_NAME);
     }
+
+    private void putAsymmetricCipherImpl(String transformation, String implClass) {
+        put("Cipher." + transformation, implClass);
+        put("Cipher." + transformation + " SupportedKeyClasses",
+                KEYSTORE_PRIVATE_KEY_CLASS_NAME + "|" + KEYSTORE_PUBLIC_KEY_CLASS_NAME);
+    }
 }
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreCipherSpiBase.java b/keystore/java/android/security/keystore/AndroidKeyStoreCipherSpiBase.java
index 3ad3c9d..fd9bdb8 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreCipherSpiBase.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreCipherSpiBase.java
@@ -66,7 +66,7 @@
      */
     private IBinder mOperationToken;
     private long mOperationHandle;
-    private KeyStoreCryptoOperationChunkedStreamer mMainDataStreamer;
+    private KeyStoreCryptoOperationStreamer mMainDataStreamer;
 
     /**
      * Encountered exception which could not be immediately thrown because it was encountered inside
@@ -210,7 +210,6 @@
         byte[] additionalEntropy = KeyStoreCryptoOperationUtils.getRandomBytesToMixIntoKeystoreRng(
                 mRng, getAdditionalEntropyAmountForBegin());
 
-        KeymasterArguments keymasterOutputArgs = new KeymasterArguments();
         OperationResult opResult = mKeyStore.begin(
                 mKey.getAlias(),
                 mEncrypting ? KeymasterDefs.KM_PURPOSE_ENCRYPT : KeymasterDefs.KM_PURPOSE_DECRYPT,
@@ -247,9 +246,21 @@
         }
 
         loadAlgorithmSpecificParametersFromBeginResult(opResult.outParams);
-        mMainDataStreamer = new KeyStoreCryptoOperationChunkedStreamer(
+        mMainDataStreamer = createMainDataStreamer(mKeyStore, opResult.token);
+    }
+
+    /**
+     * Creates a streamer which sends plaintext/ciphertext into the provided KeyStore and receives
+     * the corresponding ciphertext/plaintext from the KeyStore.
+     *
+     * <p>This implementation returns a working streamer.
+     */
+    @NonNull
+    protected KeyStoreCryptoOperationStreamer createMainDataStreamer(
+            KeyStore keyStore, IBinder operationToken) {
+        return new KeyStoreCryptoOperationChunkedStreamer(
                 new KeyStoreCryptoOperationChunkedStreamer.MainDataStream(
-                        mKeyStore, opResult.token));
+                        keyStore, operationToken));
     }
 
     @Override
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreKey.java b/keystore/java/android/security/keystore/AndroidKeyStoreKey.java
index 6098e5c..1751aa5 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreKey.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreKey.java
@@ -19,7 +19,7 @@
 import java.security.Key;
 
 /**
- * {@link Key} backed by AndroidKeyStore.
+ * {@link Key} backed by Android Keystore.
  *
  * @hide
  */
diff --git a/keystore/java/android/security/keystore/AndroidKeyStorePrivateKey.java b/keystore/java/android/security/keystore/AndroidKeyStorePrivateKey.java
new file mode 100644
index 0000000..b586ad4
--- /dev/null
+++ b/keystore/java/android/security/keystore/AndroidKeyStorePrivateKey.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.keystore;
+
+import java.security.PrivateKey;
+
+/**
+ * {@link PrivateKey} backed by Android Keystore.
+ *
+ * @hide
+ */
+public class AndroidKeyStorePrivateKey extends AndroidKeyStoreKey implements PrivateKey {
+
+    public AndroidKeyStorePrivateKey(String alias, String algorithm) {
+        super(alias, algorithm);
+    }
+}
diff --git a/keystore/java/android/security/keystore/AndroidKeyStorePublicKey.java b/keystore/java/android/security/keystore/AndroidKeyStorePublicKey.java
new file mode 100644
index 0000000..8133d46
--- /dev/null
+++ b/keystore/java/android/security/keystore/AndroidKeyStorePublicKey.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.keystore;
+
+import java.security.PublicKey;
+
+/**
+ * {@link PublicKey} backed by Android Keystore.
+ *
+ * @hide
+ */
+public class AndroidKeyStorePublicKey extends AndroidKeyStoreKey implements PublicKey {
+
+    private final byte[] mEncoded;
+
+    public AndroidKeyStorePublicKey(String alias, String algorithm, byte[] x509EncodedForm) {
+        super(alias, algorithm);
+        mEncoded = ArrayUtils.cloneIfNotEmpty(x509EncodedForm);
+    }
+
+    @Override
+    public String getFormat() {
+        return "X.509";
+    }
+
+    @Override
+    public byte[] getEncoded() {
+        return ArrayUtils.cloneIfNotEmpty(mEncoded);
+    }
+}
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreRSACipherSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreRSACipherSpi.java
new file mode 100644
index 0000000..f70c323
--- /dev/null
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreRSACipherSpi.java
@@ -0,0 +1,487 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.keystore;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.IBinder;
+import android.security.KeyStore;
+import android.security.KeyStoreException;
+import android.security.keymaster.KeyCharacteristics;
+import android.security.keymaster.KeymasterArguments;
+import android.security.keymaster.KeymasterDefs;
+
+import libcore.util.EmptyArray;
+
+import java.io.ByteArrayOutputStream;
+import java.security.AlgorithmParameters;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.Key;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.ProviderException;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.InvalidParameterSpecException;
+import java.security.spec.MGF1ParameterSpec;
+
+import javax.crypto.Cipher;
+import javax.crypto.CipherSpi;
+import javax.crypto.spec.OAEPParameterSpec;
+import javax.crypto.spec.PSource;
+
+/**
+ * Base class for {@link CipherSpi} providing Android KeyStore backed RSA encryption/decryption.
+ *
+ * @hide
+ */
+abstract class AndroidKeyStoreRSACipherSpi extends AndroidKeyStoreCipherSpiBase {
+
+    /**
+     * Raw RSA cipher without any padding.
+     */
+    public static final class NoPadding extends AndroidKeyStoreRSACipherSpi {
+        public NoPadding() {
+            super(KeymasterDefs.KM_PAD_NONE);
+        }
+
+        @Override
+        protected void initAlgorithmSpecificParameters() throws InvalidKeyException {}
+
+        @Override
+        protected void initAlgorithmSpecificParameters(@Nullable AlgorithmParameterSpec params)
+                throws InvalidAlgorithmParameterException {
+            if (params != null) {
+                throw new InvalidAlgorithmParameterException(
+                        "Unexpected parameters: " + params + ". No parameters supported");
+            }
+        }
+
+        @Override
+        protected void initAlgorithmSpecificParameters(@Nullable AlgorithmParameters params)
+                throws InvalidAlgorithmParameterException {
+
+            if (params != null) {
+                throw new InvalidAlgorithmParameterException(
+                        "Unexpected parameters: " + params + ". No parameters supported");
+            }
+        }
+
+        @Override
+        protected AlgorithmParameters engineGetParameters() {
+            return null;
+        }
+
+        @Override
+        protected final int getAdditionalEntropyAmountForBegin() {
+            return 0;
+        }
+
+        @Override
+        @NonNull
+        protected KeyStoreCryptoOperationStreamer createMainDataStreamer(
+                KeyStore keyStore, IBinder operationToken) {
+            if (isEncrypting()) {
+                // KeyStore's RSA encryption without padding expects the input to be of the same
+                // length as the modulus. We thus have to buffer all input to pad it with leading
+                // zeros.
+                return new ZeroPaddingEncryptionStreamer(
+                        super.createMainDataStreamer(keyStore, operationToken),
+                        getModulusSizeBytes());
+            } else {
+                return super.createMainDataStreamer(keyStore, operationToken);
+            }
+        }
+
+        /**
+         * Streamer which buffers all plaintext input, then pads it with leading zeros to match
+         * modulus size, and then sends it into KeyStore to obtain ciphertext.
+         */
+        private static class ZeroPaddingEncryptionStreamer
+                implements KeyStoreCryptoOperationStreamer {
+
+            private final KeyStoreCryptoOperationStreamer mDelegate;
+            private final int mModulusSizeBytes;
+            private final ByteArrayOutputStream mInputBuffer = new ByteArrayOutputStream();
+
+            private ZeroPaddingEncryptionStreamer(
+                    KeyStoreCryptoOperationStreamer delegate,
+                    int modulusSizeBytes) {
+                mDelegate = delegate;
+                mModulusSizeBytes = modulusSizeBytes;
+            }
+
+            @Override
+            public byte[] update(byte[] input, int inputOffset, int inputLength)
+                    throws KeyStoreException {
+                if (inputLength > 0) {
+                    mInputBuffer.write(input, inputOffset, inputLength);
+                }
+                return EmptyArray.BYTE;
+            }
+
+            @Override
+            public byte[] doFinal(byte[] input, int inputOffset, int inputLength)
+                    throws KeyStoreException {
+                if (inputLength > 0) {
+                    mInputBuffer.write(input, inputOffset, inputLength);
+                }
+                byte[] bufferedInput = mInputBuffer.toByteArray();
+                mInputBuffer.reset();
+                byte[] paddedInput;
+                if (bufferedInput.length < mModulusSizeBytes) {
+                    // Pad input with leading zeros
+                    paddedInput = new byte[mModulusSizeBytes];
+                    System.arraycopy(
+                            bufferedInput, 0,
+                            paddedInput,
+                            paddedInput.length - bufferedInput.length,
+                            bufferedInput.length);
+                } else {
+                    // No need to pad input
+                    paddedInput = bufferedInput;
+                }
+                return mDelegate.doFinal(paddedInput, 0, paddedInput.length);
+            }
+        }
+    }
+
+    /**
+     * RSA cipher with PKCS#1 v1.5 encryption padding.
+     */
+    public static final class PKCS1Padding extends AndroidKeyStoreRSACipherSpi {
+        public PKCS1Padding() {
+            super(KeymasterDefs.KM_PAD_RSA_PKCS1_1_5_ENCRYPT);
+        }
+
+        @Override
+        protected void initAlgorithmSpecificParameters() throws InvalidKeyException {}
+
+        @Override
+        protected void initAlgorithmSpecificParameters(@Nullable AlgorithmParameterSpec params)
+                throws InvalidAlgorithmParameterException {
+            if (params != null) {
+                throw new InvalidAlgorithmParameterException(
+                        "Unexpected parameters: " + params + ". No parameters supported");
+            }
+        }
+
+        @Override
+        protected void initAlgorithmSpecificParameters(@Nullable AlgorithmParameters params)
+                throws InvalidAlgorithmParameterException {
+
+            if (params != null) {
+                throw new InvalidAlgorithmParameterException(
+                        "Unexpected parameters: " + params + ". No parameters supported");
+            }
+        }
+
+        @Override
+        protected AlgorithmParameters engineGetParameters() {
+            return null;
+        }
+
+        @Override
+        protected final int getAdditionalEntropyAmountForBegin() {
+            return (isEncrypting()) ? getModulusSizeBytes() : 0;
+        }
+    }
+
+    /**
+     * RSA cipher with OAEP encryption padding. Only SHA-1 based MGF1 is supported as MGF.
+     */
+    abstract static class OAEPWithMGF1Padding extends AndroidKeyStoreRSACipherSpi {
+
+        private static final String MGF_ALGORITGM_MGF1 = "MGF1";
+
+        private int mKeymasterDigest = -1;
+        private int mDigestOutputSizeBytes;
+
+        OAEPWithMGF1Padding(int keymasterDigest) {
+            super(KeymasterDefs.KM_PAD_RSA_OAEP);
+            mKeymasterDigest = keymasterDigest;
+            mDigestOutputSizeBytes =
+                    (KeymasterUtils.getDigestOutputSizeBits(keymasterDigest) + 7) / 8;
+        }
+
+        @Override
+        protected final void initAlgorithmSpecificParameters() throws InvalidKeyException {}
+
+        @Override
+        protected final void initAlgorithmSpecificParameters(
+                @Nullable AlgorithmParameterSpec params) throws InvalidAlgorithmParameterException {
+            if (params == null) {
+                return;
+            }
+
+            if (!(params instanceof OAEPParameterSpec)) {
+                throw new InvalidAlgorithmParameterException(
+                        "Unsupported parameter spec: " + params
+                        + ". Only OAEPParameterSpec supported");
+            }
+            OAEPParameterSpec spec = (OAEPParameterSpec) params;
+            if (!MGF_ALGORITGM_MGF1.equalsIgnoreCase(spec.getMGFAlgorithm())) {
+                throw new InvalidAlgorithmParameterException(
+                        "Unsupported MGF: " + spec.getMGFAlgorithm()
+                        + ". Only " + MGF_ALGORITGM_MGF1 + " supported");
+            }
+            String jcaDigest = spec.getDigestAlgorithm();
+            int keymasterDigest;
+            try {
+                keymasterDigest = KeyProperties.Digest.toKeymaster(jcaDigest);
+            } catch (IllegalArgumentException e) {
+                throw new InvalidAlgorithmParameterException(
+                        "Unsupported digest: " + jcaDigest, e);
+            }
+            switch (keymasterDigest) {
+                case KeymasterDefs.KM_DIGEST_SHA1:
+                case KeymasterDefs.KM_DIGEST_SHA_2_224:
+                case KeymasterDefs.KM_DIGEST_SHA_2_256:
+                case KeymasterDefs.KM_DIGEST_SHA_2_384:
+                case KeymasterDefs.KM_DIGEST_SHA_2_512:
+                    // Permitted.
+                    break;
+                default:
+                    throw new InvalidAlgorithmParameterException(
+                            "Unsupported digest: " + jcaDigest);
+            }
+            AlgorithmParameterSpec mgfParams = spec.getMGFParameters();
+            if (mgfParams == null) {
+                throw new InvalidAlgorithmParameterException("MGF parameters must be provided");
+            }
+            // Check whether MGF parameters match the OAEPParameterSpec
+            if (!(mgfParams instanceof MGF1ParameterSpec)) {
+                throw new InvalidAlgorithmParameterException("Unsupported MGF parameters"
+                        + ": " + mgfParams + ". Only MGF1ParameterSpec supported");
+            }
+            MGF1ParameterSpec mgfSpec = (MGF1ParameterSpec) mgfParams;
+            String mgf1JcaDigest = mgfSpec.getDigestAlgorithm();
+            if (!KeyProperties.DIGEST_SHA1.equalsIgnoreCase(mgf1JcaDigest)) {
+                throw new InvalidAlgorithmParameterException(
+                        "Unsupported MGF1 digest: " + mgf1JcaDigest
+                        + ". Only " + KeyProperties.DIGEST_SHA1 + " supported");
+            }
+            PSource pSource = spec.getPSource();
+            if (!(pSource instanceof PSource.PSpecified)) {
+                throw new InvalidAlgorithmParameterException(
+                        "Unsupported source of encoding input P: " + pSource
+                        + ". Only pSpecifiedEmpty (PSource.PSpecified.DEFAULT) supported");
+            }
+            PSource.PSpecified pSourceSpecified = (PSource.PSpecified) pSource;
+            byte[] pSourceValue = pSourceSpecified.getValue();
+            if ((pSourceValue != null) && (pSourceValue.length > 0)) {
+                throw new InvalidAlgorithmParameterException(
+                        "Unsupported source of encoding input P: " + pSource
+                        + ". Only pSpecifiedEmpty (PSource.PSpecified.DEFAULT) supported");
+            }
+            mKeymasterDigest = keymasterDigest;
+            mDigestOutputSizeBytes =
+                    (KeymasterUtils.getDigestOutputSizeBits(keymasterDigest) + 7) / 8;
+        }
+
+        @Override
+        protected final void initAlgorithmSpecificParameters(@Nullable AlgorithmParameters params)
+                throws InvalidAlgorithmParameterException {
+            if (params == null) {
+                return;
+            }
+
+            OAEPParameterSpec spec;
+            try {
+                spec = params.getParameterSpec(OAEPParameterSpec.class);
+            } catch (InvalidParameterSpecException e) {
+                throw new InvalidAlgorithmParameterException("OAEP parameters required"
+                        + ", but not found in parameters: " + params, e);
+            }
+            if (spec == null) {
+                throw new InvalidAlgorithmParameterException("OAEP parameters required"
+                        + ", but not provided in parameters: " + params);
+            }
+            initAlgorithmSpecificParameters(spec);
+        }
+
+        @Override
+        protected final AlgorithmParameters engineGetParameters() {
+            OAEPParameterSpec spec =
+                    new OAEPParameterSpec(
+                            KeyProperties.Digest.fromKeymaster(mKeymasterDigest),
+                            MGF_ALGORITGM_MGF1,
+                            MGF1ParameterSpec.SHA1,
+                            PSource.PSpecified.DEFAULT);
+            try {
+                AlgorithmParameters params = AlgorithmParameters.getInstance("OAEP");
+                params.init(spec);
+                return params;
+            } catch (NoSuchAlgorithmException e) {
+                throw new ProviderException(
+                        "Failed to obtain OAEP AlgorithmParameters", e);
+            } catch (InvalidParameterSpecException e) {
+                throw new ProviderException(
+                        "Failed to initialize OAEP AlgorithmParameters with an IV",
+                        e);
+            }
+        }
+
+        @Override
+        protected final void addAlgorithmSpecificParametersToBegin(
+                KeymasterArguments keymasterArgs) {
+            super.addAlgorithmSpecificParametersToBegin(keymasterArgs);
+            keymasterArgs.addInt(KeymasterDefs.KM_TAG_DIGEST, mKeymasterDigest);
+        }
+
+        @Override
+        protected final void loadAlgorithmSpecificParametersFromBeginResult(
+                @NonNull KeymasterArguments keymasterArgs) {
+            super.loadAlgorithmSpecificParametersFromBeginResult(keymasterArgs);
+        }
+
+        @Override
+        protected final int getAdditionalEntropyAmountForBegin() {
+            return (isEncrypting()) ? mDigestOutputSizeBytes : 0;
+        }
+    }
+
+    public static class OAEPWithSHA1AndMGF1Padding extends OAEPWithMGF1Padding {
+        public OAEPWithSHA1AndMGF1Padding() {
+            super(KeymasterDefs.KM_DIGEST_SHA1);
+        }
+    }
+
+    public static class OAEPWithSHA224AndMGF1Padding extends OAEPWithMGF1Padding {
+        public OAEPWithSHA224AndMGF1Padding() {
+            super(KeymasterDefs.KM_DIGEST_SHA_2_224);
+        }
+    }
+
+    public static class OAEPWithSHA256AndMGF1Padding extends OAEPWithMGF1Padding {
+        public OAEPWithSHA256AndMGF1Padding() {
+            super(KeymasterDefs.KM_DIGEST_SHA_2_256);
+        }
+    }
+
+    public static class OAEPWithSHA384AndMGF1Padding extends OAEPWithMGF1Padding {
+        public OAEPWithSHA384AndMGF1Padding() {
+            super(KeymasterDefs.KM_DIGEST_SHA_2_384);
+        }
+    }
+
+    public static class OAEPWithSHA512AndMGF1Padding extends OAEPWithMGF1Padding {
+        public OAEPWithSHA512AndMGF1Padding() {
+            super(KeymasterDefs.KM_DIGEST_SHA_2_512);
+        }
+    }
+
+    private final int mKeymasterPadding;
+
+    private int mModulusSizeBytes = -1;
+
+    AndroidKeyStoreRSACipherSpi(int keymasterPadding) {
+        mKeymasterPadding = keymasterPadding;
+    }
+
+    @Override
+    protected final void initKey(int opmode, Key key) throws InvalidKeyException {
+        if (key == null) {
+            throw new InvalidKeyException("Unsupported key: null");
+        }
+        if (!KeyProperties.KEY_ALGORITHM_RSA.equalsIgnoreCase(key.getAlgorithm())) {
+            throw new InvalidKeyException("Unsupported key algorithm: " + key.getAlgorithm()
+                    + ". Only " + KeyProperties.KEY_ALGORITHM_RSA + " supported");
+        }
+        AndroidKeyStoreKey keystoreKey;
+        if (key instanceof AndroidKeyStorePrivateKey) {
+            keystoreKey = (AndroidKeyStoreKey) key;
+        } else if (key instanceof AndroidKeyStorePublicKey) {
+            keystoreKey = (AndroidKeyStoreKey) key;
+        } else {
+            throw new InvalidKeyException("Unsupported key type: " + key);
+        }
+
+        if (keystoreKey instanceof PrivateKey) {
+            if ((opmode != Cipher.DECRYPT_MODE) && (opmode != Cipher.UNWRAP_MODE)) {
+                throw new InvalidKeyException("Private key cannot be used with opmode: " + opmode
+                        + ". Only DECRYPT_MODE and UNWRAP_MODE supported");
+            }
+        } else {
+            if ((opmode != Cipher.ENCRYPT_MODE) && (opmode != Cipher.WRAP_MODE)) {
+                throw new InvalidKeyException("Public key cannot be used with opmode: " + opmode
+                        + ". Only ENCRYPT_MODE and WRAP_MODE supported");
+            }
+        }
+
+        KeyCharacteristics keyCharacteristics = new KeyCharacteristics();
+        int errorCode = getKeyStore().getKeyCharacteristics(
+                keystoreKey.getAlias(), null, null, keyCharacteristics);
+        if (errorCode != KeyStore.NO_ERROR) {
+            throw getKeyStore().getInvalidKeyException(keystoreKey.getAlias(), errorCode);
+        }
+        int keySizeBits = keyCharacteristics.getInt(KeymasterDefs.KM_TAG_KEY_SIZE, -1);
+        if (keySizeBits == -1) {
+            throw new InvalidKeyException("Size of key not known");
+        }
+        mModulusSizeBytes = (keySizeBits + 7) / 8;
+
+        setKey(keystoreKey);
+    }
+
+    @Override
+    protected final void resetAll() {
+        mModulusSizeBytes = -1;
+        super.resetAll();
+    }
+
+    @Override
+    protected final void resetWhilePreservingInitState() {
+        super.resetWhilePreservingInitState();
+    }
+
+    @Override
+    protected void addAlgorithmSpecificParametersToBegin(
+            @NonNull KeymasterArguments keymasterArgs) {
+        keymasterArgs.addInt(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_RSA);
+        keymasterArgs.addInt(KeymasterDefs.KM_TAG_PADDING, mKeymasterPadding);
+    }
+
+    @Override
+    protected void loadAlgorithmSpecificParametersFromBeginResult(
+            @NonNull KeymasterArguments keymasterArgs) {
+    }
+
+    @Override
+    protected final int engineGetBlockSize() {
+        // Not a block cipher, according to the RI
+        return 0;
+    }
+
+    @Override
+    protected final byte[] engineGetIV() {
+        // IV never used
+        return null;
+    }
+
+    @Override
+    protected final int engineGetOutputSize(int inputLen) {
+        return getModulusSizeBytes();
+    }
+
+    protected final int getModulusSizeBytes() {
+        if (mModulusSizeBytes == -1) {
+            throw new IllegalStateException("Not initialized");
+        }
+        return mModulusSizeBytes;
+    }
+}
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreRSAPublicKey.java b/keystore/java/android/security/keystore/AndroidKeyStoreRSAPublicKey.java
new file mode 100644
index 0000000..36bc997b
--- /dev/null
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreRSAPublicKey.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.keystore;
+
+import java.math.BigInteger;
+import java.security.interfaces.RSAPublicKey;
+
+/**
+ * {@link RSAPublicKey} backed by Android Keystore.
+ *
+ * @hide
+ */
+public class AndroidKeyStoreRSAPublicKey extends AndroidKeyStorePublicKey implements RSAPublicKey {
+    private final BigInteger mModulus;
+    private final BigInteger mPublicExponent;
+
+    public AndroidKeyStoreRSAPublicKey(String alias, byte[] x509EncodedForm, BigInteger modulus,
+            BigInteger publicExponent) {
+        super(alias, "RSA", x509EncodedForm);
+        mModulus = modulus;
+        mPublicExponent = publicExponent;
+    }
+
+    public AndroidKeyStoreRSAPublicKey(String alias, RSAPublicKey info) {
+        this(alias, info.getEncoded(), info.getModulus(), info.getPublicExponent());
+        if (!"X.509".equalsIgnoreCase(info.getFormat())) {
+            throw new IllegalArgumentException(
+                    "Unsupported key export format: " + info.getFormat());
+        }
+    }
+
+    @Override
+    public BigInteger getModulus() {
+        return mModulus;
+    }
+
+    @Override
+    public BigInteger getPublicExponent() {
+        return mPublicExponent;
+    }
+}
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreSecretKey.java b/keystore/java/android/security/keystore/AndroidKeyStoreSecretKey.java
index f75516b..af354ab 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreSecretKey.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreSecretKey.java
@@ -19,7 +19,7 @@
 import javax.crypto.SecretKey;
 
 /**
- * {@link SecretKey} backed by keystore.
+ * {@link SecretKey} backed by Android Keystore.
  *
  * @hide
  */
diff --git a/keystore/java/android/security/keystore/KeyStoreCryptoOperationChunkedStreamer.java b/keystore/java/android/security/keystore/KeyStoreCryptoOperationChunkedStreamer.java
index 7d57e5f..47b4996 100644
--- a/keystore/java/android/security/keystore/KeyStoreCryptoOperationChunkedStreamer.java
+++ b/keystore/java/android/security/keystore/KeyStoreCryptoOperationChunkedStreamer.java
@@ -44,12 +44,12 @@
  *
  * @hide
  */
-public class KeyStoreCryptoOperationChunkedStreamer {
+class KeyStoreCryptoOperationChunkedStreamer implements KeyStoreCryptoOperationStreamer {
 
     /**
      * Bidirectional chunked data stream over a KeyStore crypto operation.
      */
-    public interface Stream {
+    interface Stream {
         /**
          * Returns the result of the KeyStore {@code update} operation or null if keystore couldn't
          * be reached.
@@ -66,12 +66,11 @@
     // Binder buffer is about 1MB, but it's shared between all active transactions of the process.
     // Thus, it's safer to use a much smaller upper bound.
     private static final int DEFAULT_MAX_CHUNK_SIZE = 64 * 1024;
-    private static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
 
     private final Stream mKeyStoreStream;
     private final int mMaxChunkSize;
 
-    private byte[] mBuffered = EMPTY_BYTE_ARRAY;
+    private byte[] mBuffered = EmptyArray.BYTE;
     private int mBufferedOffset;
     private int mBufferedLength;
 
@@ -84,10 +83,11 @@
         mMaxChunkSize = maxChunkSize;
     }
 
+    @Override
     public byte[] update(byte[] input, int inputOffset, int inputLength) throws KeyStoreException {
         if (inputLength == 0) {
             // No input provided
-            return EMPTY_BYTE_ARRAY;
+            return EmptyArray.BYTE;
         }
 
         ByteArrayOutputStream bufferedOutput = null;
@@ -129,7 +129,7 @@
 
             if (opResult.inputConsumed == chunk.length) {
                 // The whole chunk was consumed
-                mBuffered = EMPTY_BYTE_ARRAY;
+                mBuffered = EmptyArray.BYTE;
                 mBufferedOffset = 0;
                 mBufferedLength = 0;
             } else if (opResult.inputConsumed == 0) {
@@ -185,17 +185,18 @@
 
         if (bufferedOutput == null) {
             // No output produced
-            return EMPTY_BYTE_ARRAY;
+            return EmptyArray.BYTE;
         } else {
             return bufferedOutput.toByteArray();
         }
     }
 
+    @Override
     public byte[] doFinal(byte[] input, int inputOffset, int inputLength)
             throws KeyStoreException {
         if (inputLength == 0) {
             // No input provided -- simplify the rest of the code
-            input = EMPTY_BYTE_ARRAY;
+            input = EmptyArray.BYTE;
             inputOffset = 0;
         }
 
diff --git a/keystore/java/android/security/keystore/KeyStoreCryptoOperationStreamer.java b/keystore/java/android/security/keystore/KeyStoreCryptoOperationStreamer.java
new file mode 100644
index 0000000..2fb8f20
--- /dev/null
+++ b/keystore/java/android/security/keystore/KeyStoreCryptoOperationStreamer.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.keystore;
+
+import android.security.KeyStore;
+import android.security.KeyStoreException;
+
+/**
+ * Helper for streaming a crypto operation's input and output via {@link KeyStore} service's
+ * {@code update} and {@code finish} operations.
+ *
+ * <p>The helper abstracts away to issues that need to be solved in most code that uses KeyStore's
+ * update and finish operations. Firstly, KeyStore's update operation can consume only a limited
+ * amount of data in one go because the operations are marshalled via Binder. Secondly, the update
+ * operation may consume less data than provided, in which case the caller has to buffer the
+ * remainder for next time. The helper exposes {@link #update(byte[], int, int) update} and
+ * {@link #doFinal(byte[], int, int) doFinal} operations which can be used to conveniently implement
+ * various JCA crypto primitives.
+ *
+ * @hide
+ */
+interface KeyStoreCryptoOperationStreamer {
+    byte[] update(byte[] input, int inputOffset, int inputLength) throws KeyStoreException;
+    byte[] doFinal(byte[] input, int inputOffset, int inputLength) throws KeyStoreException;
+}
diff --git a/libs/hwui/FrameInfo.h b/libs/hwui/FrameInfo.h
index 38a6a21..6815254 100644
--- a/libs/hwui/FrameInfo.h
+++ b/libs/hwui/FrameInfo.h
@@ -30,35 +30,36 @@
 #define UI_THREAD_FRAME_INFO_SIZE 9
 
 enum class FrameInfoIndex {
-    kFlags = 0,
-    kIntendedVsync,
-    kVsync,
-    kOldestInputEvent,
-    kNewestInputEvent,
-    kHandleInputStart,
-    kAnimationStart,
-    kPerformTraversalsStart,
-    kDrawStart,
+    Flags = 0,
+    IntendedVsync,
+    Vsync,
+    OldestInputEvent,
+    NewestInputEvent,
+    HandleInputStart,
+    AnimationStart,
+    PerformTraversalsStart,
+    DrawStart,
     // End of UI frame info
 
-    kSyncStart,
-    kIssueDrawCommandsStart,
-    kSwapBuffers,
-    kFrameCompleted,
+    SyncStart,
+    IssueDrawCommandsStart,
+    SwapBuffers,
+    FrameCompleted,
 
     // Must be the last value!
-    kNumIndexes
+    NumIndexes
 };
 
 extern const std::string FrameInfoNames[];
 
-enum class FrameInfoFlags {
-    kWindowLayoutChanged = 1 << 0,
-    kRTAnimation = 1 << 1,
-    kSurfaceCanvas = 1 << 2,
-    kSkippedFrame = 1 << 3,
+namespace FrameInfoFlags {
+    enum {
+        WindowLayoutChanged = 1 << 0,
+        RTAnimation = 1 << 1,
+        SurfaceCanvas = 1 << 2,
+        SkippedFrame = 1 << 3,
+    };
 };
-MAKE_FLAGS_ENUM(FrameInfoFlags)
 
 class ANDROID_API UiFrameInfoBuilder {
 public:
@@ -67,19 +68,19 @@
     }
 
     UiFrameInfoBuilder& setVsync(nsecs_t vsyncTime, nsecs_t intendedVsync) {
-        set(FrameInfoIndex::kVsync) = vsyncTime;
-        set(FrameInfoIndex::kIntendedVsync) = intendedVsync;
+        set(FrameInfoIndex::Vsync) = vsyncTime;
+        set(FrameInfoIndex::IntendedVsync) = intendedVsync;
         // Pretend the other fields are all at vsync, too, so that naive
         // duration calculations end up being 0 instead of very large
-        set(FrameInfoIndex::kHandleInputStart) = vsyncTime;
-        set(FrameInfoIndex::kAnimationStart) = vsyncTime;
-        set(FrameInfoIndex::kPerformTraversalsStart) = vsyncTime;
-        set(FrameInfoIndex::kDrawStart) = vsyncTime;
+        set(FrameInfoIndex::HandleInputStart) = vsyncTime;
+        set(FrameInfoIndex::AnimationStart) = vsyncTime;
+        set(FrameInfoIndex::PerformTraversalsStart) = vsyncTime;
+        set(FrameInfoIndex::DrawStart) = vsyncTime;
         return *this;
     }
 
-    UiFrameInfoBuilder& addFlag(FrameInfoFlags flag) {
-        set(FrameInfoIndex::kFlags) |= static_cast<uint64_t>(flag);
+    UiFrameInfoBuilder& addFlag(int frameInfoFlag) {
+        set(FrameInfoIndex::Flags) |= static_cast<uint64_t>(frameInfoFlag);
         return *this;
     }
 
@@ -96,32 +97,32 @@
     void importUiThreadInfo(int64_t* info);
 
     void markSyncStart() {
-        set(FrameInfoIndex::kSyncStart) = systemTime(CLOCK_MONOTONIC);
+        set(FrameInfoIndex::SyncStart) = systemTime(CLOCK_MONOTONIC);
     }
 
     void markIssueDrawCommandsStart() {
-        set(FrameInfoIndex::kIssueDrawCommandsStart) = systemTime(CLOCK_MONOTONIC);
+        set(FrameInfoIndex::IssueDrawCommandsStart) = systemTime(CLOCK_MONOTONIC);
     }
 
     void markSwapBuffers() {
-        set(FrameInfoIndex::kSwapBuffers) = systemTime(CLOCK_MONOTONIC);
+        set(FrameInfoIndex::SwapBuffers) = systemTime(CLOCK_MONOTONIC);
     }
 
     void markFrameCompleted() {
-        set(FrameInfoIndex::kFrameCompleted) = systemTime(CLOCK_MONOTONIC);
+        set(FrameInfoIndex::FrameCompleted) = systemTime(CLOCK_MONOTONIC);
     }
 
-    void addFlag(FrameInfoFlags flag) {
-        set(FrameInfoIndex::kFlags) |= static_cast<uint64_t>(flag);
+    void addFlag(int frameInfoFlag) {
+        set(FrameInfoIndex::Flags) |= static_cast<uint64_t>(frameInfoFlag);
     }
 
     int64_t operator[](FrameInfoIndex index) const {
-        if (index == FrameInfoIndex::kNumIndexes) return 0;
+        if (index == FrameInfoIndex::NumIndexes) return 0;
         return mFrameInfo[static_cast<int>(index)];
     }
 
     int64_t operator[](int index) const {
-        if (index < 0 || index >= static_cast<int>(FrameInfoIndex::kNumIndexes)) return 0;
+        if (index < 0 || index >= static_cast<int>(FrameInfoIndex::NumIndexes)) return 0;
         return mFrameInfo[index];
     }
 
@@ -130,7 +131,7 @@
         return mFrameInfo[static_cast<int>(index)];
     }
 
-    int64_t mFrameInfo[static_cast<int>(FrameInfoIndex::kNumIndexes)];
+    int64_t mFrameInfo[static_cast<int>(FrameInfoIndex::NumIndexes)];
 };
 
 } /* namespace uirenderer */
diff --git a/libs/hwui/FrameInfoVisualizer.cpp b/libs/hwui/FrameInfoVisualizer.cpp
index 95b0995..9557cb0 100644
--- a/libs/hwui/FrameInfoVisualizer.cpp
+++ b/libs/hwui/FrameInfoVisualizer.cpp
@@ -46,15 +46,15 @@
 };
 
 static const std::array<BarSegment,9> Bar {{
-    { FrameInfoIndex::kIntendedVsync, FrameInfoIndex::kVsync, 0x00695C },
-    { FrameInfoIndex::kVsync, FrameInfoIndex::kHandleInputStart, 0x00796B },
-    { FrameInfoIndex::kHandleInputStart, FrameInfoIndex::kAnimationStart, 0x00897B },
-    { FrameInfoIndex::kAnimationStart, FrameInfoIndex::kPerformTraversalsStart, 0x009688 },
-    { FrameInfoIndex::kPerformTraversalsStart, FrameInfoIndex::kDrawStart, 0x26A69A},
-    { FrameInfoIndex::kDrawStart, FrameInfoIndex::kSyncStart, 0x2196F3},
-    { FrameInfoIndex::kSyncStart, FrameInfoIndex::kIssueDrawCommandsStart, 0x4FC3F7},
-    { FrameInfoIndex::kIssueDrawCommandsStart, FrameInfoIndex::kSwapBuffers, 0xF44336},
-    { FrameInfoIndex::kSwapBuffers, FrameInfoIndex::kFrameCompleted, 0xFF9800},
+    { FrameInfoIndex::IntendedVsync, FrameInfoIndex::Vsync, 0x00695C },
+    { FrameInfoIndex::Vsync, FrameInfoIndex::HandleInputStart, 0x00796B },
+    { FrameInfoIndex::HandleInputStart, FrameInfoIndex::AnimationStart, 0x00897B },
+    { FrameInfoIndex::AnimationStart, FrameInfoIndex::PerformTraversalsStart, 0x009688 },
+    { FrameInfoIndex::PerformTraversalsStart, FrameInfoIndex::DrawStart, 0x26A69A},
+    { FrameInfoIndex::DrawStart, FrameInfoIndex::SyncStart, 0x2196F3},
+    { FrameInfoIndex::SyncStart, FrameInfoIndex::IssueDrawCommandsStart, 0x4FC3F7},
+    { FrameInfoIndex::IssueDrawCommandsStart, FrameInfoIndex::SwapBuffers, 0xF44336},
+    { FrameInfoIndex::SwapBuffers, FrameInfoIndex::FrameCompleted, 0xFF9800},
 }};
 
 static int dpToPx(int dp, float density) {
@@ -137,7 +137,7 @@
     for (size_t fi = 0, ri = 0; fi < mFrameSource.size(); fi++, ri += 4) {
         // TODO: Skipped frames will leave little holes in the graph, but this
         // is better than bogus and freaky lines, so...
-        if (mFrameSource[fi][FrameInfoIndex::kFlags] & FrameInfoFlags::kSkippedFrame) {
+        if (mFrameSource[fi][FrameInfoIndex::Flags] & FrameInfoFlags::SkippedFrame) {
             continue;
         }
 
@@ -166,7 +166,7 @@
     size_t fi = mFrameSource.size() - 1;
     size_t ri = fi * 4;
     float top = baseline - (mVerticalUnit * duration(fi,
-            FrameInfoIndex::kIntendedVsync, FrameInfoIndex::kIssueDrawCommandsStart));
+            FrameInfoIndex::IntendedVsync, FrameInfoIndex::IssueDrawCommandsStart));
     canvas->drawRect(mRects[ri], top, mRects[ri + 2], baseline, &paint);
 }
 
@@ -214,15 +214,15 @@
     fprintf(file, "\n\tDraw\tPrepare\tProcess\tExecute\n");
 
     for (size_t i = 0; i < mFrameSource.size(); i++) {
-        if (mFrameSource[i][FrameInfoIndex::kIntendedVsync] <= mLastFrameLogged) {
+        if (mFrameSource[i][FrameInfoIndex::IntendedVsync] <= mLastFrameLogged) {
             continue;
         }
-        mLastFrameLogged = mFrameSource[i][FrameInfoIndex::kIntendedVsync];
+        mLastFrameLogged = mFrameSource[i][FrameInfoIndex::IntendedVsync];
         fprintf(file, "\t%3.2f\t%3.2f\t%3.2f\t%3.2f\n",
-                duration(i, FrameInfoIndex::kIntendedVsync, FrameInfoIndex::kSyncStart),
-                duration(i, FrameInfoIndex::kSyncStart, FrameInfoIndex::kIssueDrawCommandsStart),
-                duration(i, FrameInfoIndex::kIssueDrawCommandsStart, FrameInfoIndex::kSwapBuffers),
-                duration(i, FrameInfoIndex::kSwapBuffers, FrameInfoIndex::kFrameCompleted));
+                duration(i, FrameInfoIndex::IntendedVsync, FrameInfoIndex::SyncStart),
+                duration(i, FrameInfoIndex::SyncStart, FrameInfoIndex::IssueDrawCommandsStart),
+                duration(i, FrameInfoIndex::IssueDrawCommandsStart, FrameInfoIndex::SwapBuffers),
+                duration(i, FrameInfoIndex::SwapBuffers, FrameInfoIndex::FrameCompleted));
     }
 
     fflush(file);
diff --git a/libs/hwui/JankTracker.cpp b/libs/hwui/JankTracker.cpp
index cc5c403..5c0801e 100644
--- a/libs/hwui/JankTracker.cpp
+++ b/libs/hwui/JankTracker.cpp
@@ -40,11 +40,11 @@
 };
 
 static const Comparison COMPARISONS[] = {
-        {FrameInfoIndex::kIntendedVsync, FrameInfoIndex::kVsync},
-        {FrameInfoIndex::kOldestInputEvent, FrameInfoIndex::kVsync},
-        {FrameInfoIndex::kVsync, FrameInfoIndex::kSyncStart},
-        {FrameInfoIndex::kSyncStart, FrameInfoIndex::kIssueDrawCommandsStart},
-        {FrameInfoIndex::kIssueDrawCommandsStart, FrameInfoIndex::kFrameCompleted},
+        {FrameInfoIndex::IntendedVsync, FrameInfoIndex::Vsync},
+        {FrameInfoIndex::OldestInputEvent, FrameInfoIndex::Vsync},
+        {FrameInfoIndex::Vsync, FrameInfoIndex::SyncStart},
+        {FrameInfoIndex::SyncStart, FrameInfoIndex::IssueDrawCommandsStart},
+        {FrameInfoIndex::IssueDrawCommandsStart, FrameInfoIndex::FrameCompleted},
 };
 
 // If the event exceeds 10 seconds throw it away, this isn't a jank event
@@ -64,8 +64,8 @@
  * time on the RenderThread, figure out how to attribute that as a jank-causer
  */
 static const int64_t EXEMPT_FRAMES_FLAGS
-        = FrameInfoFlags::kWindowLayoutChanged
-        | FrameInfoFlags::kSurfaceCanvas;
+        = FrameInfoFlags::WindowLayoutChanged
+        | FrameInfoFlags::SurfaceCanvas;
 
 // The bucketing algorithm controls so to speak
 // If a frame is <= to this it goes in bucket 0
@@ -206,7 +206,7 @@
     mData->totalFrameCount++;
     // Fast-path for jank-free frames
     int64_t totalDuration =
-            frame[FrameInfoIndex::kFrameCompleted] - frame[FrameInfoIndex::kIntendedVsync];
+            frame[FrameInfoIndex::FrameCompleted] - frame[FrameInfoIndex::IntendedVsync];
     uint32_t framebucket = frameCountIndexForFrameTime(
             totalDuration, mData->frameCounts.size());
     // Keep the fast path as fast as possible.
@@ -215,7 +215,7 @@
         return;
     }
 
-    if (frame[FrameInfoIndex::kFlags] & EXEMPT_FRAMES_FLAGS) {
+    if (frame[FrameInfoIndex::Flags] & EXEMPT_FRAMES_FLAGS) {
         return;
     }
 
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index acf9c13..b88f30e 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -157,7 +157,7 @@
 }
 
 static bool wasSkipped(FrameInfo* info) {
-    return info && ((*info)[FrameInfoIndex::kFlags] & FrameInfoFlags::kSkippedFrame);
+    return info && ((*info)[FrameInfoIndex::Flags] & FrameInfoFlags::SkippedFrame);
 }
 
 void CanvasContext::prepareTree(TreeInfo& info, int64_t* uiFrameInfo) {
@@ -185,7 +185,7 @@
     }
 
     if (CC_UNLIKELY(!mNativeWindow.get())) {
-        mCurrentFrameInfo->addFlag(FrameInfoFlags::kSkippedFrame);
+        mCurrentFrameInfo->addFlag(FrameInfoFlags::SkippedFrame);
         info.out.canDrawThisFrame = false;
         return;
     }
@@ -199,7 +199,7 @@
     info.out.canDrawThisFrame = !runningBehind;
 
     if (!info.out.canDrawThisFrame) {
-        mCurrentFrameInfo->addFlag(FrameInfoFlags::kSkippedFrame);
+        mCurrentFrameInfo->addFlag(FrameInfoFlags::SkippedFrame);
     }
 
     if (info.out.hasAnimations || !info.out.canDrawThisFrame) {
@@ -228,7 +228,7 @@
     mDamageAccumulator.finish(&dirty);
 
     if (dirty.isEmpty() && Properties::skipEmptyFrames) {
-        mCurrentFrameInfo->addFlag(FrameInfoFlags::kSkippedFrame);
+        mCurrentFrameInfo->addFlag(FrameInfoFlags::SkippedFrame);
         return;
     }
 
@@ -288,7 +288,7 @@
 
     int64_t frameInfo[UI_THREAD_FRAME_INFO_SIZE];
     UiFrameInfoBuilder(frameInfo)
-        .addFlag(FrameInfoFlags::kRTAnimation)
+        .addFlag(FrameInfoFlags::RTAnimation)
         .setVsync(mRenderThread.timeLord().computeFrameTimeNanos(),
                 mRenderThread.timeLord().latestVsync());
 
@@ -400,17 +400,17 @@
 void CanvasContext::dumpFrames(int fd) {
     FILE* file = fdopen(fd, "a");
     fprintf(file, "\n\n---PROFILEDATA---\n");
-    for (size_t i = 0; i < static_cast<size_t>(FrameInfoIndex::kNumIndexes); i++) {
+    for (size_t i = 0; i < static_cast<size_t>(FrameInfoIndex::NumIndexes); i++) {
         fprintf(file, "%s", FrameInfoNames[i].c_str());
         fprintf(file, ",");
     }
     for (size_t i = 0; i < mFrames.size(); i++) {
         FrameInfo& frame = mFrames[i];
-        if (frame[FrameInfoIndex::kSyncStart] == 0) {
+        if (frame[FrameInfoIndex::SyncStart] == 0) {
             continue;
         }
         fprintf(file, "\n");
-        for (int i = 0; i < static_cast<int>(FrameInfoIndex::kNumIndexes); i++) {
+        for (int i = 0; i < static_cast<int>(FrameInfoIndex::NumIndexes); i++) {
             fprintf(file, "%" PRId64 ",", frame[i]);
         }
     }
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index 83af4ae..008e297 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -110,7 +110,7 @@
 
 bool DrawFrameTask::syncFrameState(TreeInfo& info) {
     ATRACE_CALL();
-    int64_t vsync = mFrameInfo[static_cast<int>(FrameInfoIndex::kVsync)];
+    int64_t vsync = mFrameInfo[static_cast<int>(FrameInfoIndex::Vsync)];
     mRenderThread->timeLord().vsyncReceived(vsync);
     mContext->makeCurrent();
     Caches::getInstance().textureCache.resetMarkInUse();
diff --git a/libs/hwui/utils/Macros.h b/libs/hwui/utils/Macros.h
index 1b31059..5ca9083 100644
--- a/libs/hwui/utils/Macros.h
+++ b/libs/hwui/utils/Macros.h
@@ -35,30 +35,4 @@
         static_assert(std::is_standard_layout<Type>::value, \
         #Type " must have standard layout")
 
-#define MAKE_FLAGS_ENUM(enumType) \
-        inline void operator|=(int& lhs, enumType rhs) { \
-            lhs |= static_cast<int>(rhs); \
-        } \
-        inline int operator|(int lhs, enumType rhs) { \
-            return lhs | static_cast<int>(rhs); \
-        } \
-        inline int operator|(enumType lhs, int rhs) { \
-            return static_cast<int>(lhs) | rhs; \
-        } \
-        inline int operator|(enumType lhs, enumType rhs) { \
-            return static_cast<int>(lhs) | static_cast<int>(rhs); \
-        } \
-        inline void operator&=(int& lhs, enumType rhs) { \
-            lhs &= static_cast<int>(rhs); \
-        } \
-        inline int operator&(int lhs, enumType rhs) { \
-            return lhs & static_cast<int>(rhs); \
-        } \
-        inline int operator&(enumType lhs, int rhs) { \
-            return static_cast<int>(lhs) & rhs; \
-        } \
-        inline int operator&(enumType lhs, enumType rhs) { \
-            return static_cast<int>(lhs) & static_cast<int>(rhs); \
-        }
-
 #endif /* MACROS_H */
diff --git a/media/jni/android_media_MediaCrypto.cpp b/media/jni/android_media_MediaCrypto.cpp
index a9accb02..d7968d2 100644
--- a/media/jni/android_media_MediaCrypto.cpp
+++ b/media/jni/android_media_MediaCrypto.cpp
@@ -301,17 +301,19 @@
 
     status_t err = crypto->setMediaDrmSession(sessionId);
 
-    String8 msg("setMediaDrmSession failed");
-    if (err == ERROR_DRM_SESSION_NOT_OPENED) {
-        msg += ": session not opened";
-    } else if (err == ERROR_UNSUPPORTED) {
-        msg += ": not supported by this crypto scheme";
-    } else if (err == NO_INIT) {
-        msg += ": crypto plugin not initialized";
-    } else if (err != OK) {
-        msg.appendFormat(": general failure (%d)", err);
+    if (err != OK) {
+        String8 msg("setMediaDrmSession failed");
+        if (err == ERROR_DRM_SESSION_NOT_OPENED) {
+            msg += ": session not opened";
+        } else if (err == ERROR_UNSUPPORTED) {
+            msg += ": not supported by this crypto scheme";
+        } else if (err == NO_INIT) {
+            msg += ": crypto plugin not initialized";
+        } else {
+            msg.appendFormat(": general failure (%d)", err);
+        }
+        jniThrowException(env, "android/media/MediaCryptoException", msg.string());
     }
-    jniThrowException(env, "android/media/MediaCryptoException", msg.string());
 }
 
 static JNINativeMethod gMethods[] = {
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraMetadataTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraMetadataTest.java
index 29c3c75..cd0e587 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraMetadataTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraMetadataTest.java
@@ -731,27 +731,31 @@
 
     @SmallTest
     public void testReadWriteHighSpeedVideoConfiguration() {
-        // int32 x 4 x 1
+        // int32 x 5 x 1
         checkKeyMarshal("android.control.availableHighSpeedVideoConfigurations",
                 new HighSpeedVideoConfiguration(
-                        /*width*/1000, /*height*/255, /*fpsMin*/30, /*fpsMax*/200),
+                        /*width*/1000, /*height*/255, /*fpsMin*/30, /*fpsMax*/200,
+                        /*batchSizeMax*/8),
                 /* width, height, fpsMin, fpsMax */
-                toByteArray(1000, 255, 30, 200));
+                toByteArray(1000, 255, 30, 200, 8));
 
-        // int32 x 4 x 3
+        // int32 x 5 x 3
         checkKeyMarshal("android.control.availableHighSpeedVideoConfigurations",
                 new HighSpeedVideoConfiguration[] {
                     new HighSpeedVideoConfiguration(
-                            /*width*/1280, /*height*/720, /*fpsMin*/60, /*fpsMax*/120),
+                            /*width*/1280, /*height*/720, /*fpsMin*/60, /*fpsMax*/120,
+                            /*batchSizeMax*/8),
                     new HighSpeedVideoConfiguration(
-                            /*width*/123, /*height*/456, /*fpsMin*/1, /*fpsMax*/200),
+                            /*width*/123, /*height*/456, /*fpsMin*/1, /*fpsMax*/200,
+                            /*batchSizeMax*/4),
                     new HighSpeedVideoConfiguration(
-                            /*width*/4096, /*height*/2592, /*fpsMin*/30, /*fpsMax*/60)
+                            /*width*/4096, /*height*/2592, /*fpsMin*/30, /*fpsMax*/60,
+                            /*batchSizeMax*/2)
                 },
                 toByteArray(
-                        1280, 720, 60, 120,
-                        123, 456, 1, 200,
-                        4096, 2592, 30, 60
+                        1280, 720, 60, 120, 8,
+                        123, 456, 1, 200, 4,
+                        4096, 2592, 30, 60, 2
         ));
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Recents.java b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
index c702673..bbd3e60 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Recents.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
@@ -35,6 +35,7 @@
 import android.os.Handler;
 import android.os.SystemClock;
 import android.os.UserHandle;
+import android.util.MutableBoolean;
 import android.util.Pair;
 import android.view.Display;
 import android.view.LayoutInflater;
@@ -57,7 +58,6 @@
 import com.android.systemui.statusbar.phone.PhoneStatusBar;
 
 import java.util.ArrayList;
-import java.util.concurrent.atomic.AtomicBoolean;
 
 /**
  * Annotation for a method that is only called from the primary user's SystemUI process and will be
@@ -362,7 +362,12 @@
         // RecentsActivity)
         RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
         sInstanceLoadPlan = loader.createLoadPlan(mContext);
-        sInstanceLoadPlan.preloadRawTasks(true);
+
+        ActivityManager.RunningTaskInfo topTask = mSystemServicesProxy.getTopMostTask();
+        MutableBoolean isTopTaskHome = new MutableBoolean(true);
+        if (topTask != null && mSystemServicesProxy.isRecentsTopMost(topTask, isTopTaskHome)) {
+            sInstanceLoadPlan.preloadRawTasks(isTopTaskHome.value);
+        }
     }
 
     @Override
@@ -546,7 +551,7 @@
         // If Recents is the front most activity, then we should just communicate with it directly
         // to launch the first task or dismiss itself
         ActivityManager.RunningTaskInfo topTask = mSystemServicesProxy.getTopMostTask();
-        AtomicBoolean isTopTaskHome = new AtomicBoolean(true);
+        MutableBoolean isTopTaskHome = new MutableBoolean(true);
         if (topTask != null && mSystemServicesProxy.isRecentsTopMost(topTask, isTopTaskHome)) {
             // Notify recents to toggle itself
             Intent intent = createLocalBroadcastIntent(mContext, ACTION_TOGGLE_RECENTS_ACTIVITY);
@@ -555,7 +560,7 @@
             return;
         } else {
             // Otherwise, start the recents activity
-            startRecentsActivity(topTask, isTopTaskHome.get());
+            startRecentsActivity(topTask, isTopTaskHome.value);
         }
     }
 
@@ -563,9 +568,9 @@
     void startRecentsActivity() {
         // Check if the top task is in the home stack, and start the recents activity
         ActivityManager.RunningTaskInfo topTask = mSystemServicesProxy.getTopMostTask();
-        AtomicBoolean isTopTaskHome = new AtomicBoolean(true);
+        MutableBoolean isTopTaskHome = new MutableBoolean(true);
         if (topTask == null || !mSystemServicesProxy.isRecentsTopMost(topTask, isTopTaskHome)) {
-            startRecentsActivity(topTask, isTopTaskHome.get());
+            startRecentsActivity(topTask, isTopTaskHome.value);
         }
     }
 
@@ -654,6 +659,7 @@
         if (task == null) {
             // If no task is specified or we can not find the task just use the front most one
             task = tasks.get(tasks.size() - 1);
+            runningTaskOut.copyFrom(task);
         }
 
         // Get the transform for the running task
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
index ca0f357..272d39a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -54,6 +54,7 @@
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.util.Log;
+import android.util.MutableBoolean;
 import android.util.Pair;
 import android.util.SparseArray;
 import android.view.Display;
@@ -67,12 +68,9 @@
 
 import java.io.IOException;
 import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Random;
-import java.util.concurrent.atomic.AtomicBoolean;
 
 /**
  * Acts as a shim around the real system services that we need to access data from, and provides
@@ -192,7 +190,7 @@
 
         // Break early if we can't get a valid set of tasks
         if (tasks == null) {
-            return new ArrayList<ActivityManager.RecentTaskInfo>();
+            return new ArrayList<>();
         }
 
         boolean isFirstValidTask = true;
@@ -235,7 +233,7 @@
 
     /** Returns whether the recents is currently running */
     public boolean isRecentsTopMost(ActivityManager.RunningTaskInfo topTask,
-            AtomicBoolean isHomeTopMost) {
+            MutableBoolean isHomeTopMost) {
         if (topTask != null) {
             ComponentName topActivity = topTask.topActivity;
 
@@ -243,13 +241,13 @@
             if (topActivity.getPackageName().equals(Recents.sRecentsPackage) &&
                     topActivity.getClassName().equals(Recents.sRecentsActivity)) {
                 if (isHomeTopMost != null) {
-                    isHomeTopMost.set(false);
+                    isHomeTopMost.value = false;
                 }
                 return true;
             }
 
             if (isHomeTopMost != null) {
-                isHomeTopMost.set(isInHomeStack(topTask.id));
+                isHomeTopMost.value = isInHomeStack(topTask.id);
             }
         }
         return false;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
index 40cd211..f40c58d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
@@ -104,13 +104,9 @@
         if (mRawTasks == null) {
             preloadRawTasks(isTopTaskHome);
         }
-        int firstStackId = -1;
         int taskCount = mRawTasks.size();
         for (int i = 0; i < taskCount; i++) {
             ActivityManager.RecentTaskInfo t = mRawTasks.get(i);
-            if (firstStackId < 0) {
-                firstStackId = t.stackId;
-            }
 
             // Compose the task key
             Task.TaskKey taskKey = new Task.TaskKey(t.persistentId, t.stackId, t.baseIntent,
@@ -158,17 +154,17 @@
 
             if (!mConfig.multiStackEnabled ||
                     Constants.DebugFlags.App.EnableMultiStackToSingleStack) {
-                firstStackId = 0;
+                int firstStackId = 0;
                 ArrayList<Task> stackTasks = stacksTasks.get(firstStackId);
                 if (stackTasks == null) {
-                    stackTasks = new ArrayList<Task>();
+                    stackTasks = new ArrayList<>();
                     stacksTasks.put(firstStackId, stackTasks);
                 }
                 stackTasks.add(task);
             } else {
                 ArrayList<Task> stackTasks = stacksTasks.get(t.stackId);
                 if (stackTasks == null) {
-                    stackTasks = new ArrayList<Task>();
+                    stackTasks = new ArrayList<>();
                     stacksTasks.put(t.stackId, stackTasks);
                 }
                 stackTasks.add(task);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index b3e6221..cec613c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -550,7 +550,7 @@
         if (tv == null) {
             launchRunnable.run();
         } else {
-            if (!task.group.isFrontMostTask(task)) {
+            if (task.group != null && !task.group.isFrontMostTask(task)) {
                 // For affiliated tasks that are behind other tasks, we must animate the front cards
                 // out of view before starting the task transition
                 stackView.startLaunchTaskAnimation(tv, launchRunnable, lockToTask);
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index d4c3194..7bcbcfb 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -166,8 +166,6 @@
     private final List<AccessibilityServiceInfo> mEnabledServicesForFeedbackTempList =
             new ArrayList<>();
 
-    private final Region mTempRegion = new Region();
-
     private final Rect mTempRect = new Rect();
 
     private final Rect mTempRect1 = new Rect();
@@ -2241,7 +2239,7 @@
                 throws RemoteException {
             final int resolvedWindowId;
             IAccessibilityInteractionConnection connection = null;
-            Region partialInteractiveRegion = mTempRegion;
+            Region partialInteractiveRegion = Region.obtain();
             synchronized (mLock) {
                 // We treat calls from a profile as if made by its parent as profiles
                 // share the accessibility state of the parent. The call below
@@ -2265,6 +2263,7 @@
                 }
                 if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked(
                         resolvedWindowId, partialInteractiveRegion)) {
+                    partialInteractiveRegion.recycle();
                     partialInteractiveRegion = null;
                 }
             }
@@ -2282,6 +2281,10 @@
                 }
             } finally {
                 Binder.restoreCallingIdentity(identityToken);
+                // Recycle if passed to another process.
+                if (partialInteractiveRegion != null && Binder.isProxy(connection)) {
+                    partialInteractiveRegion.recycle();
+                }
             }
             return false;
         }
@@ -2293,7 +2296,7 @@
                 throws RemoteException {
             final int resolvedWindowId;
             IAccessibilityInteractionConnection connection = null;
-            Region partialInteractiveRegion = mTempRegion;
+            Region partialInteractiveRegion = Region.obtain();
             synchronized (mLock) {
                 // We treat calls from a profile as if made by its parent as profiles
                 // share the accessibility state of the parent. The call below
@@ -2317,6 +2320,7 @@
                 }
                 if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked(
                         resolvedWindowId, partialInteractiveRegion)) {
+                    partialInteractiveRegion.recycle();
                     partialInteractiveRegion = null;
                 }
             }
@@ -2334,6 +2338,10 @@
                 }
             } finally {
                 Binder.restoreCallingIdentity(identityToken);
+                // Recycle if passed to another process.
+                if (partialInteractiveRegion != null && Binder.isProxy(connection)) {
+                    partialInteractiveRegion.recycle();
+                }
             }
             return false;
         }
@@ -2345,7 +2353,7 @@
                 long interrogatingTid) throws RemoteException {
             final int resolvedWindowId;
             IAccessibilityInteractionConnection connection = null;
-            Region partialInteractiveRegion = mTempRegion;
+            Region partialInteractiveRegion = Region.obtain();
             synchronized (mLock) {
                 // We treat calls from a profile as if made by its parent as profiles
                 // share the accessibility state of the parent. The call below
@@ -2369,6 +2377,7 @@
                 }
                 if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked(
                         resolvedWindowId, partialInteractiveRegion)) {
+                    partialInteractiveRegion.recycle();
                     partialInteractiveRegion = null;
                 }
             }
@@ -2386,6 +2395,10 @@
                 }
             } finally {
                 Binder.restoreCallingIdentity(identityToken);
+                // Recycle if passed to another process.
+                if (partialInteractiveRegion != null && Binder.isProxy(connection)) {
+                    partialInteractiveRegion.recycle();
+                }
             }
             return false;
         }
@@ -2397,7 +2410,7 @@
                 throws RemoteException {
             final int resolvedWindowId;
             IAccessibilityInteractionConnection connection = null;
-            Region partialInteractiveRegion = mTempRegion;
+            Region partialInteractiveRegion = Region.obtain();
             synchronized (mLock) {
                 // We treat calls from a profile as if made by its parent as profiles
                 // share the accessibility state of the parent. The call below
@@ -2422,6 +2435,7 @@
                 }
                 if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked(
                         resolvedWindowId, partialInteractiveRegion)) {
+                    partialInteractiveRegion.recycle();
                     partialInteractiveRegion = null;
                 }
             }
@@ -2439,6 +2453,10 @@
                 }
             } finally {
                 Binder.restoreCallingIdentity(identityToken);
+                // Recycle if passed to another process.
+                if (partialInteractiveRegion != null && Binder.isProxy(connection)) {
+                    partialInteractiveRegion.recycle();
+                }
             }
             return false;
         }
@@ -2450,7 +2468,7 @@
                 throws RemoteException {
             final int resolvedWindowId;
             IAccessibilityInteractionConnection connection = null;
-            Region partialInteractiveRegion = mTempRegion;
+            Region partialInteractiveRegion = Region.obtain();
             synchronized (mLock) {
                 // We treat calls from a profile as if made by its parent as profiles
                 // share the accessibility state of the parent. The call below
@@ -2474,6 +2492,7 @@
                 }
                 if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked(
                         resolvedWindowId, partialInteractiveRegion)) {
+                    partialInteractiveRegion.recycle();
                     partialInteractiveRegion = null;
                 }
             }
@@ -2491,6 +2510,10 @@
                 }
             } finally {
                 Binder.restoreCallingIdentity(identityToken);
+                // Recycle if passed to another process.
+                if (partialInteractiveRegion != null && Binder.isProxy(connection)) {
+                    partialInteractiveRegion.recycle();
+                }
             }
             return false;
         }
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index e07e4e2..2e4b881 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -3819,10 +3819,12 @@
 //        }
         updateTcpBufferSizes(networkAgent);
 
-        // TODO: deprecate and remove mDefaultDns when we can do so safely.
-        // For now, use it only when the network has Internet access. http://b/18327075
-        final boolean useDefaultDns = networkAgent.networkCapabilities.hasCapability(
-                NET_CAPABILITY_INTERNET);
+        // TODO: deprecate and remove mDefaultDns when we can do so safely. See http://b/18327075
+        // In L, we used it only when the network had Internet access but provided no DNS servers.
+        // For now, just disable it, and if disabling it doesn't break things, remove it.
+        // final boolean useDefaultDns = networkAgent.networkCapabilities.hasCapability(
+        //        NET_CAPABILITY_INTERNET);
+        final boolean useDefaultDns = false;
         final boolean flushDns = updateRoutes(newLp, oldLp, netId);
         updateDnses(newLp, oldLp, netId, flushDns, useDefaultDns);
 
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 3315c89..21f96c9 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -1785,7 +1785,13 @@
 
         // Get the calling package. We will use it for the purpose of caching.
         final String callerPkg = loginOptions.getString(AccountManager.KEY_ANDROID_PACKAGE_NAME);
-        List<String> callerOwnedPackageNames = Arrays.asList(mPackageManager.getPackagesForUid(callerUid));
+        List<String> callerOwnedPackageNames;
+        long ident = Binder.clearCallingIdentity();
+        try {
+            callerOwnedPackageNames = Arrays.asList(mPackageManager.getPackagesForUid(callerUid));
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
         if (callerPkg == null || !callerOwnedPackageNames.contains(callerPkg)) {
             String msg = String.format(
                     "Uid %s is attempting to illegally masquerade as package %s!",
@@ -1798,15 +1804,15 @@
         loginOptions.putInt(AccountManager.KEY_CALLER_UID, callerUid);
         loginOptions.putInt(AccountManager.KEY_CALLER_PID, Binder.getCallingPid());
 
-        // Distill the caller's package signatures into a single digest.
-        final byte[] callerPkgSigDigest = calculatePackageSignatureDigest(callerPkg);
-
         if (notifyOnAuthFailure) {
             loginOptions.putBoolean(AccountManager.KEY_NOTIFY_ON_FAILURE, true);
         }
 
         long identityToken = clearCallingIdentity();
         try {
+            // Distill the caller's package signatures into a single digest.
+            final byte[] callerPkgSigDigest = calculatePackageSignatureDigest(callerPkg);
+
             // if the caller has permission, do the peek. otherwise go the more expensive
             // route of starting a Session
             if (!customTokens && permissionGranted) {
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index 745cb7e..80b8a93 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -1121,25 +1121,23 @@
     }
 
     final void logBroadcastReceiverDiscardLocked(BroadcastRecord r) {
-        if (r.nextReceiver > 0) {
-            Object curReceiver = r.receivers.get(r.nextReceiver-1);
+        final int logIndex = r.nextReceiver - 1;
+        if (logIndex >= 0 && logIndex < r.receivers.size()) {
+            Object curReceiver = r.receivers.get(logIndex);
             if (curReceiver instanceof BroadcastFilter) {
                 BroadcastFilter bf = (BroadcastFilter) curReceiver;
                 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER,
                         bf.owningUserId, System.identityHashCode(r),
-                        r.intent.getAction(),
-                        r.nextReceiver - 1,
-                        System.identityHashCode(bf));
+                        r.intent.getAction(), logIndex, System.identityHashCode(bf));
             } else {
-                ResolveInfo ri = (ResolveInfo)curReceiver;
+                ResolveInfo ri = (ResolveInfo) curReceiver;
                 EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
                         UserHandle.getUserId(ri.activityInfo.applicationInfo.uid),
-                        System.identityHashCode(r), r.intent.getAction(),
-                        r.nextReceiver - 1, ri.toString());
+                        System.identityHashCode(r), r.intent.getAction(), logIndex, ri.toString());
             }
         } else {
-            Slog.w(TAG, "Discarding broadcast before first receiver is invoked: "
-                    + r);
+            if (logIndex < 0) Slog.w(TAG,
+                    "Discarding broadcast before first receiver is invoked: " + r);
             EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP,
                     -1, System.identityHashCode(r),
                     r.intent.getAction(),
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index b8d0692..46793b9 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -1087,16 +1087,19 @@
         }
     }
 
-    private void sleepPress(KeyEvent event) {
+    private void sleepPress(long eventTime) {
+        if (mShortPressOnSleepBehavior == SHORT_PRESS_SLEEP_GO_TO_SLEEP_AND_GO_HOME) {
+            launchHomeFromHotKey(false /* awakenDreams */, true /*respectKeyguard*/);
+        }
+    }
+
+    private void sleepRelease(long eventTime) {
         switch (mShortPressOnSleepBehavior) {
             case SHORT_PRESS_SLEEP_GO_TO_SLEEP:
-                mPowerManager.goToSleep(event.getEventTime(),
-                        PowerManager.GO_TO_SLEEP_REASON_SLEEP_BUTTON, 0);
-                break;
             case SHORT_PRESS_SLEEP_GO_TO_SLEEP_AND_GO_HOME:
-                launchHomeFromHotKey(false /* awakenDreams */, true /*respectKeyguard*/);
-                mPowerManager.goToSleep(event.getEventTime(),
-                        PowerManager.GO_TO_SLEEP_REASON_SLEEP_BUTTON, 0);
+                Slog.i(TAG, "sleepRelease() calling goToSleep(GO_TO_SLEEP_REASON_SLEEP_BUTTON)");
+                mPowerManager.goToSleep(eventTime,
+                       PowerManager.GO_TO_SLEEP_REASON_SLEEP_BUTTON, 0);
                 break;
         }
     }
@@ -2116,7 +2119,9 @@
             case TYPE_KEYGUARD_SCRIM:
                 return false;
             default:
-                return true;
+                // Hide only windows below the keyguard host window.
+                return windowTypeToLayerLw(win.getBaseType())
+                        < windowTypeToLayerLw(TYPE_STATUS_BAR);
         }
     }
 
@@ -4903,7 +4908,11 @@
                 if (!mPowerManager.isInteractive()) {
                     useHapticFeedback = false; // suppress feedback if already non-interactive
                 }
-                sleepPress(event);
+                if (down) {
+                    sleepPress(event.getEventTime());
+                } else {
+                    sleepRelease(event.getEventTime());
+                }
                 break;
             }
 
@@ -5517,6 +5526,12 @@
 
     /** {@inheritDoc} */
     @Override
+    public boolean isKeyguardShowingOrOccluded() {
+        return mKeyguardDelegate == null ? false : mKeyguardDelegate.isShowing();
+    }
+
+    /** {@inheritDoc} */
+    @Override
     public boolean inKeyguardRestrictedKeyInputMode() {
         if (mKeyguardDelegate == null) return false;
         return mKeyguardDelegate.isInputRestricted();
diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java b/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java
index 01c110f..f1f9c50 100644
--- a/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java
+++ b/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java
@@ -36,10 +36,11 @@
     // Keyguard changes its state, it always triggers a layout in window manager. Because
     // IKeyguardStateCallback is synchronous and because these states are declared volatile, it's
     // guaranteed that window manager picks up the new state all the time in the layout caused by
-    // the state change of Keyguard.
-    private volatile boolean mIsShowing;
-    private volatile boolean mSimSecure;
-    private volatile boolean mInputRestricted;
+    // the state change of Keyguard. To be extra safe, assume most restrictive values until Keyguard
+    // tells us the actual value.
+    private volatile boolean mIsShowing = true;
+    private volatile boolean mSimSecure = true;
+    private volatile boolean mInputRestricted = true;
 
     private int mCurrentUserId;
 
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index 9169351..3305e1e 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -191,7 +191,8 @@
     private boolean shouldForceHide(WindowState win) {
         final WindowState imeTarget = mService.mInputMethodTarget;
         final boolean showImeOverKeyguard = imeTarget != null && imeTarget.isVisibleNow() &&
-                (imeTarget.getAttrs().flags & FLAG_SHOW_WHEN_LOCKED) != 0;
+                ((imeTarget.getAttrs().flags & FLAG_SHOW_WHEN_LOCKED) != 0
+                        || !mPolicy.canBeForceHidden(imeTarget, imeTarget.mAttrs));
 
         final WindowState winShowWhenLocked = (WindowState) mPolicy.getWinShowWhenLockedLw();
         final AppWindowToken appShowWhenLocked = winShowWhenLocked == null ?
@@ -203,7 +204,11 @@
                         || (win.mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0 && win.isAnimatingLw()
                         // Show error dialogs over apps that dismiss keyguard.
                         || (win.mAttrs.privateFlags & PRIVATE_FLAG_SYSTEM_ERROR) != 0)));
-        return (mForceHiding == KEYGUARD_SHOWN) && hideWhenLocked;
+
+        // Only hide windows if the keyguard is active and not animating away.
+        boolean keyguardOn = mPolicy.isKeyguardShowingOrOccluded()
+                && mForceHiding != KEYGUARD_ANIMATING_OUT;
+        return keyguardOn && hideWhenLocked;
     }
 
     private void updateWindowsLocked(final int displayId) {
@@ -228,6 +233,7 @@
                         winAnimator.mAnimation.setDuration(KEYGUARD_ANIM_TIMEOUT_MS);
                         winAnimator.mAnimationIsEntrance = false;
                         winAnimator.mAnimationStartTime = -1;
+                        winAnimator.mKeyguardGoingAwayAnimation = true;
                     }
                 } else {
                     if (DEBUG_KEYGUARD) Slog.d(TAG,
@@ -310,7 +316,7 @@
                         mKeyguardGoingAway = false;
                     }
                     if (win.isReadyForDisplay()) {
-                        if (nowAnimating) {
+                        if (nowAnimating && win.mWinAnimator.mKeyguardGoingAwayAnimation) {
                             mForceHiding = KEYGUARD_ANIMATING_OUT;
                         } else {
                             mForceHiding = win.isDrawnLw() ? KEYGUARD_SHOWN : KEYGUARD_NOT_SHOWN;
diff --git a/services/net/java/android/net/dhcp/DhcpAckPacket.java b/services/net/java/android/net/dhcp/DhcpAckPacket.java
index c0e1d19..334f708 100644
--- a/services/net/java/android/net/dhcp/DhcpAckPacket.java
+++ b/services/net/java/android/net/dhcp/DhcpAckPacket.java
@@ -30,8 +30,8 @@
     private final Inet4Address mSrcIp;
 
     DhcpAckPacket(int transId, short secs, boolean broadcast, Inet4Address serverAddress,
-                  Inet4Address clientIp, byte[] clientMac) {
-        super(transId, secs, INADDR_ANY, clientIp, serverAddress, INADDR_ANY, clientMac, broadcast);
+                  Inet4Address clientIp, Inet4Address yourIp, byte[] clientMac) {
+        super(transId, secs, clientIp, yourIp, serverAddress, INADDR_ANY, clientMac, broadcast);
         mBroadcast = broadcast;
         mSrcIp = serverAddress;
     }
diff --git a/services/net/java/android/net/dhcp/DhcpClient.java b/services/net/java/android/net/dhcp/DhcpClient.java
index d8d74e2..069b591 100644
--- a/services/net/java/android/net/dhcp/DhcpClient.java
+++ b/services/net/java/android/net/dhcp/DhcpClient.java
@@ -601,12 +601,15 @@
 
     /**
      * Retransmits packets using jittered exponential backoff with an optional timeout. Packet
-     * transmission is triggered by CMD_KICK, which is sent by an AlarmManager alarm.
+     * transmission is triggered by CMD_KICK, which is sent by an AlarmManager alarm. If a subclass
+     * sets mTimeout to a positive value, then timeout() is called by an AlarmManager alarm mTimeout
+     * milliseconds after entering the state. Kicks and timeouts are cancelled when leaving the
+     * state.
      *
      * Concrete subclasses must implement sendPacket, which is called when the alarm fires and a
      * packet needs to be transmitted, and receivePacket, which is triggered by CMD_RECEIVED_PACKET
-     * sent by the receive thread. They may implement timeout, which is called when the timeout
-     * fires.
+     * sent by the receive thread. They may also set mTimeout and if desired override the default
+     * timeout implementation.
      */
     abstract class PacketRetransmittingState extends LoggingState {
 
@@ -647,7 +650,19 @@
 
         abstract protected boolean sendPacket();
         abstract protected void receivePacket(DhcpPacket packet);
-        protected void timeout() {}
+
+        // Default implementation of timeout. This is only invoked if mTimeout > 0, so it will never
+        // be called if the subclass does not set a timeout.
+        protected void timeout() {
+            maybeLog("Timeout in " + getName());
+            notifyFailure();
+            if (this != mDhcpInitState) {
+                // Only transition to INIT if we're not already there. Otherwise, we'll exit the
+                // state and re-enter it, which will reset the packet transmission interval, re-set
+                // the timeout, etc.
+                transitionTo(mDhcpInitState);
+            }
+        }
 
         protected void initTimer() {
             mTimer = FIRST_TIMEOUT_MS;
@@ -696,11 +711,6 @@
             return sendDiscoverPacket();
         }
 
-        protected void timeout() {
-            maybeLog("Timeout");
-            notifyFailure();
-        }
-
         protected void receivePacket(DhcpPacket packet) {
             if (!isValidPacket(packet)) return;
             if (!(packet instanceof DhcpOfferPacket)) return;
@@ -747,11 +757,6 @@
                 transitionTo(mDhcpInitState);
             }
         }
-
-        protected void timeout() {
-            notifyFailure();
-            transitionTo(mDhcpInitState);
-        }
     }
 
     class DhcpHaveAddressState extends LoggingState {
@@ -760,6 +765,8 @@
             super.enter();
             if (!setIpAddress(mDhcpLease.ipAddress)) {
                 notifyFailure();
+                // There's likely no point in going into DhcpInitState here, we'll probably just
+                // repeat the transaction, get the same IP address as before, and fail.
                 transitionTo(mStoppedState);
             }
         }
@@ -797,7 +804,6 @@
         }
     }
 
-    // TODO: timeout.
     class DhcpRenewingState extends PacketRetransmittingState {
         public DhcpRenewingState() {
             super();
diff --git a/services/net/java/android/net/dhcp/DhcpOfferPacket.java b/services/net/java/android/net/dhcp/DhcpOfferPacket.java
index af41708..7ca7100 100644
--- a/services/net/java/android/net/dhcp/DhcpOfferPacket.java
+++ b/services/net/java/android/net/dhcp/DhcpOfferPacket.java
@@ -32,8 +32,8 @@
      * Generates a OFFER packet with the specified parameters.
      */
     DhcpOfferPacket(int transId, short secs, boolean broadcast, Inet4Address serverAddress,
-                    Inet4Address clientIp, byte[] clientMac) {
-        super(transId, secs, INADDR_ANY, clientIp, INADDR_ANY, INADDR_ANY, clientMac, broadcast);
+                    Inet4Address clientIp, Inet4Address yourIp, byte[] clientMac) {
+        super(transId, secs, clientIp, yourIp, INADDR_ANY, INADDR_ANY, clientMac, broadcast);
         mSrcIp = serverAddress;
     }
 
diff --git a/services/net/java/android/net/dhcp/DhcpPacket.java b/services/net/java/android/net/dhcp/DhcpPacket.java
index 2a25d30..d42404b 100644
--- a/services/net/java/android/net/dhcp/DhcpPacket.java
+++ b/services/net/java/android/net/dhcp/DhcpPacket.java
@@ -919,7 +919,7 @@
                 break;
             case DHCP_MESSAGE_TYPE_OFFER:
                 newPacket = new DhcpOfferPacket(
-                    transactionId, secs, broadcast, ipSrc, yourIp, clientMac);
+                    transactionId, secs, broadcast, ipSrc, clientIp, yourIp, clientMac);
                 break;
             case DHCP_MESSAGE_TYPE_REQUEST:
                 newPacket = new DhcpRequestPacket(
@@ -932,7 +932,7 @@
                 break;
             case DHCP_MESSAGE_TYPE_ACK:
                 newPacket = new DhcpAckPacket(
-                    transactionId, secs, broadcast, ipSrc, yourIp, clientMac);
+                    transactionId, secs, broadcast, ipSrc, clientIp, yourIp, clientMac);
                 break;
             case DHCP_MESSAGE_TYPE_NAK:
                 newPacket = new DhcpNakPacket(
@@ -982,9 +982,9 @@
      */
     public DhcpResults toDhcpResults() {
         Inet4Address ipAddress = mYourIp;
-        if (ipAddress == Inet4Address.ANY) {
+        if (ipAddress.equals(Inet4Address.ANY)) {
             ipAddress = mClientIp;
-            if (ipAddress == Inet4Address.ANY) {
+            if (ipAddress.equals(Inet4Address.ANY)) {
                 return null;
             }
         }
@@ -1052,7 +1052,7 @@
         Inet4Address gateway, List<Inet4Address> dnsServers,
         Inet4Address dhcpServerIdentifier, String domainName) {
         DhcpPacket pkt = new DhcpOfferPacket(
-            transactionId, (short) 0, broadcast, serverIpAddr, clientIpAddr, mac);
+            transactionId, (short) 0, broadcast, serverIpAddr, INADDR_ANY, clientIpAddr, mac);
         pkt.mGateway = gateway;
         pkt.mDnsServers = dnsServers;
         pkt.mLeaseTime = timeout;
@@ -1072,7 +1072,7 @@
         Inet4Address gateway, List<Inet4Address> dnsServers,
         Inet4Address dhcpServerIdentifier, String domainName) {
         DhcpPacket pkt = new DhcpAckPacket(
-            transactionId, (short) 0, broadcast, serverIpAddr, clientIpAddr, mac);
+            transactionId, (short) 0, broadcast, serverIpAddr, INADDR_ANY, clientIpAddr, mac);
         pkt.mGateway = gateway;
         pkt.mDnsServers = dnsServers;
         pkt.mLeaseTime = timeout;
diff --git a/services/tests/servicestests/src/android/net/dhcp/DhcpPacketTest.java b/services/tests/servicestests/src/android/net/dhcp/DhcpPacketTest.java
index f116042..e0e3fcf 100644
--- a/services/tests/servicestests/src/android/net/dhcp/DhcpPacketTest.java
+++ b/services/tests/servicestests/src/android/net/dhcp/DhcpPacketTest.java
@@ -18,6 +18,7 @@
 
 import android.net.NetworkUtils;
 import android.net.DhcpResults;
+import android.net.LinkAddress;
 import android.system.OsConstants;
 import android.test.suitebuilder.annotation.SmallTest;
 import junit.framework.TestCase;
@@ -34,19 +35,27 @@
             (Inet4Address) NetworkUtils.numericToInetAddress("192.0.2.1");
     private static Inet4Address CLIENT_ADDR =
             (Inet4Address) NetworkUtils.numericToInetAddress("192.0.2.234");
+    // Use our own empty address instead of Inet4Address.ANY or INADDR_ANY to ensure that the code
+    // doesn't use == instead of equals when comparing addresses.
+    private static Inet4Address ANY = (Inet4Address) NetworkUtils.numericToInetAddress("0.0.0.0");
+
     private static byte[] CLIENT_MAC = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 };
 
     class TestDhcpPacket extends DhcpPacket {
         private byte mType;
         // TODO: Make this a map of option numbers to bytes instead.
-        private byte[] mDomainBytes, mVendorInfoBytes, mLeaseTimeBytes;
+        private byte[] mDomainBytes, mVendorInfoBytes, mLeaseTimeBytes, mNetmaskBytes;
 
-        public TestDhcpPacket(byte type) {
-            super(0xdeadbeef, (short) 0, INADDR_ANY, CLIENT_ADDR, INADDR_ANY, INADDR_ANY,
+        public TestDhcpPacket(byte type, Inet4Address clientIp, Inet4Address yourIp) {
+            super(0xdeadbeef, (short) 0, clientIp, yourIp, INADDR_ANY, INADDR_ANY,
                   CLIENT_MAC, true);
             mType = type;
         }
 
+        public TestDhcpPacket(byte type) {
+            this(type, INADDR_ANY, CLIENT_ADDR);
+        }
+
         public TestDhcpPacket setDomainBytes(byte[] domainBytes) {
             mDomainBytes = domainBytes;
             return this;
@@ -62,6 +71,11 @@
             return this;
         }
 
+        public TestDhcpPacket setNetmaskBytes(byte[] netmaskBytes) {
+            mNetmaskBytes = netmaskBytes;
+            return this;
+        }
+
         public ByteBuffer buildPacket(int encap, short unusedDestUdp, short unusedSrcUdp) {
             ByteBuffer result = ByteBuffer.allocate(MAX_LENGTH);
             fillInPacket(encap, CLIENT_ADDR, SERVER_ADDR,
@@ -80,6 +94,9 @@
             if (mLeaseTimeBytes != null) {
                 addTlv(buffer, DHCP_LEASE_TIME, mLeaseTimeBytes);
             }
+            if (mNetmaskBytes != null) {
+                addTlv(buffer, DHCP_SUBNET_MASK, mNetmaskBytes);
+            }
             addTlvEnd(buffer);
         }
 
@@ -175,4 +192,50 @@
         assertLeaseTimeParses(true, -2147483647, 2147483649L * 1000, maxIntPlusOneLease);
         assertLeaseTimeParses(true, DhcpPacket.INFINITE_LEASE, 0, infiniteLease);
     }
+
+    private void checkIpAddress(String expected, Inet4Address clientIp, Inet4Address yourIp,
+                                byte[] netmaskBytes) {
+        checkIpAddress(expected, DHCP_MESSAGE_TYPE_OFFER, clientIp, yourIp, netmaskBytes);
+        checkIpAddress(expected, DHCP_MESSAGE_TYPE_ACK, clientIp, yourIp, netmaskBytes);
+    }
+
+    private void checkIpAddress(String expected, byte type,
+                                Inet4Address clientIp, Inet4Address yourIp,
+                                byte[] netmaskBytes) {
+        ByteBuffer packet = new TestDhcpPacket(type, clientIp, yourIp)
+                .setNetmaskBytes(netmaskBytes)
+                .build();
+        DhcpPacket offerPacket = DhcpPacket.decodeFullPacket(packet, ENCAP_BOOTP);
+        DhcpResults results = offerPacket.toDhcpResults();
+
+        if (expected != null) {
+            LinkAddress expectedAddress = new LinkAddress(expected);
+            assertEquals(expectedAddress, results.ipAddress);
+        } else {
+            assertNull(results);
+        }
+    }
+
+    @SmallTest
+    public void testIpAddress() throws Exception {
+        byte[] slash11Netmask = new byte[] { (byte) 0xff, (byte) 0xe0, 0x00, 0x00 };
+        byte[] slash24Netmask = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, 0x00 };
+        byte[] invalidNetmask = new byte[] { (byte) 0xff, (byte) 0xfb, (byte) 0xff, 0x00 };
+        Inet4Address example1 = (Inet4Address) NetworkUtils.numericToInetAddress("192.0.2.1");
+        Inet4Address example2 = (Inet4Address) NetworkUtils.numericToInetAddress("192.0.2.43");
+
+        // A packet without any addresses is not valid.
+        checkIpAddress(null, ANY, ANY, slash24Netmask);
+
+        // ClientIP is used iff YourIP is not present.
+        checkIpAddress("192.0.2.1/24", example2, example1, slash24Netmask);
+        checkIpAddress("192.0.2.43/11", example2, ANY, slash11Netmask);
+        checkIpAddress("192.0.2.43/11", ANY, example2, slash11Netmask);
+
+        // Invalid netmasks are ignored.
+        checkIpAddress(null, example2, ANY, invalidNetmask);
+
+        // If there is no netmask, implicit netmasks are used.
+        checkIpAddress("192.0.2.43/24", ANY, example2, null);
+    }
 }
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 1d751d5..dfb02bb 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -51,6 +51,10 @@
     public static final String
             ACTION_CARRIER_CONFIG_CHANGED = "android.telephony.action.CARRIER_CONFIG_CHANGED";
 
+    // Below are the keys used in carrier config bundles. To add a new variable, define the key and
+    // give it a default value in sDefaults. If you need to ship a per-network override in the
+    // system image, that can be added in packages/apps/CarrierConfig.
+
     /**
      * Flag indicating whether the Phone app should ignore EVENT_SIM_NETWORK_LOCKED
      * events from the Sim.
diff --git a/wifi/java/android/net/wifi/WifiScanner.java b/wifi/java/android/net/wifi/WifiScanner.java
index 5f430f0..a3dc077 100644
--- a/wifi/java/android/net/wifi/WifiScanner.java
+++ b/wifi/java/android/net/wifi/WifiScanner.java
@@ -1007,7 +1007,7 @@
                             ((ParcelableScanResults) msg.obj).getResults());
                     return;
                 case CMD_SINGLE_SCAN_COMPLETED:
-                    Log.d(TAG, "removing listener for single scan");
+                    if (DBG) Log.d(TAG, "removing listener for single scan");
                     removeListener(msg.arg2);
                     break;
                 default: