Merge "Add owners for window coretest"
diff --git a/Android.bp b/Android.bp
index afd8bfd..856e11ec 100644
--- a/Android.bp
+++ b/Android.bp
@@ -112,7 +112,6 @@
         ":gsiservice_aidl",
         ":incidentcompanion_aidl",
         ":installd_aidl",
-        ":keystore_aidl",
         ":libaudioclient_aidl",
         ":libbinder_aidl",
         ":libbluetooth-binder-aidl",
@@ -540,7 +539,6 @@
         "core/java/com/android/internal/util/RingBufferIndices.java",
         "core/java/com/android/internal/util/State.java",
         "core/java/com/android/internal/util/StateMachine.java",
-        "core/java/com/android/internal/util/TrafficStatsConstants.java",
         "core/java/com/android/internal/util/WakeupMessage.java",
         "core/java/com/android/internal/util/TokenBucket.java",
     ],
@@ -566,7 +564,6 @@
         "core/java/com/android/internal/util/MessageUtils.java",
         "core/java/com/android/internal/util/State.java",
         "core/java/com/android/internal/util/StateMachine.java",
-        "core/java/com/android/internal/util/TrafficStatsConstants.java",
         "core/java/com/android/internal/util/WakeupMessage.java",
     ],
 }
@@ -788,6 +785,14 @@
     path: "core/java",
 }
 
+filegroup {
+    name: "activity_manager_procstate_aidl",
+    srcs: [
+        // internal only
+    ],
+    path: "core/java",
+}
+
 aidl_interface {
     name: "libincremental_aidl",
     unstable: true,
diff --git a/boot/Android.bp b/boot/Android.bp
index 4f7c44e..71edea2 100644
--- a/boot/Android.bp
+++ b/boot/Android.bp
@@ -23,7 +23,24 @@
     default_applicable_licenses: ["frameworks_base_license"],
 }
 
-boot_image {
-    name: "framework-boot-image",
-    image_name: "boot",
+// This module provides access to information Soong has related to the
+// whole platform bootclasspath. Currently, that information is provided solely
+// through configuration but additional information will be added here.
+//
+// This will provide support for the following:
+// * Hidden API processing for those parts of the bootclasspath that are not
+//   part of an APEX.
+// * Compatibility checking to ensure that the hidden API bits encoded into the
+//   dex files by the modularized hidden API processing is compatible with the
+//   runtimes of earlier releases which expect the bits to have been computed
+//   over the entirety of the bootclasspath in one go not separately.
+// * Dexpreopting apps and other libraries not on the platform bootclasspath.
+// * Generating and installing the appropriate files to the device which will
+//   allow it to generate the bootclasspath related environment variables
+//   dynamically.
+//
+// This module needs to be present in the build for the above processing to be
+// done correctly.
+platform_bootclasspath {
+    name: "platform-bootclasspath",
 }
diff --git a/config/hiddenapi-unsupported.txt b/config/hiddenapi-unsupported.txt
index 8a377ac..48a9782 100644
--- a/config/hiddenapi-unsupported.txt
+++ b/config/hiddenapi-unsupported.txt
@@ -209,7 +209,6 @@
 Landroid/os/storage/IStorageManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/os/storage/IStorageManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/os/storage/IStorageManager;
 Landroid/security/IKeyChainService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/security/IKeyChainService;
-Landroid/security/keystore/IKeystoreService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/security/keystore/IKeystoreService;
 Landroid/service/dreams/IDreamManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/service/dreams/IDreamManager;
 Landroid/service/notification/INotificationListener$Stub;-><init>()V
 Landroid/service/persistentdata/IPersistentDataBlockService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/service/persistentdata/IPersistentDataBlockService;
diff --git a/core/api/current.txt b/core/api/current.txt
index f00f0ae..b944ac9 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -25703,12 +25703,13 @@
 
   public final class VcnGatewayConnectionConfig {
     method @NonNull public int[] getExposedCapabilities();
+    method @NonNull public String getGatewayConnectionName();
     method @IntRange(from=android.net.vcn.VcnGatewayConnectionConfig.MIN_MTU_V6) public int getMaxMtu();
     method @NonNull public long[] getRetryInterval();
   }
 
   public static final class VcnGatewayConnectionConfig.Builder {
-    ctor public VcnGatewayConnectionConfig.Builder(@NonNull android.net.vcn.VcnControlPlaneConfig);
+    ctor public VcnGatewayConnectionConfig.Builder(@NonNull String, @NonNull android.net.vcn.VcnControlPlaneConfig);
     method @NonNull public android.net.vcn.VcnGatewayConnectionConfig.Builder addExposedCapability(int);
     method @NonNull public android.net.vcn.VcnGatewayConnectionConfig build();
     method @NonNull public android.net.vcn.VcnGatewayConnectionConfig.Builder removeExposedCapability(int);
@@ -25732,7 +25733,7 @@
 
   public abstract static class VcnManager.VcnStatusCallback {
     ctor public VcnManager.VcnStatusCallback();
-    method public abstract void onGatewayConnectionError(@NonNull int[], int, @Nullable Throwable);
+    method public abstract void onGatewayConnectionError(@NonNull String, int, @Nullable Throwable);
     method public abstract void onStatusChanged(int);
   }
 
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 3f11b72..e6624cd 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -11988,7 +11988,7 @@
     method @NonNull public byte[] getEncodedMessage();
     method @NonNull public String getHeaderSection();
     method @NonNull public String getStartLine();
-    method @Nullable public String getViaBranchParameter();
+    method @NonNull public String getViaBranchParameter();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.SipMessage> CREATOR;
   }
diff --git a/core/java/android/net/INetworkPolicyManager.aidl b/core/java/android/net/INetworkPolicyManager.aidl
index 171c6a2..f50aa99 100644
--- a/core/java/android/net/INetworkPolicyManager.aidl
+++ b/core/java/android/net/INetworkPolicyManager.aidl
@@ -78,5 +78,4 @@
 
     boolean isUidNetworkingBlocked(int uid, boolean meteredNetwork);
     boolean isUidRestrictedOnMeteredNetworks(int uid);
-    boolean checkUidNetworkingBlocked(int uid, int uidRules, boolean isNetworkMetered, boolean isBackgroundRestricted);
 }
diff --git a/core/java/android/net/NetworkIdentity.java b/core/java/android/net/NetworkIdentity.java
index b037261..1eef7d9 100644
--- a/core/java/android/net/NetworkIdentity.java
+++ b/core/java/android/net/NetworkIdentity.java
@@ -198,15 +198,11 @@
         final int oemManaged = getOemBitfield(snapshot.networkCapabilities);
 
         if (legacyType == TYPE_WIFI) {
-            if (snapshot.networkCapabilities.getSsid() != null) {
-                networkId = snapshot.networkCapabilities.getSsid();
-                if (networkId == null) {
-                    // TODO: Figure out if this code path never runs. If so, remove them.
-                    final WifiManager wifi = (WifiManager) context.getSystemService(
-                            Context.WIFI_SERVICE);
-                    final WifiInfo info = wifi.getConnectionInfo();
-                    networkId = info != null ? info.getSSID() : null;
-                }
+            networkId = snapshot.networkCapabilities.getSsid();
+            if (networkId == null) {
+                final WifiManager wifi = context.getSystemService(WifiManager.class);
+                final WifiInfo info = wifi.getConnectionInfo();
+                networkId = info != null ? info.getSSID() : null;
             }
         }
 
diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java
index 68606ec..da3febd 100644
--- a/core/java/android/net/NetworkPolicyManager.java
+++ b/core/java/android/net/NetworkPolicyManager.java
@@ -564,31 +564,6 @@
     }
 
     /**
-     * Figure out if networking is blocked for a given set of conditions.
-     *
-     * This is used by ConnectivityService via passing stale copies of conditions, so it must not
-     * take any locks.
-     *
-     * @param uid The target uid.
-     * @param uidRules The uid rules which are obtained from NetworkPolicyManagerService.
-     * @param isNetworkMetered True if the network is metered.
-     * @param isBackgroundRestricted True if data saver is enabled.
-     *
-     * @return true if networking is blocked for the UID under the specified conditions.
-     *
-     * @hide
-     */
-    public boolean checkUidNetworkingBlocked(int uid, int uidRules,
-            boolean isNetworkMetered, boolean isBackgroundRestricted) {
-        try {
-            return mService.checkUidNetworkingBlocked(uid, uidRules, isNetworkMetered,
-                    isBackgroundRestricted);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
      * Check that the given uid is restricted from doing networking on metered networks.
      *
      * @param uid The target uid.
diff --git a/core/java/android/net/vcn/IVcnStatusCallback.aidl b/core/java/android/net/vcn/IVcnStatusCallback.aidl
index 236ae8b..11bc443 100644
--- a/core/java/android/net/vcn/IVcnStatusCallback.aidl
+++ b/core/java/android/net/vcn/IVcnStatusCallback.aidl
@@ -20,7 +20,7 @@
 oneway interface IVcnStatusCallback {
     void onVcnStatusChanged(int statusCode);
     void onGatewayConnectionError(
-            in int[] gatewayNetworkCapabilities,
+            in String gatewayConnectionName,
             int errorCode,
             in String exceptionClass,
             in String exceptionMessage);
diff --git a/core/java/android/net/vcn/VcnConfig.java b/core/java/android/net/vcn/VcnConfig.java
index 52cc218..d41c0b4 100644
--- a/core/java/android/net/vcn/VcnConfig.java
+++ b/core/java/android/net/vcn/VcnConfig.java
@@ -183,12 +183,25 @@
          *
          * @param gatewayConnectionConfig the configuration for an individual gateway connection
          * @return this {@link Builder} instance, for chaining
+         * @throws IllegalArgumentException if a VcnGatewayConnectionConfig has already been set for
+         *     this {@link VcnConfig} with the same GatewayConnection name (as returned via {@link
+         *     VcnGatewayConnectionConfig#getGatewayConnectionName()}).
          */
         @NonNull
         public Builder addGatewayConnectionConfig(
                 @NonNull VcnGatewayConnectionConfig gatewayConnectionConfig) {
             Objects.requireNonNull(gatewayConnectionConfig, "gatewayConnectionConfig was null");
 
+            for (final VcnGatewayConnectionConfig vcnGatewayConnectionConfig :
+                    mGatewayConnectionConfigs) {
+                if (vcnGatewayConnectionConfig
+                        .getGatewayConnectionName()
+                        .equals(gatewayConnectionConfig.getGatewayConnectionName())) {
+                    throw new IllegalArgumentException(
+                            "GatewayConnection for specified name already exists");
+                }
+            }
+
             mGatewayConnectionConfigs.add(gatewayConnectionConfig);
             return this;
         }
diff --git a/core/java/android/net/vcn/VcnGatewayConnectionConfig.java b/core/java/android/net/vcn/VcnGatewayConnectionConfig.java
index d4e8e2d..75db3820 100644
--- a/core/java/android/net/vcn/VcnGatewayConnectionConfig.java
+++ b/core/java/android/net/vcn/VcnGatewayConnectionConfig.java
@@ -148,6 +148,8 @@
                 TimeUnit.MINUTES.toMillis(5),
                 TimeUnit.MINUTES.toMillis(15)
             };
+    private static final String GATEWAY_CONNECTION_NAME_KEY = "mGatewayConnectionName";
+    @NonNull private final String mGatewayConnectionName;
 
     private static final String CTRL_PLANE_CONFIG_KEY = "mCtrlPlaneConfig";
     @NonNull private VcnControlPlaneConfig mCtrlPlaneConfig;
@@ -166,11 +168,13 @@
 
     /** Builds a VcnGatewayConnectionConfig with the specified parameters. */
     private VcnGatewayConnectionConfig(
+            @NonNull String gatewayConnectionName,
             @NonNull VcnControlPlaneConfig ctrlPlaneConfig,
             @NonNull Set<Integer> exposedCapabilities,
             @NonNull Set<Integer> underlyingCapabilities,
             @NonNull long[] retryIntervalsMs,
             @IntRange(from = MIN_MTU_V6) int maxMtu) {
+        mGatewayConnectionName = gatewayConnectionName;
         mCtrlPlaneConfig = ctrlPlaneConfig;
         mExposedCapabilities = new TreeSet(exposedCapabilities);
         mUnderlyingCapabilities = new TreeSet(underlyingCapabilities);
@@ -192,6 +196,7 @@
         final PersistableBundle underlyingCapsBundle =
                 in.getPersistableBundle(UNDERLYING_CAPABILITIES_KEY);
 
+        mGatewayConnectionName = in.getString(GATEWAY_CONNECTION_NAME_KEY);
         mCtrlPlaneConfig = VcnControlPlaneConfig.fromPersistableBundle(ctrlPlaneConfigBundle);
         mExposedCapabilities = new TreeSet<>(PersistableBundleUtils.toList(
                 exposedCapsBundle, PersistableBundleUtils.INTEGER_DESERIALIZER));
@@ -204,6 +209,7 @@
     }
 
     private void validate() {
+        Objects.requireNonNull(mGatewayConnectionName, "gatewayConnectionName was null");
         Objects.requireNonNull(mCtrlPlaneConfig, "control plane config was null");
 
         Preconditions.checkArgument(
@@ -242,6 +248,20 @@
     }
 
     /**
+     * Returns the configured Gateway Connection name.
+     *
+     * <p>This name is used by the configuring apps to distinguish between
+     * VcnGatewayConnectionConfigs configured on a single {@link VcnConfig}. This will be used as
+     * the identifier in VcnStatusCallback invocations.
+     *
+     * @see VcnManager.VcnStatusCallback#onGatewayConnectionError
+     */
+    @NonNull
+    public String getGatewayConnectionName() {
+        return mGatewayConnectionName;
+    }
+
+    /**
      * Returns control plane configuration.
      *
      * @hide
@@ -364,6 +384,7 @@
                         new ArrayList<>(mUnderlyingCapabilities),
                         PersistableBundleUtils.INTEGER_SERIALIZER);
 
+        result.putString(GATEWAY_CONNECTION_NAME_KEY, mGatewayConnectionName);
         result.putPersistableBundle(CTRL_PLANE_CONFIG_KEY, ctrlPlaneConfigBundle);
         result.putPersistableBundle(EXPOSED_CAPABILITIES_KEY, exposedCapsBundle);
         result.putPersistableBundle(UNDERLYING_CAPABILITIES_KEY, underlyingCapsBundle);
@@ -376,6 +397,7 @@
     @Override
     public int hashCode() {
         return Objects.hash(
+                mGatewayConnectionName,
                 mExposedCapabilities,
                 mUnderlyingCapabilities,
                 Arrays.hashCode(mRetryIntervalsMs),
@@ -389,7 +411,8 @@
         }
 
         final VcnGatewayConnectionConfig rhs = (VcnGatewayConnectionConfig) other;
-        return mExposedCapabilities.equals(rhs.mExposedCapabilities)
+        return mGatewayConnectionName.equals(rhs.mGatewayConnectionName)
+                && mExposedCapabilities.equals(rhs.mExposedCapabilities)
                 && mUnderlyingCapabilities.equals(rhs.mUnderlyingCapabilities)
                 && Arrays.equals(mRetryIntervalsMs, rhs.mRetryIntervalsMs)
                 && mMaxMtu == rhs.mMaxMtu;
@@ -399,6 +422,7 @@
      * This class is used to incrementally build {@link VcnGatewayConnectionConfig} objects.
      */
     public static final class Builder {
+        @NonNull private final String mGatewayConnectionName;
         @NonNull private final VcnControlPlaneConfig mCtrlPlaneConfig;
         @NonNull private final Set<Integer> mExposedCapabilities = new ArraySet();
         @NonNull private final Set<Integer> mUnderlyingCapabilities = new ArraySet();
@@ -412,12 +436,22 @@
         /**
          * Construct a Builder object.
          *
+         * @param gatewayConnectionName the String GatewayConnection name for this
+         *     VcnGatewayConnectionConfig. Each VcnGatewayConnectionConfig within a {@link
+         *     VcnConfig} must be given a unique name. This name is used by the caller to
+         *     distinguish between VcnGatewayConnectionConfigs configured on a single {@link
+         *     VcnConfig}. This will be used as the identifier in VcnStatusCallback invocations.
          * @param ctrlPlaneConfig the control plane configuration
          * @see VcnControlPlaneConfig
+         * @see VcnManager.VcnStatusCallback#onGatewayConnectionError
          */
-        public Builder(@NonNull VcnControlPlaneConfig ctrlPlaneConfig) {
+        public Builder(
+                @NonNull String gatewayConnectionName,
+                @NonNull VcnControlPlaneConfig ctrlPlaneConfig) {
+            Objects.requireNonNull(gatewayConnectionName, "gatewayConnectionName was null");
             Objects.requireNonNull(ctrlPlaneConfig, "ctrlPlaneConfig was null");
 
+            mGatewayConnectionName = gatewayConnectionName;
             mCtrlPlaneConfig = ctrlPlaneConfig;
         }
 
@@ -562,6 +596,7 @@
         @NonNull
         public VcnGatewayConnectionConfig build() {
             return new VcnGatewayConnectionConfig(
+                    mGatewayConnectionName,
                     mCtrlPlaneConfig,
                     mExposedCapabilities,
                     mUnderlyingCapabilities,
diff --git a/core/java/android/net/vcn/VcnManager.java b/core/java/android/net/vcn/VcnManager.java
index abd41da..344b20c 100644
--- a/core/java/android/net/vcn/VcnManager.java
+++ b/core/java/android/net/vcn/VcnManager.java
@@ -437,7 +437,7 @@
          * Invoked when status of the VCN for this callback's subscription group changes.
          *
          * @param statusCode the code for the status change encountered by this {@link
-         *     VcnStatusCallback}'s subscription group.
+         *     VcnStatusCallback}'s subscription group. This value will be one of VCN_STATUS_CODE_*.
          */
         public abstract void onStatusChanged(@VcnStatusCode int statusCode);
 
@@ -445,18 +445,17 @@
          * Invoked when a VCN Gateway Connection corresponding to this callback's subscription group
          * encounters an error.
          *
-         * @param networkCapabilities an array of NetworkCapabilities.NET_CAPABILITY_* capabilities
-         *     for the Gateway Connection that encountered the error, for identification purposes.
-         *     These will be a sorted list with no duplicates and will match {@link
-         *     VcnGatewayConnectionConfig#getExposedCapabilities()} for one of the {@link
-         *     VcnGatewayConnectionConfig}s set in the {@link VcnConfig} for this subscription
-         *     group.
-         * @param errorCode the code to indicate the error that occurred
+         * @param gatewayConnectionName the String GatewayConnection name for the GatewayConnection
+         *     encountering an error. This will match the name for exactly one {@link
+         *     VcnGatewayConnectionConfig} for the {@link VcnConfig} configured for this callback's
+         *     subscription group
+         * @param errorCode the code to indicate the error that occurred. This value will be one of
+         *     VCN_ERROR_CODE_*.
          * @param detail Throwable to provide additional information about the error, or {@code
          *     null} if none
          */
         public abstract void onGatewayConnectionError(
-                @NonNull int[] networkCapabilities,
+                @NonNull String gatewayConnectionName,
                 @VcnErrorCode int errorCode,
                 @Nullable Throwable detail);
     }
@@ -586,7 +585,7 @@
         // TODO(b/180521637): use ServiceSpecificException for safer Exception 'parceling'
         @Override
         public void onGatewayConnectionError(
-                @NonNull int[] networkCapabilities,
+                @NonNull String gatewayConnectionName,
                 @VcnErrorCode int errorCode,
                 @Nullable String exceptionClass,
                 @Nullable String exceptionMessage) {
@@ -597,7 +596,7 @@
                             mExecutor.execute(
                                     () ->
                                             mCallback.onGatewayConnectionError(
-                                                    networkCapabilities, errorCode, cause)));
+                                                    gatewayConnectionName, errorCode, cause)));
         }
 
         private static Throwable createThrowableByClassName(
diff --git a/core/java/android/security/ConfirmationPrompt.java b/core/java/android/security/ConfirmationPrompt.java
index 2329037..d8c44ad 100644
--- a/core/java/android/security/ConfirmationPrompt.java
+++ b/core/java/android/security/ConfirmationPrompt.java
@@ -21,7 +21,6 @@
 import android.content.Context;
 import android.provider.Settings;
 import android.provider.Settings.SettingNotFoundException;
-import android.security.keystore.AndroidKeyStoreProvider;
 import android.text.TextUtils;
 import android.util.Log;
 
@@ -106,32 +105,6 @@
     private void doCallback(int responseCode, byte[] dataThatWasConfirmed,
             ConfirmationCallback callback) {
         switch (responseCode) {
-            case KeyStore.CONFIRMATIONUI_OK:
-                callback.onConfirmed(dataThatWasConfirmed);
-                break;
-
-            case KeyStore.CONFIRMATIONUI_CANCELED:
-                callback.onDismissed();
-                break;
-
-            case KeyStore.CONFIRMATIONUI_ABORTED:
-                callback.onCanceled();
-                break;
-
-            case KeyStore.CONFIRMATIONUI_SYSTEM_ERROR:
-                callback.onError(new Exception("System error returned by ConfirmationUI."));
-                break;
-
-            default:
-                callback.onError(new Exception("Unexpected responseCode=" + responseCode
-                                + " from onConfirmtionPromptCompleted() callback."));
-                break;
-        }
-    }
-
-    private void doCallback2(int responseCode, byte[] dataThatWasConfirmed,
-            ConfirmationCallback callback) {
-        switch (responseCode) {
             case AndroidProtectedConfirmation.ERROR_OK:
                 callback.onConfirmed(dataThatWasConfirmed);
                 break;
@@ -155,31 +128,6 @@
         }
     }
 
-    private final android.os.IBinder mCallbackBinder =
-            new android.security.IConfirmationPromptCallback.Stub() {
-                @Override
-                public void onConfirmationPromptCompleted(
-                        int responseCode, final byte[] dataThatWasConfirmed)
-                        throws android.os.RemoteException {
-                    if (mCallback != null) {
-                        ConfirmationCallback callback = mCallback;
-                        Executor executor = mExecutor;
-                        mCallback = null;
-                        mExecutor = null;
-                        if (executor == null) {
-                            doCallback(responseCode, dataThatWasConfirmed, callback);
-                        } else {
-                            executor.execute(new Runnable() {
-                                    @Override
-                                    public void run() {
-                                        doCallback(responseCode, dataThatWasConfirmed, callback);
-                                    }
-                                });
-                        }
-                    }
-                }
-            };
-
     private final android.security.apc.IConfirmationCallback mConfirmationCallback =
             new android.security.apc.IConfirmationCallback.Stub() {
                 @Override
@@ -191,11 +139,11 @@
                         mCallback = null;
                         mExecutor = null;
                         if (executor == null) {
-                            doCallback2(result, dataThatWasConfirmed, callback);
+                            doCallback(result, dataThatWasConfirmed, callback);
                         } else {
                             executor.execute(new Runnable() {
                                 @Override public void run() {
-                                    doCallback2(result, dataThatWasConfirmed, callback);
+                                    doCallback(result, dataThatWasConfirmed, callback);
                                 }
                             });
                         }
@@ -266,29 +214,7 @@
         mExtraData = extraData;
     }
 
-    private static final int UI_OPTION_ACCESSIBILITY_INVERTED_FLAG = 1 << 0;
-    private static final int UI_OPTION_ACCESSIBILITY_MAGNIFIED_FLAG = 1 << 1;
-
     private int getUiOptionsAsFlags() {
-        if (AndroidKeyStoreProvider.isKeystore2Enabled()) {
-            return getUiOptionsAsFlags2();
-        }
-        int uiOptionsAsFlags = 0;
-        ContentResolver contentResolver = mContext.getContentResolver();
-        int inversionEnabled = Settings.Secure.getInt(contentResolver,
-                Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, 0);
-        if (inversionEnabled == 1) {
-            uiOptionsAsFlags |= UI_OPTION_ACCESSIBILITY_INVERTED_FLAG;
-        }
-        float fontScale = Settings.System.getFloat(contentResolver,
-                Settings.System.FONT_SCALE, (float) 1.0);
-        if (fontScale > 1.0) {
-            uiOptionsAsFlags |= UI_OPTION_ACCESSIBILITY_MAGNIFIED_FLAG;
-        }
-        return uiOptionsAsFlags;
-    }
-
-    private int getUiOptionsAsFlags2() {
         int uiOptionsAsFlags = 0;
         ContentResolver contentResolver = mContext.getContentResolver();
         int inversionEnabled = Settings.Secure.getInt(contentResolver,
@@ -349,52 +275,26 @@
         mExecutor = executor;
 
         String locale = Locale.getDefault().toLanguageTag();
-        if (AndroidKeyStoreProvider.isKeystore2Enabled()) {
-            int uiOptionsAsFlags = getUiOptionsAsFlags2();
-            int responseCode = getService().presentConfirmationPrompt(
-                    mConfirmationCallback, mPromptText.toString(), mExtraData, locale,
-                    uiOptionsAsFlags);
-            switch (responseCode) {
-                case AndroidProtectedConfirmation.ERROR_OK:
-                    return;
+        int uiOptionsAsFlags = getUiOptionsAsFlags();
+        int responseCode = getService().presentConfirmationPrompt(
+                mConfirmationCallback, mPromptText.toString(), mExtraData, locale,
+                uiOptionsAsFlags);
+        switch (responseCode) {
+            case AndroidProtectedConfirmation.ERROR_OK:
+                return;
 
-                case AndroidProtectedConfirmation.ERROR_OPERATION_PENDING:
-                    throw new ConfirmationAlreadyPresentingException();
+            case AndroidProtectedConfirmation.ERROR_OPERATION_PENDING:
+                throw new ConfirmationAlreadyPresentingException();
 
-                case AndroidProtectedConfirmation.ERROR_UNIMPLEMENTED:
-                    throw new ConfirmationNotAvailableException();
+            case AndroidProtectedConfirmation.ERROR_UNIMPLEMENTED:
+                throw new ConfirmationNotAvailableException();
 
-                default:
-                    // Unexpected error code.
-                    Log.w(TAG,
-                            "Unexpected responseCode=" + responseCode
-                                    + " from presentConfirmationPrompt() call.");
-                    throw new IllegalArgumentException();
-            }
-        } else {
-            int uiOptionsAsFlags = getUiOptionsAsFlags();
-            int responseCode = mKeyStore.presentConfirmationPrompt(
-                    mCallbackBinder, mPromptText.toString(), mExtraData, locale, uiOptionsAsFlags);
-            switch (responseCode) {
-                case KeyStore.CONFIRMATIONUI_OK:
-                    return;
-
-                case KeyStore.CONFIRMATIONUI_OPERATION_PENDING:
-                    throw new ConfirmationAlreadyPresentingException();
-
-                case KeyStore.CONFIRMATIONUI_UNIMPLEMENTED:
-                    throw new ConfirmationNotAvailableException();
-
-                case KeyStore.CONFIRMATIONUI_UIERROR:
-                    throw new IllegalArgumentException();
-
-                default:
-                    // Unexpected error code.
-                    Log.w(TAG,
-                            "Unexpected responseCode=" + responseCode
-                                    + " from presentConfirmationPrompt() call.");
-                    throw new IllegalArgumentException();
-            }
+            default:
+                // Unexpected error code.
+                Log.w(TAG,
+                        "Unexpected responseCode=" + responseCode
+                                + " from presentConfirmationPrompt() call.");
+                throw new IllegalArgumentException();
         }
     }
 
@@ -408,33 +308,18 @@
      * @throws IllegalStateException if no prompt is currently being presented.
      */
     public void cancelPrompt() {
-        if (AndroidKeyStoreProvider.isKeystore2Enabled()) {
-            int responseCode =
-                    getService().cancelConfirmationPrompt(mConfirmationCallback);
-            if (responseCode == AndroidProtectedConfirmation.ERROR_OK) {
-                return;
-            } else if (responseCode == AndroidProtectedConfirmation.ERROR_OPERATION_PENDING) {
-                throw new IllegalStateException();
-            } else {
-                // Unexpected error code.
-                Log.w(TAG,
-                        "Unexpected responseCode=" + responseCode
-                                + " from cancelConfirmationPrompt() call.");
-                throw new IllegalStateException();
-            }
+        int responseCode =
+                getService().cancelConfirmationPrompt(mConfirmationCallback);
+        if (responseCode == AndroidProtectedConfirmation.ERROR_OK) {
+            return;
+        } else if (responseCode == AndroidProtectedConfirmation.ERROR_OPERATION_PENDING) {
+            throw new IllegalStateException();
         } else {
-            int responseCode = mKeyStore.cancelConfirmationPrompt(mCallbackBinder);
-            if (responseCode == KeyStore.CONFIRMATIONUI_OK) {
-                return;
-            } else if (responseCode == KeyStore.CONFIRMATIONUI_OPERATION_PENDING) {
-                throw new IllegalStateException();
-            } else {
-                // Unexpected error code.
-                Log.w(TAG,
-                        "Unexpected responseCode=" + responseCode
-                                + " from cancelConfirmationPrompt() call.");
-                throw new IllegalStateException();
-            }
+            // Unexpected error code.
+            Log.w(TAG,
+                    "Unexpected responseCode=" + responseCode
+                            + " from cancelConfirmationPrompt() call.");
+            throw new IllegalStateException();
         }
     }
 
@@ -448,9 +333,6 @@
         if (isAccessibilityServiceRunning(context)) {
             return false;
         }
-        if (AndroidKeyStoreProvider.isKeystore2Enabled()) {
-            return new AndroidProtectedConfirmation().isConfirmationPromptSupported();
-        }
-        return KeyStore.getInstance().isConfirmationPromptSupported();
+        return new AndroidProtectedConfirmation().isConfirmationPromptSupported();
     }
 }
diff --git a/core/java/android/security/keymaster/KeymasterCertificateChain.aidl b/core/java/android/security/keymaster/KeymasterCertificateChain.aidl
new file mode 100644
index 0000000..e01db7a
--- /dev/null
+++ b/core/java/android/security/keymaster/KeymasterCertificateChain.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2021 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.keymaster;
+
+parcelable KeymasterCertificateChain;
diff --git a/core/java/android/security/keystore/recovery/RecoveryController.java b/core/java/android/security/keystore/recovery/RecoveryController.java
index 1dc7f71..17ad5f1 100644
--- a/core/java/android/security/keystore/recovery/RecoveryController.java
+++ b/core/java/android/security/keystore/recovery/RecoveryController.java
@@ -712,18 +712,10 @@
      */
     @NonNull Key getKeyFromGrant(@NonNull String grantAlias)
             throws UnrecoverableKeyException, KeyPermanentlyInvalidatedException {
-        if (grantAlias.startsWith(APPLICATION_KEY_GRANT_PREFIX)) {
-            return AndroidKeyStoreProvider
-                    .loadAndroidKeyStoreSecretKeyFromKeystore(
-                            KeyStore2.getInstance(),
-                            getGrantDescriptor(grantAlias));
-        }
-        // TODO(b/171305545): remove KeyStore1 logic.
-        return android.security.keystore.AndroidKeyStoreProvider.loadAndroidKeyStoreKeyFromKeystore(
-            mKeyStore,
-            grantAlias,
-            KeyStore.UID_SELF);
-
+        return AndroidKeyStoreProvider
+                .loadAndroidKeyStoreSecretKeyFromKeystore(
+                        KeyStore2.getInstance(),
+                        getGrantDescriptor(grantAlias));
     }
 
     private static final String APPLICATION_KEY_GRANT_PREFIX = "recoverable_key:";
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index beef982..0b78a2b 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -32,7 +32,7 @@
 
 interface IBatteryStats {
     // These first methods are also called by native code, so must
-    // be kept in sync with frameworks/native/libs/binder/include/binder/IBatteryStats.h
+    // be kept in sync with frameworks/native/libs/binder/include_batterystats/batterystats/IBatteryStats.h
     void noteStartSensor(int uid, int sensor);
     void noteStopSensor(int uid, int sensor);
     void noteStartVideo(int uid);
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 5fea76a..a541089 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -41,6 +41,7 @@
 import android.os.ZygoteProcess;
 import android.os.storage.StorageManager;
 import android.provider.DeviceConfig;
+import android.security.keystore2.AndroidKeyStoreProvider;
 import android.system.ErrnoException;
 import android.system.Os;
 import android.system.OsConstants;
@@ -222,10 +223,8 @@
         long startTime = SystemClock.uptimeMillis();
         Trace.traceBegin(
                 Trace.TRACE_TAG_DALVIK, "Starting installation of AndroidKeyStoreProvider");
-        // AndroidKeyStoreProvider.install() manipulates the list of JCA providers to insert
-        // preferred providers. Note this is not done via security.properties as the JCA providers
-        // are not on the classpath in the case of, for example, raw dalvikvm runtimes.
-        android.security.keystore2.AndroidKeyStoreProvider.install();
+
+        AndroidKeyStoreProvider.install();
         Log.i(TAG, "Installed AndroidKeyStoreProvider in "
                 + (SystemClock.uptimeMillis() - startTime) + "ms.");
         Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
diff --git a/core/java/com/android/internal/os/ZygoteServer.java b/core/java/com/android/internal/os/ZygoteServer.java
index f71b314..4d2266b 100644
--- a/core/java/com/android/internal/os/ZygoteServer.java
+++ b/core/java/com/android/internal/os/ZygoteServer.java
@@ -547,7 +547,7 @@
                         try {
                             ZygoteConnection connection = peers.get(pollIndex);
                             boolean multipleForksOK = !isUsapPoolEnabled()
-                                    && ZygoteHooks.indefiniteThreadSuspensionOK();
+                                    && ZygoteHooks.isIndefiniteThreadSuspensionSafe();
                             final Runnable command =
                                     connection.processCommand(this, multipleForksOK);
 
diff --git a/core/java/com/android/internal/util/TrafficStatsConstants.java b/core/java/com/android/internal/util/TrafficStatsConstants.java
index 413be48..131114c 100644
--- a/core/java/com/android/internal/util/TrafficStatsConstants.java
+++ b/core/java/com/android/internal/util/TrafficStatsConstants.java
@@ -21,24 +21,8 @@
  * @hide
  */
 public class TrafficStatsConstants {
-    // These tags are used by the network stack to do traffic for its own purposes. Traffic
-    // tagged with these will be counted toward the network stack and must stay inside the
-    // range defined by
-    // {@link android.net.TrafficStats#TAG_NETWORK_STACK_RANGE_START} and
-    // {@link android.net.TrafficStats#TAG_NETWORK_STACK_RANGE_END}.
-    public static final int TAG_SYSTEM_DHCP = 0xFFFFFE01;
-    public static final int TAG_SYSTEM_NEIGHBOR = 0xFFFFFE02;
-    public static final int TAG_SYSTEM_DHCP_SERVER = 0xFFFFFE03;
 
     public static final int TAG_SYSTEM_NTP = 0xFFFFFF41;
     public static final int TAG_SYSTEM_GPS = 0xFFFFFF44;
     public static final int TAG_SYSTEM_PAC = 0xFFFFFF45;
-
-    // These tags are used by the network stack to do traffic on behalf of apps. Traffic
-    // tagged with these will be counted toward the app on behalf of which the network
-    // stack is doing this traffic. These values must stay inside the range defined by
-    // {@link android.net.TrafficStats#TAG_NETWORK_STACK_IMPERSONATION_RANGE_START} and
-    // {@link android.net.TrafficStats#TAG_NETWORK_STACK_IMPERSONATION_RANGE_END}.
-    public static final int TAG_SYSTEM_PROBE = 0xFFFFFF81;
-    public static final int TAG_SYSTEM_DNS = 0xFFFFFF82;
 }
diff --git a/graphics/java/android/graphics/RecordingCanvas.java b/graphics/java/android/graphics/RecordingCanvas.java
index c0e0a24..4a24b42 100644
--- a/graphics/java/android/graphics/RecordingCanvas.java
+++ b/graphics/java/android/graphics/RecordingCanvas.java
@@ -21,6 +21,7 @@
 import android.util.Pools.SynchronizedPool;
 import android.view.DisplayListCanvas;
 import android.view.TextureLayer;
+import android.os.SystemProperties;
 
 import dalvik.annotation.optimization.CriticalNative;
 import dalvik.annotation.optimization.FastNative;
@@ -41,7 +42,14 @@
     private static final int POOL_LIMIT = 25;
 
     /** @hide */
-    public static final int MAX_BITMAP_SIZE = 100 * 1024 * 1024; // 100 MB
+    private static int getPanelFrameSize() {
+        final int DefaultSize = 100 * 1024 * 1024; // 100 MB;
+        return Math.max(SystemProperties.getInt("ro.hwui.max_texture_allocation_size", DefaultSize),
+                DefaultSize);
+    }
+
+    /** @hide */
+    public static final int MAX_BITMAP_SIZE = getPanelFrameSize();
 
     private static final SynchronizedPool<RecordingCanvas> sPool =
             new SynchronizedPool<>(POOL_LIMIT);
diff --git a/keystore/java/android/security/AndroidKeyStoreMaintenance.java b/keystore/java/android/security/AndroidKeyStoreMaintenance.java
index 72cea0c..82639de 100644
--- a/keystore/java/android/security/AndroidKeyStoreMaintenance.java
+++ b/keystore/java/android/security/AndroidKeyStoreMaintenance.java
@@ -47,7 +47,6 @@
      * @hide
      */
     public static int onUserAdded(@NonNull int userId) {
-        if (!android.security.keystore2.AndroidKeyStoreProvider.isInstalled()) return 0;
         try {
             getService().onUserAdded(userId);
             return 0;
@@ -68,7 +67,6 @@
      * @hide
      */
     public static int onUserRemoved(int userId) {
-        if (!android.security.keystore2.AndroidKeyStoreProvider.isInstalled()) return 0;
         try {
             getService().onUserRemoved(userId);
             return 0;
@@ -91,7 +89,6 @@
      * @hide
      */
     public static int onUserPasswordChanged(int userId, @Nullable byte[] password) {
-        if (!android.security.keystore2.AndroidKeyStoreProvider.isInstalled()) return 0;
         try {
             getService().onUserPasswordChanged(userId, password);
             return 0;
@@ -109,7 +106,6 @@
      * be cleared.
      */
     public static int clearNamespace(@Domain int domain, long namespace) {
-        if (!android.security.keystore2.AndroidKeyStoreProvider.isInstalled()) return 0;
         try {
             getService().clearNamespace(domain, namespace);
             return 0;
@@ -144,7 +140,6 @@
      * Informs Keystore 2.0 that an off body event was detected.
      */
     public static void onDeviceOffBody() {
-        if (!android.security.keystore2.AndroidKeyStoreProvider.isInstalled()) return;
         try {
             getService().onDeviceOffBody();
         } catch (Exception e) {
diff --git a/keystore/java/android/security/Authorization.java b/keystore/java/android/security/Authorization.java
index 50a9082..bd72d45 100644
--- a/keystore/java/android/security/Authorization.java
+++ b/keystore/java/android/security/Authorization.java
@@ -48,7 +48,6 @@
      * @return 0 if successful or {@code ResponseCode.SYSTEM_ERROR}.
      */
     public static int addAuthToken(@NonNull HardwareAuthToken authToken) {
-        if (!android.security.keystore2.AndroidKeyStoreProvider.isInstalled()) return 0;
         try {
             getService().addAuthToken(authToken);
             return 0;
@@ -80,7 +79,6 @@
      */
     public static int onLockScreenEvent(@NonNull boolean locked, @NonNull int userId,
             @Nullable byte[] syntheticPassword) {
-        if (!android.security.keystore2.AndroidKeyStoreProvider.isInstalled()) return 0;
         try {
             if (locked) {
                 getService().onLockScreenEvent(LockScreenEvent.LOCK, userId, null);
diff --git a/keystore/java/android/security/Credentials.java b/keystore/java/android/security/Credentials.java
index ae9f8664..28c601b 100644
--- a/keystore/java/android/security/Credentials.java
+++ b/keystore/java/android/security/Credentials.java
@@ -208,78 +208,4 @@
             pr.close();
         }
     }
-
-    /**
-     * Delete all types (private key, user certificate, CA certificate) for a
-     * particular {@code alias}. All three can exist for any given alias.
-     * Returns {@code true} if the alias no longer contains any types.
-     */
-    public static boolean deleteAllTypesForAlias(KeyStore keystore, String alias) {
-        return deleteAllTypesForAlias(keystore, alias, KeyStore.UID_SELF);
-    }
-
-    /**
-     * Delete all types (private key, user certificate, CA certificate) for a
-     * particular {@code alias}. All three can exist for any given alias.
-     * Returns {@code true} if the alias no longer contains any types.
-     */
-    public static boolean deleteAllTypesForAlias(KeyStore keystore, String alias, int uid) {
-        /*
-         * Make sure every type is deleted. There can be all three types, so
-         * don't use a conditional here.
-         */
-        return deleteUserKeyTypeForAlias(keystore, alias, uid)
-                & deleteCertificateTypesForAlias(keystore, alias, uid);
-    }
-
-    /**
-     * Delete certificate types (user certificate, CA certificate) for a
-     * particular {@code alias}. Both can exist for any given alias.
-     * Returns {@code true} if the alias no longer contains either type.
-     */
-    public static boolean deleteCertificateTypesForAlias(KeyStore keystore, String alias) {
-        return deleteCertificateTypesForAlias(keystore, alias, KeyStore.UID_SELF);
-    }
-
-    /**
-     * Delete certificate types (user certificate, CA certificate) for a
-     * particular {@code alias}. Both can exist for any given alias.
-     * Returns {@code true} if the alias no longer contains either type.
-     */
-    public static boolean deleteCertificateTypesForAlias(KeyStore keystore, String alias, int uid) {
-        /*
-         * Make sure every certificate type is deleted. There can be two types,
-         * so don't use a conditional here.
-         */
-        return keystore.delete(Credentials.USER_CERTIFICATE + alias, uid)
-                & keystore.delete(Credentials.CA_CERTIFICATE + alias, uid);
-    }
-
-    /**
-     * Delete user key for a particular {@code alias}.
-     * Returns {@code true} if the entry no longer exists.
-     */
-    public static boolean deleteUserKeyTypeForAlias(KeyStore keystore, String alias) {
-        return deleteUserKeyTypeForAlias(keystore, alias, KeyStore.UID_SELF);
-    }
-
-    /**
-     * Delete user key for a particular {@code alias}.
-     * Returns {@code true} if the entry no longer exists.
-     */
-    public static boolean deleteUserKeyTypeForAlias(KeyStore keystore, String alias, int uid) {
-        int ret = keystore.delete2(Credentials.USER_PRIVATE_KEY + alias, uid);
-        if (ret == KeyStore.KEY_NOT_FOUND) {
-            return keystore.delete(Credentials.USER_SECRET_KEY + alias, uid);
-        }
-        return ret == KeyStore.NO_ERROR;
-    }
-
-    /**
-     * Delete legacy prefixed entry for a particular {@code alias}
-     * Returns {@code true} if the entry no longer exists.
-     */
-    public static boolean deleteLegacyKeyForAlias(KeyStore keystore, String alias, int uid) {
-        return keystore.delete(Credentials.USER_SECRET_KEY + alias, uid);
-    }
 }
diff --git a/keystore/java/android/security/KeyChain.java b/keystore/java/android/security/KeyChain.java
index d59ca98..fd0db93 100644
--- a/keystore/java/android/security/KeyChain.java
+++ b/keystore/java/android/security/KeyChain.java
@@ -37,7 +37,6 @@
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.os.UserManager;
-import android.security.keystore.AndroidKeyStoreProvider;
 import android.security.keystore.KeyPermanentlyInvalidatedException;
 import android.security.keystore.KeyProperties;
 import android.system.keystore2.Domain;
@@ -676,23 +675,13 @@
             return null;
         }
 
-        if (AndroidKeyStoreProvider.isKeystore2Enabled()) {
-            try {
-                return android.security.keystore2.AndroidKeyStoreProvider
-                        .loadAndroidKeyStoreKeyPairFromKeystore(
-                                KeyStore2.getInstance(),
-                                getGrantDescriptor(keyId));
-            } catch (UnrecoverableKeyException | KeyPermanentlyInvalidatedException e) {
-                throw new KeyChainException(e);
-            }
-        } else {
-            try {
-                return AndroidKeyStoreProvider.loadAndroidKeyStoreKeyPairFromKeystore(
-                        KeyStore.getInstance(), keyId, KeyStore.UID_SELF);
-            } catch (RuntimeException | UnrecoverableKeyException
-                    | KeyPermanentlyInvalidatedException e) {
-                throw new KeyChainException(e);
-            }
+        try {
+            return android.security.keystore2.AndroidKeyStoreProvider
+                    .loadAndroidKeyStoreKeyPairFromKeystore(
+                            KeyStore2.getInstance(),
+                            getGrantDescriptor(keyId));
+        } catch (UnrecoverableKeyException | KeyPermanentlyInvalidatedException e) {
+            throw new KeyChainException(e);
         }
     }
 
diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java
index b05149e..a954344 100644
--- a/keystore/java/android/security/KeyStore.java
+++ b/keystore/java/android/security/KeyStore.java
@@ -16,53 +16,11 @@
 
 package android.security;
 
-import android.app.ActivityThread;
-import android.app.Application;
-import android.app.KeyguardManager;
 import android.compat.annotation.UnsupportedAppUsage;
-import android.content.Context;
-import android.hardware.biometrics.BiometricManager;
-import android.os.Binder;
 import android.os.Build;
-import android.os.IBinder;
-import android.os.Process;
-import android.os.RemoteException;
-import android.os.ServiceManager;
 import android.os.UserHandle;
-import android.security.keymaster.ExportResult;
-import android.security.keymaster.KeyCharacteristics;
-import android.security.keymaster.KeymasterArguments;
-import android.security.keymaster.KeymasterBlob;
-import android.security.keymaster.KeymasterCertificateChain;
-import android.security.keymaster.KeymasterDefs;
-import android.security.keymaster.OperationResult;
-import android.security.keystore.IKeystoreService;
-import android.security.keystore.KeyExpiredException;
-import android.security.keystore.KeyNotYetValidException;
-import android.security.keystore.KeyPermanentlyInvalidatedException;
-import android.security.keystore.KeyProperties;
-import android.security.keystore.KeystoreResponse;
-import android.security.keystore.UserNotAuthenticatedException;
 import android.security.maintenance.UserState;
 import android.system.keystore2.Domain;
-import android.util.Log;
-
-import com.android.internal.org.bouncycastle.asn1.ASN1InputStream;
-import com.android.internal.org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.math.BigInteger;
-import java.security.InvalidKeyException;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-import java.util.Locale;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ExecutionException;
-
-import sun.security.util.ObjectIdentifier;
-import sun.security.x509.AlgorithmId;
 
 /**
  * @hide This should not be made public in its present form because it
@@ -75,79 +33,10 @@
     // ResponseCodes - see system/security/keystore/include/keystore/keystore.h
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
     public static final int NO_ERROR = 1;
-    public static final int LOCKED = 2;
-    public static final int UNINITIALIZED = 3;
-    public static final int SYSTEM_ERROR = 4;
-    public static final int PROTOCOL_ERROR = 5;
-    public static final int PERMISSION_DENIED = 6;
-    public static final int KEY_NOT_FOUND = 7;
-    public static final int VALUE_CORRUPTED = 8;
-    public static final int UNDEFINED_ACTION = 9;
-    public static final int WRONG_PASSWORD = 10;
-    public static final int KEY_ALREADY_EXISTS = 16;
-    public static final int CANNOT_ATTEST_IDS = -66;
-    public static final int HARDWARE_TYPE_UNAVAILABLE = -68;
-
-    /**
-     * Per operation authentication is needed before this operation is valid.
-     * This is returned from {@link #begin} when begin succeeds but the operation uses
-     * per-operation authentication and must authenticate before calling {@link #update} or
-     * {@link #finish}.
-     */
-    public static final int OP_AUTH_NEEDED = 15;
-
-    // Used when a user changes their pin, invalidating old auth bound keys.
-    public static final int KEY_PERMANENTLY_INVALIDATED = 17;
 
     // Used for UID field to indicate the calling UID.
     public static final int UID_SELF = -1;
 
-    // Flags for "put" "import" and "generate"
-    public static final int FLAG_NONE = 0;
-
-    /**
-     * Indicates that this key (or key pair) must be encrypted at rest. This will protect the key
-     * (or key pair) with the secure lock screen credential (e.g., password, PIN, or pattern).
-     *
-     * <p>Note that this requires that the secure lock screen (e.g., password, PIN, pattern) is set
-     * up, otherwise key (or key pair) generation or import will fail. Moreover, this key (or key
-     * pair) will be deleted when the secure lock screen is disabled or reset (e.g., by the user or
-     * a Device Administrator). Finally, this key (or key pair) cannot be used until the user
-     * unlocks the secure lock screen after boot.
-     *
-     * @see KeyguardManager#isDeviceSecure()
-     */
-    public static final int FLAG_ENCRYPTED = 1;
-
-    /**
-     * Select Software keymaster device, which as of this writing is the lowest security
-     * level available on an android device. If neither FLAG_STRONGBOX nor FLAG_SOFTWARE is provided
-     * A TEE based keymaster implementation is implied.
-     *
-     * Need to be in sync with KeyStoreFlag in system/security/keystore/include/keystore/keystore.h
-     * For historical reasons this corresponds to the KEYSTORE_FLAG_FALLBACK flag.
-     */
-    public static final int FLAG_SOFTWARE = 1 << 1;
-
-    /**
-     * A private flag that's only available to system server to indicate that this key is part of
-     * device encryption flow so it receives special treatment from keystore. For example this key
-     * will not be super encrypted, and it will be stored separately under an unique UID instead
-     * of the caller UID i.e. SYSTEM.
-     *
-     * Need to be in sync with KeyStoreFlag in system/security/keystore/include/keystore/keystore.h
-     */
-    public static final int FLAG_CRITICAL_TO_DEVICE_ENCRYPTION = 1 << 3;
-
-    /**
-     * Select Strongbox keymaster device, which as of this writing the the highest security level
-     * available an android devices. If neither FLAG_STRONGBOX nor FLAG_SOFTWARE is provided
-     * A TEE based keymaster implementation is implied.
-     *
-     * Need to be in sync with KeyStoreFlag in system/security/keystore/include/keystore/keystore.h
-     */
-    public static final int FLAG_STRONGBOX = 1 << 4;
-
     // States
     public enum State {
         @UnsupportedAppUsage
@@ -157,853 +46,87 @@
         UNINITIALIZED
     };
 
-    private int mError = NO_ERROR;
-
-    private final IKeystoreService mBinder;
-    private final Context mContext;
-
-    private IBinder mToken;
-
-    private KeyStore(IKeystoreService binder) {
-        mBinder = binder;
-        mContext = getApplicationContext();
-    }
-
-    @UnsupportedAppUsage
-    public static Context getApplicationContext() {
-        Application application = ActivityThread.currentApplication();
-        if (application == null) {
-            throw new IllegalStateException(
-                    "Failed to obtain application Context from ActivityThread");
-        }
-        return application;
-    }
+    private static final KeyStore KEY_STORE = new KeyStore();
 
     @UnsupportedAppUsage
     public static KeyStore getInstance() {
-        IKeystoreService keystore = IKeystoreService.Stub.asInterface(ServiceManager
-                .getService("android.security.keystore"));
-        return new KeyStore(keystore);
+        return KEY_STORE;
     }
 
-    private synchronized IBinder getToken() {
-        if (mToken == null) {
-            mToken = new Binder();
-        }
-        return mToken;
-    }
-
+    /** @hide */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
     public State state(int userId) {
-        final int ret;
-        try {
-            if (android.security.keystore2.AndroidKeyStoreProvider.isInstalled()) {
-                int userState = AndroidKeyStoreMaintenance.getState(userId);
-                switch (userState) {
-                    case UserState.UNINITIALIZED:
-                        return KeyStore.State.UNINITIALIZED;
-                    case UserState.LSKF_UNLOCKED:
-                        return KeyStore.State.UNLOCKED;
-                    case UserState.LSKF_LOCKED:
-                        return KeyStore.State.LOCKED;
-                    default:
-                        throw new AssertionError(userState);
-                }
-            }
-            ret = mBinder.getState(userId);
-        } catch (RemoteException e) {
-            Log.w(TAG, "Cannot connect to keystore", e);
-            throw new AssertionError(e);
-        }
-
-        switch (ret) {
-            case NO_ERROR: return State.UNLOCKED;
-            case LOCKED: return State.LOCKED;
-            case UNINITIALIZED: return State.UNINITIALIZED;
-            default: throw new AssertionError(mError);
+        int userState = AndroidKeyStoreMaintenance.getState(userId);
+        switch (userState) {
+            case UserState.UNINITIALIZED:
+                return KeyStore.State.UNINITIALIZED;
+            case UserState.LSKF_UNLOCKED:
+                return KeyStore.State.UNLOCKED;
+            case UserState.LSKF_LOCKED:
+                return KeyStore.State.LOCKED;
+            default:
+                throw new AssertionError(userState);
         }
     }
 
+    /** @hide */
     @UnsupportedAppUsage
     public State state() {
         return state(UserHandle.myUserId());
     }
 
-    public boolean isUnlocked() {
-        return state() == State.UNLOCKED;
-    }
-
-    public byte[] get(String key, int uid) {
-        return get(key, uid, false);
-    }
-
+    /** @hide */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
     public byte[] get(String key) {
-        return get(key, UID_SELF);
+        return null;
     }
 
-    public byte[] get(String key, int uid, boolean suppressKeyNotFoundWarning) {
-        try {
-            key = key != null ? key : "";
-            return mBinder.get(key, uid);
-        } catch (RemoteException e) {
-             Log.w(TAG, "Cannot connect to keystore", e);
-            return null;
-        } catch (android.os.ServiceSpecificException e) {
-            if (!suppressKeyNotFoundWarning || e.errorCode != KEY_NOT_FOUND) {
-                Log.w(TAG, "KeyStore exception", e);
-            }
-            return null;
-        }
-    }
-
-    public byte[] get(String key, boolean suppressKeyNotFoundWarning) {
-        return get(key, UID_SELF, suppressKeyNotFoundWarning);
-    }
-
-
-    public boolean put(String key, byte[] value, int uid, int flags) {
-        return insert(key, value, uid, flags) == NO_ERROR;
-    }
-
-    public int insert(String key, byte[] value, int uid, int flags) {
-        try {
-            if (value == null) {
-                value = new byte[0];
-            }
-            int error = mBinder.insert(key, value, uid, flags);
-            if (error == KEY_ALREADY_EXISTS) {
-                mBinder.del(key, uid);
-                error = mBinder.insert(key, value, uid, flags);
-            }
-            return error;
-        } catch (RemoteException e) {
-            Log.w(TAG, "Cannot connect to keystore", e);
-            return SYSTEM_ERROR;
-        }
-    }
-
-    int delete2(String key, int uid) {
-        try {
-            return mBinder.del(key, uid);
-        } catch (RemoteException e) {
-            Log.w(TAG, "Cannot connect to keystore", e);
-            return SYSTEM_ERROR;
-        }
-    }
-
-    public boolean delete(String key, int uid) {
-        int ret = delete2(key, uid);
-        return ret == NO_ERROR || ret == KEY_NOT_FOUND;
-    }
-
+    /** @hide */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
     public boolean delete(String key) {
-        return delete(key, UID_SELF);
-    }
-
-    public boolean contains(String key, int uid) {
-        try {
-            return mBinder.exist(key, uid) == NO_ERROR;
-        } catch (RemoteException e) {
-            Log.w(TAG, "Cannot connect to keystore", e);
-            return false;
-        }
-    }
-
-    public boolean contains(String key) {
-        return contains(key, UID_SELF);
-    }
-
-    /**
-     * List all entries in the keystore for {@code uid} starting with {@code prefix}.
-     */
-    public String[] list(String prefix, int uid) {
-        try {
-            return mBinder.list(prefix, uid);
-        } catch (RemoteException e) {
-            Log.w(TAG, "Cannot connect to keystore", e);
-            return null;
-        } catch (android.os.ServiceSpecificException e) {
-            Log.w(TAG, "KeyStore exception", e);
-            return null;
-        }
+        return false;
     }
 
     /**
      * List uids of all keys that are auth bound to the current user.
      * Only system is allowed to call this method.
+     * @hide
+     * @deprecated This function always returns null.
      */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
     public int[] listUidsOfAuthBoundKeys() {
-        // uids are returned as a list of strings because list of integers
-        // as an output parameter is not supported by aidl-cpp.
-        List<String> uidsOut = new ArrayList<>();
-        try {
-            int rc = mBinder.listUidsOfAuthBoundKeys(uidsOut);
-            if (rc != NO_ERROR) {
-                Log.w(TAG, String.format("listUidsOfAuthBoundKeys failed with error code %d", rc));
-                return null;
-            }
-        } catch (RemoteException e) {
-            Log.w(TAG, "Cannot connect to keystore", e);
-            return null;
-        } catch (android.os.ServiceSpecificException e) {
-            Log.w(TAG, "KeyStore exception", e);
-            return null;
-        }
-        // Turn list of strings into an array of uid integers.
-        return uidsOut.stream().mapToInt(Integer::parseInt).toArray();
-   }
-
-    public String[] list(String prefix) {
-        return list(prefix, UID_SELF);
+        return null;
     }
 
+
     /**
-     * Attempt to lock the keystore for {@code user}.
-     *
-     * @param userId Android user to lock.
-     * @return whether {@code user}'s keystore was locked.
+     * @hide
+     * @deprecated This function has no effect.
      */
-    public boolean lock(int userId) {
-        try {
-            return mBinder.lock(userId) == NO_ERROR;
-        } catch (RemoteException e) {
-            Log.w(TAG, "Cannot connect to keystore", e);
-            return false;
-        }
-    }
-
-    public boolean lock() {
-        return lock(UserHandle.myUserId());
-    }
-
-    /**
-     * Attempt to unlock the keystore for {@code user} with the password {@code password}.
-     * This is required before keystore entries created with FLAG_ENCRYPTED can be accessed or
-     * created.
-     *
-     * @param userId Android user ID to operate on
-     * @param password user's keystore password. Should be the most recent value passed to
-     * {@link #onUserPasswordChanged} for the user.
-     *
-     * @return whether the keystore was unlocked.
-     */
-    public boolean unlock(int userId, String password) {
-        try {
-            password = password != null ? password : "";
-            mError = mBinder.unlock(userId, password);
-            return mError == NO_ERROR;
-        } catch (RemoteException e) {
-            Log.w(TAG, "Cannot connect to keystore", e);
-            return false;
-        }
-    }
-
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
     public boolean unlock(String password) {
-        return unlock(UserHandle.getUserId(Process.myUid()), password);
+        return false;
     }
 
     /**
-     * Check if the keystore for {@code userId} is empty.
+     *
+     * @return
+     * @deprecated This function always returns true.
+     * @hide
      */
-    public boolean isEmpty(int userId) {
-        try {
-            return mBinder.isEmpty(userId) != 0;
-        } catch (RemoteException e) {
-            Log.w(TAG, "Cannot connect to keystore", e);
-            return false;
-        }
-    }
-
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public boolean isEmpty() {
-        return isEmpty(UserHandle.myUserId());
-    }
-
-    public String grant(String key, int uid) {
-        try {
-            String grantAlias =  mBinder.grant(key, uid);
-            if (grantAlias == "") return null;
-            return grantAlias;
-        } catch (RemoteException e) {
-            Log.w(TAG, "Cannot connect to keystore", e);
-            return null;
-        }
-    }
-
-    public boolean ungrant(String key, int uid) {
-        try {
-            return mBinder.ungrant(key, uid) == NO_ERROR;
-        } catch (RemoteException e) {
-            Log.w(TAG, "Cannot connect to keystore", e);
-            return false;
-        }
-    }
-
-    /**
-     * Returns the last modification time of the key in milliseconds since the
-     * epoch. Will return -1L if the key could not be found or other error.
-     */
-    public long getmtime(String key, int uid) {
-        try {
-            final long millis = mBinder.getmtime(key, uid);
-            if (millis == -1L) {
-                return -1L;
-            }
-
-            return millis * 1000L;
-        } catch (RemoteException e) {
-            Log.w(TAG, "Cannot connect to keystore", e);
-            return -1L;
-        }
-    }
-
-    public long getmtime(String key) {
-        return getmtime(key, UID_SELF);
-    }
-
-    // TODO: remove this when it's removed from Settings
-    public boolean isHardwareBacked() {
-        return isHardwareBacked("RSA");
-    }
-
-    public boolean isHardwareBacked(String keyType) {
-        try {
-            return mBinder.is_hardware_backed(keyType.toUpperCase(Locale.US)) == NO_ERROR;
-        } catch (RemoteException e) {
-            Log.w(TAG, "Cannot connect to keystore", e);
-            return false;
-        }
-    }
-
-    public boolean clearUid(int uid) {
-        try {
-            if (android.security.keystore2.AndroidKeyStoreProvider.isInstalled()) {
-                return AndroidKeyStoreMaintenance.clearNamespace(Domain.APP, uid) == 0;
-            }
-            return mBinder.clear_uid(uid) == NO_ERROR;
-        } catch (RemoteException e) {
-            Log.w(TAG, "Cannot connect to keystore", e);
-            return false;
-        }
-    }
-
-    public int getLastError() {
-        return mError;
-    }
-
-    public boolean addRngEntropy(byte[] data, int flags) {
-        KeystoreResultPromise promise = new KeystoreResultPromise();
-        try {
-            mBinder.asBinder().linkToDeath(promise, 0);
-            int errorCode = mBinder.addRngEntropy(promise, data, flags);
-            if (errorCode == NO_ERROR) {
-                return interruptedPreservingGet(promise.getFuture()).getErrorCode() == NO_ERROR;
-            } else {
-                return false;
-            }
-        } catch (RemoteException e) {
-            Log.w(TAG, "Cannot connect to keystore", e);
-            return false;
-        } catch (ExecutionException e) {
-            Log.e(TAG, "AddRngEntropy completed with exception", e);
-            return false;
-        } finally {
-            mBinder.asBinder().unlinkToDeath(promise, 0);
-        }
-    }
-
-    private class KeyCharacteristicsCallbackResult {
-        private KeystoreResponse keystoreResponse;
-        private KeyCharacteristics keyCharacteristics;
-
-        public KeyCharacteristicsCallbackResult(KeystoreResponse keystoreResponse,
-                                                KeyCharacteristics keyCharacteristics) {
-            this.keystoreResponse = keystoreResponse;
-            this.keyCharacteristics = keyCharacteristics;
-        }
-
-        public KeystoreResponse getKeystoreResponse() {
-            return keystoreResponse;
-        }
-
-        public void setKeystoreResponse(KeystoreResponse keystoreResponse) {
-            this.keystoreResponse = keystoreResponse;
-        }
-
-        public KeyCharacteristics getKeyCharacteristics() {
-            return keyCharacteristics;
-        }
-
-        public void setKeyCharacteristics(KeyCharacteristics keyCharacteristics) {
-            this.keyCharacteristics = keyCharacteristics;
-        }
-    }
-
-    private class KeyCharacteristicsPromise
-            extends android.security.keystore.IKeystoreKeyCharacteristicsCallback.Stub
-            implements IBinder.DeathRecipient {
-        final private CompletableFuture<KeyCharacteristicsCallbackResult> future =
-                new CompletableFuture<KeyCharacteristicsCallbackResult>();
-        @Override
-        public void onFinished(KeystoreResponse keystoreResponse,
-                               KeyCharacteristics keyCharacteristics)
-                                       throws android.os.RemoteException {
-            future.complete(
-                    new KeyCharacteristicsCallbackResult(keystoreResponse, keyCharacteristics));
-        }
-        public final CompletableFuture<KeyCharacteristicsCallbackResult> getFuture() {
-            return future;
-        }
-        @Override
-        public void binderDied() {
-            future.completeExceptionally(new RemoteException("Keystore died"));
-        }
-    };
-
-    private int generateKeyInternal(String alias, KeymasterArguments args, byte[] entropy, int uid,
-            int flags, KeyCharacteristics outCharacteristics)
-                    throws RemoteException, ExecutionException {
-        KeyCharacteristicsPromise promise = new KeyCharacteristicsPromise();
-        int error = NO_ERROR;
-        KeyCharacteristicsCallbackResult result = null;
-        try {
-            mBinder.asBinder().linkToDeath(promise, 0);
-            error = mBinder.generateKey(promise, alias, args, entropy, uid, flags);
-            if (error != NO_ERROR) {
-                Log.e(TAG, "generateKeyInternal failed on request " + error);
-                return error;
-            }
-            result = interruptedPreservingGet(promise.getFuture());
-        } finally {
-            mBinder.asBinder().unlinkToDeath(promise, 0);
-        }
-
-        error = result.getKeystoreResponse().getErrorCode();
-        if (error != NO_ERROR) {
-            Log.e(TAG, "generateKeyInternal failed on response " + error);
-            return error;
-        }
-        KeyCharacteristics characteristics = result.getKeyCharacteristics();
-        if (characteristics == null) {
-            Log.e(TAG, "generateKeyInternal got empty key characteristics " + error);
-            return SYSTEM_ERROR;
-        }
-        outCharacteristics.shallowCopyFrom(characteristics);
-        return NO_ERROR;
-    }
-
-    public int generateKey(String alias, KeymasterArguments args, byte[] entropy, int uid,
-            int flags, KeyCharacteristics outCharacteristics) {
-        try {
-            entropy = entropy != null ? entropy : new byte[0];
-            args = args != null ? args : new KeymasterArguments();
-            int error = generateKeyInternal(alias, args, entropy, uid, flags, outCharacteristics);
-            if (error == KEY_ALREADY_EXISTS) {
-                mBinder.del(alias, uid);
-                error = generateKeyInternal(alias, args, entropy, uid, flags, outCharacteristics);
-            }
-            return error;
-        } catch (RemoteException e) {
-            Log.w(TAG, "Cannot connect to keystore", e);
-            return SYSTEM_ERROR;
-        } catch (ExecutionException e) {
-            Log.e(TAG, "generateKey completed with exception", e);
-            return SYSTEM_ERROR;
-        }
-    }
-
-    public int generateKey(String alias, KeymasterArguments args, byte[] entropy, int flags,
-            KeyCharacteristics outCharacteristics) {
-        return generateKey(alias, args, entropy, UID_SELF, flags, outCharacteristics);
-    }
-
-    public int getKeyCharacteristics(String alias, KeymasterBlob clientId, KeymasterBlob appId,
-            int uid, KeyCharacteristics outCharacteristics) {
-        KeyCharacteristicsPromise promise = new KeyCharacteristicsPromise();
-        try {
-            mBinder.asBinder().linkToDeath(promise, 0);
-            clientId = clientId != null ? clientId : new KeymasterBlob(new byte[0]);
-            appId = appId != null ? appId : new KeymasterBlob(new byte[0]);
-
-            int error = mBinder.getKeyCharacteristics(promise, alias, clientId, appId, uid);
-            if (error != NO_ERROR) return error;
-
-            KeyCharacteristicsCallbackResult result = interruptedPreservingGet(promise.getFuture());
-            error = result.getKeystoreResponse().getErrorCode();
-            if (error != NO_ERROR) return error;
-
-            KeyCharacteristics characteristics = result.getKeyCharacteristics();
-            if (characteristics == null) return SYSTEM_ERROR;
-            outCharacteristics.shallowCopyFrom(characteristics);
-            return NO_ERROR;
-        } catch (RemoteException e) {
-            Log.w(TAG, "Cannot connect to keystore", e);
-            return SYSTEM_ERROR;
-        } catch (ExecutionException e) {
-            Log.e(TAG, "GetKeyCharacteristics completed with exception", e);
-            return SYSTEM_ERROR;
-        } finally {
-            mBinder.asBinder().unlinkToDeath(promise, 0);
-        }
-    }
-
-    public int getKeyCharacteristics(String alias, KeymasterBlob clientId, KeymasterBlob appId,
-            KeyCharacteristics outCharacteristics) {
-        return getKeyCharacteristics(alias, clientId, appId, UID_SELF, outCharacteristics);
-    }
-
-    private int importKeyInternal(String alias, KeymasterArguments args, int format, byte[] keyData,
-            int uid, int flags, KeyCharacteristics outCharacteristics)
-                    throws RemoteException, ExecutionException {
-        KeyCharacteristicsPromise promise = new KeyCharacteristicsPromise();
-        mBinder.asBinder().linkToDeath(promise, 0);
-        try {
-            int error = mBinder.importKey(promise, alias, args, format, keyData, uid, flags);
-            if (error != NO_ERROR) return error;
-
-            KeyCharacteristicsCallbackResult result = interruptedPreservingGet(promise.getFuture());
-
-            error = result.getKeystoreResponse().getErrorCode();
-            if (error != NO_ERROR) return error;
-
-            KeyCharacteristics characteristics = result.getKeyCharacteristics();
-            if (characteristics == null) return SYSTEM_ERROR;
-            outCharacteristics.shallowCopyFrom(characteristics);
-            return NO_ERROR;
-        } finally {
-            mBinder.asBinder().unlinkToDeath(promise, 0);
-        }
-    }
-
-    public int importKey(String alias, KeymasterArguments args, int format, byte[] keyData,
-            int uid, int flags, KeyCharacteristics outCharacteristics) {
-        try {
-            int error = importKeyInternal(alias, args, format, keyData, uid, flags,
-                    outCharacteristics);
-            if (error == KEY_ALREADY_EXISTS) {
-                mBinder.del(alias, uid);
-                error = importKeyInternal(alias, args, format, keyData, uid, flags,
-                        outCharacteristics);
-            }
-            return error;
-        } catch (RemoteException e) {
-            Log.w(TAG, "Cannot connect to keystore", e);
-            return SYSTEM_ERROR;
-        } catch (ExecutionException e) {
-            Log.e(TAG, "ImportKey completed with exception", e);
-            return SYSTEM_ERROR;
-        }
-    }
-
-    public int importKey(String alias, KeymasterArguments args, int format, byte[] keyData,
-            int flags, KeyCharacteristics outCharacteristics) {
-        return importKey(alias, args, format, keyData, UID_SELF, flags, outCharacteristics);
-    }
-
-    private String getAlgorithmFromPKCS8(byte[] keyData) {
-        try {
-            final ASN1InputStream bIn = new ASN1InputStream(new ByteArrayInputStream(keyData));
-            final PrivateKeyInfo pki = PrivateKeyInfo.getInstance(bIn.readObject());
-            final String algOid = pki.getPrivateKeyAlgorithm().getAlgorithm().getId();
-            return new AlgorithmId(new ObjectIdentifier(algOid)).getName();
-        } catch (IOException e) {
-            Log.e(TAG, "getAlgorithmFromPKCS8 Failed to parse key data");
-            Log.e(TAG, Log.getStackTraceString(e));
-            return null;
-        }
-    }
-
-    private KeymasterArguments makeLegacyArguments(String algorithm) {
-        KeymasterArguments args = new KeymasterArguments();
-        args.addEnum(KeymasterDefs.KM_TAG_ALGORITHM,
-                KeyProperties.KeyAlgorithm.toKeymasterAsymmetricKeyAlgorithm(algorithm));
-        args.addEnum(KeymasterDefs.KM_TAG_PURPOSE, KeymasterDefs.KM_PURPOSE_SIGN);
-        args.addEnum(KeymasterDefs.KM_TAG_PURPOSE, KeymasterDefs.KM_PURPOSE_VERIFY);
-        args.addEnum(KeymasterDefs.KM_TAG_PURPOSE, KeymasterDefs.KM_PURPOSE_ENCRYPT);
-        args.addEnum(KeymasterDefs.KM_TAG_PURPOSE, KeymasterDefs.KM_PURPOSE_DECRYPT);
-        args.addEnum(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_NONE);
-        if (algorithm.equalsIgnoreCase(KeyProperties.KEY_ALGORITHM_RSA)) {
-            args.addEnum(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_RSA_OAEP);
-            args.addEnum(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_RSA_PKCS1_1_5_ENCRYPT);
-            args.addEnum(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_RSA_PKCS1_1_5_SIGN);
-            args.addEnum(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_RSA_PSS);
-        }
-        args.addEnum(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_NONE);
-        args.addEnum(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_MD5);
-        args.addEnum(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_SHA1);
-        args.addEnum(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_SHA_2_224);
-        args.addEnum(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_SHA_2_256);
-        args.addEnum(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_SHA_2_384);
-        args.addEnum(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_SHA_2_512);
-        args.addBoolean(KeymasterDefs.KM_TAG_NO_AUTH_REQUIRED);
-        args.addDate(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME, new Date(Long.MAX_VALUE));
-        args.addDate(KeymasterDefs.KM_TAG_USAGE_EXPIRE_DATETIME, new Date(Long.MAX_VALUE));
-        args.addDate(KeymasterDefs.KM_TAG_ACTIVE_DATETIME, new Date(0));
-        return args;
-    }
-
-    public boolean importKey(String alias, byte[] keyData, int uid, int flags) {
-        String algorithm = getAlgorithmFromPKCS8(keyData);
-        if (algorithm == null) return false;
-        KeymasterArguments args = makeLegacyArguments(algorithm);
-        KeyCharacteristics out = new KeyCharacteristics();
-        int result =  importKey(alias, args, KeymasterDefs.KM_KEY_FORMAT_PKCS8, keyData, uid,
-                                flags, out);
-        if (result != NO_ERROR) {
-            Log.e(TAG, Log.getStackTraceString(
-                    new KeyStoreException(result, "legacy key import failed")));
-            return false;
-        }
         return true;
     }
 
-    private int importWrappedKeyInternal(String wrappedKeyAlias, byte[] wrappedKey,
-            String wrappingKeyAlias,
-            byte[] maskingKey, KeymasterArguments args, long rootSid, long fingerprintSid,
-            KeyCharacteristics outCharacteristics)
-                    throws RemoteException, ExecutionException {
-        KeyCharacteristicsPromise promise = new KeyCharacteristicsPromise();
-        mBinder.asBinder().linkToDeath(promise, 0);
-        try {
-            int error = mBinder.importWrappedKey(promise, wrappedKeyAlias, wrappedKey,
-                    wrappingKeyAlias, maskingKey, args, rootSid, fingerprintSid);
-            if (error != NO_ERROR) return error;
-
-            KeyCharacteristicsCallbackResult result = interruptedPreservingGet(promise.getFuture());
-
-            error = result.getKeystoreResponse().getErrorCode();
-            if (error != NO_ERROR) return error;
-
-            KeyCharacteristics characteristics = result.getKeyCharacteristics();
-            if (characteristics == null) return SYSTEM_ERROR;
-            outCharacteristics.shallowCopyFrom(characteristics);
-            return NO_ERROR;
-        } finally {
-            mBinder.asBinder().unlinkToDeath(promise, 0);
-        }
-    }
-
-    public int importWrappedKey(String wrappedKeyAlias, byte[] wrappedKey,
-            String wrappingKeyAlias,
-            byte[] maskingKey, KeymasterArguments args, long rootSid, long fingerprintSid, int uid,
-            KeyCharacteristics outCharacteristics) {
-        // TODO b/119217337 uid parameter gets silently ignored.
-        try {
-            int error = importWrappedKeyInternal(wrappedKeyAlias, wrappedKey, wrappingKeyAlias,
-                    maskingKey, args, rootSid, fingerprintSid, outCharacteristics);
-            if (error == KEY_ALREADY_EXISTS) {
-                mBinder.del(wrappedKeyAlias, UID_SELF);
-                error = importWrappedKeyInternal(wrappedKeyAlias, wrappedKey, wrappingKeyAlias,
-                        maskingKey, args, rootSid, fingerprintSid, outCharacteristics);
-            }
-            return error;
-        } catch (RemoteException e) {
-            Log.w(TAG, "Cannot connect to keystore", e);
-            return SYSTEM_ERROR;
-        } catch (ExecutionException e) {
-            Log.e(TAG, "ImportWrappedKey completed with exception", e);
-            return SYSTEM_ERROR;
-        }
-    }
-
-    private class ExportKeyPromise
-            extends android.security.keystore.IKeystoreExportKeyCallback.Stub
-            implements IBinder.DeathRecipient {
-        final private CompletableFuture<ExportResult> future = new CompletableFuture<ExportResult>();
-        @Override
-        public void onFinished(ExportResult exportKeyResult) throws android.os.RemoteException {
-            future.complete(exportKeyResult);
-        }
-        public final CompletableFuture<ExportResult> getFuture() {
-            return future;
-        }
-        @Override
-        public void binderDied() {
-            future.completeExceptionally(new RemoteException("Keystore died"));
-        }
-    };
-
-    public ExportResult exportKey(String alias, int format, KeymasterBlob clientId,
-            KeymasterBlob appId, int uid) {
-        ExportKeyPromise promise = new ExportKeyPromise();
-        try {
-            mBinder.asBinder().linkToDeath(promise, 0);
-            clientId = clientId != null ? clientId : new KeymasterBlob(new byte[0]);
-            appId = appId != null ? appId : new KeymasterBlob(new byte[0]);
-            int error = mBinder.exportKey(promise, alias, format, clientId, appId, uid);
-            if (error == NO_ERROR) {
-                return interruptedPreservingGet(promise.getFuture());
-            } else {
-                return new ExportResult(error);
-            }
-        } catch (RemoteException e) {
-            Log.w(TAG, "Cannot connect to keystore", e);
-            return null;
-        } catch (ExecutionException e) {
-            Log.e(TAG, "ExportKey completed with exception", e);
-            return null;
-        } finally {
-            mBinder.asBinder().unlinkToDeath(promise, 0);
-        }
-    }
-    public ExportResult exportKey(String alias, int format, KeymasterBlob clientId,
-            KeymasterBlob appId) {
-        return exportKey(alias, format, clientId, appId, UID_SELF);
-    }
-
-    private class OperationPromise
-            extends android.security.keystore.IKeystoreOperationResultCallback.Stub
-            implements IBinder.DeathRecipient {
-        final private CompletableFuture<OperationResult> future = new CompletableFuture<OperationResult>();
-        @Override
-        public void onFinished(OperationResult operationResult) throws android.os.RemoteException {
-            future.complete(operationResult);
-        }
-        public final CompletableFuture<OperationResult> getFuture() {
-            return future;
-        }
-        @Override
-        public void binderDied() {
-            future.completeExceptionally(new RemoteException("Keystore died"));
-        }
-    };
-
-    public OperationResult begin(String alias, int purpose, boolean pruneable,
-            KeymasterArguments args, byte[] entropy, int uid) {
-        OperationPromise promise = new OperationPromise();
-        try {
-            mBinder.asBinder().linkToDeath(promise, 0);
-            args = args != null ? args : new KeymasterArguments();
-            entropy = entropy != null ? entropy : new byte[0];
-            int errorCode =  mBinder.begin(promise, getToken(), alias, purpose, pruneable, args,
-                                           entropy, uid);
-            if (errorCode == NO_ERROR) {
-                return interruptedPreservingGet(promise.getFuture());
-            } else {
-                return new OperationResult(errorCode);
-            }
-        } catch (RemoteException e) {
-            Log.w(TAG, "Cannot connect to keystore", e);
-            return null;
-        } catch (ExecutionException e) {
-            Log.e(TAG, "Begin completed with exception", e);
-            return null;
-        } finally {
-            mBinder.asBinder().unlinkToDeath(promise, 0);
-        }
-    }
-
-    public OperationResult begin(String alias, int purpose, boolean pruneable,
-            KeymasterArguments args, byte[] entropy) {
-        entropy = entropy != null ? entropy : new byte[0];
-        args = args != null ? args : new KeymasterArguments();
-        return begin(alias, purpose, pruneable, args, entropy, UID_SELF);
-    }
-
-    public OperationResult update(IBinder token, KeymasterArguments arguments, byte[] input) {
-        OperationPromise promise = new OperationPromise();
-        try {
-            mBinder.asBinder().linkToDeath(promise, 0);
-            arguments = arguments != null ? arguments : new KeymasterArguments();
-            input = input != null ? input : new byte[0];
-            int errorCode =  mBinder.update(promise, token, arguments, input);
-            if (errorCode == NO_ERROR) {
-                return interruptedPreservingGet(promise.getFuture());
-            } else {
-                return new OperationResult(errorCode);
-            }
-        } catch (RemoteException e) {
-            Log.w(TAG, "Cannot connect to keystore", e);
-            return null;
-        } catch (ExecutionException e) {
-            Log.e(TAG, "Update completed with exception", e);
-            return null;
-        } finally {
-            mBinder.asBinder().unlinkToDeath(promise, 0);
-        }
-    }
-
     /**
-     * Android KeyStore finish operation.
-     *
-     * @param token Authentication token.
-     * @param arguments Keymaster arguments
-     * @param input Optional additional input data.
-     * @param signature Optional signature to be verified.
-     * @param entropy Optional additional entropy
-     * @return OperationResult that will indicate success or error of the operation.
+     * Forwards the request to clear a UID to Keystore 2.0.
+     * @hide
      */
-    public OperationResult finish(IBinder token, KeymasterArguments arguments, byte[] input,
-            byte[] signature, byte[] entropy) {
-        OperationPromise promise = new OperationPromise();
-        try {
-            mBinder.asBinder().linkToDeath(promise, 0);
-            arguments = arguments != null ? arguments : new KeymasterArguments();
-            entropy = entropy != null ? entropy : new byte[0];
-            input = input != null ? input : new byte[0];
-            signature = signature != null ? signature : new byte[0];
-            int errorCode = mBinder.finish(promise, token, arguments, input, signature, entropy);
-            if (errorCode == NO_ERROR) {
-                return interruptedPreservingGet(promise.getFuture());
-            } else {
-                return new OperationResult(errorCode);
-            }
-        } catch (RemoteException e) {
-            Log.w(TAG, "Cannot connect to keystore", e);
-            return null;
-        } catch (ExecutionException e) {
-            Log.e(TAG, "Finish completed with exception", e);
-            return null;
-        } finally {
-            mBinder.asBinder().unlinkToDeath(promise, 0);
-        }
+    public boolean clearUid(int uid) {
+        return AndroidKeyStoreMaintenance.clearNamespace(Domain.APP, uid) == 0;
     }
 
-    public OperationResult finish(IBinder token, KeymasterArguments arguments, byte[] signature) {
-        return finish(token, arguments, null, signature, null);
-    }
-
-    private class KeystoreResultPromise
-            extends android.security.keystore.IKeystoreResponseCallback.Stub
-            implements IBinder.DeathRecipient {
-        final private CompletableFuture<KeystoreResponse> future = new CompletableFuture<KeystoreResponse>();
-        @Override
-        public void onFinished(KeystoreResponse keystoreResponse) throws android.os.RemoteException {
-            future.complete(keystoreResponse);
-        }
-        public final CompletableFuture<KeystoreResponse> getFuture() {
-            return future;
-        }
-        @Override
-        public void binderDied() {
-            future.completeExceptionally(new RemoteException("Keystore died"));
-        }
-    };
-
-    public int abort(IBinder token) {
-        KeystoreResultPromise promise = new KeystoreResultPromise();
-        try {
-            mBinder.asBinder().linkToDeath(promise, 0);
-            int errorCode = mBinder.abort(promise, token);
-            if (errorCode == NO_ERROR) {
-                return interruptedPreservingGet(promise.getFuture()).getErrorCode();
-            } else {
-                return errorCode;
-            }
-        } catch (RemoteException e) {
-            Log.w(TAG, "Cannot connect to keystore", e);
-            return SYSTEM_ERROR;
-        } catch (ExecutionException e) {
-            Log.e(TAG, "Abort completed with exception", e);
-            return SYSTEM_ERROR;
-        } finally {
-            mBinder.asBinder().unlinkToDeath(promise, 0);
-        }
-    }
 
     /**
      * Add an authentication record to the keystore authorization table.
@@ -1013,191 +136,7 @@
      * a {@code KeymasterDefs.KM_ERROR_} value or {@code KeyStore} ResponseCode.
      */
     public int addAuthToken(byte[] authToken) {
-        try {
-            Authorization.addAuthToken(authToken);
-            return mBinder.addAuthToken(authToken);
-        } catch (RemoteException e) {
-            Log.w(TAG, "Cannot connect to keystore", e);
-            return SYSTEM_ERROR;
-        }
-    }
-
-    /**
-     * Notify keystore that a user's password has changed.
-     *
-     * @param userId the user whose password changed.
-     * @param newPassword the new password or "" if the password was removed.
-     */
-    public boolean onUserPasswordChanged(int userId, String newPassword) {
-        // Parcel.cpp doesn't support deserializing null strings and treats them as "". Make that
-        // explicit here.
-        if (newPassword == null) {
-            newPassword = "";
-        }
-        try {
-            return mBinder.onUserPasswordChanged(userId, newPassword) == NO_ERROR;
-        } catch (RemoteException e) {
-            Log.w(TAG, "Cannot connect to keystore", e);
-            return false;
-        }
-    }
-
-    /**
-     * Notify keystore that a user was added.
-     *
-     * @param userId the new user.
-     * @param parentId the parent of the new user, or -1 if the user has no parent. If parentId is
-     * specified then the new user's keystore will be intialized with the same secure lockscreen
-     * password as the parent.
-     */
-    public void onUserAdded(int userId, int parentId) {
-        try {
-            mBinder.onUserAdded(userId, parentId);
-        } catch (RemoteException e) {
-            Log.w(TAG, "Cannot connect to keystore", e);
-        }
-    }
-
-    /**
-     * Notify keystore that a user was added.
-     *
-     * @param userId the new user.
-     */
-    public void onUserAdded(int userId) {
-        onUserAdded(userId, -1);
-    }
-
-    /**
-     * Notify keystore that a user was removed.
-     *
-     * @param userId the removed user.
-     */
-    public void onUserRemoved(int userId) {
-        try {
-            mBinder.onUserRemoved(userId);
-        } catch (RemoteException e) {
-            Log.w(TAG, "Cannot connect to keystore", e);
-        }
-    }
-
-    public boolean onUserPasswordChanged(String newPassword) {
-        return onUserPasswordChanged(UserHandle.getUserId(Process.myUid()), newPassword);
-    }
-
-    /**
-     * Notify keystore about the latest user locked state. This is to support keyguard-bound key.
-     */
-    public void onUserLockedStateChanged(int userHandle, boolean locked) {
-        try {
-            mBinder.onKeyguardVisibilityChanged(locked, userHandle);
-        } catch (RemoteException e) {
-            Log.w(TAG, "Failed to update user locked state " + userHandle, e);
-        }
-    }
-
-    private class KeyAttestationCallbackResult {
-        private KeystoreResponse keystoreResponse;
-        private KeymasterCertificateChain certificateChain;
-
-        public KeyAttestationCallbackResult(KeystoreResponse keystoreResponse,
-                KeymasterCertificateChain certificateChain) {
-            this.keystoreResponse = keystoreResponse;
-            this.certificateChain = certificateChain;
-        }
-
-        public KeystoreResponse getKeystoreResponse() {
-            return keystoreResponse;
-        }
-
-        public void setKeystoreResponse(KeystoreResponse keystoreResponse) {
-            this.keystoreResponse = keystoreResponse;
-        }
-
-        public KeymasterCertificateChain getCertificateChain() {
-            return certificateChain;
-        }
-
-        public void setCertificateChain(KeymasterCertificateChain certificateChain) {
-            this.certificateChain = certificateChain;
-        }
-    }
-
-    private class CertificateChainPromise
-            extends android.security.keystore.IKeystoreCertificateChainCallback.Stub
-            implements IBinder.DeathRecipient {
-        final private CompletableFuture<KeyAttestationCallbackResult> future = new CompletableFuture<KeyAttestationCallbackResult>();
-        @Override
-        public void onFinished(KeystoreResponse keystoreResponse,
-                KeymasterCertificateChain certificateChain) throws android.os.RemoteException {
-            future.complete(new KeyAttestationCallbackResult(keystoreResponse, certificateChain));
-        }
-        public final CompletableFuture<KeyAttestationCallbackResult> getFuture() {
-            return future;
-        }
-        @Override
-        public void binderDied() {
-            future.completeExceptionally(new RemoteException("Keystore died"));
-        }
-    };
-
-
-    public int attestKey(
-            String alias, KeymasterArguments params, KeymasterCertificateChain outChain) {
-        CertificateChainPromise promise = new CertificateChainPromise();
-        try {
-            mBinder.asBinder().linkToDeath(promise, 0);
-            if (params == null) {
-                params = new KeymasterArguments();
-            }
-            if (outChain == null) {
-                outChain = new KeymasterCertificateChain();
-            }
-            int error = mBinder.attestKey(promise, alias, params);
-            if (error != NO_ERROR) return error;
-            KeyAttestationCallbackResult result = interruptedPreservingGet(promise.getFuture());
-            error = result.getKeystoreResponse().getErrorCode();
-            if (error == NO_ERROR) {
-                outChain.shallowCopyFrom(result.getCertificateChain());
-            }
-            return error;
-        } catch (RemoteException e) {
-            Log.w(TAG, "Cannot connect to keystore", e);
-            return SYSTEM_ERROR;
-        } catch (ExecutionException e) {
-            Log.e(TAG, "AttestKey completed with exception", e);
-            return SYSTEM_ERROR;
-        } finally {
-            mBinder.asBinder().unlinkToDeath(promise, 0);
-        }
-    }
-
-    public int attestDeviceIds(KeymasterArguments params, KeymasterCertificateChain outChain) {
-        CertificateChainPromise promise = new CertificateChainPromise();
-        try {
-            mBinder.asBinder().linkToDeath(promise, 0);
-            if (params == null) {
-                params = new KeymasterArguments();
-            }
-            if (outChain == null) {
-                outChain = new KeymasterCertificateChain();
-            }
-            int error = mBinder.attestDeviceIds(promise, params);
-            if (error != NO_ERROR) return error;
-            KeyAttestationCallbackResult result = interruptedPreservingGet(promise.getFuture());
-            error = result.getKeystoreResponse().getErrorCode();
-            if (error == NO_ERROR) {
-                outChain.shallowCopyFrom(result.getCertificateChain());
-            }
-            return error;
-        } catch (RemoteException e) {
-            Log.w(TAG, "Cannot connect to keystore", e);
-            return SYSTEM_ERROR;
-        } catch (ExecutionException e) {
-            Log.e(TAG, "AttestDevicdeIds completed with exception", e);
-            return SYSTEM_ERROR;
-        } finally {
-            mBinder.asBinder().unlinkToDeath(promise, 0);
-        }
+        return Authorization.addAuthToken(authToken);
     }
 
     /**
@@ -1205,77 +144,6 @@
      */
     public void onDeviceOffBody() {
         AndroidKeyStoreMaintenance.onDeviceOffBody();
-        try {
-            mBinder.onDeviceOffBody();
-        } catch (RemoteException e) {
-            Log.w(TAG, "Cannot connect to keystore", e);
-        }
-    }
-
-    // Keep in sync with confirmationui/1.0/types.hal.
-    public static final int CONFIRMATIONUI_OK = 0;
-    public static final int CONFIRMATIONUI_CANCELED = 1;
-    public static final int CONFIRMATIONUI_ABORTED = 2;
-    public static final int CONFIRMATIONUI_OPERATION_PENDING = 3;
-    public static final int CONFIRMATIONUI_IGNORED = 4;
-    public static final int CONFIRMATIONUI_SYSTEM_ERROR = 5;
-    public static final int CONFIRMATIONUI_UNIMPLEMENTED = 6;
-    public static final int CONFIRMATIONUI_UNEXPECTED = 7;
-    public static final int CONFIRMATIONUI_UIERROR = 0x10000;
-    public static final int CONFIRMATIONUI_UIERROR_MISSING_GLYPH = 0x10001;
-    public static final int CONFIRMATIONUI_UIERROR_MESSAGE_TOO_LONG = 0x10002;
-    public static final int CONFIRMATIONUI_UIERROR_MALFORMED_UTF8_ENCODING = 0x10003;
-
-    /**
-     * Requests keystore call into the confirmationui HAL to display a prompt.
-     *
-     * @param listener the binder to use for callbacks.
-     * @param promptText the prompt to display.
-     * @param extraData extra data / nonce from application.
-     * @param locale the locale as a BCP 47 langauge tag.
-     * @param uiOptionsAsFlags the UI options to use, as flags.
-     * @return one of the {@code CONFIRMATIONUI_*} constants, for
-     * example {@code KeyStore.CONFIRMATIONUI_OK}.
-     */
-    public int presentConfirmationPrompt(IBinder listener, String promptText, byte[] extraData,
-                                         String locale, int uiOptionsAsFlags) {
-        try {
-            return mBinder.presentConfirmationPrompt(listener, promptText, extraData, locale,
-                                                     uiOptionsAsFlags);
-        } catch (RemoteException e) {
-            Log.w(TAG, "Cannot connect to keystore", e);
-            return CONFIRMATIONUI_SYSTEM_ERROR;
-        }
-    }
-
-    /**
-     * Requests keystore call into the confirmationui HAL to cancel displaying a prompt.
-     *
-     * @param listener the binder passed to the {@link #presentConfirmationPrompt} method.
-     * @return one of the {@code CONFIRMATIONUI_*} constants, for
-     * example {@code KeyStore.CONFIRMATIONUI_OK}.
-     */
-    public int cancelConfirmationPrompt(IBinder listener) {
-        try {
-            return mBinder.cancelConfirmationPrompt(listener);
-        } catch (RemoteException e) {
-            Log.w(TAG, "Cannot connect to keystore", e);
-            return CONFIRMATIONUI_SYSTEM_ERROR;
-        }
-    }
-
-    /**
-     * Requests keystore to check if the confirmationui HAL is available.
-     *
-     * @return whether the confirmationUI HAL is available.
-     */
-    public boolean isConfirmationPromptSupported() {
-        try {
-            return mBinder.isConfirmationPromptSupported();
-        } catch (RemoteException e) {
-            Log.w(TAG, "Cannot connect to keystore", e);
-            return false;
-        }
     }
 
     /**
@@ -1284,143 +152,6 @@
      */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
     public static KeyStoreException getKeyStoreException(int errorCode) {
-        if (errorCode > 0) {
-            // KeyStore layer error
-            switch (errorCode) {
-                case NO_ERROR:
-                    return new KeyStoreException(errorCode, "OK");
-                case LOCKED:
-                    return new KeyStoreException(errorCode, "User authentication required");
-                case UNINITIALIZED:
-                    return new KeyStoreException(errorCode, "Keystore not initialized");
-                case SYSTEM_ERROR:
-                    return new KeyStoreException(errorCode, "System error");
-                case PERMISSION_DENIED:
-                    return new KeyStoreException(errorCode, "Permission denied");
-                case KEY_NOT_FOUND:
-                    return new KeyStoreException(errorCode, "Key not found");
-                case VALUE_CORRUPTED:
-                    return new KeyStoreException(errorCode, "Key blob corrupted");
-                case OP_AUTH_NEEDED:
-                    return new KeyStoreException(errorCode, "Operation requires authorization");
-                case KEY_PERMANENTLY_INVALIDATED:
-                    return new KeyStoreException(errorCode, "Key permanently invalidated");
-                default:
-                    return new KeyStoreException(errorCode, String.valueOf(errorCode));
-            }
-        } else {
-            // Keymaster layer error
-            switch (errorCode) {
-                case KeymasterDefs.KM_ERROR_INVALID_AUTHORIZATION_TIMEOUT:
-                    // The name of this parameter significantly differs between Keymaster and
-                    // framework APIs. Use the framework wording to make life easier for developers.
-                    return new KeyStoreException(errorCode,
-                            "Invalid user authentication validity duration");
-                default:
-                    return new KeyStoreException(errorCode,
-                            KeymasterDefs.getErrorMessage(errorCode));
-            }
-        }
-    }
-
-    /**
-     * Returns an {@link InvalidKeyException} corresponding to the provided
-     * {@link KeyStoreException}.
-     */
-    public InvalidKeyException getInvalidKeyException(
-            String keystoreKeyAlias, int uid, KeyStoreException e) {
-        switch (e.getErrorCode()) {
-            case LOCKED:
-                return new UserNotAuthenticatedException();
-            case KeymasterDefs.KM_ERROR_KEY_EXPIRED:
-                return new KeyExpiredException();
-            case KeymasterDefs.KM_ERROR_KEY_NOT_YET_VALID:
-                return new KeyNotYetValidException();
-            case KeymasterDefs.KM_ERROR_KEY_USER_NOT_AUTHENTICATED:
-            case OP_AUTH_NEEDED:
-            {
-                // We now need to determine whether the key/operation can become usable if user
-                // authentication is performed, or whether it can never become usable again.
-                // User authentication requirements are contained in the key's characteristics. We
-                // need to check whether these requirements can be be satisfied by asking the user
-                // to authenticate.
-                KeyCharacteristics keyCharacteristics = new KeyCharacteristics();
-                int getKeyCharacteristicsErrorCode =
-                        getKeyCharacteristics(keystoreKeyAlias, null, null, uid,
-                                keyCharacteristics);
-                if (getKeyCharacteristicsErrorCode != NO_ERROR) {
-                    return new InvalidKeyException(
-                            "Failed to obtained key characteristics",
-                            getKeyStoreException(getKeyCharacteristicsErrorCode));
-                }
-                List<BigInteger> keySids =
-                        keyCharacteristics.getUnsignedLongs(KeymasterDefs.KM_TAG_USER_SECURE_ID);
-                if (keySids.isEmpty()) {
-                    // Key is not bound to any SIDs -- no amount of authentication will help here.
-                    return new KeyPermanentlyInvalidatedException();
-                }
-                long rootSid = GateKeeper.getSecureUserId();
-                if ((rootSid != 0) && (keySids.contains(KeymasterArguments.toUint64(rootSid)))) {
-                    // One of the key's SIDs is the current root SID -- user can be authenticated
-                    // against that SID.
-                    return new UserNotAuthenticatedException();
-                }
-
-                final BiometricManager bm = mContext.getSystemService(BiometricManager.class);
-                long[] biometricSids = bm.getAuthenticatorIds();
-
-                // The key must contain every biometric SID. This is because the current API surface
-                // treats all biometrics (capable of keystore integration) equally. e.g. if the
-                // device has multiple keystore-capable sensors, and one of the sensor's SIDs
-                // changed, 1) there is no way for a developer to specify authentication with a
-                // specific sensor (the one that hasn't changed), and 2) currently the only
-                // signal to developers is the UserNotAuthenticatedException, which doesn't
-                // indicate a specific sensor.
-                boolean canUnlockViaBiometrics = true;
-                for (long sid : biometricSids) {
-                    if (!keySids.contains(KeymasterArguments.toUint64(sid))) {
-                        canUnlockViaBiometrics = false;
-                        break;
-                    }
-                }
-
-                if (canUnlockViaBiometrics) {
-                    // All of the biometric SIDs are contained in the key's SIDs.
-                    return new UserNotAuthenticatedException();
-                }
-
-                // None of the key's SIDs can ever be authenticated
-                return new KeyPermanentlyInvalidatedException();
-            }
-            case UNINITIALIZED:
-                return new KeyPermanentlyInvalidatedException();
-            default:
-                return new InvalidKeyException("Keystore operation failed", e);
-        }
-    }
-
-    /**
-     * Returns an {@link InvalidKeyException} corresponding to the provided keystore/keymaster error
-     * code.
-     */
-    public InvalidKeyException getInvalidKeyException(String keystoreKeyAlias, int uid,
-            int errorCode) {
-        return getInvalidKeyException(keystoreKeyAlias, uid, getKeyStoreException(errorCode));
-    }
-
-    private static <R> R interruptedPreservingGet(CompletableFuture<R> future)
-            throws ExecutionException {
-        boolean wasInterrupted = false;
-        while (true) {
-            try {
-                R result = future.get();
-                if (wasInterrupted) {
-                    Thread.currentThread().interrupt();
-                }
-                return result;
-            } catch (InterruptedException e) {
-                wasInterrupted = true;
-            }
-        }
+        return new KeyStoreException(-10000, "Should not be called.");
     }
 }
diff --git a/keystore/java/android/security/LegacyVpnProfileStore.java b/keystore/java/android/security/LegacyVpnProfileStore.java
index 41cfb27..1d2738e 100644
--- a/keystore/java/android/security/LegacyVpnProfileStore.java
+++ b/keystore/java/android/security/LegacyVpnProfileStore.java
@@ -19,7 +19,6 @@
 import android.annotation.NonNull;
 import android.os.ServiceManager;
 import android.os.ServiceSpecificException;
-import android.security.keystore.AndroidKeyStoreProvider;
 import android.security.vpnprofilestore.IVpnProfileStore;
 import android.util.Log;
 
@@ -53,13 +52,8 @@
      */
     public static boolean put(@NonNull String alias, @NonNull byte[] profile) {
         try {
-            if (AndroidKeyStoreProvider.isKeystore2Enabled()) {
-                getService().put(alias, profile);
-                return true;
-            } else {
-                return KeyStore.getInstance().put(
-                        alias, profile, KeyStore.UID_SELF, 0);
-            }
+            getService().put(alias, profile);
+            return true;
         } catch (Exception e) {
             Log.e(TAG, "Failed to put vpn profile.", e);
             return false;
@@ -77,11 +71,7 @@
      */
     public static byte[] get(@NonNull String alias) {
         try {
-            if (AndroidKeyStoreProvider.isKeystore2Enabled()) {
-                return getService().get(alias);
-            } else {
-                return KeyStore.getInstance().get(alias, true /* suppressKeyNotFoundWarning */);
-            }
+            return getService().get(alias);
         } catch (ServiceSpecificException e) {
             if (e.errorCode != PROFILE_NOT_FOUND) {
                 Log.e(TAG, "Failed to get vpn profile.", e);
@@ -100,12 +90,8 @@
      */
     public static boolean remove(@NonNull String alias) {
         try {
-            if (AndroidKeyStoreProvider.isKeystore2Enabled()) {
-                getService().remove(alias);
-                return true;
-            } else {
-                return KeyStore.getInstance().delete(alias);
-            }
+            getService().remove(alias);
+            return true;
         } catch (ServiceSpecificException e) {
             if (e.errorCode != PROFILE_NOT_FOUND) {
                 Log.e(TAG, "Failed to remove vpn profile.", e);
@@ -124,16 +110,11 @@
      */
     public static @NonNull String[] list(@NonNull String prefix) {
         try {
-            if (AndroidKeyStoreProvider.isKeystore2Enabled()) {
-                final String[] aliases = getService().list(prefix);
-                for (int i = 0; i < aliases.length; ++i) {
-                    aliases[i] = aliases[i].substring(prefix.length());
-                }
-                return aliases;
-            } else {
-                final String[] result = KeyStore.getInstance().list(prefix);
-                return result != null ? result : new String[0];
+            final String[] aliases = getService().list(prefix);
+            for (int i = 0; i < aliases.length; ++i) {
+                aliases[i] = aliases[i].substring(prefix.length());
             }
+            return aliases;
         } catch (Exception e) {
             Log.e(TAG, "Failed to list vpn profiles.", e);
         }
diff --git a/keystore/java/android/security/keystore/AndroidKeyStore3DESCipherSpi.java b/keystore/java/android/security/keystore/AndroidKeyStore3DESCipherSpi.java
deleted file mode 100644
index 01fd062..0000000
--- a/keystore/java/android/security/keystore/AndroidKeyStore3DESCipherSpi.java
+++ /dev/null
@@ -1,298 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.security.keystore;
-
-import android.security.keymaster.KeymasterArguments;
-import android.security.keymaster.KeymasterDefs;
-
-import java.security.AlgorithmParameters;
-import java.security.InvalidAlgorithmParameterException;
-import java.security.InvalidKeyException;
-import java.security.Key;
-import java.security.NoSuchAlgorithmException;
-import java.security.ProviderException;
-import java.security.spec.AlgorithmParameterSpec;
-import java.security.spec.InvalidParameterSpecException;
-import java.util.Arrays;
-
-import javax.crypto.CipherSpi;
-import javax.crypto.spec.IvParameterSpec;
-
-/**
- * Base class for Android Keystore 3DES {@link CipherSpi} implementations.
- *
- * @hide
- */
-public class AndroidKeyStore3DESCipherSpi extends AndroidKeyStoreCipherSpiBase {
-
-    private static final int BLOCK_SIZE_BYTES = 8;
-
-    private final int mKeymasterBlockMode;
-    private final int mKeymasterPadding;
-    /** Whether this transformation requires an IV. */
-    private final boolean mIvRequired;
-
-    private byte[] mIv;
-
-    /** Whether the current {@code #mIv} has been used by the underlying crypto operation. */
-    private boolean mIvHasBeenUsed;
-
-    AndroidKeyStore3DESCipherSpi(
-            int keymasterBlockMode,
-            int keymasterPadding,
-            boolean ivRequired) {
-        mKeymasterBlockMode = keymasterBlockMode;
-        mKeymasterPadding = keymasterPadding;
-        mIvRequired = ivRequired;
-    }
-
-    abstract static class ECB extends AndroidKeyStore3DESCipherSpi {
-        protected ECB(int keymasterPadding) {
-            super(KeymasterDefs.KM_MODE_ECB, keymasterPadding, false);
-        }
-
-        public static class NoPadding extends ECB {
-            public NoPadding() {
-                super(KeymasterDefs.KM_PAD_NONE);
-            }
-        }
-
-        public static class PKCS7Padding extends ECB {
-            public PKCS7Padding() {
-                super(KeymasterDefs.KM_PAD_PKCS7);
-            }
-        }
-    }
-
-    abstract static class CBC extends AndroidKeyStore3DESCipherSpi {
-        protected CBC(int keymasterPadding) {
-            super(KeymasterDefs.KM_MODE_CBC, keymasterPadding, true);
-        }
-
-        public static class NoPadding extends CBC {
-            public NoPadding() {
-                super(KeymasterDefs.KM_PAD_NONE);
-            }
-        }
-
-        public static class PKCS7Padding extends CBC {
-            public PKCS7Padding() {
-                super(KeymasterDefs.KM_PAD_PKCS7);
-            }
-        }
-    }
-
-    @Override
-    protected void initKey(int i, Key key) throws InvalidKeyException {
-        if (!(key instanceof AndroidKeyStoreSecretKey)) {
-            throw new InvalidKeyException(
-                    "Unsupported key: " + ((key != null) ? key.getClass().getName() : "null"));
-        }
-        if (!KeyProperties.KEY_ALGORITHM_3DES.equalsIgnoreCase(key.getAlgorithm())) {
-            throw new InvalidKeyException(
-                    "Unsupported key algorithm: " + key.getAlgorithm() + ". Only " +
-                            KeyProperties.KEY_ALGORITHM_3DES + " supported");
-        }
-        setKey((AndroidKeyStoreSecretKey) key);
-    }
-
-    @Override
-    protected int engineGetBlockSize() {
-        return BLOCK_SIZE_BYTES;
-    }
-
-    @Override
-    protected int engineGetOutputSize(int inputLen) {
-        return inputLen + 3 * BLOCK_SIZE_BYTES;
-    }
-
-    @Override
-    protected final byte[] engineGetIV() {
-        return ArrayUtils.cloneIfNotEmpty(mIv);
-    }
-
-    @Override
-    protected AlgorithmParameters engineGetParameters() {
-        if (!mIvRequired) {
-            return null;
-        }
-        if ((mIv != null) && (mIv.length > 0)) {
-            try {
-                AlgorithmParameters params = AlgorithmParameters.getInstance("DESede");
-                params.init(new IvParameterSpec(mIv));
-                return params;
-            } catch (NoSuchAlgorithmException e) {
-                throw new ProviderException(
-                        "Failed to obtain 3DES AlgorithmParameters", e);
-            } catch (InvalidParameterSpecException e) {
-                throw new ProviderException(
-                        "Failed to initialize 3DES AlgorithmParameters with an IV",
-                        e);
-            }
-        }
-        return null;
-    }
-
-    @Override
-    protected void initAlgorithmSpecificParameters() throws InvalidKeyException {
-        if (!mIvRequired) {
-            return;
-        }
-
-        // IV is used
-        if (!isEncrypting()) {
-            throw new InvalidKeyException("IV required when decrypting"
-                    + ". Use IvParameterSpec or AlgorithmParameters to provide it.");
-        }
-    }
-
-    @Override
-    protected void initAlgorithmSpecificParameters(AlgorithmParameterSpec params)
-            throws InvalidAlgorithmParameterException {
-        if (!mIvRequired) {
-            if (params != null) {
-                throw new InvalidAlgorithmParameterException("Unsupported parameters: " + params);
-            }
-            return;
-        }
-
-        // IV is used
-        if (params == null) {
-            if (!isEncrypting()) {
-                // IV must be provided by the caller
-                throw new InvalidAlgorithmParameterException(
-                        "IvParameterSpec must be provided when decrypting");
-            }
-            return;
-        }
-        if (!(params instanceof IvParameterSpec)) {
-            throw new InvalidAlgorithmParameterException("Only IvParameterSpec supported");
-        }
-        mIv = ((IvParameterSpec) params).getIV();
-        if (mIv == null) {
-            throw new InvalidAlgorithmParameterException("Null IV in IvParameterSpec");
-        }
-    }
-
-    @Override
-    protected void initAlgorithmSpecificParameters(AlgorithmParameters params)
-            throws InvalidAlgorithmParameterException {
-        if (!mIvRequired) {
-            if (params != null) {
-                throw new InvalidAlgorithmParameterException("Unsupported parameters: " + params);
-            }
-            return;
-        }
-
-        // IV is used
-        if (params == null) {
-            if (!isEncrypting()) {
-                // IV must be provided by the caller
-                throw new InvalidAlgorithmParameterException("IV required when decrypting"
-                        + ". Use IvParameterSpec or AlgorithmParameters to provide it.");
-            }
-            return;
-        }
-
-        if (!"DESede".equalsIgnoreCase(params.getAlgorithm())) {
-            throw new InvalidAlgorithmParameterException(
-                    "Unsupported AlgorithmParameters algorithm: " + params.getAlgorithm()
-                            + ". Supported: DESede");
-        }
-
-        IvParameterSpec ivSpec;
-        try {
-            ivSpec = params.getParameterSpec(IvParameterSpec.class);
-        } catch (InvalidParameterSpecException e) {
-            if (!isEncrypting()) {
-                // IV must be provided by the caller
-                throw new InvalidAlgorithmParameterException("IV required when decrypting"
-                        + ", but not found in parameters: " + params, e);
-            }
-            mIv = null;
-            return;
-        }
-        mIv = ivSpec.getIV();
-        if (mIv == null) {
-            throw new InvalidAlgorithmParameterException("Null IV in AlgorithmParameters");
-        }
-    }
-
-    @Override
-    protected final int getAdditionalEntropyAmountForBegin() {
-        if ((mIvRequired) && (mIv == null) && (isEncrypting())) {
-            // IV will need to be generated
-            return BLOCK_SIZE_BYTES;
-        }
-
-        return 0;
-    }
-
-    @Override
-    protected int getAdditionalEntropyAmountForFinish() {
-        return 0;
-    }
-
-    @Override
-    protected void addAlgorithmSpecificParametersToBegin(KeymasterArguments keymasterArgs) {
-        if ((isEncrypting()) && (mIvRequired) && (mIvHasBeenUsed)) {
-            // IV is being reused for encryption: this violates security best practices.
-            throw new IllegalStateException(
-                    "IV has already been used. Reusing IV in encryption mode violates security best"
-                            + " practices.");
-        }
-
-        keymasterArgs.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_3DES);
-        keymasterArgs.addEnum(KeymasterDefs.KM_TAG_BLOCK_MODE, mKeymasterBlockMode);
-        keymasterArgs.addEnum(KeymasterDefs.KM_TAG_PADDING, mKeymasterPadding);
-        if ((mIvRequired) && (mIv != null)) {
-            keymasterArgs.addBytes(KeymasterDefs.KM_TAG_NONCE, mIv);
-        }
-    }
-
-    @Override
-    protected void loadAlgorithmSpecificParametersFromBeginResult(
-            KeymasterArguments keymasterArgs) {
-        mIvHasBeenUsed = true;
-
-        // NOTE: Keymaster doesn't always return an IV, even if it's used.
-        byte[] returnedIv = keymasterArgs.getBytes(KeymasterDefs.KM_TAG_NONCE, null);
-        if ((returnedIv != null) && (returnedIv.length == 0)) {
-            returnedIv = null;
-        }
-
-        if (mIvRequired) {
-            if (mIv == null) {
-                mIv = returnedIv;
-            } else if ((returnedIv != null) && (!Arrays.equals(returnedIv, mIv))) {
-                throw new ProviderException("IV in use differs from provided IV");
-            }
-        } else {
-            if (returnedIv != null) {
-                throw new ProviderException(
-                        "IV in use despite IV not being used by this transformation");
-            }
-        }
-    }
-
-    @Override
-    protected final void resetAll() {
-        mIv = null;
-        mIvHasBeenUsed = false;
-        super.resetAll();
-    }
-}
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreAuthenticatedAESCipherSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreAuthenticatedAESCipherSpi.java
deleted file mode 100644
index feb6101..0000000
--- a/keystore/java/android/security/keystore/AndroidKeyStoreAuthenticatedAESCipherSpi.java
+++ /dev/null
@@ -1,449 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.security.keystore;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.os.IBinder;
-import android.security.KeyStore;
-import android.security.KeyStoreException;
-import android.security.keymaster.KeymasterArguments;
-import android.security.keymaster.KeymasterDefs;
-import android.security.keymaster.OperationResult;
-import android.security.keystore.KeyStoreCryptoOperationChunkedStreamer.Stream;
-
-import libcore.util.EmptyArray;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.security.AlgorithmParameters;
-import java.security.InvalidAlgorithmParameterException;
-import java.security.InvalidKeyException;
-import java.security.Key;
-import java.security.NoSuchAlgorithmException;
-import java.security.ProviderException;
-import java.security.spec.AlgorithmParameterSpec;
-import java.security.spec.InvalidParameterSpecException;
-import java.util.Arrays;
-
-import javax.crypto.CipherSpi;
-import javax.crypto.spec.GCMParameterSpec;
-
-/**
- * Base class for Android Keystore authenticated AES {@link CipherSpi} implementations.
- *
- * @hide
- */
-abstract class AndroidKeyStoreAuthenticatedAESCipherSpi extends AndroidKeyStoreCipherSpiBase {
-
-    abstract static class GCM extends AndroidKeyStoreAuthenticatedAESCipherSpi {
-        static final int MIN_SUPPORTED_TAG_LENGTH_BITS = 96;
-        private static final int MAX_SUPPORTED_TAG_LENGTH_BITS = 128;
-        private static final int DEFAULT_TAG_LENGTH_BITS = 128;
-        private static final int IV_LENGTH_BYTES = 12;
-
-        private int mTagLengthBits = DEFAULT_TAG_LENGTH_BITS;
-
-        GCM(int keymasterPadding) {
-            super(KeymasterDefs.KM_MODE_GCM, keymasterPadding);
-        }
-
-        @Override
-        protected final void resetAll() {
-            mTagLengthBits = DEFAULT_TAG_LENGTH_BITS;
-            super.resetAll();
-        }
-
-        @Override
-        protected final void resetWhilePreservingInitState() {
-            super.resetWhilePreservingInitState();
-        }
-
-        @Override
-        protected final void initAlgorithmSpecificParameters() throws InvalidKeyException {
-            if (!isEncrypting()) {
-                throw new InvalidKeyException("IV required when decrypting"
-                        + ". Use IvParameterSpec or AlgorithmParameters to provide it.");
-            }
-        }
-
-        @Override
-        protected final void initAlgorithmSpecificParameters(AlgorithmParameterSpec params)
-                throws InvalidAlgorithmParameterException {
-            // IV is used
-            if (params == null) {
-                if (!isEncrypting()) {
-                    // IV must be provided by the caller
-                    throw new InvalidAlgorithmParameterException(
-                            "GCMParameterSpec must be provided when decrypting");
-                }
-                return;
-            }
-            if (!(params instanceof GCMParameterSpec)) {
-                throw new InvalidAlgorithmParameterException("Only GCMParameterSpec supported");
-            }
-            GCMParameterSpec spec = (GCMParameterSpec) params;
-            byte[] iv = spec.getIV();
-            if (iv == null) {
-                throw new InvalidAlgorithmParameterException("Null IV in GCMParameterSpec");
-            } else if (iv.length != IV_LENGTH_BYTES) {
-                throw new InvalidAlgorithmParameterException("Unsupported IV length: "
-                        + iv.length + " bytes. Only " + IV_LENGTH_BYTES
-                        + " bytes long IV supported");
-            }
-            int tagLengthBits = spec.getTLen();
-            if ((tagLengthBits < MIN_SUPPORTED_TAG_LENGTH_BITS)
-                    || (tagLengthBits > MAX_SUPPORTED_TAG_LENGTH_BITS)
-                    || ((tagLengthBits % 8) != 0)) {
-                throw new InvalidAlgorithmParameterException(
-                        "Unsupported tag length: " + tagLengthBits + " bits"
-                        + ". Supported lengths: 96, 104, 112, 120, 128");
-            }
-            setIv(iv);
-            mTagLengthBits = tagLengthBits;
-        }
-
-        @Override
-        protected final void initAlgorithmSpecificParameters(AlgorithmParameters params)
-                throws InvalidAlgorithmParameterException {
-            if (params == null) {
-                if (!isEncrypting()) {
-                    // IV must be provided by the caller
-                    throw new InvalidAlgorithmParameterException("IV required when decrypting"
-                            + ". Use GCMParameterSpec or GCM AlgorithmParameters to provide it.");
-                }
-                return;
-            }
-
-            if (!"GCM".equalsIgnoreCase(params.getAlgorithm())) {
-                throw new InvalidAlgorithmParameterException(
-                        "Unsupported AlgorithmParameters algorithm: " + params.getAlgorithm()
-                        + ". Supported: GCM");
-            }
-
-            GCMParameterSpec spec;
-            try {
-                spec = params.getParameterSpec(GCMParameterSpec.class);
-            } catch (InvalidParameterSpecException e) {
-                if (!isEncrypting()) {
-                    // IV must be provided by the caller
-                    throw new InvalidAlgorithmParameterException("IV and tag length required when"
-                            + " decrypting, but not found in parameters: " + params, e);
-                }
-                setIv(null);
-                return;
-            }
-            initAlgorithmSpecificParameters(spec);
-        }
-
-        @Nullable
-        @Override
-        protected final AlgorithmParameters engineGetParameters() {
-            byte[] iv = getIv();
-            if ((iv != null) && (iv.length > 0)) {
-                try {
-                    AlgorithmParameters params = AlgorithmParameters.getInstance("GCM");
-                    params.init(new GCMParameterSpec(mTagLengthBits, iv));
-                    return params;
-                } catch (NoSuchAlgorithmException e) {
-                    throw new ProviderException(
-                            "Failed to obtain GCM AlgorithmParameters", e);
-                } catch (InvalidParameterSpecException e) {
-                    throw new ProviderException(
-                            "Failed to initialize GCM AlgorithmParameters", e);
-                }
-            }
-            return null;
-        }
-
-        @NonNull
-        @Override
-        protected KeyStoreCryptoOperationStreamer createMainDataStreamer(
-                KeyStore keyStore, IBinder operationToken) {
-            KeyStoreCryptoOperationStreamer streamer = new KeyStoreCryptoOperationChunkedStreamer(
-                    new KeyStoreCryptoOperationChunkedStreamer.MainDataStream(
-                            keyStore, operationToken), 0);
-            if (isEncrypting()) {
-                return streamer;
-            } else {
-                // When decrypting, to avoid leaking unauthenticated plaintext, do not return any
-                // plaintext before ciphertext is authenticated by KeyStore.finish.
-                return new BufferAllOutputUntilDoFinalStreamer(streamer);
-            }
-        }
-
-        @NonNull
-        @Override
-        protected final KeyStoreCryptoOperationStreamer createAdditionalAuthenticationDataStreamer(
-                KeyStore keyStore, IBinder operationToken) {
-            return new KeyStoreCryptoOperationChunkedStreamer(
-                    new AdditionalAuthenticationDataStream(keyStore, operationToken), 0);
-        }
-
-        @Override
-        protected final int getAdditionalEntropyAmountForBegin() {
-            if ((getIv() == null) && (isEncrypting())) {
-                // IV will need to be generated
-                return IV_LENGTH_BYTES;
-            }
-
-            return 0;
-        }
-
-        @Override
-        protected final int getAdditionalEntropyAmountForFinish() {
-            return 0;
-        }
-
-        @Override
-        protected final void addAlgorithmSpecificParametersToBegin(
-                @NonNull KeymasterArguments keymasterArgs) {
-            super.addAlgorithmSpecificParametersToBegin(keymasterArgs);
-            keymasterArgs.addUnsignedInt(KeymasterDefs.KM_TAG_MAC_LENGTH, mTagLengthBits);
-        }
-
-        protected final int getTagLengthBits() {
-            return mTagLengthBits;
-        }
-
-        public static final class NoPadding extends GCM {
-            public NoPadding() {
-                super(KeymasterDefs.KM_PAD_NONE);
-            }
-
-            @Override
-            protected final int engineGetOutputSize(int inputLen) {
-                int tagLengthBytes = (getTagLengthBits() + 7) / 8;
-                long result;
-                if (isEncrypting()) {
-                    result = getConsumedInputSizeBytes() - getProducedOutputSizeBytes() + inputLen
-                            + tagLengthBytes;
-                } else {
-                    result = getConsumedInputSizeBytes() - getProducedOutputSizeBytes() + inputLen
-                            - tagLengthBytes;
-                }
-                if (result < 0) {
-                    return 0;
-                } else if (result > Integer.MAX_VALUE) {
-                    return Integer.MAX_VALUE;
-                }
-                return (int) result;
-            }
-        }
-    }
-
-    private static final int BLOCK_SIZE_BYTES = 16;
-
-    private final int mKeymasterBlockMode;
-    private final int mKeymasterPadding;
-
-    private byte[] mIv;
-
-    /** Whether the current {@code #mIv} has been used by the underlying crypto operation. */
-    private boolean mIvHasBeenUsed;
-
-    AndroidKeyStoreAuthenticatedAESCipherSpi(
-            int keymasterBlockMode,
-            int keymasterPadding) {
-        mKeymasterBlockMode = keymasterBlockMode;
-        mKeymasterPadding = keymasterPadding;
-    }
-
-    @Override
-    protected void resetAll() {
-        mIv = null;
-        mIvHasBeenUsed = false;
-        super.resetAll();
-    }
-
-    @Override
-    protected final void initKey(int opmode, Key key) throws InvalidKeyException {
-        if (!(key instanceof AndroidKeyStoreSecretKey)) {
-            throw new InvalidKeyException(
-                    "Unsupported key: " + ((key != null) ? key.getClass().getName() : "null"));
-        }
-        if (!KeyProperties.KEY_ALGORITHM_AES.equalsIgnoreCase(key.getAlgorithm())) {
-            throw new InvalidKeyException(
-                    "Unsupported key algorithm: " + key.getAlgorithm() + ". Only " +
-                    KeyProperties.KEY_ALGORITHM_AES + " supported");
-        }
-        setKey((AndroidKeyStoreSecretKey) key);
-    }
-
-    @Override
-    protected void addAlgorithmSpecificParametersToBegin(
-            @NonNull KeymasterArguments keymasterArgs) {
-        if ((isEncrypting()) && (mIvHasBeenUsed)) {
-            // IV is being reused for encryption: this violates security best practices.
-            throw new IllegalStateException(
-                    "IV has already been used. Reusing IV in encryption mode violates security best"
-                    + " practices.");
-        }
-
-        keymasterArgs.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_AES);
-        keymasterArgs.addEnum(KeymasterDefs.KM_TAG_BLOCK_MODE, mKeymasterBlockMode);
-        keymasterArgs.addEnum(KeymasterDefs.KM_TAG_PADDING, mKeymasterPadding);
-        if (mIv != null) {
-            keymasterArgs.addBytes(KeymasterDefs.KM_TAG_NONCE, mIv);
-        }
-    }
-
-    @Override
-    protected final void loadAlgorithmSpecificParametersFromBeginResult(
-            @NonNull KeymasterArguments keymasterArgs) {
-        mIvHasBeenUsed = true;
-
-        // NOTE: Keymaster doesn't always return an IV, even if it's used.
-        byte[] returnedIv = keymasterArgs.getBytes(KeymasterDefs.KM_TAG_NONCE, null);
-        if ((returnedIv != null) && (returnedIv.length == 0)) {
-            returnedIv = null;
-        }
-
-        if (mIv == null) {
-            mIv = returnedIv;
-        } else if ((returnedIv != null) && (!Arrays.equals(returnedIv, mIv))) {
-            throw new ProviderException("IV in use differs from provided IV");
-        }
-    }
-
-    @Override
-    protected final int engineGetBlockSize() {
-        return BLOCK_SIZE_BYTES;
-    }
-
-    @Override
-    protected final byte[] engineGetIV() {
-        return ArrayUtils.cloneIfNotEmpty(mIv);
-    }
-
-    protected void setIv(byte[] iv) {
-        mIv = iv;
-    }
-
-    protected byte[] getIv() {
-        return mIv;
-    }
-
-    /**
-     * {@link KeyStoreCryptoOperationStreamer} which buffers all output until {@code doFinal} from
-     * which it returns all output in one go, provided {@code doFinal} succeeds.
-     */
-    private static class BufferAllOutputUntilDoFinalStreamer
-        implements KeyStoreCryptoOperationStreamer {
-
-        private final KeyStoreCryptoOperationStreamer mDelegate;
-        private ByteArrayOutputStream mBufferedOutput = new ByteArrayOutputStream();
-        private long mProducedOutputSizeBytes;
-
-        private BufferAllOutputUntilDoFinalStreamer(KeyStoreCryptoOperationStreamer delegate) {
-            mDelegate = delegate;
-        }
-
-        @Override
-        public byte[] update(byte[] input, int inputOffset, int inputLength)
-                throws KeyStoreException {
-            byte[] output = mDelegate.update(input, inputOffset, inputLength);
-            if (output != null) {
-                try {
-                    mBufferedOutput.write(output);
-                } catch (IOException e) {
-                    throw new ProviderException("Failed to buffer output", e);
-                }
-            }
-            return EmptyArray.BYTE;
-        }
-
-        @Override
-        public byte[] doFinal(byte[] input, int inputOffset, int inputLength,
-                byte[] signature, byte[] additionalEntropy) throws KeyStoreException {
-            byte[] output = mDelegate.doFinal(input, inputOffset, inputLength, signature,
-                    additionalEntropy);
-            if (output != null) {
-                try {
-                    mBufferedOutput.write(output);
-                } catch (IOException e) {
-                    throw new ProviderException("Failed to buffer output", e);
-                }
-            }
-            byte[] result = mBufferedOutput.toByteArray();
-            mBufferedOutput.reset();
-            mProducedOutputSizeBytes += result.length;
-            return result;
-        }
-
-        @Override
-        public long getConsumedInputSizeBytes() {
-            return mDelegate.getConsumedInputSizeBytes();
-        }
-
-        @Override
-        public long getProducedOutputSizeBytes() {
-            return mProducedOutputSizeBytes;
-        }
-    }
-
-    /**
-     * Additional Authentication Data (AAD) stream via a KeyStore streaming operation. This stream
-     * sends AAD into the KeyStore.
-     */
-    private static class AdditionalAuthenticationDataStream implements Stream {
-
-        private final KeyStore mKeyStore;
-        private final IBinder mOperationToken;
-
-        private AdditionalAuthenticationDataStream(KeyStore keyStore, IBinder operationToken) {
-            mKeyStore = keyStore;
-            mOperationToken = operationToken;
-        }
-
-        @Override
-        public OperationResult update(byte[] input) {
-            KeymasterArguments keymasterArgs = new KeymasterArguments();
-            keymasterArgs.addBytes(KeymasterDefs.KM_TAG_ASSOCIATED_DATA, input);
-
-            // KeyStore does not reflect AAD in inputConsumed, but users of Stream rely on this
-            // field. We fix this discrepancy here. KeyStore.update contract is that all of AAD
-            // has been consumed if the method succeeds.
-            OperationResult result = mKeyStore.update(mOperationToken, keymasterArgs, null);
-            if (result.resultCode == KeyStore.NO_ERROR) {
-                result = new OperationResult(
-                        result.resultCode,
-                        result.token,
-                        result.operationHandle,
-                        input.length, // inputConsumed
-                        result.output,
-                        result.outParams);
-            }
-            return result;
-        }
-
-        @Override
-        public OperationResult finish(byte[] input, byte[] signature, byte[] additionalEntropy) {
-            if ((additionalEntropy != null) && (additionalEntropy.length > 0)) {
-                throw new ProviderException("AAD stream does not support additional entropy");
-            }
-            return new OperationResult(
-                    KeyStore.NO_ERROR,
-                    mOperationToken,
-                    0, // operation handle -- nobody cares about this being returned from finish
-                    0, // inputConsumed
-                    EmptyArray.BYTE, // output
-                    new KeymasterArguments() // additional params returned by finish
-                    );
-        }
-    }
-}
\ No newline at end of file
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreBCWorkaroundProvider.java b/keystore/java/android/security/keystore/AndroidKeyStoreBCWorkaroundProvider.java
deleted file mode 100644
index 5730234..0000000
--- a/keystore/java/android/security/keystore/AndroidKeyStoreBCWorkaroundProvider.java
+++ /dev/null
@@ -1,279 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.security.keystore;
-
-import java.security.Provider;
-
-/**
- * {@link Provider} of JCA crypto operations operating on Android KeyStore keys.
- *
- * <p>This provider was separated out of {@link AndroidKeyStoreProvider} to work around the issue
- * that Bouncy Castle provider incorrectly declares that it accepts arbitrary keys (incl. Android
- * KeyStore ones). This causes JCA to select the Bouncy Castle's implementation of JCA crypto
- * operations for Android KeyStore keys unless Android KeyStore's own implementations are installed
- * as higher-priority than Bouncy Castle ones. The purpose of this provider is to do just that: to
- * offer crypto operations operating on Android KeyStore keys and to be installed at higher priority
- * than the Bouncy Castle provider.
- *
- * <p>Once Bouncy Castle provider is fixed, this provider can be merged into the
- * {@code AndroidKeyStoreProvider}.
- *
- * @hide
- */
-public class AndroidKeyStoreBCWorkaroundProvider extends Provider {
-
-    // IMPLEMENTATION NOTE: Class names are hard-coded in this provider to avoid loading these
-    // classes when this provider is instantiated and installed early on during each app's
-    // initialization process.
-
-    private static final String PACKAGE_NAME = "android.security.keystore";
-    private static final String KEYSTORE_SECRET_KEY_CLASS_NAME =
-            PACKAGE_NAME + ".AndroidKeyStoreSecretKey";
-    private static final String KEYSTORE_PRIVATE_KEY_CLASS_NAME =
-            PACKAGE_NAME + ".AndroidKeyStorePrivateKey";
-    private static final String KEYSTORE_PUBLIC_KEY_CLASS_NAME =
-            PACKAGE_NAME + ".AndroidKeyStorePublicKey";
-
-    private static final String DESEDE_SYSTEM_PROPERTY = "ro.hardware.keystore_desede";
-
-    /** @hide */
-    public AndroidKeyStoreBCWorkaroundProvider() {
-        this("AndroidKeyStoreBCWorkaround");
-    }
-
-    /** @hide **/
-    public AndroidKeyStoreBCWorkaroundProvider(String providerName) {
-        super(providerName,
-                1.0,
-                "Android KeyStore security provider to work around Bouncy Castle");
-
-        // --------------------- javax.crypto.Mac
-        putMacImpl("HmacSHA1", PACKAGE_NAME + ".AndroidKeyStoreHmacSpi$HmacSHA1");
-        put("Alg.Alias.Mac.1.2.840.113549.2.7", "HmacSHA1");
-        put("Alg.Alias.Mac.HMAC-SHA1", "HmacSHA1");
-        put("Alg.Alias.Mac.HMAC/SHA1", "HmacSHA1");
-
-        putMacImpl("HmacSHA224", PACKAGE_NAME + ".AndroidKeyStoreHmacSpi$HmacSHA224");
-        put("Alg.Alias.Mac.1.2.840.113549.2.9", "HmacSHA224");
-        put("Alg.Alias.Mac.HMAC-SHA224", "HmacSHA224");
-        put("Alg.Alias.Mac.HMAC/SHA224", "HmacSHA224");
-
-        putMacImpl("HmacSHA256", PACKAGE_NAME + ".AndroidKeyStoreHmacSpi$HmacSHA256");
-        put("Alg.Alias.Mac.1.2.840.113549.2.9", "HmacSHA256");
-        put("Alg.Alias.Mac.HMAC-SHA256", "HmacSHA256");
-        put("Alg.Alias.Mac.HMAC/SHA256", "HmacSHA256");
-
-        putMacImpl("HmacSHA384", PACKAGE_NAME + ".AndroidKeyStoreHmacSpi$HmacSHA384");
-        put("Alg.Alias.Mac.1.2.840.113549.2.10", "HmacSHA384");
-        put("Alg.Alias.Mac.HMAC-SHA384", "HmacSHA384");
-        put("Alg.Alias.Mac.HMAC/SHA384", "HmacSHA384");
-
-        putMacImpl("HmacSHA512", PACKAGE_NAME + ".AndroidKeyStoreHmacSpi$HmacSHA512");
-        put("Alg.Alias.Mac.1.2.840.113549.2.11", "HmacSHA512");
-        put("Alg.Alias.Mac.HMAC-SHA512", "HmacSHA512");
-        put("Alg.Alias.Mac.HMAC/SHA512", "HmacSHA512");
-
-        // --------------------- javax.crypto.Cipher
-        putSymmetricCipherImpl("AES/ECB/NoPadding",
-                PACKAGE_NAME + ".AndroidKeyStoreUnauthenticatedAESCipherSpi$ECB$NoPadding");
-        putSymmetricCipherImpl("AES/ECB/PKCS7Padding",
-                PACKAGE_NAME + ".AndroidKeyStoreUnauthenticatedAESCipherSpi$ECB$PKCS7Padding");
-
-        putSymmetricCipherImpl("AES/CBC/NoPadding",
-                PACKAGE_NAME + ".AndroidKeyStoreUnauthenticatedAESCipherSpi$CBC$NoPadding");
-        putSymmetricCipherImpl("AES/CBC/PKCS7Padding",
-                PACKAGE_NAME + ".AndroidKeyStoreUnauthenticatedAESCipherSpi$CBC$PKCS7Padding");
-
-        putSymmetricCipherImpl("AES/CTR/NoPadding",
-                PACKAGE_NAME + ".AndroidKeyStoreUnauthenticatedAESCipherSpi$CTR$NoPadding");
-
-        if ("true".equals(android.os.SystemProperties.get(DESEDE_SYSTEM_PROPERTY))) {
-            putSymmetricCipherImpl("DESede/CBC/NoPadding",
-                PACKAGE_NAME + ".AndroidKeyStore3DESCipherSpi$CBC$NoPadding");
-            putSymmetricCipherImpl("DESede/CBC/PKCS7Padding",
-                PACKAGE_NAME + ".AndroidKeyStore3DESCipherSpi$CBC$PKCS7Padding");
-
-            putSymmetricCipherImpl("DESede/ECB/NoPadding",
-                PACKAGE_NAME + ".AndroidKeyStore3DESCipherSpi$ECB$NoPadding");
-            putSymmetricCipherImpl("DESede/ECB/PKCS7Padding",
-                PACKAGE_NAME + ".AndroidKeyStore3DESCipherSpi$ECB$PKCS7Padding");
-        }
-
-        putSymmetricCipherImpl("AES/GCM/NoPadding",
-                PACKAGE_NAME + ".AndroidKeyStoreAuthenticatedAESCipherSpi$GCM$NoPadding");
-
-        putAsymmetricCipherImpl("RSA/ECB/NoPadding",
-                PACKAGE_NAME + ".AndroidKeyStoreRSACipherSpi$NoPadding");
-        put("Alg.Alias.Cipher.RSA/None/NoPadding", "RSA/ECB/NoPadding");
-        putAsymmetricCipherImpl("RSA/ECB/PKCS1Padding",
-                PACKAGE_NAME + ".AndroidKeyStoreRSACipherSpi$PKCS1Padding");
-        put("Alg.Alias.Cipher.RSA/None/PKCS1Padding", "RSA/ECB/PKCS1Padding");
-        putAsymmetricCipherImpl("RSA/ECB/OAEPPadding",
-                PACKAGE_NAME + ".AndroidKeyStoreRSACipherSpi$OAEPWithSHA1AndMGF1Padding");
-        put("Alg.Alias.Cipher.RSA/None/OAEPPadding", "RSA/ECB/OAEPPadding");
-        putAsymmetricCipherImpl("RSA/ECB/OAEPWithSHA-1AndMGF1Padding",
-                PACKAGE_NAME + ".AndroidKeyStoreRSACipherSpi$OAEPWithSHA1AndMGF1Padding");
-        put("Alg.Alias.Cipher.RSA/None/OAEPWithSHA-1AndMGF1Padding",
-                "RSA/ECB/OAEPWithSHA-1AndMGF1Padding");
-        putAsymmetricCipherImpl("RSA/ECB/OAEPWithSHA-224AndMGF1Padding",
-                PACKAGE_NAME + ".AndroidKeyStoreRSACipherSpi$OAEPWithSHA224AndMGF1Padding");
-        put("Alg.Alias.Cipher.RSA/None/OAEPWithSHA-224AndMGF1Padding",
-                "RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
-        putAsymmetricCipherImpl("RSA/ECB/OAEPWithSHA-256AndMGF1Padding",
-                PACKAGE_NAME + ".AndroidKeyStoreRSACipherSpi$OAEPWithSHA256AndMGF1Padding");
-        put("Alg.Alias.Cipher.RSA/None/OAEPWithSHA-256AndMGF1Padding",
-                "RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
-        putAsymmetricCipherImpl("RSA/ECB/OAEPWithSHA-384AndMGF1Padding",
-                PACKAGE_NAME + ".AndroidKeyStoreRSACipherSpi$OAEPWithSHA384AndMGF1Padding");
-        put("Alg.Alias.Cipher.RSA/None/OAEPWithSHA-384AndMGF1Padding",
-                "RSA/ECB/OAEPWithSHA-384AndMGF1Padding");
-        putAsymmetricCipherImpl("RSA/ECB/OAEPWithSHA-512AndMGF1Padding",
-                PACKAGE_NAME + ".AndroidKeyStoreRSACipherSpi$OAEPWithSHA512AndMGF1Padding");
-        put("Alg.Alias.Cipher.RSA/None/OAEPWithSHA-512AndMGF1Padding",
-                "RSA/ECB/OAEPWithSHA-512AndMGF1Padding");
-
-        // --------------------- java.security.Signature
-        putSignatureImpl("NONEwithRSA",
-                PACKAGE_NAME + ".AndroidKeyStoreRSASignatureSpi$NONEWithPKCS1Padding");
-
-        putSignatureImpl("MD5withRSA",
-                PACKAGE_NAME + ".AndroidKeyStoreRSASignatureSpi$MD5WithPKCS1Padding");
-        put("Alg.Alias.Signature.MD5WithRSAEncryption", "MD5withRSA");
-        put("Alg.Alias.Signature.MD5/RSA", "MD5withRSA");
-        put("Alg.Alias.Signature.1.2.840.113549.1.1.4", "MD5withRSA");
-        put("Alg.Alias.Signature.1.2.840.113549.2.5with1.2.840.113549.1.1.1", "MD5withRSA");
-
-        putSignatureImpl("SHA1withRSA",
-                PACKAGE_NAME + ".AndroidKeyStoreRSASignatureSpi$SHA1WithPKCS1Padding");
-        put("Alg.Alias.Signature.SHA1WithRSAEncryption", "SHA1withRSA");
-        put("Alg.Alias.Signature.SHA1/RSA", "SHA1withRSA");
-        put("Alg.Alias.Signature.SHA-1/RSA", "SHA1withRSA");
-        put("Alg.Alias.Signature.1.2.840.113549.1.1.5", "SHA1withRSA");
-        put("Alg.Alias.Signature.1.3.14.3.2.26with1.2.840.113549.1.1.1", "SHA1withRSA");
-        put("Alg.Alias.Signature.1.3.14.3.2.26with1.2.840.113549.1.1.5", "SHA1withRSA");
-        put("Alg.Alias.Signature.1.3.14.3.2.29", "SHA1withRSA");
-
-        putSignatureImpl("SHA224withRSA",
-                PACKAGE_NAME + ".AndroidKeyStoreRSASignatureSpi$SHA224WithPKCS1Padding");
-        put("Alg.Alias.Signature.SHA224WithRSAEncryption", "SHA224withRSA");
-        put("Alg.Alias.Signature.1.2.840.113549.1.1.11", "SHA224withRSA");
-        put("Alg.Alias.Signature.2.16.840.1.101.3.4.2.4with1.2.840.113549.1.1.1",
-                "SHA224withRSA");
-        put("Alg.Alias.Signature.2.16.840.1.101.3.4.2.4with1.2.840.113549.1.1.11",
-                "SHA224withRSA");
-
-        putSignatureImpl("SHA256withRSA",
-                PACKAGE_NAME + ".AndroidKeyStoreRSASignatureSpi$SHA256WithPKCS1Padding");
-        put("Alg.Alias.Signature.SHA256WithRSAEncryption", "SHA256withRSA");
-        put("Alg.Alias.Signature.1.2.840.113549.1.1.11", "SHA256withRSA");
-        put("Alg.Alias.Signature.2.16.840.1.101.3.4.2.1with1.2.840.113549.1.1.1",
-                "SHA256withRSA");
-        put("Alg.Alias.Signature.2.16.840.1.101.3.4.2.1with1.2.840.113549.1.1.11",
-                "SHA256withRSA");
-
-        putSignatureImpl("SHA384withRSA",
-                PACKAGE_NAME + ".AndroidKeyStoreRSASignatureSpi$SHA384WithPKCS1Padding");
-        put("Alg.Alias.Signature.SHA384WithRSAEncryption", "SHA384withRSA");
-        put("Alg.Alias.Signature.1.2.840.113549.1.1.12", "SHA384withRSA");
-        put("Alg.Alias.Signature.2.16.840.1.101.3.4.2.2with1.2.840.113549.1.1.1",
-                "SHA384withRSA");
-
-        putSignatureImpl("SHA512withRSA",
-                PACKAGE_NAME + ".AndroidKeyStoreRSASignatureSpi$SHA512WithPKCS1Padding");
-        put("Alg.Alias.Signature.SHA512WithRSAEncryption", "SHA512withRSA");
-        put("Alg.Alias.Signature.1.2.840.113549.1.1.13", "SHA512withRSA");
-        put("Alg.Alias.Signature.2.16.840.1.101.3.4.2.3with1.2.840.113549.1.1.1",
-                "SHA512withRSA");
-
-        putSignatureImpl("SHA1withRSA/PSS",
-                PACKAGE_NAME + ".AndroidKeyStoreRSASignatureSpi$SHA1WithPSSPadding");
-        putSignatureImpl("SHA224withRSA/PSS",
-                PACKAGE_NAME + ".AndroidKeyStoreRSASignatureSpi$SHA224WithPSSPadding");
-        putSignatureImpl("SHA256withRSA/PSS",
-                PACKAGE_NAME + ".AndroidKeyStoreRSASignatureSpi$SHA256WithPSSPadding");
-        putSignatureImpl("SHA384withRSA/PSS",
-                PACKAGE_NAME + ".AndroidKeyStoreRSASignatureSpi$SHA384WithPSSPadding");
-        putSignatureImpl("SHA512withRSA/PSS",
-                PACKAGE_NAME + ".AndroidKeyStoreRSASignatureSpi$SHA512WithPSSPadding");
-
-        putSignatureImpl("NONEwithECDSA",
-                PACKAGE_NAME + ".AndroidKeyStoreECDSASignatureSpi$NONE");
-
-        putSignatureImpl("SHA1withECDSA", PACKAGE_NAME + ".AndroidKeyStoreECDSASignatureSpi$SHA1");
-        put("Alg.Alias.Signature.ECDSA", "SHA1withECDSA");
-        put("Alg.Alias.Signature.ECDSAwithSHA1", "SHA1withECDSA");
-        // iso(1) member-body(2) us(840) ansi-x962(10045) signatures(4) ecdsa-with-SHA1(1)
-        put("Alg.Alias.Signature.1.2.840.10045.4.1", "SHA1withECDSA");
-        put("Alg.Alias.Signature.1.3.14.3.2.26with1.2.840.10045.2.1", "SHA1withECDSA");
-
-        // iso(1) member-body(2) us(840) ansi-x962(10045) signatures(4) ecdsa-with-SHA2(3)
-        putSignatureImpl("SHA224withECDSA",
-                PACKAGE_NAME + ".AndroidKeyStoreECDSASignatureSpi$SHA224");
-        // ecdsa-with-SHA224(1)
-        put("Alg.Alias.Signature.1.2.840.10045.4.3.1", "SHA224withECDSA");
-        put("Alg.Alias.Signature.2.16.840.1.101.3.4.2.4with1.2.840.10045.2.1", "SHA224withECDSA");
-
-        // iso(1) member-body(2) us(840) ansi-x962(10045) signatures(4) ecdsa-with-SHA2(3)
-        putSignatureImpl("SHA256withECDSA",
-                PACKAGE_NAME + ".AndroidKeyStoreECDSASignatureSpi$SHA256");
-        // ecdsa-with-SHA256(2)
-        put("Alg.Alias.Signature.1.2.840.10045.4.3.2", "SHA256withECDSA");
-        put("Alg.Alias.Signature.2.16.840.1.101.3.4.2.1with1.2.840.10045.2.1", "SHA256withECDSA");
-
-        putSignatureImpl("SHA384withECDSA",
-                PACKAGE_NAME + ".AndroidKeyStoreECDSASignatureSpi$SHA384");
-        // ecdsa-with-SHA384(3)
-        put("Alg.Alias.Signature.1.2.840.10045.4.3.3", "SHA384withECDSA");
-        put("Alg.Alias.Signature.2.16.840.1.101.3.4.2.2with1.2.840.10045.2.1", "SHA384withECDSA");
-
-        putSignatureImpl("SHA512withECDSA",
-                PACKAGE_NAME + ".AndroidKeyStoreECDSASignatureSpi$SHA512");
-        // ecdsa-with-SHA512(4)
-        put("Alg.Alias.Signature.1.2.840.10045.4.3.4", "SHA512withECDSA");
-        put("Alg.Alias.Signature.2.16.840.1.101.3.4.2.3with1.2.840.10045.2.1", "SHA512withECDSA");
-    }
-
-    private void putMacImpl(String algorithm, String implClass) {
-        put("Mac." + algorithm, implClass);
-        put("Mac." + algorithm + " SupportedKeyClasses", KEYSTORE_SECRET_KEY_CLASS_NAME);
-    }
-
-    private void putSymmetricCipherImpl(String transformation, String implClass) {
-        put("Cipher." + transformation, implClass);
-        put("Cipher." + transformation + " SupportedKeyClasses", KEYSTORE_SECRET_KEY_CLASS_NAME);
-    }
-
-    private void putAsymmetricCipherImpl(String transformation, String implClass) {
-        put("Cipher." + transformation, implClass);
-        put("Cipher." + transformation + " SupportedKeyClasses",
-                KEYSTORE_PRIVATE_KEY_CLASS_NAME + "|" + KEYSTORE_PUBLIC_KEY_CLASS_NAME);
-    }
-
-    private void putSignatureImpl(String algorithm, String implClass) {
-        put("Signature." + algorithm, implClass);
-        put("Signature." + algorithm + " SupportedKeyClasses",
-                KEYSTORE_PRIVATE_KEY_CLASS_NAME + "|" + KEYSTORE_PUBLIC_KEY_CLASS_NAME);
-    }
-
-    public static String[] getSupportedEcdsaSignatureDigests() {
-        return new String[] {"NONE", "SHA-1", "SHA-224", "SHA-256", "SHA-384", "SHA-512"};
-    }
-
-    public static String[] getSupportedRsaSignatureWithPkcs1PaddingDigests() {
-        return new String[] {"NONE", "MD5", "SHA-1", "SHA-224", "SHA-256", "SHA-384", "SHA-512"};
-    }
-}
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreCipherSpiBase.java b/keystore/java/android/security/keystore/AndroidKeyStoreCipherSpiBase.java
deleted file mode 100644
index ccc3153..0000000
--- a/keystore/java/android/security/keystore/AndroidKeyStoreCipherSpiBase.java
+++ /dev/null
@@ -1,920 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.security.keystore;
-
-import android.annotation.CallSuper;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.os.IBinder;
-import android.security.KeyStore;
-import android.security.KeyStoreException;
-import android.security.keymaster.KeymasterArguments;
-import android.security.keymaster.KeymasterDefs;
-import android.security.keymaster.OperationResult;
-
-import libcore.util.EmptyArray;
-
-import java.nio.BufferOverflowException;
-import java.nio.ByteBuffer;
-import java.security.AlgorithmParameters;
-import java.security.GeneralSecurityException;
-import java.security.InvalidAlgorithmParameterException;
-import java.security.InvalidKeyException;
-import java.security.InvalidParameterException;
-import java.security.Key;
-import java.security.KeyFactory;
-import java.security.NoSuchAlgorithmException;
-import java.security.PrivateKey;
-import java.security.ProviderException;
-import java.security.PublicKey;
-import java.security.SecureRandom;
-import java.security.spec.AlgorithmParameterSpec;
-import java.security.spec.InvalidKeySpecException;
-import java.security.spec.PKCS8EncodedKeySpec;
-import java.security.spec.X509EncodedKeySpec;
-
-import javax.crypto.AEADBadTagException;
-import javax.crypto.BadPaddingException;
-import javax.crypto.Cipher;
-import javax.crypto.CipherSpi;
-import javax.crypto.IllegalBlockSizeException;
-import javax.crypto.NoSuchPaddingException;
-import javax.crypto.SecretKey;
-import javax.crypto.SecretKeyFactory;
-import javax.crypto.ShortBufferException;
-import javax.crypto.spec.SecretKeySpec;
-
-/**
- * Base class for {@link CipherSpi} implementations of Android KeyStore backed ciphers.
- *
- * @hide
- */
-abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStoreCryptoOperation {
-    private final KeyStore mKeyStore;
-
-    // Fields below are populated by Cipher.init and KeyStore.begin and should be preserved after
-    // doFinal finishes.
-    private boolean mEncrypting;
-    private int mKeymasterPurposeOverride = -1;
-    private AndroidKeyStoreKey mKey;
-    private SecureRandom mRng;
-
-    /**
-     * Token referencing this operation inside keystore service. It is initialized by
-     * {@code engineInit} and is invalidated when {@code engineDoFinal} succeeds and on some error
-     * conditions in between.
-     */
-    private IBinder mOperationToken;
-    private long mOperationHandle;
-    private KeyStoreCryptoOperationStreamer mMainDataStreamer;
-    private KeyStoreCryptoOperationStreamer mAdditionalAuthenticationDataStreamer;
-    private boolean mAdditionalAuthenticationDataStreamerClosed;
-
-    /**
-     * Encountered exception which could not be immediately thrown because it was encountered inside
-     * a method that does not throw checked exception. This exception will be thrown from
-     * {@code engineDoFinal}. Once such an exception is encountered, {@code engineUpdate} and
-     * {@code engineDoFinal} start ignoring input data.
-     */
-    private Exception mCachedException;
-
-    AndroidKeyStoreCipherSpiBase() {
-        mKeyStore = KeyStore.getInstance();
-    }
-
-    @Override
-    protected final void engineInit(int opmode, Key key, SecureRandom random)
-            throws InvalidKeyException {
-        resetAll();
-
-        boolean success = false;
-        try {
-            init(opmode, key, random);
-            initAlgorithmSpecificParameters();
-            try {
-                ensureKeystoreOperationInitialized();
-            } catch (InvalidAlgorithmParameterException e) {
-                throw new InvalidKeyException(e);
-            }
-            success = true;
-        } finally {
-            if (!success) {
-                resetAll();
-            }
-        }
-    }
-
-    @Override
-    protected final void engineInit(int opmode, Key key, AlgorithmParameters params,
-            SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException {
-        resetAll();
-
-        boolean success = false;
-        try {
-            init(opmode, key, random);
-            initAlgorithmSpecificParameters(params);
-            ensureKeystoreOperationInitialized();
-            success = true;
-        } finally {
-            if (!success) {
-                resetAll();
-            }
-        }
-    }
-
-    @Override
-    protected final void engineInit(int opmode, Key key, AlgorithmParameterSpec params,
-            SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException {
-        resetAll();
-
-        boolean success = false;
-        try {
-            init(opmode, key, random);
-            initAlgorithmSpecificParameters(params);
-            ensureKeystoreOperationInitialized();
-            success = true;
-        } finally {
-            if (!success) {
-                resetAll();
-            }
-        }
-    }
-
-    private void init(int opmode, Key key, SecureRandom random) throws InvalidKeyException {
-        switch (opmode) {
-            case Cipher.ENCRYPT_MODE:
-            case Cipher.WRAP_MODE:
-                mEncrypting = true;
-                break;
-            case Cipher.DECRYPT_MODE:
-            case Cipher.UNWRAP_MODE:
-                mEncrypting = false;
-                break;
-            default:
-                throw new InvalidParameterException("Unsupported opmode: " + opmode);
-        }
-        initKey(opmode, key);
-        if (mKey == null) {
-            throw new ProviderException("initKey did not initialize the key");
-        }
-        mRng = random;
-    }
-
-    /**
-     * Resets this cipher to its pristine pre-init state. This must be equivalent to obtaining a new
-     * cipher instance.
-     *
-     * <p>Subclasses storing additional state should override this method, reset the additional
-     * state, and then chain to superclass.
-     */
-    @CallSuper
-    protected void resetAll() {
-        IBinder operationToken = mOperationToken;
-        if (operationToken != null) {
-            mKeyStore.abort(operationToken);
-        }
-        mEncrypting = false;
-        mKeymasterPurposeOverride = -1;
-        mKey = null;
-        mRng = null;
-        mOperationToken = null;
-        mOperationHandle = 0;
-        mMainDataStreamer = null;
-        mAdditionalAuthenticationDataStreamer = null;
-        mAdditionalAuthenticationDataStreamerClosed = false;
-        mCachedException = null;
-    }
-
-    /**
-     * Resets this cipher while preserving the initialized state. This must be equivalent to
-     * rolling back the cipher's state to just after the most recent {@code engineInit} completed
-     * successfully.
-     *
-     * <p>Subclasses storing additional post-init state should override this method, reset the
-     * additional state, and then chain to superclass.
-     */
-    @CallSuper
-    protected void resetWhilePreservingInitState() {
-        IBinder operationToken = mOperationToken;
-        if (operationToken != null) {
-            mKeyStore.abort(operationToken);
-        }
-        mOperationToken = null;
-        mOperationHandle = 0;
-        mMainDataStreamer = null;
-        mAdditionalAuthenticationDataStreamer = null;
-        mAdditionalAuthenticationDataStreamerClosed = false;
-        mCachedException = null;
-    }
-
-    private void ensureKeystoreOperationInitialized() throws InvalidKeyException,
-            InvalidAlgorithmParameterException {
-        if (mMainDataStreamer != null) {
-            return;
-        }
-        if (mCachedException != null) {
-            return;
-        }
-        if (mKey == null) {
-            throw new IllegalStateException("Not initialized");
-        }
-
-        KeymasterArguments keymasterInputArgs = new KeymasterArguments();
-        addAlgorithmSpecificParametersToBegin(keymasterInputArgs);
-        byte[] additionalEntropy = KeyStoreCryptoOperationUtils.getRandomBytesToMixIntoKeystoreRng(
-                mRng, getAdditionalEntropyAmountForBegin());
-
-        int purpose;
-        if (mKeymasterPurposeOverride != -1) {
-            purpose = mKeymasterPurposeOverride;
-        } else {
-            purpose = mEncrypting
-                    ? KeymasterDefs.KM_PURPOSE_ENCRYPT : KeymasterDefs.KM_PURPOSE_DECRYPT;
-        }
-        OperationResult opResult = mKeyStore.begin(
-                mKey.getAlias(),
-                purpose,
-                true, // permit aborting this operation if keystore runs out of resources
-                keymasterInputArgs,
-                additionalEntropy,
-                mKey.getUid());
-        if (opResult == null) {
-            throw new KeyStoreConnectException();
-        }
-
-        // Store operation token and handle regardless of the error code returned by KeyStore to
-        // ensure that the operation gets aborted immediately if the code below throws an exception.
-        mOperationToken = opResult.token;
-        mOperationHandle = opResult.operationHandle;
-
-        // If necessary, throw an exception due to KeyStore operation having failed.
-        GeneralSecurityException e = KeyStoreCryptoOperationUtils.getExceptionForCipherInit(
-                mKeyStore, mKey, opResult.resultCode);
-        if (e != null) {
-            if (e instanceof InvalidKeyException) {
-                throw (InvalidKeyException) e;
-            } else if (e instanceof InvalidAlgorithmParameterException) {
-                throw (InvalidAlgorithmParameterException) e;
-            } else {
-                throw new ProviderException("Unexpected exception type", e);
-            }
-        }
-
-        if (mOperationToken == null) {
-            throw new ProviderException("Keystore returned null operation token");
-        }
-        if (mOperationHandle == 0) {
-            throw new ProviderException("Keystore returned invalid operation handle");
-        }
-
-        loadAlgorithmSpecificParametersFromBeginResult(opResult.outParams);
-        mMainDataStreamer = createMainDataStreamer(mKeyStore, opResult.token);
-        mAdditionalAuthenticationDataStreamer =
-                createAdditionalAuthenticationDataStreamer(mKeyStore, opResult.token);
-        mAdditionalAuthenticationDataStreamerClosed = false;
-    }
-
-    /**
-     * Creates a streamer which sends plaintext/ciphertext into the provided KeyStore and receives
-     * the corresponding ciphertext/plaintext from the KeyStore.
-     *
-     * <p>This implementation returns a working streamer.
-     */
-    @NonNull
-    protected KeyStoreCryptoOperationStreamer createMainDataStreamer(
-            KeyStore keyStore, IBinder operationToken) {
-        return new KeyStoreCryptoOperationChunkedStreamer(
-                new KeyStoreCryptoOperationChunkedStreamer.MainDataStream(
-                        keyStore, operationToken), 0);
-    }
-
-    /**
-     * Creates a streamer which sends Additional Authentication Data (AAD) into the KeyStore.
-     *
-     * <p>This implementation returns {@code null}.
-     *
-     * @return stream or {@code null} if AAD is not supported by this cipher.
-     */
-    @Nullable
-    protected KeyStoreCryptoOperationStreamer createAdditionalAuthenticationDataStreamer(
-            @SuppressWarnings("unused") KeyStore keyStore,
-            @SuppressWarnings("unused") IBinder operationToken) {
-        return null;
-    }
-
-    @Override
-    protected final byte[] engineUpdate(byte[] input, int inputOffset, int inputLen) {
-        if (mCachedException != null) {
-            return null;
-        }
-        try {
-            ensureKeystoreOperationInitialized();
-        } catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
-            mCachedException = e;
-            return null;
-        }
-
-        if (inputLen == 0) {
-            return null;
-        }
-
-        byte[] output;
-        try {
-            flushAAD();
-            output = mMainDataStreamer.update(input, inputOffset, inputLen);
-        } catch (KeyStoreException e) {
-            mCachedException = e;
-            return null;
-        }
-
-        if (output.length == 0) {
-            return null;
-        }
-
-        return output;
-    }
-
-    private void flushAAD() throws KeyStoreException {
-        if ((mAdditionalAuthenticationDataStreamer != null)
-                && (!mAdditionalAuthenticationDataStreamerClosed)) {
-            byte[] output;
-            try {
-                output = mAdditionalAuthenticationDataStreamer.doFinal(
-                        EmptyArray.BYTE, 0, 0,
-                        null, // no signature
-                        null // no additional entropy needed flushing AAD
-                        );
-            } finally {
-                mAdditionalAuthenticationDataStreamerClosed = true;
-            }
-            if ((output != null) && (output.length > 0)) {
-                throw new ProviderException(
-                        "AAD update unexpectedly returned data: " + output.length + " bytes");
-            }
-        }
-    }
-
-    @Override
-    protected final int engineUpdate(byte[] input, int inputOffset, int inputLen, byte[] output,
-            int outputOffset) throws ShortBufferException {
-        byte[] outputCopy = engineUpdate(input, inputOffset, inputLen);
-        if (outputCopy == null) {
-            return 0;
-        }
-        int outputAvailable = output.length - outputOffset;
-        if (outputCopy.length > outputAvailable) {
-            throw new ShortBufferException("Output buffer too short. Produced: "
-                    + outputCopy.length + ", available: " + outputAvailable);
-        }
-        System.arraycopy(outputCopy, 0, output, outputOffset, outputCopy.length);
-        return outputCopy.length;
-    }
-
-    @Override
-    protected final int engineUpdate(ByteBuffer input, ByteBuffer output)
-            throws ShortBufferException {
-        if (input == null) {
-            throw new NullPointerException("input == null");
-        }
-        if (output == null) {
-            throw new NullPointerException("output == null");
-        }
-
-        int inputSize = input.remaining();
-        byte[] outputArray;
-        if (input.hasArray()) {
-            outputArray =
-                    engineUpdate(
-                            input.array(), input.arrayOffset() + input.position(), inputSize);
-            input.position(input.position() + inputSize);
-        } else {
-            byte[] inputArray = new byte[inputSize];
-            input.get(inputArray);
-            outputArray = engineUpdate(inputArray, 0, inputSize);
-        }
-
-        int outputSize = (outputArray != null) ? outputArray.length : 0;
-        if (outputSize > 0) {
-            int outputBufferAvailable = output.remaining();
-            try {
-                output.put(outputArray);
-            } catch (BufferOverflowException e) {
-                throw new ShortBufferException(
-                        "Output buffer too small. Produced: " + outputSize + ", available: "
-                                + outputBufferAvailable);
-            }
-        }
-        return outputSize;
-    }
-
-    @Override
-    protected final void engineUpdateAAD(byte[] input, int inputOffset, int inputLen) {
-        if (mCachedException != null) {
-            return;
-        }
-
-        try {
-            ensureKeystoreOperationInitialized();
-        } catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
-            mCachedException = e;
-            return;
-        }
-
-        if (mAdditionalAuthenticationDataStreamerClosed) {
-            throw new IllegalStateException(
-                    "AAD can only be provided before Cipher.update is invoked");
-        }
-
-        if (mAdditionalAuthenticationDataStreamer == null) {
-            throw new IllegalStateException("This cipher does not support AAD");
-        }
-
-        byte[] output;
-        try {
-            output = mAdditionalAuthenticationDataStreamer.update(input, inputOffset, inputLen);
-        } catch (KeyStoreException e) {
-            mCachedException = e;
-            return;
-        }
-
-        if ((output != null) && (output.length > 0)) {
-            throw new ProviderException("AAD update unexpectedly produced output: "
-                    + output.length + " bytes");
-        }
-    }
-
-    @Override
-    protected final void engineUpdateAAD(ByteBuffer src) {
-        if (src == null) {
-            throw new IllegalArgumentException("src == null");
-        }
-        if (!src.hasRemaining()) {
-            return;
-        }
-
-        byte[] input;
-        int inputOffset;
-        int inputLen;
-        if (src.hasArray()) {
-            input = src.array();
-            inputOffset = src.arrayOffset() + src.position();
-            inputLen = src.remaining();
-            src.position(src.limit());
-        } else {
-            input = new byte[src.remaining()];
-            inputOffset = 0;
-            inputLen = input.length;
-            src.get(input);
-        }
-        engineUpdateAAD(input, inputOffset, inputLen);
-    }
-
-    @Override
-    protected final byte[] engineDoFinal(byte[] input, int inputOffset, int inputLen)
-            throws IllegalBlockSizeException, BadPaddingException {
-        if (mCachedException != null) {
-            throw (IllegalBlockSizeException)
-                    new IllegalBlockSizeException().initCause(mCachedException);
-        }
-
-        try {
-            ensureKeystoreOperationInitialized();
-        } catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
-            throw (IllegalBlockSizeException) new IllegalBlockSizeException().initCause(e);
-        }
-
-        byte[] output;
-        try {
-            flushAAD();
-            byte[] additionalEntropy =
-                    KeyStoreCryptoOperationUtils.getRandomBytesToMixIntoKeystoreRng(
-                            mRng, getAdditionalEntropyAmountForFinish());
-            output = mMainDataStreamer.doFinal(
-                    input, inputOffset, inputLen,
-                    null, // no signature involved
-                    additionalEntropy);
-        } catch (KeyStoreException e) {
-            switch (e.getErrorCode()) {
-                case KeymasterDefs.KM_ERROR_INVALID_INPUT_LENGTH:
-                    throw (IllegalBlockSizeException) new IllegalBlockSizeException().initCause(e);
-                case KeymasterDefs.KM_ERROR_INVALID_ARGUMENT:
-                    throw (BadPaddingException) new BadPaddingException().initCause(e);
-                case KeymasterDefs.KM_ERROR_VERIFICATION_FAILED:
-                    throw (AEADBadTagException) new AEADBadTagException().initCause(e);
-                default:
-                    throw (IllegalBlockSizeException) new IllegalBlockSizeException().initCause(e);
-            }
-        }
-
-        resetWhilePreservingInitState();
-        return output;
-    }
-
-    @Override
-    protected final int engineDoFinal(byte[] input, int inputOffset, int inputLen, byte[] output,
-            int outputOffset) throws ShortBufferException, IllegalBlockSizeException,
-            BadPaddingException {
-        byte[] outputCopy = engineDoFinal(input, inputOffset, inputLen);
-        if (outputCopy == null) {
-            return 0;
-        }
-        int outputAvailable = output.length - outputOffset;
-        if (outputCopy.length > outputAvailable) {
-            throw new ShortBufferException("Output buffer too short. Produced: "
-                    + outputCopy.length + ", available: " + outputAvailable);
-        }
-        System.arraycopy(outputCopy, 0, output, outputOffset, outputCopy.length);
-        return outputCopy.length;
-    }
-
-    @Override
-    protected final int engineDoFinal(ByteBuffer input, ByteBuffer output)
-            throws ShortBufferException, IllegalBlockSizeException, BadPaddingException {
-        if (input == null) {
-            throw new NullPointerException("input == null");
-        }
-        if (output == null) {
-            throw new NullPointerException("output == null");
-        }
-
-        int inputSize = input.remaining();
-        byte[] outputArray;
-        if (input.hasArray()) {
-            outputArray =
-                    engineDoFinal(
-                            input.array(), input.arrayOffset() + input.position(), inputSize);
-            input.position(input.position() + inputSize);
-        } else {
-            byte[] inputArray = new byte[inputSize];
-            input.get(inputArray);
-            outputArray = engineDoFinal(inputArray, 0, inputSize);
-        }
-
-        int outputSize = (outputArray != null) ? outputArray.length : 0;
-        if (outputSize > 0) {
-            int outputBufferAvailable = output.remaining();
-            try {
-                output.put(outputArray);
-            } catch (BufferOverflowException e) {
-                throw new ShortBufferException(
-                        "Output buffer too small. Produced: " + outputSize + ", available: "
-                                + outputBufferAvailable);
-            }
-        }
-        return outputSize;
-    }
-
-    @Override
-    protected final byte[] engineWrap(Key key)
-            throws IllegalBlockSizeException, InvalidKeyException {
-        if (mKey == null) {
-            throw new IllegalStateException("Not initilized");
-        }
-
-        if (!isEncrypting()) {
-            throw new IllegalStateException(
-                    "Cipher must be initialized in Cipher.WRAP_MODE to wrap keys");
-        }
-
-        if (key == null) {
-            throw new NullPointerException("key == null");
-        }
-        byte[] encoded = null;
-        if (key instanceof SecretKey) {
-            if ("RAW".equalsIgnoreCase(key.getFormat())) {
-                encoded = key.getEncoded();
-            }
-            if (encoded == null) {
-                try {
-                    SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(key.getAlgorithm());
-                    SecretKeySpec spec =
-                            (SecretKeySpec) keyFactory.getKeySpec(
-                                    (SecretKey) key, SecretKeySpec.class);
-                    encoded = spec.getEncoded();
-                } catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
-                    throw new InvalidKeyException(
-                            "Failed to wrap key because it does not export its key material",
-                            e);
-                }
-            }
-        } else if (key instanceof PrivateKey) {
-            if ("PKCS8".equalsIgnoreCase(key.getFormat())) {
-                encoded = key.getEncoded();
-            }
-            if (encoded == null) {
-                try {
-                    KeyFactory keyFactory = KeyFactory.getInstance(key.getAlgorithm());
-                    PKCS8EncodedKeySpec spec =
-                            keyFactory.getKeySpec(key, PKCS8EncodedKeySpec.class);
-                    encoded = spec.getEncoded();
-                } catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
-                    throw new InvalidKeyException(
-                            "Failed to wrap key because it does not export its key material",
-                            e);
-                }
-            }
-        } else if (key instanceof PublicKey) {
-            if ("X.509".equalsIgnoreCase(key.getFormat())) {
-                encoded = key.getEncoded();
-            }
-            if (encoded == null) {
-                try {
-                    KeyFactory keyFactory = KeyFactory.getInstance(key.getAlgorithm());
-                    X509EncodedKeySpec spec =
-                            keyFactory.getKeySpec(key, X509EncodedKeySpec.class);
-                    encoded = spec.getEncoded();
-                } catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
-                    throw new InvalidKeyException(
-                            "Failed to wrap key because it does not export its key material",
-                            e);
-                }
-            }
-        } else {
-            throw new InvalidKeyException("Unsupported key type: " + key.getClass().getName());
-        }
-
-        if (encoded == null) {
-            throw new InvalidKeyException(
-                    "Failed to wrap key because it does not export its key material");
-        }
-
-        try {
-            return engineDoFinal(encoded, 0, encoded.length);
-        } catch (BadPaddingException e) {
-            throw (IllegalBlockSizeException) new IllegalBlockSizeException().initCause(e);
-        }
-    }
-
-    @Override
-    protected final Key engineUnwrap(byte[] wrappedKey, String wrappedKeyAlgorithm,
-            int wrappedKeyType) throws InvalidKeyException, NoSuchAlgorithmException {
-        if (mKey == null) {
-            throw new IllegalStateException("Not initilized");
-        }
-
-        if (isEncrypting()) {
-            throw new IllegalStateException(
-                    "Cipher must be initialized in Cipher.WRAP_MODE to wrap keys");
-        }
-
-        if (wrappedKey == null) {
-            throw new NullPointerException("wrappedKey == null");
-        }
-
-        byte[] encoded;
-        try {
-            encoded = engineDoFinal(wrappedKey, 0, wrappedKey.length);
-        } catch (IllegalBlockSizeException | BadPaddingException e) {
-            throw new InvalidKeyException("Failed to unwrap key", e);
-        }
-
-        switch (wrappedKeyType) {
-            case Cipher.SECRET_KEY:
-            {
-                return new SecretKeySpec(encoded, wrappedKeyAlgorithm);
-                // break;
-            }
-            case Cipher.PRIVATE_KEY:
-            {
-                KeyFactory keyFactory = KeyFactory.getInstance(wrappedKeyAlgorithm);
-                try {
-                    return keyFactory.generatePrivate(new PKCS8EncodedKeySpec(encoded));
-                } catch (InvalidKeySpecException e) {
-                    throw new InvalidKeyException(
-                            "Failed to create private key from its PKCS#8 encoded form", e);
-                }
-                // break;
-            }
-            case Cipher.PUBLIC_KEY:
-            {
-                KeyFactory keyFactory = KeyFactory.getInstance(wrappedKeyAlgorithm);
-                try {
-                    return keyFactory.generatePublic(new X509EncodedKeySpec(encoded));
-                } catch (InvalidKeySpecException e) {
-                    throw new InvalidKeyException(
-                            "Failed to create public key from its X.509 encoded form", e);
-                }
-                // break;
-            }
-            default:
-                throw new InvalidParameterException(
-                        "Unsupported wrappedKeyType: " + wrappedKeyType);
-        }
-    }
-
-    @Override
-    protected final void engineSetMode(String mode) throws NoSuchAlgorithmException {
-        // This should never be invoked because all algorithms registered with the AndroidKeyStore
-        // provide explicitly specify block mode.
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    protected final void engineSetPadding(String arg0) throws NoSuchPaddingException {
-        // This should never be invoked because all algorithms registered with the AndroidKeyStore
-        // provide explicitly specify padding mode.
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    protected final int engineGetKeySize(Key key) throws InvalidKeyException {
-        throw new UnsupportedOperationException();
-    }
-
-    @CallSuper
-    @Override
-    public void finalize() throws Throwable {
-        try {
-            IBinder operationToken = mOperationToken;
-            if (operationToken != null) {
-                mKeyStore.abort(operationToken);
-            }
-        } finally {
-            super.finalize();
-        }
-    }
-
-    @Override
-    public final long getOperationHandle() {
-        return mOperationHandle;
-    }
-
-    protected final void setKey(@NonNull AndroidKeyStoreKey key) {
-        mKey = key;
-    }
-
-    /**
-     * Overrides the default purpose/type of the crypto operation.
-     */
-    protected final void setKeymasterPurposeOverride(int keymasterPurpose) {
-        mKeymasterPurposeOverride = keymasterPurpose;
-    }
-
-    protected final int getKeymasterPurposeOverride() {
-        return mKeymasterPurposeOverride;
-    }
-
-    /**
-     * Returns {@code true} if this cipher is initialized for encryption, {@code false} if this
-     * cipher is initialized for decryption.
-     */
-    protected final boolean isEncrypting() {
-        return mEncrypting;
-    }
-
-    @NonNull
-    protected final KeyStore getKeyStore() {
-        return mKeyStore;
-    }
-
-    protected final long getConsumedInputSizeBytes() {
-        if (mMainDataStreamer == null) {
-            throw new IllegalStateException("Not initialized");
-        }
-        return mMainDataStreamer.getConsumedInputSizeBytes();
-    }
-
-    protected final long getProducedOutputSizeBytes() {
-        if (mMainDataStreamer == null) {
-            throw new IllegalStateException("Not initialized");
-        }
-        return mMainDataStreamer.getProducedOutputSizeBytes();
-    }
-
-    static String opmodeToString(int opmode) {
-        switch (opmode) {
-            case Cipher.ENCRYPT_MODE:
-                return "ENCRYPT_MODE";
-            case Cipher.DECRYPT_MODE:
-                return "DECRYPT_MODE";
-            case Cipher.WRAP_MODE:
-                return "WRAP_MODE";
-            case Cipher.UNWRAP_MODE:
-                return "UNWRAP_MODE";
-            default:
-                return String.valueOf(opmode);
-        }
-    }
-
-    // The methods below need to be implemented by subclasses.
-
-    /**
-     * Initializes this cipher with the provided key.
-     *
-     * @throws InvalidKeyException if the {@code key} is not suitable for this cipher in the
-     *         specified {@code opmode}.
-     *
-     * @see #setKey(AndroidKeyStoreKey)
-     */
-    protected abstract void initKey(int opmode, @Nullable Key key) throws InvalidKeyException;
-
-    /**
-     * Returns algorithm-specific parameters used by this cipher or {@code null} if no
-     * algorithm-specific parameters are used.
-     */
-    @Nullable
-    @Override
-    protected abstract AlgorithmParameters engineGetParameters();
-
-    /**
-     * Invoked by {@code engineInit} to initialize algorithm-specific parameters when no additional
-     * initialization parameters were provided.
-     *
-     * @throws InvalidKeyException if this cipher cannot be configured based purely on the provided
-     *         key and needs additional parameters to be provided to {@code Cipher.init}.
-     */
-    protected abstract void initAlgorithmSpecificParameters() throws InvalidKeyException;
-
-    /**
-     * Invoked by {@code engineInit} to initialize algorithm-specific parameters when additional
-     * parameters were provided.
-     *
-     * @param params additional algorithm parameters or {@code null} if not specified.
-     *
-     * @throws InvalidAlgorithmParameterException if there is insufficient information to configure
-     *         this cipher or if the provided parameters are not suitable for this cipher.
-     */
-    protected abstract void initAlgorithmSpecificParameters(
-            @Nullable AlgorithmParameterSpec params) throws InvalidAlgorithmParameterException;
-
-    /**
-     * Invoked by {@code engineInit} to initialize algorithm-specific parameters when additional
-     * parameters were provided.
-     *
-     * @param params additional algorithm parameters or {@code null} if not specified.
-     *
-     * @throws InvalidAlgorithmParameterException if there is insufficient information to configure
-     *         this cipher or if the provided parameters are not suitable for this cipher.
-     */
-    protected abstract void initAlgorithmSpecificParameters(@Nullable AlgorithmParameters params)
-            throws InvalidAlgorithmParameterException;
-
-    /**
-     * Returns the amount of additional entropy (in bytes) to be provided to the KeyStore's
-     * {@code begin} operation. This amount of entropy is typically what's consumed to generate
-     * random parameters, such as IV.
-     *
-     * <p>For decryption, the return value should be {@code 0} because decryption should not be
-     * consuming any entropy. For encryption, the value combined with
-     * {@link #getAdditionalEntropyAmountForFinish()} should match (or exceed) the amount of Shannon
-     * entropy of the ciphertext produced by this cipher assuming the key, the plaintext, and all
-     * explicitly provided parameters to {@code Cipher.init} are known. For example, for AES CBC
-     * encryption with an explicitly provided IV the return value should be {@code 0}, whereas for
-     * the case where IV is generated by the KeyStore's {@code begin} operation it should be
-     * {@code 16}.
-     */
-    protected abstract int getAdditionalEntropyAmountForBegin();
-
-    /**
-     * Returns the amount of additional entropy (in bytes) to be provided to the KeyStore's
-     * {@code finish} operation. This amount of entropy is typically what's consumed by encryption
-     * padding scheme.
-     *
-     * <p>For decryption, the return value should be {@code 0} because decryption should not be
-     * consuming any entropy. For encryption, the value combined with
-     * {@link #getAdditionalEntropyAmountForBegin()} should match (or exceed) the amount of Shannon
-     * entropy of the ciphertext produced by this cipher assuming the key, the plaintext, and all
-     * explicitly provided parameters to {@code Cipher.init} are known. For example, for RSA with
-     * OAEP the return value should be the size of the OAEP hash output. For RSA with PKCS#1 padding
-     * the return value should be the size of the padding string or could be raised (for simplicity)
-     * to the size of the modulus.
-     */
-    protected abstract int getAdditionalEntropyAmountForFinish();
-
-    /**
-     * Invoked to add algorithm-specific parameters for the KeyStore's {@code begin} operation.
-     *
-     * @param keymasterArgs keystore/keymaster arguments to be populated with algorithm-specific
-     *        parameters.
-     */
-    protected abstract void addAlgorithmSpecificParametersToBegin(
-            @NonNull KeymasterArguments keymasterArgs);
-
-    /**
-     * Invoked to obtain algorithm-specific parameters from the result of the KeyStore's
-     * {@code begin} operation.
-     *
-     * <p>Some parameters, such as IV, are not required to be provided to {@code Cipher.init}. Such
-     * parameters, if not provided, must be generated by KeyStore and returned to the user of
-     * {@code Cipher} and potentially reused after {@code doFinal}.
-     *
-     * @param keymasterArgs keystore/keymaster arguments returned by KeyStore {@code begin}
-     *        operation.
-     */
-    protected abstract void loadAlgorithmSpecificParametersFromBeginResult(
-            @NonNull KeymasterArguments keymasterArgs);
-}
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreECDSASignatureSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreECDSASignatureSpi.java
deleted file mode 100644
index 45f2110..0000000
--- a/keystore/java/android/security/keystore/AndroidKeyStoreECDSASignatureSpi.java
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.security.keystore;
-
-import android.annotation.NonNull;
-import android.os.IBinder;
-import android.security.KeyStore;
-import android.security.KeyStoreException;
-import android.security.keymaster.KeyCharacteristics;
-import android.security.keymaster.KeymasterArguments;
-import android.security.keymaster.KeymasterDefs;
-
-import libcore.util.EmptyArray;
-
-import java.io.ByteArrayOutputStream;
-import java.security.InvalidKeyException;
-import java.security.SignatureSpi;
-
-/**
- * Base class for {@link SignatureSpi} providing Android KeyStore backed ECDSA signatures.
- *
- * @hide
- */
-abstract class AndroidKeyStoreECDSASignatureSpi extends AndroidKeyStoreSignatureSpiBase {
-
-    public final static class NONE extends AndroidKeyStoreECDSASignatureSpi {
-        public NONE() {
-            super(KeymasterDefs.KM_DIGEST_NONE);
-        }
-
-        @Override
-        protected KeyStoreCryptoOperationStreamer createMainDataStreamer(KeyStore keyStore,
-                IBinder operationToken) {
-            return new TruncateToFieldSizeMessageStreamer(
-                    super.createMainDataStreamer(keyStore, operationToken),
-                    getGroupSizeBits());
-        }
-
-        /**
-         * Streamer which buffers all input, then truncates it to field size, and then sends it into
-         * KeyStore via the provided delegate streamer.
-         */
-        private static class TruncateToFieldSizeMessageStreamer
-                implements KeyStoreCryptoOperationStreamer {
-
-            private final KeyStoreCryptoOperationStreamer mDelegate;
-            private final int mGroupSizeBits;
-            private final ByteArrayOutputStream mInputBuffer = new ByteArrayOutputStream();
-            private long mConsumedInputSizeBytes;
-
-            private TruncateToFieldSizeMessageStreamer(
-                    KeyStoreCryptoOperationStreamer delegate,
-                    int groupSizeBits) {
-                mDelegate = delegate;
-                mGroupSizeBits = groupSizeBits;
-            }
-
-            @Override
-            public byte[] update(byte[] input, int inputOffset, int inputLength)
-                    throws KeyStoreException {
-                if (inputLength > 0) {
-                    mInputBuffer.write(input, inputOffset, inputLength);
-                    mConsumedInputSizeBytes += inputLength;
-                }
-                return EmptyArray.BYTE;
-            }
-
-            @Override
-            public byte[] doFinal(byte[] input, int inputOffset, int inputLength, byte[] signature,
-                    byte[] additionalEntropy) throws KeyStoreException {
-                if (inputLength > 0) {
-                    mConsumedInputSizeBytes += inputLength;
-                    mInputBuffer.write(input, inputOffset, inputLength);
-                }
-
-                byte[] bufferedInput = mInputBuffer.toByteArray();
-                mInputBuffer.reset();
-                // Truncate input at field size (bytes)
-                return mDelegate.doFinal(bufferedInput,
-                        0,
-                        Math.min(bufferedInput.length, ((mGroupSizeBits + 7) / 8)),
-                        signature, additionalEntropy);
-            }
-
-            @Override
-            public long getConsumedInputSizeBytes() {
-                return mConsumedInputSizeBytes;
-            }
-
-            @Override
-            public long getProducedOutputSizeBytes() {
-                return mDelegate.getProducedOutputSizeBytes();
-            }
-        }
-    }
-
-    public final static class SHA1 extends AndroidKeyStoreECDSASignatureSpi {
-        public SHA1() {
-            super(KeymasterDefs.KM_DIGEST_SHA1);
-        }
-    }
-
-    public final static class SHA224 extends AndroidKeyStoreECDSASignatureSpi {
-        public SHA224() {
-            super(KeymasterDefs.KM_DIGEST_SHA_2_224);
-        }
-    }
-
-    public final static class SHA256 extends AndroidKeyStoreECDSASignatureSpi {
-        public SHA256() {
-            super(KeymasterDefs.KM_DIGEST_SHA_2_256);
-        }
-    }
-
-    public final static class SHA384 extends AndroidKeyStoreECDSASignatureSpi {
-        public SHA384() {
-            super(KeymasterDefs.KM_DIGEST_SHA_2_384);
-        }
-    }
-
-    public final static class SHA512 extends AndroidKeyStoreECDSASignatureSpi {
-        public SHA512() {
-            super(KeymasterDefs.KM_DIGEST_SHA_2_512);
-        }
-    }
-
-    private final int mKeymasterDigest;
-
-    private int mGroupSizeBits = -1;
-
-    AndroidKeyStoreECDSASignatureSpi(int keymasterDigest) {
-        mKeymasterDigest = keymasterDigest;
-    }
-
-    @Override
-    protected final void initKey(AndroidKeyStoreKey key) throws InvalidKeyException {
-        if (!KeyProperties.KEY_ALGORITHM_EC.equalsIgnoreCase(key.getAlgorithm())) {
-            throw new InvalidKeyException("Unsupported key algorithm: " + key.getAlgorithm()
-                    + ". Only" + KeyProperties.KEY_ALGORITHM_EC + " supported");
-        }
-
-        KeyCharacteristics keyCharacteristics = new KeyCharacteristics();
-        int errorCode = getKeyStore().getKeyCharacteristics(
-                key.getAlias(), null, null, key.getUid(), keyCharacteristics);
-        if (errorCode != KeyStore.NO_ERROR) {
-            throw getKeyStore().getInvalidKeyException(key.getAlias(), key.getUid(), errorCode);
-        }
-        long keySizeBits = keyCharacteristics.getUnsignedInt(KeymasterDefs.KM_TAG_KEY_SIZE, -1);
-        if (keySizeBits == -1) {
-            throw new InvalidKeyException("Size of key not known");
-        } else if (keySizeBits > Integer.MAX_VALUE) {
-            throw new InvalidKeyException("Key too large: " + keySizeBits + " bits");
-        }
-        mGroupSizeBits = (int) keySizeBits;
-
-        super.initKey(key);
-    }
-
-    @Override
-    protected final void resetAll() {
-        mGroupSizeBits = -1;
-        super.resetAll();
-    }
-
-    @Override
-    protected final void resetWhilePreservingInitState() {
-        super.resetWhilePreservingInitState();
-    }
-
-    @Override
-    protected final void addAlgorithmSpecificParametersToBegin(
-            @NonNull KeymasterArguments keymasterArgs) {
-        keymasterArgs.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_EC);
-        keymasterArgs.addEnum(KeymasterDefs.KM_TAG_DIGEST, mKeymasterDigest);
-    }
-
-    @Override
-    protected final int getAdditionalEntropyAmountForSign() {
-        return (mGroupSizeBits + 7) / 8;
-    }
-
-    protected final int getGroupSizeBits() {
-        if (mGroupSizeBits == -1) {
-            throw new IllegalStateException("Not initialized");
-        }
-        return mGroupSizeBits;
-    }
-}
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreECPrivateKey.java b/keystore/java/android/security/keystore/AndroidKeyStoreECPrivateKey.java
deleted file mode 100644
index aa7bdff..0000000
--- a/keystore/java/android/security/keystore/AndroidKeyStoreECPrivateKey.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.security.keystore;
-
-import java.security.PrivateKey;
-import java.security.interfaces.ECKey;
-import java.security.spec.ECParameterSpec;
-
-/**
- * EC private key (instance of {@link PrivateKey} and {@link ECKey}) backed by keystore.
- *
- * @hide
- */
-public class AndroidKeyStoreECPrivateKey extends AndroidKeyStorePrivateKey implements ECKey {
-    private final ECParameterSpec mParams;
-
-    public AndroidKeyStoreECPrivateKey(String alias, int uid, ECParameterSpec params) {
-        super(alias, uid, KeyProperties.KEY_ALGORITHM_EC);
-        mParams = params;
-    }
-
-    @Override
-    public ECParameterSpec getParams() {
-        return mParams;
-    }
-}
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreECPublicKey.java b/keystore/java/android/security/keystore/AndroidKeyStoreECPublicKey.java
deleted file mode 100644
index 2efaeb6..0000000
--- a/keystore/java/android/security/keystore/AndroidKeyStoreECPublicKey.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.security.keystore;
-
-import java.security.interfaces.ECPublicKey;
-import java.security.spec.ECParameterSpec;
-import java.security.spec.ECPoint;
-
-/**
- * {@link ECPublicKey} backed by keystore.
- *
- * @hide
- */
-public class AndroidKeyStoreECPublicKey extends AndroidKeyStorePublicKey implements ECPublicKey {
-
-    private final ECParameterSpec mParams;
-    private final ECPoint mW;
-
-    public AndroidKeyStoreECPublicKey(String alias, int uid, byte[] x509EncodedForm, ECParameterSpec params,
-            ECPoint w) {
-        super(alias, uid, KeyProperties.KEY_ALGORITHM_EC, x509EncodedForm);
-        mParams = params;
-        mW = w;
-    }
-
-    public AndroidKeyStoreECPublicKey(String alias, int uid, ECPublicKey info) {
-        this(alias, uid, info.getEncoded(), info.getParams(), info.getW());
-        if (!"X.509".equalsIgnoreCase(info.getFormat())) {
-            throw new IllegalArgumentException(
-                    "Unsupported key export format: " + info.getFormat());
-        }
-    }
-
-    @Override
-    public ECParameterSpec getParams() {
-        return mParams;
-    }
-
-    @Override
-    public ECPoint getW() {
-        return mW;
-    }
-}
\ No newline at end of file
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreHmacSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreHmacSpi.java
deleted file mode 100644
index 2e8ac32..0000000
--- a/keystore/java/android/security/keystore/AndroidKeyStoreHmacSpi.java
+++ /dev/null
@@ -1,265 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.security.keystore;
-
-import android.os.IBinder;
-import android.security.KeyStore;
-import android.security.KeyStoreException;
-import android.security.keymaster.KeymasterArguments;
-import android.security.keymaster.KeymasterDefs;
-import android.security.keymaster.OperationResult;
-
-import java.security.InvalidAlgorithmParameterException;
-import java.security.InvalidKeyException;
-import java.security.Key;
-import java.security.ProviderException;
-import java.security.spec.AlgorithmParameterSpec;
-
-import javax.crypto.MacSpi;
-
-/**
- * {@link MacSpi} which provides HMAC implementations backed by Android KeyStore.
- *
- * @hide
- */
-public abstract class AndroidKeyStoreHmacSpi extends MacSpi implements KeyStoreCryptoOperation {
-
-    public static class HmacSHA1 extends AndroidKeyStoreHmacSpi {
-        public HmacSHA1() {
-            super(KeymasterDefs.KM_DIGEST_SHA1);
-        }
-    }
-
-    public static class HmacSHA224 extends AndroidKeyStoreHmacSpi {
-        public HmacSHA224() {
-            super(KeymasterDefs.KM_DIGEST_SHA_2_224);
-        }
-    }
-
-    public static class HmacSHA256 extends AndroidKeyStoreHmacSpi {
-        public HmacSHA256() {
-            super(KeymasterDefs.KM_DIGEST_SHA_2_256);
-        }
-    }
-
-    public static class HmacSHA384 extends AndroidKeyStoreHmacSpi {
-        public HmacSHA384() {
-            super(KeymasterDefs.KM_DIGEST_SHA_2_384);
-        }
-    }
-
-    public static class HmacSHA512 extends AndroidKeyStoreHmacSpi {
-        public HmacSHA512() {
-            super(KeymasterDefs.KM_DIGEST_SHA_2_512);
-        }
-    }
-
-    private final KeyStore mKeyStore = KeyStore.getInstance();
-    private final int mKeymasterDigest;
-    private final int mMacSizeBits;
-
-    // Fields below are populated by engineInit and should be preserved after engineDoFinal.
-    private AndroidKeyStoreSecretKey mKey;
-
-    // Fields below are reset when engineDoFinal succeeds.
-    private KeyStoreCryptoOperationChunkedStreamer mChunkedStreamer;
-    private IBinder mOperationToken;
-    private long mOperationHandle;
-
-    protected AndroidKeyStoreHmacSpi(int keymasterDigest) {
-        mKeymasterDigest = keymasterDigest;
-        mMacSizeBits = KeymasterUtils.getDigestOutputSizeBits(keymasterDigest);
-    }
-
-    @Override
-    protected int engineGetMacLength() {
-        return (mMacSizeBits + 7) / 8;
-    }
-
-    @Override
-    protected void engineInit(Key key, AlgorithmParameterSpec params) throws InvalidKeyException,
-            InvalidAlgorithmParameterException {
-        resetAll();
-
-        boolean success = false;
-        try {
-            init(key, params);
-            ensureKeystoreOperationInitialized();
-            success = true;
-        } finally {
-            if (!success) {
-                resetAll();
-            }
-        }
-    }
-
-    private void init(Key key, AlgorithmParameterSpec params) throws InvalidKeyException,
-        InvalidAlgorithmParameterException {
-        if (key == null) {
-            throw new InvalidKeyException("key == null");
-        } else if (!(key instanceof AndroidKeyStoreSecretKey)) {
-            throw new InvalidKeyException(
-                    "Only Android KeyStore secret keys supported. Key: " + key);
-        }
-        mKey = (AndroidKeyStoreSecretKey) key;
-
-        if (params != null) {
-            throw new InvalidAlgorithmParameterException(
-                    "Unsupported algorithm parameters: " + params);
-        }
-
-    }
-
-    private void resetAll() {
-        mKey = null;
-        IBinder operationToken = mOperationToken;
-        if (operationToken != null) {
-            mKeyStore.abort(operationToken);
-        }
-        mOperationToken = null;
-        mOperationHandle = 0;
-        mChunkedStreamer = null;
-    }
-
-    private void resetWhilePreservingInitState() {
-        IBinder operationToken = mOperationToken;
-        if (operationToken != null) {
-            mKeyStore.abort(operationToken);
-        }
-        mOperationToken = null;
-        mOperationHandle = 0;
-        mChunkedStreamer = null;
-    }
-
-    @Override
-    protected void engineReset() {
-        resetWhilePreservingInitState();
-    }
-
-    private void ensureKeystoreOperationInitialized() throws InvalidKeyException {
-        if (mChunkedStreamer != null) {
-            return;
-        }
-        if (mKey == null) {
-            throw new IllegalStateException("Not initialized");
-        }
-
-        KeymasterArguments keymasterArgs = new KeymasterArguments();
-        keymasterArgs.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_HMAC);
-        keymasterArgs.addEnum(KeymasterDefs.KM_TAG_DIGEST, mKeymasterDigest);
-        keymasterArgs.addUnsignedInt(KeymasterDefs.KM_TAG_MAC_LENGTH, mMacSizeBits);
-
-        OperationResult opResult = mKeyStore.begin(
-                mKey.getAlias(),
-                KeymasterDefs.KM_PURPOSE_SIGN,
-                true,
-                keymasterArgs,
-                null, // no additional entropy needed for HMAC because it's deterministic
-                mKey.getUid());
-
-        if (opResult == null) {
-            throw new KeyStoreConnectException();
-        }
-
-        // Store operation token and handle regardless of the error code returned by KeyStore to
-        // ensure that the operation gets aborted immediately if the code below throws an exception.
-        mOperationToken = opResult.token;
-        mOperationHandle = opResult.operationHandle;
-
-        // If necessary, throw an exception due to KeyStore operation having failed.
-        InvalidKeyException e = KeyStoreCryptoOperationUtils.getInvalidKeyExceptionForInit(
-                mKeyStore, mKey, opResult.resultCode);
-        if (e != null) {
-            throw e;
-        }
-
-        if (mOperationToken == null) {
-            throw new ProviderException("Keystore returned null operation token");
-        }
-        if (mOperationHandle == 0) {
-            throw new ProviderException("Keystore returned invalid operation handle");
-        }
-
-        mChunkedStreamer = new KeyStoreCryptoOperationChunkedStreamer(
-                new KeyStoreCryptoOperationChunkedStreamer.MainDataStream(
-                        mKeyStore, mOperationToken));
-    }
-
-    @Override
-    protected void engineUpdate(byte input) {
-        engineUpdate(new byte[] {input}, 0, 1);
-    }
-
-    @Override
-    protected void engineUpdate(byte[] input, int offset, int len) {
-        try {
-            ensureKeystoreOperationInitialized();
-        } catch (InvalidKeyException e) {
-            throw new ProviderException("Failed to reinitialize MAC", e);
-        }
-
-        byte[] output;
-        try {
-            output = mChunkedStreamer.update(input, offset, len);
-        } catch (KeyStoreException e) {
-            throw new ProviderException("Keystore operation failed", e);
-        }
-        if ((output != null) && (output.length != 0)) {
-            throw new ProviderException("Update operation unexpectedly produced output");
-        }
-    }
-
-    @Override
-    protected byte[] engineDoFinal() {
-        try {
-            ensureKeystoreOperationInitialized();
-        } catch (InvalidKeyException e) {
-            throw new ProviderException("Failed to reinitialize MAC", e);
-        }
-
-        byte[] result;
-        try {
-            result = mChunkedStreamer.doFinal(
-                    null, 0, 0,
-                    null, // no signature provided -- this invocation will generate one
-                    null // no additional entropy needed -- HMAC is deterministic
-                    );
-        } catch (KeyStoreException e) {
-            throw new ProviderException("Keystore operation failed", e);
-        }
-
-        resetWhilePreservingInitState();
-        return result;
-    }
-
-    @Override
-    public void finalize() throws Throwable {
-        try {
-            IBinder operationToken = mOperationToken;
-            if (operationToken != null) {
-                mKeyStore.abort(operationToken);
-            }
-        } finally {
-            super.finalize();
-        }
-    }
-
-    @Override
-    public long getOperationHandle() {
-        return mOperationHandle;
-    }
-}
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreKey.java b/keystore/java/android/security/keystore/AndroidKeyStoreKey.java
deleted file mode 100644
index e8e6310..0000000
--- a/keystore/java/android/security/keystore/AndroidKeyStoreKey.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.security.keystore;
-
-import java.security.Key;
-
-/**
- * {@link Key} backed by Android Keystore.
- *
- * @hide
- */
-public class AndroidKeyStoreKey implements Key {
-    private final String mAlias;
-    private final int mUid;
-    private final String mAlgorithm;
-
-    public AndroidKeyStoreKey(String alias, int uid, String algorithm) {
-        mAlias = alias;
-        mUid = uid;
-        mAlgorithm = algorithm;
-    }
-
-    String getAlias() {
-        return mAlias;
-    }
-
-    int getUid() {
-        return mUid;
-    }
-
-    @Override
-    public String getAlgorithm() {
-        return mAlgorithm;
-    }
-
-    @Override
-    public String getFormat() {
-        // This key does not export its key material
-        return null;
-    }
-
-    @Override
-    public byte[] getEncoded() {
-        // This key does not export its key material
-        return null;
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result + ((mAlgorithm == null) ? 0 : mAlgorithm.hashCode());
-        result = prime * result + ((mAlias == null) ? 0 : mAlias.hashCode());
-        result = prime * result + mUid;
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj == null) {
-            return false;
-        }
-        if (getClass() != obj.getClass()) {
-            return false;
-        }
-        AndroidKeyStoreKey other = (AndroidKeyStoreKey) obj;
-        if (mAlgorithm == null) {
-            if (other.mAlgorithm != null) {
-                return false;
-            }
-        } else if (!mAlgorithm.equals(other.mAlgorithm)) {
-            return false;
-        }
-        if (mAlias == null) {
-            if (other.mAlias != null) {
-                return false;
-            }
-        } else if (!mAlias.equals(other.mAlias)) {
-            return false;
-        }
-        if (mUid != other.mUid) {
-            return false;
-        }
-        return true;
-    }
-}
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreKeyFactorySpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreKeyFactorySpi.java
deleted file mode 100644
index 303b0f2..0000000
--- a/keystore/java/android/security/keystore/AndroidKeyStoreKeyFactorySpi.java
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.security.keystore;
-
-import android.security.Credentials;
-import android.security.KeyStore;
-
-import java.security.InvalidKeyException;
-import java.security.Key;
-import java.security.KeyFactorySpi;
-import java.security.PrivateKey;
-import java.security.PublicKey;
-import java.security.spec.ECPublicKeySpec;
-import java.security.spec.InvalidKeySpecException;
-import java.security.spec.KeySpec;
-import java.security.spec.PKCS8EncodedKeySpec;
-import java.security.spec.RSAPublicKeySpec;
-import java.security.spec.X509EncodedKeySpec;
-
-/**
- * {@link KeyFactorySpi} backed by Android KeyStore.
- *
- * @hide
- */
-public class AndroidKeyStoreKeyFactorySpi extends KeyFactorySpi {
-
-    private final KeyStore mKeyStore = KeyStore.getInstance();
-
-    @Override
-    protected <T extends KeySpec> T engineGetKeySpec(Key key, Class<T> keySpecClass)
-            throws InvalidKeySpecException {
-        if (key == null) {
-            throw new InvalidKeySpecException("key == null");
-        } else if ((!(key instanceof AndroidKeyStorePrivateKey))
-            && (!(key instanceof AndroidKeyStorePublicKey))) {
-            throw new InvalidKeySpecException(
-                    "Unsupported key type: " + key.getClass().getName()
-                    + ". This KeyFactory supports only Android Keystore asymmetric keys");
-        }
-
-        // key is an Android Keystore private or public key
-
-        if (keySpecClass == null) {
-            throw new InvalidKeySpecException("keySpecClass == null");
-        } else if (KeyInfo.class.equals(keySpecClass)) {
-            if (!(key instanceof AndroidKeyStorePrivateKey)) {
-                throw new InvalidKeySpecException(
-                        "Unsupported key type: " + key.getClass().getName()
-                        + ". KeyInfo can be obtained only for Android Keystore private keys");
-            }
-            AndroidKeyStorePrivateKey keystorePrivateKey = (AndroidKeyStorePrivateKey) key;
-            String keyAliasInKeystore = keystorePrivateKey.getAlias();
-            String entryAlias;
-            if (keyAliasInKeystore.startsWith(Credentials.USER_PRIVATE_KEY)) {
-                entryAlias = keyAliasInKeystore.substring(Credentials.USER_PRIVATE_KEY.length());
-            } else {
-                throw new InvalidKeySpecException("Invalid key alias: " + keyAliasInKeystore);
-            }
-            @SuppressWarnings("unchecked")
-            T result = (T) AndroidKeyStoreSecretKeyFactorySpi.getKeyInfo(
-                    mKeyStore, entryAlias, keyAliasInKeystore, keystorePrivateKey.getUid());
-            return result;
-        } else if (X509EncodedKeySpec.class.equals(keySpecClass)) {
-            if (!(key instanceof AndroidKeyStorePublicKey)) {
-                throw new InvalidKeySpecException(
-                        "Unsupported key type: " + key.getClass().getName()
-                        + ". X509EncodedKeySpec can be obtained only for Android Keystore public"
-                        + " keys");
-            }
-            @SuppressWarnings("unchecked")
-            T result = (T) new X509EncodedKeySpec(((AndroidKeyStorePublicKey) key).getEncoded());
-            return result;
-        } else if (PKCS8EncodedKeySpec.class.equals(keySpecClass)) {
-            if (key instanceof AndroidKeyStorePrivateKey) {
-                throw new InvalidKeySpecException(
-                        "Key material export of Android Keystore private keys is not supported");
-            } else {
-                throw new InvalidKeySpecException(
-                        "Cannot export key material of public key in PKCS#8 format."
-                        + " Only X.509 format (X509EncodedKeySpec) supported for public keys.");
-            }
-        } else if (RSAPublicKeySpec.class.equals(keySpecClass)) {
-            if (key instanceof AndroidKeyStoreRSAPublicKey) {
-                AndroidKeyStoreRSAPublicKey rsaKey = (AndroidKeyStoreRSAPublicKey) key;
-                @SuppressWarnings("unchecked")
-                T result =
-                        (T) new RSAPublicKeySpec(rsaKey.getModulus(), rsaKey.getPublicExponent());
-                return result;
-            } else {
-                throw new InvalidKeySpecException(
-                        "Obtaining RSAPublicKeySpec not supported for " + key.getAlgorithm() + " "
-                        + ((key instanceof AndroidKeyStorePrivateKey) ? "private" : "public")
-                        + " key");
-            }
-        } else if (ECPublicKeySpec.class.equals(keySpecClass)) {
-            if (key instanceof AndroidKeyStoreECPublicKey) {
-                AndroidKeyStoreECPublicKey ecKey = (AndroidKeyStoreECPublicKey) key;
-                @SuppressWarnings("unchecked")
-                T result = (T) new ECPublicKeySpec(ecKey.getW(), ecKey.getParams());
-                return result;
-            } else {
-                throw new InvalidKeySpecException(
-                        "Obtaining ECPublicKeySpec not supported for " + key.getAlgorithm() + " "
-                        + ((key instanceof AndroidKeyStorePrivateKey) ? "private" : "public")
-                        + " key");
-            }
-        } else {
-            throw new InvalidKeySpecException("Unsupported key spec: " + keySpecClass.getName());
-        }
-    }
-
-    @Override
-    protected PrivateKey engineGeneratePrivate(KeySpec spec) throws InvalidKeySpecException {
-        throw new InvalidKeySpecException(
-                "To generate a key pair in Android Keystore, use KeyPairGenerator initialized with"
-                + " " + KeyGenParameterSpec.class.getName());
-    }
-
-    @Override
-    protected PublicKey engineGeneratePublic(KeySpec spec) throws InvalidKeySpecException {
-        throw new InvalidKeySpecException(
-                "To generate a key pair in Android Keystore, use KeyPairGenerator initialized with"
-                + " " + KeyGenParameterSpec.class.getName());
-    }
-
-    @Override
-    protected Key engineTranslateKey(Key key) throws InvalidKeyException {
-        if (key == null) {
-            throw new InvalidKeyException("key == null");
-        } else if ((!(key instanceof AndroidKeyStorePrivateKey))
-                && (!(key instanceof AndroidKeyStorePublicKey))) {
-            throw new InvalidKeyException(
-                    "To import a key into Android Keystore, use KeyStore.setEntry");
-        }
-        return key;
-    }
-}
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java
deleted file mode 100644
index fedde42..0000000
--- a/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java
+++ /dev/null
@@ -1,352 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.security.keystore;
-
-import android.security.Credentials;
-import android.security.KeyStore;
-import android.security.keymaster.KeyCharacteristics;
-import android.security.keymaster.KeymasterArguments;
-import android.security.keymaster.KeymasterDefs;
-import android.security.keystore.KeyGenParameterSpec;
-import android.security.keystore.KeyProperties;
-
-import libcore.util.EmptyArray;
-
-import java.security.InvalidAlgorithmParameterException;
-import java.security.ProviderException;
-import java.security.SecureRandom;
-import java.security.spec.AlgorithmParameterSpec;
-import java.util.Arrays;
-
-import javax.crypto.KeyGeneratorSpi;
-import javax.crypto.SecretKey;
-
-/**
- * {@link KeyGeneratorSpi} backed by Android KeyStore.
- *
- * @hide
- */
-public abstract class AndroidKeyStoreKeyGeneratorSpi extends KeyGeneratorSpi {
-
-    public static class AES extends AndroidKeyStoreKeyGeneratorSpi {
-        public AES() {
-            super(KeymasterDefs.KM_ALGORITHM_AES, 128);
-        }
-
-        @Override
-        protected void engineInit(AlgorithmParameterSpec params, SecureRandom random)
-                throws InvalidAlgorithmParameterException {
-            super.engineInit(params, random);
-            if ((mKeySizeBits != 128) && (mKeySizeBits != 192) && (mKeySizeBits != 256)) {
-                throw new InvalidAlgorithmParameterException(
-                        "Unsupported key size: " + mKeySizeBits
-                        + ". Supported: 128, 192, 256.");
-            }
-        }
-    }
-
-    public static class DESede extends AndroidKeyStoreKeyGeneratorSpi {
-        public DESede() {
-            super(KeymasterDefs.KM_ALGORITHM_3DES, 168);
-        }
-    }
-
-    protected static abstract class HmacBase extends AndroidKeyStoreKeyGeneratorSpi {
-        protected HmacBase(int keymasterDigest) {
-            super(KeymasterDefs.KM_ALGORITHM_HMAC,
-                    keymasterDigest,
-                    KeymasterUtils.getDigestOutputSizeBits(keymasterDigest));
-        }
-    }
-
-    public static class HmacSHA1 extends HmacBase {
-        public HmacSHA1() {
-            super(KeymasterDefs.KM_DIGEST_SHA1);
-        }
-    }
-
-    public static class HmacSHA224 extends HmacBase {
-        public HmacSHA224() {
-            super(KeymasterDefs.KM_DIGEST_SHA_2_224);
-        }
-    }
-
-    public static class HmacSHA256 extends HmacBase {
-        public HmacSHA256() {
-            super(KeymasterDefs.KM_DIGEST_SHA_2_256);
-        }
-    }
-
-    public static class HmacSHA384 extends HmacBase {
-        public HmacSHA384() {
-            super(KeymasterDefs.KM_DIGEST_SHA_2_384);
-        }
-    }
-
-    public static class HmacSHA512 extends HmacBase {
-        public HmacSHA512() {
-            super(KeymasterDefs.KM_DIGEST_SHA_2_512);
-        }
-    }
-
-    private final KeyStore mKeyStore = KeyStore.getInstance();
-    private final int mKeymasterAlgorithm;
-    private final int mKeymasterDigest;
-    private final int mDefaultKeySizeBits;
-
-    private KeyGenParameterSpec mSpec;
-    private SecureRandom mRng;
-
-    protected int mKeySizeBits;
-    private int[] mKeymasterPurposes;
-    private int[] mKeymasterBlockModes;
-    private int[] mKeymasterPaddings;
-    private int[] mKeymasterDigests;
-
-    protected AndroidKeyStoreKeyGeneratorSpi(
-            int keymasterAlgorithm,
-            int defaultKeySizeBits) {
-        this(keymasterAlgorithm, -1, defaultKeySizeBits);
-    }
-
-    protected AndroidKeyStoreKeyGeneratorSpi(
-            int keymasterAlgorithm,
-            int keymasterDigest,
-            int defaultKeySizeBits) {
-        mKeymasterAlgorithm = keymasterAlgorithm;
-        mKeymasterDigest = keymasterDigest;
-        mDefaultKeySizeBits = defaultKeySizeBits;
-        if (mDefaultKeySizeBits <= 0) {
-            throw new IllegalArgumentException("Default key size must be positive");
-        }
-
-        if ((mKeymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_HMAC) && (mKeymasterDigest == -1)) {
-            throw new IllegalArgumentException(
-                    "Digest algorithm must be specified for HMAC key");
-        }
-    }
-
-    @Override
-    protected void engineInit(SecureRandom random) {
-        throw new UnsupportedOperationException("Cannot initialize without a "
-                + KeyGenParameterSpec.class.getName() + " parameter");
-    }
-
-    @Override
-    protected void engineInit(int keySize, SecureRandom random) {
-        throw new UnsupportedOperationException("Cannot initialize without a "
-                + KeyGenParameterSpec.class.getName() + " parameter");
-    }
-
-    @Override
-    protected void engineInit(AlgorithmParameterSpec params, SecureRandom random)
-            throws InvalidAlgorithmParameterException {
-        resetAll();
-
-        boolean success = false;
-        try {
-            if ((params == null) || (!(params instanceof KeyGenParameterSpec))) {
-                throw new InvalidAlgorithmParameterException("Cannot initialize without a "
-                        + KeyGenParameterSpec.class.getName() + " parameter");
-            }
-            KeyGenParameterSpec spec = (KeyGenParameterSpec) params;
-            if (spec.getKeystoreAlias() == null) {
-                throw new InvalidAlgorithmParameterException("KeyStore entry alias not provided");
-            }
-
-            mRng = random;
-            mSpec = spec;
-
-            mKeySizeBits = (spec.getKeySize() != -1) ? spec.getKeySize() : mDefaultKeySizeBits;
-            if (mKeySizeBits <= 0) {
-                throw new InvalidAlgorithmParameterException(
-                        "Key size must be positive: " + mKeySizeBits);
-            } else if ((mKeySizeBits % 8) != 0) {
-                throw new InvalidAlgorithmParameterException(
-                        "Key size must be a multiple of 8: " + mKeySizeBits);
-            }
-
-            try {
-                mKeymasterPurposes = KeyProperties.Purpose.allToKeymaster(spec.getPurposes());
-                mKeymasterPaddings = KeyProperties.EncryptionPadding.allToKeymaster(
-                        spec.getEncryptionPaddings());
-                if (spec.getSignaturePaddings().length > 0) {
-                    throw new InvalidAlgorithmParameterException(
-                            "Signature paddings not supported for symmetric key algorithms");
-                }
-                mKeymasterBlockModes = KeyProperties.BlockMode.allToKeymaster(spec.getBlockModes());
-                if (((spec.getPurposes() & KeyProperties.PURPOSE_ENCRYPT) != 0)
-                        && (spec.isRandomizedEncryptionRequired())) {
-                    for (int keymasterBlockMode : mKeymasterBlockModes) {
-                        if (!KeymasterUtils.isKeymasterBlockModeIndCpaCompatibleWithSymmetricCrypto(
-                                keymasterBlockMode)) {
-                            throw new InvalidAlgorithmParameterException(
-                                    "Randomized encryption (IND-CPA) required but may be violated"
-                                    + " by block mode: "
-                                    + KeyProperties.BlockMode.fromKeymaster(keymasterBlockMode)
-                                    + ". See " + KeyGenParameterSpec.class.getName()
-                                    + " documentation.");
-                        }
-                    }
-                }
-                if (mKeymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_3DES) {
-                    if (mKeySizeBits != 168) {
-                        throw new InvalidAlgorithmParameterException(
-                            "3DES key size must be 168 bits.");
-                    }
-                }
-                if (mKeymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_HMAC) {
-                    if (mKeySizeBits < 64 || mKeySizeBits > 512) {
-                        throw new InvalidAlgorithmParameterException(
-                            "HMAC key sizes must be within 64-512 bits, inclusive.");
-                    }
-
-                    // JCA HMAC key algorithm implies a digest (e.g., HmacSHA256 key algorithm
-                    // implies SHA-256 digest). Because keymaster HMAC key is authorized only for
-                    // one digest, we don't let algorithm parameter spec override the digest implied
-                    // by the key. If the spec specifies digests at all, it must specify only one
-                    // digest, the only implied by key algorithm.
-                    mKeymasterDigests = new int[] {mKeymasterDigest};
-                    if (spec.isDigestsSpecified()) {
-                        // Digest(s) explicitly specified in the spec. Check that the list
-                        // consists of exactly one digest, the one implied by key algorithm.
-                        int[] keymasterDigestsFromSpec =
-                                KeyProperties.Digest.allToKeymaster(spec.getDigests());
-                        if ((keymasterDigestsFromSpec.length != 1)
-                                || (keymasterDigestsFromSpec[0] != mKeymasterDigest)) {
-                            throw new InvalidAlgorithmParameterException(
-                                    "Unsupported digests specification: "
-                                    + Arrays.asList(spec.getDigests()) + ". Only "
-                                    + KeyProperties.Digest.fromKeymaster(mKeymasterDigest)
-                                    + " supported for this HMAC key algorithm");
-                        }
-                    }
-                } else {
-                    // Key algorithm does not imply a digest.
-                    if (spec.isDigestsSpecified()) {
-                        mKeymasterDigests = KeyProperties.Digest.allToKeymaster(spec.getDigests());
-                    } else {
-                        mKeymasterDigests = EmptyArray.INT;
-                    }
-                }
-
-                // Check that user authentication related parameters are acceptable. This method
-                // will throw an IllegalStateException if there are issues (e.g., secure lock screen
-                // not set up).
-                KeymasterUtils.addUserAuthArgs(new KeymasterArguments(), spec);
-            } catch (IllegalStateException | IllegalArgumentException e) {
-                throw new InvalidAlgorithmParameterException(e);
-            }
-
-            success = true;
-        } finally {
-            if (!success) {
-                resetAll();
-            }
-        }
-    }
-
-    private void resetAll() {
-        mSpec = null;
-        mRng = null;
-        mKeySizeBits = -1;
-        mKeymasterPurposes = null;
-        mKeymasterPaddings = null;
-        mKeymasterBlockModes = null;
-    }
-
-    @Override
-    protected SecretKey engineGenerateKey() {
-        KeyGenParameterSpec spec = mSpec;
-        if (spec == null) {
-            throw new IllegalStateException("Not initialized");
-        }
-
-        KeymasterArguments args = new KeymasterArguments();
-        args.addUnsignedInt(KeymasterDefs.KM_TAG_KEY_SIZE, mKeySizeBits);
-        args.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, mKeymasterAlgorithm);
-        args.addEnums(KeymasterDefs.KM_TAG_PURPOSE, mKeymasterPurposes);
-        args.addEnums(KeymasterDefs.KM_TAG_BLOCK_MODE, mKeymasterBlockModes);
-        args.addEnums(KeymasterDefs.KM_TAG_PADDING, mKeymasterPaddings);
-        args.addEnums(KeymasterDefs.KM_TAG_DIGEST, mKeymasterDigests);
-        KeymasterUtils.addUserAuthArgs(args, spec);
-        KeymasterUtils.addMinMacLengthAuthorizationIfNecessary(
-                args,
-                mKeymasterAlgorithm,
-                mKeymasterBlockModes,
-                mKeymasterDigests);
-        args.addDateIfNotNull(KeymasterDefs.KM_TAG_ACTIVE_DATETIME, spec.getKeyValidityStart());
-        args.addDateIfNotNull(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME,
-                spec.getKeyValidityForOriginationEnd());
-        args.addDateIfNotNull(KeymasterDefs.KM_TAG_USAGE_EXPIRE_DATETIME,
-                spec.getKeyValidityForConsumptionEnd());
-
-        if (((spec.getPurposes() & KeyProperties.PURPOSE_ENCRYPT) != 0)
-                && (!spec.isRandomizedEncryptionRequired())) {
-            // Permit caller-provided IV when encrypting with this key
-            args.addBoolean(KeymasterDefs.KM_TAG_CALLER_NONCE);
-        }
-
-        byte[] additionalEntropy =
-                KeyStoreCryptoOperationUtils.getRandomBytesToMixIntoKeystoreRng(
-                        mRng, (mKeySizeBits + 7) / 8);
-        int flags = 0;
-        if (spec.isStrongBoxBacked()) {
-            flags |= KeyStore.FLAG_STRONGBOX;
-        }
-        if (spec.isCriticalToDeviceEncryption()) {
-            flags |= KeyStore.FLAG_CRITICAL_TO_DEVICE_ENCRYPTION;
-        }
-        String keyAliasInKeystore = Credentials.USER_PRIVATE_KEY + spec.getKeystoreAlias();
-        KeyCharacteristics resultingKeyCharacteristics = new KeyCharacteristics();
-        boolean success = false;
-        try {
-            Credentials.deleteAllTypesForAlias(mKeyStore, spec.getKeystoreAlias(), spec.getUid());
-            int errorCode = mKeyStore.generateKey(
-                    keyAliasInKeystore,
-                    args,
-                    additionalEntropy,
-                    spec.getUid(),
-                    flags,
-                    resultingKeyCharacteristics);
-            if (errorCode != KeyStore.NO_ERROR) {
-                if (errorCode == KeyStore.HARDWARE_TYPE_UNAVAILABLE) {
-                    throw new StrongBoxUnavailableException("Failed to generate key");
-                } else {
-                    throw new ProviderException(
-                            "Keystore operation failed", KeyStore.getKeyStoreException(errorCode));
-                }
-            }
-            @KeyProperties.KeyAlgorithmEnum String keyAlgorithmJCA;
-            try {
-                keyAlgorithmJCA = KeyProperties.KeyAlgorithm.fromKeymasterSecretKeyAlgorithm(
-                        mKeymasterAlgorithm, mKeymasterDigest);
-            } catch (IllegalArgumentException e) {
-                throw new ProviderException("Failed to obtain JCA secret key algorithm name", e);
-            }
-            SecretKey result = new AndroidKeyStoreSecretKey(
-                    keyAliasInKeystore, spec.getUid(), keyAlgorithmJCA);
-            success = true;
-            return result;
-        } finally {
-            if (!success) {
-                Credentials.deleteAllTypesForAlias(
-                        mKeyStore, spec.getKeystoreAlias(), spec.getUid());
-            }
-        }
-    }
-}
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java
deleted file mode 100644
index 988838b..0000000
--- a/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java
+++ /dev/null
@@ -1,986 +0,0 @@
-/*
- * Copyright (C) 2012 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.Nullable;
-import android.content.Context;
-import android.os.Build;
-import android.security.Credentials;
-import android.security.KeyPairGeneratorSpec;
-import android.security.KeyStore;
-import android.security.keymaster.KeyCharacteristics;
-import android.security.keymaster.KeymasterArguments;
-import android.security.keymaster.KeymasterCertificateChain;
-import android.security.keymaster.KeymasterDefs;
-import android.telephony.TelephonyManager;
-import android.util.ArraySet;
-
-import com.android.internal.org.bouncycastle.asn1.ASN1EncodableVector;
-import com.android.internal.org.bouncycastle.asn1.ASN1InputStream;
-import com.android.internal.org.bouncycastle.asn1.ASN1Integer;
-import com.android.internal.org.bouncycastle.asn1.ASN1ObjectIdentifier;
-import com.android.internal.org.bouncycastle.asn1.DERBitString;
-import com.android.internal.org.bouncycastle.asn1.DERNull;
-import com.android.internal.org.bouncycastle.asn1.DERSequence;
-import com.android.internal.org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
-import com.android.internal.org.bouncycastle.asn1.x509.AlgorithmIdentifier;
-import com.android.internal.org.bouncycastle.asn1.x509.Certificate;
-import com.android.internal.org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
-import com.android.internal.org.bouncycastle.asn1.x509.TBSCertificate;
-import com.android.internal.org.bouncycastle.asn1.x509.Time;
-import com.android.internal.org.bouncycastle.asn1.x509.V3TBSCertificateGenerator;
-import com.android.internal.org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
-import com.android.internal.org.bouncycastle.jce.X509Principal;
-import com.android.internal.org.bouncycastle.jce.provider.X509CertificateObject;
-import com.android.internal.org.bouncycastle.x509.X509V3CertificateGenerator;
-
-import libcore.util.EmptyArray;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.math.BigInteger;
-import java.nio.charset.StandardCharsets;
-import java.security.InvalidAlgorithmParameterException;
-import java.security.KeyPair;
-import java.security.KeyPairGenerator;
-import java.security.KeyPairGeneratorSpi;
-import java.security.PrivateKey;
-import java.security.ProviderException;
-import java.security.PublicKey;
-import java.security.SecureRandom;
-import java.security.UnrecoverableKeyException;
-import java.security.cert.CertificateEncodingException;
-import java.security.cert.CertificateParsingException;
-import java.security.cert.X509Certificate;
-import java.security.spec.AlgorithmParameterSpec;
-import java.security.spec.ECGenParameterSpec;
-import java.security.spec.RSAKeyGenParameterSpec;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * Provides a way to create instances of a KeyPair which will be placed in the
- * Android keystore service usable only by the application that called it. This
- * can be used in conjunction with
- * {@link java.security.KeyStore#getInstance(String)} using the
- * {@code "AndroidKeyStore"} type.
- * <p>
- * This class can not be directly instantiated and must instead be used via the
- * {@link KeyPairGenerator#getInstance(String)
- * KeyPairGenerator.getInstance("AndroidKeyStore")} API.
- *
- * @hide
- */
-public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGeneratorSpi {
-
-    public static class RSA extends AndroidKeyStoreKeyPairGeneratorSpi {
-        public RSA() {
-            super(KeymasterDefs.KM_ALGORITHM_RSA);
-        }
-    }
-
-    public static class EC extends AndroidKeyStoreKeyPairGeneratorSpi {
-        public EC() {
-            super(KeymasterDefs.KM_ALGORITHM_EC);
-        }
-    }
-
-    /*
-     * These must be kept in sync with system/security/keystore/defaults.h
-     */
-
-    /* EC */
-    private static final int EC_DEFAULT_KEY_SIZE = 256;
-
-    /* RSA */
-    private static final int RSA_DEFAULT_KEY_SIZE = 2048;
-    private static final int RSA_MIN_KEY_SIZE = 512;
-    private static final int RSA_MAX_KEY_SIZE = 8192;
-
-    private static final Map<String, Integer> SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE =
-            new HashMap<String, Integer>();
-    private static final List<String> SUPPORTED_EC_NIST_CURVE_NAMES = new ArrayList<String>();
-    private static final List<Integer> SUPPORTED_EC_NIST_CURVE_SIZES = new ArrayList<Integer>();
-    static {
-        // Aliases for NIST P-224
-        SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("p-224", 224);
-        SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("secp224r1", 224);
-
-
-        // Aliases for NIST P-256
-        SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("p-256", 256);
-        SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("secp256r1", 256);
-        SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("prime256v1", 256);
-
-        // Aliases for NIST P-384
-        SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("p-384", 384);
-        SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("secp384r1", 384);
-
-        // Aliases for NIST P-521
-        SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("p-521", 521);
-        SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("secp521r1", 521);
-
-        SUPPORTED_EC_NIST_CURVE_NAMES.addAll(SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.keySet());
-        Collections.sort(SUPPORTED_EC_NIST_CURVE_NAMES);
-
-        SUPPORTED_EC_NIST_CURVE_SIZES.addAll(
-                new HashSet<Integer>(SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.values()));
-        Collections.sort(SUPPORTED_EC_NIST_CURVE_SIZES);
-    }
-
-    private final int mOriginalKeymasterAlgorithm;
-
-    private KeyStore mKeyStore;
-
-    private KeyGenParameterSpec mSpec;
-
-    private String mEntryAlias;
-    private int mEntryUid;
-    private boolean mEncryptionAtRestRequired;
-    private @KeyProperties.KeyAlgorithmEnum String mJcaKeyAlgorithm;
-    private int mKeymasterAlgorithm = -1;
-    private int mKeySizeBits;
-    private SecureRandom mRng;
-
-    private int[] mKeymasterPurposes;
-    private int[] mKeymasterBlockModes;
-    private int[] mKeymasterEncryptionPaddings;
-    private int[] mKeymasterSignaturePaddings;
-    private int[] mKeymasterDigests;
-
-    private BigInteger mRSAPublicExponent;
-
-    protected AndroidKeyStoreKeyPairGeneratorSpi(int keymasterAlgorithm) {
-        mOriginalKeymasterAlgorithm = keymasterAlgorithm;
-    }
-
-    @SuppressWarnings("deprecation")
-    @Override
-    public void initialize(int keysize, SecureRandom random) {
-        throw new IllegalArgumentException(
-                KeyGenParameterSpec.class.getName() + " or " + KeyPairGeneratorSpec.class.getName()
-                + " required to initialize this KeyPairGenerator");
-    }
-
-    @SuppressWarnings("deprecation")
-    @Override
-    public void initialize(AlgorithmParameterSpec params, SecureRandom random)
-            throws InvalidAlgorithmParameterException {
-        resetAll();
-
-        boolean success = false;
-        try {
-            if (params == null) {
-                throw new InvalidAlgorithmParameterException(
-                        "Must supply params of type " + KeyGenParameterSpec.class.getName()
-                        + " or " + KeyPairGeneratorSpec.class.getName());
-            }
-
-            KeyGenParameterSpec spec;
-            boolean encryptionAtRestRequired = false;
-            int keymasterAlgorithm = mOriginalKeymasterAlgorithm;
-            if (params instanceof KeyGenParameterSpec) {
-                spec = (KeyGenParameterSpec) params;
-            } else if (params instanceof KeyPairGeneratorSpec) {
-                // Legacy/deprecated spec
-                KeyPairGeneratorSpec legacySpec = (KeyPairGeneratorSpec) params;
-                try {
-                    KeyGenParameterSpec.Builder specBuilder;
-                    String specKeyAlgorithm = legacySpec.getKeyType();
-                    if (specKeyAlgorithm != null) {
-                        // Spec overrides the generator's default key algorithm
-                        try {
-                            keymasterAlgorithm =
-                                    KeyProperties.KeyAlgorithm.toKeymasterAsymmetricKeyAlgorithm(
-                                            specKeyAlgorithm);
-                        } catch (IllegalArgumentException e) {
-                            throw new InvalidAlgorithmParameterException(
-                                    "Invalid key type in parameters", e);
-                        }
-                    }
-                    switch (keymasterAlgorithm) {
-                        case KeymasterDefs.KM_ALGORITHM_EC:
-                            specBuilder = new KeyGenParameterSpec.Builder(
-                                    legacySpec.getKeystoreAlias(),
-                                    KeyProperties.PURPOSE_SIGN
-                                    | KeyProperties.PURPOSE_VERIFY);
-                            // Authorized to be used with any digest (including no digest).
-                            // MD5 was never offered for Android Keystore for ECDSA.
-                            specBuilder.setDigests(
-                                    KeyProperties.DIGEST_NONE,
-                                    KeyProperties.DIGEST_SHA1,
-                                    KeyProperties.DIGEST_SHA224,
-                                    KeyProperties.DIGEST_SHA256,
-                                    KeyProperties.DIGEST_SHA384,
-                                    KeyProperties.DIGEST_SHA512);
-                            break;
-                        case KeymasterDefs.KM_ALGORITHM_RSA:
-                            specBuilder = new KeyGenParameterSpec.Builder(
-                                    legacySpec.getKeystoreAlias(),
-                                    KeyProperties.PURPOSE_ENCRYPT
-                                    | KeyProperties.PURPOSE_DECRYPT
-                                    | KeyProperties.PURPOSE_SIGN
-                                    | KeyProperties.PURPOSE_VERIFY);
-                            // Authorized to be used with any digest (including no digest).
-                            specBuilder.setDigests(
-                                    KeyProperties.DIGEST_NONE,
-                                    KeyProperties.DIGEST_MD5,
-                                    KeyProperties.DIGEST_SHA1,
-                                    KeyProperties.DIGEST_SHA224,
-                                    KeyProperties.DIGEST_SHA256,
-                                    KeyProperties.DIGEST_SHA384,
-                                    KeyProperties.DIGEST_SHA512);
-                            // Authorized to be used with any encryption and signature padding
-                            // schemes (including no padding).
-                            specBuilder.setEncryptionPaddings(
-                                    KeyProperties.ENCRYPTION_PADDING_NONE,
-                                    KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1,
-                                    KeyProperties.ENCRYPTION_PADDING_RSA_OAEP);
-                            specBuilder.setSignaturePaddings(
-                                    KeyProperties.SIGNATURE_PADDING_RSA_PKCS1,
-                                    KeyProperties.SIGNATURE_PADDING_RSA_PSS);
-                            // Disable randomized encryption requirement to support encryption
-                            // padding NONE above.
-                            specBuilder.setRandomizedEncryptionRequired(false);
-                            break;
-                        default:
-                            throw new ProviderException(
-                                    "Unsupported algorithm: " + mKeymasterAlgorithm);
-                    }
-
-                    if (legacySpec.getKeySize() != -1) {
-                        specBuilder.setKeySize(legacySpec.getKeySize());
-                    }
-                    if (legacySpec.getAlgorithmParameterSpec() != null) {
-                        specBuilder.setAlgorithmParameterSpec(
-                                legacySpec.getAlgorithmParameterSpec());
-                    }
-                    specBuilder.setCertificateSubject(legacySpec.getSubjectDN());
-                    specBuilder.setCertificateSerialNumber(legacySpec.getSerialNumber());
-                    specBuilder.setCertificateNotBefore(legacySpec.getStartDate());
-                    specBuilder.setCertificateNotAfter(legacySpec.getEndDate());
-                    encryptionAtRestRequired = legacySpec.isEncryptionRequired();
-                    specBuilder.setUserAuthenticationRequired(false);
-
-                    spec = specBuilder.build();
-                } catch (NullPointerException | IllegalArgumentException e) {
-                    throw new InvalidAlgorithmParameterException(e);
-                }
-            } else {
-                throw new InvalidAlgorithmParameterException(
-                        "Unsupported params class: " + params.getClass().getName()
-                        + ". Supported: " + KeyGenParameterSpec.class.getName()
-                        + ", " + KeyPairGeneratorSpec.class.getName());
-            }
-
-            mEntryAlias = spec.getKeystoreAlias();
-            mEntryUid = spec.getUid();
-            mSpec = spec;
-            mKeymasterAlgorithm = keymasterAlgorithm;
-            mEncryptionAtRestRequired = encryptionAtRestRequired;
-            mKeySizeBits = spec.getKeySize();
-            initAlgorithmSpecificParameters();
-            if (mKeySizeBits == -1) {
-                mKeySizeBits = getDefaultKeySize(keymasterAlgorithm);
-            }
-            checkValidKeySize(keymasterAlgorithm, mKeySizeBits, mSpec.isStrongBoxBacked());
-
-            if (spec.getKeystoreAlias() == null) {
-                throw new InvalidAlgorithmParameterException("KeyStore entry alias not provided");
-            }
-
-            String jcaKeyAlgorithm;
-            try {
-                jcaKeyAlgorithm = KeyProperties.KeyAlgorithm.fromKeymasterAsymmetricKeyAlgorithm(
-                        keymasterAlgorithm);
-                mKeymasterPurposes = KeyProperties.Purpose.allToKeymaster(spec.getPurposes());
-                mKeymasterBlockModes = KeyProperties.BlockMode.allToKeymaster(spec.getBlockModes());
-                mKeymasterEncryptionPaddings = KeyProperties.EncryptionPadding.allToKeymaster(
-                        spec.getEncryptionPaddings());
-                if (((spec.getPurposes() & KeyProperties.PURPOSE_ENCRYPT) != 0)
-                        && (spec.isRandomizedEncryptionRequired())) {
-                    for (int keymasterPadding : mKeymasterEncryptionPaddings) {
-                        if (!KeymasterUtils
-                                .isKeymasterPaddingSchemeIndCpaCompatibleWithAsymmetricCrypto(
-                                        keymasterPadding)) {
-                            throw new InvalidAlgorithmParameterException(
-                                    "Randomized encryption (IND-CPA) required but may be violated"
-                                    + " by padding scheme: "
-                                    + KeyProperties.EncryptionPadding.fromKeymaster(
-                                            keymasterPadding)
-                                    + ". See " + KeyGenParameterSpec.class.getName()
-                                    + " documentation.");
-                        }
-                    }
-                }
-                mKeymasterSignaturePaddings = KeyProperties.SignaturePadding.allToKeymaster(
-                        spec.getSignaturePaddings());
-                if (spec.isDigestsSpecified()) {
-                    mKeymasterDigests = KeyProperties.Digest.allToKeymaster(spec.getDigests());
-                } else {
-                    mKeymasterDigests = EmptyArray.INT;
-                }
-
-                // Check that user authentication related parameters are acceptable. This method
-                // will throw an IllegalStateException if there are issues (e.g., secure lock screen
-                // not set up).
-                KeymasterUtils.addUserAuthArgs(new KeymasterArguments(), mSpec);
-            } catch (IllegalArgumentException | IllegalStateException e) {
-                throw new InvalidAlgorithmParameterException(e);
-            }
-
-            mJcaKeyAlgorithm = jcaKeyAlgorithm;
-            mRng = random;
-            mKeyStore = KeyStore.getInstance();
-            success = true;
-        } finally {
-            if (!success) {
-                resetAll();
-            }
-        }
-    }
-
-    private void resetAll() {
-        mEntryAlias = null;
-        mEntryUid = KeyStore.UID_SELF;
-        mJcaKeyAlgorithm = null;
-        mKeymasterAlgorithm = -1;
-        mKeymasterPurposes = null;
-        mKeymasterBlockModes = null;
-        mKeymasterEncryptionPaddings = null;
-        mKeymasterSignaturePaddings = null;
-        mKeymasterDigests = null;
-        mKeySizeBits = 0;
-        mSpec = null;
-        mRSAPublicExponent = null;
-        mEncryptionAtRestRequired = false;
-        mRng = null;
-        mKeyStore = null;
-    }
-
-    private void initAlgorithmSpecificParameters() throws InvalidAlgorithmParameterException {
-        AlgorithmParameterSpec algSpecificSpec = mSpec.getAlgorithmParameterSpec();
-        switch (mKeymasterAlgorithm) {
-            case KeymasterDefs.KM_ALGORITHM_RSA:
-            {
-                BigInteger publicExponent = null;
-                if (algSpecificSpec instanceof RSAKeyGenParameterSpec) {
-                    RSAKeyGenParameterSpec rsaSpec = (RSAKeyGenParameterSpec) algSpecificSpec;
-                    if (mKeySizeBits == -1) {
-                        mKeySizeBits = rsaSpec.getKeysize();
-                    } else if (mKeySizeBits != rsaSpec.getKeysize()) {
-                        throw new InvalidAlgorithmParameterException("RSA key size must match "
-                                + " between " + mSpec + " and " + algSpecificSpec
-                                + ": " + mKeySizeBits + " vs " + rsaSpec.getKeysize());
-                    }
-                    publicExponent = rsaSpec.getPublicExponent();
-                } else if (algSpecificSpec != null) {
-                    throw new InvalidAlgorithmParameterException(
-                        "RSA may only use RSAKeyGenParameterSpec");
-                }
-                if (publicExponent == null) {
-                    publicExponent = RSAKeyGenParameterSpec.F4;
-                }
-                if (publicExponent.compareTo(BigInteger.ZERO) < 1) {
-                    throw new InvalidAlgorithmParameterException(
-                            "RSA public exponent must be positive: " + publicExponent);
-                }
-                if (publicExponent.compareTo(KeymasterArguments.UINT64_MAX_VALUE) > 0) {
-                    throw new InvalidAlgorithmParameterException(
-                            "Unsupported RSA public exponent: " + publicExponent
-                            + ". Maximum supported value: " + KeymasterArguments.UINT64_MAX_VALUE);
-                }
-                mRSAPublicExponent = publicExponent;
-                break;
-            }
-            case KeymasterDefs.KM_ALGORITHM_EC:
-                if (algSpecificSpec instanceof ECGenParameterSpec) {
-                    ECGenParameterSpec ecSpec = (ECGenParameterSpec) algSpecificSpec;
-                    String curveName = ecSpec.getName();
-                    Integer ecSpecKeySizeBits = SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.get(
-                            curveName.toLowerCase(Locale.US));
-                    if (ecSpecKeySizeBits == null) {
-                        throw new InvalidAlgorithmParameterException(
-                                "Unsupported EC curve name: " + curveName
-                                + ". Supported: " + SUPPORTED_EC_NIST_CURVE_NAMES);
-                    }
-                    if (mKeySizeBits == -1) {
-                        mKeySizeBits = ecSpecKeySizeBits;
-                    } else if (mKeySizeBits != ecSpecKeySizeBits) {
-                        throw new InvalidAlgorithmParameterException("EC key size must match "
-                                + " between " + mSpec + " and " + algSpecificSpec
-                                + ": " + mKeySizeBits + " vs " + ecSpecKeySizeBits);
-                    }
-                } else if (algSpecificSpec != null) {
-                    throw new InvalidAlgorithmParameterException(
-                        "EC may only use ECGenParameterSpec");
-                }
-                break;
-            default:
-                throw new ProviderException("Unsupported algorithm: " + mKeymasterAlgorithm);
-        }
-    }
-
-    @Override
-    public KeyPair generateKeyPair() {
-        if (mKeyStore == null || mSpec == null) {
-            throw new IllegalStateException("Not initialized");
-        }
-
-        int flags = (mEncryptionAtRestRequired) ? KeyStore.FLAG_ENCRYPTED : 0;
-        if (((flags & KeyStore.FLAG_ENCRYPTED) != 0)
-                && (mKeyStore.state() != KeyStore.State.UNLOCKED)) {
-            throw new IllegalStateException(
-                    "Encryption at rest using secure lock screen credential requested for key pair"
-                    + ", but the user has not yet entered the credential");
-        }
-
-        if (mSpec.isStrongBoxBacked()) {
-            flags |= KeyStore.FLAG_STRONGBOX;
-        }
-        if (mSpec.isCriticalToDeviceEncryption()) {
-            flags |= KeyStore.FLAG_CRITICAL_TO_DEVICE_ENCRYPTION;
-        }
-
-        byte[] additionalEntropy =
-                KeyStoreCryptoOperationUtils.getRandomBytesToMixIntoKeystoreRng(
-                        mRng, (mKeySizeBits + 7) / 8);
-
-        Credentials.deleteAllTypesForAlias(mKeyStore, mEntryAlias, mEntryUid);
-        final String privateKeyAlias = Credentials.USER_PRIVATE_KEY + mEntryAlias;
-        boolean success = false;
-        try {
-            generateKeystoreKeyPair(
-                    privateKeyAlias, constructKeyGenerationArguments(), additionalEntropy, flags);
-            KeyPair keyPair = loadKeystoreKeyPair(privateKeyAlias);
-
-            storeCertificateChain(flags, createCertificateChain(privateKeyAlias, keyPair));
-
-            success = true;
-            return keyPair;
-        } catch (ProviderException | IllegalArgumentException | DeviceIdAttestationException e) {
-          if ((mSpec.getPurposes() & KeyProperties.PURPOSE_WRAP_KEY) != 0) {
-              throw new SecureKeyImportUnavailableException(e);
-          } else {
-                throw new ProviderException(e);
-          }
-        } finally {
-            if (!success) {
-                Credentials.deleteAllTypesForAlias(mKeyStore, mEntryAlias, mEntryUid);
-            }
-        }
-    }
-
-    private Iterable<byte[]> createCertificateChain(final String privateKeyAlias, KeyPair keyPair)
-            throws ProviderException, DeviceIdAttestationException {
-        byte[] challenge = mSpec.getAttestationChallenge();
-        if (challenge != null) {
-            KeymasterArguments args = new KeymasterArguments();
-            args.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_CHALLENGE, challenge);
-
-            if (mSpec.isDevicePropertiesAttestationIncluded()) {
-                args.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_ID_BRAND,
-                        Build.BRAND.getBytes(StandardCharsets.UTF_8));
-                args.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_ID_DEVICE,
-                        Build.DEVICE.getBytes(StandardCharsets.UTF_8));
-                args.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_ID_PRODUCT,
-                        Build.PRODUCT.getBytes(StandardCharsets.UTF_8));
-                args.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_ID_MANUFACTURER,
-                        Build.MANUFACTURER.getBytes(StandardCharsets.UTF_8));
-                args.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_ID_MODEL,
-                        Build.MODEL.getBytes(StandardCharsets.UTF_8));
-            }
-
-            int[] idTypes = mSpec.getAttestationIds();
-            if (idTypes != null) {
-                final Set<Integer> idTypesSet = new ArraySet<>(idTypes.length);
-                for (int idType : idTypes) {
-                    idTypesSet.add(idType);
-                }
-                TelephonyManager telephonyService = null;
-                if (idTypesSet.contains(AttestationUtils.ID_TYPE_IMEI)
-                        || idTypesSet.contains(AttestationUtils.ID_TYPE_MEID)) {
-                    telephonyService =
-                            (TelephonyManager) KeyStore.getApplicationContext().getSystemService(
-                                    Context.TELEPHONY_SERVICE);
-                    if (telephonyService == null) {
-                        throw new DeviceIdAttestationException(
-                                "Unable to access telephony service");
-                    }
-                }
-                for (final Integer idType : idTypesSet) {
-                    switch (idType) {
-                        case AttestationUtils.ID_TYPE_SERIAL:
-                            args.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_ID_SERIAL,
-                                    Build.getSerial().getBytes(StandardCharsets.UTF_8)
-                            );
-                            break;
-                        case AttestationUtils.ID_TYPE_IMEI: {
-                            final String imei = telephonyService.getImei(0);
-                            if (imei == null) {
-                                throw new DeviceIdAttestationException("Unable to retrieve IMEI");
-                            }
-                            args.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_ID_IMEI,
-                                    imei.getBytes(StandardCharsets.UTF_8)
-                            );
-                            break;
-                        }
-                        case AttestationUtils.ID_TYPE_MEID: {
-                            final String meid = telephonyService.getMeid(0);
-                            if (meid == null) {
-                                throw new DeviceIdAttestationException("Unable to retrieve MEID");
-                            }
-                            args.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_ID_MEID,
-                                    meid.getBytes(StandardCharsets.UTF_8)
-                            );
-                            break;
-                        }
-                        case AttestationUtils.USE_INDIVIDUAL_ATTESTATION: {
-                            args.addBoolean(KeymasterDefs.KM_TAG_DEVICE_UNIQUE_ATTESTATION);
-                            break;
-                        }
-                        default:
-                            throw new IllegalArgumentException("Unknown device ID type " + idType);
-                    }
-                }
-            }
-
-            return getAttestationChain(privateKeyAlias, keyPair, args);
-        }
-
-        // Very short certificate chain in the non-attestation case.
-        return Collections.singleton(generateSelfSignedCertificateBytes(keyPair));
-    }
-
-    private void generateKeystoreKeyPair(final String privateKeyAlias, KeymasterArguments args,
-            byte[] additionalEntropy, final int flags) throws ProviderException {
-        KeyCharacteristics resultingKeyCharacteristics = new KeyCharacteristics();
-        int errorCode = mKeyStore.generateKey(privateKeyAlias, args, additionalEntropy,
-                mEntryUid, flags, resultingKeyCharacteristics);
-        if (errorCode != KeyStore.NO_ERROR) {
-            if (errorCode == KeyStore.HARDWARE_TYPE_UNAVAILABLE) {
-                throw new StrongBoxUnavailableException("Failed to generate key pair");
-            } else {
-                throw new ProviderException(
-                        "Failed to generate key pair", KeyStore.getKeyStoreException(errorCode));
-            }
-        }
-    }
-
-    private KeyPair loadKeystoreKeyPair(final String privateKeyAlias) throws ProviderException {
-        try {
-            KeyPair result  = AndroidKeyStoreProvider.loadAndroidKeyStoreKeyPairFromKeystore(
-                    mKeyStore, privateKeyAlias, mEntryUid);
-            if (!mJcaKeyAlgorithm.equalsIgnoreCase(result.getPrivate().getAlgorithm())) {
-                throw new ProviderException(
-                        "Generated key pair algorithm does not match requested algorithm: "
-                                + result.getPrivate().getAlgorithm() + " vs " + mJcaKeyAlgorithm);
-            }
-            return result;
-        } catch (UnrecoverableKeyException | KeyPermanentlyInvalidatedException e) {
-            throw new ProviderException("Failed to load generated key pair from keystore", e);
-        }
-    }
-
-    private KeymasterArguments constructKeyGenerationArguments()
-            throws IllegalArgumentException, DeviceIdAttestationException {
-        KeymasterArguments args = new KeymasterArguments();
-        args.addUnsignedInt(KeymasterDefs.KM_TAG_KEY_SIZE, mKeySizeBits);
-        args.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, mKeymasterAlgorithm);
-        args.addEnums(KeymasterDefs.KM_TAG_PURPOSE, mKeymasterPurposes);
-        args.addEnums(KeymasterDefs.KM_TAG_BLOCK_MODE, mKeymasterBlockModes);
-        args.addEnums(KeymasterDefs.KM_TAG_PADDING, mKeymasterEncryptionPaddings);
-        args.addEnums(KeymasterDefs.KM_TAG_PADDING, mKeymasterSignaturePaddings);
-        args.addEnums(KeymasterDefs.KM_TAG_DIGEST, mKeymasterDigests);
-
-        KeymasterUtils.addUserAuthArgs(args, mSpec);
-        args.addDateIfNotNull(KeymasterDefs.KM_TAG_ACTIVE_DATETIME, mSpec.getKeyValidityStart());
-        args.addDateIfNotNull(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME,
-                mSpec.getKeyValidityForOriginationEnd());
-        args.addDateIfNotNull(KeymasterDefs.KM_TAG_USAGE_EXPIRE_DATETIME,
-                mSpec.getKeyValidityForConsumptionEnd());
-        addAlgorithmSpecificParameters(args);
-
-        if (mSpec.isUniqueIdIncluded()) {
-            args.addBoolean(KeymasterDefs.KM_TAG_INCLUDE_UNIQUE_ID);
-        }
-        return args;
-    }
-
-    private void storeCertificateChain(final int flags, Iterable<byte[]> iterable)
-            throws ProviderException {
-        Iterator<byte[]> iter = iterable.iterator();
-        storeCertificate(
-                Credentials.USER_CERTIFICATE, iter.next(), flags, "Failed to store certificate");
-
-        if (!iter.hasNext()) {
-            return;
-        }
-
-        ByteArrayOutputStream certificateConcatenationStream = new ByteArrayOutputStream();
-        while (iter.hasNext()) {
-            byte[] data = iter.next();
-            certificateConcatenationStream.write(data, 0, data.length);
-        }
-
-        storeCertificate(Credentials.CA_CERTIFICATE, certificateConcatenationStream.toByteArray(),
-                flags, "Failed to store attestation CA certificate");
-    }
-
-    private void storeCertificate(String prefix, byte[] certificateBytes, final int flags,
-            String failureMessage) throws ProviderException {
-        int insertErrorCode = mKeyStore.insert(
-                prefix + mEntryAlias,
-                certificateBytes,
-                mEntryUid,
-                flags);
-        if (insertErrorCode != KeyStore.NO_ERROR) {
-            throw new ProviderException(failureMessage,
-                    KeyStore.getKeyStoreException(insertErrorCode));
-        }
-    }
-
-    private byte[] generateSelfSignedCertificateBytes(KeyPair keyPair) throws ProviderException {
-        try {
-            return generateSelfSignedCertificate(keyPair.getPrivate(), keyPair.getPublic())
-                    .getEncoded();
-        } catch (IOException | CertificateParsingException e) {
-            throw new ProviderException("Failed to generate self-signed certificate", e);
-        } catch (CertificateEncodingException e) {
-            throw new ProviderException(
-                    "Failed to obtain encoded form of self-signed certificate", e);
-        }
-    }
-
-    private Iterable<byte[]> getAttestationChain(String privateKeyAlias,
-            KeyPair keyPair, KeymasterArguments args)
-                    throws ProviderException {
-        final KeymasterCertificateChain outChain = new KeymasterCertificateChain();
-        final int errorCode;
-        if (mSpec.isDevicePropertiesAttestationIncluded()
-                && mSpec.getAttestationChallenge() == null) {
-            throw new ProviderException("An attestation challenge must be provided when requesting "
-                    + "device properties attestation.");
-        }
-        errorCode = mKeyStore.attestKey(privateKeyAlias, args, outChain);
-        if (errorCode != KeyStore.NO_ERROR) {
-            throw new ProviderException("Failed to generate attestation certificate chain",
-                    KeyStore.getKeyStoreException(errorCode));
-        }
-        Collection<byte[]> chain = outChain.getCertificates();
-        if (chain.size() < 2) {
-            throw new ProviderException("Attestation certificate chain contained "
-                    + chain.size() + " entries. At least two are required.");
-        }
-        return chain;
-    }
-
-    private void addAlgorithmSpecificParameters(KeymasterArguments keymasterArgs) {
-        switch (mKeymasterAlgorithm) {
-            case KeymasterDefs.KM_ALGORITHM_RSA:
-                keymasterArgs.addUnsignedLong(
-                        KeymasterDefs.KM_TAG_RSA_PUBLIC_EXPONENT, mRSAPublicExponent);
-                break;
-            case KeymasterDefs.KM_ALGORITHM_EC:
-                break;
-            default:
-                throw new ProviderException("Unsupported algorithm: " + mKeymasterAlgorithm);
-        }
-    }
-
-    private X509Certificate generateSelfSignedCertificate(PrivateKey privateKey,
-            PublicKey publicKey) throws CertificateParsingException, IOException {
-        String signatureAlgorithm =
-                getCertificateSignatureAlgorithm(mKeymasterAlgorithm, mKeySizeBits, mSpec);
-        if (signatureAlgorithm == null) {
-            // Key cannot be used to sign a certificate
-            return generateSelfSignedCertificateWithFakeSignature(publicKey);
-        } else {
-            // Key can be used to sign a certificate
-            try {
-                return generateSelfSignedCertificateWithValidSignature(
-                        privateKey, publicKey, signatureAlgorithm);
-            } catch (Exception e) {
-                // Failed to generate the self-signed certificate with valid signature. Fall back
-                // to generating a self-signed certificate with a fake signature. This is done for
-                // all exception types because we prefer key pair generation to succeed and end up
-                // producing a self-signed certificate with an invalid signature to key pair
-                // generation failing.
-                return generateSelfSignedCertificateWithFakeSignature(publicKey);
-            }
-        }
-    }
-
-    @SuppressWarnings("deprecation")
-    private X509Certificate generateSelfSignedCertificateWithValidSignature(
-            PrivateKey privateKey, PublicKey publicKey, String signatureAlgorithm) throws Exception {
-        final X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();
-        certGen.setPublicKey(publicKey);
-        certGen.setSerialNumber(mSpec.getCertificateSerialNumber());
-        certGen.setSubjectDN(mSpec.getCertificateSubject());
-        certGen.setIssuerDN(mSpec.getCertificateSubject());
-        certGen.setNotBefore(mSpec.getCertificateNotBefore());
-        certGen.setNotAfter(mSpec.getCertificateNotAfter());
-        certGen.setSignatureAlgorithm(signatureAlgorithm);
-        return certGen.generate(privateKey);
-    }
-
-    @SuppressWarnings("deprecation")
-    private X509Certificate generateSelfSignedCertificateWithFakeSignature(
-            PublicKey publicKey) throws IOException, CertificateParsingException {
-        V3TBSCertificateGenerator tbsGenerator = new V3TBSCertificateGenerator();
-        ASN1ObjectIdentifier sigAlgOid;
-        AlgorithmIdentifier sigAlgId;
-        byte[] signature;
-        switch (mKeymasterAlgorithm) {
-            case KeymasterDefs.KM_ALGORITHM_EC:
-                sigAlgOid = X9ObjectIdentifiers.ecdsa_with_SHA256;
-                sigAlgId = new AlgorithmIdentifier(sigAlgOid);
-                ASN1EncodableVector v = new ASN1EncodableVector();
-                v.add(new ASN1Integer(BigInteger.valueOf(0)));
-                v.add(new ASN1Integer(BigInteger.valueOf(0)));
-                signature = new DERSequence().getEncoded();
-                break;
-            case KeymasterDefs.KM_ALGORITHM_RSA:
-                sigAlgOid = PKCSObjectIdentifiers.sha256WithRSAEncryption;
-                sigAlgId = new AlgorithmIdentifier(sigAlgOid, DERNull.INSTANCE);
-                signature = new byte[1];
-                break;
-            default:
-                throw new ProviderException("Unsupported key algorithm: " + mKeymasterAlgorithm);
-        }
-
-        try (ASN1InputStream publicKeyInfoIn = new ASN1InputStream(publicKey.getEncoded())) {
-            tbsGenerator.setSubjectPublicKeyInfo(
-                    SubjectPublicKeyInfo.getInstance(publicKeyInfoIn.readObject()));
-        }
-        tbsGenerator.setSerialNumber(new ASN1Integer(mSpec.getCertificateSerialNumber()));
-        X509Principal subject =
-                new X509Principal(mSpec.getCertificateSubject().getEncoded());
-        tbsGenerator.setSubject(subject);
-        tbsGenerator.setIssuer(subject);
-        tbsGenerator.setStartDate(new Time(mSpec.getCertificateNotBefore()));
-        tbsGenerator.setEndDate(new Time(mSpec.getCertificateNotAfter()));
-        tbsGenerator.setSignature(sigAlgId);
-        TBSCertificate tbsCertificate = tbsGenerator.generateTBSCertificate();
-
-        ASN1EncodableVector result = new ASN1EncodableVector();
-        result.add(tbsCertificate);
-        result.add(sigAlgId);
-        result.add(new DERBitString(signature));
-        return new X509CertificateObject(Certificate.getInstance(new DERSequence(result)));
-    }
-
-    private static int getDefaultKeySize(int keymasterAlgorithm) {
-        switch (keymasterAlgorithm) {
-            case KeymasterDefs.KM_ALGORITHM_EC:
-                return EC_DEFAULT_KEY_SIZE;
-            case KeymasterDefs.KM_ALGORITHM_RSA:
-                return RSA_DEFAULT_KEY_SIZE;
-            default:
-                throw new ProviderException("Unsupported algorithm: " + keymasterAlgorithm);
-        }
-    }
-
-    private static void checkValidKeySize(
-            int keymasterAlgorithm,
-            int keySize,
-            boolean isStrongBoxBacked)
-            throws InvalidAlgorithmParameterException {
-        switch (keymasterAlgorithm) {
-            case KeymasterDefs.KM_ALGORITHM_EC:
-                if (isStrongBoxBacked && keySize != 256) {
-                    throw new InvalidAlgorithmParameterException(
-                            "Unsupported StrongBox EC key size: "
-                            + keySize + " bits. Supported: 256");
-                }
-                if (!SUPPORTED_EC_NIST_CURVE_SIZES.contains(keySize)) {
-                    throw new InvalidAlgorithmParameterException("Unsupported EC key size: "
-                            + keySize + " bits. Supported: " + SUPPORTED_EC_NIST_CURVE_SIZES);
-                }
-                break;
-            case KeymasterDefs.KM_ALGORITHM_RSA:
-                if (keySize < RSA_MIN_KEY_SIZE || keySize > RSA_MAX_KEY_SIZE) {
-                    throw new InvalidAlgorithmParameterException("RSA key size must be >= "
-                            + RSA_MIN_KEY_SIZE + " and <= " + RSA_MAX_KEY_SIZE);
-                }
-                break;
-            default:
-                throw new ProviderException("Unsupported algorithm: " + keymasterAlgorithm);
-        }
-    }
-
-    /**
-     * Returns the {@code Signature} algorithm to be used for signing a certificate using the
-     * specified key or {@code null} if the key cannot be used for signing a certificate.
-     */
-    @Nullable
-    private static String getCertificateSignatureAlgorithm(
-            int keymasterAlgorithm,
-            int keySizeBits,
-            KeyGenParameterSpec spec) {
-        // Constraints:
-        // 1. Key must be authorized for signing without user authentication.
-        // 2. Signature digest must be one of key's authorized digests.
-        // 3. For RSA keys, the digest output size must not exceed modulus size minus space overhead
-        //    of RSA PKCS#1 signature padding scheme (about 30 bytes).
-        // 4. For EC keys, the there is no point in using a digest whose output size is longer than
-        //    key/field size because the digest will be truncated to that size.
-
-        if ((spec.getPurposes() & KeyProperties.PURPOSE_SIGN) == 0) {
-            // Key not authorized for signing
-            return null;
-        }
-        if (spec.isUserAuthenticationRequired()) {
-            // Key not authorized for use without user authentication
-            return null;
-        }
-        if (!spec.isDigestsSpecified()) {
-            // Key not authorized for any digests -- can't sign
-            return null;
-        }
-        switch (keymasterAlgorithm) {
-            case KeymasterDefs.KM_ALGORITHM_EC:
-            {
-                Set<Integer> availableKeymasterDigests = getAvailableKeymasterSignatureDigests(
-                        spec.getDigests(),
-                        AndroidKeyStoreBCWorkaroundProvider.getSupportedEcdsaSignatureDigests());
-
-                int bestKeymasterDigest = -1;
-                int bestDigestOutputSizeBits = -1;
-                for (int keymasterDigest : availableKeymasterDigests) {
-                    int outputSizeBits = KeymasterUtils.getDigestOutputSizeBits(keymasterDigest);
-                    if (outputSizeBits == keySizeBits) {
-                        // Perfect match -- use this digest
-                        bestKeymasterDigest = keymasterDigest;
-                        bestDigestOutputSizeBits = outputSizeBits;
-                        break;
-                    }
-                    // Not a perfect match -- check against the best digest so far
-                    if (bestKeymasterDigest == -1) {
-                        // First digest tested -- definitely the best so far
-                        bestKeymasterDigest = keymasterDigest;
-                        bestDigestOutputSizeBits = outputSizeBits;
-                    } else {
-                        // Prefer output size to be as close to key size as possible, with output
-                        // sizes larger than key size preferred to those smaller than key size.
-                        if (bestDigestOutputSizeBits < keySizeBits) {
-                            // Output size of the best digest so far is smaller than key size.
-                            // Anything larger is a win.
-                            if (outputSizeBits > bestDigestOutputSizeBits) {
-                                bestKeymasterDigest = keymasterDigest;
-                                bestDigestOutputSizeBits = outputSizeBits;
-                            }
-                        } else {
-                            // Output size of the best digest so far is larger than key size.
-                            // Anything smaller is a win, as long as it's not smaller than key size.
-                            if ((outputSizeBits < bestDigestOutputSizeBits)
-                                    && (outputSizeBits >= keySizeBits)) {
-                                bestKeymasterDigest = keymasterDigest;
-                                bestDigestOutputSizeBits = outputSizeBits;
-                            }
-                        }
-                    }
-                }
-                if (bestKeymasterDigest == -1) {
-                    return null;
-                }
-                return KeyProperties.Digest.fromKeymasterToSignatureAlgorithmDigest(
-                        bestKeymasterDigest) + "WithECDSA";
-            }
-            case KeymasterDefs.KM_ALGORITHM_RSA:
-            {
-                // Check whether this key is authorized for PKCS#1 signature padding.
-                // We use Bouncy Castle to generate self-signed RSA certificates. Bouncy Castle
-                // only supports RSA certificates signed using PKCS#1 padding scheme. The key needs
-                // to be authorized for PKCS#1 padding or padding NONE which means any padding.
-                boolean pkcs1SignaturePaddingSupported =
-                        com.android.internal.util.ArrayUtils.contains(
-                                KeyProperties.SignaturePadding.allToKeymaster(
-                                        spec.getSignaturePaddings()),
-                                KeymasterDefs.KM_PAD_RSA_PKCS1_1_5_SIGN);
-                if (!pkcs1SignaturePaddingSupported) {
-                    // Key not authorized for PKCS#1 signature padding -- can't sign
-                    return null;
-                }
-
-                Set<Integer> availableKeymasterDigests = getAvailableKeymasterSignatureDigests(
-                        spec.getDigests(),
-                        AndroidKeyStoreBCWorkaroundProvider.getSupportedEcdsaSignatureDigests());
-
-                // The amount of space available for the digest is less than modulus size by about
-                // 30 bytes because padding must be at least 11 bytes long (00 || 01 || PS || 00,
-                // where PS must be at least 8 bytes long), and then there's also the 15--19 bytes
-                // overhead (depending the on chosen digest) for encoding digest OID and digest
-                // value in DER.
-                int maxDigestOutputSizeBits = keySizeBits - 30 * 8;
-                int bestKeymasterDigest = -1;
-                int bestDigestOutputSizeBits = -1;
-                for (int keymasterDigest : availableKeymasterDigests) {
-                    int outputSizeBits = KeymasterUtils.getDigestOutputSizeBits(keymasterDigest);
-                    if (outputSizeBits > maxDigestOutputSizeBits) {
-                        // Digest too long (signature generation will fail) -- skip
-                        continue;
-                    }
-                    if (bestKeymasterDigest == -1) {
-                        // First digest tested -- definitely the best so far
-                        bestKeymasterDigest = keymasterDigest;
-                        bestDigestOutputSizeBits = outputSizeBits;
-                    } else {
-                        // The longer the better
-                        if (outputSizeBits > bestDigestOutputSizeBits) {
-                            bestKeymasterDigest = keymasterDigest;
-                            bestDigestOutputSizeBits = outputSizeBits;
-                        }
-                    }
-                }
-                if (bestKeymasterDigest == -1) {
-                    return null;
-                }
-                return KeyProperties.Digest.fromKeymasterToSignatureAlgorithmDigest(
-                        bestKeymasterDigest) + "WithRSA";
-            }
-            default:
-                throw new ProviderException("Unsupported algorithm: " + keymasterAlgorithm);
-        }
-    }
-
-    private static Set<Integer> getAvailableKeymasterSignatureDigests(
-            @KeyProperties.DigestEnum String[] authorizedKeyDigests,
-            @KeyProperties.DigestEnum String[] supportedSignatureDigests) {
-        Set<Integer> authorizedKeymasterKeyDigests = new HashSet<Integer>();
-        for (int keymasterDigest : KeyProperties.Digest.allToKeymaster(authorizedKeyDigests)) {
-            authorizedKeymasterKeyDigests.add(keymasterDigest);
-        }
-        Set<Integer> supportedKeymasterSignatureDigests = new HashSet<Integer>();
-        for (int keymasterDigest
-                : KeyProperties.Digest.allToKeymaster(supportedSignatureDigests)) {
-            supportedKeymasterSignatureDigests.add(keymasterDigest);
-        }
-        Set<Integer> result = new HashSet<Integer>(supportedKeymasterSignatureDigests);
-        result.retainAll(authorizedKeymasterKeyDigests);
-        return result;
-    }
-}
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreLoadStoreParameter.java b/keystore/java/android/security/keystore/AndroidKeyStoreLoadStoreParameter.java
deleted file mode 100644
index 45d579e..0000000
--- a/keystore/java/android/security/keystore/AndroidKeyStoreLoadStoreParameter.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.security.keystore;
-
-import java.security.KeyStore;
-import java.security.KeyStore.ProtectionParameter;
-
-class AndroidKeyStoreLoadStoreParameter implements KeyStore.LoadStoreParameter {
-
-    private final int mUid;
-
-    AndroidKeyStoreLoadStoreParameter(int uid) {
-        mUid = uid;
-    }
-
-    @Override
-    public ProtectionParameter getProtectionParameter() {
-        return null;
-    }
-
-    int getUid() {
-        return mUid;
-    }
-}
diff --git a/keystore/java/android/security/keystore/AndroidKeyStorePrivateKey.java b/keystore/java/android/security/keystore/AndroidKeyStorePrivateKey.java
deleted file mode 100644
index 06e4c88..0000000
--- a/keystore/java/android/security/keystore/AndroidKeyStorePrivateKey.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.security.keystore;
-
-import java.security.PrivateKey;
-
-/**
- * {@link PrivateKey} backed by Android Keystore.
- *
- * @hide
- */
-public class AndroidKeyStorePrivateKey extends AndroidKeyStoreKey implements PrivateKey {
-
-    public AndroidKeyStorePrivateKey(String alias, int uid, String algorithm) {
-        super(alias, uid, algorithm);
-    }
-}
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreProvider.java b/keystore/java/android/security/keystore/AndroidKeyStoreProvider.java
index 0871517..ecb082e 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreProvider.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreProvider.java
@@ -20,30 +20,13 @@
 import android.annotation.SystemApi;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.security.KeyStore;
-import android.security.keymaster.ExportResult;
-import android.security.keymaster.KeyCharacteristics;
-import android.security.keymaster.KeymasterDefs;
 
 import java.io.IOException;
-import java.security.KeyFactory;
-import java.security.KeyPair;
 import java.security.KeyStoreException;
 import java.security.NoSuchAlgorithmException;
 import java.security.NoSuchProviderException;
 import java.security.Provider;
-import java.security.ProviderException;
-import java.security.PublicKey;
-import java.security.Security;
-import java.security.Signature;
-import java.security.UnrecoverableKeyException;
 import java.security.cert.CertificateException;
-import java.security.interfaces.ECKey;
-import java.security.interfaces.ECPublicKey;
-import java.security.interfaces.RSAKey;
-import java.security.interfaces.RSAPublicKey;
-import java.security.spec.InvalidKeySpecException;
-import java.security.spec.X509EncodedKeySpec;
-import java.util.List;
 
 import javax.crypto.Cipher;
 import javax.crypto.Mac;
@@ -57,117 +40,10 @@
 public class AndroidKeyStoreProvider extends Provider {
     private static final String PROVIDER_NAME = "AndroidKeyStore";
 
-    // IMPLEMENTATION NOTE: Class names are hard-coded in this provider to avoid loading these
-    // classes when this provider is instantiated and installed early on during each app's
-    // initialization process.
-    //
-    // Crypto operations operating on the AndroidKeyStore keys must not be offered by this provider.
-    // Instead, they need to be offered by AndroidKeyStoreBCWorkaroundProvider. See its Javadoc
-    // for details.
-
-    private static final String PACKAGE_NAME = "android.security.keystore";
-
-    private static final String DESEDE_SYSTEM_PROPERTY =
-            "ro.hardware.keystore_desede";
-
     /** @hide */
-    public AndroidKeyStoreProvider() {
-        this(PROVIDER_NAME);
-    }
-
-    /** @hide **/
-    public AndroidKeyStoreProvider(String providerName) {
-        super(providerName, 1.0, "Android KeyStore security provider");
-
-        boolean supports3DES = "true".equals(android.os.SystemProperties.get(DESEDE_SYSTEM_PROPERTY));
-
-        // java.security.KeyStore
-        put("KeyStore." + providerName, PACKAGE_NAME + ".AndroidKeyStoreSpi");
-
-        // java.security.KeyPairGenerator
-        put("KeyPairGenerator.EC", PACKAGE_NAME + ".AndroidKeyStoreKeyPairGeneratorSpi$EC");
-        put("KeyPairGenerator.RSA", PACKAGE_NAME +  ".AndroidKeyStoreKeyPairGeneratorSpi$RSA");
-
-        // java.security.KeyFactory
-        putKeyFactoryImpl("EC");
-        putKeyFactoryImpl("RSA");
-
-        // javax.crypto.KeyGenerator
-        put("KeyGenerator.AES", PACKAGE_NAME + ".AndroidKeyStoreKeyGeneratorSpi$AES");
-        put("KeyGenerator.HmacSHA1", PACKAGE_NAME + ".AndroidKeyStoreKeyGeneratorSpi$HmacSHA1");
-        put("KeyGenerator.HmacSHA224", PACKAGE_NAME + ".AndroidKeyStoreKeyGeneratorSpi$HmacSHA224");
-        put("KeyGenerator.HmacSHA256", PACKAGE_NAME + ".AndroidKeyStoreKeyGeneratorSpi$HmacSHA256");
-        put("KeyGenerator.HmacSHA384", PACKAGE_NAME + ".AndroidKeyStoreKeyGeneratorSpi$HmacSHA384");
-        put("KeyGenerator.HmacSHA512", PACKAGE_NAME + ".AndroidKeyStoreKeyGeneratorSpi$HmacSHA512");
-
-        if (supports3DES) {
-            put("KeyGenerator.DESede", PACKAGE_NAME + ".AndroidKeyStoreKeyGeneratorSpi$DESede");
-        }
-
-        // java.security.SecretKeyFactory
-        putSecretKeyFactoryImpl("AES");
-        if (supports3DES) {
-            putSecretKeyFactoryImpl("DESede");
-        }
-        putSecretKeyFactoryImpl("HmacSHA1");
-        putSecretKeyFactoryImpl("HmacSHA224");
-        putSecretKeyFactoryImpl("HmacSHA256");
-        putSecretKeyFactoryImpl("HmacSHA384");
-        putSecretKeyFactoryImpl("HmacSHA512");
-    }
-
-    /**
-     * This function indicates whether or not Keystore 2.0 is enabled. Some parts of the
-     * Keystore SPI must behave subtly differently when Keystore 2.0 is enabled. However,
-     * the platform property that indicates that Keystore 2.0 is enabled is not readable
-     * by applications. So we set this value when {@code install()} is called because it
-     * is called by zygote, which can access Keystore2Properties.
-     *
-     * This function can be removed once the transition to Keystore 2.0 is complete.
-     * b/171305684
-     *
-     * @return true if Keystore 2.0 is enabled.
-     * @hide
-     */
-    public static boolean isKeystore2Enabled() {
-        return android.security.keystore2.AndroidKeyStoreProvider.isInstalled();
-    }
-
-    /**
-     * Installs a new instance of this provider (and the
-     * {@link AndroidKeyStoreBCWorkaroundProvider}).
-     * @hide
-     */
-    public static void install() {
-        Provider[] providers = Security.getProviders();
-        int bcProviderIndex = -1;
-        for (int i = 0; i < providers.length; i++) {
-            Provider provider = providers[i];
-            if ("BC".equals(provider.getName())) {
-                bcProviderIndex = i;
-                break;
-            }
-        }
-
-        Security.addProvider(new AndroidKeyStoreProvider());
-        Provider workaroundProvider = new AndroidKeyStoreBCWorkaroundProvider();
-        if (bcProviderIndex != -1) {
-            // Bouncy Castle provider found -- install the workaround provider above it.
-            // insertProviderAt uses 1-based positions.
-            Security.insertProviderAt(workaroundProvider, bcProviderIndex + 1);
-        } else {
-            // Bouncy Castle provider not found -- install the workaround provider at lowest
-            // priority.
-            Security.addProvider(workaroundProvider);
-        }
-    }
-
-    private void putSecretKeyFactoryImpl(String algorithm) {
-        put("SecretKeyFactory." + algorithm, PACKAGE_NAME + ".AndroidKeyStoreSecretKeyFactorySpi");
-    }
-
-    private void putKeyFactoryImpl(String algorithm) {
-        put("KeyFactory." + algorithm, PACKAGE_NAME + ".AndroidKeyStoreKeyFactorySpi");
+    public AndroidKeyStoreProvider(@NonNull String name) {
+        super(name, 1.0, "Android KeyStore security provider");
+        throw new IllegalStateException("Should not be instantiated.");
     }
 
     /**
@@ -189,229 +65,7 @@
         if (cryptoPrimitive == null) {
             throw new NullPointerException();
         }
-        Object spi;
-        if (cryptoPrimitive instanceof Signature) {
-            spi = ((Signature) cryptoPrimitive).getCurrentSpi();
-        } else if (cryptoPrimitive instanceof Mac) {
-            spi = ((Mac) cryptoPrimitive).getCurrentSpi();
-        } else if (cryptoPrimitive instanceof Cipher) {
-            spi = ((Cipher) cryptoPrimitive).getCurrentSpi();
-        } else {
-            throw new IllegalArgumentException("Unsupported crypto primitive: " + cryptoPrimitive
-                    + ". Supported: Signature, Mac, Cipher");
-        }
-        if (spi == null) {
-            throw new IllegalStateException("Crypto primitive not initialized");
-        } else if (!(spi instanceof KeyStoreCryptoOperation)) {
-            throw new IllegalArgumentException(
-                    "Crypto primitive not backed by AndroidKeyStore provider: " + cryptoPrimitive
-                    + ", spi: " + spi);
-        }
-        return ((KeyStoreCryptoOperation) spi).getOperationHandle();
-    }
-
-    /** @hide **/
-    @NonNull
-    public static AndroidKeyStorePublicKey getAndroidKeyStorePublicKey(
-            @NonNull String alias,
-            int uid,
-            @NonNull @KeyProperties.KeyAlgorithmEnum String keyAlgorithm,
-            @NonNull byte[] x509EncodedForm) {
-        PublicKey publicKey;
-        try {
-            KeyFactory keyFactory = KeyFactory.getInstance(keyAlgorithm);
-            publicKey = keyFactory.generatePublic(new X509EncodedKeySpec(x509EncodedForm));
-        } catch (NoSuchAlgorithmException e) {
-            throw new ProviderException(
-                    "Failed to obtain " + keyAlgorithm + " KeyFactory", e);
-        } catch (InvalidKeySpecException e) {
-            throw new ProviderException("Invalid X.509 encoding of public key", e);
-        }
-        if (KeyProperties.KEY_ALGORITHM_EC.equalsIgnoreCase(keyAlgorithm)) {
-            return new AndroidKeyStoreECPublicKey(alias, uid, (ECPublicKey) publicKey);
-        } else if (KeyProperties.KEY_ALGORITHM_RSA.equalsIgnoreCase(keyAlgorithm)) {
-            return new AndroidKeyStoreRSAPublicKey(alias, uid, (RSAPublicKey) publicKey);
-        } else {
-            throw new ProviderException("Unsupported Android Keystore public key algorithm: "
-                    + keyAlgorithm);
-        }
-    }
-
-    @NonNull
-    private static AndroidKeyStorePrivateKey getAndroidKeyStorePrivateKey(
-            @NonNull AndroidKeyStorePublicKey publicKey) {
-        String keyAlgorithm = publicKey.getAlgorithm();
-        if (KeyProperties.KEY_ALGORITHM_EC.equalsIgnoreCase(keyAlgorithm)) {
-            return new AndroidKeyStoreECPrivateKey(
-                    publicKey.getAlias(), publicKey.getUid(), ((ECKey) publicKey).getParams());
-        } else if (KeyProperties.KEY_ALGORITHM_RSA.equalsIgnoreCase(keyAlgorithm)) {
-            return new AndroidKeyStoreRSAPrivateKey(
-                    publicKey.getAlias(), publicKey.getUid(), ((RSAKey) publicKey).getModulus());
-        } else {
-            throw new ProviderException("Unsupported Android Keystore public key algorithm: "
-                    + keyAlgorithm);
-        }
-    }
-
-    @NonNull
-    private static KeyCharacteristics getKeyCharacteristics(@NonNull KeyStore keyStore,
-            @NonNull String alias, int uid)
-            throws UnrecoverableKeyException, KeyPermanentlyInvalidatedException {
-        KeyCharacteristics keyCharacteristics = new KeyCharacteristics();
-        int errorCode = keyStore.getKeyCharacteristics(
-                alias, null, null, uid, keyCharacteristics);
-        if (errorCode == KeyStore.KEY_PERMANENTLY_INVALIDATED) {
-            throw (KeyPermanentlyInvalidatedException)
-                new KeyPermanentlyInvalidatedException(
-                            "User changed or deleted their auth credentials",
-                            KeyStore.getKeyStoreException(errorCode));
-        }
-        if (errorCode != KeyStore.NO_ERROR) {
-            throw (UnrecoverableKeyException)
-                    new UnrecoverableKeyException("Failed to obtain information about key")
-                            .initCause(KeyStore.getKeyStoreException(errorCode));
-        }
-        return keyCharacteristics;
-    }
-
-    @NonNull
-    private static AndroidKeyStorePublicKey loadAndroidKeyStorePublicKeyFromKeystore(
-            @NonNull KeyStore keyStore, @NonNull String privateKeyAlias, int uid,
-            KeyCharacteristics keyCharacteristics)
-            throws UnrecoverableKeyException {
-        ExportResult exportResult = keyStore.exportKey(
-                privateKeyAlias, KeymasterDefs.KM_KEY_FORMAT_X509, null, null, uid);
-        if (exportResult.resultCode != KeyStore.NO_ERROR) {
-            throw (UnrecoverableKeyException)
-                    new UnrecoverableKeyException("Failed to obtain X.509 form of public key")
-                    .initCause(KeyStore.getKeyStoreException(exportResult.resultCode));
-        }
-        final byte[] x509EncodedPublicKey = exportResult.exportData;
-
-        Integer keymasterAlgorithm = keyCharacteristics.getEnum(KeymasterDefs.KM_TAG_ALGORITHM);
-        if (keymasterAlgorithm == null) {
-            throw new UnrecoverableKeyException("Key algorithm unknown");
-        }
-
-        String jcaKeyAlgorithm;
-        try {
-            jcaKeyAlgorithm = KeyProperties.KeyAlgorithm.fromKeymasterAsymmetricKeyAlgorithm(
-                    keymasterAlgorithm);
-        } catch (IllegalArgumentException e) {
-            throw (UnrecoverableKeyException)
-                    new UnrecoverableKeyException("Failed to load private key")
-                    .initCause(e);
-        }
-
-        return AndroidKeyStoreProvider.getAndroidKeyStorePublicKey(
-                privateKeyAlias, uid, jcaKeyAlgorithm, x509EncodedPublicKey);
-    }
-
-    /** @hide **/
-    @NonNull
-    public static AndroidKeyStorePublicKey loadAndroidKeyStorePublicKeyFromKeystore(
-            @NonNull KeyStore keyStore, @NonNull String privateKeyAlias, int uid)
-            throws UnrecoverableKeyException, KeyPermanentlyInvalidatedException {
-        return loadAndroidKeyStorePublicKeyFromKeystore(keyStore, privateKeyAlias, uid,
-                getKeyCharacteristics(keyStore, privateKeyAlias, uid));
-    }
-
-    @NonNull
-    private static KeyPair loadAndroidKeyStoreKeyPairFromKeystore(
-            @NonNull KeyStore keyStore, @NonNull String privateKeyAlias, int uid,
-            @NonNull KeyCharacteristics keyCharacteristics)
-            throws UnrecoverableKeyException {
-        AndroidKeyStorePublicKey publicKey =
-                loadAndroidKeyStorePublicKeyFromKeystore(keyStore, privateKeyAlias, uid,
-                        keyCharacteristics);
-        AndroidKeyStorePrivateKey privateKey =
-                AndroidKeyStoreProvider.getAndroidKeyStorePrivateKey(publicKey);
-        return new KeyPair(publicKey, privateKey);
-    }
-
-    /** @hide **/
-    @NonNull
-    public static KeyPair loadAndroidKeyStoreKeyPairFromKeystore(
-            @NonNull KeyStore keyStore, @NonNull String privateKeyAlias, int uid)
-            throws UnrecoverableKeyException, KeyPermanentlyInvalidatedException {
-        return loadAndroidKeyStoreKeyPairFromKeystore(keyStore, privateKeyAlias, uid,
-                getKeyCharacteristics(keyStore, privateKeyAlias, uid));
-    }
-
-    @NonNull
-    private static AndroidKeyStorePrivateKey loadAndroidKeyStorePrivateKeyFromKeystore(
-            @NonNull KeyStore keyStore, @NonNull String privateKeyAlias, int uid,
-            @NonNull KeyCharacteristics keyCharacteristics)
-            throws UnrecoverableKeyException {
-        KeyPair keyPair = loadAndroidKeyStoreKeyPairFromKeystore(keyStore, privateKeyAlias, uid,
-                keyCharacteristics);
-        return (AndroidKeyStorePrivateKey) keyPair.getPrivate();
-    }
-
-    /** @hide **/
-    @NonNull
-    public static AndroidKeyStorePrivateKey loadAndroidKeyStorePrivateKeyFromKeystore(
-            @NonNull KeyStore keyStore, @NonNull String privateKeyAlias, int uid)
-            throws UnrecoverableKeyException, KeyPermanentlyInvalidatedException {
-        return loadAndroidKeyStorePrivateKeyFromKeystore(keyStore, privateKeyAlias, uid,
-                getKeyCharacteristics(keyStore, privateKeyAlias, uid));
-    }
-
-    @NonNull
-    private static AndroidKeyStoreSecretKey loadAndroidKeyStoreSecretKeyFromKeystore(
-            @NonNull String secretKeyAlias, int uid, @NonNull KeyCharacteristics keyCharacteristics)
-            throws UnrecoverableKeyException {
-        Integer keymasterAlgorithm = keyCharacteristics.getEnum(KeymasterDefs.KM_TAG_ALGORITHM);
-        if (keymasterAlgorithm == null) {
-            throw new UnrecoverableKeyException("Key algorithm unknown");
-        }
-
-        List<Integer> keymasterDigests = keyCharacteristics.getEnums(KeymasterDefs.KM_TAG_DIGEST);
-        int keymasterDigest;
-        if (keymasterDigests.isEmpty()) {
-            keymasterDigest = -1;
-        } else {
-            // More than one digest can be permitted for this key. Use the first one to form the
-            // JCA key algorithm name.
-            keymasterDigest = keymasterDigests.get(0);
-        }
-
-        @KeyProperties.KeyAlgorithmEnum String keyAlgorithmString;
-        try {
-            keyAlgorithmString = KeyProperties.KeyAlgorithm.fromKeymasterSecretKeyAlgorithm(
-                    keymasterAlgorithm, keymasterDigest);
-        } catch (IllegalArgumentException e) {
-            throw (UnrecoverableKeyException)
-                    new UnrecoverableKeyException("Unsupported secret key type").initCause(e);
-        }
-
-        return new AndroidKeyStoreSecretKey(secretKeyAlias, uid, keyAlgorithmString);
-    }
-
-    /** @hide **/
-    @NonNull
-    public static AndroidKeyStoreKey loadAndroidKeyStoreKeyFromKeystore(
-            @NonNull KeyStore keyStore, @NonNull String userKeyAlias, int uid)
-            throws UnrecoverableKeyException, KeyPermanentlyInvalidatedException  {
-        KeyCharacteristics keyCharacteristics = getKeyCharacteristics(keyStore, userKeyAlias, uid);
-
-        Integer keymasterAlgorithm = keyCharacteristics.getEnum(KeymasterDefs.KM_TAG_ALGORITHM);
-        if (keymasterAlgorithm == null) {
-            throw new UnrecoverableKeyException("Key algorithm unknown");
-        }
-
-        if (keymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_HMAC ||
-                keymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_AES ||
-                keymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_3DES) {
-            return loadAndroidKeyStoreSecretKeyFromKeystore(userKeyAlias, uid,
-                    keyCharacteristics);
-        } else if (keymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_RSA ||
-                keymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_EC) {
-            return loadAndroidKeyStorePrivateKeyFromKeystore(keyStore, userKeyAlias, uid,
-                    keyCharacteristics);
-        } else {
-            throw new UnrecoverableKeyException("Key algorithm unknown");
-        }
+        return 0;
     }
 
     /**
@@ -434,13 +88,9 @@
     @NonNull
     public static java.security.KeyStore getKeyStoreForUid(int uid)
             throws KeyStoreException, NoSuchProviderException {
-        final java.security.KeyStore.LoadStoreParameter loadParameter;
-        if (android.security.keystore2.AndroidKeyStoreProvider.isInstalled()) {
-            loadParameter = new android.security.keystore2.AndroidKeyStoreLoadStoreParameter(
-                    KeyProperties.legacyUidToNamespace(uid));
-        } else {
-            loadParameter = new AndroidKeyStoreLoadStoreParameter(uid);
-        }
+        final java.security.KeyStore.LoadStoreParameter loadParameter =
+                new android.security.keystore2.AndroidKeyStoreLoadStoreParameter(
+                        KeyProperties.legacyUidToNamespace(uid));
         java.security.KeyStore result = java.security.KeyStore.getInstance(PROVIDER_NAME);
         try {
             result.load(loadParameter);
diff --git a/keystore/java/android/security/keystore/AndroidKeyStorePublicKey.java b/keystore/java/android/security/keystore/AndroidKeyStorePublicKey.java
deleted file mode 100644
index 4194780..0000000
--- a/keystore/java/android/security/keystore/AndroidKeyStorePublicKey.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.security.keystore;
-
-import java.security.PublicKey;
-import java.util.Arrays;
-
-/**
- * {@link PublicKey} backed by Android Keystore.
- *
- * @hide
- */
-public class AndroidKeyStorePublicKey extends AndroidKeyStoreKey implements PublicKey {
-
-    private final byte[] mEncoded;
-
-    public AndroidKeyStorePublicKey(String alias, int uid, String algorithm, byte[] x509EncodedForm) {
-        super(alias, uid, algorithm);
-        mEncoded = ArrayUtils.cloneIfNotEmpty(x509EncodedForm);
-    }
-
-    @Override
-    public String getFormat() {
-        return "X.509";
-    }
-
-    @Override
-    public byte[] getEncoded() {
-        return ArrayUtils.cloneIfNotEmpty(mEncoded);
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 31;
-        int result = super.hashCode();
-        result = prime * result + Arrays.hashCode(mEncoded);
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (!super.equals(obj)) {
-            return false;
-        }
-        if (getClass() != obj.getClass()) {
-            return false;
-        }
-        AndroidKeyStorePublicKey other = (AndroidKeyStorePublicKey) obj;
-        if (!Arrays.equals(mEncoded, other.mEncoded)) {
-            return false;
-        }
-        return true;
-    }
-}
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreRSACipherSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreRSACipherSpi.java
deleted file mode 100644
index 2ae68fa..0000000
--- a/keystore/java/android/security/keystore/AndroidKeyStoreRSACipherSpi.java
+++ /dev/null
@@ -1,515 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.security.keystore;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.security.KeyStore;
-import android.security.keymaster.KeyCharacteristics;
-import android.security.keymaster.KeymasterArguments;
-import android.security.keymaster.KeymasterDefs;
-
-import java.security.AlgorithmParameters;
-import java.security.InvalidAlgorithmParameterException;
-import java.security.InvalidKeyException;
-import java.security.Key;
-import java.security.NoSuchAlgorithmException;
-import java.security.PrivateKey;
-import java.security.ProviderException;
-import java.security.spec.AlgorithmParameterSpec;
-import java.security.spec.InvalidParameterSpecException;
-import java.security.spec.MGF1ParameterSpec;
-
-import javax.crypto.Cipher;
-import javax.crypto.CipherSpi;
-import javax.crypto.spec.OAEPParameterSpec;
-import javax.crypto.spec.PSource;
-
-/**
- * Base class for {@link CipherSpi} providing Android KeyStore backed RSA encryption/decryption.
- *
- * @hide
- */
-abstract class AndroidKeyStoreRSACipherSpi extends AndroidKeyStoreCipherSpiBase {
-
-    /**
-     * Raw RSA cipher without any padding.
-     */
-    public static final class NoPadding extends AndroidKeyStoreRSACipherSpi {
-        public NoPadding() {
-            super(KeymasterDefs.KM_PAD_NONE);
-        }
-
-        @Override
-        protected boolean adjustConfigForEncryptingWithPrivateKey() {
-            // RSA encryption with no padding using private key is a way to implement raw RSA
-            // signatures which JCA does not expose via Signature. We thus have to support this.
-            setKeymasterPurposeOverride(KeymasterDefs.KM_PURPOSE_SIGN);
-            return true;
-        }
-
-        @Override
-        protected void initAlgorithmSpecificParameters() throws InvalidKeyException {}
-
-        @Override
-        protected void initAlgorithmSpecificParameters(@Nullable AlgorithmParameterSpec params)
-                throws InvalidAlgorithmParameterException {
-            if (params != null) {
-                throw new InvalidAlgorithmParameterException(
-                        "Unexpected parameters: " + params + ". No parameters supported");
-            }
-        }
-
-        @Override
-        protected void initAlgorithmSpecificParameters(@Nullable AlgorithmParameters params)
-                throws InvalidAlgorithmParameterException {
-
-            if (params != null) {
-                throw new InvalidAlgorithmParameterException(
-                        "Unexpected parameters: " + params + ". No parameters supported");
-            }
-        }
-
-        @Override
-        protected AlgorithmParameters engineGetParameters() {
-            return null;
-        }
-
-        @Override
-        protected final int getAdditionalEntropyAmountForBegin() {
-            return 0;
-        }
-
-        @Override
-        protected final int getAdditionalEntropyAmountForFinish() {
-            return 0;
-        }
-    }
-
-    /**
-     * RSA cipher with PKCS#1 v1.5 encryption padding.
-     */
-    public static final class PKCS1Padding extends AndroidKeyStoreRSACipherSpi {
-        public PKCS1Padding() {
-            super(KeymasterDefs.KM_PAD_RSA_PKCS1_1_5_ENCRYPT);
-        }
-
-        @Override
-        protected boolean adjustConfigForEncryptingWithPrivateKey() {
-            // RSA encryption with PCKS#1 padding using private key is a way to implement RSA
-            // signatures with PKCS#1 padding. We have to support this for legacy reasons.
-            setKeymasterPurposeOverride(KeymasterDefs.KM_PURPOSE_SIGN);
-            setKeymasterPaddingOverride(KeymasterDefs.KM_PAD_RSA_PKCS1_1_5_SIGN);
-            return true;
-        }
-
-        @Override
-        protected void initAlgorithmSpecificParameters() throws InvalidKeyException {}
-
-        @Override
-        protected void initAlgorithmSpecificParameters(@Nullable AlgorithmParameterSpec params)
-                throws InvalidAlgorithmParameterException {
-            if (params != null) {
-                throw new InvalidAlgorithmParameterException(
-                        "Unexpected parameters: " + params + ". No parameters supported");
-            }
-        }
-
-        @Override
-        protected void initAlgorithmSpecificParameters(@Nullable AlgorithmParameters params)
-                throws InvalidAlgorithmParameterException {
-
-            if (params != null) {
-                throw new InvalidAlgorithmParameterException(
-                        "Unexpected parameters: " + params + ". No parameters supported");
-            }
-        }
-
-        @Override
-        protected AlgorithmParameters engineGetParameters() {
-            return null;
-        }
-
-        @Override
-        protected final int getAdditionalEntropyAmountForBegin() {
-            return 0;
-        }
-
-        @Override
-        protected final int getAdditionalEntropyAmountForFinish() {
-            return (isEncrypting()) ? getModulusSizeBytes() : 0;
-        }
-    }
-
-    /**
-     * RSA cipher with OAEP encryption padding. Only SHA-1 based MGF1 is supported as MGF.
-     */
-    abstract static class OAEPWithMGF1Padding extends AndroidKeyStoreRSACipherSpi {
-
-        private static final String MGF_ALGORITGM_MGF1 = "MGF1";
-
-        private int mKeymasterDigest = -1;
-        private int mDigestOutputSizeBytes;
-
-        OAEPWithMGF1Padding(int keymasterDigest) {
-            super(KeymasterDefs.KM_PAD_RSA_OAEP);
-            mKeymasterDigest = keymasterDigest;
-            mDigestOutputSizeBytes =
-                    (KeymasterUtils.getDigestOutputSizeBits(keymasterDigest) + 7) / 8;
-        }
-
-        @Override
-        protected final void initAlgorithmSpecificParameters() throws InvalidKeyException {}
-
-        @Override
-        protected final void initAlgorithmSpecificParameters(
-                @Nullable AlgorithmParameterSpec params) throws InvalidAlgorithmParameterException {
-            if (params == null) {
-                return;
-            }
-
-            if (!(params instanceof OAEPParameterSpec)) {
-                throw new InvalidAlgorithmParameterException(
-                        "Unsupported parameter spec: " + params
-                        + ". Only OAEPParameterSpec supported");
-            }
-            OAEPParameterSpec spec = (OAEPParameterSpec) params;
-            if (!MGF_ALGORITGM_MGF1.equalsIgnoreCase(spec.getMGFAlgorithm())) {
-                throw new InvalidAlgorithmParameterException(
-                        "Unsupported MGF: " + spec.getMGFAlgorithm()
-                        + ". Only " + MGF_ALGORITGM_MGF1 + " supported");
-            }
-            String jcaDigest = spec.getDigestAlgorithm();
-            int keymasterDigest;
-            try {
-                keymasterDigest = KeyProperties.Digest.toKeymaster(jcaDigest);
-            } catch (IllegalArgumentException e) {
-                throw new InvalidAlgorithmParameterException(
-                        "Unsupported digest: " + jcaDigest, e);
-            }
-            switch (keymasterDigest) {
-                case KeymasterDefs.KM_DIGEST_SHA1:
-                case KeymasterDefs.KM_DIGEST_SHA_2_224:
-                case KeymasterDefs.KM_DIGEST_SHA_2_256:
-                case KeymasterDefs.KM_DIGEST_SHA_2_384:
-                case KeymasterDefs.KM_DIGEST_SHA_2_512:
-                    // Permitted.
-                    break;
-                default:
-                    throw new InvalidAlgorithmParameterException(
-                            "Unsupported digest: " + jcaDigest);
-            }
-            AlgorithmParameterSpec mgfParams = spec.getMGFParameters();
-            if (mgfParams == null) {
-                throw new InvalidAlgorithmParameterException("MGF parameters must be provided");
-            }
-            // Check whether MGF parameters match the OAEPParameterSpec
-            if (!(mgfParams instanceof MGF1ParameterSpec)) {
-                throw new InvalidAlgorithmParameterException("Unsupported MGF parameters"
-                        + ": " + mgfParams + ". Only MGF1ParameterSpec supported");
-            }
-            MGF1ParameterSpec mgfSpec = (MGF1ParameterSpec) mgfParams;
-            String mgf1JcaDigest = mgfSpec.getDigestAlgorithm();
-            if (!KeyProperties.DIGEST_SHA1.equalsIgnoreCase(mgf1JcaDigest)) {
-                throw new InvalidAlgorithmParameterException(
-                        "Unsupported MGF1 digest: " + mgf1JcaDigest
-                        + ". Only " + KeyProperties.DIGEST_SHA1 + " supported");
-            }
-            PSource pSource = spec.getPSource();
-            if (!(pSource instanceof PSource.PSpecified)) {
-                throw new InvalidAlgorithmParameterException(
-                        "Unsupported source of encoding input P: " + pSource
-                        + ". Only pSpecifiedEmpty (PSource.PSpecified.DEFAULT) supported");
-            }
-            PSource.PSpecified pSourceSpecified = (PSource.PSpecified) pSource;
-            byte[] pSourceValue = pSourceSpecified.getValue();
-            if ((pSourceValue != null) && (pSourceValue.length > 0)) {
-                throw new InvalidAlgorithmParameterException(
-                        "Unsupported source of encoding input P: " + pSource
-                        + ". Only pSpecifiedEmpty (PSource.PSpecified.DEFAULT) supported");
-            }
-            mKeymasterDigest = keymasterDigest;
-            mDigestOutputSizeBytes =
-                    (KeymasterUtils.getDigestOutputSizeBits(keymasterDigest) + 7) / 8;
-        }
-
-        @Override
-        protected final void initAlgorithmSpecificParameters(@Nullable AlgorithmParameters params)
-                throws InvalidAlgorithmParameterException {
-            if (params == null) {
-                return;
-            }
-
-            OAEPParameterSpec spec;
-            try {
-                spec = params.getParameterSpec(OAEPParameterSpec.class);
-            } catch (InvalidParameterSpecException e) {
-                throw new InvalidAlgorithmParameterException("OAEP parameters required"
-                        + ", but not found in parameters: " + params, e);
-            }
-            if (spec == null) {
-                throw new InvalidAlgorithmParameterException("OAEP parameters required"
-                        + ", but not provided in parameters: " + params);
-            }
-            initAlgorithmSpecificParameters(spec);
-        }
-
-        @Override
-        protected final AlgorithmParameters engineGetParameters() {
-            OAEPParameterSpec spec =
-                    new OAEPParameterSpec(
-                            KeyProperties.Digest.fromKeymaster(mKeymasterDigest),
-                            MGF_ALGORITGM_MGF1,
-                            MGF1ParameterSpec.SHA1,
-                            PSource.PSpecified.DEFAULT);
-            try {
-                AlgorithmParameters params = AlgorithmParameters.getInstance("OAEP");
-                params.init(spec);
-                return params;
-            } catch (NoSuchAlgorithmException e) {
-                throw new ProviderException(
-                        "Failed to obtain OAEP AlgorithmParameters", e);
-            } catch (InvalidParameterSpecException e) {
-                throw new ProviderException(
-                        "Failed to initialize OAEP AlgorithmParameters with an IV",
-                        e);
-            }
-        }
-
-        @Override
-        protected final void addAlgorithmSpecificParametersToBegin(
-                KeymasterArguments keymasterArgs) {
-            super.addAlgorithmSpecificParametersToBegin(keymasterArgs);
-            keymasterArgs.addEnum(KeymasterDefs.KM_TAG_DIGEST, mKeymasterDigest);
-        }
-
-        @Override
-        protected final void loadAlgorithmSpecificParametersFromBeginResult(
-                @NonNull KeymasterArguments keymasterArgs) {
-            super.loadAlgorithmSpecificParametersFromBeginResult(keymasterArgs);
-        }
-
-        @Override
-        protected final int getAdditionalEntropyAmountForBegin() {
-            return 0;
-        }
-
-        @Override
-        protected final int getAdditionalEntropyAmountForFinish() {
-            return (isEncrypting()) ? mDigestOutputSizeBytes : 0;
-        }
-    }
-
-    public static class OAEPWithSHA1AndMGF1Padding extends OAEPWithMGF1Padding {
-        public OAEPWithSHA1AndMGF1Padding() {
-            super(KeymasterDefs.KM_DIGEST_SHA1);
-        }
-    }
-
-    public static class OAEPWithSHA224AndMGF1Padding extends OAEPWithMGF1Padding {
-        public OAEPWithSHA224AndMGF1Padding() {
-            super(KeymasterDefs.KM_DIGEST_SHA_2_224);
-        }
-    }
-
-    public static class OAEPWithSHA256AndMGF1Padding extends OAEPWithMGF1Padding {
-        public OAEPWithSHA256AndMGF1Padding() {
-            super(KeymasterDefs.KM_DIGEST_SHA_2_256);
-        }
-    }
-
-    public static class OAEPWithSHA384AndMGF1Padding extends OAEPWithMGF1Padding {
-        public OAEPWithSHA384AndMGF1Padding() {
-            super(KeymasterDefs.KM_DIGEST_SHA_2_384);
-        }
-    }
-
-    public static class OAEPWithSHA512AndMGF1Padding extends OAEPWithMGF1Padding {
-        public OAEPWithSHA512AndMGF1Padding() {
-            super(KeymasterDefs.KM_DIGEST_SHA_2_512);
-        }
-    }
-
-    private final int mKeymasterPadding;
-    private int mKeymasterPaddingOverride;
-
-    private int mModulusSizeBytes = -1;
-
-    AndroidKeyStoreRSACipherSpi(int keymasterPadding) {
-        mKeymasterPadding = keymasterPadding;
-    }
-
-    @Override
-    protected final void initKey(int opmode, Key key) throws InvalidKeyException {
-        if (key == null) {
-            throw new InvalidKeyException("Unsupported key: null");
-        }
-        if (!KeyProperties.KEY_ALGORITHM_RSA.equalsIgnoreCase(key.getAlgorithm())) {
-            throw new InvalidKeyException("Unsupported key algorithm: " + key.getAlgorithm()
-                    + ". Only " + KeyProperties.KEY_ALGORITHM_RSA + " supported");
-        }
-        AndroidKeyStoreKey keystoreKey;
-        if (key instanceof AndroidKeyStorePrivateKey) {
-            keystoreKey = (AndroidKeyStoreKey) key;
-        } else if (key instanceof AndroidKeyStorePublicKey) {
-            keystoreKey = (AndroidKeyStoreKey) key;
-        } else {
-            throw new InvalidKeyException("Unsupported key type: " + key);
-        }
-
-        if (keystoreKey instanceof PrivateKey) {
-            // Private key
-            switch (opmode) {
-                case Cipher.DECRYPT_MODE:
-                case Cipher.UNWRAP_MODE:
-                    // Permitted
-                    break;
-                case Cipher.ENCRYPT_MODE:
-                case Cipher.WRAP_MODE:
-                    if (!adjustConfigForEncryptingWithPrivateKey()) {
-                        throw new InvalidKeyException(
-                                "RSA private keys cannot be used with " + opmodeToString(opmode)
-                                + " and padding "
-                                + KeyProperties.EncryptionPadding.fromKeymaster(mKeymasterPadding)
-                                + ". Only RSA public keys supported for this mode");
-                    }
-                    break;
-                default:
-                    throw new InvalidKeyException(
-                            "RSA private keys cannot be used with opmode: " + opmode);
-            }
-        } else {
-            // Public key
-            switch (opmode) {
-                case Cipher.ENCRYPT_MODE:
-                case Cipher.WRAP_MODE:
-                    // Permitted
-                    break;
-                case Cipher.DECRYPT_MODE:
-                case Cipher.UNWRAP_MODE:
-                    throw new InvalidKeyException(
-                            "RSA public keys cannot be used with " + opmodeToString(opmode)
-                            + " and padding "
-                            + KeyProperties.EncryptionPadding.fromKeymaster(mKeymasterPadding)
-                            + ". Only RSA private keys supported for this opmode.");
-                    // break;
-                default:
-                    throw new InvalidKeyException(
-                            "RSA public keys cannot be used with " + opmodeToString(opmode));
-            }
-        }
-
-        KeyCharacteristics keyCharacteristics = new KeyCharacteristics();
-        int errorCode = getKeyStore().getKeyCharacteristics(
-                keystoreKey.getAlias(), null, null, keystoreKey.getUid(), keyCharacteristics);
-        if (errorCode != KeyStore.NO_ERROR) {
-            throw getKeyStore().getInvalidKeyException(
-                    keystoreKey.getAlias(), keystoreKey.getUid(), errorCode);
-        }
-        long keySizeBits = keyCharacteristics.getUnsignedInt(KeymasterDefs.KM_TAG_KEY_SIZE, -1);
-        if (keySizeBits == -1) {
-            throw new InvalidKeyException("Size of key not known");
-        } else if (keySizeBits > Integer.MAX_VALUE) {
-            throw new InvalidKeyException("Key too large: " + keySizeBits + " bits");
-        }
-        mModulusSizeBytes = (int) ((keySizeBits + 7) / 8);
-
-        setKey(keystoreKey);
-    }
-
-    /**
-     * Adjusts the configuration of this cipher for encrypting using the private key.
-     *
-     * <p>The default implementation does nothing and refuses to adjust the configuration.
-     *
-     * @return {@code true} if the configuration has been adjusted, {@code false} if encrypting
-     *         using private key is not permitted for this cipher.
-     */
-    protected boolean adjustConfigForEncryptingWithPrivateKey() {
-        return false;
-    }
-
-    @Override
-    protected final void resetAll() {
-        mModulusSizeBytes = -1;
-        mKeymasterPaddingOverride = -1;
-        super.resetAll();
-    }
-
-    @Override
-    protected final void resetWhilePreservingInitState() {
-        super.resetWhilePreservingInitState();
-    }
-
-    @Override
-    protected void addAlgorithmSpecificParametersToBegin(
-            @NonNull KeymasterArguments keymasterArgs) {
-        keymasterArgs.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_RSA);
-        int keymasterPadding = getKeymasterPaddingOverride();
-        if (keymasterPadding == -1) {
-            keymasterPadding = mKeymasterPadding;
-        }
-        keymasterArgs.addEnum(KeymasterDefs.KM_TAG_PADDING, keymasterPadding);
-        int purposeOverride = getKeymasterPurposeOverride();
-        if ((purposeOverride != -1)
-                && ((purposeOverride == KeymasterDefs.KM_PURPOSE_SIGN)
-                || (purposeOverride == KeymasterDefs.KM_PURPOSE_VERIFY))) {
-            // Keymaster sign/verify requires digest to be specified. For raw sign/verify it's NONE.
-            keymasterArgs.addEnum(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_NONE);
-        }
-    }
-
-    @Override
-    protected void loadAlgorithmSpecificParametersFromBeginResult(
-            @NonNull KeymasterArguments keymasterArgs) {
-    }
-
-    @Override
-    protected final int engineGetBlockSize() {
-        // Not a block cipher, according to the RI
-        return 0;
-    }
-
-    @Override
-    protected final byte[] engineGetIV() {
-        // IV never used
-        return null;
-    }
-
-    @Override
-    protected final int engineGetOutputSize(int inputLen) {
-        return getModulusSizeBytes();
-    }
-
-    protected final int getModulusSizeBytes() {
-        if (mModulusSizeBytes == -1) {
-            throw new IllegalStateException("Not initialized");
-        }
-        return mModulusSizeBytes;
-    }
-
-    /**
-     * Overrides the default padding of the crypto operation.
-     */
-    protected final void setKeymasterPaddingOverride(int keymasterPadding) {
-        mKeymasterPaddingOverride = keymasterPadding;
-    }
-
-    protected final int getKeymasterPaddingOverride() {
-        return mKeymasterPaddingOverride;
-    }
-}
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreRSAPrivateKey.java b/keystore/java/android/security/keystore/AndroidKeyStoreRSAPrivateKey.java
deleted file mode 100644
index adb3922..0000000
--- a/keystore/java/android/security/keystore/AndroidKeyStoreRSAPrivateKey.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.security.keystore;
-
-import java.math.BigInteger;
-import java.security.PrivateKey;
-import java.security.interfaces.RSAKey;
-
-/**
- * RSA private key (instance of {@link PrivateKey} and {@link RSAKey}) backed by keystore.
- *
- * @hide
- */
-public class AndroidKeyStoreRSAPrivateKey extends AndroidKeyStorePrivateKey implements RSAKey {
-
-    private final BigInteger mModulus;
-
-    public AndroidKeyStoreRSAPrivateKey(String alias, int uid, BigInteger modulus) {
-        super(alias, uid, KeyProperties.KEY_ALGORITHM_RSA);
-        mModulus = modulus;
-    }
-
-    @Override
-    public BigInteger getModulus() {
-        return mModulus;
-    }
-}
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreRSAPublicKey.java b/keystore/java/android/security/keystore/AndroidKeyStoreRSAPublicKey.java
deleted file mode 100644
index d85aace..0000000
--- a/keystore/java/android/security/keystore/AndroidKeyStoreRSAPublicKey.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.security.keystore;
-
-import java.math.BigInteger;
-import java.security.interfaces.RSAPublicKey;
-
-/**
- * {@link RSAPublicKey} backed by Android Keystore.
- *
- * @hide
- */
-public class AndroidKeyStoreRSAPublicKey extends AndroidKeyStorePublicKey implements RSAPublicKey {
-    private final BigInteger mModulus;
-    private final BigInteger mPublicExponent;
-
-    public AndroidKeyStoreRSAPublicKey(String alias, int uid, byte[] x509EncodedForm, BigInteger modulus,
-            BigInteger publicExponent) {
-        super(alias, uid, KeyProperties.KEY_ALGORITHM_RSA, x509EncodedForm);
-        mModulus = modulus;
-        mPublicExponent = publicExponent;
-    }
-
-    public AndroidKeyStoreRSAPublicKey(String alias, int uid, RSAPublicKey info) {
-        this(alias, uid, info.getEncoded(), info.getModulus(), info.getPublicExponent());
-        if (!"X.509".equalsIgnoreCase(info.getFormat())) {
-            throw new IllegalArgumentException(
-                    "Unsupported key export format: " + info.getFormat());
-        }
-    }
-
-    @Override
-    public BigInteger getModulus() {
-        return mModulus;
-    }
-
-    @Override
-    public BigInteger getPublicExponent() {
-        return mPublicExponent;
-    }
-}
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreRSASignatureSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreRSASignatureSpi.java
deleted file mode 100644
index ecfc97e..0000000
--- a/keystore/java/android/security/keystore/AndroidKeyStoreRSASignatureSpi.java
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.security.keystore;
-
-import android.annotation.NonNull;
-import android.security.keymaster.KeymasterArguments;
-import android.security.keymaster.KeymasterDefs;
-
-import java.security.InvalidKeyException;
-import java.security.SignatureSpi;
-
-/**
- * Base class for {@link SignatureSpi} providing Android KeyStore backed RSA signatures.
- *
- * @hide
- */
-abstract class AndroidKeyStoreRSASignatureSpi extends AndroidKeyStoreSignatureSpiBase {
-
-    abstract static class PKCS1Padding extends AndroidKeyStoreRSASignatureSpi {
-        PKCS1Padding(int keymasterDigest) {
-            super(keymasterDigest, KeymasterDefs.KM_PAD_RSA_PKCS1_1_5_SIGN);
-        }
-
-        @Override
-        protected final int getAdditionalEntropyAmountForSign() {
-            // No entropy required for this deterministic signature scheme.
-            return 0;
-        }
-    }
-
-    public static final class NONEWithPKCS1Padding extends PKCS1Padding {
-        public NONEWithPKCS1Padding() {
-            super(KeymasterDefs.KM_DIGEST_NONE);
-        }
-    }
-
-    public static final class MD5WithPKCS1Padding extends PKCS1Padding {
-        public MD5WithPKCS1Padding() {
-            super(KeymasterDefs.KM_DIGEST_MD5);
-        }
-    }
-
-    public static final class SHA1WithPKCS1Padding extends PKCS1Padding {
-        public SHA1WithPKCS1Padding() {
-            super(KeymasterDefs.KM_DIGEST_SHA1);
-        }
-    }
-
-    public static final class SHA224WithPKCS1Padding extends PKCS1Padding {
-        public SHA224WithPKCS1Padding() {
-            super(KeymasterDefs.KM_DIGEST_SHA_2_224);
-        }
-    }
-
-    public static final class SHA256WithPKCS1Padding extends PKCS1Padding {
-        public SHA256WithPKCS1Padding() {
-            super(KeymasterDefs.KM_DIGEST_SHA_2_256);
-        }
-    }
-
-    public static final class SHA384WithPKCS1Padding extends PKCS1Padding {
-        public SHA384WithPKCS1Padding() {
-            super(KeymasterDefs.KM_DIGEST_SHA_2_384);
-        }
-    }
-
-    public static final class SHA512WithPKCS1Padding extends PKCS1Padding {
-        public SHA512WithPKCS1Padding() {
-            super(KeymasterDefs.KM_DIGEST_SHA_2_512);
-        }
-    }
-
-    abstract static class PSSPadding extends AndroidKeyStoreRSASignatureSpi {
-        private static final int SALT_LENGTH_BYTES = 20;
-
-        PSSPadding(int keymasterDigest) {
-            super(keymasterDigest, KeymasterDefs.KM_PAD_RSA_PSS);
-        }
-
-        @Override
-        protected final int getAdditionalEntropyAmountForSign() {
-            return SALT_LENGTH_BYTES;
-        }
-    }
-
-    public static final class SHA1WithPSSPadding extends PSSPadding {
-        public SHA1WithPSSPadding() {
-            super(KeymasterDefs.KM_DIGEST_SHA1);
-        }
-    }
-
-    public static final class SHA224WithPSSPadding extends PSSPadding {
-        public SHA224WithPSSPadding() {
-            super(KeymasterDefs.KM_DIGEST_SHA_2_224);
-        }
-    }
-
-    public static final class SHA256WithPSSPadding extends PSSPadding {
-        public SHA256WithPSSPadding() {
-            super(KeymasterDefs.KM_DIGEST_SHA_2_256);
-        }
-    }
-
-    public static final class SHA384WithPSSPadding extends PSSPadding {
-        public SHA384WithPSSPadding() {
-            super(KeymasterDefs.KM_DIGEST_SHA_2_384);
-        }
-    }
-
-    public static final class SHA512WithPSSPadding extends PSSPadding {
-        public SHA512WithPSSPadding() {
-            super(KeymasterDefs.KM_DIGEST_SHA_2_512);
-        }
-    }
-
-    private final int mKeymasterDigest;
-    private final int mKeymasterPadding;
-
-    AndroidKeyStoreRSASignatureSpi(int keymasterDigest, int keymasterPadding) {
-        mKeymasterDigest = keymasterDigest;
-        mKeymasterPadding = keymasterPadding;
-    }
-
-    @Override
-    protected final void initKey(AndroidKeyStoreKey key) throws InvalidKeyException {
-        if (!KeyProperties.KEY_ALGORITHM_RSA.equalsIgnoreCase(key.getAlgorithm())) {
-            throw new InvalidKeyException("Unsupported key algorithm: " + key.getAlgorithm()
-                    + ". Only" + KeyProperties.KEY_ALGORITHM_RSA + " supported");
-        }
-        super.initKey(key);
-    }
-
-    @Override
-    protected final void resetAll() {
-        super.resetAll();
-    }
-
-    @Override
-    protected final void resetWhilePreservingInitState() {
-        super.resetWhilePreservingInitState();
-    }
-
-    @Override
-    protected final void addAlgorithmSpecificParametersToBegin(
-            @NonNull KeymasterArguments keymasterArgs) {
-        keymasterArgs.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_RSA);
-        keymasterArgs.addEnum(KeymasterDefs.KM_TAG_DIGEST, mKeymasterDigest);
-        keymasterArgs.addEnum(KeymasterDefs.KM_TAG_PADDING, mKeymasterPadding);
-    }
-}
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreSecretKey.java b/keystore/java/android/security/keystore/AndroidKeyStoreSecretKey.java
deleted file mode 100644
index b8e6af7..0000000
--- a/keystore/java/android/security/keystore/AndroidKeyStoreSecretKey.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.security.keystore;
-
-import javax.crypto.SecretKey;
-
-/**
- * {@link SecretKey} backed by Android Keystore.
- *
- * @hide
- */
-public class AndroidKeyStoreSecretKey extends AndroidKeyStoreKey implements SecretKey {
-
-    public AndroidKeyStoreSecretKey(String alias, int uid, String algorithm) {
-        super(alias, uid, algorithm);
-    }
-}
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreSecretKeyFactorySpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreSecretKeyFactorySpi.java
deleted file mode 100644
index d2678c7..0000000
--- a/keystore/java/android/security/keystore/AndroidKeyStoreSecretKeyFactorySpi.java
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.security.keystore;
-
-import android.security.Credentials;
-import android.security.GateKeeper;
-import android.security.KeyStore;
-import android.security.keymaster.KeyCharacteristics;
-import android.security.keymaster.KeymasterDefs;
-
-import java.math.BigInteger;
-import java.security.InvalidKeyException;
-import java.security.ProviderException;
-import java.security.spec.InvalidKeySpecException;
-import java.security.spec.KeySpec;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-
-import javax.crypto.SecretKey;
-import javax.crypto.SecretKeyFactorySpi;
-import javax.crypto.spec.SecretKeySpec;
-
-/**
- * {@link SecretKeyFactorySpi} backed by Android Keystore.
- *
- * @hide
- */
-public class AndroidKeyStoreSecretKeyFactorySpi extends SecretKeyFactorySpi {
-
-    private final KeyStore mKeyStore = KeyStore.getInstance();
-
-    @Override
-    protected KeySpec engineGetKeySpec(SecretKey key,
-            @SuppressWarnings("rawtypes") Class keySpecClass) throws InvalidKeySpecException {
-        if (keySpecClass == null) {
-            throw new InvalidKeySpecException("keySpecClass == null");
-        }
-        if (!(key instanceof AndroidKeyStoreSecretKey)) {
-            throw new InvalidKeySpecException("Only Android KeyStore secret keys supported: " +
-                    ((key != null) ? key.getClass().getName() : "null"));
-        }
-        if (SecretKeySpec.class.isAssignableFrom(keySpecClass)) {
-            throw new InvalidKeySpecException(
-                    "Key material export of Android KeyStore keys is not supported");
-        }
-        if (!KeyInfo.class.equals(keySpecClass)) {
-            throw new InvalidKeySpecException("Unsupported key spec: " + keySpecClass.getName());
-        }
-        AndroidKeyStoreKey keystoreKey = (AndroidKeyStoreKey) key;
-        String keyAliasInKeystore = keystoreKey.getAlias();
-        String entryAlias;
-        if (keyAliasInKeystore.startsWith(Credentials.USER_PRIVATE_KEY)) {
-            entryAlias = keyAliasInKeystore.substring(Credentials.USER_PRIVATE_KEY.length());
-        } else if (keyAliasInKeystore.startsWith(Credentials.USER_SECRET_KEY)){
-            // key has legacy prefix
-            entryAlias = keyAliasInKeystore.substring(Credentials.USER_SECRET_KEY.length());
-        } else {
-            throw new InvalidKeySpecException("Invalid key alias: " + keyAliasInKeystore);
-        }
-
-        return getKeyInfo(mKeyStore, entryAlias, keyAliasInKeystore, keystoreKey.getUid());
-    }
-
-    static KeyInfo getKeyInfo(KeyStore keyStore, String entryAlias, String keyAliasInKeystore,
-            int keyUid) {
-        KeyCharacteristics keyCharacteristics = new KeyCharacteristics();
-        int errorCode = keyStore.getKeyCharacteristics(
-                keyAliasInKeystore, null, null, keyUid, keyCharacteristics);
-        if (errorCode != KeyStore.NO_ERROR) {
-            throw new ProviderException("Failed to obtain information about key."
-                    + " Keystore error: " + errorCode);
-        }
-
-        boolean insideSecureHardware;
-        @KeyProperties.OriginEnum int origin;
-        int keySize;
-        @KeyProperties.PurposeEnum int purposes;
-        String[] encryptionPaddings;
-        String[] signaturePaddings;
-        @KeyProperties.DigestEnum String[] digests;
-        @KeyProperties.BlockModeEnum String[] blockModes;
-        int keymasterSwEnforcedUserAuthenticators;
-        int keymasterHwEnforcedUserAuthenticators;
-        List<BigInteger> keymasterSecureUserIds;
-        try {
-            if (keyCharacteristics.hwEnforced.containsTag(KeymasterDefs.KM_TAG_ORIGIN)) {
-                insideSecureHardware = true;
-                origin = KeyProperties.Origin.fromKeymaster(
-                        keyCharacteristics.hwEnforced.getEnum(KeymasterDefs.KM_TAG_ORIGIN, -1));
-            } else if (keyCharacteristics.swEnforced.containsTag(KeymasterDefs.KM_TAG_ORIGIN)) {
-                insideSecureHardware = false;
-                origin = KeyProperties.Origin.fromKeymaster(
-                        keyCharacteristics.swEnforced.getEnum(KeymasterDefs.KM_TAG_ORIGIN, -1));
-            } else {
-                throw new ProviderException("Key origin not available");
-            }
-            long keySizeUnsigned =
-                    keyCharacteristics.getUnsignedInt(KeymasterDefs.KM_TAG_KEY_SIZE, -1);
-            if (keySizeUnsigned == -1) {
-                throw new ProviderException("Key size not available");
-            } else if (keySizeUnsigned > Integer.MAX_VALUE) {
-                throw new ProviderException("Key too large: " + keySizeUnsigned + " bits");
-            }
-            keySize = (int) keySizeUnsigned;
-            purposes = KeyProperties.Purpose.allFromKeymaster(
-                    keyCharacteristics.getEnums(KeymasterDefs.KM_TAG_PURPOSE));
-
-            List<String> encryptionPaddingsList = new ArrayList<String>();
-            List<String> signaturePaddingsList = new ArrayList<String>();
-            // Keymaster stores both types of paddings in the same array -- we split it into two.
-            for (int keymasterPadding : keyCharacteristics.getEnums(KeymasterDefs.KM_TAG_PADDING)) {
-                try {
-                    @KeyProperties.EncryptionPaddingEnum String jcaPadding =
-                            KeyProperties.EncryptionPadding.fromKeymaster(keymasterPadding);
-                    encryptionPaddingsList.add(jcaPadding);
-                } catch (IllegalArgumentException e) {
-                    try {
-                        @KeyProperties.SignaturePaddingEnum String padding =
-                                KeyProperties.SignaturePadding.fromKeymaster(keymasterPadding);
-                        signaturePaddingsList.add(padding);
-                    } catch (IllegalArgumentException e2) {
-                        throw new ProviderException(
-                                "Unsupported encryption padding: " + keymasterPadding);
-                    }
-                }
-
-            }
-            encryptionPaddings =
-                    encryptionPaddingsList.toArray(new String[encryptionPaddingsList.size()]);
-            signaturePaddings =
-                    signaturePaddingsList.toArray(new String[signaturePaddingsList.size()]);
-
-            digests = KeyProperties.Digest.allFromKeymaster(
-                    keyCharacteristics.getEnums(KeymasterDefs.KM_TAG_DIGEST));
-            blockModes = KeyProperties.BlockMode.allFromKeymaster(
-                    keyCharacteristics.getEnums(KeymasterDefs.KM_TAG_BLOCK_MODE));
-            keymasterSwEnforcedUserAuthenticators =
-                    keyCharacteristics.swEnforced.getEnum(KeymasterDefs.KM_TAG_USER_AUTH_TYPE, 0);
-            keymasterHwEnforcedUserAuthenticators =
-                    keyCharacteristics.hwEnforced.getEnum(KeymasterDefs.KM_TAG_USER_AUTH_TYPE, 0);
-            keymasterSecureUserIds =
-                keyCharacteristics.getUnsignedLongs(KeymasterDefs.KM_TAG_USER_SECURE_ID);
-        } catch (IllegalArgumentException e) {
-            throw new ProviderException("Unsupported key characteristic", e);
-        }
-
-        Date keyValidityStart = keyCharacteristics.getDate(KeymasterDefs.KM_TAG_ACTIVE_DATETIME);
-        Date keyValidityForOriginationEnd =
-                keyCharacteristics.getDate(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME);
-        Date keyValidityForConsumptionEnd =
-                keyCharacteristics.getDate(KeymasterDefs.KM_TAG_USAGE_EXPIRE_DATETIME);
-        boolean userAuthenticationRequired =
-                !keyCharacteristics.getBoolean(KeymasterDefs.KM_TAG_NO_AUTH_REQUIRED);
-        long userAuthenticationValidityDurationSeconds =
-                keyCharacteristics.getUnsignedInt(KeymasterDefs.KM_TAG_AUTH_TIMEOUT, 0);
-        if (userAuthenticationValidityDurationSeconds > Integer.MAX_VALUE) {
-            throw new ProviderException("User authentication timeout validity too long: "
-                    + userAuthenticationValidityDurationSeconds + " seconds");
-        }
-        boolean userAuthenticationRequirementEnforcedBySecureHardware = (userAuthenticationRequired)
-                && (keymasterHwEnforcedUserAuthenticators != 0)
-                && (keymasterSwEnforcedUserAuthenticators == 0);
-        boolean userAuthenticationValidWhileOnBody =
-                keyCharacteristics.hwEnforced.getBoolean(KeymasterDefs.KM_TAG_ALLOW_WHILE_ON_BODY);
-        boolean trustedUserPresenceRequired =
-                keyCharacteristics.hwEnforced.getBoolean(
-                    KeymasterDefs.KM_TAG_TRUSTED_USER_PRESENCE_REQUIRED);
-
-        boolean invalidatedByBiometricEnrollment = false;
-        if (keymasterSwEnforcedUserAuthenticators == KeymasterDefs.HW_AUTH_BIOMETRIC
-            || keymasterHwEnforcedUserAuthenticators == KeymasterDefs.HW_AUTH_BIOMETRIC) {
-            // Fingerprint-only key; will be invalidated if the root SID isn't in the SID list.
-            invalidatedByBiometricEnrollment = keymasterSecureUserIds != null
-                    && !keymasterSecureUserIds.isEmpty()
-                    && !keymasterSecureUserIds.contains(getGateKeeperSecureUserId());
-        }
-
-        boolean userConfirmationRequired = keyCharacteristics.hwEnforced.getBoolean(KeymasterDefs.KM_TAG_TRUSTED_CONFIRMATION_REQUIRED);
-
-        return new KeyInfo(entryAlias,
-                insideSecureHardware,
-                origin,
-                keySize,
-                keyValidityStart,
-                keyValidityForOriginationEnd,
-                keyValidityForConsumptionEnd,
-                purposes,
-                encryptionPaddings,
-                signaturePaddings,
-                digests,
-                blockModes,
-                userAuthenticationRequired,
-                (int) userAuthenticationValidityDurationSeconds,
-                keymasterHwEnforcedUserAuthenticators,
-                userAuthenticationRequirementEnforcedBySecureHardware,
-                userAuthenticationValidWhileOnBody,
-                trustedUserPresenceRequired,
-                invalidatedByBiometricEnrollment,
-                userConfirmationRequired,
-                // Keystore 1.0 does not tell us the exact security level of the key
-                // so we report an unknown but secure security level.
-                insideSecureHardware ? KeyProperties.SECURITY_LEVEL_UNKNOWN_SECURE
-                        : KeyProperties.SECURITY_LEVEL_SOFTWARE,
-                KeyProperties.UNRESTRICTED_USAGE_COUNT);
-    }
-
-    private static BigInteger getGateKeeperSecureUserId() throws ProviderException {
-    	try {
-    		return BigInteger.valueOf(GateKeeper.getSecureUserId());
-    	} catch (IllegalStateException e) {
-    		throw new ProviderException("Failed to get GateKeeper secure user ID", e);
-    	}
-    }
-
-    @Override
-    protected SecretKey engineGenerateSecret(KeySpec keySpec) throws InvalidKeySpecException {
-        throw new InvalidKeySpecException(
-                "To generate secret key in Android Keystore, use KeyGenerator initialized with "
-                        + KeyGenParameterSpec.class.getName());
-    }
-
-    @Override
-    protected SecretKey engineTranslateKey(SecretKey key) throws InvalidKeyException {
-        if (key == null) {
-            throw new InvalidKeyException("key == null");
-        } else if (!(key instanceof AndroidKeyStoreSecretKey)) {
-            throw new InvalidKeyException(
-                    "To import a secret key into Android Keystore, use KeyStore.setEntry");
-        }
-
-        return key;
-    }
-}
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreSignatureSpiBase.java b/keystore/java/android/security/keystore/AndroidKeyStoreSignatureSpiBase.java
deleted file mode 100644
index da47b6b..0000000
--- a/keystore/java/android/security/keystore/AndroidKeyStoreSignatureSpiBase.java
+++ /dev/null
@@ -1,431 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.security.keystore;
-
-import android.annotation.CallSuper;
-import android.annotation.NonNull;
-import android.os.IBinder;
-import android.security.KeyStore;
-import android.security.KeyStoreException;
-import android.security.keymaster.KeymasterArguments;
-import android.security.keymaster.KeymasterDefs;
-import android.security.keymaster.OperationResult;
-
-import libcore.util.EmptyArray;
-
-import java.nio.ByteBuffer;
-import java.security.InvalidKeyException;
-import java.security.InvalidParameterException;
-import java.security.PrivateKey;
-import java.security.ProviderException;
-import java.security.PublicKey;
-import java.security.SecureRandom;
-import java.security.SignatureException;
-import java.security.SignatureSpi;
-
-/**
- * Base class for {@link SignatureSpi} implementations of Android KeyStore backed ciphers.
- *
- * @hide
- */
-abstract class AndroidKeyStoreSignatureSpiBase extends SignatureSpi
-        implements KeyStoreCryptoOperation {
-    private final KeyStore mKeyStore;
-
-    // Fields below are populated by SignatureSpi.engineInitSign/engineInitVerify and KeyStore.begin
-    // and should be preserved after SignatureSpi.engineSign/engineVerify finishes.
-    private boolean mSigning;
-    private AndroidKeyStoreKey mKey;
-
-    /**
-     * Token referencing this operation inside keystore service. It is initialized by
-     * {@code engineInitSign}/{@code engineInitVerify} and is invalidated when
-     * {@code engineSign}/{@code engineVerify} succeeds and on some error conditions in between.
-     */
-    private IBinder mOperationToken;
-    private long mOperationHandle;
-    private KeyStoreCryptoOperationStreamer mMessageStreamer;
-
-    /**
-     * Encountered exception which could not be immediately thrown because it was encountered inside
-     * a method that does not throw checked exception. This exception will be thrown from
-     * {@code engineSign} or {@code engineVerify}. Once such an exception is encountered,
-     * {@code engineUpdate} starts ignoring input data.
-     */
-    private Exception mCachedException;
-
-    AndroidKeyStoreSignatureSpiBase() {
-        mKeyStore = KeyStore.getInstance();
-    }
-
-    @Override
-    protected final void engineInitSign(PrivateKey key) throws InvalidKeyException {
-        engineInitSign(key, null);
-    }
-
-    @Override
-    protected final void engineInitSign(PrivateKey privateKey, SecureRandom random)
-            throws InvalidKeyException {
-        resetAll();
-
-        boolean success = false;
-        try {
-            if (privateKey == null) {
-                throw new InvalidKeyException("Unsupported key: null");
-            }
-            AndroidKeyStoreKey keystoreKey;
-            if (privateKey instanceof AndroidKeyStorePrivateKey) {
-                keystoreKey = (AndroidKeyStoreKey) privateKey;
-            } else {
-                throw new InvalidKeyException("Unsupported private key type: " + privateKey);
-            }
-            mSigning = true;
-            initKey(keystoreKey);
-            appRandom = random;
-            ensureKeystoreOperationInitialized();
-            success = true;
-        } finally {
-            if (!success) {
-                resetAll();
-            }
-        }
-    }
-
-    @Override
-    protected final void engineInitVerify(PublicKey publicKey) throws InvalidKeyException {
-        resetAll();
-
-        boolean success = false;
-        try {
-            if (publicKey == null) {
-                throw new InvalidKeyException("Unsupported key: null");
-            }
-            AndroidKeyStoreKey keystoreKey;
-            if (publicKey instanceof AndroidKeyStorePublicKey) {
-                keystoreKey = (AndroidKeyStorePublicKey) publicKey;
-            } else {
-                throw new InvalidKeyException("Unsupported public key type: " + publicKey);
-            }
-            mSigning = false;
-            initKey(keystoreKey);
-            appRandom = null;
-            ensureKeystoreOperationInitialized();
-            success = true;
-        } finally {
-            if (!success) {
-                resetAll();
-            }
-        }
-    }
-
-    /**
-     * Configures this signature instance to use the provided key.
-     *
-     * @throws InvalidKeyException if the {@code key} is not suitable.
-     */
-    @CallSuper
-    protected void initKey(AndroidKeyStoreKey key) throws InvalidKeyException {
-        mKey = key;
-    }
-
-    /**
-     * Resets this cipher to its pristine pre-init state. This must be equivalent to obtaining a new
-     * cipher instance.
-     *
-     * <p>Subclasses storing additional state should override this method, reset the additional
-     * state, and then chain to superclass.
-     */
-    @CallSuper
-    protected void resetAll() {
-        IBinder operationToken = mOperationToken;
-        if (operationToken != null) {
-            mOperationToken = null;
-            mKeyStore.abort(operationToken);
-        }
-        mSigning = false;
-        mKey = null;
-        appRandom = null;
-        mOperationToken = null;
-        mOperationHandle = 0;
-        mMessageStreamer = null;
-        mCachedException = null;
-    }
-
-    /**
-     * Resets this cipher while preserving the initialized state. This must be equivalent to
-     * rolling back the cipher's state to just after the most recent {@code engineInit} completed
-     * successfully.
-     *
-     * <p>Subclasses storing additional post-init state should override this method, reset the
-     * additional state, and then chain to superclass.
-     */
-    @CallSuper
-    protected void resetWhilePreservingInitState() {
-        IBinder operationToken = mOperationToken;
-        if (operationToken != null) {
-            mOperationToken = null;
-            mKeyStore.abort(operationToken);
-        }
-        mOperationHandle = 0;
-        mMessageStreamer = null;
-        mCachedException = null;
-    }
-
-    private void ensureKeystoreOperationInitialized() throws InvalidKeyException {
-        if (mMessageStreamer != null) {
-            return;
-        }
-        if (mCachedException != null) {
-            return;
-        }
-        if (mKey == null) {
-            throw new IllegalStateException("Not initialized");
-        }
-
-        KeymasterArguments keymasterInputArgs = new KeymasterArguments();
-        addAlgorithmSpecificParametersToBegin(keymasterInputArgs);
-
-        OperationResult opResult = mKeyStore.begin(
-                mKey.getAlias(),
-                mSigning ? KeymasterDefs.KM_PURPOSE_SIGN : KeymasterDefs.KM_PURPOSE_VERIFY,
-                true, // permit aborting this operation if keystore runs out of resources
-                keymasterInputArgs,
-                null, // no additional entropy for begin -- only finish might need some
-                mKey.getUid());
-        if (opResult == null) {
-            throw new KeyStoreConnectException();
-        }
-
-        // Store operation token and handle regardless of the error code returned by KeyStore to
-        // ensure that the operation gets aborted immediately if the code below throws an exception.
-        mOperationToken = opResult.token;
-        mOperationHandle = opResult.operationHandle;
-
-        // If necessary, throw an exception due to KeyStore operation having failed.
-        InvalidKeyException e = KeyStoreCryptoOperationUtils.getInvalidKeyExceptionForInit(
-                mKeyStore, mKey, opResult.resultCode);
-        if (e != null) {
-            throw e;
-        }
-
-        if (mOperationToken == null) {
-            throw new ProviderException("Keystore returned null operation token");
-        }
-        if (mOperationHandle == 0) {
-            throw new ProviderException("Keystore returned invalid operation handle");
-        }
-
-        mMessageStreamer = createMainDataStreamer(mKeyStore, opResult.token);
-    }
-
-    /**
-     * Creates a streamer which sends the message to be signed/verified into the provided KeyStore
-     *
-     * <p>This implementation returns a working streamer.
-     */
-    @NonNull
-    protected KeyStoreCryptoOperationStreamer createMainDataStreamer(
-            KeyStore keyStore, IBinder operationToken) {
-        return new KeyStoreCryptoOperationChunkedStreamer(
-                new KeyStoreCryptoOperationChunkedStreamer.MainDataStream(
-                        keyStore, operationToken));
-    }
-
-    @Override
-    public final long getOperationHandle() {
-        return mOperationHandle;
-    }
-
-    @Override
-    protected final void engineUpdate(byte[] b, int off, int len) throws SignatureException {
-        if (mCachedException != null) {
-            throw new SignatureException(mCachedException);
-        }
-
-        try {
-            ensureKeystoreOperationInitialized();
-        } catch (InvalidKeyException e) {
-            throw new SignatureException(e);
-        }
-
-        if (len == 0) {
-            return;
-        }
-
-        byte[] output;
-        try {
-            output = mMessageStreamer.update(b, off, len);
-        } catch (KeyStoreException e) {
-            throw new SignatureException(e);
-        }
-
-        if (output.length != 0) {
-            throw new ProviderException(
-                    "Update operation unexpectedly produced output: " + output.length + " bytes");
-        }
-    }
-
-    @Override
-    protected final void engineUpdate(byte b) throws SignatureException {
-        engineUpdate(new byte[] {b}, 0, 1);
-    }
-
-    @Override
-    protected final void engineUpdate(ByteBuffer input) {
-        byte[] b;
-        int off;
-        int len = input.remaining();
-        if (input.hasArray()) {
-            b = input.array();
-            off = input.arrayOffset() + input.position();
-            input.position(input.limit());
-        } else {
-            b = new byte[len];
-            off = 0;
-            input.get(b);
-        }
-
-        try {
-            engineUpdate(b, off, len);
-        } catch (SignatureException e) {
-            mCachedException = e;
-        }
-    }
-
-    @Override
-    protected final int engineSign(byte[] out, int outOffset, int outLen)
-            throws SignatureException {
-        return super.engineSign(out, outOffset, outLen);
-    }
-
-    @Override
-    protected final byte[] engineSign() throws SignatureException {
-        if (mCachedException != null) {
-            throw new SignatureException(mCachedException);
-        }
-
-        byte[] signature;
-        try {
-            ensureKeystoreOperationInitialized();
-
-            byte[] additionalEntropy =
-                    KeyStoreCryptoOperationUtils.getRandomBytesToMixIntoKeystoreRng(
-                            appRandom, getAdditionalEntropyAmountForSign());
-            signature = mMessageStreamer.doFinal(
-                    EmptyArray.BYTE, 0, 0,
-                    null, // no signature provided -- it'll be generated by this invocation
-                    additionalEntropy);
-        } catch (InvalidKeyException | KeyStoreException e) {
-            throw new SignatureException(e);
-        }
-
-        resetWhilePreservingInitState();
-        return signature;
-    }
-
-    @Override
-    protected final boolean engineVerify(byte[] signature) throws SignatureException {
-        if (mCachedException != null) {
-            throw new SignatureException(mCachedException);
-        }
-
-        try {
-            ensureKeystoreOperationInitialized();
-        } catch (InvalidKeyException e) {
-            throw new SignatureException(e);
-        }
-
-        boolean verified;
-        try {
-            byte[] output = mMessageStreamer.doFinal(
-                    EmptyArray.BYTE, 0, 0,
-                    signature,
-                    null // no additional entropy needed -- verification is deterministic
-                    );
-            if (output.length != 0) {
-                throw new ProviderException(
-                        "Signature verification unexpected produced output: " + output.length
-                        + " bytes");
-            }
-            verified = true;
-        } catch (KeyStoreException e) {
-            switch (e.getErrorCode()) {
-                case KeymasterDefs.KM_ERROR_VERIFICATION_FAILED:
-                    verified = false;
-                    break;
-                default:
-                    throw new SignatureException(e);
-            }
-        }
-
-        resetWhilePreservingInitState();
-        return verified;
-    }
-
-    @Override
-    protected final boolean engineVerify(byte[] sigBytes, int offset, int len)
-            throws SignatureException {
-        return engineVerify(ArrayUtils.subarray(sigBytes, offset, len));
-    }
-
-    @Deprecated
-    @Override
-    protected final Object engineGetParameter(String param) throws InvalidParameterException {
-        throw new InvalidParameterException();
-    }
-
-    @Deprecated
-    @Override
-    protected final void engineSetParameter(String param, Object value)
-            throws InvalidParameterException {
-        throw new InvalidParameterException();
-    }
-
-    protected final KeyStore getKeyStore() {
-        return mKeyStore;
-    }
-
-    /**
-     * Returns {@code true} if this signature is initialized for signing, {@code false} if this
-     * signature is initialized for verification.
-     */
-    protected final boolean isSigning() {
-        return mSigning;
-    }
-
-    // The methods below need to be implemented by subclasses.
-
-    /**
-     * Returns the amount of additional entropy (in bytes) to be provided to the KeyStore's
-     * {@code finish} operation when generating a signature.
-     *
-     * <p>This value should match (or exceed) the amount of Shannon entropy of the produced
-     * signature assuming the key and the message are known. For example, for ECDSA signature this
-     * should be the size of {@code R}, whereas for the RSA signature with PKCS#1 padding this
-     * should be {@code 0}.
-     */
-    protected abstract int getAdditionalEntropyAmountForSign();
-
-    /**
-     * Invoked to add algorithm-specific parameters for the KeyStore's {@code begin} operation.
-     *
-     * @param keymasterArgs keystore/keymaster arguments to be populated with algorithm-specific
-     *        parameters.
-     */
-    protected abstract void addAlgorithmSpecificParametersToBegin(
-            @NonNull KeymasterArguments keymasterArgs);
-}
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
deleted file mode 100644
index 51c4252..0000000
--- a/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
+++ /dev/null
@@ -1,1112 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.security.keystore;
-
-import android.security.Credentials;
-import android.security.GateKeeper;
-import android.security.KeyStore;
-import android.security.KeyStoreParameter;
-import android.security.keymaster.KeyCharacteristics;
-import android.security.keymaster.KeymasterArguments;
-import android.security.keymaster.KeymasterDefs;
-import android.security.keystore.KeyPermanentlyInvalidatedException;
-import android.security.keystore.KeyProperties;
-import android.security.keystore.KeyProtection;
-import android.security.keystore.SecureKeyImportUnavailableException;
-import android.security.keystore.WrappedKeyEntry;
-import android.util.Log;
-
-import libcore.util.EmptyArray;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.security.Key;
-import java.security.KeyStore.Entry;
-import java.security.KeyStore.LoadStoreParameter;
-import java.security.KeyStore.PrivateKeyEntry;
-import java.security.KeyStore.ProtectionParameter;
-import java.security.KeyStore.SecretKeyEntry;
-import java.security.KeyStoreException;
-import java.security.KeyStoreSpi;
-import java.security.NoSuchAlgorithmException;
-import java.security.PrivateKey;
-import java.security.ProviderException;
-import java.security.PublicKey;
-import java.security.UnrecoverableKeyException;
-import java.security.cert.Certificate;
-import java.security.cert.CertificateEncodingException;
-import java.security.cert.CertificateException;
-import java.security.cert.CertificateFactory;
-import java.security.cert.X509Certificate;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Date;
-import java.util.Enumeration;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Set;
-
-import javax.crypto.SecretKey;
-
-/**
- * A java.security.KeyStore interface for the Android KeyStore. An instance of
- * it can be created via the {@link java.security.KeyStore#getInstance(String)
- * KeyStore.getInstance("AndroidKeyStore")} interface. This returns a
- * java.security.KeyStore backed by this "AndroidKeyStore" implementation.
- * <p>
- * This is built on top of Android's keystore daemon. The convention of alias
- * use is:
- * <p>
- * PrivateKeyEntry will have a Credentials.USER_PRIVATE_KEY as the private key,
- * Credentials.USER_CERTIFICATE as the first certificate in the chain (the one
- * that corresponds to the private key), and then a Credentials.CA_CERTIFICATE
- * entry which will have the rest of the chain concatenated in BER format.
- * <p>
- * TrustedCertificateEntry will just have a Credentials.CA_CERTIFICATE entry
- * with a single certificate.
- *
- * @hide
- */
-public class AndroidKeyStoreSpi extends KeyStoreSpi {
-    public static final String NAME = "AndroidKeyStore";
-
-    private KeyStore mKeyStore;
-    private int mUid = KeyStore.UID_SELF;
-
-    @Override
-    public Key engineGetKey(String alias, char[] password) throws NoSuchAlgorithmException,
-            UnrecoverableKeyException {
-        String userKeyAlias = Credentials.USER_PRIVATE_KEY + alias;
-        AndroidKeyStoreKey key;
-        if (!mKeyStore.contains(userKeyAlias, mUid)) {
-            // try legacy prefix for backward compatibility
-            userKeyAlias = Credentials.USER_SECRET_KEY + alias;
-            if (!mKeyStore.contains(userKeyAlias, mUid)) return null;
-        }
-        try {
-            key = AndroidKeyStoreProvider.loadAndroidKeyStoreKeyFromKeystore(mKeyStore,
-                                                                             userKeyAlias,
-                                                                             mUid);
-        } catch (KeyPermanentlyInvalidatedException e) {
-            throw new UnrecoverableKeyException(e.getMessage());
-        }
-        return key;
-    }
-
-    @Override
-    public Certificate[] engineGetCertificateChain(String alias) {
-        if (alias == null) {
-            throw new NullPointerException("alias == null");
-        }
-
-        final X509Certificate leaf = (X509Certificate) engineGetCertificate(alias);
-        if (leaf == null) {
-            return null;
-        }
-
-        final Certificate[] caList;
-
-        // Suppress the key not found warning for this call. It seems that this error is exclusively
-        // being thrown when there is a self signed certificate chain, so when the keystore service
-        // attempts to query for the CA details, it obviously fails to find them and returns a
-        // key not found exception. This is WAI, and throwing a stack trace here can be very
-        // misleading since the trace is not clear.
-        final byte[] caBytes = mKeyStore.get(Credentials.CA_CERTIFICATE + alias,
-                                             mUid,
-                                             true /* suppressKeyNotFoundWarning */);
-        if (caBytes != null) {
-            final Collection<X509Certificate> caChain = toCertificates(caBytes);
-
-            caList = new Certificate[caChain.size() + 1];
-
-            final Iterator<X509Certificate> it = caChain.iterator();
-            int i = 1;
-            while (it.hasNext()) {
-                caList[i++] = it.next();
-            }
-        } else {
-            caList = new Certificate[1];
-        }
-
-        caList[0] = leaf;
-
-        return caList;
-    }
-
-    @Override
-    public Certificate engineGetCertificate(String alias) {
-        if (alias == null) {
-            throw new NullPointerException("alias == null");
-        }
-
-        byte[] encodedCert = mKeyStore.get(Credentials.USER_CERTIFICATE + alias, mUid);
-        if (encodedCert != null) {
-            return getCertificateForPrivateKeyEntry(alias, encodedCert);
-        }
-
-        encodedCert = mKeyStore.get(Credentials.CA_CERTIFICATE + alias, mUid);
-        if (encodedCert != null) {
-            return getCertificateForTrustedCertificateEntry(encodedCert);
-        }
-
-        // This entry/alias does not contain a certificate.
-        return null;
-    }
-
-    private Certificate getCertificateForTrustedCertificateEntry(byte[] encodedCert) {
-        // For this certificate there shouldn't be a private key in this KeyStore entry. Thus,
-        // there's no need to wrap this certificate as opposed to the certificate associated with
-        // a private key entry.
-        return toCertificate(encodedCert);
-    }
-
-    private Certificate getCertificateForPrivateKeyEntry(String alias, byte[] encodedCert) {
-        // All crypto algorithms offered by Android Keystore for its private keys must also
-        // be offered for the corresponding public keys stored in the Android Keystore. The
-        // complication is that the underlying keystore service operates only on full key pairs,
-        // rather than just public keys or private keys. As a result, Android Keystore-backed
-        // crypto can only be offered for public keys for which keystore contains the
-        // corresponding private key. This is not the case for certificate-only entries (e.g.,
-        // trusted certificates).
-        //
-        // getCertificate().getPublicKey() is the only way to obtain the public key
-        // corresponding to the private key stored in the KeyStore. Thus, we need to make sure
-        // that the returned public key points to the underlying key pair / private key
-        // when available.
-
-        X509Certificate cert = toCertificate(encodedCert);
-        if (cert == null) {
-            // Failed to parse the certificate.
-            return null;
-        }
-
-        String privateKeyAlias = Credentials.USER_PRIVATE_KEY + alias;
-        if (mKeyStore.contains(privateKeyAlias, mUid)) {
-            // As expected, keystore contains the private key corresponding to this public key. Wrap
-            // the certificate so that its getPublicKey method returns an Android Keystore
-            // PublicKey. This key will delegate crypto operations involving this public key to
-            // Android Keystore when higher-priority providers do not offer these crypto
-            // operations for this key.
-            return wrapIntoKeyStoreCertificate(privateKeyAlias, mUid, cert);
-        } else {
-            // This KeyStore entry/alias is supposed to contain the private key corresponding to
-            // the public key in this certificate, but it does not for some reason. It's probably a
-            // bug. Let other providers handle crypto operations involving the public key returned
-            // by this certificate's getPublicKey.
-            return cert;
-        }
-    }
-
-    /**
-     * Wraps the provided cerificate into {@link KeyStoreX509Certificate} so that the public key
-     * returned by the certificate contains information about the alias of the private key in
-     * keystore. This is needed so that Android Keystore crypto operations using public keys can
-     * find out which key alias to use. These operations cannot work without an alias.
-     */
-    private static KeyStoreX509Certificate wrapIntoKeyStoreCertificate(
-            String privateKeyAlias, int uid, X509Certificate certificate) {
-        return (certificate != null)
-                ? new KeyStoreX509Certificate(privateKeyAlias, uid, certificate) : null;
-    }
-
-    private static X509Certificate toCertificate(byte[] bytes) {
-        try {
-            final CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
-            return (X509Certificate) certFactory.generateCertificate(
-                    new ByteArrayInputStream(bytes));
-        } catch (CertificateException e) {
-            Log.w(NAME, "Couldn't parse certificate in keystore", e);
-            return null;
-        }
-    }
-
-    @SuppressWarnings("unchecked")
-    private static Collection<X509Certificate> toCertificates(byte[] bytes) {
-        try {
-            final CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
-            return (Collection<X509Certificate>) certFactory.generateCertificates(
-                            new ByteArrayInputStream(bytes));
-        } catch (CertificateException e) {
-            Log.w(NAME, "Couldn't parse certificates in keystore", e);
-            return new ArrayList<X509Certificate>();
-        }
-    }
-
-    private Date getModificationDate(String alias) {
-        final long epochMillis = mKeyStore.getmtime(alias, mUid);
-        if (epochMillis == -1L) {
-            return null;
-        }
-
-        return new Date(epochMillis);
-    }
-
-    @Override
-    public Date engineGetCreationDate(String alias) {
-        if (alias == null) {
-            throw new NullPointerException("alias == null");
-        }
-
-        Date d = getModificationDate(Credentials.USER_PRIVATE_KEY + alias);
-        if (d != null) {
-            return d;
-        }
-
-        d = getModificationDate(Credentials.USER_SECRET_KEY + alias);
-        if (d != null) {
-            return d;
-        }
-
-        d = getModificationDate(Credentials.USER_CERTIFICATE + alias);
-        if (d != null) {
-            return d;
-        }
-
-        return getModificationDate(Credentials.CA_CERTIFICATE + alias);
-    }
-
-    @Override
-    public void engineSetKeyEntry(String alias, Key key, char[] password, Certificate[] chain)
-            throws KeyStoreException {
-        if ((password != null) && (password.length > 0)) {
-            throw new KeyStoreException("entries cannot be protected with passwords");
-        }
-
-        if (key instanceof PrivateKey) {
-            setPrivateKeyEntry(alias, (PrivateKey) key, chain, null);
-        } else if (key instanceof SecretKey) {
-            setSecretKeyEntry(alias, (SecretKey) key, null);
-        } else {
-            throw new KeyStoreException("Only PrivateKey and SecretKey are supported");
-        }
-    }
-
-    private static KeyProtection getLegacyKeyProtectionParameter(PrivateKey key)
-            throws KeyStoreException {
-        String keyAlgorithm = key.getAlgorithm();
-        KeyProtection.Builder specBuilder;
-        if (KeyProperties.KEY_ALGORITHM_EC.equalsIgnoreCase(keyAlgorithm)) {
-            specBuilder =
-                    new KeyProtection.Builder(
-                            KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY);
-            // Authorized to be used with any digest (including no digest).
-            // MD5 was never offered for Android Keystore for ECDSA.
-            specBuilder.setDigests(
-                    KeyProperties.DIGEST_NONE,
-                    KeyProperties.DIGEST_SHA1,
-                    KeyProperties.DIGEST_SHA224,
-                    KeyProperties.DIGEST_SHA256,
-                    KeyProperties.DIGEST_SHA384,
-                    KeyProperties.DIGEST_SHA512);
-        } else if (KeyProperties.KEY_ALGORITHM_RSA.equalsIgnoreCase(keyAlgorithm)) {
-            specBuilder =
-                    new KeyProtection.Builder(
-                            KeyProperties.PURPOSE_ENCRYPT
-                            | KeyProperties.PURPOSE_DECRYPT
-                            | KeyProperties.PURPOSE_SIGN
-                            | KeyProperties.PURPOSE_VERIFY);
-            // Authorized to be used with any digest (including no digest).
-            specBuilder.setDigests(
-                    KeyProperties.DIGEST_NONE,
-                    KeyProperties.DIGEST_MD5,
-                    KeyProperties.DIGEST_SHA1,
-                    KeyProperties.DIGEST_SHA224,
-                    KeyProperties.DIGEST_SHA256,
-                    KeyProperties.DIGEST_SHA384,
-                    KeyProperties.DIGEST_SHA512);
-            // Authorized to be used with any encryption and signature padding
-            // schemes (including no padding).
-            specBuilder.setEncryptionPaddings(
-                    KeyProperties.ENCRYPTION_PADDING_NONE,
-                    KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1,
-                    KeyProperties.ENCRYPTION_PADDING_RSA_OAEP);
-            specBuilder.setSignaturePaddings(
-                    KeyProperties.SIGNATURE_PADDING_RSA_PKCS1,
-                    KeyProperties.SIGNATURE_PADDING_RSA_PSS);
-            // Disable randomized encryption requirement to support encryption
-            // padding NONE above.
-            specBuilder.setRandomizedEncryptionRequired(false);
-        } else {
-            throw new KeyStoreException("Unsupported key algorithm: " + keyAlgorithm);
-        }
-        specBuilder.setUserAuthenticationRequired(false);
-
-        return specBuilder.build();
-    }
-
-    private void setPrivateKeyEntry(String alias, PrivateKey key, Certificate[] chain,
-            java.security.KeyStore.ProtectionParameter param) throws KeyStoreException {
-        int flags = 0;
-        KeyProtection spec;
-        if (param == null) {
-            spec = getLegacyKeyProtectionParameter(key);
-        } else if (param instanceof KeyStoreParameter) {
-            spec = getLegacyKeyProtectionParameter(key);
-            KeyStoreParameter legacySpec = (KeyStoreParameter) param;
-            if (legacySpec.isEncryptionRequired()) {
-                flags = KeyStore.FLAG_ENCRYPTED;
-            }
-        } else if (param instanceof KeyProtection) {
-            spec = (KeyProtection) param;
-            if (spec.isCriticalToDeviceEncryption()) {
-                flags |= KeyStore.FLAG_CRITICAL_TO_DEVICE_ENCRYPTION;
-            }
-
-            if (spec.isStrongBoxBacked()) {
-                flags |= KeyStore.FLAG_STRONGBOX;
-            }
-        } else {
-            throw new KeyStoreException(
-                    "Unsupported protection parameter class:" + param.getClass().getName()
-                    + ". Supported: " + KeyProtection.class.getName() + ", "
-                    + KeyStoreParameter.class.getName());
-        }
-
-        // Make sure the chain exists since this is a PrivateKey
-        if ((chain == null) || (chain.length == 0)) {
-            throw new KeyStoreException("Must supply at least one Certificate with PrivateKey");
-        }
-
-        // Do chain type checking.
-        X509Certificate[] x509chain = new X509Certificate[chain.length];
-        for (int i = 0; i < chain.length; i++) {
-            if (!"X.509".equals(chain[i].getType())) {
-                throw new KeyStoreException("Certificates must be in X.509 format: invalid cert #"
-                        + i);
-            }
-
-            if (!(chain[i] instanceof X509Certificate)) {
-                throw new KeyStoreException("Certificates must be in X.509 format: invalid cert #"
-                        + i);
-            }
-
-            x509chain[i] = (X509Certificate) chain[i];
-        }
-
-        final byte[] userCertBytes;
-        try {
-            userCertBytes = x509chain[0].getEncoded();
-        } catch (CertificateEncodingException e) {
-            throw new KeyStoreException("Failed to encode certificate #0", e);
-        }
-
-        /*
-         * If we have a chain, store it in the CA certificate slot for this
-         * alias as concatenated DER-encoded certificates. These can be
-         * deserialized by {@link CertificateFactory#generateCertificates}.
-         */
-        final byte[] chainBytes;
-        if (chain.length > 1) {
-            /*
-             * The chain is passed in as {user_cert, ca_cert_1, ca_cert_2, ...}
-             * so we only need the certificates starting at index 1.
-             */
-            final byte[][] certsBytes = new byte[x509chain.length - 1][];
-            int totalCertLength = 0;
-            for (int i = 0; i < certsBytes.length; i++) {
-                try {
-                    certsBytes[i] = x509chain[i + 1].getEncoded();
-                    totalCertLength += certsBytes[i].length;
-                } catch (CertificateEncodingException e) {
-                    throw new KeyStoreException("Failed to encode certificate #" + i, e);
-                }
-            }
-
-            /*
-             * Serialize this into one byte array so we can later call
-             * CertificateFactory#generateCertificates to recover them.
-             */
-            chainBytes = new byte[totalCertLength];
-            int outputOffset = 0;
-            for (int i = 0; i < certsBytes.length; i++) {
-                final int certLength = certsBytes[i].length;
-                System.arraycopy(certsBytes[i], 0, chainBytes, outputOffset, certLength);
-                outputOffset += certLength;
-                certsBytes[i] = null;
-            }
-        } else {
-            chainBytes = null;
-        }
-
-        final String pkeyAlias;
-        if (key instanceof AndroidKeyStorePrivateKey) {
-            pkeyAlias = ((AndroidKeyStoreKey) key).getAlias();
-        } else {
-            pkeyAlias = null;
-        }
-
-        byte[] pkcs8EncodedPrivateKeyBytes;
-        KeymasterArguments importArgs;
-        final boolean shouldReplacePrivateKey;
-        if (pkeyAlias != null && pkeyAlias.startsWith(Credentials.USER_PRIVATE_KEY)) {
-            final String keySubalias = pkeyAlias.substring(Credentials.USER_PRIVATE_KEY.length());
-            if (!alias.equals(keySubalias)) {
-                throw new KeyStoreException("Can only replace keys with same alias: " + alias
-                        + " != " + keySubalias);
-            }
-            shouldReplacePrivateKey = false;
-            importArgs = null;
-            pkcs8EncodedPrivateKeyBytes = null;
-        } else {
-            shouldReplacePrivateKey = true;
-            // Make sure the PrivateKey format is the one we support.
-            final String keyFormat = key.getFormat();
-            if ((keyFormat == null) || (!"PKCS#8".equals(keyFormat))) {
-                throw new KeyStoreException(
-                        "Unsupported private key export format: " + keyFormat
-                        + ". Only private keys which export their key material in PKCS#8 format are"
-                        + " supported.");
-            }
-
-            // Make sure we can actually encode the key.
-            pkcs8EncodedPrivateKeyBytes = key.getEncoded();
-            if (pkcs8EncodedPrivateKeyBytes == null) {
-                throw new KeyStoreException("Private key did not export any key material");
-            }
-
-            importArgs = new KeymasterArguments();
-            try {
-                importArgs.addEnum(KeymasterDefs.KM_TAG_ALGORITHM,
-                        KeyProperties.KeyAlgorithm.toKeymasterAsymmetricKeyAlgorithm(
-                                key.getAlgorithm()));
-                @KeyProperties.PurposeEnum int purposes = spec.getPurposes();
-                importArgs.addEnums(KeymasterDefs.KM_TAG_PURPOSE,
-                        KeyProperties.Purpose.allToKeymaster(purposes));
-                if (spec.isDigestsSpecified()) {
-                    importArgs.addEnums(KeymasterDefs.KM_TAG_DIGEST,
-                            KeyProperties.Digest.allToKeymaster(spec.getDigests()));
-                }
-
-                importArgs.addEnums(KeymasterDefs.KM_TAG_BLOCK_MODE,
-                        KeyProperties.BlockMode.allToKeymaster(spec.getBlockModes()));
-                int[] keymasterEncryptionPaddings =
-                        KeyProperties.EncryptionPadding.allToKeymaster(
-                                spec.getEncryptionPaddings());
-                if (((purposes & KeyProperties.PURPOSE_ENCRYPT) != 0)
-                        && (spec.isRandomizedEncryptionRequired())) {
-                    for (int keymasterPadding : keymasterEncryptionPaddings) {
-                        if (!KeymasterUtils
-                                .isKeymasterPaddingSchemeIndCpaCompatibleWithAsymmetricCrypto(
-                                        keymasterPadding)) {
-                            throw new KeyStoreException(
-                                    "Randomized encryption (IND-CPA) required but is violated by"
-                                    + " encryption padding mode: "
-                                    + KeyProperties.EncryptionPadding.fromKeymaster(
-                                            keymasterPadding)
-                                    + ". See KeyProtection documentation.");
-                        }
-                    }
-                }
-                importArgs.addEnums(KeymasterDefs.KM_TAG_PADDING, keymasterEncryptionPaddings);
-                importArgs.addEnums(KeymasterDefs.KM_TAG_PADDING,
-                        KeyProperties.SignaturePadding.allToKeymaster(spec.getSignaturePaddings()));
-                KeymasterUtils.addUserAuthArgs(importArgs, spec);
-                importArgs.addDateIfNotNull(KeymasterDefs.KM_TAG_ACTIVE_DATETIME,
-                        spec.getKeyValidityStart());
-                importArgs.addDateIfNotNull(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME,
-                        spec.getKeyValidityForOriginationEnd());
-                importArgs.addDateIfNotNull(KeymasterDefs.KM_TAG_USAGE_EXPIRE_DATETIME,
-                        spec.getKeyValidityForConsumptionEnd());
-            } catch (IllegalArgumentException | IllegalStateException e) {
-                throw new KeyStoreException(e);
-            }
-        }
-
-
-        boolean success = false;
-        try {
-            // Store the private key, if necessary
-            if (shouldReplacePrivateKey) {
-                // Delete the stored private key and any related entries before importing the
-                // provided key
-                Credentials.deleteAllTypesForAlias(mKeyStore, alias, mUid);
-                KeyCharacteristics resultingKeyCharacteristics = new KeyCharacteristics();
-                int errorCode = mKeyStore.importKey(
-                        Credentials.USER_PRIVATE_KEY + alias,
-                        importArgs,
-                        KeymasterDefs.KM_KEY_FORMAT_PKCS8,
-                        pkcs8EncodedPrivateKeyBytes,
-                        mUid,
-                        flags,
-                        resultingKeyCharacteristics);
-                if (errorCode != KeyStore.NO_ERROR) {
-                    throw new KeyStoreException("Failed to store private key",
-                            KeyStore.getKeyStoreException(errorCode));
-                }
-            } else {
-                // Keep the stored private key around -- delete all other entry types
-                Credentials.deleteCertificateTypesForAlias(mKeyStore, alias, mUid);
-                Credentials.deleteLegacyKeyForAlias(mKeyStore, alias, mUid);
-            }
-
-            // Store the leaf certificate
-            int errorCode = mKeyStore.insert(Credentials.USER_CERTIFICATE + alias, userCertBytes,
-                    mUid, flags);
-            if (errorCode != KeyStore.NO_ERROR) {
-                throw new KeyStoreException("Failed to store certificate #0",
-                        KeyStore.getKeyStoreException(errorCode));
-            }
-
-            // Store the certificate chain
-            errorCode = mKeyStore.insert(Credentials.CA_CERTIFICATE + alias, chainBytes,
-                    mUid, flags);
-            if (errorCode != KeyStore.NO_ERROR) {
-                throw new KeyStoreException("Failed to store certificate chain",
-                        KeyStore.getKeyStoreException(errorCode));
-            }
-            success = true;
-        } finally {
-            if (!success) {
-                if (shouldReplacePrivateKey) {
-                    Credentials.deleteAllTypesForAlias(mKeyStore, alias, mUid);
-                } else {
-                    Credentials.deleteCertificateTypesForAlias(mKeyStore, alias, mUid);
-                    Credentials.deleteLegacyKeyForAlias(mKeyStore, alias, mUid);
-                }
-            }
-        }
-    }
-
-    private void setSecretKeyEntry(String entryAlias, SecretKey key,
-            java.security.KeyStore.ProtectionParameter param)
-            throws KeyStoreException {
-        if ((param != null) && (!(param instanceof KeyProtection))) {
-            throw new KeyStoreException(
-                    "Unsupported protection parameter class: " + param.getClass().getName()
-                    + ". Supported: " + KeyProtection.class.getName());
-        }
-        KeyProtection params = (KeyProtection) param;
-
-        if (key instanceof AndroidKeyStoreSecretKey) {
-            // KeyStore-backed secret key. It cannot be duplicated into another entry and cannot
-            // overwrite its own entry.
-            String keyAliasInKeystore = ((AndroidKeyStoreSecretKey) key).getAlias();
-            if (keyAliasInKeystore == null) {
-                throw new KeyStoreException("KeyStore-backed secret key does not have an alias");
-            }
-            String keyAliasPrefix = Credentials.USER_PRIVATE_KEY;
-            if (!keyAliasInKeystore.startsWith(keyAliasPrefix)) {
-                // try legacy prefix
-                keyAliasPrefix = Credentials.USER_SECRET_KEY;
-                if (!keyAliasInKeystore.startsWith(keyAliasPrefix)) {
-                    throw new KeyStoreException("KeyStore-backed secret key has invalid alias: "
-                            + keyAliasInKeystore);
-                }
-            }
-            String keyEntryAlias =
-                    keyAliasInKeystore.substring(keyAliasPrefix.length());
-            if (!entryAlias.equals(keyEntryAlias)) {
-                throw new KeyStoreException("Can only replace KeyStore-backed keys with same"
-                        + " alias: " + entryAlias + " != " + keyEntryAlias);
-            }
-            // This is the entry where this key is already stored. No need to do anything.
-            if (params != null) {
-                throw new KeyStoreException("Modifying KeyStore-backed key using protection"
-                        + " parameters not supported");
-            }
-            return;
-        }
-
-        if (params == null) {
-            throw new KeyStoreException(
-                    "Protection parameters must be specified when importing a symmetric key");
-        }
-
-        // Not a KeyStore-backed secret key -- import its key material into keystore.
-        String keyExportFormat = key.getFormat();
-        if (keyExportFormat == null) {
-            throw new KeyStoreException(
-                    "Only secret keys that export their key material are supported");
-        } else if (!"RAW".equals(keyExportFormat)) {
-            throw new KeyStoreException(
-                    "Unsupported secret key material export format: " + keyExportFormat);
-        }
-        byte[] keyMaterial = key.getEncoded();
-        if (keyMaterial == null) {
-            throw new KeyStoreException("Key did not export its key material despite supporting"
-                    + " RAW format export");
-        }
-
-        KeymasterArguments args = new KeymasterArguments();
-        try {
-            int keymasterAlgorithm =
-                    KeyProperties.KeyAlgorithm.toKeymasterSecretKeyAlgorithm(key.getAlgorithm());
-            args.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, keymasterAlgorithm);
-
-            int[] keymasterDigests;
-            if (keymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_HMAC) {
-                // JCA HMAC key algorithm implies a digest (e.g., HmacSHA256 key algorithm
-                // implies SHA-256 digest). Because keymaster HMAC key is authorized only for one
-                // digest, we don't let import parameters override the digest implied by the key.
-                // If the parameters specify digests at all, they must specify only one digest, the
-                // only implied by key algorithm.
-                int keymasterImpliedDigest =
-                        KeyProperties.KeyAlgorithm.toKeymasterDigest(key.getAlgorithm());
-                if (keymasterImpliedDigest == -1) {
-                    throw new ProviderException(
-                            "HMAC key algorithm digest unknown for key algorithm "
-                                    + key.getAlgorithm());
-                }
-                keymasterDigests = new int[] {keymasterImpliedDigest};
-                if (params.isDigestsSpecified()) {
-                    // Digest(s) explicitly specified in params -- check that the list consists of
-                    // exactly one digest, the one implied by key algorithm.
-                    int[] keymasterDigestsFromParams =
-                            KeyProperties.Digest.allToKeymaster(params.getDigests());
-                    if ((keymasterDigestsFromParams.length != 1)
-                            || (keymasterDigestsFromParams[0] != keymasterImpliedDigest)) {
-                        throw new KeyStoreException(
-                                "Unsupported digests specification: "
-                                + Arrays.asList(params.getDigests()) + ". Only "
-                                + KeyProperties.Digest.fromKeymaster(keymasterImpliedDigest)
-                                + " supported for HMAC key algorithm " + key.getAlgorithm());
-                    }
-                }
-            } else {
-                // Key algorithm does not imply a digest.
-                if (params.isDigestsSpecified()) {
-                    keymasterDigests = KeyProperties.Digest.allToKeymaster(params.getDigests());
-                } else {
-                    keymasterDigests = EmptyArray.INT;
-                }
-            }
-            args.addEnums(KeymasterDefs.KM_TAG_DIGEST, keymasterDigests);
-
-            @KeyProperties.PurposeEnum int purposes = params.getPurposes();
-            int[] keymasterBlockModes =
-                    KeyProperties.BlockMode.allToKeymaster(params.getBlockModes());
-            if (((purposes & KeyProperties.PURPOSE_ENCRYPT) != 0)
-                    && (params.isRandomizedEncryptionRequired())) {
-                for (int keymasterBlockMode : keymasterBlockModes) {
-                    if (!KeymasterUtils.isKeymasterBlockModeIndCpaCompatibleWithSymmetricCrypto(
-                            keymasterBlockMode)) {
-                        throw new KeyStoreException(
-                                "Randomized encryption (IND-CPA) required but may be violated by"
-                                + " block mode: "
-                                + KeyProperties.BlockMode.fromKeymaster(keymasterBlockMode)
-                                + ". See KeyProtection documentation.");
-                    }
-                }
-            }
-            args.addEnums(KeymasterDefs.KM_TAG_PURPOSE,
-                    KeyProperties.Purpose.allToKeymaster(purposes));
-            args.addEnums(KeymasterDefs.KM_TAG_BLOCK_MODE, keymasterBlockModes);
-            if (params.getSignaturePaddings().length > 0) {
-                throw new KeyStoreException("Signature paddings not supported for symmetric keys");
-            }
-            int[] keymasterPaddings = KeyProperties.EncryptionPadding.allToKeymaster(
-                    params.getEncryptionPaddings());
-            args.addEnums(KeymasterDefs.KM_TAG_PADDING, keymasterPaddings);
-            KeymasterUtils.addUserAuthArgs(args, params);
-            KeymasterUtils.addMinMacLengthAuthorizationIfNecessary(
-                    args,
-                    keymasterAlgorithm,
-                    keymasterBlockModes,
-                    keymasterDigests);
-            args.addDateIfNotNull(KeymasterDefs.KM_TAG_ACTIVE_DATETIME,
-                    params.getKeyValidityStart());
-            args.addDateIfNotNull(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME,
-                    params.getKeyValidityForOriginationEnd());
-            args.addDateIfNotNull(KeymasterDefs.KM_TAG_USAGE_EXPIRE_DATETIME,
-                    params.getKeyValidityForConsumptionEnd());
-
-            if (((purposes & KeyProperties.PURPOSE_ENCRYPT) != 0)
-                    && (!params.isRandomizedEncryptionRequired())) {
-                // Permit caller-provided IV when encrypting with this key
-                args.addBoolean(KeymasterDefs.KM_TAG_CALLER_NONCE);
-            }
-        } catch (IllegalArgumentException | IllegalStateException e) {
-            throw new KeyStoreException(e);
-        }
-        int flags = 0;
-        if (params.isCriticalToDeviceEncryption()) {
-            flags |= KeyStore.FLAG_CRITICAL_TO_DEVICE_ENCRYPTION;
-        }
-        if (params.isStrongBoxBacked()) {
-            flags |= KeyStore.FLAG_STRONGBOX;
-        }
-
-        Credentials.deleteAllTypesForAlias(mKeyStore, entryAlias, mUid);
-        String keyAliasInKeystore = Credentials.USER_PRIVATE_KEY + entryAlias;
-        int errorCode = mKeyStore.importKey(
-                keyAliasInKeystore,
-                args,
-                KeymasterDefs.KM_KEY_FORMAT_RAW,
-                keyMaterial,
-                mUid,
-                flags,
-                new KeyCharacteristics());
-        if (errorCode != KeyStore.NO_ERROR) {
-            throw new KeyStoreException("Failed to import secret key. Keystore error code: "
-                + errorCode);
-        }
-    }
-
-    private void setWrappedKeyEntry(String alias, WrappedKeyEntry entry,
-            java.security.KeyStore.ProtectionParameter param) throws KeyStoreException {
-        if (param != null) {
-            throw new KeyStoreException("Protection parameters are specified inside wrapped keys");
-        }
-
-        byte[] maskingKey = new byte[32];
-
-
-        KeymasterArguments args = new KeymasterArguments();
-        String[] parts = entry.getTransformation().split("/");
-
-        String algorithm = parts[0];
-        if (KeyProperties.KEY_ALGORITHM_RSA.equalsIgnoreCase(algorithm)) {
-            args.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_RSA);
-        } else if (KeyProperties.KEY_ALGORITHM_EC.equalsIgnoreCase(algorithm)) {
-            args.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_RSA);
-        }
-
-        if (parts.length > 1) {
-            String mode = parts[1];
-            if (KeyProperties.BLOCK_MODE_ECB.equalsIgnoreCase(mode)) {
-                args.addEnums(KeymasterDefs.KM_TAG_BLOCK_MODE, KeymasterDefs.KM_MODE_ECB);
-            } else if (KeyProperties.BLOCK_MODE_CBC.equalsIgnoreCase(mode)) {
-                args.addEnums(KeymasterDefs.KM_TAG_BLOCK_MODE, KeymasterDefs.KM_MODE_CBC);
-            } else if (KeyProperties.BLOCK_MODE_CTR.equalsIgnoreCase(mode)) {
-                args.addEnums(KeymasterDefs.KM_TAG_BLOCK_MODE, KeymasterDefs.KM_MODE_CTR);
-            } else if (KeyProperties.BLOCK_MODE_GCM.equalsIgnoreCase(mode)) {
-                args.addEnums(KeymasterDefs.KM_TAG_BLOCK_MODE, KeymasterDefs.KM_MODE_GCM);
-            }
-        }
-
-        if (parts.length > 2) {
-            String padding = parts[2];
-            if (KeyProperties.ENCRYPTION_PADDING_NONE.equalsIgnoreCase(padding)) {
-                // Noop
-            } else if (KeyProperties.ENCRYPTION_PADDING_PKCS7.equalsIgnoreCase(padding)) {
-                args.addEnums(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_PKCS7);
-            } else if (KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1.equalsIgnoreCase(padding)) {
-                args.addEnums(KeymasterDefs.KM_TAG_PADDING,
-                    KeymasterDefs.KM_PAD_RSA_PKCS1_1_5_ENCRYPT);
-            } else if (KeyProperties.ENCRYPTION_PADDING_RSA_OAEP.equalsIgnoreCase(padding)) {
-                args.addEnums(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_RSA_OAEP);
-            }
-        }
-
-        KeyGenParameterSpec spec = (KeyGenParameterSpec) entry.getAlgorithmParameterSpec();
-        if (spec.isDigestsSpecified()) {
-            String digest = spec.getDigests()[0];
-            if (KeyProperties.DIGEST_NONE.equalsIgnoreCase(digest)) {
-                // Noop
-            } else if (KeyProperties.DIGEST_MD5.equalsIgnoreCase(digest)) {
-                args.addEnums(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_MD5);
-            } else if (KeyProperties.DIGEST_SHA1.equalsIgnoreCase(digest)) {
-                args.addEnums(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_SHA1);
-            } else if (KeyProperties.DIGEST_SHA224.equalsIgnoreCase(digest)) {
-                args.addEnums(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_SHA_2_224);
-            } else if (KeyProperties.DIGEST_SHA256.equalsIgnoreCase(digest)) {
-                args.addEnums(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_SHA_2_256);
-            } else if (KeyProperties.DIGEST_SHA384.equalsIgnoreCase(digest)) {
-                args.addEnums(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_SHA_2_384);
-            } else if (KeyProperties.DIGEST_SHA512.equalsIgnoreCase(digest)) {
-                args.addEnums(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_SHA_2_512);
-            }
-        }
-
-        int errorCode = mKeyStore.importWrappedKey(
-            Credentials.USER_PRIVATE_KEY + alias,
-            entry.getWrappedKeyBytes(),
-            Credentials.USER_PRIVATE_KEY + entry.getWrappingKeyAlias(),
-            maskingKey,
-            args,
-            GateKeeper.getSecureUserId(),
-            0, // FIXME fingerprint id?
-            mUid,
-            new KeyCharacteristics());
-        if (errorCode == KeymasterDefs.KM_ERROR_UNIMPLEMENTED) {
-          throw new SecureKeyImportUnavailableException("Could not import wrapped key");
-        } else if (errorCode != KeyStore.NO_ERROR) {
-            throw new KeyStoreException("Failed to import wrapped key. Keystore error code: "
-                + errorCode);
-        }
-    }
-
-    @Override
-    public void engineSetKeyEntry(String alias, byte[] userKey, Certificate[] chain)
-            throws KeyStoreException {
-        throw new KeyStoreException("Operation not supported because key encoding is unknown");
-    }
-
-    @Override
-    public void engineSetCertificateEntry(String alias, Certificate cert) throws KeyStoreException {
-        if (isKeyEntry(alias)) {
-            throw new KeyStoreException("Entry exists and is not a trusted certificate");
-        }
-
-        // We can't set something to null.
-        if (cert == null) {
-            throw new NullPointerException("cert == null");
-        }
-
-        final byte[] encoded;
-        try {
-            encoded = cert.getEncoded();
-        } catch (CertificateEncodingException e) {
-            throw new KeyStoreException(e);
-        }
-
-        if (!mKeyStore.put(Credentials.CA_CERTIFICATE + alias, encoded, mUid, KeyStore.FLAG_NONE)) {
-            throw new KeyStoreException("Couldn't insert certificate; is KeyStore initialized?");
-        }
-    }
-
-    @Override
-    public void engineDeleteEntry(String alias) throws KeyStoreException {
-        if (!Credentials.deleteAllTypesForAlias(mKeyStore, alias, mUid)) {
-            throw new KeyStoreException("Failed to delete entry: " + alias);
-        }
-    }
-
-    private Set<String> getUniqueAliases() {
-        final String[] rawAliases = mKeyStore.list("", mUid);
-        if (rawAliases == null) {
-            return new HashSet<String>();
-        }
-
-        final Set<String> aliases = new HashSet<String>(rawAliases.length);
-        for (String alias : rawAliases) {
-            final int idx = alias.indexOf('_');
-            if ((idx == -1) || (alias.length() <= idx)) {
-                Log.e(NAME, "invalid alias: " + alias);
-                continue;
-            }
-
-            aliases.add(new String(alias.substring(idx + 1)));
-        }
-
-        return aliases;
-    }
-
-    @Override
-    public Enumeration<String> engineAliases() {
-        return Collections.enumeration(getUniqueAliases());
-    }
-
-    @Override
-    public boolean engineContainsAlias(String alias) {
-        if (alias == null) {
-            throw new NullPointerException("alias == null");
-        }
-
-        return mKeyStore.contains(Credentials.USER_PRIVATE_KEY + alias, mUid)
-                || mKeyStore.contains(Credentials.USER_SECRET_KEY + alias, mUid)
-                || mKeyStore.contains(Credentials.USER_CERTIFICATE + alias, mUid)
-                || mKeyStore.contains(Credentials.CA_CERTIFICATE + alias, mUid);
-    }
-
-    @Override
-    public int engineSize() {
-        return getUniqueAliases().size();
-    }
-
-    @Override
-    public boolean engineIsKeyEntry(String alias) {
-        return isKeyEntry(alias);
-    }
-
-    private boolean isKeyEntry(String alias) {
-        return mKeyStore.contains(Credentials.USER_PRIVATE_KEY + alias, mUid) ||
-                mKeyStore.contains(Credentials.USER_SECRET_KEY + alias, mUid);
-    }
-
-
-    private boolean isCertificateEntry(String alias) {
-        if (alias == null) {
-            throw new NullPointerException("alias == null");
-        }
-
-        return mKeyStore.contains(Credentials.CA_CERTIFICATE + alias, mUid);
-    }
-
-    @Override
-    public boolean engineIsCertificateEntry(String alias) {
-        return !isKeyEntry(alias) && isCertificateEntry(alias);
-    }
-
-    @Override
-    public String engineGetCertificateAlias(Certificate cert) {
-        if (cert == null) {
-            return null;
-        }
-        if (!"X.509".equalsIgnoreCase(cert.getType())) {
-            // Only X.509 certificates supported
-            return null;
-        }
-        byte[] targetCertBytes;
-        try {
-            targetCertBytes = cert.getEncoded();
-        } catch (CertificateEncodingException e) {
-            return null;
-        }
-        if (targetCertBytes == null) {
-            return null;
-        }
-
-        final Set<String> nonCaEntries = new HashSet<String>();
-
-        /*
-         * First scan the PrivateKeyEntry types. The KeyStoreSpi documentation
-         * says to only compare the first certificate in the chain which is
-         * equivalent to the USER_CERTIFICATE prefix for the Android keystore
-         * convention.
-         */
-        final String[] certAliases = mKeyStore.list(Credentials.USER_CERTIFICATE, mUid);
-        if (certAliases != null) {
-            for (String alias : certAliases) {
-                final byte[] certBytes = mKeyStore.get(Credentials.USER_CERTIFICATE + alias, mUid);
-                if (certBytes == null) {
-                    continue;
-                }
-
-                nonCaEntries.add(alias);
-
-                if (Arrays.equals(certBytes, targetCertBytes)) {
-                    return alias;
-                }
-            }
-        }
-
-        /*
-         * Look at all the TrustedCertificateEntry types. Skip all the
-         * PrivateKeyEntry we looked at above.
-         */
-        final String[] caAliases = mKeyStore.list(Credentials.CA_CERTIFICATE, mUid);
-        if (certAliases != null) {
-            for (String alias : caAliases) {
-                if (nonCaEntries.contains(alias)) {
-                    continue;
-                }
-
-                final byte[] certBytes = mKeyStore.get(Credentials.CA_CERTIFICATE + alias, mUid);
-                if (certBytes == null) {
-                    continue;
-                }
-
-                if (Arrays.equals(certBytes, targetCertBytes)) {
-                    return alias;
-                }
-            }
-        }
-
-        return null;
-    }
-
-    @Override
-    public void engineStore(OutputStream stream, char[] password) throws IOException,
-            NoSuchAlgorithmException, CertificateException {
-        throw new UnsupportedOperationException("Can not serialize AndroidKeyStore to OutputStream");
-    }
-
-    @Override
-    public void engineLoad(InputStream stream, char[] password) throws IOException,
-            NoSuchAlgorithmException, CertificateException {
-        if (stream != null) {
-            throw new IllegalArgumentException("InputStream not supported");
-        }
-
-        if (password != null) {
-            throw new IllegalArgumentException("password not supported");
-        }
-
-        // Unfortunate name collision.
-        mKeyStore = KeyStore.getInstance();
-        mUid = KeyStore.UID_SELF;
-    }
-
-    @Override
-    public void engineLoad(LoadStoreParameter param) throws IOException,
-            NoSuchAlgorithmException, CertificateException {
-        int uid = KeyStore.UID_SELF;
-        if (param != null) {
-            if (param instanceof AndroidKeyStoreLoadStoreParameter) {
-                uid = ((AndroidKeyStoreLoadStoreParameter) param).getUid();
-            } else {
-                throw new IllegalArgumentException(
-                        "Unsupported param type: " + param.getClass());
-            }
-        }
-        mKeyStore = KeyStore.getInstance();
-        mUid = uid;
-    }
-
-    @Override
-    public void engineSetEntry(String alias, Entry entry, ProtectionParameter param)
-            throws KeyStoreException {
-        if (entry == null) {
-            throw new KeyStoreException("entry == null");
-        }
-
-        Credentials.deleteAllTypesForAlias(mKeyStore, alias, mUid);
-
-        if (entry instanceof java.security.KeyStore.TrustedCertificateEntry) {
-            java.security.KeyStore.TrustedCertificateEntry trE =
-                    (java.security.KeyStore.TrustedCertificateEntry) entry;
-            engineSetCertificateEntry(alias, trE.getTrustedCertificate());
-            return;
-        }
-
-        if (entry instanceof PrivateKeyEntry) {
-            PrivateKeyEntry prE = (PrivateKeyEntry) entry;
-            setPrivateKeyEntry(alias, prE.getPrivateKey(), prE.getCertificateChain(), param);
-        } else if (entry instanceof SecretKeyEntry) {
-            SecretKeyEntry secE = (SecretKeyEntry) entry;
-            setSecretKeyEntry(alias, secE.getSecretKey(), param);
-        } else if (entry instanceof WrappedKeyEntry) {
-            WrappedKeyEntry wke = (WrappedKeyEntry) entry;
-            setWrappedKeyEntry(alias, wke, param);
-        } else {
-            throw new KeyStoreException(
-                    "Entry must be a PrivateKeyEntry, SecretKeyEntry or TrustedCertificateEntry"
-                    + "; was " + entry);
-        }
-    }
-
-    /**
-     * {@link X509Certificate} which returns {@link AndroidKeyStorePublicKey} from
-     * {@link #getPublicKey()}. This is so that crypto operations on these public keys contain
-     * can find out which keystore private key entry to use. This is needed so that Android Keystore
-     * crypto operations using public keys can find out which key alias to use. These operations
-     * require an alias.
-     */
-    static class KeyStoreX509Certificate extends DelegatingX509Certificate {
-        private final String mPrivateKeyAlias;
-        private final int mPrivateKeyUid;
-        KeyStoreX509Certificate(String privateKeyAlias, int privateKeyUid,
-                X509Certificate delegate) {
-            super(delegate);
-            mPrivateKeyAlias = privateKeyAlias;
-            mPrivateKeyUid = privateKeyUid;
-        }
-
-        @Override
-        public PublicKey getPublicKey() {
-            PublicKey original = super.getPublicKey();
-            return AndroidKeyStoreProvider.getAndroidKeyStorePublicKey(
-                    mPrivateKeyAlias, mPrivateKeyUid,
-                    original.getAlgorithm(), original.getEncoded());
-        }
-    }
-}
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreUnauthenticatedAESCipherSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreUnauthenticatedAESCipherSpi.java
deleted file mode 100644
index 1f1d36f..0000000
--- a/keystore/java/android/security/keystore/AndroidKeyStoreUnauthenticatedAESCipherSpi.java
+++ /dev/null
@@ -1,319 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.security.keystore;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.security.keymaster.KeymasterArguments;
-import android.security.keymaster.KeymasterDefs;
-
-import java.security.AlgorithmParameters;
-import java.security.InvalidAlgorithmParameterException;
-import java.security.InvalidKeyException;
-import java.security.Key;
-import java.security.NoSuchAlgorithmException;
-import java.security.ProviderException;
-import java.security.spec.AlgorithmParameterSpec;
-import java.security.spec.InvalidParameterSpecException;
-import java.util.Arrays;
-
-import javax.crypto.CipherSpi;
-import javax.crypto.spec.IvParameterSpec;
-
-/**
- * Base class for Android Keystore unauthenticated AES {@link CipherSpi} implementations.
- *
- * @hide
- */
-class AndroidKeyStoreUnauthenticatedAESCipherSpi extends AndroidKeyStoreCipherSpiBase {
-
-    abstract static class ECB extends AndroidKeyStoreUnauthenticatedAESCipherSpi {
-        protected ECB(int keymasterPadding) {
-            super(KeymasterDefs.KM_MODE_ECB, keymasterPadding, false);
-        }
-
-        public static class NoPadding extends ECB {
-            public NoPadding() {
-                super(KeymasterDefs.KM_PAD_NONE);
-            }
-        }
-
-        public static class PKCS7Padding extends ECB {
-            public PKCS7Padding() {
-                super(KeymasterDefs.KM_PAD_PKCS7);
-            }
-        }
-    }
-
-    abstract static class CBC extends AndroidKeyStoreUnauthenticatedAESCipherSpi {
-        protected CBC(int keymasterPadding) {
-            super(KeymasterDefs.KM_MODE_CBC, keymasterPadding, true);
-        }
-
-        public static class NoPadding extends CBC {
-            public NoPadding() {
-                super(KeymasterDefs.KM_PAD_NONE);
-            }
-        }
-
-        public static class PKCS7Padding extends CBC {
-            public PKCS7Padding() {
-                super(KeymasterDefs.KM_PAD_PKCS7);
-            }
-        }
-    }
-
-    abstract static class CTR extends AndroidKeyStoreUnauthenticatedAESCipherSpi {
-        protected CTR(int keymasterPadding) {
-            super(KeymasterDefs.KM_MODE_CTR, keymasterPadding, true);
-        }
-
-        public static class NoPadding extends CTR {
-            public NoPadding() {
-                super(KeymasterDefs.KM_PAD_NONE);
-            }
-        }
-    }
-
-    private static final int BLOCK_SIZE_BYTES = 16;
-
-    private final int mKeymasterBlockMode;
-    private final int mKeymasterPadding;
-    /** Whether this transformation requires an IV. */
-    private final boolean mIvRequired;
-
-    private byte[] mIv;
-
-    /** Whether the current {@code #mIv} has been used by the underlying crypto operation. */
-    private boolean mIvHasBeenUsed;
-
-    AndroidKeyStoreUnauthenticatedAESCipherSpi(
-            int keymasterBlockMode,
-            int keymasterPadding,
-            boolean ivRequired) {
-        mKeymasterBlockMode = keymasterBlockMode;
-        mKeymasterPadding = keymasterPadding;
-        mIvRequired = ivRequired;
-    }
-
-    @Override
-    protected final void resetAll() {
-        mIv = null;
-        mIvHasBeenUsed = false;
-        super.resetAll();
-    }
-
-    @Override
-    protected final void resetWhilePreservingInitState() {
-        super.resetWhilePreservingInitState();
-    }
-
-    @Override
-    protected final void initKey(int opmode, Key key) throws InvalidKeyException {
-        if (!(key instanceof AndroidKeyStoreSecretKey)) {
-            throw new InvalidKeyException(
-                    "Unsupported key: " + ((key != null) ? key.getClass().getName() : "null"));
-        }
-        if (!KeyProperties.KEY_ALGORITHM_AES.equalsIgnoreCase(key.getAlgorithm())) {
-            throw new InvalidKeyException(
-                    "Unsupported key algorithm: " + key.getAlgorithm() + ". Only " +
-                    KeyProperties.KEY_ALGORITHM_AES + " supported");
-        }
-        setKey((AndroidKeyStoreSecretKey) key);
-    }
-
-    @Override
-    protected final void initAlgorithmSpecificParameters() throws InvalidKeyException {
-        if (!mIvRequired) {
-            return;
-        }
-
-        // IV is used
-        if (!isEncrypting()) {
-            throw new InvalidKeyException("IV required when decrypting"
-                    + ". Use IvParameterSpec or AlgorithmParameters to provide it.");
-        }
-    }
-
-    @Override
-    protected final void initAlgorithmSpecificParameters(AlgorithmParameterSpec params)
-            throws InvalidAlgorithmParameterException {
-        if (!mIvRequired) {
-            if (params != null) {
-                throw new InvalidAlgorithmParameterException("Unsupported parameters: " + params);
-            }
-            return;
-        }
-
-        // IV is used
-        if (params == null) {
-            if (!isEncrypting()) {
-                // IV must be provided by the caller
-                throw new InvalidAlgorithmParameterException(
-                        "IvParameterSpec must be provided when decrypting");
-            }
-            return;
-        }
-        if (!(params instanceof IvParameterSpec)) {
-            throw new InvalidAlgorithmParameterException("Only IvParameterSpec supported");
-        }
-        mIv = ((IvParameterSpec) params).getIV();
-        if (mIv == null) {
-            throw new InvalidAlgorithmParameterException("Null IV in IvParameterSpec");
-        }
-    }
-
-    @Override
-    protected final void initAlgorithmSpecificParameters(AlgorithmParameters params)
-            throws InvalidAlgorithmParameterException {
-        if (!mIvRequired) {
-            if (params != null) {
-                throw new InvalidAlgorithmParameterException("Unsupported parameters: " + params);
-            }
-            return;
-        }
-
-        // IV is used
-        if (params == null) {
-            if (!isEncrypting()) {
-                // IV must be provided by the caller
-                throw new InvalidAlgorithmParameterException("IV required when decrypting"
-                        + ". Use IvParameterSpec or AlgorithmParameters to provide it.");
-            }
-            return;
-        }
-
-        if (!"AES".equalsIgnoreCase(params.getAlgorithm())) {
-            throw new InvalidAlgorithmParameterException(
-                    "Unsupported AlgorithmParameters algorithm: " + params.getAlgorithm()
-                    + ". Supported: AES");
-        }
-
-        IvParameterSpec ivSpec;
-        try {
-            ivSpec = params.getParameterSpec(IvParameterSpec.class);
-        } catch (InvalidParameterSpecException e) {
-            if (!isEncrypting()) {
-                // IV must be provided by the caller
-                throw new InvalidAlgorithmParameterException("IV required when decrypting"
-                        + ", but not found in parameters: " + params, e);
-            }
-            mIv = null;
-            return;
-        }
-        mIv = ivSpec.getIV();
-        if (mIv == null) {
-            throw new InvalidAlgorithmParameterException("Null IV in AlgorithmParameters");
-        }
-    }
-
-    @Override
-    protected final int getAdditionalEntropyAmountForBegin() {
-        if ((mIvRequired) && (mIv == null) && (isEncrypting())) {
-            // IV will need to be generated
-            return BLOCK_SIZE_BYTES;
-        }
-
-        return 0;
-    }
-
-    @Override
-    protected final int getAdditionalEntropyAmountForFinish() {
-        return 0;
-    }
-
-    @Override
-    protected final void addAlgorithmSpecificParametersToBegin(
-            @NonNull KeymasterArguments keymasterArgs) {
-        if ((isEncrypting()) && (mIvRequired) && (mIvHasBeenUsed)) {
-            // IV is being reused for encryption: this violates security best practices.
-            throw new IllegalStateException(
-                    "IV has already been used. Reusing IV in encryption mode violates security best"
-                    + " practices.");
-        }
-
-        keymasterArgs.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_AES);
-        keymasterArgs.addEnum(KeymasterDefs.KM_TAG_BLOCK_MODE, mKeymasterBlockMode);
-        keymasterArgs.addEnum(KeymasterDefs.KM_TAG_PADDING, mKeymasterPadding);
-        if ((mIvRequired) && (mIv != null)) {
-            keymasterArgs.addBytes(KeymasterDefs.KM_TAG_NONCE, mIv);
-        }
-    }
-
-    @Override
-    protected final void loadAlgorithmSpecificParametersFromBeginResult(
-            @NonNull KeymasterArguments keymasterArgs) {
-        mIvHasBeenUsed = true;
-
-        // NOTE: Keymaster doesn't always return an IV, even if it's used.
-        byte[] returnedIv = keymasterArgs.getBytes(KeymasterDefs.KM_TAG_NONCE, null);
-        if ((returnedIv != null) && (returnedIv.length == 0)) {
-            returnedIv = null;
-        }
-
-        if (mIvRequired) {
-            if (mIv == null) {
-                mIv = returnedIv;
-            } else if ((returnedIv != null) && (!Arrays.equals(returnedIv, mIv))) {
-                throw new ProviderException("IV in use differs from provided IV");
-            }
-        } else {
-            if (returnedIv != null) {
-                throw new ProviderException(
-                        "IV in use despite IV not being used by this transformation");
-            }
-        }
-    }
-
-    @Override
-    protected final int engineGetBlockSize() {
-        return BLOCK_SIZE_BYTES;
-    }
-
-    @Override
-    protected final int engineGetOutputSize(int inputLen) {
-        return inputLen + 3 * BLOCK_SIZE_BYTES;
-    }
-
-    @Override
-    protected final byte[] engineGetIV() {
-        return ArrayUtils.cloneIfNotEmpty(mIv);
-    }
-
-    @Nullable
-    @Override
-    protected final AlgorithmParameters engineGetParameters() {
-        if (!mIvRequired) {
-            return null;
-        }
-        if ((mIv != null) && (mIv.length > 0)) {
-            try {
-                AlgorithmParameters params = AlgorithmParameters.getInstance("AES");
-                params.init(new IvParameterSpec(mIv));
-                return params;
-            } catch (NoSuchAlgorithmException e) {
-                throw new ProviderException(
-                        "Failed to obtain AES AlgorithmParameters", e);
-            } catch (InvalidParameterSpecException e) {
-                throw new ProviderException(
-                        "Failed to initialize AES AlgorithmParameters with an IV",
-                        e);
-            }
-        }
-        return null;
-    }
-}
diff --git a/keystore/java/android/security/keystore/AttestationUtils.java b/keystore/java/android/security/keystore/AttestationUtils.java
index 1eb8541..be865a0 100644
--- a/keystore/java/android/security/keystore/AttestationUtils.java
+++ b/keystore/java/android/security/keystore/AttestationUtils.java
@@ -36,9 +36,11 @@
 import java.security.KeyPairGenerator;
 import java.security.KeyStore;
 import java.security.SecureRandom;
+import java.security.cert.Certificate;
 import java.security.cert.CertificateFactory;
 import java.security.cert.X509Certificate;
 import java.security.spec.ECGenParameterSpec;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Random;
 import java.util.Set;
@@ -281,8 +283,9 @@
             KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
             keyStore.load(null);
 
+            Certificate[] certs = keyStore.getCertificateChain(keystoreAlias);
             X509Certificate[] certificateChain =
-                    (X509Certificate[]) keyStore.getCertificateChain(keystoreAlias);
+                Arrays.copyOf(certs, certs.length, X509Certificate[].class);
 
             keyStore.deleteEntry(keystoreAlias);
 
diff --git a/keystore/java/android/security/keystore/KeyGenParameterSpec.java b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
index 9ca551b..1f9022b 100644
--- a/keystore/java/android/security/keystore/KeyGenParameterSpec.java
+++ b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
@@ -446,13 +446,6 @@
     @UnsupportedAppUsage
     @Deprecated
     public int getUid() {
-        if (!AndroidKeyStoreProvider.isKeystore2Enabled()) {
-            // If Keystore2 has not been enabled we have to behave as if mNamespace is actually
-            // a UID, because we are still being used with the old Keystore SPI.
-            // TODO This if statement and body can be removed when the Keystore 2 migration is
-            //      complete. b/171563717
-            return mNamespace;
-        }
         try {
             return KeyProperties.namespaceToLegacyUid(mNamespace);
         } catch (IllegalArgumentException e) {
@@ -1021,14 +1014,6 @@
         @NonNull
         @Deprecated
         public Builder setUid(int uid) {
-            if (!AndroidKeyStoreProvider.isKeystore2Enabled()) {
-                // If Keystore2 has not been enabled we have to behave as if mNamespace is actually
-                // a UID, because we are still being used with the old Keystore SPI.
-                // TODO This if statement and body can be removed when the Keystore 2 migration is
-                //      complete. b/171563717
-                mNamespace = uid;
-                return this;
-            }
             mNamespace = KeyProperties.legacyUidToNamespace(uid);
             return this;
         }
@@ -1666,9 +1651,10 @@
          * Set whether this key is critical to the device encryption flow
          *
          * This is a special flag only available to system servers to indicate the current key
-         * is part of the device encryption flow.
+         * is part of the device encryption flow. Setting this flag causes the key to not
+         * be cryptographically bound to the LSKF even if the key is otherwise authentication
+         * bound.
          *
-         * @see android.security.KeyStore#FLAG_CRITICAL_TO_DEVICE_ENCRYPTION
          * @hide
          */
         public Builder setCriticalToDeviceEncryption(boolean critical) {
diff --git a/keystore/java/android/security/keystore/KeyProtection.java b/keystore/java/android/security/keystore/KeyProtection.java
index 673491e..88d1a5b 100644
--- a/keystore/java/android/security/keystore/KeyProtection.java
+++ b/keystore/java/android/security/keystore/KeyProtection.java
@@ -24,6 +24,7 @@
 import android.hardware.biometrics.BiometricManager;
 import android.hardware.biometrics.BiometricPrompt;
 import android.security.GateKeeper;
+import android.security.keystore2.KeymasterUtils;
 
 import java.security.Key;
 import java.security.KeyStore.ProtectionParameter;
diff --git a/keystore/java/android/security/keystore/KeyStoreCryptoOperationChunkedStreamer.java b/keystore/java/android/security/keystore/KeyStoreCryptoOperationChunkedStreamer.java
deleted file mode 100644
index 2c0f40d..0000000
--- a/keystore/java/android/security/keystore/KeyStoreCryptoOperationChunkedStreamer.java
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.security.keystore;
-
-import android.os.IBinder;
-import android.security.KeyStore;
-import android.security.KeyStoreException;
-import android.security.keymaster.KeymasterDefs;
-import android.security.keymaster.OperationResult;
-
-import libcore.util.EmptyArray;
-
-/**
- * Helper for streaming a crypto operation's input and output via {@link KeyStore} service's
- * {@code update} and {@code finish} operations.
- *
- * <p>The helper abstracts away issues that need to be solved in most code that uses KeyStore's
- * update and finish operations. Firstly, KeyStore's update operation can consume only a limited
- * amount of data in one go because the operations are marshalled via Binder. Secondly, the update
- * operation may consume less data than provided, in which case the caller has to buffer the
- * remainder for next time. Thirdly, when the input is smaller than a threshold, skipping update
- * and passing input data directly to final improves performance. This threshold is configurable;
- * using a threshold <= 1 causes the helper act eagerly, which may be required for some types of
- * operations (e.g. ciphers).
- *
- * <p>The helper exposes {@link #update(byte[], int, int) update} and
- * {@link #doFinal(byte[], int, int, byte[], byte[]) doFinal} operations which can be used to
- * conveniently implement various JCA crypto primitives.
- *
- * <p>Bidirectional chunked streaming of data via a KeyStore crypto operation is abstracted away as
- * a {@link Stream} to avoid having this class deal with operation tokens and occasional additional
- * parameters to {@code update} and {@code final} operations.
- *
- * @hide
- */
-class KeyStoreCryptoOperationChunkedStreamer implements KeyStoreCryptoOperationStreamer {
-
-    /**
-     * Bidirectional chunked data stream over a KeyStore crypto operation.
-     */
-    interface Stream {
-        /**
-         * Returns the result of the KeyStore {@code update} operation or null if keystore couldn't
-         * be reached.
-         */
-        OperationResult update(byte[] input);
-
-        /**
-         * Returns the result of the KeyStore {@code finish} operation or null if keystore couldn't
-         * be reached.
-         */
-        OperationResult finish(byte[] input, byte[] siganture, byte[] additionalEntropy);
-    }
-
-    // Binder buffer is about 1MB, but it's shared between all active transactions of the process.
-    // Thus, it's safer to use a much smaller upper bound.
-    private static final int DEFAULT_CHUNK_SIZE_MAX = 64 * 1024;
-    // The chunk buffer will be sent to update until its size under this threshold.
-    // This threshold should be <= the max input allowed for finish.
-    // Setting this threshold <= 1 will effectivley disable buffering between updates.
-    private static final int DEFAULT_CHUNK_SIZE_THRESHOLD = 2 * 1024;
-
-    private final Stream mKeyStoreStream;
-    private final int mChunkSizeMax;
-    private final int mChunkSizeThreshold;
-    private final byte[] mChunk;
-    private int mChunkLength = 0;
-    private long mConsumedInputSizeBytes;
-    private long mProducedOutputSizeBytes;
-
-    KeyStoreCryptoOperationChunkedStreamer(Stream operation) {
-        this(operation, DEFAULT_CHUNK_SIZE_THRESHOLD, DEFAULT_CHUNK_SIZE_MAX);
-    }
-
-    KeyStoreCryptoOperationChunkedStreamer(Stream operation, int chunkSizeThreshold) {
-        this(operation, chunkSizeThreshold, DEFAULT_CHUNK_SIZE_MAX);
-    }
-
-    KeyStoreCryptoOperationChunkedStreamer(Stream operation, int chunkSizeThreshold,
-            int chunkSizeMax) {
-        mKeyStoreStream = operation;
-        mChunkSizeMax = chunkSizeMax;
-        if (chunkSizeThreshold <= 0) {
-            mChunkSizeThreshold = 1;
-        } else if (chunkSizeThreshold > chunkSizeMax) {
-            mChunkSizeThreshold = chunkSizeMax;
-        } else {
-            mChunkSizeThreshold = chunkSizeThreshold;
-        }
-        mChunk = new byte[mChunkSizeMax];
-    }
-
-    public byte[] update(byte[] input, int inputOffset, int inputLength) throws KeyStoreException {
-        if (inputLength == 0 || input == null) {
-            // No input provided
-            return EmptyArray.BYTE;
-        }
-        if (inputLength < 0 || inputOffset < 0 || (inputOffset + inputLength) > input.length) {
-            throw new KeyStoreException(KeymasterDefs.KM_ERROR_UNKNOWN_ERROR,
-                "Input offset and length out of bounds of input array");
-        }
-
-        byte[] output = EmptyArray.BYTE;
-
-        while (inputLength > 0 || mChunkLength >= mChunkSizeThreshold) {
-            int inputConsumed = ArrayUtils.copy(input, inputOffset, mChunk, mChunkLength,
-                    inputLength);
-            inputLength -= inputConsumed;
-            inputOffset += inputConsumed;
-            mChunkLength += inputConsumed;
-            mConsumedInputSizeBytes += inputConsumed;
-
-            if (mChunkLength > mChunkSizeMax) {
-                throw new KeyStoreException(KeymasterDefs.KM_ERROR_INVALID_INPUT_LENGTH,
-                    "Chunk size exceeded max chunk size. Max: " + mChunkSizeMax
-                    + " Actual: " + mChunkLength);
-            }
-
-            if (mChunkLength >= mChunkSizeThreshold) {
-                OperationResult opResult = mKeyStoreStream.update(
-                        ArrayUtils.subarray(mChunk, 0, mChunkLength));
-
-                if (opResult == null) {
-                    throw new KeyStoreConnectException();
-                } else if (opResult.resultCode != KeyStore.NO_ERROR) {
-                    throw KeyStore.getKeyStoreException(opResult.resultCode);
-                }
-                if (opResult.inputConsumed <= 0) {
-                    throw new KeyStoreException(KeymasterDefs.KM_ERROR_INVALID_INPUT_LENGTH,
-                        "Keystore consumed 0 of " + mChunkLength + " bytes provided.");
-                } else if (opResult.inputConsumed > mChunkLength) {
-                    throw new KeyStoreException(KeymasterDefs.KM_ERROR_UNKNOWN_ERROR,
-                        "Keystore consumed more input than provided. Provided: "
-                            + mChunkLength + ", consumed: " + opResult.inputConsumed);
-                }
-                mChunkLength -= opResult.inputConsumed;
-
-                if (mChunkLength > 0) {
-                    // Partialy consumed, shift chunk contents
-                    ArrayUtils.copy(mChunk, opResult.inputConsumed, mChunk, 0, mChunkLength);
-                }
-
-                if ((opResult.output != null) && (opResult.output.length > 0)) {
-                    // Output was produced
-                    mProducedOutputSizeBytes += opResult.output.length;
-                    output = ArrayUtils.concat(output, opResult.output);
-                }
-            }
-        }
-        return output;
-    }
-
-    public byte[] doFinal(byte[] input, int inputOffset, int inputLength,
-            byte[] signature, byte[] additionalEntropy) throws KeyStoreException {
-        byte[] output = update(input, inputOffset, inputLength);
-        byte[] finalChunk = ArrayUtils.subarray(mChunk, 0, mChunkLength);
-        OperationResult opResult = mKeyStoreStream.finish(finalChunk, signature, additionalEntropy);
-
-        if (opResult == null) {
-            throw new KeyStoreConnectException();
-        } else if (opResult.resultCode != KeyStore.NO_ERROR) {
-            throw KeyStore.getKeyStoreException(opResult.resultCode);
-        }
-        // If no error, assume all input consumed
-        mConsumedInputSizeBytes += finalChunk.length;
-
-        if ((opResult.output != null) && (opResult.output.length > 0)) {
-            mProducedOutputSizeBytes += opResult.output.length;
-            output = ArrayUtils.concat(output, opResult.output);
-        }
-
-        return output;
-    }
-
-    @Override
-    public long getConsumedInputSizeBytes() {
-        return mConsumedInputSizeBytes;
-    }
-
-    @Override
-    public long getProducedOutputSizeBytes() {
-        return mProducedOutputSizeBytes;
-    }
-
-    /**
-     * Main data stream via a KeyStore streaming operation.
-     *
-     * <p>For example, for an encryption operation, this is the stream through which plaintext is
-     * provided and ciphertext is obtained.
-     */
-    public static class MainDataStream implements Stream {
-
-        private final KeyStore mKeyStore;
-        private final IBinder mOperationToken;
-
-        public MainDataStream(KeyStore keyStore, IBinder operationToken) {
-            mKeyStore = keyStore;
-            mOperationToken = operationToken;
-        }
-
-        @Override
-        public OperationResult update(byte[] input) {
-            return mKeyStore.update(mOperationToken, null, input);
-        }
-
-        @Override
-        public OperationResult finish(byte[] input, byte[] signature, byte[] additionalEntropy) {
-            return mKeyStore.finish(mOperationToken, null, input, signature, additionalEntropy);
-        }
-    }
-}
diff --git a/keystore/java/android/security/keystore/KeyStoreCryptoOperationStreamer.java b/keystore/java/android/security/keystore/KeyStoreCryptoOperationStreamer.java
deleted file mode 100644
index 062c2d4..0000000
--- a/keystore/java/android/security/keystore/KeyStoreCryptoOperationStreamer.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.security.keystore;
-
-import android.security.KeyStore;
-import android.security.KeyStoreException;
-
-/**
- * Helper for streaming a crypto operation's input and output via {@link KeyStore} service's
- * {@code update} and {@code finish} operations.
- *
- * <p>The helper abstracts away to issues that need to be solved in most code that uses KeyStore's
- * update and finish operations. Firstly, KeyStore's update operation can consume only a limited
- * amount of data in one go because the operations are marshalled via Binder. Secondly, the update
- * operation may consume less data than provided, in which case the caller has to buffer the
- * remainder for next time. The helper exposes {@link #update(byte[], int, int) update} and
- * {@link #doFinal(byte[], int, int, byte[], byte[]) doFinal} operations which can be used to
- * conveniently implement various JCA crypto primitives.
- *
- * @hide
- */
-interface KeyStoreCryptoOperationStreamer {
-    byte[] update(byte[] input, int inputOffset, int inputLength) throws KeyStoreException;
-    byte[] doFinal(byte[] input, int inputOffset, int inputLength, byte[] signature,
-            byte[] additionalEntropy) throws KeyStoreException;
-    long getConsumedInputSizeBytes();
-    long getProducedOutputSizeBytes();
-}
diff --git a/keystore/java/android/security/keystore/KeyStoreCryptoOperationUtils.java b/keystore/java/android/security/keystore/KeyStoreCryptoOperationUtils.java
deleted file mode 100644
index c82b6e6b..0000000
--- a/keystore/java/android/security/keystore/KeyStoreCryptoOperationUtils.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.security.keystore;
-
-import android.security.KeyStore;
-import android.security.keymaster.KeymasterDefs;
-
-import libcore.util.EmptyArray;
-
-import java.security.GeneralSecurityException;
-import java.security.InvalidAlgorithmParameterException;
-import java.security.InvalidKeyException;
-import java.security.SecureRandom;
-
-/**
- * Assorted utility methods for implementing crypto operations on top of KeyStore.
- *
- * @hide
- */
-abstract class KeyStoreCryptoOperationUtils {
-
-    private static volatile SecureRandom sRng;
-
-    private KeyStoreCryptoOperationUtils() {}
-
-    /**
-     * Returns the {@link InvalidKeyException} to be thrown by the {@code init} method of
-     * the crypto operation in response to {@code KeyStore.begin} operation or {@code null} if
-     * the {@code init} method should succeed.
-     */
-    static InvalidKeyException getInvalidKeyExceptionForInit(
-            KeyStore keyStore, AndroidKeyStoreKey key, int beginOpResultCode) {
-        if (beginOpResultCode == KeyStore.NO_ERROR) {
-            return null;
-        }
-
-        // An error occurred. However, some errors should not lead to init throwing an exception.
-        // See below.
-        InvalidKeyException e =
-                keyStore.getInvalidKeyException(key.getAlias(), key.getUid(), beginOpResultCode);
-        switch (beginOpResultCode) {
-            case KeyStore.OP_AUTH_NEEDED:
-                // Operation needs to be authorized by authenticating the user. Don't throw an
-                // exception is such authentication is possible for this key
-                // (UserNotAuthenticatedException). An example of when it's not possible is where
-                // the key is permanently invalidated (KeyPermanentlyInvalidatedException).
-                if (e instanceof UserNotAuthenticatedException) {
-                    return null;
-                }
-                break;
-        }
-        return e;
-    }
-
-    /**
-     * Returns the exception to be thrown by the {@code Cipher.init} method of the crypto operation
-     * in response to {@code KeyStore.begin} operation or {@code null} if the {@code init} method
-     * should succeed.
-     */
-    public static GeneralSecurityException getExceptionForCipherInit(
-            KeyStore keyStore, AndroidKeyStoreKey key, int beginOpResultCode) {
-        if (beginOpResultCode == KeyStore.NO_ERROR) {
-            return null;
-        }
-
-        // Cipher-specific cases
-        switch (beginOpResultCode) {
-            case KeymasterDefs.KM_ERROR_INVALID_NONCE:
-                return new InvalidAlgorithmParameterException("Invalid IV");
-            case KeymasterDefs.KM_ERROR_CALLER_NONCE_PROHIBITED:
-                return new InvalidAlgorithmParameterException("Caller-provided IV not permitted");
-        }
-
-        // General cases
-        return getInvalidKeyExceptionForInit(keyStore, key, beginOpResultCode);
-    }
-
-    /**
-     * Returns the requested number of random bytes to mix into keystore/keymaster RNG.
-     *
-     * @param rng RNG from which to obtain the random bytes or {@code null} for the platform-default
-     *        RNG.
-     */
-    static byte[] getRandomBytesToMixIntoKeystoreRng(SecureRandom rng, int sizeBytes) {
-        if (sizeBytes <= 0) {
-            return EmptyArray.BYTE;
-        }
-        if (rng == null) {
-            rng = getRng();
-        }
-        byte[] result = new byte[sizeBytes];
-        rng.nextBytes(result);
-        return result;
-    }
-
-    private static SecureRandom getRng() {
-        // IMPLEMENTATION NOTE: It's OK to share a SecureRandom instance because SecureRandom is
-        // required to be thread-safe.
-        if (sRng == null) {
-            sRng = new SecureRandom();
-        }
-        return sRng;
-    }
-}
diff --git a/keystore/java/android/security/keystore/KeymasterUtils.java b/keystore/java/android/security/keystore/KeymasterUtils.java
deleted file mode 100644
index 670ef5e..0000000
--- a/keystore/java/android/security/keystore/KeymasterUtils.java
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.security.keystore;
-
-import android.hardware.biometrics.BiometricManager;
-import android.security.GateKeeper;
-import android.security.KeyStore;
-import android.security.keymaster.KeymasterArguments;
-import android.security.keymaster.KeymasterDefs;
-
-import java.security.ProviderException;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * @hide
- */
-public abstract class KeymasterUtils {
-
-    private KeymasterUtils() {}
-
-    public static int getDigestOutputSizeBits(int keymasterDigest) {
-        switch (keymasterDigest) {
-            case KeymasterDefs.KM_DIGEST_NONE:
-                return -1;
-            case KeymasterDefs.KM_DIGEST_MD5:
-                return 128;
-            case KeymasterDefs.KM_DIGEST_SHA1:
-                return 160;
-            case KeymasterDefs.KM_DIGEST_SHA_2_224:
-                return 224;
-            case KeymasterDefs.KM_DIGEST_SHA_2_256:
-                return 256;
-            case KeymasterDefs.KM_DIGEST_SHA_2_384:
-                return 384;
-            case KeymasterDefs.KM_DIGEST_SHA_2_512:
-                return 512;
-            default:
-                throw new IllegalArgumentException("Unknown digest: " + keymasterDigest);
-        }
-    }
-
-    public static boolean isKeymasterBlockModeIndCpaCompatibleWithSymmetricCrypto(
-            int keymasterBlockMode) {
-        switch (keymasterBlockMode) {
-            case KeymasterDefs.KM_MODE_ECB:
-                return false;
-            case KeymasterDefs.KM_MODE_CBC:
-            case KeymasterDefs.KM_MODE_CTR:
-            case KeymasterDefs.KM_MODE_GCM:
-                return true;
-            default:
-                throw new IllegalArgumentException("Unsupported block mode: " + keymasterBlockMode);
-        }
-    }
-
-    public static boolean isKeymasterPaddingSchemeIndCpaCompatibleWithAsymmetricCrypto(
-            int keymasterPadding) {
-        switch (keymasterPadding) {
-            case KeymasterDefs.KM_PAD_NONE:
-                return false;
-            case KeymasterDefs.KM_PAD_RSA_OAEP:
-            case KeymasterDefs.KM_PAD_RSA_PKCS1_1_5_ENCRYPT:
-                return true;
-            default:
-                throw new IllegalArgumentException(
-                        "Unsupported asymmetric encryption padding scheme: " + keymasterPadding);
-        }
-    }
-
-    private static void addSids(KeymasterArguments args, UserAuthArgs spec) {
-        // If both biometric and credential are accepted, then just use the root sid from gatekeeper
-        if (spec.getUserAuthenticationType() == (KeyProperties.AUTH_BIOMETRIC_STRONG
-                                                 | KeyProperties.AUTH_DEVICE_CREDENTIAL)) {
-            if (spec.getBoundToSpecificSecureUserId() != GateKeeper.INVALID_SECURE_USER_ID) {
-                args.addUnsignedLong(KeymasterDefs.KM_TAG_USER_SECURE_ID,
-                        KeymasterArguments.toUint64(spec.getBoundToSpecificSecureUserId()));
-            } else {
-                // The key is authorized for use for the specified amount of time after the user has
-                // authenticated. Whatever unlocks the secure lock screen should authorize this key.
-                args.addUnsignedLong(KeymasterDefs.KM_TAG_USER_SECURE_ID,
-                        KeymasterArguments.toUint64(getRootSid()));
-            }
-        } else {
-            List<Long> sids = new ArrayList<>();
-            if ((spec.getUserAuthenticationType() & KeyProperties.AUTH_BIOMETRIC_STRONG) != 0) {
-                final BiometricManager bm = KeyStore.getApplicationContext()
-                        .getSystemService(BiometricManager.class);
-
-                // TODO: Restore permission check in getAuthenticatorIds once the ID is no longer
-                // needed here.
-
-                final long[] biometricSids = bm.getAuthenticatorIds();
-
-                if (biometricSids.length == 0) {
-                    throw new IllegalStateException(
-                            "At least one biometric must be enrolled to create keys requiring user"
-                            + " authentication for every use");
-                }
-
-                if (spec.getBoundToSpecificSecureUserId() != GateKeeper.INVALID_SECURE_USER_ID) {
-                    sids.add(spec.getBoundToSpecificSecureUserId());
-                } else if (spec.isInvalidatedByBiometricEnrollment()) {
-                    // The biometric-only SIDs will change on biometric enrollment or removal of all
-                    // enrolled templates, invalidating the key.
-                    for (long sid : biometricSids) {
-                        sids.add(sid);
-                    }
-                } else {
-                    // The root SID will *not* change on fingerprint enrollment, or removal of all
-                    // enrolled fingerprints, allowing the key to remain valid.
-                    sids.add(getRootSid());
-                }
-            } else if ((spec.getUserAuthenticationType() & KeyProperties.AUTH_DEVICE_CREDENTIAL)
-                            != 0) {
-                sids.add(getRootSid());
-            } else {
-                throw new IllegalStateException("Invalid or no authentication type specified.");
-            }
-
-            for (int i = 0; i < sids.size(); i++) {
-                args.addUnsignedLong(KeymasterDefs.KM_TAG_USER_SECURE_ID,
-                        KeymasterArguments.toUint64(sids.get(i)));
-            }
-        }
-    }
-
-    /**
-     * Adds keymaster arguments to express the key's authorization policy supported by user
-     * authentication.
-     *
-     * @param args The arguments sent to keymaster that need to be populated from the spec
-     * @param spec The user authentication relevant portions of the spec passed in from the caller.
-     *        This spec will be translated into the relevant keymaster tags to be loaded into args.
-     * @throws IllegalStateException if user authentication is required but the system is in a wrong
-     *         state (e.g., secure lock screen not set up) for generating or importing keys that
-     *         require user authentication.
-     */
-    public static void addUserAuthArgs(KeymasterArguments args, UserAuthArgs spec) {
-
-        if (spec.isUserConfirmationRequired()) {
-            args.addBoolean(KeymasterDefs.KM_TAG_TRUSTED_CONFIRMATION_REQUIRED);
-        }
-
-        if (spec.isUserPresenceRequired()) {
-            args.addBoolean(KeymasterDefs.KM_TAG_TRUSTED_USER_PRESENCE_REQUIRED);
-        }
-
-        if (spec.isUnlockedDeviceRequired()) {
-            args.addBoolean(KeymasterDefs.KM_TAG_UNLOCKED_DEVICE_REQUIRED);
-        }
-
-        if (!spec.isUserAuthenticationRequired()) {
-            args.addBoolean(KeymasterDefs.KM_TAG_NO_AUTH_REQUIRED);
-            return;
-        }
-
-        if (spec.getUserAuthenticationValidityDurationSeconds() == 0) {
-            // Every use of this key needs to be authorized by the user.
-            addSids(args, spec);
-            args.addEnum(KeymasterDefs.KM_TAG_USER_AUTH_TYPE, spec.getUserAuthenticationType());
-
-            if (spec.isUserAuthenticationValidWhileOnBody()) {
-                throw new ProviderException("Key validity extension while device is on-body is not "
-                        + "supported for keys requiring fingerprint authentication");
-            }
-        } else {
-            addSids(args, spec);
-            args.addEnum(KeymasterDefs.KM_TAG_USER_AUTH_TYPE, spec.getUserAuthenticationType());
-            args.addUnsignedInt(KeymasterDefs.KM_TAG_AUTH_TIMEOUT,
-                    spec.getUserAuthenticationValidityDurationSeconds());
-            if (spec.isUserAuthenticationValidWhileOnBody()) {
-                args.addBoolean(KeymasterDefs.KM_TAG_ALLOW_WHILE_ON_BODY);
-            }
-        }
-    }
-
-    /**
-     * Adds {@code KM_TAG_MIN_MAC_LENGTH} tag, if necessary, to the keymaster arguments for
-     * generating or importing a key. This tag may only be needed for symmetric keys (e.g., HMAC,
-     * AES-GCM).
-     */
-    public static void addMinMacLengthAuthorizationIfNecessary(KeymasterArguments args,
-            int keymasterAlgorithm,
-            int[] keymasterBlockModes,
-            int[] keymasterDigests) {
-        switch (keymasterAlgorithm) {
-            case KeymasterDefs.KM_ALGORITHM_AES:
-                if (com.android.internal.util.ArrayUtils.contains(
-                        keymasterBlockModes, KeymasterDefs.KM_MODE_GCM)) {
-                    // AES GCM key needs the minimum length of AEAD tag specified.
-                    args.addUnsignedInt(KeymasterDefs.KM_TAG_MIN_MAC_LENGTH,
-                            AndroidKeyStoreAuthenticatedAESCipherSpi.GCM
-                                    .MIN_SUPPORTED_TAG_LENGTH_BITS);
-                }
-                break;
-            case KeymasterDefs.KM_ALGORITHM_HMAC:
-                // HMAC key needs the minimum length of MAC set to the output size of the associated
-                // digest. This is because we do not offer a way to generate shorter MACs and
-                // don't offer a way to verify MACs (other than by generating them).
-                if (keymasterDigests.length != 1) {
-                    throw new ProviderException(
-                            "Unsupported number of authorized digests for HMAC key: "
-                                    + keymasterDigests.length
-                                    + ". Exactly one digest must be authorized");
-                }
-                int keymasterDigest = keymasterDigests[0];
-                int digestOutputSizeBits = getDigestOutputSizeBits(keymasterDigest);
-                if (digestOutputSizeBits == -1) {
-                    throw new ProviderException(
-                            "HMAC key authorized for unsupported digest: "
-                                    + KeyProperties.Digest.fromKeymaster(keymasterDigest));
-                }
-                args.addUnsignedInt(KeymasterDefs.KM_TAG_MIN_MAC_LENGTH, digestOutputSizeBits);
-                break;
-        }
-    }
-
-    private static long getRootSid() {
-        long rootSid = GateKeeper.getSecureUserId();
-        if (rootSid == 0) {
-            throw new IllegalStateException("Secure lock screen must be enabled"
-                    + " to create keys requiring user authentication");
-        }
-        return rootSid;
-    }
-}
diff --git a/keystore/java/android/security/keystore/SecureKeyImportUnavailableException.java b/keystore/java/android/security/keystore/SecureKeyImportUnavailableException.java
index d1cc572..c1842b4 100644
--- a/keystore/java/android/security/keystore/SecureKeyImportUnavailableException.java
+++ b/keystore/java/android/security/keystore/SecureKeyImportUnavailableException.java
@@ -16,8 +16,8 @@
 
 package android.security.keystore;
 
-import android.security.KeyStore;
 import android.security.KeyStoreException;
+import android.security.keymaster.KeymasterDefs;
 
 import java.security.ProviderException;
 
@@ -31,7 +31,7 @@
     }
 
     public SecureKeyImportUnavailableException(String message) {
-        super(message, new KeyStoreException(KeyStore.HARDWARE_TYPE_UNAVAILABLE,
+        super(message, new KeyStoreException(KeymasterDefs.KM_ERROR_HARDWARE_TYPE_UNAVAILABLE,
                 "Secure Key Import not available"));
     }
 
diff --git a/keystore/java/android/security/keystore/StrongBoxUnavailableException.java b/keystore/java/android/security/keystore/StrongBoxUnavailableException.java
index 6c7e9a9..1f4e12e 100644
--- a/keystore/java/android/security/keystore/StrongBoxUnavailableException.java
+++ b/keystore/java/android/security/keystore/StrongBoxUnavailableException.java
@@ -16,8 +16,8 @@
 
 package android.security.keystore;
 
-import android.security.KeyStore;
 import android.security.KeyStoreException;
+import android.security.keymaster.KeymasterDefs;
 
 import java.security.ProviderException;
 
@@ -33,7 +33,8 @@
 
     public StrongBoxUnavailableException(String message) {
         super(message,
-                new KeyStoreException(KeyStore.HARDWARE_TYPE_UNAVAILABLE, "No StrongBox available")
+                new KeyStoreException(KeymasterDefs.KM_ERROR_HARDWARE_TYPE_UNAVAILABLE,
+                        "No StrongBox available")
         );
     }
 
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreHmacSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreHmacSpi.java
index 0f77749..268b15bf 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreHmacSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreHmacSpi.java
@@ -21,7 +21,6 @@
 import android.security.KeyStoreOperation;
 import android.security.keymaster.KeymasterDefs;
 import android.security.keystore.KeyStoreCryptoOperation;
-import android.security.keystore.KeymasterUtils;
 
 import java.security.InvalidAlgorithmParameterException;
 import java.security.InvalidKeyException;
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyGeneratorSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyGeneratorSpi.java
index 1575bb4..f1681ec 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyGeneratorSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyGeneratorSpi.java
@@ -20,12 +20,10 @@
 import android.hardware.security.keymint.SecurityLevel;
 import android.security.KeyStore2;
 import android.security.KeyStoreSecurityLevel;
-import android.security.keymaster.KeymasterArguments;
 import android.security.keymaster.KeymasterDefs;
 import android.security.keystore.ArrayUtils;
 import android.security.keystore.KeyGenParameterSpec;
 import android.security.keystore.KeyProperties;
-import android.security.keystore.KeymasterUtils;
 import android.security.keystore.StrongBoxUnavailableException;
 import android.system.keystore2.Domain;
 import android.system.keystore2.IKeystoreSecurityLevel;
@@ -259,7 +257,7 @@
                 // Check that user authentication related parameters are acceptable. This method
                 // will throw an IllegalStateException if there are issues (e.g., secure lock screen
                 // not set up).
-                KeymasterUtils.addUserAuthArgs(new KeymasterArguments(), spec);
+                KeyStore2ParameterUtils.addUserAuthArgs(new ArrayList<>(), spec);
             } catch (IllegalStateException | IllegalArgumentException e) {
                 throw new InvalidAlgorithmParameterException(e);
             }
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java
index 2d8901a..c26d9f583 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.app.ActivityThread;
 import android.content.Context;
 import android.hardware.security.keymint.KeyParameter;
 import android.hardware.security.keymint.KeyPurpose;
@@ -28,7 +29,6 @@
 import android.security.GenerateRkpKey;
 import android.security.GenerateRkpKeyException;
 import android.security.KeyPairGeneratorSpec;
-import android.security.KeyStore;
 import android.security.KeyStore2;
 import android.security.KeyStoreException;
 import android.security.KeyStoreSecurityLevel;
@@ -39,7 +39,6 @@
 import android.security.keystore.DeviceIdAttestationException;
 import android.security.keystore.KeyGenParameterSpec;
 import android.security.keystore.KeyProperties;
-import android.security.keystore.KeymasterUtils;
 import android.security.keystore.SecureKeyImportUnavailableException;
 import android.security.keystore.StrongBoxUnavailableException;
 import android.system.keystore2.Authorization;
@@ -270,7 +269,7 @@
                 // Check that user authentication related parameters are acceptable. This method
                 // will throw an IllegalStateException if there are issues (e.g., secure lock screen
                 // not set up).
-                KeymasterUtils.addUserAuthArgs(new KeymasterArguments(), mSpec);
+                KeyStore2ParameterUtils.addUserAuthArgs(new ArrayList<>(), mSpec);
             } catch (IllegalArgumentException | IllegalStateException e) {
                 throw new InvalidAlgorithmParameterException(e);
             }
@@ -572,7 +571,8 @@
             AndroidKeyStorePublicKey publicKey =
                     AndroidKeyStoreProvider.makeAndroidKeyStorePublicKeyFromKeyEntryResponse(
                             descriptor, metadata, iSecurityLevel, mKeymasterAlgorithm);
-            GenerateRkpKey keyGen = new GenerateRkpKey(KeyStore.getApplicationContext());
+            GenerateRkpKey keyGen = new GenerateRkpKey(ActivityThread
+                    .currentApplication());
             try {
                 if (mSpec.getAttestationChallenge() != null) {
                     keyGen.notifyKeyGenerated(securityLevel);
@@ -589,7 +589,8 @@
                 case KeymasterDefs.KM_ERROR_HARDWARE_TYPE_UNAVAILABLE:
                     throw new StrongBoxUnavailableException("Failed to generated key pair.", e);
                 case ResponseCode.OUT_OF_KEYS:
-                    GenerateRkpKey keyGen = new GenerateRkpKey(KeyStore.getApplicationContext());
+                    GenerateRkpKey keyGen = new GenerateRkpKey(ActivityThread
+                            .currentApplication());
                     try {
                         keyGen.notifyEmpty(securityLevel);
                     } catch (RemoteException f) {
@@ -665,8 +666,8 @@
             if (idTypesSet.contains(AttestationUtils.ID_TYPE_IMEI)
                     || idTypesSet.contains(AttestationUtils.ID_TYPE_MEID)) {
                 telephonyService =
-                    (TelephonyManager) KeyStore.getApplicationContext().getSystemService(
-                        Context.TELEPHONY_SERVICE);
+                    (TelephonyManager) android.app.AppGlobals.getInitialApplication()
+                            .getSystemService(Context.TELEPHONY_SERVICE);
                 if (telephonyService == null) {
                     throw new DeviceIdAttestationException("Unable to access telephony service");
                 }
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java b/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java
index ba6d22f..89d2b74 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java
@@ -110,23 +110,6 @@
         putSecretKeyFactoryImpl("HmacSHA512");
     }
 
-    private static boolean sInstalled = false;
-
-    /**
-     * This function indicates whether or not this provider was installed. This is manly used
-     * as indicator for
-     * {@link android.security.keystore.AndroidKeyStoreProvider#getKeyStoreForUid(int)}
-     * to whether or not to retrieve the Keystore provider by "AndroidKeyStoreLegacy".
-     * This function can be removed once the transition to Keystore 2.0 is complete.
-     * b/171305684
-     *
-     * @return true if this provider was installed.
-     * @hide
-     */
-    public static boolean isInstalled() {
-        return sInstalled;
-    }
-
     /**
      * Installs a new instance of this provider (and the
      * {@link AndroidKeyStoreBCWorkaroundProvider}).
@@ -142,7 +125,6 @@
                 break;
             }
         }
-        sInstalled = true;
 
         Security.addProvider(new AndroidKeyStoreProvider());
         Provider workaroundProvider = new AndroidKeyStoreBCWorkaroundProvider();
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreRSACipherSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreRSACipherSpi.java
index 6ff9432..5848247 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreRSACipherSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreRSACipherSpi.java
@@ -21,7 +21,6 @@
 import android.hardware.security.keymint.KeyParameter;
 import android.security.keymaster.KeymasterDefs;
 import android.security.keystore.KeyProperties;
-import android.security.keystore.KeymasterUtils;
 import android.system.keystore2.Authorization;
 
 import java.security.AlgorithmParameters;
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java
index 32f98a2..3e2fb94 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java
@@ -30,7 +30,6 @@
 import android.security.keystore.KeyPermanentlyInvalidatedException;
 import android.security.keystore.KeyProperties;
 import android.security.keystore.KeyProtection;
-import android.security.keystore.KeymasterUtils;
 import android.security.keystore.SecureKeyImportUnavailableException;
 import android.security.keystore.WrappedKeyEntry;
 import android.system.keystore2.AuthenticatorSpec;
diff --git a/keystore/java/android/security/keystore2/KeymasterUtils.java b/keystore/java/android/security/keystore2/KeymasterUtils.java
new file mode 100644
index 0000000..de4696c
--- /dev/null
+++ b/keystore/java/android/security/keystore2/KeymasterUtils.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2021 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.keystore2;
+
+import android.security.keymaster.KeymasterArguments;
+import android.security.keymaster.KeymasterDefs;
+import android.security.keystore.KeyProperties;
+
+import java.security.ProviderException;
+
+/**
+ * @hide
+ */
+public abstract class KeymasterUtils {
+
+    private KeymasterUtils() {}
+
+    /** @hide */
+    static int getDigestOutputSizeBits(int keymasterDigest) {
+        switch (keymasterDigest) {
+            case KeymasterDefs.KM_DIGEST_NONE:
+                return -1;
+            case KeymasterDefs.KM_DIGEST_MD5:
+                return 128;
+            case KeymasterDefs.KM_DIGEST_SHA1:
+                return 160;
+            case KeymasterDefs.KM_DIGEST_SHA_2_224:
+                return 224;
+            case KeymasterDefs.KM_DIGEST_SHA_2_256:
+                return 256;
+            case KeymasterDefs.KM_DIGEST_SHA_2_384:
+                return 384;
+            case KeymasterDefs.KM_DIGEST_SHA_2_512:
+                return 512;
+            default:
+                throw new IllegalArgumentException("Unknown digest: " + keymasterDigest);
+        }
+    }
+
+    /** @hide */
+    static boolean isKeymasterBlockModeIndCpaCompatibleWithSymmetricCrypto(
+            int keymasterBlockMode) {
+        switch (keymasterBlockMode) {
+            case KeymasterDefs.KM_MODE_ECB:
+                return false;
+            case KeymasterDefs.KM_MODE_CBC:
+            case KeymasterDefs.KM_MODE_CTR:
+            case KeymasterDefs.KM_MODE_GCM:
+                return true;
+            default:
+                throw new IllegalArgumentException("Unsupported block mode: " + keymasterBlockMode);
+        }
+    }
+
+    /** @hide */
+    static boolean isKeymasterPaddingSchemeIndCpaCompatibleWithAsymmetricCrypto(
+            int keymasterPadding) {
+        switch (keymasterPadding) {
+            case KeymasterDefs.KM_PAD_NONE:
+                return false;
+            case KeymasterDefs.KM_PAD_RSA_OAEP:
+            case KeymasterDefs.KM_PAD_RSA_PKCS1_1_5_ENCRYPT:
+                return true;
+            default:
+                throw new IllegalArgumentException(
+                        "Unsupported asymmetric encryption padding scheme: " + keymasterPadding);
+        }
+    }
+
+    /**
+     * Adds {@code KM_TAG_MIN_MAC_LENGTH} tag, if necessary, to the keymaster arguments for
+     * generating or importing a key. This tag may only be needed for symmetric keys (e.g., HMAC,
+     * AES-GCM).
+     */
+    public static void addMinMacLengthAuthorizationIfNecessary(KeymasterArguments args,
+            int keymasterAlgorithm,
+            int[] keymasterBlockModes,
+            int[] keymasterDigests) {
+        switch (keymasterAlgorithm) {
+            case KeymasterDefs.KM_ALGORITHM_AES:
+                if (com.android.internal.util.ArrayUtils.contains(
+                        keymasterBlockModes, KeymasterDefs.KM_MODE_GCM)) {
+                    // AES GCM key needs the minimum length of AEAD tag specified.
+                    args.addUnsignedInt(KeymasterDefs.KM_TAG_MIN_MAC_LENGTH,
+                            AndroidKeyStoreAuthenticatedAESCipherSpi.GCM
+                                    .MIN_SUPPORTED_TAG_LENGTH_BITS);
+                }
+                break;
+            case KeymasterDefs.KM_ALGORITHM_HMAC:
+                // HMAC key needs the minimum length of MAC set to the output size of the associated
+                // digest. This is because we do not offer a way to generate shorter MACs and
+                // don't offer a way to verify MACs (other than by generating them).
+                if (keymasterDigests.length != 1) {
+                    throw new ProviderException(
+                            "Unsupported number of authorized digests for HMAC key: "
+                                    + keymasterDigests.length
+                                    + ". Exactly one digest must be authorized");
+                }
+                int keymasterDigest = keymasterDigests[0];
+                int digestOutputSizeBits = getDigestOutputSizeBits(keymasterDigest);
+                if (digestOutputSizeBits == -1) {
+                    throw new ProviderException(
+                            "HMAC key authorized for unsupported digest: "
+                                    + KeyProperties.Digest.fromKeymaster(keymasterDigest));
+                }
+                args.addUnsignedInt(KeymasterDefs.KM_TAG_MIN_MAC_LENGTH, digestOutputSizeBits);
+                break;
+        }
+    }
+}
diff --git a/native/android/OWNERS b/native/android/OWNERS
index d414ed4..6f7def8 100644
--- a/native/android/OWNERS
+++ b/native/android/OWNERS
@@ -2,3 +2,7 @@
 per-file libandroid_net.map.txt, net.c = codewiz@google.com, jchalard@google.com, junyulai@google.com
 per-file libandroid_net.map.txt, net.c = lorenzo@google.com, reminv@google.com, satk@google.com
 per-file system_fonts.cpp = file:/graphics/java/android/graphics/fonts/OWNERS
+
+per-file native_window_jni.cpp = file:/services/core/java/com/android/server/wm/OWNERS
+per-file native_activity.cpp = file:/services/core/java/com/android/server/wm/OWNERS
+per-file surface_control.cpp = file:/services/core/java/com/android/server/wm/OWNERS
diff --git a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java
index 550e324..10d68ba 100644
--- a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java
+++ b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java
@@ -50,7 +50,7 @@
 import android.widget.TextView;
 
 import com.android.internal.util.ArrayUtils;
-import com.android.internal.util.TrafficStatsConstants;
+import com.android.net.module.util.NetworkStackConstants;
 
 import java.io.IOException;
 import java.lang.reflect.Field;
@@ -238,7 +238,7 @@
                 HttpURLConnection urlConnection = null;
                 int httpResponseCode = 500;
                 int oldTag = TrafficStats.getAndSetThreadStatsTag(
-                        TrafficStatsConstants.TAG_SYSTEM_PROBE);
+                        NetworkStackConstants.TAG_SYSTEM_PROBE);
                 try {
                     urlConnection = (HttpURLConnection) mNetwork.openConnection(
                             new URL(mCm.getCaptivePortalServerUrl()));
diff --git a/packages/Connectivity/framework/aidl-export/android/net/IpPrefix.aidl b/packages/Connectivity/framework/aidl-export/android/net/IpPrefix.aidl
index 0d70f2a..3495efc 100644
--- a/packages/Connectivity/framework/aidl-export/android/net/IpPrefix.aidl
+++ b/packages/Connectivity/framework/aidl-export/android/net/IpPrefix.aidl
@@ -18,5 +18,5 @@
 package android.net;
 
 // @JavaOnlyStableParcelable only affects the parcelable when built as stable aidl (aidl_interface
-// build rule). IpPrefix is also used in cpp but only as non-stable aidl.
-@JavaOnlyStableParcelable parcelable IpPrefix cpp_header "binder/IpPrefix.h";
+// build rule).
+@JavaOnlyStableParcelable parcelable IpPrefix;
diff --git a/packages/Connectivity/framework/api/current.txt b/packages/Connectivity/framework/api/current.txt
index 0a9560a..ab290f9 100644
--- a/packages/Connectivity/framework/api/current.txt
+++ b/packages/Connectivity/framework/api/current.txt
@@ -298,7 +298,6 @@
     method @Nullable public android.net.NetworkSpecifier getNetworkSpecifier();
     method public int getOwnerUid();
     method public int getSignalStrength();
-    method @NonNull public java.util.Set<java.lang.Integer> getSubIds();
     method @Nullable public android.net.TransportInfo getTransportInfo();
     method public boolean hasCapability(int);
     method public boolean hasTransport(int);
@@ -408,7 +407,6 @@
     method public android.net.NetworkRequest.Builder removeTransportType(int);
     method @Deprecated public android.net.NetworkRequest.Builder setNetworkSpecifier(String);
     method public android.net.NetworkRequest.Builder setNetworkSpecifier(android.net.NetworkSpecifier);
-    method @NonNull public android.net.NetworkRequest.Builder setSubIds(@NonNull java.util.Set<java.lang.Integer>);
   }
 
   public class ParseException extends java.lang.RuntimeException {
diff --git a/packages/Connectivity/framework/api/module-lib-current.txt b/packages/Connectivity/framework/api/module-lib-current.txt
index cd96a1b..f2f5c1b 100644
--- a/packages/Connectivity/framework/api/module-lib-current.txt
+++ b/packages/Connectivity/framework/api/module-lib-current.txt
@@ -176,10 +176,12 @@
   }
 
   public final class VpnTransportInfo implements android.os.Parcelable android.net.TransportInfo {
-    ctor public VpnTransportInfo(int);
+    ctor public VpnTransportInfo(int, @Nullable String);
     method public int describeContents();
+    method @NonNull public android.net.VpnTransportInfo makeCopy(long);
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.net.VpnTransportInfo> CREATOR;
+    field @Nullable public final String sessionId;
     field public final int type;
   }
 
diff --git a/packages/Connectivity/framework/api/system-current.txt b/packages/Connectivity/framework/api/system-current.txt
index afd4fa0..0a82cb7 100644
--- a/packages/Connectivity/framework/api/system-current.txt
+++ b/packages/Connectivity/framework/api/system-current.txt
@@ -273,7 +273,9 @@
 
   public final class NetworkCapabilities implements android.os.Parcelable {
     method @NonNull public int[] getAdministratorUids();
+    method @Nullable public static String getCapabilityCarrierName(int);
     method @Nullable public String getSsid();
+    method @NonNull public java.util.Set<java.lang.Integer> getSubIds();
     method @NonNull public int[] getTransportTypes();
     method public boolean isPrivateDnsBroken();
     method public boolean satisfiedByNetworkCapabilities(@Nullable android.net.NetworkCapabilities);
@@ -327,6 +329,7 @@
 
   public static class NetworkRequest.Builder {
     method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_SIGNAL_STRENGTH_WAKEUP) public android.net.NetworkRequest.Builder setSignalStrength(int);
+    method @NonNull public android.net.NetworkRequest.Builder setSubIds(@NonNull java.util.Set<java.lang.Integer>);
   }
 
   public final class NetworkScore implements android.os.Parcelable {
diff --git a/packages/Connectivity/framework/src/android/net/ConnectivityManager.java b/packages/Connectivity/framework/src/android/net/ConnectivityManager.java
index c6f4e0b..92ed7fc 100644
--- a/packages/Connectivity/framework/src/android/net/ConnectivityManager.java
+++ b/packages/Connectivity/framework/src/android/net/ConnectivityManager.java
@@ -3140,18 +3140,27 @@
     }
 
     /**
-     * Set a network-independent global http proxy.  This is not normally what you want
-     * for typical HTTP proxies - they are general network dependent.  However if you're
-     * doing something unusual like general internal filtering this may be useful.  On
-     * a private network where the proxy is not accessible, you may break HTTP using this.
+     * Set a network-independent global HTTP proxy.
      *
-     * @param p A {@link ProxyInfo} object defining the new global
-     *        HTTP proxy.  A {@code null} value will clear the global HTTP proxy.
+     * This sets an HTTP proxy that applies to all networks and overrides any network-specific
+     * proxy. If set, HTTP libraries that are proxy-aware will use this global proxy when
+     * accessing any network, regardless of what the settings for that network are.
+     *
+     * Note that HTTP proxies are by nature typically network-dependent, and setting a global
+     * proxy is likely to break networking on multiple networks. This method is only meant
+     * for device policy clients looking to do general internal filtering or similar use cases.
+     *
+     * {@see #getGlobalProxy}
+     * {@see LinkProperties#getHttpProxy}
+     *
+     * @param p A {@link ProxyInfo} object defining the new global HTTP proxy. Calling this
+     *          method with a {@code null} value will clear the global HTTP proxy.
      * @hide
      */
+    // Used by Device Policy Manager to set the global proxy.
     @SystemApi(client = MODULE_LIBRARIES)
     @RequiresPermission(android.Manifest.permission.NETWORK_STACK)
-    public void setGlobalProxy(@Nullable ProxyInfo p) {
+    public void setGlobalProxy(@Nullable final ProxyInfo p) {
         try {
             mService.setGlobalProxy(p);
         } catch (RemoteException e) {
diff --git a/packages/Connectivity/framework/src/android/net/DnsResolver.java b/packages/Connectivity/framework/src/android/net/DnsResolver.java
index 3f7660f..dac88ad 100644
--- a/packages/Connectivity/framework/src/android/net/DnsResolver.java
+++ b/packages/Connectivity/framework/src/android/net/DnsResolver.java
@@ -500,7 +500,7 @@
                             try {
                                 resp = resNetworkResult(fd);  // Closes fd, marks it invalid.
                             } catch (ErrnoException e) {
-                                Log.e(TAG, "resNetworkResult:" + e.toString());
+                                Log.w(TAG, "resNetworkResult:" + e.toString());
                                 exception = e;
                             }
                         }
diff --git a/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java b/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java
index 7e70891..d39f4fb 100644
--- a/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java
+++ b/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java
@@ -728,6 +728,23 @@
         return ((mNetworkCapabilities & CONNECTIVITY_MANAGED_CAPABILITIES) != 0);
     }
 
+    /**
+     * Get the name of the given capability that carriers use.
+     * If the capability does not have a carrier-name, returns null.
+     *
+     * @param capability The capability to get the carrier-name of.
+     * @return The carrier-name of the capability, or null if it doesn't exist.
+     * @hide
+     */
+    @SystemApi
+    public static @Nullable String getCapabilityCarrierName(@NetCapability int capability) {
+        if (capability == NET_CAPABILITY_ENTERPRISE) {
+            return capabilityNameOf(capability);
+        } else {
+            return null;
+        }
+    }
+
     private void combineNetCapabilities(@NonNull NetworkCapabilities nc) {
         final long wantedCaps = this.mNetworkCapabilities | nc.mNetworkCapabilities;
         final long unwantedCaps =
@@ -2346,9 +2363,15 @@
 
     /**
      * Gets the subscription ID set that associated to this network or request.
+     *
+     * <p>Instances of NetworkCapabilities will only have this field populated by the system if the
+     * receiver holds the NETWORK_FACTORY permission. In all other cases, it will be the empty set.
+     *
      * @return
+     * @hide
      */
     @NonNull
+    @SystemApi
     public Set<Integer> getSubIds() {
         return new ArraySet<>(mSubIds);
     }
@@ -2713,10 +2736,17 @@
         /**
          * Set the subscription ID set.
          *
+         * <p>SubIds are populated in NetworkCapability instances from the system only for callers
+         * that hold the NETWORK_FACTORY permission. Similarly, the system will reject any
+         * NetworkRequests filed with a non-empty set of subIds unless the caller holds the
+         * NETWORK_FACTORY permission.
+         *
          * @param subIds a set that represent the subscription IDs. Empty if clean up.
          * @return this builder.
+         * @hide
          */
         @NonNull
+        @SystemApi
         public Builder setSubIds(@NonNull final Set<Integer> subIds) {
             mCaps.setSubIds(subIds);
             return this;
diff --git a/packages/Connectivity/framework/src/android/net/NetworkRequest.java b/packages/Connectivity/framework/src/android/net/NetworkRequest.java
index 38691ef..5d40417 100644
--- a/packages/Connectivity/framework/src/android/net/NetworkRequest.java
+++ b/packages/Connectivity/framework/src/android/net/NetworkRequest.java
@@ -501,9 +501,14 @@
          * A network will satisfy this request only if it matches one of the subIds in this set.
          * An empty set matches all networks, including those without a subId.
          *
+         * <p>Registering a NetworkRequest with a non-empty set of subIds requires the
+         * NETWORK_FACTORY permission.
+         *
          * @param subIds A {@code Set} that represents subscription IDs.
+         * @hide
          */
         @NonNull
+        @SystemApi
         public Builder setSubIds(@NonNull Set<Integer> subIds) {
             mNetworkCapabilities.setSubIds(subIds);
             return this;
diff --git a/packages/Connectivity/framework/src/android/net/VpnTransportInfo.java b/packages/Connectivity/framework/src/android/net/VpnTransportInfo.java
index cd8f4c0..ba83a44 100644
--- a/packages/Connectivity/framework/src/android/net/VpnTransportInfo.java
+++ b/packages/Connectivity/framework/src/android/net/VpnTransportInfo.java
@@ -17,11 +17,14 @@
 package android.net;
 
 import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
+import static android.net.NetworkCapabilities.REDACT_FOR_NETWORK_SETTINGS;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.text.TextUtils;
 
 import java.util.Objects;
 
@@ -38,8 +41,26 @@
     /** Type of this VPN. */
     public final int type;
 
-    public VpnTransportInfo(int type) {
+    @Nullable
+    public final String sessionId;
+
+    @Override
+    public long getApplicableRedactions() {
+        return REDACT_FOR_NETWORK_SETTINGS;
+    }
+
+    /**
+     * Create a copy of a {@link VpnTransportInfo} with the sessionId redacted if necessary.
+     */
+    @NonNull
+    public VpnTransportInfo makeCopy(long redactions) {
+        return new VpnTransportInfo(type,
+            ((redactions & REDACT_FOR_NETWORK_SETTINGS) != 0) ? null : sessionId);
+    }
+
+    public VpnTransportInfo(int type, @Nullable String sessionId) {
         this.type = type;
+        this.sessionId = sessionId;
     }
 
     @Override
@@ -47,17 +68,17 @@
         if (!(o instanceof VpnTransportInfo)) return false;
 
         VpnTransportInfo that = (VpnTransportInfo) o;
-        return this.type == that.type;
+        return (this.type == that.type) && TextUtils.equals(this.sessionId, that.sessionId);
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(type);
+        return Objects.hash(type, sessionId);
     }
 
     @Override
     public String toString() {
-        return String.format("VpnTransportInfo{type=%d}", type);
+        return String.format("VpnTransportInfo{type=%d, sessionId=%s}", type, sessionId);
     }
 
     @Override
@@ -68,12 +89,13 @@
     @Override
     public void writeToParcel(@NonNull Parcel dest, int flags) {
         dest.writeInt(type);
+        dest.writeString(sessionId);
     }
 
     public static final @NonNull Creator<VpnTransportInfo> CREATOR =
             new Creator<VpnTransportInfo>() {
         public VpnTransportInfo createFromParcel(Parcel in) {
-            return new VpnTransportInfo(in.readInt());
+            return new VpnTransportInfo(in.readInt(), in.readString());
         }
         public VpnTransportInfo[] newArray(int size) {
             return new VpnTransportInfo[size];
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
index c57d4ad..cbb5105 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
@@ -66,31 +66,40 @@
         @Override
         public void onCapabilitiesChanged(
                 Network network, NetworkCapabilities networkCapabilities) {
+            WifiInfo wifiInfo = (WifiInfo) networkCapabilities.getTransportInfo();
+            updateWifiInfo(wifiInfo);
+            updateStatusLabel();
+            mCallback.run();
+        }
+
+        @Override
+        public void onLost(Network network) {
+            updateWifiInfo(null);
             updateStatusLabel();
             mCallback.run();
         }
     };
     private final NetworkCallback mDefaultNetworkCallback = new NetworkCallback() {
-                @Override
-                public void onCapabilitiesChanged(Network network, NetworkCapabilities nc) {
-                    // network is now the default network, and its capabilities are nc.
-                    // This method will always be called immediately after the network becomes the
-                    // default, in addition to any time the capabilities change while the network is
-                    // the default.
-                    mDefaultNetwork = network;
-                    mDefaultNetworkCapabilities = nc;
-                    updateStatusLabel();
-                    mCallback.run();
-                }
-                @Override
-                public void onLost(Network network) {
-                    // The system no longer has a default network.
-                    mDefaultNetwork = null;
-                    mDefaultNetworkCapabilities = null;
-                    updateStatusLabel();
-                    mCallback.run();
-                }
-            };
+        @Override
+        public void onCapabilitiesChanged(Network network, NetworkCapabilities nc) {
+            // network is now the default network, and its capabilities are nc.
+            // This method will always be called immediately after the network becomes the
+            // default, in addition to any time the capabilities change while the network is
+            // the default.
+            mDefaultNetwork = network;
+            mDefaultNetworkCapabilities = nc;
+            updateStatusLabel();
+            mCallback.run();
+        }
+        @Override
+        public void onLost(Network network) {
+            // The system no longer has a default network.
+            mDefaultNetwork = null;
+            mDefaultNetworkCapabilities = null;
+            updateStatusLabel();
+            mCallback.run();
+        }
+    };
     private Network mDefaultNetwork = null;
     private NetworkCapabilities mDefaultNetworkCapabilities = null;
     private final Runnable mCallback;
@@ -170,32 +179,22 @@
         String action = intent.getAction();
         if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
             updateWifiState();
-        } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
-            updateWifiState();
-            final NetworkInfo networkInfo =
-                    intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
-            connected = networkInfo != null && networkInfo.isConnected();
-            mWifiInfo = null;
-            ssid = null;
-            if (connected) {
-                mWifiInfo = mWifiManager.getConnectionInfo();
-                if (mWifiInfo != null) {
-                    if (mWifiInfo.isPasspointAp() || mWifiInfo.isOsuAp()) {
-                        ssid = mWifiInfo.getPasspointProviderFriendlyName();
-                    } else {
-                        ssid = getValidSsid(mWifiInfo);
-                    }
-                    updateRssi(mWifiInfo.getRssi());
-                    maybeRequestNetworkScore();
-                }
+        }
+    }
+
+    private void updateWifiInfo(WifiInfo wifiInfo) {
+        updateWifiState();
+        connected = wifiInfo != null;
+        mWifiInfo = wifiInfo;
+        ssid = null;
+        if (mWifiInfo != null) {
+            if (mWifiInfo.isPasspointAp() || mWifiInfo.isOsuAp()) {
+                ssid = mWifiInfo.getPasspointProviderFriendlyName();
+            } else {
+                ssid = getValidSsid(mWifiInfo);
             }
-            updateStatusLabel();
-            mCallback.run();
-        } else if (action.equals(WifiManager.RSSI_CHANGED_ACTION)) {
-            // Default to -200 as its below WifiManager.MIN_RSSI.
-            updateRssi(intent.getIntExtra(WifiManager.EXTRA_NEW_RSSI, -200));
-            updateStatusLabel();
-            mCallback.run();
+            updateRssi(mWifiInfo.getRssi());
+            maybeRequestNetworkScore();
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index df00a4f..7e3ffde 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -344,8 +344,6 @@
 
         // broadcasts
         IntentFilter filter = new IntentFilter();
-        filter.addAction(WifiManager.RSSI_CHANGED_ACTION);
-        filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
         filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
         filter.addAction(Intent.ACTION_SIM_STATE_CHANGED);
         filter.addAction(TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
index 4ae9665..3c0b07a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
@@ -101,11 +101,7 @@
                 wifiDesc, mCurrentState.isTransient, mCurrentState.statusLabel);
     }
 
-    /**
-     * Fetches wifi initial state replacing the initial sticky broadcast.
-     */
-    public void fetchInitialState() {
-        mWifiTracker.fetchInitialState();
+    private void copyWifiStates() {
         mCurrentState.enabled = mWifiTracker.enabled;
         mCurrentState.isDefault = mWifiTracker.isDefaultNetwork;
         mCurrentState.connected = mWifiTracker.connected;
@@ -113,6 +109,14 @@
         mCurrentState.rssi = mWifiTracker.rssi;
         mCurrentState.level = mWifiTracker.level;
         mCurrentState.statusLabel = mWifiTracker.statusLabel;
+    }
+
+    /**
+     * Fetches wifi initial state replacing the initial sticky broadcast.
+     */
+    public void fetchInitialState() {
+        mWifiTracker.fetchInitialState();
+        copyWifiStates();
         notifyListenersIfNecessary();
     }
 
@@ -121,19 +125,12 @@
      */
     public void handleBroadcast(Intent intent) {
         mWifiTracker.handleBroadcast(intent);
-        mCurrentState.enabled = mWifiTracker.enabled;
-        mCurrentState.isDefault = mWifiTracker.isDefaultNetwork;
-        mCurrentState.connected = mWifiTracker.connected;
-        mCurrentState.ssid = mWifiTracker.ssid;
-        mCurrentState.rssi = mWifiTracker.rssi;
-        mCurrentState.level = mWifiTracker.level;
-        mCurrentState.statusLabel = mWifiTracker.statusLabel;
+        copyWifiStates();
         notifyListenersIfNecessary();
     }
 
     private void handleStatusUpdated() {
-        mCurrentState.statusLabel = mWifiTracker.statusLabel;
-        mCurrentState.isDefault = mWifiTracker.isDefaultNetwork;
+        copyWifiStates();
         notifyListenersIfNecessary();
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
index 3a84e31..0dfcf7a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
@@ -40,7 +40,9 @@
 import android.net.ConnectivityManager;
 import android.net.Network;
 import android.net.NetworkCapabilities;
+import android.net.NetworkRequest;
 import android.net.NetworkScoreManager;
+import android.net.wifi.WifiInfo;
 import android.net.wifi.WifiManager;
 import android.os.Handler;
 import android.provider.Settings;
@@ -51,7 +53,6 @@
 import android.telephony.SignalStrength;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
-import android.telephony.TelephonyCallback;
 import android.telephony.TelephonyDisplayInfo;
 import android.telephony.TelephonyManager;
 import android.testing.TestableLooper;
@@ -115,6 +116,7 @@
     protected int mSubId;
 
     private NetworkCapabilities mNetCapabilities;
+    private ConnectivityManager.NetworkCallback mDefaultNetworkCallback;
     private ConnectivityManager.NetworkCallback mNetworkCallback;
 
     @Rule
@@ -214,6 +216,10 @@
             ArgumentCaptor.forClass(ConnectivityManager.NetworkCallback.class);
         verify(mMockCm, atLeastOnce())
             .registerDefaultNetworkCallback(callbackArg.capture(), isA(Handler.class));
+        mDefaultNetworkCallback = callbackArg.getValue();
+        assertNotNull(mDefaultNetworkCallback);
+        verify(mMockCm, atLeastOnce()).registerNetworkCallback(
+                isA(NetworkRequest.class), callbackArg.capture(), isA(Handler.class));
         mNetworkCallback = callbackArg.getValue();
         assertNotNull(mNetworkCallback);
     }
@@ -270,10 +276,19 @@
     }
 
     public void setConnectivityViaCallback(
-        int networkType, boolean validated, boolean isConnected){
+            int networkType, boolean validated, boolean isConnected, WifiInfo wifiInfo) {
+        mNetCapabilities.setTransportInfo(wifiInfo);
         setConnectivityCommon(networkType, validated, isConnected);
-        mNetworkCallback.onCapabilitiesChanged(
+        mDefaultNetworkCallback.onCapabilitiesChanged(
             mock(Network.class), new NetworkCapabilities(mNetCapabilities));
+        if (networkType == NetworkCapabilities.TRANSPORT_WIFI) {
+            if (isConnected) {
+                mNetworkCallback.onCapabilitiesChanged(
+                        mock(Network.class), new NetworkCapabilities(mNetCapabilities));
+            } else {
+                mNetworkCallback.onLost(mock(Network.class));
+            }
+        }
     }
 
     private void setConnectivityCommon(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java
index 988e022..9c9d6ea 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java
@@ -32,6 +32,7 @@
     // These match the constants in WifiManager and need to be kept up to date.
     private static final int MIN_RSSI = -100;
     private static final int MAX_RSSI = -55;
+    private WifiInfo mWifiInfo = mock(WifiInfo.class);
 
     @Test
     public void testWifiIcon() {
@@ -41,15 +42,16 @@
 
         setWifiState(true, testSsid);
         setWifiLevel(0);
+        setConnectivityViaCallback(NetworkCapabilities.TRANSPORT_WIFI, false, true, mWifiInfo);
         // Connected, but still not validated - does not show
         verifyLastWifiIcon(false, WifiIcons.WIFI_SIGNAL_STRENGTH[0][0]);
 
         for (int testLevel = 0; testLevel < WifiIcons.WIFI_LEVEL_COUNT; testLevel++) {
             setWifiLevel(testLevel);
 
-            setConnectivityViaBroadcast(NetworkCapabilities.TRANSPORT_WIFI, true, true);
+            setConnectivityViaCallback(NetworkCapabilities.TRANSPORT_WIFI, true, true, mWifiInfo);
             verifyLastWifiIcon(true, WifiIcons.WIFI_SIGNAL_STRENGTH[1][testLevel]);
-            setConnectivityViaBroadcast(NetworkCapabilities.TRANSPORT_WIFI, false, true);
+            setConnectivityViaCallback(NetworkCapabilities.TRANSPORT_WIFI, false, true, mWifiInfo);
             // Icon does not show if not validated
             verifyLastWifiIcon(false, WifiIcons.WIFI_SIGNAL_STRENGTH[0][testLevel]);
         }
@@ -69,10 +71,10 @@
         for (int testLevel = 0; testLevel < WifiIcons.WIFI_LEVEL_COUNT; testLevel++) {
             setWifiLevel(testLevel);
 
-            setConnectivityViaBroadcast(NetworkCapabilities.TRANSPORT_WIFI, true, true);
+            setConnectivityViaCallback(NetworkCapabilities.TRANSPORT_WIFI, true, true, mWifiInfo);
             verifyLastQsWifiIcon(true, true, WifiIcons.QS_WIFI_SIGNAL_STRENGTH[1][testLevel],
                     testSsid);
-            setConnectivityViaBroadcast(NetworkCapabilities.TRANSPORT_WIFI, false, true);
+            setConnectivityViaCallback(NetworkCapabilities.TRANSPORT_WIFI, false, true, mWifiInfo);
             verifyLastQsWifiIcon(true, true, WifiIcons.QS_WIFI_SIGNAL_STRENGTH[0][testLevel],
                     testSsid);
         }
@@ -86,7 +88,7 @@
         setWifiEnabled(true);
         setWifiState(true, testSsid);
         setWifiLevel(testLevel);
-        setConnectivityViaBroadcast(NetworkCapabilities.TRANSPORT_WIFI, true, true);
+        setConnectivityViaCallback(NetworkCapabilities.TRANSPORT_WIFI, true, true, mWifiInfo);
         verifyLastQsWifiIcon(true, true,
                 WifiIcons.QS_WIFI_SIGNAL_STRENGTH[1][testLevel], testSsid);
 
@@ -111,14 +113,14 @@
         setWifiEnabled(true);
         setWifiState(true, testSsid);
         setWifiLevel(testLevel);
-        setConnectivityViaBroadcast(NetworkCapabilities.TRANSPORT_WIFI, true, true);
+        setConnectivityViaCallback(NetworkCapabilities.TRANSPORT_WIFI, true, true, mWifiInfo);
         verifyLastWifiIcon(true, WifiIcons.WIFI_SIGNAL_STRENGTH[1][testLevel]);
 
         setupDefaultSignal();
         setGsmRoaming(true);
         // Still be on wifi though.
-        setConnectivityViaBroadcast(NetworkCapabilities.TRANSPORT_WIFI, true, true);
-        setConnectivityViaBroadcast(NetworkCapabilities.TRANSPORT_CELLULAR, false, false);
+        setConnectivityViaCallback(NetworkCapabilities.TRANSPORT_WIFI, true, true, mWifiInfo);
+        setConnectivityViaCallback(NetworkCapabilities.TRANSPORT_CELLULAR, false, false, mWifiInfo);
         verifyLastMobileDataIndicators(true,
                 DEFAULT_LEVEL,
                 0, true);
@@ -132,10 +134,10 @@
         setWifiEnabled(true);
         setWifiState(true, testSsid);
         setWifiLevel(testLevel);
-        setConnectivityViaBroadcast(NetworkCapabilities.TRANSPORT_WIFI, true, true);
+        setConnectivityViaCallback(NetworkCapabilities.TRANSPORT_WIFI, true, true, mWifiInfo);
         verifyLastWifiIcon(true, WifiIcons.WIFI_SIGNAL_STRENGTH[1][testLevel]);
 
-        setConnectivityViaCallback(NetworkCapabilities.TRANSPORT_WIFI, false, true);
+        setConnectivityViaCallback(NetworkCapabilities.TRANSPORT_WIFI, false, true, mWifiInfo);
         verifyLastWifiIcon(false, WifiIcons.WIFI_SIGNAL_STRENGTH[0][testLevel]);
     }
 
@@ -147,11 +149,11 @@
         setWifiEnabled(true);
         setWifiState(true, testSsid);
         setWifiLevel(testLevel);
-        setConnectivityViaBroadcast(NetworkCapabilities.TRANSPORT_WIFI, true, true);
+        setConnectivityViaCallback(NetworkCapabilities.TRANSPORT_WIFI, true, true, mWifiInfo);
         verifyLastWifiIcon(true, WifiIcons.WIFI_SIGNAL_STRENGTH[1][testLevel]);
 
         setWifiState(false, testSsid);
-        setConnectivityViaCallback(NetworkCapabilities.TRANSPORT_WIFI, false, false);
+        setConnectivityViaCallback(NetworkCapabilities.TRANSPORT_WIFI, false, false, mWifiInfo);
         verifyLastWifiIcon(false, WifiIcons.WIFI_NO_NETWORK);
     }
 
@@ -162,14 +164,14 @@
         setWifiEnabled(true);
         verifyLastWifiIcon(false, WifiIcons.WIFI_NO_NETWORK);
 
-        setConnectivityViaCallback(NetworkCapabilities.TRANSPORT_VPN, false, true);
-        setConnectivityViaCallback(NetworkCapabilities.TRANSPORT_VPN, true, true);
+        setConnectivityViaCallback(NetworkCapabilities.TRANSPORT_VPN, false, true, mWifiInfo);
+        setConnectivityViaCallback(NetworkCapabilities.TRANSPORT_VPN, true, true, mWifiInfo);
         verifyLastWifiIcon(false, WifiIcons.WIFI_NO_NETWORK);
 
         // Mock calling setUnderlyingNetworks.
         setWifiState(true, testSsid);
         setWifiLevel(testLevel);
-        setConnectivityViaCallback(NetworkCapabilities.TRANSPORT_WIFI, true, true);
+        setConnectivityViaCallback(NetworkCapabilities.TRANSPORT_WIFI, true, true, mWifiInfo);
         verifyLastWifiIcon(true, WifiIcons.WIFI_SIGNAL_STRENGTH[1][testLevel]);
     }
 
@@ -209,6 +211,7 @@
         int rssi = (int)(MIN_RSSI + level * amountPerLevel);
         // Put RSSI in the middle of the range.
         rssi += amountPerLevel / 2;
+        when(mWifiInfo.getRssi()).thenReturn(rssi);
         Intent i = new Intent(WifiManager.RSSI_CHANGED_ACTION);
         i.putExtra(WifiManager.EXTRA_NEW_RSSI, rssi);
         mNetworkController.onReceive(mContext, i);
@@ -224,10 +227,8 @@
         Intent i = new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION);
         NetworkInfo networkInfo = mock(NetworkInfo.class);
         when(networkInfo.isConnected()).thenReturn(connected);
-
-        WifiInfo wifiInfo = mock(WifiInfo.class);
-        when(wifiInfo.getSSID()).thenReturn(ssid);
-        when(mMockWm.getConnectionInfo()).thenReturn(wifiInfo);
+        when(mWifiInfo.getSSID()).thenReturn(ssid);
+        when(mMockWm.getConnectionInfo()).thenReturn(mWifiInfo);
 
         i.putExtra(WifiManager.EXTRA_NETWORK_INFO, networkInfo);
         mNetworkController.onReceive(mContext, i);
diff --git a/packages/WAPPushManager/AndroidManifest.xml b/packages/WAPPushManager/AndroidManifest.xml
index a75fb2d..15f01e6 100644
--- a/packages/WAPPushManager/AndroidManifest.xml
+++ b/packages/WAPPushManager/AndroidManifest.xml
@@ -27,7 +27,8 @@
 
     <original-package android:name="com.android.smspush" />
     <application
-        android:allowClearUserData="false">
+        android:allowClearUserData="false"
+        android:directBootAware="true">
         <service android:name=".WapPushManager"
             android:permission="com.android.smspush.WAPPUSH_MANAGER_BIND"
             android:exported="true">
diff --git a/packages/WAPPushManager/src/com/android/smspush/WapPushManager.java b/packages/WAPPushManager/src/com/android/smspush/WapPushManager.java
index dc2707b..951e64f 100755
--- a/packages/WAPPushManager/src/com/android/smspush/WapPushManager.java
+++ b/packages/WAPPushManager/src/com/android/smspush/WapPushManager.java
@@ -26,17 +26,21 @@
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.database.Cursor;
-import android.database.sqlite.SQLiteOpenHelper;
 import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
 import android.os.Build;
 import android.os.IBinder;
 import android.os.PowerManager;
 import android.os.RemoteException;
+import android.os.UserManager;
 import android.util.Log;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.IWapPushManager;
 import com.android.internal.telephony.WapPushManagerParams;
 
+import java.io.File;
+
 /**
  * The WapPushManager service is implemented to process incoming
  * WAP Push messages and to maintain the Receiver Application/Application
@@ -67,8 +71,13 @@
     /**
      * Inner class that deals with application ID table
      */
-    private class WapPushManDBHelper extends SQLiteOpenHelper {
-        WapPushManDBHelper(Context context) {
+    @VisibleForTesting
+    public static class WapPushManDBHelper extends SQLiteOpenHelper {
+        /**
+         * Constructor
+         */
+        @VisibleForTesting
+        public WapPushManDBHelper(Context context) {
             super(context, DATABASE_NAME, null, WAP_PUSH_MANAGER_VERSION);
             if (LOCAL_LOGV) Log.v(LOG_TAG, "helper instance created.");
         }
@@ -269,10 +278,6 @@
                 int app_type, boolean need_signature, boolean further_processing) {
             WapPushManDBHelper dbh = getDatabase(mContext);
             SQLiteDatabase db = dbh.getWritableDatabase();
-            WapPushManDBHelper.queryData lastapp = dbh.queryLastApp(db, x_app_id, content_type);
-            boolean ret = false;
-            boolean insert = false;
-            int sq = 0;
 
             if (!appTypeCheck(app_type)) {
                 Log.w(LOG_TAG, "invalid app_type " + app_type + ". app_type must be "
@@ -280,34 +285,8 @@
                         + WapPushManagerParams.APP_TYPE_SERVICE);
                 return false;
             }
-
-            if (lastapp == null) {
-                insert = true;
-                sq = 0;
-            } else if (!lastapp.packageName.equals(package_name) ||
-                    !lastapp.className.equals(class_name)) {
-                insert = true;
-                sq = lastapp.installOrder + 1;
-            }
-
-            if (insert) {
-                ContentValues values = new ContentValues();
-
-                values.put("x_wap_application", x_app_id);
-                values.put("content_type", content_type);
-                values.put("package_name", package_name);
-                values.put("class_name", class_name);
-                values.put("app_type", app_type);
-                values.put("need_signature", need_signature ? 1 : 0);
-                values.put("further_processing", further_processing ? 1 : 0);
-                values.put("install_order", sq);
-                db.insert(APPID_TABLE_NAME, null, values);
-                if (LOCAL_LOGV) Log.v(LOG_TAG, "add:" + x_app_id + ":" + content_type
-                        + " " + package_name + "." + class_name
-                        + ", newsq:" + sq);
-                ret = true;
-            }
-
+            boolean ret = insertPackage(dbh, db, x_app_id, content_type, package_name, class_name,
+                    app_type, need_signature, further_processing);
             db.close();
 
             return ret;
@@ -404,11 +383,91 @@
     protected WapPushManDBHelper getDatabase(Context context) {
         if (mDbHelper == null) {
             if (LOCAL_LOGV) Log.v(LOG_TAG, "create new db inst.");
-            mDbHelper = new WapPushManDBHelper(context);
+            mDbHelper = new WapPushManDBHelper(context.createDeviceProtectedStorageContext());
         }
+        // Migrate existing legacy database into the device encrypted storage.
+        migrateWapPushManDBIfNeeded(context);
         return mDbHelper;
     }
 
+    /**
+     * Inserts a package information into a database
+     */
+    @VisibleForTesting
+    public boolean insertPackage(WapPushManDBHelper dbh, SQLiteDatabase db, String appId,
+            String contentType, String packageName, String className, int appType,
+            boolean needSignature, boolean furtherProcessing) {
+
+        WapPushManDBHelper.queryData lastapp = dbh.queryLastApp(db, appId, contentType);
+        boolean insert = false;
+        int sq = 0;
+
+        if (lastapp == null) {
+            insert = true;
+            sq = 0;
+        } else if (!lastapp.packageName.equals(packageName)
+                || !lastapp.className.equals(className)) {
+            insert = true;
+            sq = lastapp.installOrder + 1;
+        }
+
+        if (insert) {
+            ContentValues values = new ContentValues();
+
+            values.put("x_wap_application", appId);
+            values.put("content_type", contentType);
+            values.put("package_name", packageName);
+            values.put("class_name", className);
+            values.put("app_type", appType);
+            values.put("need_signature", needSignature ? 1 : 0);
+            values.put("further_processing", furtherProcessing ? 1 : 0);
+            values.put("install_order", sq);
+            db.insert(APPID_TABLE_NAME, null, values);
+            if (LOCAL_LOGV) {
+                Log.v(LOG_TAG, "add:" + appId + ":" + contentType + " " + packageName
+                        + "." + className + ", newsq:" + sq);
+            }
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Migrates a legacy database into the device encrypted storage
+     */
+    private void migrateWapPushManDBIfNeeded(Context context) {
+        UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
+        File file = context.getDatabasePath(DATABASE_NAME);
+        if (!userManager.isUserUnlocked() || !file.exists()) {
+            // Check if the device is unlocked because a legacy database can't access during
+            // DirectBoot.
+            return;
+        }
+
+        // Migration steps below:
+        // 1. Merge the package info to legacy database if there is any package info which is
+        // registered during DirectBoot.
+        // 2. Move the data base to the device encryped storage.
+        WapPushManDBHelper legacyDbHelper = new WapPushManDBHelper(context);
+        SQLiteDatabase legacyDb = legacyDbHelper.getWritableDatabase();
+        SQLiteDatabase db = mDbHelper.getWritableDatabase();
+        Cursor cur = db.query(APPID_TABLE_NAME, null, null, null, null, null, null);
+        while (cur.moveToNext()) {
+            insertPackage(legacyDbHelper, legacyDb,
+                    cur.getString(cur.getColumnIndex("x_wap_application")),
+                    cur.getString(cur.getColumnIndex("content_type")),
+                    cur.getString(cur.getColumnIndex("package_name")),
+                    cur.getString(cur.getColumnIndex("class_name")),
+                    cur.getInt(cur.getColumnIndex("app_type")),
+                    cur.getInt(cur.getColumnIndex("need_signature")) == 1,
+                    cur.getInt(cur.getColumnIndex("further_processing")) == 1);
+        }
+        cur.close();
+        legacyDb.close();
+        db.close();
+        context.createDeviceProtectedStorageContext().moveDatabaseFrom(context, DATABASE_NAME);
+        Log.i(LOG_TAG, "Migrated the legacy database.");
+    }
 
     /**
      * This method is used for testing
diff --git a/packages/WAPPushManager/tests/src/com/android/smspush/unitTests/WapPushTest.java b/packages/WAPPushManager/tests/src/com/android/smspush/unitTests/WapPushTest.java
index f7afc57..b9dac4e 100644
--- a/packages/WAPPushManager/tests/src/com/android/smspush/unitTests/WapPushTest.java
+++ b/packages/WAPPushManager/tests/src/com/android/smspush/unitTests/WapPushTest.java
@@ -21,6 +21,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.ServiceConnection;
+import android.database.sqlite.SQLiteDatabase;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.provider.Telephony.Sms.Intents;
@@ -33,7 +34,9 @@
 import com.android.internal.telephony.uicc.IccUtils;
 import com.android.internal.util.HexDump;
 import com.android.smspush.WapPushManager;
+import com.android.smspush.WapPushManager.WapPushManDBHelper;
 
+import java.io.File;
 import java.util.Random;
 
 /**
@@ -467,8 +470,9 @@
         try {
             super.setUp();
             // get verifier
-            getContext().bindService(new Intent(IDataVerify.class.getName()),
-                    mConn, Context.BIND_AUTO_CREATE);
+            Intent intent = new Intent(IDataVerify.class.getName());
+            intent.setPackage("com.android.smspush.unitTests");
+            getContext().bindService(intent, mConn, Context.BIND_AUTO_CREATE);
         } catch (Exception e) {
             Log.w(LOG_TAG, "super exception");
         }
@@ -552,15 +556,15 @@
     }
 
     /**
-     * Add sqlite injection test
+     * Sqlite injection test
      */
-    public void testAddPackage0() {
+    public void testSqliteInjection() {
         String inject = "' union select 0,'com.android.settings','com.android.settings.Settings',0,0,0--";
 
-        // insert new data
+        // update data
         IWapPushManager iwapman = getInterface();
         try {
-            assertFalse(iwapman.addPackage(
+            assertFalse(iwapman.updatePackage(
                     inject,
                     Integer.toString(mContentTypeValue),
                     mPackageName, mClassName,
@@ -2528,4 +2532,45 @@
         mMessageBody = originalMessageBody;
     }
 
+    /**
+     * DataBase migration test.
+     */
+    public void testDataBaseMigration() {
+        IWapPushManager iwapman = getInterface();
+        WapPushManager wpman = getService();
+        Context context = getContext();
+
+        addPackageToLegacyDB(mAppIdValue, mContentTypeValue, mPackageName, mClassName,
+                WapPushManagerParams.APP_TYPE_SERVICE, true, true);
+        addPackageToLegacyDB(mAppIdValue + 10, mContentTypeValue, mPackageName, mClassName,
+                WapPushManagerParams.APP_TYPE_SERVICE, true, true);
+
+        File oldDbFile = context.getDatabasePath("wappush.db");
+        assertTrue(oldDbFile.exists());
+        assertTrue(wpman.verifyData(Integer.toString(mAppIdValue),
+                Integer.toString(mContentTypeValue),
+                mPackageName, mClassName,
+                WapPushManagerParams.APP_TYPE_SERVICE, true, true));
+        assertFalse(oldDbFile.exists());
+
+        // Clean up DB
+        try {
+            iwapman.deletePackage(Integer.toString(mAppIdValue),
+                    Integer.toString(mContentTypeValue), mPackageName, mClassName);
+            iwapman.deletePackage(Integer.toString(mAppIdValue + 10),
+                    Integer.toString(mContentTypeValue), mPackageName, mClassName);
+        } catch (RemoteException e) {
+            assertTrue(false);
+        }
+    }
+
+    private void addPackageToLegacyDB(int appId, int contextType, String packagename,
+            String classnName, int appType, boolean signature, boolean furtherProcessing) {
+        WapPushManager wpman = getService();
+        WapPushManDBHelper dbh = new WapPushManDBHelper(getContext());
+        SQLiteDatabase db = dbh.getWritableDatabase();
+
+        wpman.insertPackage(dbh, db, Integer.toString(appId), Integer.toString(contextType),
+                packagename, classnName, appType, signature, furtherProcessing);
+    }
 }
diff --git a/services/backup/OWNERS b/services/backup/OWNERS
index ba2a63a..cc36b47 100644
--- a/services/backup/OWNERS
+++ b/services/backup/OWNERS
@@ -9,4 +9,3 @@
 niamhfw@google.com
 philippov@google.com
 rthakohov@google.com
-tobiast@google.com
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 70c9fe7..629006a 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -1281,14 +1281,22 @@
 
         mPermissionMonitor = new PermissionMonitor(mContext, mNetd);
 
+        mUserAllContext = mContext.createContextAsUser(UserHandle.ALL, 0 /* flags */);
         // Listen for user add/removes to inform PermissionMonitor.
         // Should run on mHandler to avoid any races.
-        IntentFilter intentFilter = new IntentFilter();
-        intentFilter.addAction(Intent.ACTION_USER_ADDED);
-        intentFilter.addAction(Intent.ACTION_USER_REMOVED);
+        final IntentFilter userIntentFilter = new IntentFilter();
+        userIntentFilter.addAction(Intent.ACTION_USER_ADDED);
+        userIntentFilter.addAction(Intent.ACTION_USER_REMOVED);
+        mUserAllContext.registerReceiver(mUserIntentReceiver, userIntentFilter,
+                null /* broadcastPermission */, mHandler);
 
-        mUserAllContext = mContext.createContextAsUser(UserHandle.ALL, 0 /* flags */);
-        mUserAllContext.registerReceiver(mIntentReceiver, intentFilter,
+        // Listen to package add/removes for netd
+        final IntentFilter packageIntentFilter = new IntentFilter();
+        packageIntentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
+        packageIntentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
+        packageIntentFilter.addAction(Intent.ACTION_PACKAGE_REPLACED);
+        packageIntentFilter.addDataScheme("package");
+        mUserAllContext.registerReceiver(mPackageIntentReceiver, packageIntentFilter,
                 null /* broadcastPermission */, mHandler);
 
         mNetworkActivityTracker = new LegacyNetworkActivityTracker(mContext, mHandler, mNetd);
@@ -1895,6 +1903,10 @@
             newNc.setNetworkSpecifier(newNc.getNetworkSpecifier().redact());
         }
         newNc.setAdministratorUids(new int[0]);
+        if (!checkAnyPermissionOf(
+                callerPid, callerUid, android.Manifest.permission.NETWORK_FACTORY)) {
+            newNc.setSubIds(Collections.emptySet());
+        }
 
         return newNc;
     }
@@ -4034,7 +4046,7 @@
                 }
             }
         }
-        decrementRequestCount(nri);
+        nri.decrementRequestCount();
         mNetworkRequestInfoLogs.log("RELEASE " + nri);
 
         if (null != nri.getActiveRequest()) {
@@ -4151,14 +4163,6 @@
                 ? mSystemNetworkRequestCounter : mNetworkRequestCounter;
     }
 
-    private void incrementRequestCountOrThrow(NetworkRequestInfo nri) {
-        getRequestCounter(nri).incrementCountOrThrow(nri.mUid);
-    }
-
-    private void decrementRequestCount(NetworkRequestInfo nri) {
-        getRequestCounter(nri).decrementCount(nri.mUid);
-    }
-
     @Override
     public void setAcceptUnvalidated(Network network, boolean accept, boolean always) {
         enforceNetworkStackSettingsOrSetup();
@@ -4962,7 +4966,7 @@
     }
 
     @Override
-    public void setGlobalProxy(final ProxyInfo proxyProperties) {
+    public void setGlobalProxy(@Nullable final ProxyInfo proxyProperties) {
         PermissionUtils.enforceNetworkStackPermission(mContext);
         mProxyTracker.setGlobalProxy(proxyProperties);
     }
@@ -5307,14 +5311,14 @@
         }
     }
 
-    private void onUserAdded(UserHandle user) {
+    private void onUserAdded(@NonNull final UserHandle user) {
         mPermissionMonitor.onUserAdded(user);
         if (mOemNetworkPreferences.getNetworkPreferences().size() > 0) {
             handleSetOemNetworkPreference(mOemNetworkPreferences, null);
         }
     }
 
-    private void onUserRemoved(UserHandle user) {
+    private void onUserRemoved(@NonNull final UserHandle user) {
         mPermissionMonitor.onUserRemoved(user);
         // If there was a network preference for this user, remove it.
         handleSetProfileNetworkPreference(new ProfileNetworkPreferences.Preference(user, null),
@@ -5324,7 +5328,18 @@
         }
     }
 
-    private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
+    private void onPackageChanged(@NonNull final String packageName) {
+        // This is necessary in case a package is added or removed, but also when it's replaced to
+        // run as a new UID by its manifest rules. Also, if a separate package shares the same UID
+        // as one in the preferences, then it should follow the same routing as that other package,
+        // which means updating the rules is never to be needed in this case (whether it joins or
+        // leaves a UID with a preference).
+        if (isMappedInOemNetworkPreference(packageName)) {
+            handleSetOemNetworkPreference(mOemNetworkPreferences, null);
+        }
+    }
+
+    private final BroadcastReceiver mUserIntentReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
             ensureRunningOnConnectivityServiceThread();
@@ -5347,6 +5362,22 @@
         }
     };
 
+    private final BroadcastReceiver mPackageIntentReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            ensureRunningOnConnectivityServiceThread();
+            switch (intent.getAction()) {
+                case Intent.ACTION_PACKAGE_ADDED:
+                case Intent.ACTION_PACKAGE_REMOVED:
+                case Intent.ACTION_PACKAGE_REPLACED:
+                    onPackageChanged(intent.getData().getSchemeSpecificPart());
+                    break;
+                default:
+                    Log.wtf(TAG, "received unexpected intent: " + intent.getAction());
+            }
+        }
+    };
+
     private final HashMap<Messenger, NetworkProviderInfo> mNetworkProviderInfos = new HashMap<>();
     private final HashMap<NetworkRequest, NetworkRequestInfo> mNetworkRequests = new HashMap<>();
 
@@ -5457,6 +5488,9 @@
         @Nullable
         final String mCallingAttributionTag;
 
+        // Counter keeping track of this NRI.
+        final PerUidCounter mPerUidCounter;
+
         // Effective UID of this request. This is different from mUid when a privileged process
         // files a request on behalf of another UID. This UID is used to determine blocked status,
         // UID matching, and so on. mUid above is used for permission checks and to enforce the
@@ -5507,7 +5541,8 @@
             mPid = getCallingPid();
             mUid = mDeps.getCallingUid();
             mAsUid = asUid;
-            incrementRequestCountOrThrow(this);
+            mPerUidCounter = getRequestCounter(this);
+            mPerUidCounter.incrementCountOrThrow(mUid);
             /**
              * Location sensitive data not included in pending intent. Only included in
              * {@link NetworkCallback}.
@@ -5539,7 +5574,8 @@
             mUid = mDeps.getCallingUid();
             mAsUid = asUid;
             mPendingIntent = null;
-            incrementRequestCountOrThrow(this);
+            mPerUidCounter = getRequestCounter(this);
+            mPerUidCounter.incrementCountOrThrow(mUid);
             mCallbackFlags = callbackFlags;
             mCallingAttributionTag = callingAttributionTag;
             linkDeathRecipient();
@@ -5577,7 +5613,8 @@
             mUid = nri.mUid;
             mAsUid = nri.mAsUid;
             mPendingIntent = nri.mPendingIntent;
-            incrementRequestCountOrThrow(this);
+            mPerUidCounter = getRequestCounter(this);
+            mPerUidCounter.incrementCountOrThrow(mUid);
             mCallbackFlags = nri.mCallbackFlags;
             mCallingAttributionTag = nri.mCallingAttributionTag;
             linkDeathRecipient();
@@ -5609,6 +5646,10 @@
             return Collections.unmodifiableList(tempRequests);
         }
 
+        void decrementRequestCount() {
+            mPerUidCounter.decrementCount(mUid);
+        }
+
         void linkDeathRecipient() {
             if (null != mBinder) {
                 try {
@@ -5666,6 +5707,10 @@
                     "Insufficient permissions to request a specific signal strength");
         }
         mAppOpsManager.checkPackage(callerUid, callerPackageName);
+
+        if (!nc.getSubIds().isEmpty()) {
+            enforceNetworkFactoryPermission();
+        }
     }
 
     private int[] getSignalStrengthThresholds(@NonNull final NetworkAgentInfo nai) {
@@ -6156,6 +6201,15 @@
     @NonNull
     private ProfileNetworkPreferences mProfileNetworkPreferences = new ProfileNetworkPreferences();
 
+    /**
+     * Determine whether a given package has a mapping in the current OemNetworkPreferences.
+     * @param packageName the package name to check existence of a mapping for.
+     * @return true if a mapping exists, false otherwise
+     */
+    private boolean isMappedInOemNetworkPreference(@NonNull final String packageName) {
+        return mOemNetworkPreferences.getNetworkPreferences().containsKey(packageName);
+    }
+
     // The always-on request for an Internet-capable network that apps without a specific default
     // fall back to.
     @VisibleForTesting
@@ -6176,7 +6230,7 @@
      * @return the NetworkRequestInfo tracking the given uid.
      */
     @NonNull
-    private NetworkRequestInfo getDefaultRequestTrackingUid(@NonNull final int uid) {
+    private NetworkRequestInfo getDefaultRequestTrackingUid(final int uid) {
         for (final NetworkRequestInfo nri : mDefaultNetworkRequests) {
             if (nri == mDefaultRequest) {
                 continue;
@@ -6623,7 +6677,7 @@
                     mDeps.reportNetworkInterfaceForTransports(mContext, iface,
                             caps.getTransportTypes());
                 } catch (Exception e) {
-                    loge("Exception adding interface: " + e);
+                    logw("Exception adding interface: " + e);
                 }
             }
         }
@@ -8773,7 +8827,7 @@
             // Decrement the reference count for this NetworkRequestInfo. The reference count is
             // incremented when the NetworkRequestInfo is created as part of
             // enforceRequestCountLimit().
-            decrementRequestCount(nri);
+            nri.decrementRequestCount();
             return;
         }
 
@@ -8839,7 +8893,7 @@
         // Decrement the reference count for this NetworkRequestInfo. The reference count is
         // incremented when the NetworkRequestInfo is created as part of
         // enforceRequestCountLimit().
-        decrementRequestCount(nri);
+        nri.decrementRequestCount();
 
         iCb.unlinkToDeath(cbInfo, 0);
     }
@@ -9415,14 +9469,8 @@
             throw new IllegalArgumentException("Must explicitly specify a user handle ("
                     + "UserHandle.CURRENT not supported)");
         }
-        final UserManager um;
-        try {
-            um = mContext.createContextAsUser(profile, 0 /* flags */)
-                    .getSystemService(UserManager.class);
-        } catch (IllegalStateException e) {
-            throw new IllegalArgumentException("Profile does not exist");
-        }
-        if (!um.isManagedProfile()) {
+        final UserManager um = mContext.getSystemService(UserManager.class);
+        if (!um.isManagedProfile(profile.getIdentifier())) {
             throw new IllegalArgumentException("Profile must be a managed profile");
         }
         // Strictly speaking, mOemNetworkPreferences should only be touched on the
@@ -9589,7 +9637,6 @@
                 new OemNetworkRequestFactory().createNrisFromOemNetworkPreferences(preference);
         replaceDefaultNetworkRequestsForPreference(nris);
         mOemNetworkPreferences = preference;
-        // TODO http://b/176496396 persist data to shared preferences.
 
         if (null != listener) {
             try {
@@ -9746,7 +9793,6 @@
                     // packages are sent on a network preference as the system will watch for
                     // package installations associated with this network preference and update
                     // accordingly. This is done so as to minimize race conditions on app install.
-                    // TODO b/177092163 add app install watching.
                     continue;
                 }
             }
diff --git a/services/core/java/com/android/server/VcnManagementService.java b/services/core/java/com/android/server/VcnManagementService.java
index 8eefbfc..f7ae58c 100644
--- a/services/core/java/com/android/server/VcnManagementService.java
+++ b/services/core/java/com/android/server/VcnManagementService.java
@@ -16,6 +16,8 @@
 
 package com.android.server;
 
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
+import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
 import static android.net.vcn.VcnManager.VCN_STATUS_CODE_ACTIVE;
 import static android.net.vcn.VcnManager.VCN_STATUS_CODE_INACTIVE;
 import static android.net.vcn.VcnManager.VCN_STATUS_CODE_NOT_CONFIGURED;
@@ -35,12 +37,13 @@
 import android.content.IntentFilter;
 import android.net.ConnectivityManager;
 import android.net.LinkProperties;
+import android.net.Network;
 import android.net.NetworkCapabilities;
+import android.net.NetworkRequest;
 import android.net.vcn.IVcnManagementService;
 import android.net.vcn.IVcnStatusCallback;
 import android.net.vcn.IVcnUnderlyingNetworkPolicyListener;
 import android.net.vcn.VcnConfig;
-import android.net.vcn.VcnManager;
 import android.net.vcn.VcnManager.VcnErrorCode;
 import android.net.vcn.VcnManager.VcnStatusCode;
 import android.net.vcn.VcnUnderlyingNetworkPolicy;
@@ -162,6 +165,9 @@
     @NonNull private final VcnContext mVcnContext;
     @NonNull private final BroadcastReceiver mPkgChangeReceiver;
 
+    @NonNull
+    private final TrackingNetworkCallback mTrackingNetworkCallback = new TrackingNetworkCallback();
+
     /** Can only be assigned when {@link #systemReady()} is called, since it uses AppOpsManager. */
     @Nullable private LocationPermissionChecker mLocationPermissionChecker;
 
@@ -358,6 +364,10 @@
     public void systemReady() {
         mContext.getSystemService(ConnectivityManager.class)
                 .registerNetworkProvider(mNetworkProvider);
+        mContext.getSystemService(ConnectivityManager.class)
+                .registerNetworkCallback(
+                        new NetworkRequest.Builder().clearCapabilities().build(),
+                        mTrackingNetworkCallback);
         mTelephonySubscriptionTracker.register();
         mLocationPermissionChecker = mDeps.newLocationPermissionChecker(mVcnContext.getContext());
     }
@@ -532,15 +542,7 @@
 
         if (mVcns.containsKey(subscriptionGroup)) {
             final Vcn vcn = mVcns.get(subscriptionGroup);
-            final boolean isActive = vcn.isActive();
             vcn.updateConfig(config);
-
-            // Only notify VcnStatusCallbacks if this VCN was previously in Safe Mode
-            if (!isActive) {
-                // TODO(b/181789060): invoke asynchronously after Vcn notifies through VcnCallback
-                notifyAllPermissionedStatusCallbacksLocked(
-                        subscriptionGroup, VCN_STATUS_CODE_ACTIVE);
-            }
         } else {
             startVcnLocked(subscriptionGroup, config);
         }
@@ -769,7 +771,7 @@
             synchronized (mLock) {
                 final Vcn vcn = mVcns.get(subGrp);
                 if (vcn != null) {
-                    if (vcn.isActive()) {
+                    if (vcn.getStatus() == VCN_STATUS_CODE_ACTIVE) {
                         isVcnManagedNetwork = true;
                     }
 
@@ -792,8 +794,9 @@
                         NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
             }
 
+            final NetworkCapabilities result = ncBuilder.build();
             return new VcnUnderlyingNetworkPolicy(
-                    false /* isTearDownRequested */, ncBuilder.build());
+                    mTrackingNetworkCallback.requiresRestartForCarrierWifi(result), result);
         });
     }
 
@@ -880,20 +883,23 @@
                 // now that callback is registered, send it the VCN's current status
                 final VcnConfig vcnConfig = mConfigs.get(subGroup);
                 final Vcn vcn = mVcns.get(subGroup);
-                final int vcnStatus;
+                final int vcnStatus =
+                        vcn == null ? VCN_STATUS_CODE_NOT_CONFIGURED : vcn.getStatus();
+                final int resultStatus;
                 if (vcnConfig == null || !isCallbackPermissioned(cbInfo, subGroup)) {
-                    vcnStatus = VcnManager.VCN_STATUS_CODE_NOT_CONFIGURED;
+                    resultStatus = VCN_STATUS_CODE_NOT_CONFIGURED;
                 } else if (vcn == null) {
-                    vcnStatus = VcnManager.VCN_STATUS_CODE_INACTIVE;
-                } else if (vcn.isActive()) {
-                    vcnStatus = VcnManager.VCN_STATUS_CODE_ACTIVE;
+                    resultStatus = VCN_STATUS_CODE_INACTIVE;
+                } else if (vcnStatus == VCN_STATUS_CODE_ACTIVE
+                        || vcnStatus == VCN_STATUS_CODE_SAFE_MODE) {
+                    resultStatus = vcnStatus;
                 } else {
-                    // TODO(b/181789060): create Vcn.getStatus() and Log.WTF() for unknown status
-                    vcnStatus = VcnManager.VCN_STATUS_CODE_SAFE_MODE;
+                    Slog.wtf(TAG, "Unknown VCN status: " + vcnStatus);
+                    resultStatus = VCN_STATUS_CODE_NOT_CONFIGURED;
                 }
 
                 try {
-                    cbInfo.mCallback.onVcnStatusChanged(vcnStatus);
+                    cbInfo.mCallback.onVcnStatusChanged(resultStatus);
                 } catch (RemoteException e) {
                     Slog.d(TAG, "VcnStatusCallback threw on VCN status change", e);
                 }
@@ -926,17 +932,60 @@
     // TODO(b/180452282): Make name more generic and implement directly with VcnManagementService
     /** Callback for Vcn signals sent up to VcnManagementService. */
     public interface VcnCallback {
-        /** Called by a Vcn to signal that it has entered safe mode. */
-        void onEnteredSafeMode();
+        /** Called by a Vcn to signal that its safe mode status has changed. */
+        void onSafeModeStatusChanged(boolean isInSafeMode);
 
         /** Called by a Vcn to signal that an error occurred. */
         void onGatewayConnectionError(
-                @NonNull int[] networkCapabilities,
+                @NonNull String gatewayConnectionName,
                 @VcnErrorCode int errorCode,
                 @Nullable String exceptionClass,
                 @Nullable String exceptionMessage);
     }
 
+    /**
+     * TrackingNetworkCallback tracks all active networks
+     *
+     * <p>This is used to ensure that no underlying networks have immutable capabilities changed
+     * without requiring a Network restart.
+     */
+    private class TrackingNetworkCallback extends ConnectivityManager.NetworkCallback {
+        private final Map<Network, NetworkCapabilities> mCaps = new ArrayMap<>();
+
+        @Override
+        public void onCapabilitiesChanged(Network network, NetworkCapabilities caps) {
+            synchronized (mCaps) {
+                mCaps.put(network, caps);
+            }
+        }
+
+        @Override
+        public void onLost(Network network) {
+            synchronized (mCaps) {
+                mCaps.remove(network);
+            }
+        }
+
+        private boolean requiresRestartForCarrierWifi(NetworkCapabilities caps) {
+            if (!caps.hasTransport(TRANSPORT_WIFI) || caps.getSubIds() == null) {
+                return false;
+            }
+
+            synchronized (mCaps) {
+                for (NetworkCapabilities existing : mCaps.values()) {
+                    if (existing.hasTransport(TRANSPORT_WIFI)
+                            && caps.getSubIds().equals(existing.getSubIds())) {
+                        // Restart if any immutable capabilities have changed
+                        return existing.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)
+                                != caps.hasCapability(NET_CAPABILITY_NOT_RESTRICTED);
+                    }
+                }
+            }
+
+            return false;
+        }
+    }
+
     /** VcnCallbackImpl for Vcn signals sent up to VcnManagementService. */
     private class VcnCallbackImpl implements VcnCallback {
         @NonNull private final ParcelUuid mSubGroup;
@@ -946,21 +995,24 @@
         }
 
         @Override
-        public void onEnteredSafeMode() {
+        public void onSafeModeStatusChanged(boolean isInSafeMode) {
             synchronized (mLock) {
                 // Ignore if this subscription group doesn't exist anymore
                 if (!mVcns.containsKey(mSubGroup)) {
                     return;
                 }
 
+                final int status =
+                        isInSafeMode ? VCN_STATUS_CODE_SAFE_MODE : VCN_STATUS_CODE_ACTIVE;
+
                 notifyAllPolicyListenersLocked();
-                notifyAllPermissionedStatusCallbacksLocked(mSubGroup, VCN_STATUS_CODE_SAFE_MODE);
+                notifyAllPermissionedStatusCallbacksLocked(mSubGroup, status);
             }
         }
 
         @Override
         public void onGatewayConnectionError(
-                @NonNull int[] networkCapabilities,
+                @NonNull String gatewayConnectionName,
                 @VcnErrorCode int errorCode,
                 @Nullable String exceptionClass,
                 @Nullable String exceptionMessage) {
@@ -976,7 +1028,7 @@
                         Binder.withCleanCallingIdentity(
                                 () ->
                                         cbInfo.mCallback.onGatewayConnectionError(
-                                                networkCapabilities,
+                                                gatewayConnectionName,
                                                 errorCode,
                                                 exceptionClass,
                                                 exceptionMessage));
diff --git a/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java b/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java
index 5e6b9f3..2e51be3 100644
--- a/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java
+++ b/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java
@@ -36,7 +36,7 @@
 import android.util.Pair;
 
 import com.android.internal.util.IndentingPrintWriter;
-import com.android.internal.util.TrafficStatsConstants;
+import com.android.net.module.util.NetworkStackConstants;
 
 import libcore.io.IoUtils;
 
@@ -446,7 +446,7 @@
                 int sockType, int protocol, long writeTimeout, long readTimeout, int dstPort)
                 throws ErrnoException, IOException {
             final int oldTag = TrafficStats.getAndSetThreadStatsTag(
-                    TrafficStatsConstants.TAG_SYSTEM_PROBE);
+                    NetworkStackConstants.TAG_SYSTEM_PROBE);
             try {
                 mFileDescriptor = Os.socket(mAddressFamily, sockType, protocol);
             } finally {
@@ -745,7 +745,7 @@
             if (ensureMeasurementNecessary()) return;
 
             // No need to restore the tag, since this thread is only used for this measurement.
-            TrafficStats.getAndSetThreadStatsTag(TrafficStatsConstants.TAG_SYSTEM_PROBE);
+            TrafficStats.getAndSetThreadStatsTag(NetworkStackConstants.TAG_SYSTEM_PROBE);
 
             try (SSLSocket sslSocket = setupSSLSocket()) {
                 sendDoTProbe(sslSocket);
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index e5ce4f0..0a76bdc 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -101,7 +101,6 @@
 import android.provider.Settings;
 import android.security.Credentials;
 import android.security.KeyStore2;
-import android.security.keystore.AndroidKeyStoreProvider;
 import android.security.keystore.KeyProperties;
 import android.system.keystore2.Domain;
 import android.system.keystore2.KeyDescriptor;
@@ -463,7 +462,7 @@
                 .addTransportType(NetworkCapabilities.TRANSPORT_VPN)
                 .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
                 .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED)
-                .setTransportInfo(new VpnTransportInfo(VpnManager.TYPE_VPN_NONE))
+                .setTransportInfo(new VpnTransportInfo(VpnManager.TYPE_VPN_NONE, null))
                 .build();
 
         loadAlwaysOnPackage();
@@ -527,7 +526,7 @@
     private void resetNetworkCapabilities() {
         mNetworkCapabilities = new NetworkCapabilities.Builder(mNetworkCapabilities)
                 .setUids(null)
-                .setTransportInfo(new VpnTransportInfo(VpnManager.TYPE_VPN_NONE))
+                .setTransportInfo(new VpnTransportInfo(VpnManager.TYPE_VPN_NONE, null))
                 .build();
     }
 
@@ -1257,7 +1256,7 @@
         capsBuilder.setUids(createUserAndRestrictedProfilesRanges(mUserId,
                 mConfig.allowedApplications, mConfig.disallowedApplications));
 
-        capsBuilder.setTransportInfo(new VpnTransportInfo(getActiveVpnType()));
+        capsBuilder.setTransportInfo(new VpnTransportInfo(getActiveVpnType(), mConfig.session));
 
         // Only apps targeting Q and above can explicitly declare themselves as metered.
         // These VPNs are assumed metered unless they state otherwise.
@@ -2055,10 +2054,6 @@
         if (alias == null) {
             return null;
         }
-        // If Keystore 2.0 is not enabled the legacy private key prefix is used.
-        if (!AndroidKeyStoreProvider.isKeystore2Enabled()) {
-            return Credentials.USER_PRIVATE_KEY + alias;
-        }
         final KeyStore2 keystore2 = KeyStore2.getInstance();
 
         KeyDescriptor key = new KeyDescriptor();
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index 0215188..f96fa09 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -99,6 +99,7 @@
 import android.security.keystore.recovery.KeyChainSnapshot;
 import android.security.keystore.recovery.RecoveryCertPath;
 import android.security.keystore.recovery.WrappedApplicationKey;
+import android.security.keystore2.AndroidKeyStoreProvider;
 import android.service.gatekeeper.GateKeeperResponse;
 import android.service.gatekeeper.IGateKeeperService;
 import android.text.TextUtils;
@@ -262,7 +263,7 @@
 
         @Override
         public void onStart() {
-            android.security.keystore2.AndroidKeyStoreProvider.install();
+            AndroidKeyStoreProvider.install();
             mLockSettingsService = new LockSettingsService(getContext());
             publishBinderService("lock_settings", mLockSettingsService);
         }
@@ -796,10 +797,6 @@
                 // Notify keystore that a new user was added.
                 final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
                 AndroidKeyStoreMaintenance.onUserAdded(userHandle);
-                final KeyStore ks = KeyStore.getInstance();
-                final UserInfo parentInfo = mUserManager.getProfileParent(userHandle);
-                final int parentHandle = parentInfo != null ? parentInfo.id : -1;
-                ks.onUserAdded(userHandle, parentHandle);
             } else if (Intent.ACTION_USER_STARTING.equals(intent.getAction())) {
                 final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
                 mStorage.prefetchUser(userHandle);
@@ -1264,19 +1261,11 @@
 
     private void setKeystorePassword(byte[] password, int userHandle) {
         AndroidKeyStoreMaintenance.onUserPasswordChanged(userHandle, password);
-        final KeyStore ks = KeyStore.getInstance();
-        // TODO(b/120484642): Update keystore to accept byte[] passwords
-        String passwordString = password == null ? null : new String(password);
-        ks.onUserPasswordChanged(userHandle, passwordString);
     }
 
     private void unlockKeystore(byte[] password, int userHandle) {
         if (DEBUG) Slog.v(TAG, "Unlock keystore for user: " + userHandle);
         Authorization.onLockScreenEvent(false, userHandle, password);
-        // TODO(b/120484642): Update keystore to accept byte[] passwords
-        String passwordString = password == null ? null : new String(password);
-        final KeyStore ks = KeyStore.getInstance();
-        ks.unlock(userHandle, passwordString);
     }
 
     @VisibleForTesting /** Note: this method is overridden in unit tests */
@@ -2296,8 +2285,6 @@
         mStrongAuth.removeUser(userId);
 
         AndroidKeyStoreMaintenance.onUserRemoved(userId);
-        final KeyStore ks = KeyStore.getInstance();
-        ks.onUserRemoved(userId);
         mManagedProfilePasswordCache.removePassword(userId);
 
         gateKeeperClearSecureUserId(userId);
diff --git a/services/core/java/com/android/server/locksettings/ManagedProfilePasswordCache.java b/services/core/java/com/android/server/locksettings/ManagedProfilePasswordCache.java
index 7950fcf..fa477c8 100644
--- a/services/core/java/com/android/server/locksettings/ManagedProfilePasswordCache.java
+++ b/services/core/java/com/android/server/locksettings/ManagedProfilePasswordCache.java
@@ -20,10 +20,10 @@
 import android.content.pm.UserInfo;
 import android.os.UserHandle;
 import android.os.UserManager;
-import android.security.keystore.AndroidKeyStoreSpi;
 import android.security.keystore.KeyGenParameterSpec;
 import android.security.keystore.KeyProperties;
 import android.security.keystore.UserNotAuthenticatedException;
+import android.security.keystore2.AndroidKeyStoreSpi;
 import android.util.Slog;
 import android.util.SparseArray;
 
diff --git a/services/core/java/com/android/server/locksettings/RebootEscrowKeyStoreManager.java b/services/core/java/com/android/server/locksettings/RebootEscrowKeyStoreManager.java
index bae029c..da29368 100644
--- a/services/core/java/com/android/server/locksettings/RebootEscrowKeyStoreManager.java
+++ b/services/core/java/com/android/server/locksettings/RebootEscrowKeyStoreManager.java
@@ -16,11 +16,10 @@
 
 package com.android.server.locksettings;
 
-import android.security.keystore.AndroidKeyStoreSpi;
 import android.security.keystore.KeyGenParameterSpec;
 import android.security.keystore.KeyProperties;
 import android.security.keystore2.AndroidKeyStoreLoadStoreParameter;
-import android.security.keystore2.AndroidKeyStoreProvider;
+import android.security.keystore2.AndroidKeyStoreSpi;
 import android.util.Slog;
 
 import com.android.internal.annotations.GuardedBy;
@@ -67,9 +66,7 @@
             KeyStore keyStore = KeyStore.getInstance(ANDROID_KEY_STORE_PROVIDER);
             KeyStore.LoadStoreParameter loadStoreParameter = null;
             // Load from the specific namespace if keystore2 is enabled.
-            if (AndroidKeyStoreProvider.isInstalled()) {
-                loadStoreParameter = new AndroidKeyStoreLoadStoreParameter(KEY_STORE_NAMESPACE);
-            }
+            loadStoreParameter = new AndroidKeyStoreLoadStoreParameter(KEY_STORE_NAMESPACE);
             keyStore.load(loadStoreParameter);
             return (SecretKey) keyStore.getKey(REBOOT_ESCROW_KEY_STORE_ENCRYPTION_KEY_NAME,
                     null);
@@ -91,9 +88,7 @@
                 KeyStore keyStore = KeyStore.getInstance(ANDROID_KEY_STORE_PROVIDER);
                 KeyStore.LoadStoreParameter loadStoreParameter = null;
                 // Load from the specific namespace if keystore2 is enabled.
-                if (AndroidKeyStoreProvider.isInstalled()) {
-                    loadStoreParameter = new AndroidKeyStoreLoadStoreParameter(KEY_STORE_NAMESPACE);
-                }
+                loadStoreParameter = new AndroidKeyStoreLoadStoreParameter(KEY_STORE_NAMESPACE);
                 keyStore.load(loadStoreParameter);
                 keyStore.deleteEntry(REBOOT_ESCROW_KEY_STORE_ENCRYPTION_KEY_NAME);
             } catch (IOException | GeneralSecurityException e) {
@@ -119,9 +114,7 @@
                         .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
                         .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE);
                 // Generate the key with the correct namespace if keystore2 is enabled.
-                if (AndroidKeyStoreProvider.isInstalled()) {
-                    parameterSpecBuilder.setNamespace(KEY_STORE_NAMESPACE);
-                }
+                parameterSpecBuilder.setNamespace(KEY_STORE_NAMESPACE);
                 generator.init(parameterSpecBuilder.build());
                 return generator.generateKey();
             } catch (GeneralSecurityException e) {
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/ApplicationKeyStorage.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/ApplicationKeyStorage.java
index 2398f56..8582c67 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/ApplicationKeyStorage.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/ApplicationKeyStorage.java
@@ -20,8 +20,6 @@
 
 import android.annotation.Nullable;
 import android.os.ServiceSpecificException;
-import android.security.Credentials;
-import android.security.KeyStore;
 import android.security.KeyStore2;
 import android.security.keystore.KeyProperties;
 import android.security.keystore.KeyProtection;
@@ -75,13 +73,7 @@
     public @Nullable String getGrantAlias(int userId, int uid, String alias) {
         Log.i(TAG, String.format(Locale.US, "Get %d/%d/%s", userId, uid, alias));
         String keystoreAlias = getInternalAlias(userId, uid, alias);
-        if (useKeyStore2()) {
-            return makeKeystoreEngineGrantString(uid, keystoreAlias);
-        } else {
-            // Aliases used by {@link KeyStore} are different than used by public API.
-            // {@code USER_PRIVATE_KEY} prefix is used secret keys.
-            return KeyStore.getInstance().grant(Credentials.USER_PRIVATE_KEY + keystoreAlias, uid);
-        }
+        return makeKeystoreEngineGrantString(uid, keystoreAlias);
     }
 
     public void setSymmetricKeyEntry(int userId, int uid, String alias, byte[] secretKey)
@@ -148,9 +140,4 @@
         }
         return String.format("%s%016X", APPLICATION_KEY_GRANT_PREFIX, key.nspace);
     }
-
-    private static boolean useKeyStore2() {
-        return android.security.keystore2.AndroidKeyStoreProvider.isInstalled();
-    }
-
 }
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index c127858..290307b 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -5581,17 +5581,6 @@
     }
 
     @Override
-    public boolean checkUidNetworkingBlocked(int uid, int uidRules,
-            boolean isNetworkMetered, boolean isBackgroundRestricted) {
-        mContext.enforceCallingOrSelfPermission(OBSERVE_NETWORK_POLICY, TAG);
-        // Log of invoking this function is disabled because it will be called very frequently. And
-        // metrics are unlikely needed on this method because the callers are external and this
-        // method doesn't take any locks or perform expensive operations.
-        return isUidNetworkingBlockedInternal(uid, uidRules, isNetworkMetered,
-                isBackgroundRestricted, null);
-    }
-
-    @Override
     public boolean isUidRestrictedOnMeteredNetworks(int uid) {
         mContext.enforceCallingOrSelfPermission(OBSERVE_NETWORK_POLICY, TAG);
         final int uidRules;
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index afcf81f..ff763fc 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -54,7 +54,6 @@
 import android.os.UserManager;
 import android.provider.Settings;
 import android.security.Authorization;
-import android.security.KeyStore;
 import android.service.trust.TrustAgentService;
 import android.text.TextUtils;
 import android.util.ArrayMap;
@@ -701,13 +700,11 @@
             dispatchDeviceLocked(userId, locked);
 
             Authorization.onLockScreenEvent(locked, userId, null);
-            KeyStore.getInstance().onUserLockedStateChanged(userId, locked);
             // Also update the user's profiles who have unified challenge, since they
             // share the same unlocked state (see {@link #isDeviceLocked(int)})
             for (int profileHandle : mUserManager.getEnabledProfileIds(userId)) {
                 if (mLockPatternUtils.isManagedProfileWithUnifiedChallenge(profileHandle)) {
                     mAuthorizationService.onLockScreenEvent(locked, profileHandle, null);
-                    KeyStore.getInstance().onUserLockedStateChanged(profileHandle, locked);
                 }
             }
         }
@@ -1259,7 +1256,6 @@
                     }
 
                     Authorization.onLockScreenEvent(locked, userId, null);
-                    KeyStore.getInstance().onUserLockedStateChanged(userId, locked);
 
                     if (locked) {
                         try {
diff --git a/services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java b/services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java
index 069c5c3..ab9de77 100644
--- a/services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java
+++ b/services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java
@@ -118,7 +118,7 @@
         if (!mIsQuitting) {
             mRouteSelectionCallback = new RouteSelectionCallback();
             mConnectivityManager.requestBackgroundNetwork(
-                    getBaseNetworkRequestBuilder().build(), mHandler, mRouteSelectionCallback);
+                    getRouteSelectionRequest(), mHandler, mRouteSelectionCallback);
 
             mWifiBringupCallback = new NetworkBringupCallback();
             mConnectivityManager.requestBackgroundNetwork(
@@ -149,12 +149,48 @@
         }
     }
 
-    private NetworkRequest getWifiNetworkRequest() {
+    /**
+     * Builds the Route selection request
+     *
+     * <p>This request is guaranteed to select carrier-owned, non-VCN underlying networks by virtue
+     * of a populated set of subIds as expressed in NetworkCapabilities#getSubIds(). Only carrier
+     * owned networks may be selected, as the request specifies only subIds in the VCN's
+     * subscription group, while the VCN networks are excluded by virtue of not having subIds set on
+     * the VCN-exposed networks.
+     */
+    private NetworkRequest getRouteSelectionRequest() {
         return getBaseNetworkRequestBuilder()
-                .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
+                .setSubIds(mLastSnapshot.getAllSubIdsInGroup(mSubscriptionGroup))
                 .build();
     }
 
+    /**
+     * Builds the WiFi bringup request
+     *
+     * <p>This request is built specifically to match only carrier-owned WiFi networks, but is also
+     * built to ONLY keep Carrier WiFi Networks alive (but never bring them up). This is a result of
+     * the WifiNetworkFactory not advertising a list of subIds, and therefore not accepting this
+     * request. As such, it will bind to a Carrier WiFi Network that has already been brought up,
+     * but will NEVER bring up a Carrier WiFi network itself.
+     */
+    private NetworkRequest getWifiNetworkRequest() {
+        return getBaseNetworkRequestBuilder()
+                .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
+                .setSubIds(mLastSnapshot.getAllSubIdsInGroup(mSubscriptionGroup))
+                .build();
+    }
+
+    /**
+     * Builds a Cellular bringup request for a given subId
+     *
+     * <p>This request is filed in order to ensure that the Telephony stack always has a
+     * NetworkRequest to bring up a VCN underlying cellular network. It is required in order to
+     * ensure that even when a VCN (appears as Cellular) satisfies the default request, Telephony
+     * will bring up additional underlying Cellular networks.
+     *
+     * <p>Since this request MUST make it to the TelephonyNetworkFactory, subIds are not specified
+     * in the NetworkCapabilities, but rather in the TelephonyNetworkSpecifier.
+     */
     private NetworkRequest getCellNetworkRequestForSubId(int subId) {
         return getBaseNetworkRequestBuilder()
                 .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
@@ -164,20 +200,13 @@
 
     /**
      * Builds and returns a NetworkRequest builder common to all Underlying Network requests
-     *
-     * <p>This request is guaranteed to select carrier-owned, non-VCN underlying networks by virtue
-     * of a populated set of subIds as expressed in NetworkCapabilities#getSubIds(). Only carrier
-     * owned networks may be selected, as the request specifies only subIds in the VCN's
-     * subscription group, while the VCN networks are excluded by virtue of not having subIds set on
-     * the VCN-exposed networks.
      */
     private NetworkRequest.Builder getBaseNetworkRequestBuilder() {
         return new NetworkRequest.Builder()
                 .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
                 .removeCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED)
                 .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
-                .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED)
-                .setSubIds(mLastSnapshot.getAllSubIdsInGroup(mSubscriptionGroup));
+                .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED);
     }
 
     /**
diff --git a/services/core/java/com/android/server/vcn/Vcn.java b/services/core/java/com/android/server/vcn/Vcn.java
index 89ed956..ae806aa 100644
--- a/services/core/java/com/android/server/vcn/Vcn.java
+++ b/services/core/java/com/android/server/vcn/Vcn.java
@@ -17,6 +17,10 @@
 package com.android.server.vcn;
 
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED;
+import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+import static android.net.vcn.VcnManager.VCN_STATUS_CODE_ACTIVE;
+import static android.net.vcn.VcnManager.VCN_STATUS_CODE_INACTIVE;
+import static android.net.vcn.VcnManager.VCN_STATUS_CODE_SAFE_MODE;
 
 import static com.android.server.VcnManagementService.VDBG;
 
@@ -44,7 +48,6 @@
 import java.util.Map.Entry;
 import java.util.Objects;
 import java.util.Set;
-import java.util.concurrent.atomic.AtomicBoolean;
 
 /**
  * Represents an single instance of a VCN.
@@ -94,17 +97,21 @@
      */
     private static final int MSG_EVENT_GATEWAY_CONNECTION_QUIT = MSG_EVENT_BASE + 3;
 
+    /**
+     * Triggers reevaluation of safe mode conditions.
+     *
+     * <p>Upon entering safe mode, the VCN will only provide gateway connections opportunistically,
+     * leaving the underlying networks marked as NOT_VCN_MANAGED.
+     *
+     * <p>Any VcnGatewayConnection in safe mode will result in the entire Vcn instance being put
+     * into safe mode. Upon receiving this message, the Vcn MUST query all VcnGatewayConnections to
+     * determine if any are in safe mode.
+     */
+    private static final int MSG_EVENT_SAFE_MODE_STATE_CHANGED = MSG_EVENT_BASE + 4;
+
     /** Triggers an immediate teardown of the entire Vcn, including GatewayConnections. */
     private static final int MSG_CMD_TEARDOWN = MSG_CMD_BASE;
 
-    /**
-     * Causes this VCN to immediately enter safe mode.
-     *
-     * <p>Upon entering safe mode, the VCN will unregister its RequestListener, tear down all of its
-     * VcnGatewayConnections, and notify VcnManagementService that it is in safe mode.
-     */
-    private static final int MSG_CMD_ENTER_SAFE_MODE = MSG_CMD_BASE + 1;
-
     @NonNull private final VcnContext mVcnContext;
     @NonNull private final ParcelUuid mSubscriptionGroup;
     @NonNull private final Dependencies mDeps;
@@ -137,17 +144,14 @@
     @NonNull private TelephonySubscriptionSnapshot mLastSnapshot;
 
     /**
-     * Whether this Vcn instance is active and running.
+     * The current status of this Vcn instance
      *
-     * <p>The value will be {@code true} while running. It will be {@code false} if the VCN has been
-     * shut down or has entered safe mode.
-     *
-     * <p>This AtomicBoolean is required in order to ensure consistency and correctness across
-     * multiple threads. Unlike the rest of the Vcn, this is queried synchronously on Binder threads
-     * from VcnManagementService, and therefore cannot rely on guarantees of running on the VCN
-     * Looper.
+     * <p>The value will be {@link VCN_STATUS_CODE_ACTIVE} while all VcnGatewayConnections are in
+     * good standing, {@link VCN_STATUS_CODE_SAFE_MODE} if any VcnGatewayConnections are in safe
+     * mode, and {@link VCN_STATUS_CODE_INACTIVE} once a teardown has been commanded.
      */
-    private final AtomicBoolean mIsActive = new AtomicBoolean(true);
+    // Accessed from different threads, but always under lock in VcnManagementService
+    private volatile int mCurrentStatus = VCN_STATUS_CODE_ACTIVE;
 
     public Vcn(
             @NonNull VcnContext vcnContext,
@@ -199,9 +203,15 @@
         sendMessageAtFrontOfQueue(obtainMessage(MSG_CMD_TEARDOWN));
     }
 
-    /** Synchronously checks whether this Vcn is active. */
-    public boolean isActive() {
-        return mIsActive.get();
+    /** Synchronously retrieves the current status code. */
+    public int getStatus() {
+        return mCurrentStatus;
+    }
+
+    /** Sets the status of this VCN */
+    @VisibleForTesting(visibility = Visibility.PRIVATE)
+    public void setStatus(int status) {
+        mCurrentStatus = status;
     }
 
     /** Get current Gateways for testing purposes */
@@ -217,12 +227,6 @@
         return Collections.unmodifiableMap(new HashMap<>(mVcnGatewayConnections));
     }
 
-    /** Set whether this Vcn is active for testing purposes */
-    @VisibleForTesting(visibility = Visibility.PRIVATE)
-    public void setIsActive(boolean isActive) {
-        mIsActive.set(isActive);
-    }
-
     private class VcnNetworkRequestListener implements VcnNetworkProvider.NetworkRequestListener {
         @Override
         public void onNetworkRequested(@NonNull NetworkRequest request, int score, int providerId) {
@@ -234,6 +238,11 @@
 
     @Override
     public void handleMessage(@NonNull Message msg) {
+        if (mCurrentStatus != VCN_STATUS_CODE_ACTIVE
+                && mCurrentStatus != VCN_STATUS_CODE_SAFE_MODE) {
+            return;
+        }
+
         switch (msg.what) {
             case MSG_EVENT_CONFIG_UPDATED:
                 handleConfigUpdated((VcnConfig) msg.obj);
@@ -247,12 +256,12 @@
             case MSG_EVENT_GATEWAY_CONNECTION_QUIT:
                 handleGatewayConnectionQuit((VcnGatewayConnectionConfig) msg.obj);
                 break;
+            case MSG_EVENT_SAFE_MODE_STATE_CHANGED:
+                handleSafeModeStatusChanged();
+                break;
             case MSG_CMD_TEARDOWN:
                 handleTeardown();
                 break;
-            case MSG_CMD_ENTER_SAFE_MODE:
-                handleEnterSafeMode();
-                break;
             default:
                 Slog.wtf(getLogTag(), "Unknown msg.what: " + msg.what);
         }
@@ -264,35 +273,28 @@
 
         mConfig = config;
 
-        if (mIsActive.getAndSet(true)) {
-            // VCN is already active - teardown any GatewayConnections whose configs have been
-            // removed and get all current requests
-            for (final Entry<VcnGatewayConnectionConfig, VcnGatewayConnection> entry :
-                    mVcnGatewayConnections.entrySet()) {
-                final VcnGatewayConnectionConfig gatewayConnectionConfig = entry.getKey();
-                final VcnGatewayConnection gatewayConnection = entry.getValue();
+        // Teardown any GatewayConnections whose configs have been removed and get all current
+        // requests
+        for (final Entry<VcnGatewayConnectionConfig, VcnGatewayConnection> entry :
+                mVcnGatewayConnections.entrySet()) {
+            final VcnGatewayConnectionConfig gatewayConnectionConfig = entry.getKey();
+            final VcnGatewayConnection gatewayConnection = entry.getValue();
 
-                // GatewayConnectionConfigs must match exactly (otherwise authentication or
-                // connection details may have changed).
-                if (!mConfig.getGatewayConnectionConfigs().contains(gatewayConnectionConfig)) {
-                    if (gatewayConnection == null) {
-                        Slog.wtf(
-                                getLogTag(),
-                                "Found gatewayConnectionConfig without GatewayConnection");
-                    } else {
-                        gatewayConnection.teardownAsynchronously();
-                    }
+            // GatewayConnectionConfigs must match exactly (otherwise authentication or
+            // connection details may have changed).
+            if (!mConfig.getGatewayConnectionConfigs().contains(gatewayConnectionConfig)) {
+                if (gatewayConnection == null) {
+                    Slog.wtf(
+                            getLogTag(), "Found gatewayConnectionConfig without GatewayConnection");
+                } else {
+                    gatewayConnection.teardownAsynchronously();
                 }
             }
-
-            // Trigger a re-evaluation of all NetworkRequests (to make sure any that can be
-            // satisfied start a new GatewayConnection)
-            mVcnContext.getVcnNetworkProvider().resendAllRequests(mRequestListener);
-        } else {
-            // If this VCN was not previously active, it is exiting Safe Mode. Re-register the
-            // request listener to get NetworkRequests again (and all cached requests).
-            mVcnContext.getVcnNetworkProvider().registerListener(mRequestListener);
         }
+
+        // Trigger a re-evaluation of all NetworkRequests (to make sure any that can be
+        // satisfied start a new GatewayConnection)
+        mVcnContext.getVcnNetworkProvider().resendAllRequests(mRequestListener);
     }
 
     private void handleTeardown() {
@@ -302,22 +304,30 @@
             gatewayConnection.teardownAsynchronously();
         }
 
-        mIsActive.set(false);
+        mCurrentStatus = VCN_STATUS_CODE_INACTIVE;
     }
 
-    private void handleEnterSafeMode() {
-        handleTeardown();
+    private void handleSafeModeStatusChanged() {
+        boolean hasSafeModeGatewayConnection = false;
 
-        mVcnCallback.onEnteredSafeMode();
+        // If any VcnGatewayConnection is in safe mode, mark the entire VCN as being in safe mode
+        for (VcnGatewayConnection gatewayConnection : mVcnGatewayConnections.values()) {
+            if (gatewayConnection.isInSafeMode()) {
+                hasSafeModeGatewayConnection = true;
+                break;
+            }
+        }
+
+        final int oldStatus = mCurrentStatus;
+        mCurrentStatus =
+                hasSafeModeGatewayConnection ? VCN_STATUS_CODE_SAFE_MODE : VCN_STATUS_CODE_ACTIVE;
+        if (oldStatus != mCurrentStatus) {
+            mVcnCallback.onSafeModeStatusChanged(hasSafeModeGatewayConnection);
+        }
     }
 
     private void handleNetworkRequested(
             @NonNull NetworkRequest request, int score, int providerId) {
-        if (!isActive()) {
-            Slog.v(getLogTag(), "Received NetworkRequest while inactive. Ignore for now");
-            return;
-        }
-
         if (score > getNetworkScore()) {
             if (VDBG) {
                 Slog.v(
@@ -370,25 +380,23 @@
         mVcnGatewayConnections.remove(config);
 
         // Trigger a re-evaluation of all NetworkRequests (to make sure any that can be satisfied
-        // start a new GatewayConnection), but only if the Vcn is still active
-        if (isActive()) {
-            mVcnContext.getVcnNetworkProvider().resendAllRequests(mRequestListener);
-        }
+        // start a new GatewayConnection). VCN is always alive here, courtesy of the liveness check
+        // in handleMessage()
+        mVcnContext.getVcnNetworkProvider().resendAllRequests(mRequestListener);
     }
 
     private void handleSubscriptionsChanged(@NonNull TelephonySubscriptionSnapshot snapshot) {
         mLastSnapshot = snapshot;
 
-        if (isActive()) {
-            for (VcnGatewayConnection gatewayConnection : mVcnGatewayConnections.values()) {
-                gatewayConnection.updateSubscriptionSnapshot(mLastSnapshot);
-            }
+        for (VcnGatewayConnection gatewayConnection : mVcnGatewayConnections.values()) {
+            gatewayConnection.updateSubscriptionSnapshot(mLastSnapshot);
         }
     }
 
     private boolean isRequestSatisfiedByGatewayConnectionConfig(
             @NonNull NetworkRequest request, @NonNull VcnGatewayConnectionConfig config) {
         final NetworkCapabilities.Builder builder = new NetworkCapabilities.Builder();
+        builder.addTransportType(TRANSPORT_CELLULAR);
         builder.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
         for (int cap : config.getAllExposedCapabilities()) {
             builder.addCapability(cap);
@@ -412,12 +420,12 @@
     /** Callback used for passing status signals from a VcnGatewayConnection to its managing Vcn. */
     @VisibleForTesting(visibility = Visibility.PACKAGE)
     public interface VcnGatewayStatusCallback {
-        /** Called by a VcnGatewayConnection to indicate that it has entered safe mode. */
-        void onEnteredSafeMode();
+        /** Called by a VcnGatewayConnection to indicate that it's safe mode status has changed. */
+        void onSafeModeStatusChanged();
 
         /** Callback by a VcnGatewayConnection to indicate that an error occurred. */
         void onGatewayConnectionError(
-                @NonNull int[] networkCapabilities,
+                @NonNull String gatewayConnectionName,
                 @VcnErrorCode int errorCode,
                 @Nullable String exceptionClass,
                 @Nullable String exceptionMessage);
@@ -439,18 +447,18 @@
         }
 
         @Override
-        public void onEnteredSafeMode() {
-            sendMessage(obtainMessage(MSG_CMD_ENTER_SAFE_MODE));
+        public void onSafeModeStatusChanged() {
+            sendMessage(obtainMessage(MSG_EVENT_SAFE_MODE_STATE_CHANGED));
         }
 
         @Override
         public void onGatewayConnectionError(
-                @NonNull int[] networkCapabilities,
+                @NonNull String gatewayConnectionName,
                 @VcnErrorCode int errorCode,
                 @Nullable String exceptionClass,
                 @Nullable String exceptionMessage) {
             mVcnCallback.onGatewayConnectionError(
-                    networkCapabilities, errorCode, exceptionClass, exceptionMessage);
+                    gatewayConnectionName, errorCode, exceptionClass, exceptionMessage);
         }
     }
 
diff --git a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
index 9589505..20c08eb 100644
--- a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
+++ b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
@@ -32,6 +32,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
+import android.net.ConnectivityManager;
 import android.net.InetAddresses;
 import android.net.IpPrefix;
 import android.net.IpSecManager;
@@ -44,6 +45,7 @@
 import android.net.NetworkAgent;
 import android.net.NetworkAgentConfig;
 import android.net.NetworkCapabilities;
+import android.net.NetworkProvider;
 import android.net.RouteInfo;
 import android.net.TelephonyNetworkSpecifier;
 import android.net.Uri;
@@ -92,6 +94,7 @@
 import java.util.Objects;
 import java.util.Set;
 import java.util.concurrent.TimeUnit;
+import java.util.function.Consumer;
 
 /**
  * A single VCN Gateway Connection, providing a single public-facing VCN network.
@@ -504,6 +507,15 @@
     private boolean mIsQuitting = false;
 
     /**
+     * Whether the VcnGatewayConnection is in safe mode.
+     *
+     * <p>Upon hitting the safe mode timeout, this will be set to {@code true}. In safe mode, this
+     * VcnGatewayConnection will continue attempting to connect, and if a successful connection is
+     * made, safe mode will be exited.
+     */
+    private boolean mIsInSafeMode = false;
+
+    /**
      * The token used by the primary/current/active session.
      *
      * <p>This token MUST be updated when a new stateful/async session becomes the
@@ -562,8 +574,7 @@
      * <p>Set in Connected state, always @NonNull in Connected, Migrating states, @Nullable
      * otherwise.
      */
-    @VisibleForTesting(visibility = Visibility.PRIVATE)
-    NetworkAgent mNetworkAgent;
+    private NetworkAgent mNetworkAgent;
 
     @Nullable private WakeupMessage mTeardownTimeoutAlarm;
     @Nullable private WakeupMessage mDisconnectRequestAlarm;
@@ -628,6 +639,14 @@
         start();
     }
 
+    /** Queries whether this VcnGatewayConnection is in safe mode. */
+    public boolean isInSafeMode() {
+        // Accessing internal state; must only be done on looper thread.
+        mVcnContext.ensureRunningOnLooperThread();
+
+        return mIsInSafeMode;
+    }
+
     /**
      * Asynchronously tears down this GatewayConnection, and any resources used.
      *
@@ -980,7 +999,7 @@
         // IkeSessionCallback.onClosedExceptionally(), which calls sessionClosed()
         if (exception != null) {
             mGatewayStatusCallback.onGatewayConnectionError(
-                    mConnectionConfig.getExposedCapabilities(),
+                    mConnectionConfig.getGatewayConnectionName(),
                     VCN_ERROR_CODE_INTERNAL_ERROR,
                     RuntimeException.class.getName(),
                     "Received "
@@ -1017,7 +1036,7 @@
         }
 
         mGatewayStatusCallback.onGatewayConnectionError(
-                mConnectionConfig.getExposedCapabilities(),
+                mConnectionConfig.getGatewayConnectionName(),
                 errorCode,
                 exceptionClass,
                 exceptionMessage);
@@ -1162,6 +1181,15 @@
             }
         }
 
+        protected void handleSafeModeTimeoutExceeded() {
+            mSafeModeTimeoutAlarm = null;
+
+            // Connectivity for this GatewayConnection is broken; tear down the Network.
+            teardownNetwork();
+            mIsInSafeMode = true;
+            mGatewayStatusCallback.onSafeModeStatusChanged();
+        }
+
         protected void logUnexpectedEvent(int what) {
             Slog.d(TAG, String.format(
                     "Unexpected event code %d in state %s", what, this.getClass().getSimpleName()));
@@ -1315,8 +1343,7 @@
                     }
                     break;
                 case EVENT_SAFE_MODE_TIMEOUT_EXCEEDED:
-                    mGatewayStatusCallback.onEnteredSafeMode();
-                    mSafeModeTimeoutAlarm = null;
+                    handleSafeModeTimeoutExceeded();
                     break;
                 default:
                     logUnhandledMessage(msg);
@@ -1401,8 +1428,7 @@
                     handleDisconnectRequested((EventDisconnectRequestedInfo) msg.obj);
                     break;
                 case EVENT_SAFE_MODE_TIMEOUT_EXCEEDED:
-                    mGatewayStatusCallback.onEnteredSafeMode();
-                    mSafeModeTimeoutAlarm = null;
+                    handleSafeModeTimeoutExceeded();
                     break;
                 default:
                     logUnhandledMessage(msg);
@@ -1432,30 +1458,35 @@
                     buildNetworkCapabilities(mConnectionConfig, mUnderlying);
             final LinkProperties lp =
                     buildConnectedLinkProperties(mConnectionConfig, tunnelIface, childConfig);
+            final NetworkAgentConfig nac =
+                    new NetworkAgentConfig.Builder()
+                            .setLegacyType(ConnectivityManager.TYPE_MOBILE)
+                            .build();
 
             final NetworkAgent agent =
-                    new NetworkAgent(
-                            mVcnContext.getContext(),
-                            mVcnContext.getLooper(),
+                    mDeps.newNetworkAgent(
+                            mVcnContext,
                             TAG,
                             caps,
                             lp,
                             Vcn.getNetworkScore(),
-                            new NetworkAgentConfig.Builder().build(),
-                            mVcnContext.getVcnNetworkProvider()) {
-                        @Override
-                        public void onNetworkUnwanted() {
-                            Slog.d(TAG, "NetworkAgent was unwanted");
-                            teardownAsynchronously();
-                        }
-
-                        @Override
-                        public void onValidationStatus(int status, @Nullable Uri redirectUri) {
-                            if (status == NetworkAgent.VALIDATION_STATUS_VALID) {
-                                clearFailedAttemptCounterAndSafeModeAlarm();
-                            }
-                        }
-                    };
+                            nac,
+                            mVcnContext.getVcnNetworkProvider(),
+                            () -> {
+                                Slog.d(TAG, "NetworkAgent was unwanted");
+                                // If network agent has already been torn down, skip sending the
+                                // disconnect. Unwanted() is always called, even when networkAgents
+                                // are unregistered in teardownNetwork(), so prevent duplicate
+                                // notifications.
+                                if (mNetworkAgent != null) {
+                                    teardownAsynchronously();
+                                }
+                            } /* networkUnwantedCallback */,
+                            (status) -> {
+                                if (status == NetworkAgent.VALIDATION_STATUS_VALID) {
+                                    clearFailedAttemptCounterAndSafeModeAlarm();
+                                }
+                            } /* validationStatusCallback */);
 
             agent.register();
             agent.markConnected();
@@ -1469,6 +1500,11 @@
             // Validated connection, clear failed attempt counter
             mFailedAttempts = 0;
             cancelSafeModeAlarm();
+
+            if (mIsInSafeMode) {
+                mIsInSafeMode = false;
+                mGatewayStatusCallback.onSafeModeStatusChanged();
+            }
         }
 
         protected void applyTransform(
@@ -1491,13 +1527,6 @@
         protected void setupInterface(
                 int token,
                 @NonNull IpSecTunnelInterface tunnelIface,
-                @NonNull VcnChildSessionConfiguration childConfig) {
-            setupInterface(token, tunnelIface, childConfig, null);
-        }
-
-        protected void setupInterface(
-                int token,
-                @NonNull IpSecTunnelInterface tunnelIface,
                 @NonNull VcnChildSessionConfiguration childConfig,
                 @Nullable VcnChildSessionConfiguration oldChildConfig) {
             try {
@@ -1579,16 +1608,17 @@
                             transformCreatedInfo.direction);
                     break;
                 case EVENT_SETUP_COMPLETED:
+                    final VcnChildSessionConfiguration oldChildConfig = mChildConfig;
                     mChildConfig = ((EventSetupCompletedInfo) msg.obj).childSessionConfig;
 
-                    setupInterfaceAndNetworkAgent(mCurrentToken, mTunnelIface, mChildConfig);
+                    setupInterfaceAndNetworkAgent(
+                            mCurrentToken, mTunnelIface, mChildConfig, oldChildConfig);
                     break;
                 case EVENT_DISCONNECT_REQUESTED:
                     handleDisconnectRequested((EventDisconnectRequestedInfo) msg.obj);
                     break;
                 case EVENT_SAFE_MODE_TIMEOUT_EXCEEDED:
-                    mGatewayStatusCallback.onEnteredSafeMode();
-                    mSafeModeTimeoutAlarm = null;
+                    handleSafeModeTimeoutExceeded();
                     break;
                 default:
                     logUnhandledMessage(msg);
@@ -1626,8 +1656,9 @@
         protected void setupInterfaceAndNetworkAgent(
                 int token,
                 @NonNull IpSecTunnelInterface tunnelIface,
-                @NonNull VcnChildSessionConfiguration childConfig) {
-            setupInterface(token, tunnelIface, childConfig);
+                @NonNull VcnChildSessionConfiguration childConfig,
+                @NonNull VcnChildSessionConfiguration oldChildConfig) {
+            setupInterface(token, tunnelIface, childConfig, oldChildConfig);
 
             if (mNetworkAgent == null) {
                 mNetworkAgent = buildNetworkAgent(tunnelIface, childConfig);
@@ -1692,8 +1723,7 @@
                     handleDisconnectRequested((EventDisconnectRequestedInfo) msg.obj);
                     break;
                 case EVENT_SAFE_MODE_TIMEOUT_EXCEEDED:
-                    mGatewayStatusCallback.onEnteredSafeMode();
-                    mSafeModeTimeoutAlarm = null;
+                    handleSafeModeTimeoutExceeded();
                     break;
                 default:
                     logUnhandledMessage(msg);
@@ -1935,6 +1965,16 @@
     }
 
     @VisibleForTesting(visibility = Visibility.PRIVATE)
+    NetworkAgent getNetworkAgent() {
+        return mNetworkAgent;
+    }
+
+    @VisibleForTesting(visibility = Visibility.PRIVATE)
+    void setNetworkAgent(@Nullable NetworkAgent networkAgent) {
+        mNetworkAgent = networkAgent;
+    }
+
+    @VisibleForTesting(visibility = Visibility.PRIVATE)
     void sendDisconnectRequestedAndAcquireWakelock(String reason, boolean shouldQuit) {
         sendMessageAndAcquireWakeLock(
                 EVENT_DISCONNECT_REQUESTED,
@@ -2018,6 +2058,38 @@
             return new WakeupMessage(vcnContext.getContext(), handler, tag, runnable);
         }
 
+        /** Builds a new NetworkAgent. */
+        public NetworkAgent newNetworkAgent(
+                @NonNull VcnContext vcnContext,
+                @NonNull String tag,
+                @NonNull NetworkCapabilities caps,
+                @NonNull LinkProperties lp,
+                @NonNull int score,
+                @NonNull NetworkAgentConfig nac,
+                @NonNull NetworkProvider provider,
+                @NonNull Runnable networkUnwantedCallback,
+                @NonNull Consumer<Integer> validationStatusCallback) {
+            return new NetworkAgent(
+                    vcnContext.getContext(),
+                    vcnContext.getLooper(),
+                    tag,
+                    caps,
+                    lp,
+                    score,
+                    nac,
+                    provider) {
+                @Override
+                public void onNetworkUnwanted() {
+                    networkUnwantedCallback.run();
+                }
+
+                @Override
+                public void onValidationStatus(int status, @Nullable Uri redirectUri) {
+                    validationStatusCallback.accept(status);
+                }
+            };
+        }
+
         /** Gets the elapsed real time since boot, in millis. */
         public long getElapsedRealTime() {
             return SystemClock.elapsedRealtime();
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index ea47a27..24bb1b1 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -110,7 +110,6 @@
         "libhardware",
         "libhardware_legacy",
         "libhidlbase",
-        "libkeystore_binder",
         "libmtp",
         "libnativehelper",
         "libprocessgroup",
diff --git a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
index 100d3ea..f5876fa 100644
--- a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
@@ -33,12 +33,6 @@
 import static android.net.NetworkPolicyManager.POLICY_ALLOW_METERED_BACKGROUND;
 import static android.net.NetworkPolicyManager.POLICY_NONE;
 import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
-import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
-import static android.net.NetworkPolicyManager.RULE_ALLOW_METERED;
-import static android.net.NetworkPolicyManager.RULE_NONE;
-import static android.net.NetworkPolicyManager.RULE_REJECT_ALL;
-import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
-import static android.net.NetworkPolicyManager.RULE_TEMPORARY_ALLOW_METERED;
 import static android.net.NetworkPolicyManager.uidPoliciesToString;
 import static android.net.NetworkPolicyManager.uidRulesToString;
 import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK;
@@ -49,7 +43,6 @@
 import static android.net.NetworkTemplate.buildTemplateMobileAll;
 import static android.net.NetworkTemplate.buildTemplateWifi;
 import static android.net.TrafficStats.MB_IN_BYTES;
-import static android.os.Process.SYSTEM_UID;
 import static android.telephony.CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED;
 import static android.telephony.CarrierConfigManager.DATA_CYCLE_THRESHOLD_DISABLED;
 import static android.telephony.CarrierConfigManager.DATA_CYCLE_USE_PLATFORM_DEFAULT;
@@ -141,7 +134,6 @@
 import android.util.ArrayMap;
 import android.util.DataUnit;
 import android.util.Log;
-import android.util.Pair;
 import android.util.Range;
 import android.util.RecurrenceRule;
 
@@ -1844,68 +1836,6 @@
         reset(mStatsService);
     }
 
-    /**
-     * Exhaustively test checkUidNetworkingBlocked to output the expected results based on external
-     * conditions.
-     */
-    @Test
-    public void testCheckUidNetworkingBlocked() {
-        final ArrayList<Pair<Boolean, Integer>> expectedBlockedStates = new ArrayList<>();
-
-        // Metered network. Data saver on.
-        expectedBlockedStates.add(new Pair<>(true, RULE_NONE));
-        expectedBlockedStates.add(new Pair<>(false, RULE_ALLOW_METERED));
-        expectedBlockedStates.add(new Pair<>(false, RULE_TEMPORARY_ALLOW_METERED));
-        expectedBlockedStates.add(new Pair<>(true, RULE_REJECT_METERED));
-        expectedBlockedStates.add(new Pair<>(true, RULE_ALLOW_ALL));
-        expectedBlockedStates.add(new Pair<>(true, RULE_REJECT_ALL));
-        verifyNetworkBlockedState(
-                true /* metered */, true /* backgroundRestricted */, expectedBlockedStates);
-        expectedBlockedStates.clear();
-
-        // Metered network. Data saver off.
-        expectedBlockedStates.add(new Pair<>(false, RULE_NONE));
-        expectedBlockedStates.add(new Pair<>(false, RULE_ALLOW_METERED));
-        expectedBlockedStates.add(new Pair<>(false, RULE_TEMPORARY_ALLOW_METERED));
-        expectedBlockedStates.add(new Pair<>(true, RULE_REJECT_METERED));
-        expectedBlockedStates.add(new Pair<>(false, RULE_ALLOW_ALL));
-        expectedBlockedStates.add(new Pair<>(true, RULE_REJECT_ALL));
-        verifyNetworkBlockedState(
-                true /* metered */, false /* backgroundRestricted */, expectedBlockedStates);
-        expectedBlockedStates.clear();
-
-        // Non-metered network. Data saver on.
-        expectedBlockedStates.add(new Pair<>(false, RULE_NONE));
-        expectedBlockedStates.add(new Pair<>(false, RULE_ALLOW_METERED));
-        expectedBlockedStates.add(new Pair<>(false, RULE_TEMPORARY_ALLOW_METERED));
-        expectedBlockedStates.add(new Pair<>(false, RULE_REJECT_METERED));
-        expectedBlockedStates.add(new Pair<>(false, RULE_ALLOW_ALL));
-        expectedBlockedStates.add(new Pair<>(true, RULE_REJECT_ALL));
-        verifyNetworkBlockedState(
-                false /* metered */, true /* backgroundRestricted */, expectedBlockedStates);
-
-        // Non-metered network. Data saver off. The result is the same as previous case since
-        // the network is blocked only for RULE_REJECT_ALL regardless of data saver.
-        verifyNetworkBlockedState(
-                false /* metered */, false /* backgroundRestricted */, expectedBlockedStates);
-        expectedBlockedStates.clear();
-    }
-
-    private void verifyNetworkBlockedState(boolean metered, boolean backgroundRestricted,
-            ArrayList<Pair<Boolean, Integer>> expectedBlockedStateForRules) {
-
-        for (Pair<Boolean, Integer> pair : expectedBlockedStateForRules) {
-            final boolean expectedResult = pair.first;
-            final int rule = pair.second;
-            assertEquals(formatBlockedStateError(UID_A, rule, metered, backgroundRestricted),
-                    expectedResult, mService.checkUidNetworkingBlocked(UID_A, rule,
-                            metered, backgroundRestricted));
-            assertFalse(formatBlockedStateError(SYSTEM_UID, rule, metered, backgroundRestricted),
-                    mService.checkUidNetworkingBlocked(SYSTEM_UID, rule, metered,
-                            backgroundRestricted));
-        }
-    }
-
     private void enableRestrictedMode(boolean enable) throws Exception {
         mService.mRestrictedNetworkingMode = enable;
         mService.updateRestrictedModeAllowlistUL();
diff --git a/telephony/java/android/telephony/data/DataCallResponse.java b/telephony/java/android/telephony/data/DataCallResponse.java
index a5e5ab01..ad57b91 100644
--- a/telephony/java/android/telephony/data/DataCallResponse.java
+++ b/telephony/java/android/telephony/data/DataCallResponse.java
@@ -70,6 +70,7 @@
 
     /** {@hide} */
     @IntDef(prefix = "HANDOVER_FAILURE_MODE_", value = {
+            HANDOVER_FAILURE_MODE_UNKNOWN,
             HANDOVER_FAILURE_MODE_LEGACY,
             HANDOVER_FAILURE_MODE_DO_FALLBACK,
             HANDOVER_FAILURE_MODE_NO_FALLBACK_RETRY_HANDOVER,
diff --git a/telephony/java/android/telephony/ims/SipMessage.java b/telephony/java/android/telephony/ims/SipMessage.java
index ad6d73c..b529563 100644
--- a/telephony/java/android/telephony/ims/SipMessage.java
+++ b/telephony/java/android/telephony/ims/SipMessage.java
@@ -24,6 +24,7 @@
 import android.os.Build;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.text.TextUtils;
 
 import com.android.internal.telephony.SipMessageParsingUtils;
 
@@ -60,14 +61,19 @@
      */
     public SipMessage(@NonNull String startLine, @NonNull String headerSection,
             @NonNull byte[] content) {
-        if (startLine == null || headerSection == null || content == null) {
-            throw new IllegalArgumentException("One or more null parameters entered");
-        }
+        Objects.requireNonNull(startLine, "Required parameter is null: startLine");
+        Objects.requireNonNull(headerSection, "Required parameter is null: headerSection");
+        Objects.requireNonNull(content, "Required parameter is null: content");
+
         mStartLine = startLine;
         mHeaderSection = headerSection;
         mContent = content;
 
         mViaBranchParam = SipMessageParsingUtils.getTransactionId(mHeaderSection);
+        if (TextUtils.isEmpty(mViaBranchParam)) {
+            throw new IllegalArgumentException("header section MUST contain a branch parameter "
+                    + "inside of the Via header.");
+        }
         mCallIdParam = SipMessageParsingUtils.getCallId(mHeaderSection);
     }
 
@@ -107,11 +113,9 @@
 
     /**
      * @return the branch parameter enclosed in the Via header key's value. See RFC 3261 section
-     * 20.42 for more information on the Via header. If {@code null}, then there was either no
-     * Via parameter found in this SIP message's headers or no branch parameter found in the
-     * Via header.
+     * 20.42 for more information on the Via header.
      */
-    public @Nullable String getViaBranchParameter() {
+    public @NonNull String getViaBranchParameter() {
         return mViaBranchParam;
     }
 
diff --git a/telephony/java/android/telephony/ims/aidl/SipDelegateAidlWrapper.java b/telephony/java/android/telephony/ims/aidl/SipDelegateAidlWrapper.java
index 739946b..5c9ec53 100644
--- a/telephony/java/android/telephony/ims/aidl/SipDelegateAidlWrapper.java
+++ b/telephony/java/android/telephony/ims/aidl/SipDelegateAidlWrapper.java
@@ -28,8 +28,6 @@
 import android.telephony.ims.SipDelegateManager;
 import android.telephony.ims.SipMessage;
 import android.telephony.ims.stub.SipDelegate;
-import android.text.TextUtils;
-import android.util.Log;
 
 import java.util.ArrayList;
 import java.util.Set;
@@ -187,11 +185,6 @@
 
     private void notifyLocalMessageFailedToBeReceived(SipMessage m, int reason) {
         String transactionId = m.getViaBranchParameter();
-        if (TextUtils.isEmpty(transactionId)) {
-            Log.w(LOG_TAG, "failure to parse SipMessage.");
-            throw new IllegalArgumentException("Malformed SipMessage, can not determine "
-                    + "transaction ID.");
-        }
         SipDelegate d = mDelegate;
         if (d != null) {
             mExecutor.execute(() -> d.notifyMessageReceiveError(transactionId, reason));
diff --git a/telephony/java/android/telephony/ims/aidl/SipDelegateConnectionAidlWrapper.java b/telephony/java/android/telephony/ims/aidl/SipDelegateConnectionAidlWrapper.java
index 3cd2726..ad02fe5 100644
--- a/telephony/java/android/telephony/ims/aidl/SipDelegateConnectionAidlWrapper.java
+++ b/telephony/java/android/telephony/ims/aidl/SipDelegateConnectionAidlWrapper.java
@@ -28,7 +28,6 @@
 import android.telephony.ims.stub.DelegateConnectionMessageCallback;
 import android.telephony.ims.stub.DelegateConnectionStateCallback;
 import android.telephony.ims.stub.SipDelegate;
-import android.text.TextUtils;
 import android.util.ArraySet;
 import android.util.Log;
 
@@ -267,12 +266,6 @@
 
     private void notifyLocalMessageFailedToSend(SipMessage m, int reason) {
         String transactionId = m.getViaBranchParameter();
-        if (TextUtils.isEmpty(transactionId)) {
-            Log.w(LOG_TAG, "sendMessage detected a malformed SipMessage and can not get a "
-                    + "transaction ID.");
-            throw new IllegalArgumentException("Could not send SipMessage due to malformed header");
-        }
-        mExecutor.execute(() ->
-                mMessageCallback.onMessageSendFailure(transactionId, reason));
+        mExecutor.execute(() -> mMessageCallback.onMessageSendFailure(transactionId, reason));
     }
 }
diff --git a/tests/net/java/android/net/VpnTransportInfoTest.java b/tests/net/java/android/net/VpnTransportInfoTest.java
index b7a42ec..fee65f0 100644
--- a/tests/net/java/android/net/VpnTransportInfoTest.java
+++ b/tests/net/java/android/net/VpnTransportInfoTest.java
@@ -16,6 +16,9 @@
 
 package android.net;
 
+import static android.net.NetworkCapabilities.REDACT_FOR_NETWORK_SETTINGS;
+import static android.net.NetworkCapabilities.REDACT_NONE;
+
 import static com.android.testutils.ParcelUtils.assertParcelSane;
 
 import static org.junit.Assert.assertEquals;
@@ -33,23 +36,33 @@
 
     @Test
     public void testParceling() {
-        VpnTransportInfo v = new VpnTransportInfo(VpnManager.TYPE_VPN_PLATFORM);
-        assertParcelSane(v, 1 /* fieldCount */);
+        VpnTransportInfo v = new VpnTransportInfo(VpnManager.TYPE_VPN_PLATFORM, "12345");
+        assertParcelSane(v, 2 /* fieldCount */);
     }
 
     @Test
     public void testEqualsAndHashCode() {
-        VpnTransportInfo v1 = new VpnTransportInfo(VpnManager.TYPE_VPN_PLATFORM);
-        VpnTransportInfo v2 = new VpnTransportInfo(VpnManager.TYPE_VPN_SERVICE);
-        VpnTransportInfo v3 = new VpnTransportInfo(VpnManager.TYPE_VPN_PLATFORM);
-        VpnTransportInfo v4 = new VpnTransportInfo(VpnManager.TYPE_VPN_LEGACY);
-        VpnTransportInfo v5 = new VpnTransportInfo(VpnManager.TYPE_VPN_OEM);
+        String session1 = "12345";
+        String session2 = "6789";
+        VpnTransportInfo v11 = new VpnTransportInfo(VpnManager.TYPE_VPN_PLATFORM, session1);
+        VpnTransportInfo v12 = new VpnTransportInfo(VpnManager.TYPE_VPN_SERVICE, session1);
+        VpnTransportInfo v13 = new VpnTransportInfo(VpnManager.TYPE_VPN_PLATFORM, session1);
+        VpnTransportInfo v14 = new VpnTransportInfo(VpnManager.TYPE_VPN_LEGACY, session1);
+        VpnTransportInfo v15 = new VpnTransportInfo(VpnManager.TYPE_VPN_OEM, session1);
+        VpnTransportInfo v21 = new VpnTransportInfo(VpnManager.TYPE_VPN_LEGACY, session2);
 
-        assertNotEquals(v1, v2);
-        assertNotEquals(v3, v4);
-        assertNotEquals(v4, v5);
+        VpnTransportInfo v31 = v11.makeCopy(REDACT_FOR_NETWORK_SETTINGS);
+        VpnTransportInfo v32 = v13.makeCopy(REDACT_FOR_NETWORK_SETTINGS);
 
-        assertEquals(v1, v3);
-        assertEquals(v1.hashCode(), v3.hashCode());
+        assertNotEquals(v11, v12);
+        assertNotEquals(v13, v14);
+        assertNotEquals(v14, v15);
+        assertNotEquals(v14, v21);
+
+        assertEquals(v11, v13);
+        assertEquals(v31, v32);
+        assertEquals(v11.hashCode(), v13.hashCode());
+        assertEquals(REDACT_FOR_NETWORK_SETTINGS, v32.getApplicableRedactions());
+        assertEquals(session1, v15.makeCopy(REDACT_NONE).sessionId);
     }
-}
\ No newline at end of file
+}
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index ad93420..270941f 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -18,8 +18,12 @@
 
 import static android.Manifest.permission.CHANGE_NETWORK_STATE;
 import static android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS;
+import static android.Manifest.permission.NETWORK_FACTORY;
 import static android.Manifest.permission.NETWORK_SETTINGS;
 import static android.app.PendingIntent.FLAG_IMMUTABLE;
+import static android.content.Intent.ACTION_PACKAGE_ADDED;
+import static android.content.Intent.ACTION_PACKAGE_REMOVED;
+import static android.content.Intent.ACTION_PACKAGE_REPLACED;
 import static android.content.Intent.ACTION_USER_ADDED;
 import static android.content.Intent.ACTION_USER_REMOVED;
 import static android.content.Intent.ACTION_USER_UNLOCKED;
@@ -577,6 +581,7 @@
             final UserManager umMock = createContextAsUser(userHandle, 0 /* flags */)
                     .getSystemService(UserManager.class);
             doReturn(value).when(umMock).isManagedProfile();
+            doReturn(value).when(mUserManager).isManagedProfile(eq(userHandle.getIdentifier()));
         }
 
         @Override
@@ -1228,10 +1233,12 @@
             if (mAgentRegistered) throw new IllegalStateException("already registered");
             updateState(NetworkInfo.DetailedState.CONNECTING, "registerAgent");
             mConfig = new VpnConfig();
+            mConfig.session = "MySession12345";
             setUids(uids);
             if (!isAlwaysMetered) mNetworkCapabilities.addCapability(NET_CAPABILITY_NOT_METERED);
             mInterface = VPN_IFNAME;
-            mNetworkCapabilities.setTransportInfo(new VpnTransportInfo(getActiveVpnType()));
+            mNetworkCapabilities.setTransportInfo(new VpnTransportInfo(getActiveVpnType(),
+                    mConfig.session));
             mMockNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN, lp,
                     mNetworkCapabilities);
             mMockNetworkAgent.waitForIdle(TIMEOUT_MS);
@@ -2791,10 +2798,14 @@
     }
 
     private void grantUsingBackgroundNetworksPermissionForUid(final int uid) throws Exception {
-        final String myPackageName = mContext.getPackageName();
-        when(mPackageManager.getPackageInfo(eq(myPackageName), eq(GET_PERMISSIONS)))
+        grantUsingBackgroundNetworksPermissionForUid(uid, mContext.getPackageName());
+    }
+
+    private void grantUsingBackgroundNetworksPermissionForUid(
+            final int uid, final String packageName) throws Exception {
+        when(mPackageManager.getPackageInfo(eq(packageName), eq(GET_PERMISSIONS)))
                 .thenReturn(buildPackageInfo(true, uid));
-        mService.mPermissionMonitor.onPackageAdded(myPackageName, uid);
+        mService.mPermissionMonitor.onPackageAdded(packageName, uid);
     }
 
     @Test
@@ -10253,6 +10264,12 @@
                 .thenReturn(applicationInfo);
     }
 
+    private void mockGetApplicationInfoThrowsNameNotFound(@NonNull final String packageName)
+            throws Exception {
+        when(mPackageManager.getApplicationInfo(eq(packageName), anyInt()))
+                .thenThrow(new PackageManager.NameNotFoundException(packageName));
+    }
+
     private void mockHasSystemFeature(@NonNull final String featureName,
             @NonNull final boolean hasFeature) {
         when(mPackageManager.hasSystemFeature(eq(featureName)))
@@ -10709,15 +10726,23 @@
             @NonNull final UidRangeParcel[] uidRanges,
             @NonNull final String testPackageName)
             throws Exception {
-        mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, true);
-
         // These tests work off a single UID therefore using 'start' is valid.
         mockGetApplicationInfo(testPackageName, uidRanges[0].start);
 
+        setOemNetworkPreference(networkPrefToSetup, testPackageName);
+    }
+
+    private void setOemNetworkPreference(final int networkPrefToSetup,
+            @NonNull final String... testPackageNames)
+            throws Exception {
+        mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, true);
+
         // Build OemNetworkPreferences object
-        final OemNetworkPreferences pref = new OemNetworkPreferences.Builder()
-                .addNetworkPreference(testPackageName, networkPrefToSetup)
-                .build();
+        final OemNetworkPreferences.Builder builder = new OemNetworkPreferences.Builder();
+        for (final String packageName : testPackageNames) {
+            builder.addNetworkPreference(packageName, networkPrefToSetup);
+        }
+        final OemNetworkPreferences pref = builder.build();
 
         // Act on ConnectivityService.setOemNetworkPreference()
         final TestOemListenerCallback oemPrefListener = new TestOemListenerCallback();
@@ -11316,8 +11341,7 @@
         // Arrange PackageManager mocks
         final int secondUserTestPackageUid = UserHandle.getUid(secondUser, TEST_PACKAGE_UID);
         final UidRangeParcel[] uidRangesSingleUser =
-                toUidRangeStableParcels(
-                        uidRangesForUids(TEST_PACKAGE_UID));
+                toUidRangeStableParcels(uidRangesForUids(TEST_PACKAGE_UID));
         final UidRangeParcel[] uidRangesBothUsers =
                 toUidRangeStableParcels(
                         uidRangesForUids(TEST_PACKAGE_UID, secondUserTestPackageUid));
@@ -11364,6 +11388,84 @@
                 false /* shouldDestroyNetwork */);
     }
 
+    @Test
+    public void testMultilayerForPackageChangesEvaluatesCorrectly()
+            throws Exception {
+        @OemNetworkPreferences.OemNetworkPreference final int networkPref =
+                OEM_NETWORK_PREFERENCE_OEM_PAID;
+        final String packageScheme = "package:";
+
+        // Arrange PackageManager mocks
+        final String packageToInstall = "package.to.install";
+        final int packageToInstallUid = 81387;
+        final UidRangeParcel[] uidRangesSinglePackage =
+                toUidRangeStableParcels(uidRangesForUids(TEST_PACKAGE_UID));
+        mockGetApplicationInfo(TEST_PACKAGE_NAME, TEST_PACKAGE_UID);
+        mockGetApplicationInfoThrowsNameNotFound(packageToInstall);
+        setOemNetworkPreference(networkPref, TEST_PACKAGE_NAME, packageToInstall);
+        grantUsingBackgroundNetworksPermissionForUid(Binder.getCallingUid(), packageToInstall);
+
+        // Verify the starting state. No networks should be connected.
+        verifySetOemNetworkPreferenceForPreference(uidRangesSinglePackage,
+                OEM_PREF_ANY_NET_ID, 0 /* times */,
+                OEM_PREF_ANY_NET_ID, 0 /* times */,
+                false /* shouldDestroyNetwork */);
+
+        // Test that we correctly add the expected values for installed packages.
+        setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
+        verifySetOemNetworkPreferenceForPreference(uidRangesSinglePackage,
+                mCellNetworkAgent.getNetwork().netId, 1 /* times */,
+                OEM_PREF_ANY_NET_ID, 0 /* times */,
+                false /* shouldDestroyNetwork */);
+
+        // Set the system to recognize the package to be installed
+        mockGetApplicationInfo(packageToInstall, packageToInstallUid);
+        final UidRangeParcel[] uidRangesAllPackages =
+                toUidRangeStableParcels(uidRangesForUids(TEST_PACKAGE_UID, packageToInstallUid));
+
+        // Send a broadcast indicating a package was installed.
+        final Intent addedIntent = new Intent(ACTION_PACKAGE_ADDED);
+        addedIntent.setData(Uri.parse(packageScheme + packageToInstall));
+        processBroadcast(addedIntent);
+
+        // Test the single package is removed and the combined packages are added.
+        verifySetOemNetworkPreferenceForPreference(uidRangesAllPackages, uidRangesSinglePackage,
+                mCellNetworkAgent.getNetwork().netId, 1 /* times */,
+                mCellNetworkAgent.getNetwork().netId, 1 /* times */,
+                false /* shouldDestroyNetwork */);
+
+        // Set the system to no longer recognize the package to be installed
+        mockGetApplicationInfoThrowsNameNotFound(packageToInstall);
+
+        // Send a broadcast indicating a package was removed.
+        final Intent removedIntent = new Intent(ACTION_PACKAGE_REMOVED);
+        removedIntent.setData(Uri.parse(packageScheme + packageToInstall));
+        processBroadcast(removedIntent);
+
+        // Test the combined packages are removed and the single package is added.
+        verifySetOemNetworkPreferenceForPreference(uidRangesSinglePackage, uidRangesAllPackages,
+                mCellNetworkAgent.getNetwork().netId, 1 /* times */,
+                mCellNetworkAgent.getNetwork().netId, 1 /* times */,
+                false /* shouldDestroyNetwork */);
+
+        // Set the system to change the installed package's uid
+        final int replacedTestPackageUid = TEST_PACKAGE_UID + 1;
+        mockGetApplicationInfo(TEST_PACKAGE_NAME, replacedTestPackageUid);
+        final UidRangeParcel[] uidRangesReplacedPackage =
+                toUidRangeStableParcels(uidRangesForUids(replacedTestPackageUid));
+
+        // Send a broadcast indicating a package was replaced.
+        final Intent replacedIntent = new Intent(ACTION_PACKAGE_REPLACED);
+        replacedIntent.setData(Uri.parse(packageScheme + TEST_PACKAGE_NAME));
+        processBroadcast(replacedIntent);
+
+        // Test the original uid is removed and is replaced with the new uid.
+        verifySetOemNetworkPreferenceForPreference(uidRangesReplacedPackage, uidRangesSinglePackage,
+                mCellNetworkAgent.getNetwork().netId, 1 /* times */,
+                mCellNetworkAgent.getNetwork().netId, 1 /* times */,
+                false /* shouldDestroyNetwork */);
+    }
+
     /**
      * Test network priority for preference OEM_NETWORK_PREFERENCE_OEM_PAID in the following order:
      * NET_CAPABILITY_NOT_METERED -> NET_CAPABILITY_OEM_PAID -> fallback
@@ -12186,4 +12288,68 @@
                         mCm.setProfileNetworkPreference(testHandle,
                                 PROFILE_NETWORK_PREFERENCE_ENTERPRISE, null, null));
     }
+
+    @Test
+    public void testSubIdsClearedWithoutNetworkFactoryPermission() throws Exception {
+        mServiceContext.setPermission(NETWORK_FACTORY, PERMISSION_DENIED);
+        final NetworkCapabilities nc = new NetworkCapabilities();
+        nc.setSubIds(Collections.singleton(Process.myUid()));
+
+        final NetworkCapabilities result =
+                mService.networkCapabilitiesRestrictedForCallerPermissions(
+                        nc, Process.myPid(), Process.myUid());
+        assertTrue(result.getSubIds().isEmpty());
+    }
+
+    @Test
+    public void testSubIdsExistWithNetworkFactoryPermission() throws Exception {
+        mServiceContext.setPermission(NETWORK_FACTORY, PERMISSION_GRANTED);
+
+        final Set<Integer> subIds = Collections.singleton(Process.myUid());
+        final NetworkCapabilities nc = new NetworkCapabilities();
+        nc.setSubIds(subIds);
+
+        final NetworkCapabilities result =
+                mService.networkCapabilitiesRestrictedForCallerPermissions(
+                        nc, Process.myPid(), Process.myUid());
+        assertEquals(subIds, result.getSubIds());
+    }
+
+    private NetworkRequest getRequestWithSubIds() {
+        return new NetworkRequest.Builder()
+                .setSubIds(Collections.singleton(Process.myUid()))
+                .build();
+    }
+
+    @Test
+    public void testNetworkRequestWithSubIdsWithNetworkFactoryPermission() throws Exception {
+        mServiceContext.setPermission(NETWORK_FACTORY, PERMISSION_GRANTED);
+        final PendingIntent pendingIntent = PendingIntent.getBroadcast(
+                mContext, 0 /* requestCode */, new Intent("a"), FLAG_IMMUTABLE);
+        final NetworkCallback networkCallback1 = new NetworkCallback();
+        final NetworkCallback networkCallback2 = new NetworkCallback();
+
+        mCm.requestNetwork(getRequestWithSubIds(), networkCallback1);
+        mCm.requestNetwork(getRequestWithSubIds(), pendingIntent);
+        mCm.registerNetworkCallback(getRequestWithSubIds(), networkCallback2);
+
+        mCm.unregisterNetworkCallback(networkCallback1);
+        mCm.releaseNetworkRequest(pendingIntent);
+        mCm.unregisterNetworkCallback(networkCallback2);
+    }
+
+    @Test
+    public void testNetworkRequestWithSubIdsWithoutNetworkFactoryPermission() throws Exception {
+        mServiceContext.setPermission(NETWORK_FACTORY, PERMISSION_DENIED);
+        final PendingIntent pendingIntent = PendingIntent.getBroadcast(
+                mContext, 0 /* requestCode */, new Intent("a"), FLAG_IMMUTABLE);
+
+        final Class<SecurityException> expected = SecurityException.class;
+        assertThrows(
+                expected, () -> mCm.requestNetwork(getRequestWithSubIds(), new NetworkCallback()));
+        assertThrows(expected, () -> mCm.requestNetwork(getRequestWithSubIds(), pendingIntent));
+        assertThrows(
+                expected,
+                () -> mCm.registerNetworkCallback(getRequestWithSubIds(), new NetworkCallback()));
+    }
 }
diff --git a/tests/vcn/java/android/net/vcn/VcnConfigTest.java b/tests/vcn/java/android/net/vcn/VcnConfigTest.java
index c1ef350..7ac51b7 100644
--- a/tests/vcn/java/android/net/vcn/VcnConfigTest.java
+++ b/tests/vcn/java/android/net/vcn/VcnConfigTest.java
@@ -79,6 +79,18 @@
     }
 
     @Test
+    public void testBuilderRequiresUniqueGatewayConnectionNames() {
+        final VcnGatewayConnectionConfig config = VcnGatewayConnectionConfigTest.buildTestConfig();
+        try {
+            new VcnConfig.Builder(mContext)
+                    .addGatewayConnectionConfig(config)
+                    .addGatewayConnectionConfig(config);
+            fail("Expected exception due to duplicate gateway connection name");
+        } catch (IllegalArgumentException e) {
+        }
+    }
+
+    @Test
     public void testBuilderAndGetters() {
         final VcnConfig config = buildTestConfig(mContext);
 
diff --git a/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java b/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java
index 8a0c923..4ee4d61 100644
--- a/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java
+++ b/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java
@@ -19,6 +19,7 @@
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
 import android.net.NetworkCapabilities;
@@ -61,13 +62,20 @@
     public static final VcnControlPlaneConfig CONTROL_PLANE_CONFIG =
             VcnControlPlaneIkeConfigTest.buildTestConfig();
 
+    public static final String GATEWAY_CONNECTION_NAME_PREFIX = "gatewayConnectionName-";
+    private static int sGatewayConnectionConfigCount = 0;
+
     // Public for use in VcnGatewayConnectionTest
     public static VcnGatewayConnectionConfig buildTestConfig() {
         return buildTestConfigWithExposedCaps(EXPOSED_CAPS);
     }
 
     private static VcnGatewayConnectionConfig.Builder newBuilder() {
-        return new VcnGatewayConnectionConfig.Builder(CONTROL_PLANE_CONFIG);
+        // Append a unique identifier to the name prefix to guarantee that all created
+        // VcnGatewayConnectionConfigs have a unique name (required by VcnConfig).
+        return new VcnGatewayConnectionConfig.Builder(
+                GATEWAY_CONNECTION_NAME_PREFIX + sGatewayConnectionConfigCount++,
+                CONTROL_PLANE_CONFIG);
     }
 
     // Public for use in VcnGatewayConnectionTest
@@ -87,9 +95,23 @@
     }
 
     @Test
+    public void testBuilderRequiresNonNullGatewayConnectionName() {
+        try {
+            new VcnGatewayConnectionConfig.Builder(
+                            null /* gatewayConnectionName */, CONTROL_PLANE_CONFIG)
+                    .build();
+
+            fail("Expected exception due to invalid gateway connection name");
+        } catch (NullPointerException e) {
+        }
+    }
+
+    @Test
     public void testBuilderRequiresNonNullControlPlaneConfig() {
         try {
-            new VcnGatewayConnectionConfig.Builder(null).build();
+            new VcnGatewayConnectionConfig.Builder(
+                            GATEWAY_CONNECTION_NAME_PREFIX, null /* ctrlPlaneConfig */)
+                    .build();
 
             fail("Expected exception due to invalid control plane config");
         } catch (NullPointerException e) {
@@ -139,6 +161,8 @@
     public void testBuilderAndGetters() {
         final VcnGatewayConnectionConfig config = buildTestConfig();
 
+        assertTrue(config.getGatewayConnectionName().startsWith(GATEWAY_CONNECTION_NAME_PREFIX));
+
         int[] exposedCaps = config.getExposedCapabilities();
         Arrays.sort(exposedCaps);
         assertArrayEquals(EXPOSED_CAPS, exposedCaps);
diff --git a/tests/vcn/java/android/net/vcn/VcnManagerTest.java b/tests/vcn/java/android/net/vcn/VcnManagerTest.java
index 516c206..8461de6 100644
--- a/tests/vcn/java/android/net/vcn/VcnManagerTest.java
+++ b/tests/vcn/java/android/net/vcn/VcnManagerTest.java
@@ -50,9 +50,7 @@
 
 public class VcnManagerTest {
     private static final ParcelUuid SUB_GROUP = new ParcelUuid(new UUID(0, 0));
-    private static final int[] UNDERLYING_NETWORK_CAPABILITIES = {
-        NetworkCapabilities.NET_CAPABILITY_IMS, NetworkCapabilities.NET_CAPABILITY_INTERNET
-    };
+    private static final String GATEWAY_CONNECTION_NAME = "gatewayConnectionName";
     private static final Executor INLINE_EXECUTOR = Runnable::run;
 
     private IVcnManagementService mMockVcnManagementService;
@@ -207,13 +205,13 @@
         verify(mMockStatusCallback).onStatusChanged(VCN_STATUS_CODE_ACTIVE);
 
         cbBinder.onGatewayConnectionError(
-                UNDERLYING_NETWORK_CAPABILITIES,
+                GATEWAY_CONNECTION_NAME,
                 VcnManager.VCN_ERROR_CODE_NETWORK_ERROR,
                 UnknownHostException.class.getName(),
                 "exception_message");
         verify(mMockStatusCallback)
                 .onGatewayConnectionError(
-                        eq(UNDERLYING_NETWORK_CAPABILITIES),
+                        eq(GATEWAY_CONNECTION_NAME),
                         eq(VcnManager.VCN_ERROR_CODE_NETWORK_ERROR),
                         any(UnknownHostException.class));
     }
diff --git a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
index c88b0c1..43e6676 100644
--- a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
+++ b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
@@ -16,9 +16,13 @@
 
 package com.android.server;
 
+import static android.net.ConnectivityManager.NetworkCallback;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED;
 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
 import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
+import static android.net.vcn.VcnManager.VCN_STATUS_CODE_ACTIVE;
+import static android.net.vcn.VcnManager.VCN_STATUS_CODE_SAFE_MODE;
 import static android.telephony.TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
 import static android.telephony.TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS;
 
@@ -53,8 +57,10 @@
 import android.content.Intent;
 import android.net.ConnectivityManager;
 import android.net.LinkProperties;
+import android.net.Network;
 import android.net.NetworkCapabilities;
 import android.net.NetworkCapabilities.Transport;
+import android.net.NetworkRequest;
 import android.net.TelephonyNetworkSpecifier;
 import android.net.vcn.IVcnStatusCallback;
 import android.net.vcn.IVcnUnderlyingNetworkPolicyListener;
@@ -256,6 +262,10 @@
 
         verify(mConnMgr).registerNetworkProvider(any(VcnNetworkProvider.class));
         verify(mSubscriptionTracker).register();
+        verify(mConnMgr)
+                .registerNetworkCallback(
+                        eq(new NetworkRequest.Builder().clearCapabilities().build()),
+                        any(NetworkCallback.class));
     }
 
     @Test
@@ -527,17 +537,6 @@
     }
 
     @Test
-    public void testSetVcnConfigInSafeModeNotifiesStatusCallback() throws Exception {
-        setupSubscriptionAndStartVcn(TEST_SUBSCRIPTION_ID, TEST_UUID_2, false /* isActive */);
-        mVcnMgmtSvc.registerVcnStatusCallback(TEST_UUID_2, mMockStatusCallback, TEST_PACKAGE_NAME);
-        verify(mMockStatusCallback).onVcnStatusChanged(VcnManager.VCN_STATUS_CODE_SAFE_MODE);
-
-        mVcnMgmtSvc.setVcnConfig(TEST_UUID_2, TEST_VCN_CONFIG, TEST_PACKAGE_NAME);
-
-        verify(mMockStatusCallback).onVcnStatusChanged(VcnManager.VCN_STATUS_CODE_ACTIVE);
-    }
-
-    @Test
     public void testClearVcnConfigRequiresNonSystemServer() throws Exception {
         doReturn(Process.SYSTEM_UID).when(mMockDeps).getBinderCallingUid();
 
@@ -695,17 +694,17 @@
                 hasCarrierPrivileges);
 
         final Vcn vcn = startAndGetVcnInstance(subGrp);
-        doReturn(isVcnActive).when(vcn).isActive();
+        doReturn(isVcnActive ? VCN_STATUS_CODE_ACTIVE : VCN_STATUS_CODE_SAFE_MODE)
+                .when(vcn)
+                .getStatus();
 
         doReturn(true)
                 .when(mLocationPermissionChecker)
                 .checkLocationPermission(eq(TEST_PACKAGE_NAME), any(), eq(TEST_UID), any());
     }
 
-    private VcnUnderlyingNetworkPolicy startVcnAndGetPolicyForTransport(
-            int subId, ParcelUuid subGrp, boolean isVcnActive, int transport) {
-        setupSubscriptionAndStartVcn(subId, subGrp, isVcnActive);
-
+    private NetworkCapabilities.Builder getNetworkCapabilitiesBuilderForTransport(
+            int subId, int transport) {
         final NetworkCapabilities.Builder ncBuilder =
                 new NetworkCapabilities.Builder()
                         .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
@@ -714,7 +713,16 @@
             ncBuilder.setSubIds(Collections.singleton(subId));
         }
 
-        return mVcnMgmtSvc.getUnderlyingNetworkPolicy(ncBuilder.build(), new LinkProperties());
+        return ncBuilder;
+    }
+
+    private VcnUnderlyingNetworkPolicy startVcnAndGetPolicyForTransport(
+            int subId, ParcelUuid subGrp, boolean isVcnActive, int transport) {
+        setupSubscriptionAndStartVcn(subId, subGrp, isVcnActive);
+
+        return mVcnMgmtSvc.getUnderlyingNetworkPolicy(
+                getNetworkCapabilitiesBuilderForTransport(subId, transport).build(),
+                new LinkProperties());
     }
 
     @Test
@@ -776,6 +784,53 @@
                 true /* isRestricted */);
     }
 
+    private void setupTrackedCarrierWifiNetwork(NetworkCapabilities caps) {
+        mVcnMgmtSvc.systemReady();
+
+        final ArgumentCaptor<NetworkCallback> captor =
+                ArgumentCaptor.forClass(NetworkCallback.class);
+        verify(mConnMgr)
+                .registerNetworkCallback(
+                        eq(new NetworkRequest.Builder().clearCapabilities().build()),
+                        captor.capture());
+        captor.getValue().onCapabilitiesChanged(new Network(0), caps);
+    }
+
+    @Test
+    public void testGetUnderlyingNetworkPolicyVcnWifi_unrestrictingExistingNetworkRequiresRestart()
+            throws Exception {
+        final NetworkCapabilities existingNetworkCaps =
+                getNetworkCapabilitiesBuilderForTransport(TEST_SUBSCRIPTION_ID, TRANSPORT_WIFI)
+                        .removeCapability(NET_CAPABILITY_NOT_RESTRICTED)
+                        .build();
+        setupTrackedCarrierWifiNetwork(existingNetworkCaps);
+
+        // Trigger test without VCN instance alive; expect restart due to change of NOT_RESTRICTED
+        // immutable capability
+        final VcnUnderlyingNetworkPolicy policy =
+                mVcnMgmtSvc.getUnderlyingNetworkPolicy(
+                        getNetworkCapabilitiesBuilderForTransport(
+                                        TEST_SUBSCRIPTION_ID, TRANSPORT_WIFI)
+                                .build(),
+                        new LinkProperties());
+        assertTrue(policy.isTeardownRequested());
+    }
+
+    @Test
+    public void testGetUnderlyingNetworkPolicyVcnWifi_restrictingExistingNetworkRequiresRestart()
+            throws Exception {
+        final NetworkCapabilities existingNetworkCaps =
+                getNetworkCapabilitiesBuilderForTransport(TEST_SUBSCRIPTION_ID, TRANSPORT_WIFI)
+                        .build();
+        setupTrackedCarrierWifiNetwork(existingNetworkCaps);
+
+        final VcnUnderlyingNetworkPolicy policy =
+                startVcnAndGetPolicyForTransport(
+                        TEST_SUBSCRIPTION_ID, TEST_UUID_2, false /* isActive */, TRANSPORT_WIFI);
+
+        assertTrue(policy.isTeardownRequested());
+    }
+
     @Test
     public void testGetUnderlyingNetworkPolicyNonVcnNetwork() throws Exception {
         setupSubscriptionAndStartVcn(TEST_SUBSCRIPTION_ID, TEST_UUID_1, true /* isActive */);
@@ -836,7 +891,9 @@
     }
 
     private void triggerVcnSafeMode(
-            @NonNull ParcelUuid subGroup, @NonNull TelephonySubscriptionSnapshot snapshot)
+            @NonNull ParcelUuid subGroup,
+            @NonNull TelephonySubscriptionSnapshot snapshot,
+            boolean isInSafeMode)
             throws Exception {
         verify(mMockDeps)
                 .newVcn(
@@ -847,22 +904,32 @@
                         mVcnCallbackCaptor.capture());
 
         VcnCallback vcnCallback = mVcnCallbackCaptor.getValue();
-        vcnCallback.onEnteredSafeMode();
+        vcnCallback.onSafeModeStatusChanged(isInSafeMode);
     }
 
-    @Test
-    public void testVcnEnteringSafeModeNotifiesPolicyListeners() throws Exception {
+    private void verifyVcnSafeModeChangesNotifiesPolicyListeners(boolean enterSafeMode)
+            throws Exception {
         TelephonySubscriptionSnapshot snapshot =
                 triggerSubscriptionTrackerCbAndGetSnapshot(Collections.singleton(TEST_UUID_1));
 
         mVcnMgmtSvc.addVcnUnderlyingNetworkPolicyListener(mMockPolicyListener);
 
-        triggerVcnSafeMode(TEST_UUID_1, snapshot);
+        triggerVcnSafeMode(TEST_UUID_1, snapshot, enterSafeMode);
 
         verify(mMockPolicyListener).onPolicyChanged();
     }
 
-    private void triggerVcnStatusCallbackOnEnteredSafeMode(
+    @Test
+    public void testVcnEnteringSafeModeNotifiesPolicyListeners() throws Exception {
+        verifyVcnSafeModeChangesNotifiesPolicyListeners(true /* enterSafeMode */);
+    }
+
+    @Test
+    public void testVcnExitingSafeModeNotifiesPolicyListeners() throws Exception {
+        verifyVcnSafeModeChangesNotifiesPolicyListeners(false /* enterSafeMode */);
+    }
+
+    private void triggerVcnStatusCallbackOnSafeModeStatusChanged(
             @NonNull ParcelUuid subGroup,
             @NonNull String pkgName,
             int uid,
@@ -885,12 +952,13 @@
 
         mVcnMgmtSvc.registerVcnStatusCallback(subGroup, mMockStatusCallback, pkgName);
 
-        triggerVcnSafeMode(subGroup, snapshot);
+        triggerVcnSafeMode(subGroup, snapshot, true /* enterSafeMode */);
     }
 
     @Test
-    public void testVcnStatusCallbackOnEnteredSafeModeWithCarrierPrivileges() throws Exception {
-        triggerVcnStatusCallbackOnEnteredSafeMode(
+    public void testVcnStatusCallbackOnSafeModeStatusChangedWithCarrierPrivileges()
+            throws Exception {
+        triggerVcnStatusCallbackOnSafeModeStatusChanged(
                 TEST_UUID_1,
                 TEST_PACKAGE_NAME,
                 TEST_UID,
@@ -901,8 +969,9 @@
     }
 
     @Test
-    public void testVcnStatusCallbackOnEnteredSafeModeWithoutCarrierPrivileges() throws Exception {
-        triggerVcnStatusCallbackOnEnteredSafeMode(
+    public void testVcnStatusCallbackOnSafeModeStatusChangedWithoutCarrierPrivileges()
+            throws Exception {
+        triggerVcnStatusCallbackOnSafeModeStatusChanged(
                 TEST_UUID_1,
                 TEST_PACKAGE_NAME,
                 TEST_UID,
@@ -914,8 +983,9 @@
     }
 
     @Test
-    public void testVcnStatusCallbackOnEnteredSafeModeWithoutLocationPermission() throws Exception {
-        triggerVcnStatusCallbackOnEnteredSafeMode(
+    public void testVcnStatusCallbackOnSafeModeStatusChangedWithoutLocationPermission()
+            throws Exception {
+        triggerVcnStatusCallbackOnSafeModeStatusChanged(
                 TEST_UUID_1,
                 TEST_PACKAGE_NAME,
                 TEST_UID,
diff --git a/tests/vcn/java/com/android/server/vcn/UnderlyingNetworkTrackerTest.java b/tests/vcn/java/com/android/server/vcn/UnderlyingNetworkTrackerTest.java
index ed2e4d9..b592000 100644
--- a/tests/vcn/java/com/android/server/vcn/UnderlyingNetworkTrackerTest.java
+++ b/tests/vcn/java/com/android/server/vcn/UnderlyingNetworkTrackerTest.java
@@ -158,7 +158,7 @@
         for (final int subId : expectedSubIds) {
             verify(mConnectivityManager)
                     .requestBackgroundNetwork(
-                            eq(getCellRequestForSubId(subId, expectedSubIds)),
+                            eq(getCellRequestForSubId(subId)),
                             any(),
                             any(NetworkBringupCallback.class));
         }
@@ -189,30 +189,30 @@
     }
 
     private NetworkRequest getWifiRequest(Set<Integer> netCapsSubIds) {
-        return getExpectedRequestBase(netCapsSubIds)
+        return getExpectedRequestBase()
                 .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
+                .setSubIds(netCapsSubIds)
                 .build();
     }
 
-    private NetworkRequest getCellRequestForSubId(int subId, Set<Integer> netCapsSubIds) {
-        return getExpectedRequestBase(netCapsSubIds)
+    private NetworkRequest getCellRequestForSubId(int subId) {
+        return getExpectedRequestBase()
                 .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
                 .setNetworkSpecifier(new TelephonyNetworkSpecifier(subId))
                 .build();
     }
 
     private NetworkRequest getRouteSelectionRequest(Set<Integer> netCapsSubIds) {
-        return getExpectedRequestBase(netCapsSubIds).build();
+        return getExpectedRequestBase().setSubIds(netCapsSubIds).build();
     }
 
-    private NetworkRequest.Builder getExpectedRequestBase(Set<Integer> subIds) {
+    private NetworkRequest.Builder getExpectedRequestBase() {
         final NetworkRequest.Builder builder =
                 new NetworkRequest.Builder()
                         .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
                         .removeCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED)
                         .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
-                        .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED)
-                        .setSubIds(subIds);
+                        .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED);
 
         return builder;
     }
diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java
index ca6448c..34c0018 100644
--- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java
+++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java
@@ -32,6 +32,7 @@
 import static org.junit.Assert.assertTrue;
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.argThat;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
@@ -40,6 +41,8 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
 
+import android.net.ConnectivityManager;
+import android.net.LinkAddress;
 import android.net.LinkProperties;
 import android.net.NetworkAgent;
 import android.net.NetworkCapabilities;
@@ -58,19 +61,29 @@
 import org.mockito.ArgumentCaptor;
 
 import java.io.IOException;
+import java.net.InetAddress;
 import java.net.UnknownHostException;
+import java.util.Arrays;
 import java.util.Collections;
+import java.util.List;
+import java.util.function.Consumer;
 
 /** Tests for VcnGatewayConnection.ConnectedState */
 @RunWith(AndroidJUnit4.class)
 @SmallTest
 public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnectionTestBase {
     private VcnIkeSession mIkeSession;
+    private NetworkAgent mNetworkAgent;
 
     @Before
     public void setUp() throws Exception {
         super.setUp();
 
+        mNetworkAgent = mock(NetworkAgent.class);
+        doReturn(mNetworkAgent)
+                .when(mDeps)
+                .newNetworkAgent(any(), any(), any(), any(), anyInt(), any(), any(), any(), any());
+
         mGatewayConnection.setUnderlyingNetwork(TEST_UNDERLYING_NETWORK_RECORD_1);
 
         mIkeSession = mGatewayConnection.buildIkeSession(TEST_UNDERLYING_NETWORK_RECORD_1.network);
@@ -159,21 +172,44 @@
         assertEquals(mGatewayConnection.mConnectedState, mGatewayConnection.getCurrentState());
     }
 
-    @Test
-    public void testChildOpenedRegistersNetwork() throws Exception {
-        // Verify scheduled but not canceled when entering ConnectedState
-        verifySafeModeTimeoutAlarmAndGetCallback(false /* expectCanceled */);
+    private void triggerChildOpened() {
+        triggerChildOpened(Collections.singletonList(TEST_INTERNAL_ADDR), TEST_DNS_ADDR);
+    }
 
+    private void triggerChildOpened(List<LinkAddress> internalAddresses, InetAddress dnsAddress) {
         final VcnChildSessionConfiguration mMockChildSessionConfig =
                 mock(VcnChildSessionConfiguration.class);
-        doReturn(Collections.singletonList(TEST_INTERNAL_ADDR))
-                .when(mMockChildSessionConfig)
-                .getInternalAddresses();
-        doReturn(Collections.singletonList(TEST_DNS_ADDR))
+        doReturn(internalAddresses).when(mMockChildSessionConfig).getInternalAddresses();
+        doReturn(Collections.singletonList(dnsAddress))
                 .when(mMockChildSessionConfig)
                 .getInternalDnsServers();
 
         getChildSessionCallback().onOpened(mMockChildSessionConfig);
+    }
+
+    private void triggerValidation(int status) {
+        final ArgumentCaptor<Consumer<Integer>> validationCallbackCaptor =
+                ArgumentCaptor.forClass(Consumer.class);
+        verify(mDeps)
+                .newNetworkAgent(
+                        any(),
+                        any(),
+                        any(),
+                        any(),
+                        anyInt(),
+                        any(),
+                        any(),
+                        any(),
+                        validationCallbackCaptor.capture());
+
+        validationCallbackCaptor.getValue().accept(status);
+    }
+
+    @Test
+    public void testChildOpenedRegistersNetwork() throws Exception {
+        // Verify scheduled but not canceled when entering ConnectedState
+        verifySafeModeTimeoutAlarmAndGetCallback(false /* expectCanceled */);
+        triggerChildOpened();
         mTestLooper.dispatchAll();
 
         assertEquals(mGatewayConnection.mConnectedState, mGatewayConnection.getCurrentState());
@@ -182,15 +218,20 @@
                 ArgumentCaptor.forClass(LinkProperties.class);
         final ArgumentCaptor<NetworkCapabilities> ncCaptor =
                 ArgumentCaptor.forClass(NetworkCapabilities.class);
-        verify(mConnMgr)
-                .registerNetworkAgent(
-                        any(),
-                        any(),
-                        lpCaptor.capture(),
+        verify(mDeps)
+                .newNetworkAgent(
+                        eq(mVcnContext),
+                        any(String.class),
                         ncCaptor.capture(),
+                        lpCaptor.capture(),
+                        anyInt(),
+                        argThat(nac -> nac.getLegacyType() == ConnectivityManager.TYPE_MOBILE),
                         any(),
                         any(),
-                        anyInt());
+                        any());
+        verify(mNetworkAgent).register();
+        verify(mNetworkAgent).markConnected();
+
         verify(mIpSecSvc)
                 .addAddressToTunnelInterface(
                         eq(TEST_IPSEC_TUNNEL_RESOURCE_ID), eq(TEST_INTERNAL_ADDR), any());
@@ -208,9 +249,78 @@
 
         // Now that Vcn Network is up, notify it as validated and verify the SafeMode alarm is
         // canceled
-        mGatewayConnection.mNetworkAgent.onValidationStatus(
-                NetworkAgent.VALIDATION_STATUS_VALID, null /* redirectUri */);
+        triggerValidation(NetworkAgent.VALIDATION_STATUS_VALID);
         verify(mSafeModeTimeoutAlarm).cancel();
+        assertFalse(mGatewayConnection.isInSafeMode());
+    }
+
+    @Test
+    public void testInternalAndDnsAddressesChanged() throws Exception {
+        final List<LinkAddress> startingInternalAddrs =
+                Arrays.asList(new LinkAddress[] {TEST_INTERNAL_ADDR, TEST_INTERNAL_ADDR_2});
+        triggerChildOpened(startingInternalAddrs, TEST_DNS_ADDR);
+        mTestLooper.dispatchAll();
+
+        for (LinkAddress addr : startingInternalAddrs) {
+            verify(mIpSecSvc)
+                    .addAddressToTunnelInterface(
+                            eq(TEST_IPSEC_TUNNEL_RESOURCE_ID), eq(addr), any());
+        }
+
+        verify(mDeps)
+                .newNetworkAgent(
+                        any(),
+                        any(),
+                        any(),
+                        argThat(
+                                lp ->
+                                        startingInternalAddrs.equals(lp.getLinkAddresses())
+                                                && Collections.singletonList(TEST_DNS_ADDR)
+                                                        .equals(lp.getDnsServers())),
+                        anyInt(),
+                        any(),
+                        any(),
+                        any(),
+                        any());
+
+        // Trigger another connection event, and verify that the addresses change
+        final List<LinkAddress> newInternalAddrs =
+                Arrays.asList(new LinkAddress[] {TEST_INTERNAL_ADDR_2, TEST_INTERNAL_ADDR_3});
+        triggerChildOpened(newInternalAddrs, TEST_DNS_ADDR_2);
+        mTestLooper.dispatchAll();
+
+        // Verify addresses on tunnel network added/removed
+        for (LinkAddress addr : newInternalAddrs) {
+            verify(mIpSecSvc)
+                    .addAddressToTunnelInterface(
+                            eq(TEST_IPSEC_TUNNEL_RESOURCE_ID), eq(addr), any());
+        }
+        verify(mIpSecSvc)
+                .removeAddressFromTunnelInterface(
+                        eq(TEST_IPSEC_TUNNEL_RESOURCE_ID), eq(TEST_INTERNAL_ADDR), any());
+
+        // TODO(b/184579891): Also verify link properties updated and sent when sendLinkProperties
+        // is mockable
+
+        // Verify that IpSecTunnelInterface only created once
+        verify(mIpSecSvc).createTunnelInterface(any(), any(), any(), any(), any());
+        verifyNoMoreInteractions(mIpSecSvc);
+    }
+
+    @Test
+    public void testSuccessfulConnectionExitsSafeMode() throws Exception {
+        verifySafeModeTimeoutNotifiesCallbackAndUnregistersNetworkAgent(
+                mGatewayConnection.mConnectedState);
+
+        assertTrue(mGatewayConnection.isInSafeMode());
+        assertFalse(mGatewayConnection.isQuitting());
+
+        triggerChildOpened();
+        mTestLooper.dispatchAll();
+
+        triggerValidation(NetworkAgent.VALIDATION_STATUS_VALID);
+
+        assertFalse(mGatewayConnection.isInSafeMode());
     }
 
     @Test
@@ -241,7 +351,7 @@
 
         verify(mGatewayStatusCallback)
                 .onGatewayConnectionError(
-                        eq(mConfig.getExposedCapabilities()),
+                        eq(mConfig.getGatewayConnectionName()),
                         eq(VCN_ERROR_CODE_INTERNAL_ERROR),
                         any(),
                         any());
@@ -275,7 +385,10 @@
 
         verify(mGatewayStatusCallback)
                 .onGatewayConnectionError(
-                        eq(mConfig.getExposedCapabilities()), eq(expectedErrorType), any(), any());
+                        eq(mConfig.getGatewayConnectionName()),
+                        eq(expectedErrorType),
+                        any(),
+                        any());
     }
 
     @Test
diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectingStateTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectingStateTest.java
index 7afa449..bfe8c73 100644
--- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectingStateTest.java
+++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectingStateTest.java
@@ -118,8 +118,9 @@
     }
 
     @Test
-    public void testSafeModeTimeoutNotifiesCallback() {
-        verifySafeModeTimeoutNotifiesCallback(mGatewayConnection.mConnectingState);
+    public void testSafeModeTimeoutNotifiesCallbackAndUnregistersNetworkAgent() {
+        verifySafeModeTimeoutNotifiesCallbackAndUnregistersNetworkAgent(
+                mGatewayConnection.mConnectingState);
     }
 
     @Test
diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionDisconnectingStateTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionDisconnectingStateTest.java
index 99feffd..9da8b45 100644
--- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionDisconnectingStateTest.java
+++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionDisconnectingStateTest.java
@@ -86,8 +86,9 @@
     }
 
     @Test
-    public void testSafeModeTimeoutNotifiesCallback() {
-        verifySafeModeTimeoutNotifiesCallback(mGatewayConnection.mDisconnectingState);
+    public void testSafeModeTimeoutNotifiesCallbackAndUnregistersNetworkAgent() {
+        verifySafeModeTimeoutNotifiesCallbackAndUnregistersNetworkAgent(
+                mGatewayConnection.mDisconnectingState);
     }
 
     @Test
diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionRetryTimeoutStateTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionRetryTimeoutStateTest.java
index 85a0277..6dbf7d5 100644
--- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionRetryTimeoutStateTest.java
+++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionRetryTimeoutStateTest.java
@@ -96,8 +96,9 @@
     }
 
     @Test
-    public void testSafeModeTimeoutNotifiesCallback() {
-        verifySafeModeTimeoutNotifiesCallback(mGatewayConnection.mRetryTimeoutState);
+    public void testSafeModeTimeoutNotifiesCallbackAndUnregistersNetworkAgent() {
+        verifySafeModeTimeoutNotifiesCallbackAndUnregistersNetworkAgent(
+                mGatewayConnection.mRetryTimeoutState);
     }
 
     @Test
diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java
index a660735..c5ed8f6 100644
--- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java
+++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java
@@ -21,6 +21,8 @@
 import static com.android.server.vcn.VcnTestUtils.setupIpSecManager;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.atLeastOnce;
@@ -42,6 +44,7 @@
 import android.net.LinkAddress;
 import android.net.LinkProperties;
 import android.net.Network;
+import android.net.NetworkAgent;
 import android.net.NetworkCapabilities;
 import android.net.ipsec.ike.ChildSessionCallback;
 import android.net.ipsec.ike.IkeSessionCallback;
@@ -71,8 +74,14 @@
     protected static final ParcelUuid TEST_SUB_GRP = new ParcelUuid(UUID.randomUUID());
     protected static final InetAddress TEST_DNS_ADDR =
             InetAddresses.parseNumericAddress("2001:DB8:0:1::");
+    protected static final InetAddress TEST_DNS_ADDR_2 =
+            InetAddresses.parseNumericAddress("2001:DB8:0:2::");
     protected static final LinkAddress TEST_INTERNAL_ADDR =
-            new LinkAddress(InetAddresses.parseNumericAddress("2001:DB8:0:2::"), 64);
+            new LinkAddress(InetAddresses.parseNumericAddress("2001:DB8:1:1::"), 64);
+    protected static final LinkAddress TEST_INTERNAL_ADDR_2 =
+            new LinkAddress(InetAddresses.parseNumericAddress("2001:DB8:1:2::"), 64);
+    protected static final LinkAddress TEST_INTERNAL_ADDR_3 =
+            new LinkAddress(InetAddresses.parseNumericAddress("2001:DB8:1:3::"), 64);
 
     protected static final int TEST_IPSEC_SPI_VALUE = 0x1234;
     protected static final int TEST_IPSEC_SPI_RESOURCE_ID = 1;
@@ -267,7 +276,12 @@
                 expectCanceled);
     }
 
-    protected void verifySafeModeTimeoutNotifiesCallback(@NonNull State expectedState) {
+    protected void verifySafeModeTimeoutNotifiesCallbackAndUnregistersNetworkAgent(
+            @NonNull State expectedState) {
+        // Set a NetworkAgent, and expect it to be unregistered and cleared
+        final NetworkAgent mockNetworkAgent = mock(NetworkAgent.class);
+        mGatewayConnection.setNetworkAgent(mockNetworkAgent);
+
         // SafeMode timer starts when VcnGatewayConnection exits DisconnectedState (the initial
         // state)
         final Runnable delayedEvent =
@@ -275,7 +289,11 @@
         delayedEvent.run();
         mTestLooper.dispatchAll();
 
-        verify(mGatewayStatusCallback).onEnteredSafeMode();
+        verify(mGatewayStatusCallback).onSafeModeStatusChanged();
         assertEquals(expectedState, mGatewayConnection.getCurrentState());
+        assertTrue(mGatewayConnection.isInSafeMode());
+
+        verify(mockNetworkAgent).unregister();
+        assertNull(mGatewayConnection.getNetworkAgent());
     }
 }
diff --git a/tests/vcn/java/com/android/server/vcn/VcnTest.java b/tests/vcn/java/com/android/server/vcn/VcnTest.java
index c853fc5..90eb75e 100644
--- a/tests/vcn/java/com/android/server/vcn/VcnTest.java
+++ b/tests/vcn/java/com/android/server/vcn/VcnTest.java
@@ -19,12 +19,13 @@
 import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_MMS;
+import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+import static android.net.vcn.VcnManager.VCN_STATUS_CODE_ACTIVE;
+import static android.net.vcn.VcnManager.VCN_STATUS_CODE_SAFE_MODE;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
 import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.argThat;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.doReturn;
@@ -51,7 +52,8 @@
 import org.junit.Test;
 import org.mockito.ArgumentCaptor;
 
-import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Set;
 import java.util.UUID;
 
@@ -132,6 +134,7 @@
     private void startVcnGatewayWithCapabilities(
             NetworkRequestListener requestListener, int... netCapabilities) {
         final NetworkRequest.Builder requestBuilder = new NetworkRequest.Builder();
+        requestBuilder.addTransportType(TRANSPORT_CELLULAR);
         for (final int netCapability : netCapabilities) {
             requestBuilder.addCapability(netCapability);
         }
@@ -140,7 +143,7 @@
         mTestLooper.dispatchAll();
     }
 
-    private void verifyUpdateSubscriptionSnapshotNotifiesConnectionGateways(boolean isActive) {
+    private void verifyUpdateSubscriptionSnapshotNotifiesGatewayConnections(int status) {
         final NetworkRequestListener requestListener = verifyAndGetRequestListener();
         startVcnGatewayWithCapabilities(requestListener, TEST_CAPS[0]);
 
@@ -150,25 +153,24 @@
         final TelephonySubscriptionSnapshot updatedSnapshot =
                 mock(TelephonySubscriptionSnapshot.class);
 
-        mVcn.setIsActive(isActive);
+        mVcn.setStatus(status);
 
         mVcn.updateSubscriptionSnapshot(updatedSnapshot);
         mTestLooper.dispatchAll();
 
         for (final VcnGatewayConnection gateway : gatewayConnections) {
-            verify(gateway, isActive ? times(1) : never())
-                    .updateSubscriptionSnapshot(eq(updatedSnapshot));
+            verify(gateway).updateSubscriptionSnapshot(eq(updatedSnapshot));
         }
     }
 
     @Test
     public void testSubscriptionSnapshotUpdatesVcnGatewayConnections() {
-        verifyUpdateSubscriptionSnapshotNotifiesConnectionGateways(true /* isActive */);
+        verifyUpdateSubscriptionSnapshotNotifiesGatewayConnections(VCN_STATUS_CODE_ACTIVE);
     }
 
     @Test
-    public void testSubscriptionSnapshotUpdatesVcnGatewayConnectionsWhileInactive() {
-        verifyUpdateSubscriptionSnapshotNotifiesConnectionGateways(false /* isActive */);
+    public void testSubscriptionSnapshotUpdatesVcnGatewayConnectionsInSafeMode() {
+        verifyUpdateSubscriptionSnapshotNotifiesGatewayConnections(VCN_STATUS_CODE_SAFE_MODE);
     }
 
     private void triggerVcnRequestListeners(NetworkRequestListener requestListener) {
@@ -198,32 +200,53 @@
 
     private void verifySafeMode(
             NetworkRequestListener requestListener,
-            Set<VcnGatewayConnection> expectedGatewaysTornDown) {
-        assertFalse(mVcn.isActive());
-        for (final VcnGatewayConnection gatewayConnection : expectedGatewaysTornDown) {
-            verify(gatewayConnection).teardownAsynchronously();
+            Set<VcnGatewayConnection> activeGateways,
+            boolean expectInSafeMode) {
+        for (VcnGatewayConnection gatewayConnection : activeGateways) {
+            verify(gatewayConnection, never()).teardownAsynchronously();
         }
-        verify(mVcnNetworkProvider).unregisterListener(requestListener);
-        verify(mVcnCallback).onEnteredSafeMode();
+
+        assertEquals(
+                expectInSafeMode ? VCN_STATUS_CODE_SAFE_MODE : VCN_STATUS_CODE_ACTIVE,
+                mVcn.getStatus());
+        verify(mVcnCallback).onSafeModeStatusChanged(expectInSafeMode);
     }
 
     @Test
-    public void testGatewayEnteringSafeModeNotifiesVcn() {
+    public void testGatewayEnteringAndExitingSafeModeNotifiesVcn() {
         final NetworkRequestListener requestListener = verifyAndGetRequestListener();
         final Set<VcnGatewayConnection> gatewayConnections =
                 startGatewaysAndGetGatewayConnections(requestListener);
 
-        // Doesn't matter which callback this gets - any Gateway entering Safemode should shut down
-        // all Gateways
+        // Doesn't matter which callback this gets, or which VCN is in safe mode - any Gateway
+        // entering Safemode should trigger safe mode
         final VcnGatewayStatusCallback statusCallback = mGatewayStatusCallbackCaptor.getValue();
-        statusCallback.onEnteredSafeMode();
+        final VcnGatewayConnection gatewayConnection = gatewayConnections.iterator().next();
+
+        doReturn(true).when(gatewayConnection).isInSafeMode();
+        statusCallback.onSafeModeStatusChanged();
         mTestLooper.dispatchAll();
 
-        verifySafeMode(requestListener, gatewayConnections);
+        verifySafeMode(requestListener, gatewayConnections, true /* expectInSafeMode */);
+
+        // Verify that when all GatewayConnections exit safe mode, the VCN also exits safe mode
+        doReturn(false).when(gatewayConnection).isInSafeMode();
+        statusCallback.onSafeModeStatusChanged();
+        mTestLooper.dispatchAll();
+
+        verifySafeMode(requestListener, gatewayConnections, false /* expectInSafeMode */);
+
+        // Re-trigger, verify safe mode callback does not get fired again for identical state
+        statusCallback.onSafeModeStatusChanged();
+        mTestLooper.dispatchAll();
+
+        // Expect only once still; from above.
+        verify(mVcnCallback).onSafeModeStatusChanged(false);
     }
 
-    @Test
-    public void testGatewayQuit() {
+    private void verifyGatewayQuit(int status) {
+        mVcn.setStatus(status);
+
         final NetworkRequestListener requestListener = verifyAndGetRequestListener();
         final Set<VcnGatewayConnection> gatewayConnections =
                 new ArraySet<>(startGatewaysAndGetGatewayConnections(requestListener));
@@ -236,7 +259,7 @@
         assertEquals(1, mVcn.getVcnGatewayConnections().size());
         verify(mVcnNetworkProvider).resendAllRequests(requestListener);
 
-        // Verify that the VcnGatewayConnection is restarted
+        // Verify that the VcnGatewayConnection is restarted if a request exists for it
         triggerVcnRequestListeners(requestListener);
         mTestLooper.dispatchAll();
         assertEquals(2, mVcn.getVcnGatewayConnections().size());
@@ -250,21 +273,13 @@
     }
 
     @Test
-    public void testGatewayQuitWhileInactive() {
-        final NetworkRequestListener requestListener = verifyAndGetRequestListener();
-        final Set<VcnGatewayConnection> gatewayConnections =
-                new ArraySet<>(startGatewaysAndGetGatewayConnections(requestListener));
+    public void testGatewayQuitReevaluatesRequests() {
+        verifyGatewayQuit(VCN_STATUS_CODE_ACTIVE);
+    }
 
-        mVcn.teardownAsynchronously();
-        mTestLooper.dispatchAll();
-
-        final VcnGatewayStatusCallback statusCallback = mGatewayStatusCallbackCaptor.getValue();
-        statusCallback.onQuit();
-        mTestLooper.dispatchAll();
-
-        // Verify that the VCN requests the networkRequests be resent
-        assertEquals(1, mVcn.getVcnGatewayConnections().size());
-        verify(mVcnNetworkProvider, never()).resendAllRequests(requestListener);
+    @Test
+    public void testGatewayQuitReevaluatesRequestsInSafeMode() {
+        verifyGatewayQuit(VCN_STATUS_CODE_SAFE_MODE);
     }
 
     @Test
@@ -274,11 +289,12 @@
         assertEquals(2, mVcn.getVcnGatewayConnectionConfigMap().size());
 
         // Create VcnConfig with only one VcnGatewayConnectionConfig so a gateway connection is torn
-        // down
-        final VcnGatewayConnectionConfig activeConfig =
-                VcnGatewayConnectionConfigTest.buildTestConfigWithExposedCaps(TEST_CAPS[0]);
-        final VcnGatewayConnectionConfig removedConfig =
-                VcnGatewayConnectionConfigTest.buildTestConfigWithExposedCaps(TEST_CAPS[1]);
+        // down. Reuse existing VcnGatewayConnectionConfig so that the gateway connection name
+        // matches.
+        final List<VcnGatewayConnectionConfig> currentConfigs =
+                new ArrayList<>(mVcn.getVcnGatewayConnectionConfigMap().keySet());
+        final VcnGatewayConnectionConfig activeConfig = currentConfigs.get(0);
+        final VcnGatewayConnectionConfig removedConfig = currentConfigs.get(1);
         final VcnConfig updatedConfig =
                 new VcnConfig.Builder(mContext).addGatewayConnectionConfig(activeConfig).build();
 
@@ -293,49 +309,4 @@
         verify(removedGatewayConnection).teardownAsynchronously();
         verify(mVcnNetworkProvider).resendAllRequests(requestListener);
     }
-
-    @Test
-    public void testUpdateConfigExitsSafeMode() {
-        final NetworkRequestListener requestListener = verifyAndGetRequestListener();
-        final Set<VcnGatewayConnection> gatewayConnections =
-                new ArraySet<>(startGatewaysAndGetGatewayConnections(requestListener));
-
-        final VcnGatewayStatusCallback statusCallback = mGatewayStatusCallbackCaptor.getValue();
-        statusCallback.onEnteredSafeMode();
-        mTestLooper.dispatchAll();
-        verifySafeMode(requestListener, gatewayConnections);
-
-        doAnswer(invocation -> {
-            final NetworkRequestListener listener = invocation.getArgument(0);
-            triggerVcnRequestListeners(listener);
-            return null;
-        }).when(mVcnNetworkProvider).registerListener(eq(requestListener));
-
-        mVcn.updateConfig(mConfig);
-        mTestLooper.dispatchAll();
-
-        // Registered on start, then re-registered with new configs
-        verify(mVcnNetworkProvider, times(2)).registerListener(eq(requestListener));
-        assertTrue(mVcn.isActive());
-        for (final int[] caps : TEST_CAPS) {
-            // Expect each gateway connection created only on initial startup
-            verify(mDeps)
-                    .newVcnGatewayConnection(
-                            eq(mVcnContext),
-                            eq(TEST_SUB_GROUP),
-                            eq(mSubscriptionSnapshot),
-                            argThat(config -> Arrays.equals(caps, config.getExposedCapabilities())),
-                            any());
-        }
-    }
-
-    @Test
-    public void testIgnoreNetworkRequestWhileInactive() {
-        mVcn.setIsActive(false /* isActive */);
-
-        final NetworkRequestListener requestListener = verifyAndGetRequestListener();
-        triggerVcnRequestListeners(requestListener);
-
-        verify(mDeps, never()).newVcnGatewayConnection(any(), any(), any(), any(), any());
-    }
 }
diff --git a/tools/hiddenapi/exclude.sh b/tools/hiddenapi/exclude.sh
index 18c4054..73eacc0 100755
--- a/tools/hiddenapi/exclude.sh
+++ b/tools/hiddenapi/exclude.sh
@@ -35,7 +35,7 @@
 PACKAGES=$(for t in $TEAMS; do echo $(eval echo \${${t}_PACKAGES}); done)
 RE=$(echo ${PACKAGES} | sed "s/ /|/g")
 git show --name-only --pretty=format: $1 | grep "config/hiddenapi-.*txt" | while read file; do
-    ENTRIES=$(grep -E "^L(${RE})/" <(git show $1:$file))
+    ENTRIES=$(grep -E "^L(${RE})/" || true <(git show $1:$file))
     if [[ -n "${ENTRIES}" ]]; then
       echo -e "\e[1m\e[31m$file $1 contains the following entries\e[0m"
       echo -e "\e[1m\e[31mfor packages that are handled using UnsupportedAppUsage. Please remove\e[0m"