Merge "Switch to SkAndroidCodec::computeSampleSize"
diff --git a/api/current.txt b/api/current.txt
index a958482..bfb1934 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -6354,6 +6354,7 @@
     field public static final java.lang.String EXTRA_DISABLE_WARNING = "android.app.extra.DISABLE_WARNING";
     field public static final java.lang.String EXTRA_LOCK_TASK_PACKAGE = "android.app.extra.LOCK_TASK_PACKAGE";
     field public static final java.lang.String EXTRA_TRANSFER_OWNER_ADMIN_EXTRAS_BUNDLE = "android.app.extra.TRANSFER_OWNER_ADMIN_EXTRAS_BUNDLE";
+    field public static final java.lang.String SUPPORT_TRANSFER_OWNERSHIP_META_DATA = "android.app.support_transfer_ownership";
   }
 
   public class DeviceAdminService extends android.app.Service {
@@ -11159,7 +11160,7 @@
     field public static final java.lang.String FEATURE_USB_HOST = "android.hardware.usb.host";
     field public static final java.lang.String FEATURE_VERIFIED_BOOT = "android.software.verified_boot";
     field public static final java.lang.String FEATURE_VR_HEADTRACKING = "android.hardware.vr.headtracking";
-    field public static final java.lang.String FEATURE_VR_MODE = "android.software.vr.mode";
+    field public static final deprecated java.lang.String FEATURE_VR_MODE = "android.software.vr.mode";
     field public static final java.lang.String FEATURE_VR_MODE_HIGH_PERFORMANCE = "android.hardware.vr.high_performance";
     field public static final java.lang.String FEATURE_VULKAN_HARDWARE_COMPUTE = "android.hardware.vulkan.compute";
     field public static final java.lang.String FEATURE_VULKAN_HARDWARE_LEVEL = "android.hardware.vulkan.level";
@@ -26229,9 +26230,9 @@
     method public void applyTransportModeTransform(java.io.FileDescriptor, int, android.net.IpSecTransform) throws java.io.IOException;
     method public android.net.IpSecManager.UdpEncapsulationSocket openUdpEncapsulationSocket(int) throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException;
     method public android.net.IpSecManager.UdpEncapsulationSocket openUdpEncapsulationSocket() throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException;
-    method public void removeTransportModeTransforms(java.net.Socket, android.net.IpSecTransform) throws java.io.IOException;
-    method public void removeTransportModeTransforms(java.net.DatagramSocket, android.net.IpSecTransform) throws java.io.IOException;
-    method public void removeTransportModeTransforms(java.io.FileDescriptor, android.net.IpSecTransform) throws java.io.IOException;
+    method public void removeTransportModeTransforms(java.net.Socket) throws java.io.IOException;
+    method public void removeTransportModeTransforms(java.net.DatagramSocket) throws java.io.IOException;
+    method public void removeTransportModeTransforms(java.io.FileDescriptor) throws java.io.IOException;
     field public static final int DIRECTION_IN = 0; // 0x0
     field public static final int DIRECTION_OUT = 1; // 0x1
   }
diff --git a/cmds/statsd/src/packages/UidMap.cpp b/cmds/statsd/src/packages/UidMap.cpp
index b0c3197..dcb8eed 100644
--- a/cmds/statsd/src/packages/UidMap.cpp
+++ b/cmds/statsd/src/packages/UidMap.cpp
@@ -471,10 +471,13 @@
                                                              {"AID_AUTOMOTIVE_EVS", 1062},
                                                              {"AID_LOWPAN", 1063},
                                                              {"AID_HSM", 1064},
+                                                             {"AID_RESERVED_DISK", 1065},
+                                                             {"AID_STATSD", 1066},
+                                                             {"AID_INCIDENTD", 1067},
                                                              {"AID_SHELL", 2000},
                                                              {"AID_CACHE", 2001},
                                                              {"AID_DIAG", 2002}};
 
 }  // namespace statsd
 }  // namespace os
-}  // namespace android
\ No newline at end of file
+}  // namespace android
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index aa099eb..cfe5572 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -6616,7 +6616,6 @@
      *    to run as a {@link android.service.vr.VrListenerService} is not installed, or has
      *    not been enabled in user settings.
      *
-     * @see android.content.pm.PackageManager#FEATURE_VR_MODE
      * @see android.content.pm.PackageManager#FEATURE_VR_MODE_HIGH_PERFORMANCE
      * @see android.service.vr.VrListenerService
      * @see android.provider.Settings#ACTION_VR_LISTENER_SETTINGS
diff --git a/core/java/android/app/admin/DeviceAdminReceiver.java b/core/java/android/app/admin/DeviceAdminReceiver.java
index aa05b76..302d52f 100644
--- a/core/java/android/app/admin/DeviceAdminReceiver.java
+++ b/core/java/android/app/admin/DeviceAdminReceiver.java
@@ -467,6 +467,31 @@
     public static final String EXTRA_TRANSFER_OWNER_ADMIN_EXTRAS_BUNDLE =
             "android.app.extra.TRANSFER_OWNER_ADMIN_EXTRAS_BUNDLE";
 
+    /**
+     * Name under which a device administration component indicates whether it supports transfer of
+     * ownership. This meta-data is of type <code>boolean</code>. A value of <code>true</code>
+     * allows this administrator to be used as a target administrator for a transfer. If the value
+     * is <code>false</code>, ownership cannot be transferred to this administrator. The default
+     * value is <code>false</code>.
+     * <p>This metadata is used to avoid ownership transfer migration to an administrator with a
+     * version which does not yet support it.
+     * <p>Usage:
+     * <pre>
+     * &lt;receiver name="..." android:permission="android.permission.BIND_DEVICE_ADMIN"&gt;
+     *     &lt;meta-data
+     *         android:name="android.app.device_admin"
+     *         android:resource="@xml/..." /&gt;
+     *     &lt;meta-data
+     *         android:name="android.app.support_transfer_ownership"
+     *         android:value="true" /&gt;
+     * &lt;/receiver&gt;
+     * </pre>
+     *
+     * @see DevicePolicyManager#transferOwnership(ComponentName, ComponentName, PersistableBundle)
+     */
+    public static final String SUPPORT_TRANSFER_OWNERSHIP_META_DATA =
+            "android.app.support_transfer_ownership";
+
     private DevicePolicyManager mManager;
     private ComponentName mWho;
 
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 0455949..cc4d29e 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -9096,6 +9096,11 @@
      * will be received in the
      * {@link DeviceAdminReceiver#onTransferOwnershipComplete(Context, PersistableBundle)} callback.
      *
+     * <p>The incoming target administrator must have the
+     * {@link DeviceAdminReceiver#SUPPORT_TRANSFER_OWNERSHIP_META_DATA} <code>meta-data</code> tag
+     * included in its corresponding <code>receiver</code> component with a value of {@code true}.
+     * Otherwise an {@link IllegalArgumentException} will be thrown.
+     *
      * @param admin which {@link DeviceAdminReceiver} this request is associated with
      * @param target which {@link DeviceAdminReceiver} we want the new administrator to be
      * @param bundle data to be sent to the new administrator
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index deb8dfb..44b4a33 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -2535,31 +2535,22 @@
      * Devices declaring this feature must include an application implementing a
      * {@link android.service.vr.VrListenerService} that can be targeted by VR applications via
      * {@link android.app.Activity#setVrModeEnabled}.
+     * @deprecated use {@link #FEATURE_VR_MODE_HIGH_PERFORMANCE} instead.
      */
+    @Deprecated
     @SdkConstant(SdkConstantType.FEATURE)
     public static final String FEATURE_VR_MODE = "android.software.vr.mode";
 
     /**
      * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}:
-     * The device implements {@link #FEATURE_VR_MODE} but additionally meets extra CDD requirements
-     * to provide a high-quality VR experience.  In general, devices declaring this feature will
-     * additionally:
-     * <ul>
-     *   <li>Deliver consistent performance at a high framerate over an extended period of time
-     *   for typical VR application CPU/GPU workloads with a minimal number of frame drops for VR
-     *   applications that have called
-     *   {@link android.view.Window#setSustainedPerformanceMode}.</li>
-     *   <li>Implement {@link #FEATURE_HIFI_SENSORS} and have a low sensor latency.</li>
-     *   <li>Include optimizations to lower display persistence while running VR applications.</li>
-     *   <li>Implement an optimized render path to minimize latency to draw to the device's main
-     *   display.</li>
-     *   <li>Include the following EGL extensions: EGL_ANDROID_create_native_client_buffer,
-     *   EGL_ANDROID_front_buffer_auto_refresh, EGL_EXT_protected_content,
-     *   EGL_KHR_mutable_render_buffer, EGL_KHR_reusable_sync, and EGL_KHR_wait_sync.</li>
-     *   <li>Provide at least one CPU core that is reserved for use solely by the top, foreground
-     *   VR application process for critical render threads while such an application is
-     *   running.</li>
-     * </ul>
+     * The device implements an optimized mode for virtual reality (VR) applications that handles
+     * stereoscopic rendering of notifications, disables most monocular system UI components
+     * while a VR application has user focus and meets extra CDD requirements to provide a
+     * high-quality VR experience.
+     * Devices declaring this feature must include an application implementing a
+     * {@link android.service.vr.VrListenerService} that can be targeted by VR applications via
+     * {@link android.app.Activity#setVrModeEnabled}.
+     * and must meet CDD requirements to provide a high-quality VR experience.
      */
     @SdkConstant(SdkConstantType.FEATURE)
     public static final String FEATURE_VR_MODE_HIGH_PERFORMANCE
diff --git a/core/java/android/net/IIpSecService.aidl b/core/java/android/net/IIpSecService.aidl
index 3fe531f..790c80b 100644
--- a/core/java/android/net/IIpSecService.aidl
+++ b/core/java/android/net/IIpSecService.aidl
@@ -45,5 +45,5 @@
 
     void applyTransportModeTransform(in ParcelFileDescriptor socket, int direction, int transformId);
 
-    void removeTransportModeTransforms(in ParcelFileDescriptor socket, int transformId);
+    void removeTransportModeTransforms(in ParcelFileDescriptor socket);
 }
diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java
index 2202df3..2cda58c 100644
--- a/core/java/android/net/IpSecManager.java
+++ b/core/java/android/net/IpSecManager.java
@@ -405,62 +405,56 @@
     /**
      * Remove an IPsec transform from a stream socket.
      *
-     * <p>Once removed, traffic on the socket will not be encrypted. This operation will succeed
-     * regardless of the state of the transform. Removing a transform from a socket allows the
-     * socket to be reused for communication in the clear.
+     * <p>Once removed, traffic on the socket will not be encrypted. Removing transforms from a
+     * socket allows the socket to be reused for communication in the clear.
      *
      * <p>If an {@code IpSecTransform} object applied to this socket was deallocated by calling
      * {@link IpSecTransform#close()}, then communication on the socket will fail until this method
      * is called.
      *
      * @param socket a socket that previously had a transform applied to it
-     * @param transform the IPsec Transform that was previously applied to the given socket
      * @throws IOException indicating that the transform could not be removed from the socket
      */
-    public void removeTransportModeTransforms(Socket socket, IpSecTransform transform)
+    public void removeTransportModeTransforms(Socket socket)
             throws IOException {
-        removeTransportModeTransforms(socket.getFileDescriptor$(), transform);
+        removeTransportModeTransforms(socket.getFileDescriptor$());
     }
 
     /**
      * Remove an IPsec transform from a datagram socket.
      *
-     * <p>Once removed, traffic on the socket will not be encrypted. This operation will succeed
-     * regardless of the state of the transform. Removing a transform from a socket allows the
-     * socket to be reused for communication in the clear.
+     * <p>Once removed, traffic on the socket will not be encrypted. Removing transforms from a
+     * socket allows the socket to be reused for communication in the clear.
      *
      * <p>If an {@code IpSecTransform} object applied to this socket was deallocated by calling
      * {@link IpSecTransform#close()}, then communication on the socket will fail until this method
      * is called.
      *
      * @param socket a socket that previously had a transform applied to it
-     * @param transform the IPsec Transform that was previously applied to the given socket
      * @throws IOException indicating that the transform could not be removed from the socket
      */
-    public void removeTransportModeTransforms(DatagramSocket socket, IpSecTransform transform)
+    public void removeTransportModeTransforms(DatagramSocket socket)
             throws IOException {
-        removeTransportModeTransforms(socket.getFileDescriptor$(), transform);
+        removeTransportModeTransforms(socket.getFileDescriptor$());
     }
 
     /**
      * Remove an IPsec transform from a socket.
      *
-     * <p>Once removed, traffic on the socket will not be encrypted. This operation will succeed
-     * regardless of the state of the transform. Removing a transform from a socket allows the
-     * socket to be reused for communication in the clear.
+     * <p>Once removed, traffic on the socket will not be encrypted. Removing transforms from a
+     * socket allows the socket to be reused for communication in the clear.
      *
      * <p>If an {@code IpSecTransform} object applied to this socket was deallocated by calling
      * {@link IpSecTransform#close()}, then communication on the socket will fail until this method
      * is called.
      *
      * @param socket a socket that previously had a transform applied to it
-     * @param transform the IPsec Transform that was previously applied to the given socket
      * @throws IOException indicating that the transform could not be removed from the socket
      */
-    public void removeTransportModeTransforms(FileDescriptor socket, IpSecTransform transform)
+    public void removeTransportModeTransforms(FileDescriptor socket)
             throws IOException {
         try (ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(socket)) {
-            mService.removeTransportModeTransforms(pfd, transform.getResourceId());
+            mService.removeTransportModeTransforms(pfd);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
diff --git a/core/java/android/security/keystore/EntryRecoveryData.aidl b/core/java/android/security/keystore/KeychainProtectionParameter.aidl
similarity index 93%
copy from core/java/android/security/keystore/EntryRecoveryData.aidl
copy to core/java/android/security/keystore/KeychainProtectionParameter.aidl
index c6c20e3..1e2c365 100644
--- a/core/java/android/security/keystore/EntryRecoveryData.aidl
+++ b/core/java/android/security/keystore/KeychainProtectionParameter.aidl
@@ -17,4 +17,4 @@
 package android.security.keystore;
 
 /* @hide */
-parcelable EntryRecoveryData;
+parcelable KeychainProtectionParameter;
diff --git a/core/java/android/security/keystore/RecoveryMetadata.java b/core/java/android/security/keystore/KeychainProtectionParameter.java
similarity index 78%
rename from core/java/android/security/keystore/RecoveryMetadata.java
rename to core/java/android/security/keystore/KeychainProtectionParameter.java
index 3f09455..2319ef5 100644
--- a/core/java/android/security/keystore/RecoveryMetadata.java
+++ b/core/java/android/security/keystore/KeychainProtectionParameter.java
@@ -28,12 +28,26 @@
 import java.util.Arrays;
 
 /**
- * Helper class with data necessary to recover Keystore on a new device.
- * It defines UI shown to the user and a way to derive a cryptographic key from user output.
+ * A {@link KeychainSnapshot} is protected with a key derived from the user's lock screen. This
+ * class wraps all the data necessary to derive the same key on a recovering device:
+ *
+ * <ul>
+ *     <li>UI parameters for the user's lock screen - so that if e.g., the user was using a pattern,
+ *         the recovering device can display the pattern UI to the user when asking them to enter
+ *         the lock screen from their previous device.
+ *     <li>The algorithm used to derive a key from the user's lock screen, e.g. SHA-256 with a salt.
+ * </ul>
+ *
+ * <p>As such, this data is sent along with the {@link KeychainSnapshot} when syncing the current
+ * version of the keychain.
+ *
+ * <p>For now, the recoverable keychain only supports a single layer of protection, which is the
+ * user's lock screen. In the future, the keychain will support multiple layers of protection
+ * (e.g. an additional keychain password, along with the lock screen).
  *
  * @hide
  */
-public final class RecoveryMetadata implements Parcelable {
+public final class KeychainProtectionParameter implements Parcelable {
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
     @IntDef({TYPE_LOCKSCREEN, TYPE_CUSTOM_PASSWORD})
@@ -88,7 +102,7 @@
      * @link {#clearSecret} to overwrite its value in memory.
      * @hide
      */
-    public RecoveryMetadata(@UserSecretType int userSecretType,
+    public KeychainProtectionParameter(@UserSecretType int userSecretType,
             @LockScreenUiFormat int lockScreenUiFormat,
             @NonNull KeyDerivationParams keyDerivationParams,
             @NonNull byte[] secret) {
@@ -98,7 +112,7 @@
         mSecret = Preconditions.checkNotNull(secret);
     }
 
-    private RecoveryMetadata() {
+    private KeychainProtectionParameter() {
 
     }
 
@@ -141,10 +155,10 @@
     }
 
     /**
-     * Builder for creating {@link RecoveryMetadata}.
+     * Builder for creating {@link KeychainProtectionParameter}.
      */
     public static class Builder {
-        private RecoveryMetadata mInstance = new RecoveryMetadata();
+        private KeychainProtectionParameter mInstance = new KeychainProtectionParameter();
 
         /**
          * Sets user secret type.
@@ -198,14 +212,14 @@
 
 
         /**
-         * Creates a new {@link RecoveryMetadata} instance.
+         * Creates a new {@link KeychainProtectionParameter} instance.
          * The instance will include default values, if {@link setSecret}
          * or {@link setUserSecretType} were not called.
          *
          * @return new instance
          * @throws NullPointerException if some required fields were not set.
          */
-        public @NonNull RecoveryMetadata build() {
+        @NonNull public KeychainProtectionParameter build() {
             if (mInstance.mUserSecretType == null) {
                 mInstance.mUserSecretType = TYPE_LOCKSCREEN;
             }
@@ -235,14 +249,14 @@
         Arrays.fill(mSecret, (byte) 0);
     }
 
-    public static final Parcelable.Creator<RecoveryMetadata> CREATOR =
-            new Parcelable.Creator<RecoveryMetadata>() {
-        public RecoveryMetadata createFromParcel(Parcel in) {
-            return new RecoveryMetadata(in);
+    public static final Parcelable.Creator<KeychainProtectionParameter> CREATOR =
+            new Parcelable.Creator<KeychainProtectionParameter>() {
+        public KeychainProtectionParameter createFromParcel(Parcel in) {
+            return new KeychainProtectionParameter(in);
         }
 
-        public RecoveryMetadata[] newArray(int length) {
-            return new RecoveryMetadata[length];
+        public KeychainProtectionParameter[] newArray(int length) {
+            return new KeychainProtectionParameter[length];
         }
     };
 
@@ -260,7 +274,7 @@
     /**
      * @hide
      */
-    protected RecoveryMetadata(Parcel in) {
+    protected KeychainProtectionParameter(Parcel in) {
         mUserSecretType = in.readInt();
         mLockScreenUiFormat = in.readInt();
         mKeyDerivationParams = in.readTypedObject(KeyDerivationParams.CREATOR);
diff --git a/core/java/android/security/keystore/EntryRecoveryData.aidl b/core/java/android/security/keystore/KeychainSnapshot.aidl
similarity index 95%
rename from core/java/android/security/keystore/EntryRecoveryData.aidl
rename to core/java/android/security/keystore/KeychainSnapshot.aidl
index c6c20e3..b35713f 100644
--- a/core/java/android/security/keystore/EntryRecoveryData.aidl
+++ b/core/java/android/security/keystore/KeychainSnapshot.aidl
@@ -17,4 +17,4 @@
 package android.security.keystore;
 
 /* @hide */
-parcelable EntryRecoveryData;
+parcelable KeychainSnapshot;
diff --git a/core/java/android/security/keystore/KeychainSnapshot.java b/core/java/android/security/keystore/KeychainSnapshot.java
new file mode 100644
index 0000000..71a808a
--- /dev/null
+++ b/core/java/android/security/keystore/KeychainSnapshot.java
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2017 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.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.util.Preconditions;
+
+import java.util.List;
+
+/**
+ * A snapshot of a version of the keystore. Two events can trigger the generation of a new snapshot:
+ *
+ * <ul>
+ *     <li>The user's lock screen changes. (A key derived from the user's lock screen is used to
+ *         protected the keychain, which is why this forces a new snapshot.)
+ *     <li>A key is added to or removed from the recoverable keychain.
+ * </ul>
+ *
+ * <p>The snapshot data is also encrypted with the remote trusted hardware's public key, so even
+ * the recovery agent itself should not be able to decipher the data. The recovery agent sends an
+ * instance of this to the remote trusted hardware whenever a new snapshot is generated. During a
+ * recovery flow, the recovery agent retrieves a snapshot from the remote trusted hardware. It then
+ * sends it to the framework, where it is decrypted using the user's lock screen from their previous
+ * device.
+ *
+ * @hide
+ */
+public final class KeychainSnapshot implements Parcelable {
+    private int mSnapshotVersion;
+    private List<KeychainProtectionParameter> mKeychainProtectionParams;
+    private List<WrappedApplicationKey> mEntryRecoveryData;
+    private byte[] mEncryptedRecoveryKeyBlob;
+
+    /**
+     * @hide
+     * Deprecated, consider using builder.
+     */
+    public KeychainSnapshot(
+            int snapshotVersion,
+            @NonNull List<KeychainProtectionParameter> keychainProtectionParams,
+            @NonNull List<WrappedApplicationKey> wrappedApplicationKeys,
+            @NonNull byte[] encryptedRecoveryKeyBlob) {
+        mSnapshotVersion = snapshotVersion;
+        mKeychainProtectionParams =
+                Preconditions.checkCollectionElementsNotNull(keychainProtectionParams,
+                        "keychainProtectionParams");
+        mEntryRecoveryData = Preconditions.checkCollectionElementsNotNull(wrappedApplicationKeys,
+                "wrappedApplicationKeys");
+        mEncryptedRecoveryKeyBlob = Preconditions.checkNotNull(encryptedRecoveryKeyBlob);
+    }
+
+    private KeychainSnapshot() {
+
+    }
+
+    /**
+     * Snapshot version for given account. It is incremented when user secret or list of application
+     * keys changes.
+     */
+    public int getSnapshotVersion() {
+        return mSnapshotVersion;
+    }
+
+    /**
+     * UI and key derivation parameters. Note that combination of secrets may be used.
+     */
+    public @NonNull List<KeychainProtectionParameter> getKeychainProtectionParams() {
+        return mKeychainProtectionParams;
+    }
+
+    /**
+     * List of application keys, with key material encrypted by
+     * the recovery key ({@link #getEncryptedRecoveryKeyBlob}).
+     */
+    public @NonNull List<WrappedApplicationKey> getWrappedApplicationKeys() {
+        return mEntryRecoveryData;
+    }
+
+    /**
+     * Recovery key blob, encrypted by user secret and recovery service public key.
+     */
+    public @NonNull byte[] getEncryptedRecoveryKeyBlob() {
+        return mEncryptedRecoveryKeyBlob;
+    }
+
+    public static final Parcelable.Creator<KeychainSnapshot> CREATOR =
+            new Parcelable.Creator<KeychainSnapshot>() {
+        public KeychainSnapshot createFromParcel(Parcel in) {
+            return new KeychainSnapshot(in);
+        }
+
+        public KeychainSnapshot[] newArray(int length) {
+            return new KeychainSnapshot[length];
+        }
+    };
+
+    /**
+     * Builder for creating {@link KeychainSnapshot}.
+     */
+    public static class Builder {
+        private KeychainSnapshot mInstance = new KeychainSnapshot();
+
+        /**
+         * Snapshot version for given account.
+         *
+         * @param snapshotVersion The snapshot version
+         * @return This builder.
+         */
+        public Builder setSnapshotVersion(int snapshotVersion) {
+            mInstance.mSnapshotVersion = snapshotVersion;
+            return this;
+        }
+
+        /**
+         * Sets UI and key derivation parameters
+         *
+         * @param recoveryMetadata The UI and key derivation parameters
+         * @return This builder.
+         */
+        public Builder setKeychainProtectionParams(
+                @NonNull List<KeychainProtectionParameter> recoveryMetadata) {
+            mInstance.mKeychainProtectionParams = recoveryMetadata;
+            return this;
+        }
+
+        /**
+         * List of application keys.
+         *
+         * @param entryRecoveryData List of application keys
+         * @return This builder.
+         */
+        public Builder setWrappedApplicationKeys(List<WrappedApplicationKey> entryRecoveryData) {
+            mInstance.mEntryRecoveryData = entryRecoveryData;
+            return this;
+        }
+
+        /**
+         * Sets recovery key blob
+         *
+         * @param encryptedRecoveryKeyBlob The recovery key blob.
+         * @return This builder.
+         */
+        public Builder setEncryptedRecoveryKeyBlob(@NonNull byte[] encryptedRecoveryKeyBlob) {
+            mInstance.mEncryptedRecoveryKeyBlob = encryptedRecoveryKeyBlob;
+            return this;
+        }
+
+
+        /**
+         * Creates a new {@link KeychainSnapshot} instance.
+         *
+         * @return new instance
+         * @throws NullPointerException if some required fields were not set.
+         */
+        @NonNull public KeychainSnapshot build() {
+            Preconditions.checkCollectionElementsNotNull(mInstance.mKeychainProtectionParams,
+                    "recoveryMetadata");
+            Preconditions.checkCollectionElementsNotNull(mInstance.mEntryRecoveryData,
+                    "entryRecoveryData");
+            Preconditions.checkNotNull(mInstance.mEncryptedRecoveryKeyBlob);
+            return mInstance;
+        }
+    }
+
+    /**
+     * @hide
+     */
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeInt(mSnapshotVersion);
+        out.writeTypedList(mKeychainProtectionParams);
+        out.writeByteArray(mEncryptedRecoveryKeyBlob);
+        out.writeTypedList(mEntryRecoveryData);
+    }
+
+    /**
+     * @hide
+     */
+    protected KeychainSnapshot(Parcel in) {
+        mSnapshotVersion = in.readInt();
+        mKeychainProtectionParams = in.createTypedArrayList(KeychainProtectionParameter.CREATOR);
+        mEncryptedRecoveryKeyBlob = in.createByteArray();
+        mEntryRecoveryData = in.createTypedArrayList(WrappedApplicationKey.CREATOR);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+}
diff --git a/core/java/android/security/keystore/RecoveryData.aidl b/core/java/android/security/keystore/RecoveryData.aidl
deleted file mode 100644
index 4200de1..0000000
--- a/core/java/android/security/keystore/RecoveryData.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2017 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;
-
-/* @hide */
-parcelable RecoveryData;
diff --git a/core/java/android/security/keystore/RecoveryData.java b/core/java/android/security/keystore/RecoveryData.java
deleted file mode 100644
index 897aa18..0000000
--- a/core/java/android/security/keystore/RecoveryData.java
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * Copyright (C) 2017 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.os.Parcel;
-import android.os.Parcelable;
-
-import com.android.internal.util.Preconditions;
-
-import java.util.List;
-
-/**
- * Helper class which returns data necessary to recover keys.
- * Contains
- *
- * <ul>
- * <li>Snapshot version.
- * <li>Recovery metadata with UI and key derivation parameters.
- * <li>List of application keys encrypted by recovery key.
- * <li>Encrypted recovery key.
- * </ul>
- *
- * @hide
- */
-public final class RecoveryData implements Parcelable {
-    private int mSnapshotVersion;
-    private List<RecoveryMetadata> mRecoveryMetadata;
-    private List<EntryRecoveryData> mEntryRecoveryData;
-    private byte[] mEncryptedRecoveryKeyBlob;
-
-    /**
-     * @hide
-     * Deprecated, consider using builder.
-     */
-    public RecoveryData(
-            int snapshotVersion,
-            @NonNull List<RecoveryMetadata> recoveryMetadata,
-            @NonNull List<EntryRecoveryData> entryRecoveryData,
-            @NonNull byte[] encryptedRecoveryKeyBlob) {
-        mSnapshotVersion = snapshotVersion;
-        mRecoveryMetadata =
-                Preconditions.checkCollectionElementsNotNull(recoveryMetadata, "recoveryMetadata");
-        mEntryRecoveryData = Preconditions.checkCollectionElementsNotNull(entryRecoveryData,
-                "entryRecoveryData");
-        mEncryptedRecoveryKeyBlob = Preconditions.checkNotNull(encryptedRecoveryKeyBlob);
-    }
-
-    private RecoveryData() {
-
-    }
-
-    /**
-     * Snapshot version for given account. It is incremented when user secret or list of application
-     * keys changes.
-     */
-    public int getSnapshotVersion() {
-        return mSnapshotVersion;
-    }
-
-    /**
-     * UI and key derivation parameters. Note that combination of secrets may be used.
-     */
-    public @NonNull List<RecoveryMetadata> getRecoveryMetadata() {
-        return mRecoveryMetadata;
-    }
-
-    /**
-     * List of application keys, with key material encrypted by
-     * the recovery key ({@link #getEncryptedRecoveryKeyBlob}).
-     */
-    public @NonNull List<EntryRecoveryData> getEntryRecoveryData() {
-        return mEntryRecoveryData;
-    }
-
-    /**
-     * Recovery key blob, encrypted by user secret and recovery service public key.
-     */
-    public @NonNull byte[] getEncryptedRecoveryKeyBlob() {
-        return mEncryptedRecoveryKeyBlob;
-    }
-
-    public static final Parcelable.Creator<RecoveryData> CREATOR =
-            new Parcelable.Creator<RecoveryData>() {
-        public RecoveryData createFromParcel(Parcel in) {
-            return new RecoveryData(in);
-        }
-
-        public RecoveryData[] newArray(int length) {
-            return new RecoveryData[length];
-        }
-    };
-
-    /**
-     * Builder for creating {@link RecoveryData}.
-     */
-    public static class Builder {
-        private RecoveryData mInstance = new RecoveryData();
-
-        /**
-         * Snapshot version for given account.
-         *
-         * @param snapshotVersion The snapshot version
-         * @return This builder.
-         */
-        public Builder setSnapshotVersion(int snapshotVersion) {
-            mInstance.mSnapshotVersion = snapshotVersion;
-            return this;
-        }
-
-        /**
-         * Sets UI and key derivation parameters
-         *
-         * @param recoveryMetadata The UI and key derivation parameters
-         * @return This builder.
-         */
-        public Builder setRecoveryMetadata(@NonNull List<RecoveryMetadata> recoveryMetadata) {
-            mInstance.mRecoveryMetadata = recoveryMetadata;
-            return this;
-        }
-
-        /**
-         * List of application keys.
-         *
-         * @param entryRecoveryData List of application keys
-         * @return This builder.
-         */
-        public Builder setEntryRecoveryData(List<EntryRecoveryData> entryRecoveryData) {
-            mInstance.mEntryRecoveryData = entryRecoveryData;
-            return this;
-        }
-
-        /**
-         * Sets recovery key blob
-         *
-         * @param encryptedRecoveryKeyBlob The recovery key blob.
-         * @return This builder.
-         */
-        public Builder setEncryptedRecoveryKeyBlob(@NonNull byte[] encryptedRecoveryKeyBlob) {
-            mInstance.mEncryptedRecoveryKeyBlob = encryptedRecoveryKeyBlob;
-            return this;
-        }
-
-
-        /**
-         * Creates a new {@link RecoveryData} instance.
-         *
-         * @return new instance
-         * @throws NullPointerException if some required fields were not set.
-         */
-        public @NonNull RecoveryData build() {
-            Preconditions.checkCollectionElementsNotNull(mInstance.mRecoveryMetadata,
-                    "recoveryMetadata");
-            Preconditions.checkCollectionElementsNotNull(mInstance.mEntryRecoveryData,
-                    "entryRecoveryData");
-            Preconditions.checkNotNull(mInstance.mEncryptedRecoveryKeyBlob);
-            return mInstance;
-        }
-    }
-
-    /**
-     * @hide
-     */
-    @Override
-    public void writeToParcel(Parcel out, int flags) {
-        out.writeInt(mSnapshotVersion);
-        out.writeTypedList(mRecoveryMetadata);
-        out.writeByteArray(mEncryptedRecoveryKeyBlob);
-        out.writeTypedList(mEntryRecoveryData);
-    }
-
-    /**
-     * @hide
-     */
-    protected RecoveryData(Parcel in) {
-        mSnapshotVersion = in.readInt();
-        mRecoveryMetadata = in.createTypedArrayList(RecoveryMetadata.CREATOR);
-        mEncryptedRecoveryKeyBlob = in.createByteArray();
-        mEntryRecoveryData = in.createTypedArrayList(EntryRecoveryData.CREATOR);
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-}
diff --git a/core/java/android/security/keystore/RecoveryManager.java b/core/java/android/security/keystore/RecoveryManager.java
index 99bd284..bddf3e8 100644
--- a/core/java/android/security/keystore/RecoveryManager.java
+++ b/core/java/android/security/keystore/RecoveryManager.java
@@ -99,11 +99,11 @@
      * @return Data necessary to recover keystore.
      * @hide
      */
-    public @NonNull RecoveryData getRecoveryData(@NonNull byte[] account)
+    @NonNull public KeychainSnapshot getRecoveryData(@NonNull byte[] account)
             throws RecoveryManagerException {
         try {
-            RecoveryData recoveryData = mBinder.getRecoveryData(account);
-            return recoveryData;
+            KeychainSnapshot keychainSnapshot = mBinder.getRecoveryData(account);
+            return keychainSnapshot;
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         } catch (ServiceSpecificException e) {
@@ -136,7 +136,7 @@
      * version. Version zero is used, if no snapshots were created for the account.
      *
      * @return Map from recovery agent accounts to snapshot versions.
-     * @see RecoveryData#getSnapshotVersion
+     * @see KeychainSnapshot#getSnapshotVersion
      * @hide
      */
     public @NonNull Map<byte[], Integer> getRecoverySnapshotVersions()
@@ -156,7 +156,7 @@
 
     /**
      * Server parameters used to generate new recovery key blobs. This value will be included in
-     * {@code RecoveryData.getEncryptedRecoveryKeyBlob()}. The same value must be included
+     * {@code KeychainSnapshot.getEncryptedRecoveryKeyBlob()}. The same value must be included
      * in vaultParams {@link #startRecoverySession}
      *
      * @param serverParams included in recovery key blob.
@@ -230,11 +230,11 @@
      * Specifies a set of secret types used for end-to-end keystore encryption. Knowing all of them
      * is necessary to recover data.
      *
-     * @param secretTypes {@link RecoveryMetadata#TYPE_LOCKSCREEN} or {@link
-     *     RecoveryMetadata#TYPE_CUSTOM_PASSWORD}
+     * @param secretTypes {@link KeychainProtectionParameter#TYPE_LOCKSCREEN} or {@link
+     *     KeychainProtectionParameter#TYPE_CUSTOM_PASSWORD}
      */
     public void setRecoverySecretTypes(
-            @NonNull @RecoveryMetadata.UserSecretType int[] secretTypes)
+            @NonNull @KeychainProtectionParameter.UserSecretType int[] secretTypes)
             throws RecoveryManagerException {
         try {
             mBinder.setRecoverySecretTypes(secretTypes);
@@ -247,12 +247,12 @@
 
     /**
      * Defines a set of secret types used for end-to-end keystore encryption. Knowing all of them is
-     * necessary to generate RecoveryData.
+     * necessary to generate KeychainSnapshot.
      *
      * @return list of recovery secret types
-     * @see RecoveryData
+     * @see KeychainSnapshot
      */
-    public @NonNull @RecoveryMetadata.UserSecretType int[] getRecoverySecretTypes()
+    @NonNull public @KeychainProtectionParameter.UserSecretType int[] getRecoverySecretTypes()
             throws RecoveryManagerException {
         try {
             return mBinder.getRecoverySecretTypes();
@@ -271,7 +271,8 @@
      * @return list of recovery secret types
      * @hide
      */
-    public @NonNull @RecoveryMetadata.UserSecretType int[] getPendingRecoverySecretTypes()
+    @NonNull
+    public @KeychainProtectionParameter.UserSecretType int[] getPendingRecoverySecretTypes()
             throws RecoveryManagerException {
         try {
             return mBinder.getPendingRecoverySecretTypes();
@@ -285,14 +286,14 @@
     /**
      * Method notifies KeyStore that a user-generated secret is available. This method generates a
      * symmetric session key which a trusted remote device can use to return a recovery key. Caller
-     * should use {@link RecoveryMetadata#clearSecret} to override the secret value in
+     * should use {@link KeychainProtectionParameter#clearSecret} to override the secret value in
      * memory.
      *
      * @param recoverySecret user generated secret together with parameters necessary to regenerate
      *     it on a new device.
      * @hide
      */
-    public void recoverySecretAvailable(@NonNull RecoveryMetadata recoverySecret)
+    public void recoverySecretAvailable(@NonNull KeychainProtectionParameter recoverySecret)
             throws RecoveryManagerException {
         try {
             mBinder.recoverySecretAvailable(recoverySecret);
@@ -326,7 +327,7 @@
             @NonNull byte[] verifierPublicKey,
             @NonNull byte[] vaultParams,
             @NonNull byte[] vaultChallenge,
-            @NonNull List<RecoveryMetadata> secrets)
+            @NonNull List<KeychainProtectionParameter> secrets)
             throws RecoveryManagerException {
         try {
             byte[] recoveryClaim =
@@ -352,13 +353,13 @@
      * @param recoveryKeyBlob Recovery blob encrypted by symmetric key generated for this session.
      * @param applicationKeys Application keys. Key material can be decrypted using recoveryKeyBlob
      *     and session. KeyStore only uses package names from the application info in {@link
-     *     EntryRecoveryData}. Caller is responsibility to perform certificates check.
+     *     WrappedApplicationKey}. Caller is responsibility to perform certificates check.
      * @return Map from alias to raw key material.
      */
     public Map<String, byte[]> recoverKeys(
             @NonNull String sessionId,
             @NonNull byte[] recoveryKeyBlob,
-            @NonNull List<EntryRecoveryData> applicationKeys)
+            @NonNull List<WrappedApplicationKey> applicationKeys)
             throws RecoveryManagerException {
         try {
             return (Map<String, byte[]>) mBinder.recoverKeys(
diff --git a/core/java/android/security/keystore/RecoveryMetadata.aidl b/core/java/android/security/keystore/RecoveryMetadata.aidl
deleted file mode 100644
index 8e342b4..0000000
--- a/core/java/android/security/keystore/RecoveryMetadata.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2017 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;
-
-/* @hide */
-parcelable RecoveryMetadata;
diff --git a/core/java/android/security/keystore/EntryRecoveryData.aidl b/core/java/android/security/keystore/WrappedApplicationKey.aidl
similarity index 94%
copy from core/java/android/security/keystore/EntryRecoveryData.aidl
copy to core/java/android/security/keystore/WrappedApplicationKey.aidl
index c6c20e3..a6294fe 100644
--- a/core/java/android/security/keystore/EntryRecoveryData.aidl
+++ b/core/java/android/security/keystore/WrappedApplicationKey.aidl
@@ -17,4 +17,4 @@
 package android.security.keystore;
 
 /* @hide */
-parcelable EntryRecoveryData;
+parcelable WrappedApplicationKey;
diff --git a/core/java/android/security/keystore/EntryRecoveryData.java b/core/java/android/security/keystore/WrappedApplicationKey.java
similarity index 78%
rename from core/java/android/security/keystore/EntryRecoveryData.java
rename to core/java/android/security/keystore/WrappedApplicationKey.java
index aaca3fe..522bb95 100644
--- a/core/java/android/security/keystore/EntryRecoveryData.java
+++ b/core/java/android/security/keystore/WrappedApplicationKey.java
@@ -35,16 +35,16 @@
  *
  * @hide
  */
-public final class EntryRecoveryData implements Parcelable {
+public final class WrappedApplicationKey implements Parcelable {
     private String mAlias;
     // The only supported format is AES-256 symmetric key.
     private byte[] mEncryptedKeyMaterial;
 
     /**
-     * Builder for creating {@link EntryRecoveryData}.
+     * Builder for creating {@link WrappedApplicationKey}.
      */
     public static class Builder {
-        private EntryRecoveryData mInstance = new EntryRecoveryData();
+        private WrappedApplicationKey mInstance = new WrappedApplicationKey();
 
         /**
          * Sets Application-specific alias of the key.
@@ -70,19 +70,19 @@
         }
 
         /**
-         * Creates a new {@link EntryRecoveryData} instance.
+         * Creates a new {@link WrappedApplicationKey} instance.
          *
          * @return new instance
          * @throws NullPointerException if some required fields were not set.
          */
-        public @NonNull EntryRecoveryData build() {
+        @NonNull public WrappedApplicationKey build() {
             Preconditions.checkNotNull(mInstance.mAlias);
             Preconditions.checkNotNull(mInstance.mEncryptedKeyMaterial);
             return mInstance;
         }
     }
 
-    private EntryRecoveryData() {
+    private WrappedApplicationKey() {
 
     }
 
@@ -90,7 +90,7 @@
      * Deprecated - consider using Builder.
      * @hide
      */
-    public EntryRecoveryData(@NonNull String alias, @NonNull byte[] encryptedKeyMaterial) {
+    public WrappedApplicationKey(@NonNull String alias, @NonNull byte[] encryptedKeyMaterial) {
         mAlias = Preconditions.checkNotNull(alias);
         mEncryptedKeyMaterial = Preconditions.checkNotNull(encryptedKeyMaterial);
     }
@@ -109,14 +109,14 @@
         return mEncryptedKeyMaterial;
     }
 
-    public static final Parcelable.Creator<EntryRecoveryData> CREATOR =
-            new Parcelable.Creator<EntryRecoveryData>() {
-                public EntryRecoveryData createFromParcel(Parcel in) {
-                    return new EntryRecoveryData(in);
+    public static final Parcelable.Creator<WrappedApplicationKey> CREATOR =
+            new Parcelable.Creator<WrappedApplicationKey>() {
+                public WrappedApplicationKey createFromParcel(Parcel in) {
+                    return new WrappedApplicationKey(in);
                 }
 
-                public EntryRecoveryData[] newArray(int length) {
-                    return new EntryRecoveryData[length];
+                public WrappedApplicationKey[] newArray(int length) {
+                    return new WrappedApplicationKey[length];
                 }
             };
 
@@ -132,7 +132,7 @@
     /**
      * @hide
      */
-    protected EntryRecoveryData(Parcel in) {
+    protected WrappedApplicationKey(Parcel in) {
         mAlias = in.readString();
         mEncryptedKeyMaterial = in.createByteArray();
     }
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index bd3be1b..f0b712b 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -4210,6 +4210,11 @@
      */
     private static boolean sCanFocusZeroSized;
 
+    /**
+     * Always assign focus if a focusable View is available.
+     */
+    private static boolean sAlwaysAssignFocus;
+
     private String mTransitionName;
 
     static class TintInfo {
@@ -4827,6 +4832,8 @@
 
             sCanFocusZeroSized = targetSdkVersion < Build.VERSION_CODES.P;
 
+            sAlwaysAssignFocus = targetSdkVersion < Build.VERSION_CODES.P;
+
             sCompatibilityDone = true;
         }
     }
@@ -7017,8 +7024,8 @@
      * Called when this view wants to give up focus. If focus is cleared
      * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
      * <p>
-     * <strong>Note:</strong> When a View clears focus the framework is trying
-     * to give focus to the first focusable View from the top. Hence, if this
+     * <strong>Note:</strong> When not in touch-mode, the framework will try to give focus
+     * to the first focusable View from the top after focus is cleared. Hence, if this
      * View is the first from the top that can take focus, then all callbacks
      * related to clearing focus will be invoked after which the framework will
      * give focus to this view.
@@ -7029,7 +7036,8 @@
             System.out.println(this + " clearFocus()");
         }
 
-        clearFocusInternal(null, true, true);
+        final boolean refocus = sAlwaysAssignFocus || !isInTouchMode();
+        clearFocusInternal(null, true, refocus);
     }
 
     /**
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index fe3b696..30f584c 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -530,7 +530,7 @@
         mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
 
         if (!sCompatibilityDone) {
-            sAlwaysAssignFocus = true;
+            sAlwaysAssignFocus = mTargetSdkVersion < Build.VERSION_CODES.P;
 
             sCompatibilityDone = true;
         }
@@ -2337,7 +2337,7 @@
         }
 
         if (mFirst) {
-            if (sAlwaysAssignFocus) {
+            if (sAlwaysAssignFocus || !isInTouchMode()) {
                 // handle first focus request
                 if (DEBUG_INPUT_RESIZE) {
                     Log.v(mTag, "First: mView.hasFocus()=" + mView.hasFocus());
@@ -3608,7 +3608,7 @@
         checkThread();
         if (mView != null) {
             if (!mView.hasFocus()) {
-                if (sAlwaysAssignFocus) {
+                if (sAlwaysAssignFocus || !isInTouchMode()) {
                     v.requestFocus();
                 }
             } else {
@@ -4211,10 +4211,7 @@
 
             // find the best view to give focus to in this brave new non-touch-mode
             // world
-            final View focused = focusSearch(null, View.FOCUS_DOWN);
-            if (focused != null) {
-                return focused.requestFocus(View.FOCUS_DOWN);
-            }
+            return mView.restoreDefaultFocus();
         }
         return false;
     }
diff --git a/core/java/com/android/internal/print/DualDumpOutputStream.java b/core/java/com/android/internal/print/DualDumpOutputStream.java
index f7826cc..4b10ef2 100644
--- a/core/java/com/android/internal/print/DualDumpOutputStream.java
+++ b/core/java/com/android/internal/print/DualDumpOutputStream.java
@@ -18,11 +18,10 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.util.ArrayMap;
+import android.util.Log;
 import android.util.proto.ProtoOutputStream;
 
 import com.android.internal.util.IndentingPrintWriter;
-import com.android.internal.util.Preconditions;
 
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
@@ -36,6 +35,8 @@
  * <p>This mirrors the interface of {@link ProtoOutputStream}.
  */
 public class DualDumpOutputStream {
+    private static final String LOG_TAG = DualDumpOutputStream.class.getSimpleName();
+
     // When writing to a proto, the proto
     private final @Nullable ProtoOutputStream mProtoStream;
 
@@ -44,18 +45,18 @@
     // Temporary storage of data when printing to mIpw
     private final LinkedList<DumpObject> mDumpObjects = new LinkedList<>();
 
-    private static abstract class DumpAble {
+    private static abstract class Dumpable {
         final String name;
 
-        private DumpAble(String name) {
+        private Dumpable(String name) {
             this.name = name;
         }
 
         abstract void print(IndentingPrintWriter ipw, boolean printName);
     }
 
-    private static class DumpObject extends DumpAble {
-        private final LinkedHashMap<String, ArrayList<DumpAble>> mSubObjects = new LinkedHashMap<>();
+    private static class DumpObject extends Dumpable {
+        private final LinkedHashMap<String, ArrayList<Dumpable>> mSubObjects = new LinkedHashMap<>();
 
         private DumpObject(String name) {
             super(name);
@@ -70,7 +71,7 @@
             }
             ipw.increaseIndent();
 
-            for (ArrayList<DumpAble> subObject: mSubObjects.values()) {
+            for (ArrayList<Dumpable> subObject: mSubObjects.values()) {
                 int numDumpables = subObject.size();
 
                 if (numDumpables == 1) {
@@ -100,8 +101,8 @@
          * @param fieldName name of the field added
          * @param d The dumpable to add
          */
-        public void add(String fieldName, DumpAble d) {
-            ArrayList<DumpAble> l = mSubObjects.get(fieldName);
+        public void add(String fieldName, Dumpable d) {
+            ArrayList<Dumpable> l = mSubObjects.get(fieldName);
 
             if (l == null) {
                 l = new ArrayList<>(1);
@@ -112,7 +113,7 @@
         }
     }
 
-    private static class DumpField extends DumpAble {
+    private static class DumpField extends Dumpable {
         private final String mValue;
 
         private DumpField(String name, String value) {
@@ -139,7 +140,10 @@
      */
     public DualDumpOutputStream(@Nullable ProtoOutputStream proto,
             @Nullable IndentingPrintWriter ipw) {
-        Preconditions.checkArgument((proto == null) != (ipw == null));
+        if ((proto == null) == (ipw == null)) {
+            Log.e(LOG_TAG, "Cannot dump to clear text and proto at once. Ignoring proto");
+            proto = null;
+        }
 
         mProtoStream = proto;
         mIpw = ipw;
@@ -213,7 +217,7 @@
             DumpObject d = new DumpObject(fieldName);
             mDumpObjects.getLast().add(fieldName, d);
             mDumpObjects.addLast(d);
-            return 0;
+            return System.identityHashCode(d);
         }
     }
 
@@ -221,6 +225,10 @@
         if (mProtoStream != null) {
             mProtoStream.end(token);
         } else {
+            if (System.identityHashCode(mDumpObjects.getLast()) != token) {
+                Log.w(LOG_TAG, "Unexpected token for ending " + mDumpObjects.getLast().name
+                                + " at " + Arrays.toString(Thread.currentThread().getStackTrace()));
+            }
             mDumpObjects.removeLast();
         }
     }
@@ -250,7 +258,10 @@
      * @param nestedState The state of the dump
      */
     public void writeNested(@NonNull String fieldName, byte[] nestedState) {
-        Preconditions.checkNotNull(mIpw);
+        if (mIpw == null) {
+            Log.w(LOG_TAG, "writeNested does not work for proto logging");
+            return;
+        }
 
         mDumpObjects.getLast().add(fieldName,
                 new DumpField(fieldName, (new String(nestedState, StandardCharsets.UTF_8)).trim()));
diff --git a/core/java/com/android/internal/widget/ILockSettings.aidl b/core/java/com/android/internal/widget/ILockSettings.aidl
index 31d22e0..b2bab6f 100644
--- a/core/java/com/android/internal/widget/ILockSettings.aidl
+++ b/core/java/com/android/internal/widget/ILockSettings.aidl
@@ -19,9 +19,9 @@
 import android.app.PendingIntent;
 import android.app.trust.IStrongAuthTracker;
 import android.os.Bundle;
-import android.security.keystore.EntryRecoveryData;
-import android.security.keystore.RecoveryData;
-import android.security.keystore.RecoveryMetadata;
+import android.security.keystore.WrappedApplicationKey;
+import android.security.keystore.KeychainSnapshot;
+import android.security.keystore.KeychainProtectionParameter;
 import com.android.internal.widget.ICheckCredentialProgressCallback;
 import com.android.internal.widget.VerifyCredentialResponse;
 
@@ -64,7 +64,7 @@
     // {@code ServiceSpecificException} may be thrown to signal an error, which caller can
     // convert to  {@code RecoveryManagerException}.
     void initRecoveryService(in String rootCertificateAlias, in byte[] signedPublicKeyList);
-    RecoveryData getRecoveryData(in byte[] account);
+    KeychainSnapshot getRecoveryData(in byte[] account);
     byte[] generateAndStoreKey(String alias);
     void removeKey(String alias);
     void setSnapshotCreatedPendingIntent(in PendingIntent intent);
@@ -75,10 +75,10 @@
     void setRecoverySecretTypes(in int[] secretTypes);
     int[] getRecoverySecretTypes();
     int[] getPendingRecoverySecretTypes();
-    void recoverySecretAvailable(in RecoveryMetadata recoverySecret);
+    void recoverySecretAvailable(in KeychainProtectionParameter recoverySecret);
     byte[] startRecoverySession(in String sessionId,
             in byte[] verifierPublicKey, in byte[] vaultParams, in byte[] vaultChallenge,
-            in List<RecoveryMetadata> secrets);
+            in List<KeychainProtectionParameter> secrets);
     Map/*<String, byte[]>*/ recoverKeys(in String sessionId, in byte[] recoveryKeyBlob,
-            in List<EntryRecoveryData> applicationKeys);
+            in List<WrappedApplicationKey> applicationKeys);
 }
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index 79aa5ac..685fcaf 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -237,10 +237,22 @@
 
     // Create the codec.
     NinePatchPeeker peeker;
-    std::unique_ptr<SkAndroidCodec> codec = SkAndroidCodec::MakeFromStream(
-            std::move(stream), &peeker);
-    if (!codec.get()) {
-        return nullObjectReturn("SkAndroidCodec::MakeFromStream returned null");
+    std::unique_ptr<SkAndroidCodec> codec;
+    {
+        SkCodec::Result result;
+        std::unique_ptr<SkCodec> c = SkCodec::MakeFromStream(std::move(stream), &result,
+                                                             &peeker);
+        if (!c) {
+            SkString msg;
+            msg.printf("Failed to create image decoder with message '%s'",
+                       SkCodec::ResultToString(result));
+            return nullObjectReturn(msg.c_str());
+        }
+
+        codec = SkAndroidCodec::MakeFromCodec(std::move(c));
+        if (!codec) {
+            return nullObjectReturn("SkAndroidCodec::MakeFromCodec returned null");
+        }
     }
 
     // Do not allow ninepatch decodes to 565.  In the past, decodes to 565
diff --git a/core/jni/android/graphics/ImageDecoder.cpp b/core/jni/android/graphics/ImageDecoder.cpp
index ea9c772..249202a 100644
--- a/core/jni/android/graphics/ImageDecoder.cpp
+++ b/core/jni/android/graphics/ImageDecoder.cpp
@@ -77,11 +77,27 @@
         return nullptr;
     }
     std::unique_ptr<ImageDecoder> decoder(new ImageDecoder);
-    decoder->mCodec = SkAndroidCodec::MakeFromStream(std::move(stream), &decoder->mPeeker);
+    SkCodec::Result result;
+    auto codec = SkCodec::MakeFromStream(std::move(stream), &result, &decoder->mPeeker);
+    if (!codec) {
+        switch (result) {
+            case SkCodec::kIncompleteInput:
+                env->ThrowNew(gIncomplete_class, "Incomplete input");
+                break;
+            default:
+                SkString msg;
+                msg.printf("Failed to create image decoder with message '%s'",
+                           SkCodec::ResultToString(result));
+                doThrowIOE(env, msg.c_str());
+                break;
+        }
+
+        return nullptr;
+    }
+
+    decoder->mCodec = SkAndroidCodec::MakeFromCodec(std::move(codec));
     if (!decoder->mCodec.get()) {
-        // FIXME: (b/71578461) Use the error message from
-        // SkCodec::MakeFromStream to report a more informative error message.
-        doThrowIOE(env, "Failed to create an SkCodec");
+        doThrowIOE(env, "Could not create AndroidCodec");
         return nullptr;
     }
 
diff --git a/graphics/java/android/graphics/ImageDecoder.java b/graphics/java/android/graphics/ImageDecoder.java
index 419e2b7..d13e05c 100644
--- a/graphics/java/android/graphics/ImageDecoder.java
+++ b/graphics/java/android/graphics/ImageDecoder.java
@@ -239,11 +239,12 @@
     };
 
     /**
-     *  Supplied to onPartialImage if the provided data is incomplete.
+     *  Used if the provided data is incomplete.
      *
-     *  Will never be thrown by ImageDecoder.
+     *  May be thrown if there is nothing to display.
      *
-     *  There may be a partial image to display.
+     *  If supplied to onPartialImage, there may be a correct partial image to
+     *  display.
      */
     public static class IncompleteException extends IOException {};
 
diff --git a/packages/PrintSpooler/src/com/android/printspooler/model/PrintSpoolerService.java b/packages/PrintSpooler/src/com/android/printspooler/model/PrintSpoolerService.java
index 074f9ef..6c74418 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/model/PrintSpoolerService.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/model/PrintSpoolerService.java
@@ -161,11 +161,11 @@
         return new PrintSpooler();
     }
 
-    private void dumpLocked(@NonNull DualDumpOutputStream proto) {
+    private void dumpLocked(@NonNull DualDumpOutputStream dumpStream) {
         int numPrintJobs = mPrintJobs.size();
         for (int i = 0; i < numPrintJobs; i++) {
-            writePrintJobInfo(this, proto, "print_jobs", PrintSpoolerInternalStateProto.PRINT_JOBS,
-                    mPrintJobs.get(i));
+            writePrintJobInfo(this, dumpStream, "print_jobs",
+                    PrintSpoolerInternalStateProto.PRINT_JOBS, mPrintJobs.get(i));
         }
 
         File[] files = getFilesDir().listFiles();
@@ -173,8 +173,8 @@
             for (int i = 0; i < files.length; i++) {
                 File file = files[i];
                 if (file.isFile() && file.getName().startsWith(PRINT_JOB_FILE_PREFIX)) {
-                    proto.write("print_job_files", PrintSpoolerInternalStateProto.PRINT_JOB_FILES,
-                            file.getName());
+                    dumpStream.write("print_job_files",
+                            PrintSpoolerInternalStateProto.PRINT_JOB_FILES, file.getName());
                 }
             }
         }
@@ -184,13 +184,13 @@
             for (String approvedService : approvedPrintServices) {
                 ComponentName componentName = ComponentName.unflattenFromString(approvedService);
                 if (componentName != null) {
-                    writeComponentName(proto, "approved_services",
+                    writeComponentName(dumpStream, "approved_services",
                             PrintSpoolerInternalStateProto.APPROVED_SERVICES, componentName);
                 }
             }
         }
 
-        proto.flush();
+        dumpStream.flush();
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarView.java
index 6cbbd6c..e5a311d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarView.java
@@ -17,11 +17,15 @@
 package com.android.systemui.statusbar.car;
 
 import android.content.Context;
+import android.graphics.Canvas;
 import android.util.AttributeSet;
+import android.view.MotionEvent;
 import android.view.View;
 import android.widget.LinearLayout;
 
 import com.android.systemui.R;
+import com.android.systemui.plugins.statusbar.phone.NavGesture;
+import com.android.systemui.statusbar.phone.NavigationBarGestureHelper;
 import com.android.systemui.statusbar.phone.NavigationBarView;
 
 /**
@@ -72,4 +76,68 @@
         // Calling setNavigationIconHints in the base class will result in a NPE as the car
         // navigation bar does not have a back button.
     }
+
+    @Override
+    public void onPluginConnected(NavGesture plugin, Context context) {
+        // set to null version of the plugin ignoring incoming arg.
+        super.onPluginConnected(new NullNavGesture(), context);
+    }
+
+    @Override
+    public void onPluginDisconnected(NavGesture plugin) {
+        // reinstall the null nav gesture plugin
+        super.onPluginConnected(new NullNavGesture(), getContext());
+    }
+
+    /**
+     * Null object pattern to work around expectations of the base class.
+     * This is a temporary solution to have the car system ui working.
+     * Already underway is a refactor of they car sys ui as to not use this class
+     * hierarchy.
+     */
+    private static class NullNavGesture implements NavGesture {
+        @Override
+        public GestureHelper getGestureHelper() {
+            return new GestureHelper() {
+                @Override
+                public boolean onTouchEvent(MotionEvent event) {
+                    return false;
+                }
+
+                @Override
+                public boolean onInterceptTouchEvent(MotionEvent event) {
+                    return false;
+                }
+
+                @Override
+                public void setBarState(boolean vertical, boolean isRtl) {
+                }
+
+                @Override
+                public void onDraw(Canvas canvas) {
+                }
+
+                @Override
+                public void onDarkIntensityChange(float intensity) {
+                }
+
+                @Override
+                public void onLayout(boolean changed, int left, int top, int right, int bottom) {
+                }
+            };
+        }
+
+        @Override
+        public int getVersion() {
+            return 0;
+        }
+
+        @Override
+        public void onCreate(Context sysuiContext, Context pluginContext) {
+        }
+
+        @Override
+        public void onDestroy() {
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java
index 9d228c3..46a35ec 100644
--- a/services/core/java/com/android/server/IpSecService.java
+++ b/services/core/java/com/android/server/IpSecService.java
@@ -1235,8 +1235,8 @@
      * reserved for future improved input validation.
      */
     @Override
-    public synchronized void removeTransportModeTransforms(
-            ParcelFileDescriptor socket, int resourceId) throws RemoteException {
+    public synchronized void removeTransportModeTransforms(ParcelFileDescriptor socket)
+            throws RemoteException {
         try {
             mSrvConfig
                     .getNetdInstance()
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index dfe89e0..8cff20c 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -13674,7 +13674,8 @@
      * not.
      */
     private void enforceSystemHasVrFeature() {
-        if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_VR_MODE)) {
+        if (!mContext.getPackageManager().hasSystemFeature(
+                PackageManager.FEATURE_VR_MODE_HIGH_PERFORMANCE)) {
             throw new UnsupportedOperationException("VR mode not supported on this device!");
         }
     }
@@ -13733,9 +13734,7 @@
 
     @Override
     public int setVrMode(IBinder token, boolean enabled, ComponentName packageName) {
-        if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_VR_MODE)) {
-            throw new UnsupportedOperationException("VR mode not supported on this device!");
-        }
+        enforceSystemHasVrFeature();
 
         final VrManagerInternal vrService = LocalServices.getService(VrManagerInternal.class);
 
@@ -13767,9 +13766,7 @@
 
     @Override
     public boolean isVrModePackageEnabled(ComponentName packageName) {
-        if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_VR_MODE)) {
-            throw new UnsupportedOperationException("VR mode not supported on this device!");
-        }
+        enforceSystemHasVrFeature();
 
         final VrManagerInternal vrService = LocalServices.getService(VrManagerInternal.class);
 
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index db94028..879c024 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -63,7 +63,6 @@
 import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.os.ServiceManager;
-import android.os.ServiceSpecificException;
 import android.os.ShellCallback;
 import android.os.StrictMode;
 import android.os.SystemProperties;
@@ -78,11 +77,10 @@
 import android.security.keystore.AndroidKeyStoreProvider;
 import android.security.keystore.KeyProperties;
 import android.security.keystore.KeyProtection;
+import android.security.keystore.KeychainProtectionParameter;
 import android.security.keystore.UserNotAuthenticatedException;
-import android.security.keystore.EntryRecoveryData;
-import android.security.keystore.RecoveryData;
-import android.security.keystore.RecoveryMetadata;
-import android.security.keystore.RecoveryManagerException;
+import android.security.keystore.WrappedApplicationKey;
+import android.security.keystore.KeychainSnapshot;
 import android.service.gatekeeper.GateKeeperResponse;
 import android.service.gatekeeper.IGateKeeperService;
 import android.text.TextUtils;
@@ -1970,7 +1968,7 @@
     }
 
     @Override
-    public RecoveryData getRecoveryData(@NonNull byte[] account) throws RemoteException {
+    public KeychainSnapshot getRecoveryData(@NonNull byte[] account) throws RemoteException {
         return mRecoverableKeyStoreManager.getRecoveryData(account);
     }
 
@@ -1999,7 +1997,7 @@
     }
 
     @Override
-    public void setRecoverySecretTypes(@NonNull @RecoveryMetadata.UserSecretType
+    public void setRecoverySecretTypes(@NonNull @KeychainProtectionParameter.UserSecretType
             int[] secretTypes) throws RemoteException {
         mRecoverableKeyStoreManager.setRecoverySecretTypes(secretTypes);
     }
@@ -2016,7 +2014,7 @@
     }
 
     @Override
-    public void recoverySecretAvailable(@NonNull RecoveryMetadata recoverySecret)
+    public void recoverySecretAvailable(@NonNull KeychainProtectionParameter recoverySecret)
             throws RemoteException {
         mRecoverableKeyStoreManager.recoverySecretAvailable(recoverySecret);
     }
@@ -2024,7 +2022,7 @@
     @Override
     public byte[] startRecoverySession(@NonNull String sessionId,
             @NonNull byte[] verifierPublicKey, @NonNull byte[] vaultParams,
-            @NonNull byte[] vaultChallenge, @NonNull List<RecoveryMetadata> secrets)
+            @NonNull byte[] vaultChallenge, @NonNull List<KeychainProtectionParameter> secrets)
             throws RemoteException {
         return mRecoverableKeyStoreManager.startRecoverySession(sessionId, verifierPublicKey,
                 vaultParams, vaultChallenge, secrets);
@@ -2032,7 +2030,7 @@
 
     @Override
     public Map<String, byte[]> recoverKeys(@NonNull String sessionId,
-            @NonNull byte[] recoveryKeyBlob, @NonNull List<EntryRecoveryData> applicationKeys)
+            @NonNull byte[] recoveryKeyBlob, @NonNull List<WrappedApplicationKey> applicationKeys)
             throws RemoteException {
         return mRecoverableKeyStoreManager.recoverKeys(
                 sessionId, recoveryKeyBlob, applicationKeys);
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java
index 5fe11b1..38745f6 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java
@@ -16,15 +16,14 @@
 
 package com.android.server.locksettings.recoverablekeystore;
 
-import static android.security.keystore.RecoveryMetadata.TYPE_LOCKSCREEN;
+import static android.security.keystore.KeychainProtectionParameter.TYPE_LOCKSCREEN;
 
-import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
 import android.security.keystore.KeyDerivationParams;
-import android.security.keystore.EntryRecoveryData;
-import android.security.keystore.RecoveryData;
-import android.security.keystore.RecoveryMetadata;
+import android.security.keystore.KeychainProtectionParameter;
+import android.security.keystore.KeychainSnapshot;
+import android.security.keystore.WrappedApplicationKey;
 import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -251,12 +250,12 @@
         }
         // TODO: store raw data in RecoveryServiceMetadataEntry and generate Parcelables later
         // TODO: use Builder.
-        RecoveryMetadata metadata = new RecoveryMetadata(
+        KeychainProtectionParameter metadata = new KeychainProtectionParameter(
                 /*userSecretType=*/ TYPE_LOCKSCREEN,
                 /*lockScreenUiFormat=*/ getUiFormat(mCredentialType, mCredential),
                 /*keyDerivationParams=*/ KeyDerivationParams.createSha256Params(salt),
                 /*secret=*/ new byte[0]);
-        ArrayList<RecoveryMetadata> metadataList = new ArrayList<>();
+        ArrayList<KeychainProtectionParameter> metadataList = new ArrayList<>();
         metadataList.add(metadata);
 
         int snapshotVersion = incrementSnapshotVersion(recoveryAgentUid);
@@ -265,7 +264,7 @@
         mRecoverableKeyStoreDb.setShouldCreateSnapshot(mUserId, recoveryAgentUid, false);
 
         // TODO: use Builder.
-        mRecoverySnapshotStorage.put(recoveryAgentUid, new RecoveryData(
+        mRecoverySnapshotStorage.put(recoveryAgentUid, new KeychainSnapshot(
                 snapshotVersion,
                 /*recoveryMetadata=*/ metadataList,
                 /*applicationKeyBlobs=*/ createApplicationKeyEntries(encryptedApplicationKeys),
@@ -308,7 +307,7 @@
      */
     private boolean shoudCreateSnapshot(int recoveryAgentUid) {
         int[] types = mRecoverableKeyStoreDb.getRecoverySecretTypes(mUserId, recoveryAgentUid);
-        if (!ArrayUtils.contains(types, RecoveryMetadata.TYPE_LOCKSCREEN)) {
+        if (!ArrayUtils.contains(types, KeychainProtectionParameter.TYPE_LOCKSCREEN)) {
             // Only lockscreen type is supported.
             // We will need to pass extra argument to KeySyncTask to support custom pass phrase.
             return false;
@@ -331,14 +330,14 @@
      * @return The format - either pattern, pin, or password.
      */
     @VisibleForTesting
-    @RecoveryMetadata.LockScreenUiFormat static int getUiFormat(
+    @KeychainProtectionParameter.LockScreenUiFormat static int getUiFormat(
             int credentialType, String credential) {
         if (credentialType == LockPatternUtils.CREDENTIAL_TYPE_PATTERN) {
-            return RecoveryMetadata.TYPE_PATTERN;
+            return KeychainProtectionParameter.TYPE_PATTERN;
         } else if (isPin(credential)) {
-            return RecoveryMetadata.TYPE_PIN;
+            return KeychainProtectionParameter.TYPE_PIN;
         } else {
-            return RecoveryMetadata.TYPE_PASSWORD;
+            return KeychainProtectionParameter.TYPE_PASSWORD;
         }
     }
 
@@ -401,12 +400,12 @@
         return keyGenerator.generateKey();
     }
 
-    private static List<EntryRecoveryData> createApplicationKeyEntries(
+    private static List<WrappedApplicationKey> createApplicationKeyEntries(
             Map<String, byte[]> encryptedApplicationKeys) {
-        ArrayList<EntryRecoveryData> keyEntries = new ArrayList<>();
+        ArrayList<WrappedApplicationKey> keyEntries = new ArrayList<>();
         for (String alias : encryptedApplicationKeys.keySet()) {
             keyEntries.add(
-                    new EntryRecoveryData(
+                    new WrappedApplicationKey(
                             alias,
                             encryptedApplicationKeys.get(alias)));
         }
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
index 7658178..f14af4b 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
@@ -34,9 +34,9 @@
 import android.os.ServiceSpecificException;
 import android.os.UserHandle;
 
-import android.security.keystore.EntryRecoveryData;
-import android.security.keystore.RecoveryData;
-import android.security.keystore.RecoveryMetadata;
+import android.security.keystore.KeychainProtectionParameter;
+import android.security.keystore.KeychainSnapshot;
+import android.security.keystore.WrappedApplicationKey;
 import android.security.keystore.RecoveryManager;
 import android.util.Log;
 
@@ -45,7 +45,6 @@
 import com.android.server.locksettings.recoverablekeystore.storage.RecoverySessionStorage;
 import com.android.server.locksettings.recoverablekeystore.storage.RecoverySnapshotStorage;
 
-import java.nio.charset.StandardCharsets;
 import java.security.InvalidKeyException;
 import java.security.KeyStoreException;
 import java.security.KeyFactory;
@@ -171,11 +170,12 @@
      * @return recovery data
      * @hide
      */
-    public @NonNull RecoveryData getRecoveryData(@NonNull byte[] account)
+    public @NonNull
+    KeychainSnapshot getRecoveryData(@NonNull byte[] account)
             throws RemoteException {
         checkRecoverKeyStorePermission();
         int uid = Binder.getCallingUid();
-        RecoveryData snapshot = mSnapshotStorage.get(uid);
+        KeychainSnapshot snapshot = mSnapshotStorage.get(uid);
         if (snapshot == null) {
             throw new ServiceSpecificException(ERROR_NO_SNAPSHOT_PENDING);
         }
@@ -257,7 +257,7 @@
      * @hide
      */
     public void setRecoverySecretTypes(
-            @NonNull @RecoveryMetadata.UserSecretType int[] secretTypes)
+            @NonNull @KeychainProtectionParameter.UserSecretType int[] secretTypes)
             throws RemoteException {
         checkRecoverKeyStorePermission();
         int userId = UserHandle.getCallingUserId();
@@ -292,9 +292,9 @@
     }
 
     public void recoverySecretAvailable(
-            @NonNull RecoveryMetadata recoverySecret) throws RemoteException {
+            @NonNull KeychainProtectionParameter recoverySecret) throws RemoteException {
         int uid = Binder.getCallingUid();
-        if (recoverySecret.getLockScreenUiFormat() == RecoveryMetadata.TYPE_LOCKSCREEN) {
+        if (recoverySecret.getLockScreenUiFormat() == KeychainProtectionParameter.TYPE_LOCKSCREEN) {
             throw new SecurityException(
                     "Caller " + uid + " is not allowed to set lock screen secret");
         }
@@ -320,13 +320,13 @@
             @NonNull byte[] verifierPublicKey,
             @NonNull byte[] vaultParams,
             @NonNull byte[] vaultChallenge,
-            @NonNull List<RecoveryMetadata> secrets)
+            @NonNull List<KeychainProtectionParameter> secrets)
             throws RemoteException {
         checkRecoverKeyStorePermission();
         int uid = Binder.getCallingUid();
 
         if (secrets.size() != 1) {
-            throw new UnsupportedOperationException("Only a single RecoveryMetadata is supported");
+            throw new UnsupportedOperationException("Only a single KeychainProtectionParameter is supported");
         }
 
         PublicKey publicKey;
@@ -384,7 +384,7 @@
     public Map<String, byte[]> recoverKeys(
             @NonNull String sessionId,
             @NonNull byte[] encryptedRecoveryKey,
-            @NonNull List<EntryRecoveryData> applicationKeys)
+            @NonNull List<WrappedApplicationKey> applicationKeys)
             throws RemoteException {
         checkRecoverKeyStorePermission();
         int uid = Binder.getCallingUid();
@@ -474,9 +474,9 @@
      */
     private Map<String, byte[]> recoverApplicationKeys(
             @NonNull byte[] recoveryKey,
-            @NonNull List<EntryRecoveryData> applicationKeys) throws RemoteException {
+            @NonNull List<WrappedApplicationKey> applicationKeys) throws RemoteException {
         HashMap<String, byte[]> keyMaterialByAlias = new HashMap<>();
-        for (EntryRecoveryData applicationKey : applicationKeys) {
+        for (WrappedApplicationKey applicationKey : applicationKeys) {
             String alias = applicationKey.getAlias();
             byte[] encryptedKeyMaterial = applicationKey.getEncryptedKeyMaterial();
 
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDb.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDb.java
index eb2da80..8bba212 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDb.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDb.java
@@ -404,7 +404,7 @@
     /**
      * Updates the list of user secret types used for end-to-end encryption.
      * If no secret types are set, recovery snapshot will not be created.
-     * See {@code RecoveryMetadata}
+     * See {@code KeychainProtectionParameter}
      *
      * @param userId The userId of the profile the application is running under.
      * @param uid The uid of the application.
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverySnapshotStorage.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverySnapshotStorage.java
index 158b1e3..62bb41e 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverySnapshotStorage.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverySnapshotStorage.java
@@ -17,7 +17,7 @@
 package com.android.server.locksettings.recoverablekeystore.storage;
 
 import android.annotation.Nullable;
-import android.security.keystore.RecoveryData;
+import android.security.keystore.KeychainSnapshot;
 import android.util.SparseArray;
 
 import com.android.internal.annotations.GuardedBy;
@@ -34,12 +34,12 @@
  */
 public class RecoverySnapshotStorage {
     @GuardedBy("this")
-    private final SparseArray<RecoveryData> mSnapshotByUid = new SparseArray<>();
+    private final SparseArray<KeychainSnapshot> mSnapshotByUid = new SparseArray<>();
 
     /**
      * Sets the latest {@code snapshot} for the recovery agent {@code uid}.
      */
-    public synchronized void put(int uid, RecoveryData snapshot) {
+    public synchronized void put(int uid, KeychainSnapshot snapshot) {
         mSnapshotByUid.put(uid, snapshot);
     }
 
@@ -47,7 +47,7 @@
      * Returns the latest snapshot for the recovery agent {@code uid}, or null if none exists.
      */
     @Nullable
-    public synchronized RecoveryData get(int uid) {
+    public synchronized KeychainSnapshot get(int uid) {
         return mSnapshotByUid.get(uid);
     }
 
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 0d9d85f..4e29935 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -12096,6 +12096,11 @@
         final DeviceAdminInfo incomingDeviceInfo = findAdmin(target, callingUserId,
                 /* throwForMissingPermission= */ true);
         checkActiveAdminPrecondition(target, incomingDeviceInfo, policy);
+        if (!incomingDeviceInfo.getActivityInfo().metaData
+                .getBoolean(DeviceAdminReceiver.SUPPORT_TRANSFER_OWNERSHIP_META_DATA, false)) {
+            throw new IllegalArgumentException("Provided target does not support "
+                    + "ownership transfer.");
+        }
 
         final long id = mInjector.binderClearCallingIdentity();
         try {
diff --git a/services/print/java/com/android/server/print/PrintManagerService.java b/services/print/java/com/android/server/print/PrintManagerService.java
index 1dc9d26..cd4e8f9 100644
--- a/services/print/java/com/android/server/print/PrintManagerService.java
+++ b/services/print/java/com/android/server/print/PrintManagerService.java
@@ -685,16 +685,16 @@
             }
         }
 
-        private void dump(@NonNull DualDumpOutputStream proto,
+        private void dump(@NonNull DualDumpOutputStream dumpStream,
                 @NonNull ArrayList<UserState> userStatesToDump) {
             final int userStateCount = userStatesToDump.size();
             for (int i = 0; i < userStateCount; i++) {
-                long token = proto.start("user_states", PrintServiceDumpProto.USER_STATES);
-                userStatesToDump.get(i).dump(proto);
-                proto.end(token);
+                long token = dumpStream.start("user_states", PrintServiceDumpProto.USER_STATES);
+                userStatesToDump.get(i).dump(dumpStream);
+                dumpStream.end(token);
             }
 
-            proto.flush();
+            dumpStream.flush();
         }
 
         private void registerContentObservers() {
diff --git a/services/print/java/com/android/server/print/RemotePrintSpooler.java b/services/print/java/com/android/server/print/RemotePrintSpooler.java
index 5520255..a69baa1 100644
--- a/services/print/java/com/android/server/print/RemotePrintSpooler.java
+++ b/services/print/java/com/android/server/print/RemotePrintSpooler.java
@@ -556,18 +556,18 @@
         }
     }
 
-    public void dump(@NonNull DualDumpOutputStream proto) {
+    public void dump(@NonNull DualDumpOutputStream dumpStream) {
         synchronized (mLock) {
-            proto.write("is_destroyed", PrintSpoolerStateProto.IS_DESTROYED, mDestroyed);
-            proto.write("is_bound", PrintSpoolerStateProto.IS_BOUND, mRemoteInstance != null);
+            dumpStream.write("is_destroyed", PrintSpoolerStateProto.IS_DESTROYED, mDestroyed);
+            dumpStream.write("is_bound", PrintSpoolerStateProto.IS_BOUND, mRemoteInstance != null);
         }
 
         try {
-            if (proto.isProto()) {
-                proto.write(null, PrintSpoolerStateProto.INTERNAL_STATE,
+            if (dumpStream.isProto()) {
+                dumpStream.write(null, PrintSpoolerStateProto.INTERNAL_STATE,
                         TransferPipe.dumpAsync(getRemoteInstanceLazy().asBinder(), "--proto"));
             } else {
-                proto.writeNested("internal_state", TransferPipe.dumpAsync(
+                dumpStream.writeNested("internal_state", TransferPipe.dumpAsync(
                         getRemoteInstanceLazy().asBinder()));
             }
         } catch (IOException | TimeoutException | RemoteException | InterruptedException e) {
diff --git a/services/print/java/com/android/server/print/UserState.java b/services/print/java/com/android/server/print/UserState.java
index 318e481..e2808e8 100644
--- a/services/print/java/com/android/server/print/UserState.java
+++ b/services/print/java/com/android/server/print/UserState.java
@@ -815,61 +815,63 @@
         mDestroyed = true;
     }
 
-    public void dump(@NonNull DualDumpOutputStream proto) {
+    public void dump(@NonNull DualDumpOutputStream dumpStream) {
         synchronized (mLock) {
-            proto.write("user_id", PrintUserStateProto.USER_ID, mUserId);
+            dumpStream.write("user_id", PrintUserStateProto.USER_ID, mUserId);
 
             final int installedServiceCount = mInstalledServices.size();
             for (int i = 0; i < installedServiceCount; i++) {
-                long token = proto.start("installed_services",
+                long token = dumpStream.start("installed_services",
                         PrintUserStateProto.INSTALLED_SERVICES);
                 PrintServiceInfo installedService = mInstalledServices.get(i);
 
                 ResolveInfo resolveInfo = installedService.getResolveInfo();
-                writeComponentName(proto, "component_name",
+                writeComponentName(dumpStream, "component_name",
                         InstalledPrintServiceProto.COMPONENT_NAME,
                         new ComponentName(resolveInfo.serviceInfo.packageName,
                                 resolveInfo.serviceInfo.name));
 
-                writeStringIfNotNull(proto, "settings_activity",
+                writeStringIfNotNull(dumpStream, "settings_activity",
                         InstalledPrintServiceProto.SETTINGS_ACTIVITY,
                         installedService.getSettingsActivityName());
-                writeStringIfNotNull(proto, "add_printers_activity",
+                writeStringIfNotNull(dumpStream, "add_printers_activity",
                         InstalledPrintServiceProto.ADD_PRINTERS_ACTIVITY,
                         installedService.getAddPrintersActivityName());
-                writeStringIfNotNull(proto, "advanced_options_activity",
+                writeStringIfNotNull(dumpStream, "advanced_options_activity",
                         InstalledPrintServiceProto.ADVANCED_OPTIONS_ACTIVITY,
                         installedService.getAdvancedOptionsActivityName());
 
-                proto.end(token);
+                dumpStream.end(token);
             }
 
             for (ComponentName disabledService : mDisabledServices) {
-                writeComponentName(proto, "disabled_services",
+                writeComponentName(dumpStream, "disabled_services",
                         PrintUserStateProto.DISABLED_SERVICES, disabledService);
             }
 
             final int activeServiceCount = mActiveServices.size();
             for (int i = 0; i < activeServiceCount; i++) {
-                long token = proto.start("actives_services", PrintUserStateProto.ACTIVE_SERVICES);
-                mActiveServices.valueAt(i).dump(proto);
-                proto.end(token);
+                long token = dumpStream.start("actives_services",
+                        PrintUserStateProto.ACTIVE_SERVICES);
+                mActiveServices.valueAt(i).dump(dumpStream);
+                dumpStream.end(token);
             }
 
-            mPrintJobForAppCache.dumpLocked(proto);
+            mPrintJobForAppCache.dumpLocked(dumpStream);
 
             if (mPrinterDiscoverySession != null) {
-                long token = proto.start("discovery_service",
+                long token = dumpStream.start("discovery_service",
                         PrintUserStateProto.DISCOVERY_SESSIONS);
-                mPrinterDiscoverySession.dumpLocked(proto);
-                proto.end(token);
+                mPrinterDiscoverySession.dumpLocked(dumpStream);
+                dumpStream.end(token);
             }
 
         }
 
-        long token = proto.start("print_spooler_state", PrintUserStateProto.PRINT_SPOOLER_STATE);
-        mSpooler.dump(proto);
-        proto.end(token);
+        long token = dumpStream.start("print_spooler_state",
+                PrintUserStateProto.PRINT_SPOOLER_STATE);
+        mSpooler.dump(dumpStream);
+        dumpStream.end(token);
     }
 
     private void readConfigurationLocked() {
@@ -1597,16 +1599,16 @@
             }
         }
 
-        public void dumpLocked(@NonNull DualDumpOutputStream proto) {
-            proto.write("is_destroyed", PrinterDiscoverySessionProto.IS_DESTROYED, mDestroyed);
-            proto.write("is_printer_discovery_in_progress",
+        public void dumpLocked(@NonNull DualDumpOutputStream dumpStream) {
+            dumpStream.write("is_destroyed", PrinterDiscoverySessionProto.IS_DESTROYED, mDestroyed);
+            dumpStream.write("is_printer_discovery_in_progress",
                     PrinterDiscoverySessionProto.IS_PRINTER_DISCOVERY_IN_PROGRESS,
                     !mStartedPrinterDiscoveryTokens.isEmpty());
 
             final int observerCount = mDiscoveryObservers.beginBroadcast();
             for (int i = 0; i < observerCount; i++) {
                 IPrinterDiscoveryObserver observer = mDiscoveryObservers.getBroadcastItem(i);
-                proto.write("printer_discovery_observers",
+                dumpStream.write("printer_discovery_observers",
                         PrinterDiscoverySessionProto.PRINTER_DISCOVERY_OBSERVERS,
                         observer.toString());
             }
@@ -1615,21 +1617,21 @@
             final int tokenCount = this.mStartedPrinterDiscoveryTokens.size();
             for (int i = 0; i < tokenCount; i++) {
                 IBinder token = mStartedPrinterDiscoveryTokens.get(i);
-                proto.write("discovery_requests",
+                dumpStream.write("discovery_requests",
                         PrinterDiscoverySessionProto.DISCOVERY_REQUESTS, token.toString());
             }
 
             final int trackedPrinters = mStateTrackedPrinters.size();
             for (int i = 0; i < trackedPrinters; i++) {
                 PrinterId printer = mStateTrackedPrinters.get(i);
-                writePrinterId(proto, "tracked_printer_requests",
+                writePrinterId(dumpStream, "tracked_printer_requests",
                         PrinterDiscoverySessionProto.TRACKED_PRINTER_REQUESTS, printer);
             }
 
             final int printerCount = mPrinters.size();
             for (int i = 0; i < printerCount; i++) {
                 PrinterInfo printer = mPrinters.valueAt(i);
-                writePrinterInfo(mContext, proto, "printer",
+                writePrinterInfo(mContext, dumpStream, "printer",
                         PrinterDiscoverySessionProto.PRINTER, printer);
             }
         }
@@ -1843,22 +1845,22 @@
             }
         }
 
-        public void dumpLocked(@NonNull DualDumpOutputStream proto) {
+        public void dumpLocked(@NonNull DualDumpOutputStream dumpStream) {
             final int bucketCount = mPrintJobsForRunningApp.size();
             for (int i = 0; i < bucketCount; i++) {
                 final int appId = mPrintJobsForRunningApp.keyAt(i);
                 List<PrintJobInfo> bucket = mPrintJobsForRunningApp.valueAt(i);
                 final int printJobCount = bucket.size();
                 for (int j = 0; j < printJobCount; j++) {
-                    long token = proto.start("cached_print_jobs",
+                    long token = dumpStream.start("cached_print_jobs",
                             PrintUserStateProto.CACHED_PRINT_JOBS);
 
-                    proto.write("app_id", CachedPrintJobProto.APP_ID, appId);
+                    dumpStream.write("app_id", CachedPrintJobProto.APP_ID, appId);
 
-                    writePrintJobInfo(mContext, proto, "print_job", CachedPrintJobProto.PRINT_JOB,
-                            bucket.get(j));
+                    writePrintJobInfo(mContext, dumpStream, "print_job",
+                            CachedPrintJobProto.PRINT_JOB, bucket.get(j));
 
-                    proto.end(token);
+                    dumpStream.end(token);
                 }
             }
         }
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java
index 9eb42e9..c1789ba 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java
@@ -16,11 +16,11 @@
 
 package com.android.server.locksettings.recoverablekeystore;
 
-import static android.security.keystore.RecoveryMetadata.TYPE_LOCKSCREEN;
+import static android.security.keystore.KeychainProtectionParameter.TYPE_LOCKSCREEN;
 
-import static android.security.keystore.RecoveryMetadata.TYPE_PASSWORD;
-import static android.security.keystore.RecoveryMetadata.TYPE_PATTERN;
-import static android.security.keystore.RecoveryMetadata.TYPE_PIN;
+import static android.security.keystore.KeychainProtectionParameter.TYPE_PASSWORD;
+import static android.security.keystore.KeychainProtectionParameter.TYPE_PATTERN;
+import static android.security.keystore.KeychainProtectionParameter.TYPE_PIN;
 
 import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSWORD;
 import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PATTERN;
@@ -41,8 +41,8 @@
 import android.security.keystore.KeyGenParameterSpec;
 import android.security.keystore.KeyProperties;
 import android.security.keystore.KeyDerivationParams;
-import android.security.keystore.EntryRecoveryData;
-import android.security.keystore.RecoveryData;
+import android.security.keystore.KeychainSnapshot;
+import android.security.keystore.WrappedApplicationKey;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
@@ -283,9 +283,9 @@
                 addApplicationKey(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_APP_KEY_ALIAS);
         mKeySyncTask.run();
 
-        RecoveryData recoveryData = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
+        KeychainSnapshot keychainSnapshot = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
         KeyDerivationParams KeyDerivationParams =
-                recoveryData.getRecoveryMetadata().get(0).getKeyDerivationParams();
+                keychainSnapshot.getKeychainProtectionParams().get(0).getKeyDerivationParams();
         assertThat(KeyDerivationParams.getAlgorithm()).isEqualTo(
                 KeyDerivationParams.ALGORITHM_SHA256);
         verify(mSnapshotListenersStorage).recoverySnapshotAvailable(TEST_RECOVERY_AGENT_UID);
@@ -296,15 +296,15 @@
         assertThat(counterId).isNotNull();
         byte[] recoveryKey = decryptThmEncryptedKey(
                 lockScreenHash,
-                recoveryData.getEncryptedRecoveryKeyBlob(),
+                keychainSnapshot.getEncryptedRecoveryKeyBlob(),
                 /*vaultParams=*/ KeySyncUtils.packVaultParams(
                         mKeyPair.getPublic(),
                         counterId,
                         TEST_DEVICE_ID,
                         /*maxAttempts=*/ 10));
-        List<EntryRecoveryData> applicationKeys = recoveryData.getEntryRecoveryData();
+        List<WrappedApplicationKey> applicationKeys = keychainSnapshot.getWrappedApplicationKeys();
         assertThat(applicationKeys).hasSize(1);
-        EntryRecoveryData keyData = applicationKeys.get(0);
+        WrappedApplicationKey keyData = applicationKeys.get(0);
         assertEquals(TEST_APP_KEY_ALIAS, keyData.getAlias());
         assertThat(keyData.getAlias()).isEqualTo(keyData.getAlias());
         byte[] appKey = KeySyncUtils.decryptApplicationKey(
@@ -322,14 +322,14 @@
 
         mKeySyncTask.run();
 
-        RecoveryData recoveryData = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
-        assertThat(recoveryData.getSnapshotVersion()).isEqualTo(1); // default value;
+        KeychainSnapshot keychainSnapshot = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
+        assertThat(keychainSnapshot.getSnapshotVersion()).isEqualTo(1); // default value;
         mRecoverableKeyStoreDb.setShouldCreateSnapshot(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, true);
 
         mKeySyncTask.run();
 
-        recoveryData = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
-        assertThat(recoveryData.getSnapshotVersion()).isEqualTo(2); // Updated
+        keychainSnapshot = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
+        assertThat(keychainSnapshot.getSnapshotVersion()).isEqualTo(2); // Updated
     }
 
     @Test
@@ -352,9 +352,9 @@
 
         mKeySyncTask.run();
 
-        RecoveryData recoveryData = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
-        assertThat(recoveryData.getRecoveryMetadata()).hasSize(1);
-        assertThat(recoveryData.getRecoveryMetadata().get(0).getLockScreenUiFormat()).
+        KeychainSnapshot keychainSnapshot = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
+        assertThat(keychainSnapshot.getKeychainProtectionParams()).hasSize(1);
+        assertThat(keychainSnapshot.getKeychainProtectionParams().get(0).getLockScreenUiFormat()).
                 isEqualTo(TYPE_PASSWORD);
     }
 
@@ -378,10 +378,10 @@
 
         mKeySyncTask.run();
 
-        RecoveryData recoveryData = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
-        assertThat(recoveryData.getRecoveryMetadata()).hasSize(1);
+        KeychainSnapshot keychainSnapshot = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
+        assertThat(keychainSnapshot.getKeychainProtectionParams()).hasSize(1);
         // Password with only digits is changed to pin.
-        assertThat(recoveryData.getRecoveryMetadata().get(0).getLockScreenUiFormat()).
+        assertThat(keychainSnapshot.getKeychainProtectionParams().get(0).getLockScreenUiFormat()).
                 isEqualTo(TYPE_PIN);
     }
 
@@ -405,9 +405,9 @@
 
         mKeySyncTask.run();
 
-        RecoveryData recoveryData = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
-        assertThat(recoveryData.getRecoveryMetadata()).hasSize(1);
-        assertThat(recoveryData.getRecoveryMetadata().get(0).getLockScreenUiFormat()).
+        KeychainSnapshot keychainSnapshot = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
+        assertThat(keychainSnapshot.getKeychainProtectionParams()).hasSize(1);
+        assertThat(keychainSnapshot.getKeychainProtectionParams().get(0).getLockScreenUiFormat()).
                 isEqualTo(TYPE_PATTERN);
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java
index 1bdcf47..3715742 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java
@@ -16,8 +16,8 @@
 
 package com.android.server.locksettings.recoverablekeystore;
 
-import static android.security.keystore.RecoveryMetadata.TYPE_LOCKSCREEN;
-import static android.security.keystore.RecoveryMetadata.TYPE_PASSWORD;
+import static android.security.keystore.KeychainProtectionParameter.TYPE_LOCKSCREEN;
+import static android.security.keystore.KeychainProtectionParameter.TYPE_PASSWORD;
 
 import static com.google.common.truth.Truth.assertThat;
 import static org.junit.Assert.assertArrayEquals;
@@ -43,9 +43,8 @@
 import android.security.keystore.KeyGenParameterSpec;
 import android.security.keystore.KeyProperties;
 import android.security.keystore.KeyDerivationParams;
-import android.security.keystore.EntryRecoveryData;
-import android.security.keystore.RecoveryMetadata;
-import android.security.keystore.RecoveryManager;
+import android.security.keystore.KeychainProtectionParameter;
+import android.security.keystore.WrappedApplicationKey;
 import android.support.test.filters.SmallTest;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.runner.AndroidJUnit4;
@@ -251,7 +250,7 @@
                 TEST_VAULT_PARAMS,
                 TEST_VAULT_CHALLENGE,
                 ImmutableList.of(
-                        new RecoveryMetadata(
+                        new KeychainProtectionParameter(
                                 TYPE_LOCKSCREEN,
                                 TYPE_PASSWORD,
                                 KeyDerivationParams.createSha256Params(TEST_SALT),
@@ -270,7 +269,7 @@
                 TEST_VAULT_PARAMS,
                 TEST_VAULT_CHALLENGE,
                 ImmutableList.of(
-                        new RecoveryMetadata(
+                        new KeychainProtectionParameter(
                                 TYPE_LOCKSCREEN,
                                 TYPE_PASSWORD,
                                 KeyDerivationParams.createSha256Params(TEST_SALT),
@@ -295,7 +294,7 @@
             fail("should have thrown");
         } catch (ServiceSpecificException e) {
             assertThat(e.getMessage()).startsWith(
-                    "Only a single RecoveryMetadata is supported");
+                    "Only a single KeychainProtectionParameter is supported");
         }
     }
 
@@ -308,7 +307,7 @@
                     TEST_VAULT_PARAMS,
                     TEST_VAULT_CHALLENGE,
                     ImmutableList.of(
-                            new RecoveryMetadata(
+                            new KeychainProtectionParameter(
                                     TYPE_LOCKSCREEN,
                                     TYPE_PASSWORD,
                                     KeyDerivationParams.createSha256Params(TEST_SALT),
@@ -330,7 +329,7 @@
                     vaultParams,
                     TEST_VAULT_CHALLENGE,
                     ImmutableList.of(
-                            new RecoveryMetadata(
+                            new KeychainProtectionParameter(
                                     TYPE_LOCKSCREEN,
                                     TYPE_PASSWORD,
                                     KeyDerivationParams.createSha256Params(TEST_SALT),
@@ -348,7 +347,7 @@
                     TEST_SESSION_ID,
                     /*recoveryKeyBlob=*/ randomBytes(32),
                     /*applicationKeys=*/ ImmutableList.of(
-                            new EntryRecoveryData("alias", randomBytes(32))
+                            new WrappedApplicationKey("alias", randomBytes(32))
                     ));
             fail("should have thrown");
         } catch (ServiceSpecificException e) {
@@ -363,7 +362,7 @@
                 TEST_PUBLIC_KEY,
                 TEST_VAULT_PARAMS,
                 TEST_VAULT_CHALLENGE,
-                ImmutableList.of(new RecoveryMetadata(
+                ImmutableList.of(new KeychainProtectionParameter(
                         TYPE_LOCKSCREEN,
                         TYPE_PASSWORD,
                         KeyDerivationParams.createSha256Params(TEST_SALT),
@@ -387,7 +386,7 @@
                 TEST_PUBLIC_KEY,
                 TEST_VAULT_PARAMS,
                 TEST_VAULT_CHALLENGE,
-                ImmutableList.of(new RecoveryMetadata(
+                ImmutableList.of(new KeychainProtectionParameter(
                         TYPE_LOCKSCREEN,
                         TYPE_PASSWORD,
                         KeyDerivationParams.createSha256Params(TEST_SALT),
@@ -397,7 +396,7 @@
         SecretKey recoveryKey = randomRecoveryKey();
         byte[] encryptedClaimResponse = encryptClaimResponse(
                 keyClaimant, TEST_SECRET, TEST_VAULT_PARAMS, recoveryKey);
-        EntryRecoveryData badApplicationKey = new EntryRecoveryData(
+        WrappedApplicationKey badApplicationKey = new WrappedApplicationKey(
                 TEST_ALIAS,
                 randomBytes(32));
 
@@ -419,7 +418,7 @@
                 TEST_PUBLIC_KEY,
                 TEST_VAULT_PARAMS,
                 TEST_VAULT_CHALLENGE,
-                ImmutableList.of(new RecoveryMetadata(
+                ImmutableList.of(new KeychainProtectionParameter(
                         TYPE_LOCKSCREEN,
                         TYPE_PASSWORD,
                         KeyDerivationParams.createSha256Params(TEST_SALT),
@@ -430,7 +429,7 @@
         byte[] encryptedClaimResponse = encryptClaimResponse(
                 keyClaimant, TEST_SECRET, TEST_VAULT_PARAMS, recoveryKey);
         byte[] applicationKeyBytes = randomBytes(32);
-        EntryRecoveryData applicationKey = new EntryRecoveryData(
+        WrappedApplicationKey applicationKey = new WrappedApplicationKey(
                 TEST_ALIAS,
                 encryptedApplicationKey(recoveryKey, applicationKeyBytes));
 
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverySnapshotStorageTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverySnapshotStorageTest.java
index 6308f74..56b44e2 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverySnapshotStorageTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverySnapshotStorageTest.java
@@ -3,7 +3,7 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
 
-import android.security.keystore.RecoveryData;
+import android.security.keystore.KeychainSnapshot;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 
@@ -26,25 +26,25 @@
     @Test
     public void get_returnsSetSnapshot() {
         int userId = 1000;
-        RecoveryData recoveryData = new RecoveryData(
+        KeychainSnapshot keychainSnapshot = new KeychainSnapshot(
                 /*snapshotVersion=*/ 1,
                 new ArrayList<>(),
                 new ArrayList<>(),
                 new byte[0]);
-        mRecoverySnapshotStorage.put(userId, recoveryData);
+        mRecoverySnapshotStorage.put(userId, keychainSnapshot);
 
-        assertEquals(recoveryData, mRecoverySnapshotStorage.get(userId));
+        assertEquals(keychainSnapshot, mRecoverySnapshotStorage.get(userId));
     }
 
     @Test
     public void remove_removesSnapshots() {
         int userId = 1000;
-        RecoveryData recoveryData = new RecoveryData(
+        KeychainSnapshot keychainSnapshot = new KeychainSnapshot(
                 /*snapshotVersion=*/ 1,
                 new ArrayList<>(),
                 new ArrayList<>(),
                 new byte[0]);
-        mRecoverySnapshotStorage.put(userId, recoveryData);
+        mRecoverySnapshotStorage.put(userId, keychainSnapshot);
 
         mRecoverySnapshotStorage.remove(userId);
 
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ScheduleCalendarTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ScheduleCalendarTest.java
index 9564ab9..36136a8 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ScheduleCalendarTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ScheduleCalendarTest.java
@@ -48,7 +48,6 @@
         mScheduleCalendar = new ScheduleCalendar();
         mScheduleInfo = new ZenModeConfig.ScheduleInfo();
         mScheduleInfo.days = new int[] {1, 2, 3, 4, 5};
-        mScheduleCalendar.setSchedule(mScheduleInfo);
     }
 
     @Test
@@ -100,6 +99,7 @@
         mScheduleInfo.startMinute = 15;
         mScheduleInfo.endMinute = 15;
         mScheduleInfo.exitAtAlarm = false;
+        mScheduleCalendar.setSchedule(mScheduleInfo);
 
         Calendar expected = new GregorianCalendar();
         expected.setTimeInMillis(cal.getTimeInMillis());
@@ -126,6 +126,7 @@
         mScheduleInfo.startMinute = 15;
         mScheduleInfo.endMinute = 15;
         mScheduleInfo.exitAtAlarm = false;
+        mScheduleCalendar.setSchedule(mScheduleInfo);
 
         Calendar expected = new GregorianCalendar();
         expected.setTimeInMillis(cal.getTimeInMillis());
@@ -153,6 +154,7 @@
         mScheduleInfo.startMinute = 15;
         mScheduleInfo.endMinute = 15;
         mScheduleInfo.exitAtAlarm = false;
+        mScheduleCalendar.setSchedule(mScheduleInfo);
 
         Calendar expected = new GregorianCalendar();
         expected.setTimeInMillis(cal.getTimeInMillis());
@@ -171,6 +173,7 @@
     public void testShouldExitForAlarm_settingOff() {
         mScheduleInfo.exitAtAlarm = false;
         mScheduleInfo.nextAlarm = 1000;
+        mScheduleCalendar.setSchedule(mScheduleInfo);
 
         assertFalse(mScheduleCalendar.shouldExitForAlarm(1000));
     }
@@ -179,6 +182,7 @@
     public void testShouldExitForAlarm_beforeAlarm() {
         mScheduleInfo.exitAtAlarm = true;
         mScheduleInfo.nextAlarm = 1000;
+        mScheduleCalendar.setSchedule(mScheduleInfo);
 
         assertFalse(mScheduleCalendar.shouldExitForAlarm(999));
     }
@@ -187,6 +191,7 @@
     public void testShouldExitForAlarm_noAlarm() {
         mScheduleInfo.exitAtAlarm = true;
         mScheduleInfo.nextAlarm = 0;
+        mScheduleCalendar.setSchedule(mScheduleInfo);
 
         assertFalse(mScheduleCalendar.shouldExitForAlarm(999));
     }
@@ -195,6 +200,7 @@
     public void testShouldExitForAlarm() {
         mScheduleInfo.exitAtAlarm = true;
         mScheduleInfo.nextAlarm = 1000;
+        mScheduleCalendar.setSchedule(mScheduleInfo);
 
         assertTrue(mScheduleCalendar.shouldExitForAlarm(1000));
     }
@@ -203,6 +209,7 @@
     public void testMaybeSetNextAlarm_settingOff() {
         mScheduleInfo.exitAtAlarm = false;
         mScheduleInfo.nextAlarm = 0;
+        mScheduleCalendar.setSchedule(mScheduleInfo);
 
         mScheduleCalendar.maybeSetNextAlarm(1000, 2000);
 
@@ -213,6 +220,7 @@
     public void testMaybeSetNextAlarm_settingOn() {
         mScheduleInfo.exitAtAlarm = true;
         mScheduleInfo.nextAlarm = 0;
+        mScheduleCalendar.setSchedule(mScheduleInfo);
 
         mScheduleCalendar.maybeSetNextAlarm(1000, 2000);
 
@@ -223,6 +231,7 @@
     public void testMaybeSetNextAlarm_alarmCanceled() {
         mScheduleInfo.exitAtAlarm = true;
         mScheduleInfo.nextAlarm = 10000;
+        mScheduleCalendar.setSchedule(mScheduleInfo);
 
         mScheduleCalendar.maybeSetNextAlarm(1000, 0);
 
@@ -233,6 +242,7 @@
     public void testMaybeSetNextAlarm_earlierAlarm() {
         mScheduleInfo.exitAtAlarm = true;
         mScheduleInfo.nextAlarm = 2000;
+        mScheduleCalendar.setSchedule(mScheduleInfo);
 
         mScheduleCalendar.maybeSetNextAlarm(1000, 1500);
 
@@ -242,6 +252,7 @@
     @Test
     public void testMaybeSetNextAlarm_laterAlarm() {
         mScheduleInfo.exitAtAlarm = true;
+        mScheduleCalendar.setSchedule(mScheduleInfo);
         mScheduleInfo.nextAlarm = 2000;
 
         mScheduleCalendar.maybeSetNextAlarm(1000, 3000);
@@ -253,6 +264,7 @@
     public void testMaybeSetNextAlarm_expiredAlarm() {
         mScheduleInfo.exitAtAlarm = true;
         mScheduleInfo.nextAlarm = 998;
+        mScheduleCalendar.setSchedule(mScheduleInfo);
 
         mScheduleCalendar.maybeSetNextAlarm(1000, 999);
 
@@ -272,6 +284,7 @@
         mScheduleInfo.endHour = 3;
         mScheduleInfo.startMinute = 15;
         mScheduleInfo.endMinute = 15;
+        mScheduleCalendar.setSchedule(mScheduleInfo);
 
         assertTrue(mScheduleCalendar.isInSchedule(cal.getTimeInMillis()));
     }
@@ -289,6 +302,7 @@
         mScheduleInfo.endHour = 3;
         mScheduleInfo.startMinute = 16;
         mScheduleInfo.endMinute = 15;
+        mScheduleCalendar.setSchedule(mScheduleInfo);
 
         assertTrue(mScheduleCalendar.isInSchedule(cal.getTimeInMillis()));
     }
@@ -306,6 +320,7 @@
         mScheduleInfo.startMinute = 16;
         mScheduleInfo.endHour = 15;
         mScheduleInfo.endMinute = 15;
+        mScheduleCalendar.setSchedule(mScheduleInfo);
 
         assertFalse(mScheduleCalendar.isInSchedule(cal.getTimeInMillis()));
     }
@@ -322,6 +337,7 @@
         mScheduleInfo.endHour = 3;
         mScheduleInfo.startMinute = 16;
         mScheduleInfo.endMinute = 15;
+        mScheduleCalendar.setSchedule(mScheduleInfo);
 
         assertFalse(mScheduleCalendar.isInSchedule(cal.getTimeInMillis()));
     }
diff --git a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java
index 1ddab5b..4fbb228 100644
--- a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java
+++ b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java
@@ -353,7 +353,7 @@
     @Test
     public void testRemoveTransportModeTransform() throws Exception {
         ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(new Socket());
-        mIpSecService.removeTransportModeTransforms(pfd, 1);
+        mIpSecService.removeTransportModeTransforms(pfd);
 
         verify(mMockNetd).ipSecRemoveTransportModeTransform(pfd.getFileDescriptor());
     }
diff --git a/tests/net/java/com/android/server/IpSecServiceTest.java b/tests/net/java/com/android/server/IpSecServiceTest.java
index b2a27e8..3eba881 100644
--- a/tests/net/java/com/android/server/IpSecServiceTest.java
+++ b/tests/net/java/com/android/server/IpSecServiceTest.java
@@ -423,7 +423,7 @@
     @Test
     public void testRemoveTransportModeTransform() throws Exception {
         ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(new Socket());
-        mIpSecService.removeTransportModeTransforms(pfd, 1);
+        mIpSecService.removeTransportModeTransforms(pfd);
 
         verify(mMockNetd).ipSecRemoveTransportModeTransform(pfd.getFileDescriptor());
     }
diff --git a/tools/aapt2/java/ClassDefinition.cpp b/tools/aapt2/java/ClassDefinition.cpp
index b692ccf..f5f5b05 100644
--- a/tools/aapt2/java/ClassDefinition.cpp
+++ b/tools/aapt2/java/ClassDefinition.cpp
@@ -45,8 +45,18 @@
   Result result = Result::kAdded;
   auto iter = indexed_members_.find(member->GetName());
   if (iter != indexed_members_.end()) {
-    // Overwrite the entry.
-    ordered_members_[iter->second].reset();
+    // Overwrite the entry. Be careful, as the key in indexed_members_ is actually memory owned
+    // by the value at ordered_members_[index]. Since overwriting a value for a key doesn't replace
+    // the key (the initial key inserted into the unordered_map is kept), we must erase and then
+    // insert a new key, whose memory is being kept around. We do all this to avoid using more
+    // memory for each key.
+    size_t index = iter->second;
+
+    // Erase the key + value from the map.
+    indexed_members_.erase(iter);
+
+    // Now clear the memory that was backing the key (now erased).
+    ordered_members_[index].reset();
     result = Result::kOverridden;
   }
 
diff --git a/tools/aapt2/java/ManifestClassGenerator_test.cpp b/tools/aapt2/java/ManifestClassGenerator_test.cpp
index c324238..f4e10ab 100644
--- a/tools/aapt2/java/ManifestClassGenerator_test.cpp
+++ b/tools/aapt2/java/ManifestClassGenerator_test.cpp
@@ -129,13 +129,16 @@
   std::unique_ptr<xml::XmlResource> manifest = test::BuildXmlDom(R"(
       <manifest xmlns:android="http://schemas.android.com/apk/res/android">
         <permission android:name="android.permission.ACCESS_INTERNET" />
-        <permission android:name="com.android.aapt.test.ACCESS_INTERNET" />
+        <permission android:name="com.android.sample.ACCESS_INTERNET" />
+        <permission android:name="com.android.permission.UNRELATED_PERMISSION" />
+        <permission android:name="com.android.aapt.test.ACCESS_INTERNET" /> -->
       </manifest>)");
 
   std::string actual;
   ASSERT_TRUE(GetManifestClassText(context.get(), manifest.get(), &actual));
   EXPECT_THAT(actual, HasSubstr("ACCESS_INTERNET=\"com.android.aapt.test.ACCESS_INTERNET\";"));
   EXPECT_THAT(actual, Not(HasSubstr("ACCESS_INTERNET=\"android.permission.ACCESS_INTERNET\";")));
+  EXPECT_THAT(actual, Not(HasSubstr("ACCESS_INTERNET=\"com.android.sample.ACCESS_INTERNET\";")));
 }
 
 static ::testing::AssertionResult GetManifestClassText(IAaptContext* context, xml::XmlResource* res,