Merge "Adding TEST_MAPPING to system/security/keystore"
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index 68df61f..9b96f36 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -4,7 +4,7 @@
 
 [Builtin Hooks Options]
 clang_format = --commit ${PREUPLOAD_COMMIT} --style file --extensions c,h,cc,cpp
-rustfmt = --check --config-path=rustfmt.toml ${PREUPLOAD_FILES}
+rustfmt = --config-path=rustfmt.toml
 
 [Hook Scripts]
 aosp_hook = ${REPO_ROOT}/frameworks/base/tools/aosp/aosp_sha.sh ${PREUPLOAD_COMMIT} "."
diff --git a/keystore/Android.bp b/keystore/Android.bp
index b881757..45b721b 100644
--- a/keystore/Android.bp
+++ b/keystore/Android.bp
@@ -34,8 +34,9 @@
         "blob.cpp",
         "confirmation_manager.cpp",
         "grant_store.cpp",
-        "key_config.proto",
-        "key_proto_handler.cpp",
+        "key_creation_log_handler.cpp",
+        "key_operation_log_handler.cpp",
+        "key_attestation_log_handler.cpp",
         "key_store_service.cpp",
         "keyblob_utils.cpp",
         "keymaster_enforcement.cpp",
@@ -44,8 +45,6 @@
         "keystore_utils.cpp",
         "legacy_keymaster_device_wrapper.cpp",
         "operation.cpp",
-        "operation_config.proto",
-        "operation_proto_handler.cpp",
         "permissions.cpp",
         "user_state.cpp",
     ],
@@ -74,6 +73,7 @@
         "libservices",
         "libsoftkeymasterdevice",
         "libutils",
+        "libstatslog",
     ],
     init_rc: ["keystore.rc"],
     aidl: {
diff --git a/keystore/KeyStore.h b/keystore/KeyStore.h
index 0027ec8..7841a80 100644
--- a/keystore/KeyStore.h
+++ b/keystore/KeyStore.h
@@ -62,9 +62,9 @@
 }  // namespace keystore
 
 namespace std {
-template <typename T, size_t count> struct tuple_size<keystore::Devices<T, count>> {
+template <typename T, size_t N> struct tuple_size<keystore::Devices<T, N>> {
   public:
-    static constexpr size_t value = std::tuple_size<std::array<T, count>>::value;
+    static constexpr size_t value = std::tuple_size<std::array<T, N>>::value;
 };
 }  // namespace std
 
diff --git a/keystore/include/keystore/keystore.h b/keystore/include/keystore/keystore.h
index 3aed8c2..f840eb7 100644
--- a/keystore/include/keystore/keystore.h
+++ b/keystore/include/keystore/keystore.h
@@ -45,6 +45,21 @@
     OP_AUTH_NEEDED = 15,  // Auth is needed for this operation before it can be used.
     KEY_ALREADY_EXISTS = 16,
     KEY_PERMANENTLY_INVALIDATED = 17,
+
+    /**
+     * Following three response codes are for logging purposes only.
+     * The operations are logged at the end of the life cycle of an operation handle,
+     * along with the reason for the end of the operation handle. For the operations
+     * that fail in update and finish, the reason for failure is available with
+     * the above response codes.
+     * For the operations that are aborted in three different ways, the reason
+     * for aborting is not available. The following enum values define the
+     * three ways an operation can get aborted.
+     */
+    ABORT_CALLED = 18,
+    PRUNED = 19,
+    BINDER_DIED = 20,
+
 };
 
 /*
diff --git a/keystore/key_proto_handler.h b/keystore/key_attestation_log_handler.cpp
similarity index 66%
copy from keystore/key_proto_handler.h
copy to keystore/key_attestation_log_handler.cpp
index a2f6a24..34c76a3 100644
--- a/keystore/key_proto_handler.h
+++ b/keystore/key_attestation_log_handler.cpp
@@ -13,17 +13,13 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
-#ifndef KEYSTORE_KEY_PROTO_HANDLER_H_
-#define KEYSTORE_KEY_PROTO_HANDLER_H_
-
-#include <keystore/keystore_hidl_support.h>
-
+#include <statslog.h>
 namespace keystore {
 
-void uploadKeyCharacteristicsAsProto(const hidl_vec<KeyParameter>& keyParams,
-                                     bool wasCreationSuccessful);
+void logKeystoreKeyAttestationEvent(bool wasSuccessful, int32_t errorCode) {
+    android::util::stats_write(android::util::KEYSTORE_KEY_EVENT_REPORTED,
+                               android::util::KEYSTORE_KEY_EVENT_REPORTED__TYPE__KEY_ATTESTATION,
+                               wasSuccessful, errorCode);
+}
 
-}  // namespace keystore
-
-#endif  // KEYSTORE_KEY_PROTO_HANDLER_H_
+}  // namespace keystore
\ No newline at end of file
diff --git a/keystore/key_proto_handler.h b/keystore/key_attestation_log_handler.h
similarity index 66%
copy from keystore/key_proto_handler.h
copy to keystore/key_attestation_log_handler.h
index a2f6a24..e69e667 100644
--- a/keystore/key_proto_handler.h
+++ b/keystore/key_attestation_log_handler.h
@@ -14,16 +14,13 @@
  * limitations under the License.
  */
 
-#ifndef KEYSTORE_KEY_PROTO_HANDLER_H_
-#define KEYSTORE_KEY_PROTO_HANDLER_H_
-
-#include <keystore/keystore_hidl_support.h>
+#ifndef _KEY_ATTESTATION_LOG_HANDLER_H_
+#define _KEY_ATTESTATION_LOG_HANDLER_H_
 
 namespace keystore {
 
-void uploadKeyCharacteristicsAsProto(const hidl_vec<KeyParameter>& keyParams,
-                                     bool wasCreationSuccessful);
+void logKeystoreKeyAttestationEvent(bool wasSuccessful, int32_t errorCode);
 
-}  // namespace keystore
+}
 
-#endif  // KEYSTORE_KEY_PROTO_HANDLER_H_
+#endif  //_KEY_ATTESTATION_LOG_HANDLER_H_
\ No newline at end of file
diff --git a/keystore/key_config.proto b/keystore/key_config.proto
deleted file mode 100644
index 0b1a398..0000000
--- a/keystore/key_config.proto
+++ /dev/null
@@ -1,62 +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.
- */
-
-syntax = "proto2";
-
-package keystore;
-
-option optimize_for = LITE_RUNTIME;
-
-message KeyConfig {
-  // What type of encryption algorithm is this key being generated/imported for
-  // e.g. AES, RSA, etc
-  optional string algorithm = 1;
-
-  // Size of the key being generated/imported
-  optional int32 key_size = 2;
-
-  // Log whether the key was generated, imported, securely imported, or derived.
-  optional string origin = 3;
-
-  // What auth types does this key require? If none, then no auth required.
-  optional string user_auth_type = 4;
-
-  // If user authentication is required, is the requirement time based? If it
-  // is not time based then this field will not be used and the key is per
-  // operation. Per operation keys must be user authenticated on each usage.
-  optional int32 user_auth_key_timeout = 5;
-
-  // Track which padding modes this key supports.
-  repeated string padding = 6;
-
-  // Track which digests this key supports
-  repeated string digest = 7;
-
-  // Check what block mode is being used depending on the mode of encryption
-  repeated string block_mode = 8;
-
-  // Was the key generated/imported successfully?
-  optional bool was_creation_successful = 9;
-
-  // What purposes can this key be used for?
-  repeated string purpose = 10;
-
-  // Which ec curve was selected if elliptic curve cryptography is in use
-  optional string ec_curve = 11;
-
-  // Standalone or is a file system required
-  optional string key_blob_usage_reqs = 12;
-}
diff --git a/keystore/key_creation_log_handler.cpp b/keystore/key_creation_log_handler.cpp
new file mode 100644
index 0000000..d846257
--- /dev/null
+++ b/keystore/key_creation_log_handler.cpp
@@ -0,0 +1,211 @@
+/*
+ * 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.
+ */
+#define LOG_TAG "KeystoreOperation"
+
+#include "key_creation_log_handler.h"
+#include <statslog.h>
+
+namespace keystore {
+
+template <typename Tag>
+int32_t getEnumTagValue(const AuthorizationSet& authorization_set, Tag tag) {
+    auto tagValue = authorization_set.GetTagValue(tag);
+    if (tagValue.isOk()) {
+        static_assert(sizeof(decltype(tagValue.value())) <= sizeof(int32_t),
+                      "Tag type value will be truncated, if cast to int32_t");
+        return static_cast<int32_t>(tagValue.value());
+    }
+    // Usually, if the value is not present, 0 is set. However, since 0 is a valid
+    // enum value, -1 is set for single enum fields.
+    return -1;
+}
+
+int32_t generateBitMapForPaddingModeValues(const AuthorizationSet& authorization_set) {
+    int32_t bitMap = 0;
+    int32_t tagValueCount = authorization_set.GetTagCount(TAG_PADDING);
+    if (tagValueCount == 0) {
+        // unlike in the single enum fields, if no value is provided,
+        // 0 is set for the bitmap
+        return bitMap;
+    }
+    int current_offset = -1;
+    while (tagValueCount > 0) {
+        current_offset = authorization_set.find(TAG_PADDING, current_offset);
+        KeyParameter keyParam = authorization_set[current_offset];
+        auto tagValue = accessTagValue(TAG_PADDING, keyParam);
+        switch (tagValue) {
+        case PaddingMode::NONE:
+            bitMap |= (1 << NONE_BIT_POS);
+            break;
+        case PaddingMode::RSA_OAEP:
+            bitMap |= (1 << PaddingModeBitPosition::RSA_OAEP_BIT_POS);
+            break;
+        case PaddingMode::RSA_PSS:
+            bitMap |= (1 << PaddingModeBitPosition::RSA_PSS_BIT_POS);
+            break;
+        case PaddingMode::RSA_PKCS1_1_5_ENCRYPT:
+            bitMap |= (1 << PaddingModeBitPosition::RSA_PKCS1_1_5_ENCRYPT_BIT_POS);
+            break;
+        case PaddingMode::RSA_PKCS1_1_5_SIGN:
+            bitMap |= (1 << PaddingModeBitPosition::RSA_PKCS1_1_5_SIGN_BIT_POS);
+            break;
+        case PaddingMode::PKCS7:
+            bitMap |= (1 << PaddingModeBitPosition::PKCS7_BIT_POS);
+            break;
+        default:
+            break;
+        }
+        tagValueCount -= 1;
+    }
+    return bitMap;
+}
+
+int32_t generateBitMapForDigestValues(const AuthorizationSet& authorization_set) {
+    int32_t bitMap = 0;
+    int32_t tagValueCount = authorization_set.GetTagCount(TAG_DIGEST);
+    if (tagValueCount == 0) {
+        // unlike in the single enum fields, if no value is provided,
+        // 0 is set for the bitmap
+        return bitMap;
+    }
+    int current_offset = -1;
+    while (tagValueCount > 0) {
+        current_offset = authorization_set.find(TAG_DIGEST, current_offset);
+        KeyParameter keyParam = authorization_set[current_offset];
+        auto tagValue = accessTagValue(TAG_DIGEST, keyParam);
+        switch (tagValue) {
+        case Digest::NONE:
+            bitMap |= (1 << NONE_BIT_POS);
+            break;
+        case Digest::MD5:
+            bitMap |= (1 << DigestBitPosition::MD5_BIT_POS);
+            break;
+        case Digest::SHA1:
+            bitMap |= (1 << DigestBitPosition::SHA1_BIT_POS);
+            break;
+        case Digest::SHA_2_224:
+            bitMap |= (1 << DigestBitPosition::SHA_2_224_BIT_POS);
+            break;
+        case Digest::SHA_2_256:
+            bitMap |= (1 << DigestBitPosition::SHA_2_256_BIT_POS);
+            break;
+        case Digest::SHA_2_384:
+            bitMap |= (1 << DigestBitPosition::SHA_2_384_BIT_POS);
+            break;
+        case Digest::SHA_2_512:
+            bitMap |= (1 << DigestBitPosition::SHA_2_512_BIT_POS);
+            break;
+        default:
+            break;
+        }
+        tagValueCount -= 1;
+    }
+    return bitMap;
+}
+
+int32_t generateBitMapForBlockModeValues(const AuthorizationSet& authorization_set) {
+    int32_t bitMap = 0;
+    int32_t tagValueCount = authorization_set.GetTagCount(TAG_BLOCK_MODE);
+    if (tagValueCount == 0) {
+        // unlike in the single enum fields, if no value is provided,
+        // 0 is set for the bitmap
+        return bitMap;
+    }
+    int current_offset = -1;
+    while (tagValueCount > 0) {
+        current_offset = authorization_set.find(TAG_BLOCK_MODE, current_offset);
+        KeyParameter keyParam = authorization_set[current_offset];
+        auto tagValue = accessTagValue(TAG_BLOCK_MODE, keyParam);
+        switch (tagValue) {
+        case BlockMode::ECB:
+            bitMap |= (1 << BlockModeBitPosition::ECB_BIT_POS);
+            break;
+        case BlockMode::CBC:
+            bitMap |= (1 << BlockModeBitPosition::CBC_BIT_POS);
+            break;
+        case BlockMode::CTR:
+            bitMap |= (1 << BlockModeBitPosition::CTR_BIT_POS);
+            break;
+        case BlockMode::GCM:
+            bitMap |= (1 << BlockModeBitPosition::GCM_BIT_POS);
+            break;
+        default:
+            break;
+        }
+        tagValueCount -= 1;
+    }
+    return bitMap;
+}
+
+int32_t generateBitMapForKeyPurposeValues(const AuthorizationSet& authorization_set) {
+    int32_t bitMap = 0;
+    int32_t tagValueCount = authorization_set.GetTagCount(TAG_PURPOSE);
+    if (tagValueCount == 0) {
+        // unlike in the single enum fields, if no value is provided,
+        // 0 is set for the bitmap
+        return bitMap;
+    }
+    int current_offset = -1;
+    while (tagValueCount > 0) {
+        current_offset = authorization_set.find(TAG_PURPOSE, current_offset);
+        KeyParameter keyParam = authorization_set[current_offset];
+        auto tagValue = accessTagValue(TAG_PURPOSE, keyParam);
+        switch (tagValue) {
+        case KeyPurpose::ENCRYPT:
+            bitMap |= (1 << KeyPurposeBitPosition::ENCRYPT_BIT_POS);
+            break;
+        case KeyPurpose::DECRYPT:
+            bitMap |= (1 << KeyPurposeBitPosition::DECRYPT_BIT_POS);
+            break;
+        case KeyPurpose::SIGN:
+            bitMap |= (1 << KeyPurposeBitPosition::SIGN_BIT_POS);
+            break;
+        case KeyPurpose::VERIFY:
+            bitMap |= (1 << KeyPurposeBitPosition::VERIFY_BIT_POS);
+            break;
+        case KeyPurpose::WRAP_KEY:
+            bitMap |= (1 << KeyPurposeBitPosition::WRAP_KEY_BIT_POS);
+            break;
+        default:
+            break;
+        }
+        tagValueCount -= 1;
+    }
+    return bitMap;
+}
+
+void logKeystoreKeyCreationEvent(const hidl_vec<KeyParameter>& keyParams,
+                                 bool wasCreationSuccessful, int32_t errorCode) {
+    AuthorizationSet authorization_set(keyParams);
+    authorization_set.Deduplicate();
+
+    android::util::stats_write(android::util::KEYSTORE_KEY_EVENT_REPORTED,
+                               getEnumTagValue(authorization_set, TAG_ALGORITHM),
+                               getEnumTagValue(authorization_set, TAG_KEY_SIZE),
+                               getEnumTagValue(authorization_set, TAG_ORIGIN),
+                               getEnumTagValue(authorization_set, TAG_USER_AUTH_TYPE),
+                               getEnumTagValue(authorization_set, TAG_AUTH_TIMEOUT),
+                               generateBitMapForPaddingModeValues(authorization_set),
+                               generateBitMapForDigestValues(authorization_set),
+                               generateBitMapForBlockModeValues(authorization_set),
+                               generateBitMapForKeyPurposeValues(authorization_set),
+                               getEnumTagValue(authorization_set, TAG_EC_CURVE),
+                               getEnumTagValue(authorization_set, TAG_BLOB_USAGE_REQUIREMENTS),
+                               android::util::KEYSTORE_KEY_EVENT_REPORTED__TYPE__KEY_CREATION,
+                               wasCreationSuccessful, errorCode);
+}
+
+}  // namespace keystore
diff --git a/keystore/key_creation_log_handler.h b/keystore/key_creation_log_handler.h
new file mode 100644
index 0000000..a314eb1
--- /dev/null
+++ b/keystore/key_creation_log_handler.h
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ */
+
+#ifndef KEY_CREATION_LOG_HANDLER_H_
+#define KEY_CREATION_LOG_HANDLER_H_
+
+#include <keystore/keystore_hidl_support.h>
+
+namespace keystore {
+
+/**
+ * Following enums are defined as a part of the workaround to log the repeated
+ * values of ENUM_REP type. The workaround is to represent the repeated values
+ * of ENUM_REP type as a bitmap and the following enums define their positions
+ * in the bitmap.
+ */
+
+enum PaddingModeBitPosition : int32_t {
+    RSA_OAEP_BIT_POS = 1,
+    RSA_PSS_BIT_POS = 2,
+    RSA_PKCS1_1_5_ENCRYPT_BIT_POS = 3,
+    RSA_PKCS1_1_5_SIGN_BIT_POS = 4,
+    PKCS7_BIT_POS = 5,
+};
+
+enum DigestBitPosition : int32_t {
+    MD5_BIT_POS = 1,
+    SHA1_BIT_POS = 2,
+    SHA_2_224_BIT_POS = 3,
+    SHA_2_256_BIT_POS = 4,
+    SHA_2_384_BIT_POS = 5,
+    SHA_2_512_BIT_POS = 6,
+};
+
+enum BlockModeBitPosition : int32_t {
+    ECB_BIT_POS = 1,
+    CBC_BIT_POS = 2,
+    CTR_BIT_POS = 3,
+    GCM_BIT_POS = 4,
+};
+
+enum KeyPurposeBitPosition : int32_t {
+    ENCRYPT_BIT_POS = 1,
+    DECRYPT_BIT_POS = 2,
+    SIGN_BIT_POS = 3,
+    VERIFY_BIT_POS = 4,
+    WRAP_KEY_BIT_POS = 5,
+};
+
+// None is an enum value for digest and a deprecated value for padding mode
+const int32_t NONE_BIT_POS = 0;
+
+void logKeystoreKeyCreationEvent(const hidl_vec<KeyParameter>& keyParams,
+                                 bool wasCreationSuccessful, int32_t errorCode);
+
+}  // namespace keystore
+
+#endif  // KEY_CREATION_LOG_HANDLER_H_
diff --git a/keystore/key_operation_log_handler.cpp b/keystore/key_operation_log_handler.cpp
new file mode 100644
index 0000000..140d5a7
--- /dev/null
+++ b/keystore/key_operation_log_handler.cpp
@@ -0,0 +1,136 @@
+/*
+ * 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.
+ */
+#define LOG_TAG "KeystoreOperation"
+
+#include "key_operation_log_handler.h"
+#include "key_creation_log_handler.h"
+
+#include <keystore/keystore_hidl_support.h>
+#include <statslog.h>
+
+namespace keystore {
+
+template <typename Tag>
+int32_t getOptionalEnumTagValue(const AuthorizationSet& authorization_set, Tag tag) {
+    auto tagValue = authorization_set.GetTagValue(tag);
+    if (tagValue.isOk()) {
+        static_assert(sizeof(decltype(tagValue.value())) <= sizeof(int32_t),
+                      "Tag type value will be truncated, if cast to int32_t");
+        return static_cast<int32_t>(tagValue.value());
+    }
+    //-1 is an invalid value for all enum types.
+    return -1;
+}
+
+int32_t generateBitMapForPaddingModeValue(const AuthorizationSet& authorization_set) {
+    auto tagValue = authorization_set.GetTagValue(TAG_PADDING);
+    if (tagValue.isOk()) {
+        auto value = tagValue.value();
+        switch (value) {
+        case PaddingMode::NONE:
+            return (1 << NONE_BIT_POS);
+        case PaddingMode::RSA_OAEP:
+            return (1 << PaddingModeBitPosition::RSA_OAEP_BIT_POS);
+        case PaddingMode::RSA_PSS:
+            return (1 << PaddingModeBitPosition::RSA_PSS_BIT_POS);
+        case PaddingMode::RSA_PKCS1_1_5_ENCRYPT:
+            return (1 << PaddingModeBitPosition::RSA_PKCS1_1_5_ENCRYPT_BIT_POS);
+        case PaddingMode::RSA_PKCS1_1_5_SIGN:
+            return (1 << PaddingModeBitPosition::RSA_PKCS1_1_5_SIGN_BIT_POS);
+        case PaddingMode::PKCS7:
+            return (1 << PaddingModeBitPosition::PKCS7_BIT_POS);
+        default:
+            break;
+        }
+    }
+    // unlike in the single enum fields, if no value is provided,
+    // 0 is set for the bitmap
+    return 0;
+}
+
+int32_t generateBitMapForDigestValue(const AuthorizationSet& authorization_set) {
+    auto tagValue = authorization_set.GetTagValue(TAG_DIGEST);
+    if (tagValue.isOk()) {
+        auto value = tagValue.value();
+        switch (value) {
+        case Digest::NONE:
+            return (1 << NONE_BIT_POS);
+        case Digest::MD5:
+            return (1 << DigestBitPosition::MD5_BIT_POS);
+        case Digest::SHA1:
+            return (1 << DigestBitPosition::SHA1_BIT_POS);
+        case Digest::SHA_2_224:
+            return (1 << DigestBitPosition::SHA_2_224_BIT_POS);
+        case Digest::SHA_2_256:
+            return (1 << DigestBitPosition::SHA_2_256_BIT_POS);
+        case Digest::SHA_2_384:
+            return (1 << DigestBitPosition::SHA_2_384_BIT_POS);
+        case Digest::SHA_2_512:
+            return (1 << DigestBitPosition::SHA_2_512_BIT_POS);
+        default:
+            break;
+        }
+    }
+    // unlike in the single enum fields, if no value is provided,
+    // 0 is set for the bitmap
+    return 0;
+}
+
+int32_t generateBitMapForBlockModeValue(const AuthorizationSet& authorization_set) {
+    auto tagValue = authorization_set.GetTagValue(TAG_BLOCK_MODE);
+    if (tagValue.isOk()) {
+        auto value = tagValue.value();
+        switch (value) {
+        case BlockMode::ECB:
+            return (1 << BlockModeBitPosition::ECB_BIT_POS);
+        case BlockMode::CBC:
+            return (1 << BlockModeBitPosition::CBC_BIT_POS);
+        case BlockMode::CTR:
+            return (1 << BlockModeBitPosition::CTR_BIT_POS);
+        case BlockMode::GCM:
+            return (1 << BlockModeBitPosition::GCM_BIT_POS);
+        default:
+            break;
+        }
+    }
+    // unlike in the single enum fields, if no value is provided,
+    // 0 is set for the bitmap
+    return 0;
+}
+
+void logKeystoreKeyOperationEvent(const Operation& op, bool wasOperationSuccessful,
+                                  int32_t responseCode) {
+    AuthorizationSet authorization_set(op.characteristics.softwareEnforced);
+    authorization_set.Union(op.characteristics.hardwareEnforced);
+    AuthorizationSet operation_params(op.params);
+
+    android::util::stats_write(
+        android::util::KEYSTORE_KEY_EVENT_REPORTED,
+        getOptionalEnumTagValue(authorization_set, TAG_ALGORITHM),
+        getOptionalEnumTagValue(authorization_set, TAG_KEY_SIZE),
+        getOptionalEnumTagValue(authorization_set, TAG_ORIGIN),
+        getOptionalEnumTagValue(authorization_set, TAG_USER_AUTH_TYPE),
+        getOptionalEnumTagValue(authorization_set, TAG_AUTH_TIMEOUT),
+        generateBitMapForPaddingModeValue(operation_params),
+        generateBitMapForDigestValue(operation_params),
+        generateBitMapForBlockModeValue(operation_params), static_cast<int32_t>(op.purpose),
+        getOptionalEnumTagValue(authorization_set, TAG_EC_CURVE),
+        getOptionalEnumTagValue(authorization_set, TAG_BLOB_USAGE_REQUIREMENTS),
+        android::util::KEYSTORE_KEY_EVENT_REPORTED__TYPE__KEY_OPERATION, wasOperationSuccessful,
+        responseCode);
+}
+
+}  // namespace keystore
diff --git a/keystore/key_proto_handler.h b/keystore/key_operation_log_handler.h
similarity index 68%
rename from keystore/key_proto_handler.h
rename to keystore/key_operation_log_handler.h
index a2f6a24..efd3f00 100644
--- a/keystore/key_proto_handler.h
+++ b/keystore/key_operation_log_handler.h
@@ -14,16 +14,15 @@
  * limitations under the License.
  */
 
-#ifndef KEYSTORE_KEY_PROTO_HANDLER_H_
-#define KEYSTORE_KEY_PROTO_HANDLER_H_
+#ifndef KEY_OPERATION_LOG_HANDLER_H_
+#define KEY_OPERATION_LOG_HANDLER_H_
 
-#include <keystore/keystore_hidl_support.h>
+#include "operation_struct.h"
 
 namespace keystore {
 
-void uploadKeyCharacteristicsAsProto(const hidl_vec<KeyParameter>& keyParams,
-                                     bool wasCreationSuccessful);
+void logKeystoreKeyOperationEvent(const Operation& op, bool wasSuccessful, int32_t errorCode);
 
 }  // namespace keystore
 
-#endif  // KEYSTORE_KEY_PROTO_HANDLER_H_
+#endif  // KEY_OPERATION_LOG_HANDLER_H_
diff --git a/keystore/key_proto_handler.cpp b/keystore/key_proto_handler.cpp
deleted file mode 100644
index f8400af..0000000
--- a/keystore/key_proto_handler.cpp
+++ /dev/null
@@ -1,87 +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.
- */
-#define LOG_TAG "KeystoreOperation"
-
-#include "key_proto_handler.h"
-
-#include <android/os/DropBoxManager.h>
-#include <google/protobuf/message_lite.h>
-#include <keymasterV4_1/Keymaster.h>
-#include <keystore/keymaster_types.h>
-#include <utils/String16.h>
-#include <utils/StrongPointer.h>
-
-#include "key_config.pb.h"
-
-namespace keystore {
-
-void checkEnforcedCharacteristics(const hidl_vec<KeyParameter>& keyParams, KeyConfig* keyConfig) {
-    for (auto& keyParam : keyParams) {
-        switch (keyParam.tag) {
-        case Tag::PURPOSE:
-            keyConfig->add_purpose(toString(accessTagValue(TAG_PURPOSE, keyParam)));
-            break;
-        case Tag::ALGORITHM:
-            keyConfig->set_algorithm(toString(accessTagValue(TAG_ALGORITHM, keyParam)));
-            break;
-        case Tag::KEY_SIZE:
-            keyConfig->set_key_size(accessTagValue(TAG_KEY_SIZE, keyParam));
-            break;
-        case Tag::BLOCK_MODE:
-            keyConfig->add_block_mode(toString(accessTagValue(TAG_BLOCK_MODE, keyParam)));
-            break;
-        case Tag::PADDING:
-            keyConfig->add_padding(toString(accessTagValue(TAG_PADDING, keyParam)));
-            break;
-        case Tag::DIGEST:
-            keyConfig->add_digest(toString(accessTagValue(TAG_DIGEST, keyParam)));
-            break;
-        case Tag::EC_CURVE:
-            keyConfig->set_ec_curve(toString(accessTagValue(TAG_EC_CURVE, keyParam)));
-            break;
-        case Tag::AUTH_TIMEOUT:
-            keyConfig->set_user_auth_key_timeout(accessTagValue(TAG_AUTH_TIMEOUT, keyParam));
-            break;
-        case Tag::ORIGIN:
-            keyConfig->set_origin(toString(accessTagValue(TAG_ORIGIN, keyParam)));
-            break;
-        case Tag::BLOB_USAGE_REQUIREMENTS:
-            keyConfig->set_key_blob_usage_reqs(
-                toString(accessTagValue(TAG_BLOB_USAGE_REQUIREMENTS, keyParam)));
-            break;
-        case Tag::USER_AUTH_TYPE:
-            keyConfig->set_user_auth_type(toString(accessTagValue(TAG_USER_AUTH_TYPE, keyParam)));
-            break;
-        default:
-            break;
-        }
-    }
-}
-
-void uploadKeyCharacteristicsAsProto(const hidl_vec<KeyParameter>& keyParams,
-                                     bool wasCreationSuccessful) {
-    KeyConfig keyConfig;
-    checkEnforcedCharacteristics(keyParams, &keyConfig);
-    android::sp<android::os::DropBoxManager> dropbox(new android::os::DropBoxManager());
-    keyConfig.set_was_creation_successful(wasCreationSuccessful);
-
-    size_t size = keyConfig.ByteSize();
-    auto data = std::make_unique<uint8_t[]>(size);
-    keyConfig.SerializeWithCachedSizesToArray(data.get());
-    dropbox->addData(android::String16("keymaster"), data.get(), size, 0);
-}
-
-}  // namespace keystore
diff --git a/keystore/key_store_service.cpp b/keystore/key_store_service.cpp
index 583f5b6..4e5bc48 100644
--- a/keystore/key_store_service.cpp
+++ b/keystore/key_store_service.cpp
@@ -41,7 +41,7 @@
 #include <keymasterV4_0/keymaster_utils.h>
 
 #include "defaults.h"
-#include "key_proto_handler.h"
+#include "key_attestation_log_handler.h"
 #include "keystore_keymaster_enforcement.h"
 #include "keystore_utils.h"
 #include <keystore/keystore_attestation_id.h>
@@ -1118,6 +1118,10 @@
 
     AuthorizationSet mutableParams = params.getParameters();
     KeyStoreServiceReturnCode rc = updateParamsForAttestation(callingUid, &mutableParams);
+
+    auto logErrorOnReturn = android::base::make_scope_guard(
+        [&] { logKeystoreKeyAttestationEvent(false /*wasSuccessful*/, rc.getErrorCode()); });
+
     if (!rc.isOk()) {
         return AIDL_RETURN(rc);
     }
@@ -1134,6 +1138,8 @@
         return AIDL_RETURN(rc);
     }
 
+    logErrorOnReturn.Disable();
+
     auto dev = mKeyStore->getDevice(keyBlob);
     auto hidlKey = blob2hidlVec(keyBlob);
     dev->attestKey(
@@ -1142,13 +1148,18 @@
                   std::tuple<ErrorCode, hidl_vec<hidl_vec<uint8_t>>>&& hidlResult) {
             auto& [ret, certChain] = hidlResult;
             if (!rc.isOk()) {
+                logKeystoreKeyAttestationEvent(false /*wasSuccessful*/,
+                                               static_cast<int32_t>(ResponseCode::SYSTEM_ERROR));
                 cb->onFinished(KeyStoreServiceReturnCode(ResponseCode::SYSTEM_ERROR), {});
             } else if (ret != ErrorCode::OK) {
+                KeyStoreServiceReturnCode ksrc(ret);
+                logKeystoreKeyAttestationEvent(false /*wasSuccessful*/, ksrc.getErrorCode());
                 dev->logIfKeymasterVendorError(ret);
-                cb->onFinished(KeyStoreServiceReturnCode(ret), {});
+                cb->onFinished(ksrc, {});
             } else {
-                cb->onFinished(KeyStoreServiceReturnCode(ret),
-                               KeymasterCertificateChain(std::move(certChain)));
+                KeyStoreServiceReturnCode ksrc(ret);
+                logKeystoreKeyAttestationEvent(true /*wasSuccessful*/, ksrc.getErrorCode());
+                cb->onFinished(ksrc, KeymasterCertificateChain(std::move(certChain)));
             }
         });
 
diff --git a/keystore/keymaster_worker.cpp b/keystore/keymaster_worker.cpp
index 911815e..7481a1e 100644
--- a/keystore/keymaster_worker.cpp
+++ b/keystore/keymaster_worker.cpp
@@ -29,7 +29,7 @@
 #include "KeyStore.h"
 #include "keymaster_enforcement.h"
 
-#include "key_proto_handler.h"
+#include "key_creation_log_handler.h"
 #include "keystore_utils.h"
 
 #include <chrono>
@@ -336,8 +336,10 @@
     return {rc, std::move(authToken)};
 }
 
-KeyStoreServiceReturnCode KeymasterWorker::abort(const sp<IBinder>& token) {
-    auto op = operationMap_.removeOperation(token, false /* wasOpSuccessful */);
+KeyStoreServiceReturnCode KeymasterWorker::abort(const sp<IBinder>& token,
+                                                 ResponseCode reason_for_abort) {
+    auto op = operationMap_.removeOperation(token, false /* wasOpSuccessful */,
+                                            static_cast<int32_t>(reason_for_abort));
     if (op) {
         keyStore_->getAuthTokenTable().MarkCompleted(op->handle);
         return KS_HANDLE_HIDL_ERROR(keymasterDevice_, keymasterDevice_->abort(op->handle));
@@ -355,7 +357,7 @@
     size_t op_count_before_abort = operationMap_.getOperationCount();
     // We mostly ignore errors from abort() because all we care about is whether at least
     // one operation has been removed.
-    auto rc = abort(oldest);
+    auto rc = abort(oldest, ResponseCode::PRUNED);
     keyStore_->removeOperationDevice(oldest);
     if (operationMap_.getOperationCount() >= op_count_before_abort) {
         ALOGE("Failed to abort pruneable operation %p, error: %d", oldest.get(), rc.getErrorCode());
@@ -598,7 +600,7 @@
         }
 
         Finalize abort_operation_in_case_of_error([&] {
-            operationMap_.removeOperation(token, false);
+            operationMap_.removeOperation(token, false, rc.getErrorCode());
             keyStore_->getAuthTokenTable().MarkCompleted(op->handle);
             KS_HANDLE_HIDL_ERROR(keymasterDevice_, keymasterDevice_->abort(op->handle));
         });
@@ -677,7 +679,7 @@
 
         bool finished = false;
         Finalize abort_operation_in_case_of_error([&] {
-            operationMap_.removeOperation(token, finished && rc.isOk());
+            operationMap_.removeOperation(token, finished && rc.isOk(), rc.getErrorCode());
             keyStore_->getAuthTokenTable().MarkCompleted(op->handle);
             if (!finished)
                 KS_HANDLE_HIDL_ERROR(keymasterDevice_, keymasterDevice_->abort(op->handle));
@@ -745,8 +747,9 @@
 }
 
 void KeymasterWorker::abort(sp<IBinder> token, abort_cb worker_cb) {
-    Worker::addRequest(
-        [this, CAPTURE_MOVE(token), CAPTURE_MOVE(worker_cb)]() { return worker_cb(abort(token)); });
+    Worker::addRequest([this, CAPTURE_MOVE(token), CAPTURE_MOVE(worker_cb)]() {
+        return worker_cb(abort(token, ResponseCode::ABORT_CALLED));
+    });
 }
 
 void KeymasterWorker::verifyAuthorization(uint64_t challenge, hidl_vec<KeyParameter> params,
@@ -800,8 +803,10 @@
         // by KeyStore::getFallbackDevice()
         bool consider_fallback = securityLevel == SecurityLevel::TRUSTED_ENVIRONMENT;
 
-        Finalize logOnFail(
-            [&] { uploadKeyCharacteristicsAsProto(keyParams, false /* wasCreationSuccessful */); });
+        Finalize logOnFail([&] {
+            logKeystoreKeyCreationEvent(keyParams, false /*wasCreationSuccessful*/,
+                                        rc.getErrorCode());
+        });
 
         KeyCharacteristics outCharacteristics;
         KeyStoreServiceReturnCode error;
@@ -870,7 +875,8 @@
 
         // log on success
         logOnFail.release();
-        uploadKeyCharacteristicsAsProto(keyParams, true /* wasCreationSuccessful */);
+        logKeystoreKeyCreationEvent(keyParams, true /*wasCreationSuccessful*/,
+                                    error.getErrorCode());
 
         return worker_cb(error, std::move(outCharacteristics));
     });
@@ -904,11 +910,13 @@
         // by KeyStore::getFallbackDevice()
         bool consider_fallback = securityLevel == SecurityLevel::TRUSTED_ENVIRONMENT;
 
-        Finalize logOnFail(
-            [&] { uploadKeyCharacteristicsAsProto(keyParams, false /* wasCreationSuccessful */); });
+        KeyStoreServiceReturnCode error;
+        Finalize logOnFail([&] {
+            logKeystoreKeyCreationEvent(keyParams, false /*wasCreationSuccessful*/,
+                                        error.getErrorCode());
+        });
 
         KeyCharacteristics outCharacteristics;
-        KeyStoreServiceReturnCode error;
         auto hidl_cb = [&](ErrorCode ret, const hidl_vec<uint8_t>& hidlKeyBlob,
                            const KeyCharacteristics& keyCharacteristics) {
             keymasterDevice_->logIfKeymasterVendorError(ret);
@@ -975,7 +983,8 @@
 
         // log on success
         logOnFail.release();
-        uploadKeyCharacteristicsAsProto(keyParams, true /* wasCreationSuccessful */);
+        logKeystoreKeyCreationEvent(keyParams, true /*wasCreationSuccessful*/,
+                                    error.getErrorCode());
 
         return worker_cb(error, std::move(outCharacteristics));
     });
@@ -1126,7 +1135,7 @@
     Worker::addRequest([this, who]() {
         auto operations = operationMap_.getOperationsForToken(who.unsafe_get());
         for (const auto& token : operations) {
-            abort(token);
+            abort(token, ResponseCode::BINDER_DIED);
             keyStore_->removeOperationDevice(token);
         }
     });
diff --git a/keystore/keymaster_worker.h b/keystore/keymaster_worker.h
index 8e35c16..f11af29 100644
--- a/keystore/keymaster_worker.h
+++ b/keystore/keymaster_worker.h
@@ -190,7 +190,7 @@
     getAuthToken(const KeyCharacteristics& characteristics, uint64_t handle, KeyPurpose purpose,
                  bool failOnTokenMissing = true);
 
-    KeyStoreServiceReturnCode abort(const sp<IBinder>& token);
+    KeyStoreServiceReturnCode abort(const sp<IBinder>& token, ResponseCode reason_for_abort);
 
     bool pruneOperation();
 
diff --git a/keystore/operation.cpp b/keystore/operation.cpp
index 71ab340..bd4bd5e 100644
--- a/keystore/operation.cpp
+++ b/keystore/operation.cpp
@@ -16,6 +16,7 @@
 #define LOG_TAG "KeystoreOperation"
 
 #include "operation.h"
+#include "key_operation_log_handler.h"
 
 #include <algorithm>
 #include <android-base/logging.h>
@@ -58,12 +59,12 @@
 }
 
 std::shared_ptr<Operation> OperationMap::removeOperation(const sp<IBinder>& token,
-                                                         bool wasSuccessful) {
+                                                         bool wasSuccessful, int32_t responseCode) {
     auto entry = mMap.find(token);
     if (entry == mMap.end()) return {};
 
     auto op = entry->second;
-    operationUploader.uploadOpAsProto(*op, wasSuccessful);
+    logKeystoreKeyOperationEvent(*op, wasSuccessful, responseCode);
     mMap.erase(entry);
 
     auto lruEntry = std::find(mLru.begin(), mLru.end(), token);
diff --git a/keystore/operation.h b/keystore/operation.h
index ef880a7..8423db5 100644
--- a/keystore/operation.h
+++ b/keystore/operation.h
@@ -33,7 +33,6 @@
 #include <keystore/keystore_concurrency.h>
 #include <keystore/keystore_hidl_support.h>
 
-#include "operation_proto_handler.h"
 #include "operation_struct.h"
 
 namespace keystore {
@@ -57,7 +56,8 @@
                              KeyCharacteristics&& characteristics,
                              const hidl_vec<KeyParameter>& params, bool pruneable);
     std::shared_ptr<Operation> getOperation(const sp<IBinder>& token);
-    std::shared_ptr<Operation> removeOperation(const sp<IBinder>& token, bool wasSuccessful);
+    std::shared_ptr<Operation> removeOperation(const sp<IBinder>& token, bool wasSuccessful,
+                                               int32_t responseCode);
     size_t getOperationCount() const { return mMap.size(); }
     sp<IBinder> getOldestPruneableOperation();
     std::vector<sp<IBinder>> getOperationsForToken(const sp<IBinder>& appToken);
@@ -70,7 +70,6 @@
     std::list<sp<IBinder>> mLru;
     std::map<sp<IBinder>, std::vector<sp<IBinder>>> mAppTokenMap;
     IBinder::DeathRecipient* mDeathRecipient;
-    OperationProtoHandler operationUploader;
 };
 
 }  // namespace keystore
diff --git a/keystore/operation_config.proto b/keystore/operation_config.proto
deleted file mode 100644
index efbb4fe..0000000
--- a/keystore/operation_config.proto
+++ /dev/null
@@ -1,77 +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.
- */
-
-syntax = "proto2";
-
-package keystore;
-
-option optimize_for = LITE_RUNTIME;
-
-// A single operation config
-message OperationConfig {
-  // What type of encryption algorithm is the key being used in the op for.
-  optional string algorithm = 1;
-
-  // Size of the key being used in this op
-  optional int32 key_size = 2;
-
-  // Log whether the key in this op was generated, imported,
-  // securely imported, or derived.
-  optional string origin = 3;
-
-  // What auth types does this op require? If none, then no auth required.
-  optional string user_auth_type = 4;
-
-  // If user authentication is required, is the requirement time based? If it
-  // is not time based then this field will not be used and the key is per
-  // operation. Per operation keys must be user authenticated on each usage.
-  optional int32 user_auth_key_timeout = 5;
-
-  // Track which padding mode was used for this operation.
-  optional string padding = 6;
-
-  // Keep track of the digest algorithm being used.
-  optional string digest = 7;
-
-  // Check what block mode is being used depending on the mode of encryption
-  optional string block_mode = 8;
-
-  // Did the operation succeed? If it didn't, this represents bugs or
-  // error cases occurring.
-  optional bool was_op_successful = 9;
-
-  // What purpose is this operation serving? Encrypt, decrypt, sign verify?
-  optional string purpose = 10;
-
-  // Which ec curve was selected if elliptic curve cryptography is in use
-  optional string ec_curve = 11;
-
-  // Standalone or is a file system required
-  optional string key_blob_usage_reqs = 12;
-}
-
-message OperationConfigEvent {
-  optional OperationConfig op_config = 1;
-
-  // counts corresponds to the number of times each op_config in the above array
-  // was recorded during the collection period.
-  optional uint32 count = 2;
-}
-
-message OperationConfigEvents {
-    repeated OperationConfigEvent op_config_events = 1;
-}
-
diff --git a/keystore/operation_proto_handler.cpp b/keystore/operation_proto_handler.cpp
deleted file mode 100644
index 3b3d3fc..0000000
--- a/keystore/operation_proto_handler.cpp
+++ /dev/null
@@ -1,147 +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.
- */
-#define LOG_TAG "KeystoreOperation"
-
-#include "operation_proto_handler.h"
-
-#include <android/os/DropBoxManager.h>
-#include <google/protobuf/message_lite.h>
-#include <keymasterV4_1/Keymaster.h>
-#include <keystore/keymaster_types.h>
-#include <keystore/keystore_hidl_support.h>
-#include <utils/String16.h>
-#include <utils/StrongPointer.h>
-
-using namespace std::chrono;
-
-namespace keystore {
-
-constexpr auto kCollectionTime = 1h;
-
-void determinePurpose(KeyPurpose purpose, OperationConfig* operationConfig) {
-    switch (purpose) {
-    case KeyPurpose::VERIFY:
-        operationConfig->set_purpose("verify");
-        break;
-    case KeyPurpose::ENCRYPT:
-        operationConfig->set_purpose("encrypt");
-        break;
-    case KeyPurpose::SIGN:
-        operationConfig->set_purpose("sign");
-        break;
-    case KeyPurpose::DECRYPT:
-        operationConfig->set_purpose("decrypt");
-        break;
-    case KeyPurpose::WRAP_KEY:
-        operationConfig->set_purpose("wrap");
-        break;
-    default:
-        break;
-    }
-}
-
-void checkKeyCharacteristics(const hidl_vec<KeyParameter>& characteristics,
-                             OperationConfig* operationConfig) {
-    for (auto& opParam : characteristics) {
-        switch (opParam.tag) {
-        case Tag::ALGORITHM:
-            operationConfig->set_algorithm(toString(accessTagValue(TAG_ALGORITHM, opParam)));
-            break;
-        case Tag::KEY_SIZE:
-            operationConfig->set_key_size(accessTagValue(TAG_KEY_SIZE, opParam));
-            break;
-        case Tag::EC_CURVE:
-            operationConfig->set_ec_curve(toString(accessTagValue(TAG_EC_CURVE, opParam)));
-            break;
-        case Tag::AUTH_TIMEOUT:
-            operationConfig->set_user_auth_key_timeout(accessTagValue(TAG_AUTH_TIMEOUT, opParam));
-            break;
-        case Tag::ORIGIN:
-            operationConfig->set_origin(toString(accessTagValue(TAG_ORIGIN, opParam)));
-            break;
-        case Tag::BLOB_USAGE_REQUIREMENTS:
-            operationConfig->set_key_blob_usage_reqs(
-                toString(accessTagValue(TAG_BLOB_USAGE_REQUIREMENTS, opParam)));
-            break;
-        case Tag::USER_AUTH_TYPE:
-            operationConfig->set_user_auth_type(
-                toString(accessTagValue(TAG_USER_AUTH_TYPE, opParam)));
-            break;
-        default:
-            break;
-        }
-    }
-}
-
-void checkOpCharacteristics(const hidl_vec<KeyParameter>& characteristics,
-                            OperationConfig* operationConfig) {
-    for (auto& opParam : characteristics) {
-        switch (opParam.tag) {
-        case Tag::BLOCK_MODE:
-            operationConfig->set_block_mode(toString(accessTagValue(TAG_BLOCK_MODE, opParam)));
-            break;
-        case Tag::PADDING:
-            operationConfig->set_padding(toString(accessTagValue(TAG_PADDING, opParam)));
-            break;
-        case Tag::DIGEST:
-            operationConfig->set_digest(toString(accessTagValue(TAG_DIGEST, opParam)));
-            break;
-        default:
-            break;
-        }
-    }
-}
-
-void OperationProtoHandler::uploadOpAsProto(Operation& op, bool wasOpSuccessful) {
-    std::lock_guard<std::mutex> lock(op_upload_mutex);
-    OperationConfig operationConfig;
-    determinePurpose(op.purpose, &operationConfig);
-    checkKeyCharacteristics(op.characteristics.softwareEnforced, &operationConfig);
-    checkKeyCharacteristics(op.characteristics.hardwareEnforced, &operationConfig);
-    checkOpCharacteristics(op.params, &operationConfig);
-    operationConfig.set_was_op_successful(wasOpSuccessful);
-    // Only bother with counting an hour out when an operation entry is actually
-    // added
-    if (protoMap.empty()) {
-        start_time = std::chrono::steady_clock::now();
-    }
-    auto cur_time = std::chrono::steady_clock::now();
-
-    // Add operations to a map within the time duration of an hour. Deduplicate
-    // repeated ops by incrementing the counter of the original one stored and
-    // discarding the new one.
-    protoMap[operationConfig.SerializeAsString()]++;
-
-    if (cur_time - start_time >= kCollectionTime) {
-        // Iterate through the unordered map and dump all the operation protos
-        // accumulated over the hour into the holding list proto after setting
-        // their counts.
-        OperationConfigEvents opConfigEvents;
-        for (auto elem : protoMap) {
-            OperationConfigEvent* event = opConfigEvents.add_op_config_events();
-            event->mutable_op_config()->ParseFromString(elem.first);
-            event->set_count(elem.second);
-        }
-        android::sp<android::os::DropBoxManager> dropbox(new android::os::DropBoxManager);
-        size_t size = opConfigEvents.ByteSize();
-        auto data = std::make_unique<uint8_t[]>(size);
-        opConfigEvents.SerializeWithCachedSizesToArray(data.get());
-        dropbox->addData(android::String16("keymaster"), data.get(), size, 0);
-        protoMap.clear();
-    }
-}
-
-}  // namespace keystore
diff --git a/keystore/operation_proto_handler.h b/keystore/operation_proto_handler.h
deleted file mode 100644
index 64d0a59..0000000
--- a/keystore/operation_proto_handler.h
+++ /dev/null
@@ -1,44 +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.
- */
-
-#ifndef KEYSTORE_OPERATION_PROTO_HANDLER_H_
-#define KEYSTORE_OPERATION_PROTO_HANDLER_H_
-
-#include "operation_config.pb.h"
-#include "operation_struct.h"
-#include <chrono>
-#include <mutex>
-#include <unordered_map>
-#include <vector>
-
-namespace keystore {
-
-using ::android::IBinder;
-using keymaster::support::Keymaster;
-
-class OperationProtoHandler {
-  public:
-    void uploadOpAsProto(Operation& op, bool wasOpSuccessful);
-
-  private:
-    std::unordered_map<std::string, int> protoMap;
-    std::chrono::steady_clock::time_point start_time = std::chrono::steady_clock::now();
-    std::mutex op_upload_mutex;
-};
-
-}  // namespace keystore
-
-#endif  // KEYSTORE_OPERATION_PROTO_HANDLER_H_
diff --git a/keystore2/Android.bp b/keystore2/Android.bp
new file mode 100644
index 0000000..154b675
--- /dev/null
+++ b/keystore2/Android.bp
@@ -0,0 +1,88 @@
+// Copyright 2020, 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.
+
+rust_library {
+    name: "libkeystore2",
+    crate_name: "keystore2",
+    srcs: ["src/lib.rs"],
+
+    rustlibs: [
+        "libanyhow",
+        "libkeystore_aidl_generated",
+        "libkeystore2_selinux",
+        "liblazy_static",
+        "liblibsqlite3_sys",
+        "liblog_rust",
+        "librand",
+        "librusqlite",
+        "libthiserror",
+    ],
+}
+
+rust_test {
+    name: "keystore2_test",
+    crate_name: "keystore2",
+    srcs: ["src/lib.rs"],
+    test_suites: ["general-tests"],
+    auto_gen_config: true,
+    rustlibs: [
+        "libandroid_logger",
+        "libanyhow",
+        "libkeystore_aidl_generated",
+        "libkeystore2_selinux",
+        "liblazy_static",
+        "liblibsqlite3_sys",
+        "liblog_rust",
+        "librusqlite",
+        "libthiserror",
+    ],
+}
+
+// This is a placeholder for the libraries that will be generated from the AIDL specs
+// eventually.
+rust_library {
+    name: "libkeystore_aidl_generated",
+    crate_name: "keystore_aidl_generated",
+
+    srcs: ["src/aidl_generated.rs"],
+}
+
+// This is a placeholder for the libraries that will be generated from the AIDL specs
+// eventually.
+rust_library {
+    name: "libandroid_hardware_keymint",
+    crate_name: "android_hardware_keymint",
+
+    srcs: ["src/android_hardware_keymint.rs"],
+
+    rustlibs: [
+        "libbinder_rs",
+        "liblazy_static",
+    ],
+}
+
+// This is a placeholder for the libraries that will be generated from the AIDL specs
+// eventually.
+rust_library {
+    name: "libandroid_security_keystore2",
+    crate_name: "android_security_keystore2",
+
+    srcs: ["src/android_security_keystore2.rs"],
+
+    rustlibs: [
+        "libandroid_hardware_keymint",
+        "libbinder_rs",
+        "liblazy_static",
+    ],
+}
diff --git a/keystore2/TEST_MAPPING b/keystore2/TEST_MAPPING
new file mode 100644
index 0000000..70e3175
--- /dev/null
+++ b/keystore2/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "presubmit": [
+    {
+      "name": "keystore2_test"
+    }
+  ]
+}
diff --git a/keystore2/selinux/Android.bp b/keystore2/selinux/Android.bp
new file mode 100644
index 0000000..acbf5ef
--- /dev/null
+++ b/keystore2/selinux/Android.bp
@@ -0,0 +1,54 @@
+// Copyright 2020, 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.
+
+rust_library {
+    name: "libkeystore2_selinux",
+    crate_name: "keystore2_selinux",
+    srcs: [
+        "src/lib.rs",
+    ],
+
+    shared_libs: [
+        "libselinux",
+    ],
+
+    rustlibs: [
+        "libanyhow",
+        "liblog_rust",
+        "libselinux_bindgen",
+        "libthiserror",
+    ],
+}
+
+rust_test {
+    name: "keystore2_selinux_test",
+    srcs: [
+        "src/lib.rs",
+    ],
+    crate_name: "keystore2_selinux_test",
+    test_suites: ["general-tests"],
+    auto_gen_config: true,
+
+    shared_libs: [
+        "libselinux",
+    ],
+
+    rustlibs: [
+        "libandroid_logger",
+        "libanyhow",
+        "liblog_rust",
+        "libselinux_bindgen",
+        "libthiserror",
+    ],
+}
diff --git a/keystore2/selinux/TEST_MAPPING b/keystore2/selinux/TEST_MAPPING
new file mode 100644
index 0000000..0e68257
--- /dev/null
+++ b/keystore2/selinux/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "presubmit": [
+    {
+      "name": "keystore2_selinux_test"
+    }
+  ]
+}
diff --git a/keystore2/selinux/src/lib.rs b/keystore2/selinux/src/lib.rs
new file mode 100644
index 0000000..05f9db8
--- /dev/null
+++ b/keystore2/selinux/src/lib.rs
@@ -0,0 +1,427 @@
+// Copyright 2020, 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.
+
+// #![allow(missing_docs)]
+
+//! This crate provides some safe wrappers around the libselinux API. It is currently limited
+//! to the API surface that Keystore 2.0 requires to perform permission checks against
+//! the SEPolicy. Notably, it provides wrappers for:
+//!  * getcon
+//!  * selinux_check_access
+//!  * selabel_lookup for the keystore2_key backend.
+//! And it provides an owning wrapper around context strings `Context`.
+
+use std::ffi::{CStr, CString};
+use std::fmt;
+use std::io;
+use std::marker::{Send, Sync};
+pub use std::ops::Deref;
+use std::os::raw::c_char;
+use std::ptr;
+use std::sync;
+
+use selinux_bindgen as selinux;
+
+use anyhow::Context as AnyhowContext;
+use anyhow::{anyhow, Result};
+
+use selinux::SELABEL_CTX_ANDROID_KEYSTORE2_KEY;
+use selinux::SELINUX_CB_LOG;
+
+static SELINUX_LOG_INIT: sync::Once = sync::Once::new();
+
+fn redirect_selinux_logs_to_logcat() {
+    // `selinux_set_callback` assigned the static lifetime function pointer
+    // `selinux_log_callback` to a static lifetime variable.
+    let cb = selinux::selinux_callback { func_log: Some(selinux::selinux_log_callback) };
+    unsafe {
+        selinux::selinux_set_callback(SELINUX_CB_LOG as i32, cb);
+    }
+}
+
+// This function must be called before any entrypoint into lib selinux.
+// Or leave a comment reasoning why calling this macro is not necessary
+// for a given entry point.
+fn init_logger_once() {
+    SELINUX_LOG_INIT.call_once(redirect_selinux_logs_to_logcat)
+}
+
+/// Selinux Error code.
+#[derive(thiserror::Error, Debug, PartialEq)]
+pub enum Error {
+    /// Indicates that an access check yielded no access.
+    #[error("Permission Denied")]
+    PermissionDenied,
+    /// Indicates an unexpected system error. Nested string provides some details.
+    #[error("Selinux SystemError: {0}")]
+    SystemError(String),
+}
+
+impl Error {
+    /// Constructs a `PermissionDenied` error.
+    pub fn perm() -> Self {
+        Error::PermissionDenied
+    }
+    fn sys<T: Into<String>>(s: T) -> Self {
+        Error::SystemError(s.into())
+    }
+}
+
+/// Context represents an SELinux context string. It can take ownership of a raw
+/// s-string as allocated by `getcon` or `selabel_lookup`. In this case it uses
+/// `freecon` to free the resources when dropped. In its second variant it stores
+/// an `std::ffi::CString` that can be initialized from a Rust string slice.
+pub enum Context {
+    /// Wraps a raw context c-string as returned by libselinux.
+    Raw(*mut ::std::os::raw::c_char),
+    /// Stores a context string as `std::ffi::CString`.
+    CString(CString),
+}
+
+impl fmt::Display for Context {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{}", (**self).to_str().unwrap_or("Invalid context"))
+    }
+}
+
+impl Drop for Context {
+    fn drop(&mut self) {
+        if let Self::Raw(p) = self {
+            // No need to initialize the logger here, because
+            // `freecon` cannot run unless `Backend::lookup` or `getcon`
+            // has run.
+            unsafe { selinux::freecon(*p) };
+        }
+    }
+}
+
+impl Deref for Context {
+    type Target = CStr;
+
+    fn deref(&self) -> &Self::Target {
+        match self {
+            Self::Raw(p) => unsafe { CStr::from_ptr(*p) },
+            Self::CString(cstr) => &cstr,
+        }
+    }
+}
+
+impl Context {
+    /// Initializes the `Context::CString` variant from a Rust string slice.
+    pub fn new(con: &str) -> Result<Self> {
+        Ok(Self::CString(
+            CString::new(con)
+                .with_context(|| format!("Failed to create Context with \"{}\"", con))?,
+        ))
+    }
+}
+
+/// The backend trait provides a uniform interface to all libselinux context backends.
+/// Currently, we only implement the KeystoreKeyBackend though.
+pub trait Backend {
+    /// Implementers use libselinux `selabel_lookup` to lookup the context for the given `key`.
+    fn lookup(&self, key: &str) -> Result<Context>;
+}
+
+/// Keystore key backend takes onwnership of the SELinux context handle returned by
+/// `selinux_android_keystore2_key_context_handle` and uses `selabel_close` to free
+/// the handle when dropped.
+/// It implements `Backend` to provide keystore_key label lookup functionality.
+pub struct KeystoreKeyBackend {
+    handle: *mut selinux::selabel_handle,
+}
+
+// KeystoreKeyBackend is Sync because selabel_lookup is thread safe.
+unsafe impl Sync for KeystoreKeyBackend {}
+unsafe impl Send for KeystoreKeyBackend {}
+
+impl KeystoreKeyBackend {
+    const BACKEND_TYPE: i32 = SELABEL_CTX_ANDROID_KEYSTORE2_KEY as i32;
+
+    /// Creates a new instance representing an SELinux context handle as returned by
+    /// `selinux_android_keystore2_key_context_handle`.
+    pub fn new() -> Result<Self> {
+        init_logger_once();
+        let handle = unsafe { selinux::selinux_android_keystore2_key_context_handle() };
+        if handle.is_null() {
+            return Err(anyhow!(Error::sys("Failed to open KeystoreKeyBackend")));
+        }
+        Ok(KeystoreKeyBackend { handle })
+    }
+}
+
+impl Drop for KeystoreKeyBackend {
+    fn drop(&mut self) {
+        // No need to initialize the logger here because it cannot be called unless
+        // KeystoreKeyBackend::new has run.
+        unsafe { selinux::selabel_close(self.handle) };
+    }
+}
+
+// Because KeystoreKeyBackend is Sync and Send, member function must never call
+// non thread safe libselinux functions. As of this writing no non thread safe
+// functions exist that could be called on a label backend handle.
+impl Backend for KeystoreKeyBackend {
+    fn lookup(&self, key: &str) -> Result<Context> {
+        let mut con: *mut c_char = ptr::null_mut();
+        let c_key = CString::new(key).with_context(|| {
+            format!("selabel_lookup: Failed to convert key \"{}\" to CString.", key)
+        })?;
+        match unsafe {
+            // No need to initialize the logger here because it cannot run unless
+            // KeystoreKeyBackend::new has run.
+            selinux::selabel_lookup(self.handle, &mut con, c_key.as_ptr(), Self::BACKEND_TYPE)
+        } {
+            0 => {
+                if !con.is_null() {
+                    Ok(Context::Raw(con))
+                } else {
+                    Err(anyhow!(Error::sys(format!(
+                        "selabel_lookup returned a NULL context for key \"{}\"",
+                        key
+                    ))))
+                }
+            }
+            _ => Err(anyhow!(io::Error::last_os_error()))
+                .with_context(|| format!("selabel_lookup failed for key \"{}\"", key)),
+        }
+    }
+}
+
+/// Safe wrapper around libselinux `getcon`. It initializes the `Context::Raw` variant of the
+/// returned `Context`.
+///
+/// ## Return
+///  * Ok(Context::Raw()) if successful.
+///  * Err(Error::sys()) if getcon succeeded but returned a NULL pointer.
+///  * Err(io::Error::last_os_error()) if getcon failed.
+pub fn getcon() -> Result<Context> {
+    init_logger_once();
+    let mut con: *mut c_char = ptr::null_mut();
+    match unsafe { selinux::getcon(&mut con) } {
+        0 => {
+            if !con.is_null() {
+                Ok(Context::Raw(con))
+            } else {
+                Err(anyhow!(Error::sys("getcon returned a NULL context")))
+            }
+        }
+        _ => Err(anyhow!(io::Error::last_os_error())).context("getcon failed"),
+    }
+}
+
+/// Safe wrapper around selinux_check_access.
+///
+/// ## Return
+///  * Ok(()) iff the requested access was granted.
+///  * Err(anyhow!(Error::perm()))) if the permission was denied.
+///  * Err(anyhow!(ioError::last_os_error())) if any other error occurred while performing
+///            the access check.
+pub fn check_access(source: &Context, target: &Context, tclass: &str, perm: &str) -> Result<()> {
+    init_logger_once();
+    let c_tclass = CString::new(tclass).with_context(|| {
+        format!("check_access: Failed to convert tclass \"{}\" to CString.", tclass)
+    })?;
+    let c_perm = CString::new(perm).with_context(|| {
+        format!("check_access: Failed to convert perm \"{}\" to CString.", perm)
+    })?;
+
+    match unsafe {
+        selinux::selinux_check_access(
+            source.as_ptr(),
+            target.as_ptr(),
+            c_tclass.as_ptr(),
+            c_perm.as_ptr(),
+            ptr::null_mut(),
+        )
+    } {
+        0 => Ok(()),
+        _ => {
+            let e = io::Error::last_os_error();
+            match e.kind() {
+                io::ErrorKind::PermissionDenied => Err(anyhow!(Error::perm())),
+                _ => Err(anyhow!(e)),
+            }
+            .with_context(|| {
+                format!(
+                    concat!(
+                        "check_access: Failed with sctx: {} tctx: {}",
+                        " with target class: \"{}\" perm: \"{}\""
+                    ),
+                    source, target, tclass, perm
+                )
+            })
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use anyhow::Result;
+
+    /// The su_key namespace as defined in su.te and keystore_key_contexts of the
+    /// SePolicy (system/sepolicy).
+    static SU_KEY_NAMESPACE: &str = "0";
+    /// The shell_key namespace as defined in shell.te and keystore_key_contexts of the
+    /// SePolicy (system/sepolicy).
+    static SHELL_KEY_NAMESPACE: &str = "1";
+
+    fn check_context() -> Result<(Context, &'static str, bool)> {
+        let context = getcon()?;
+        match context.to_str().unwrap() {
+            "u:r:su:s0" => Ok((context, SU_KEY_NAMESPACE, true)),
+            "u:r:shell:s0" => Ok((context, SHELL_KEY_NAMESPACE, false)),
+            c => Err(anyhow!(format!(
+                "This test must be run as \"su\" or \"shell\". Current context: \"{}\"",
+                c
+            ))),
+        }
+    }
+
+    #[test]
+    fn test_getcon() -> Result<()> {
+        check_context()?;
+        Ok(())
+    }
+
+    #[test]
+    fn test_label_lookup() -> Result<()> {
+        let (_context, namespace, is_su) = check_context()?;
+        let backend = crate::KeystoreKeyBackend::new()?;
+        let context = backend.lookup(namespace)?;
+        if is_su {
+            assert_eq!(context.to_str(), Ok("u:object_r:su_key:s0"));
+        } else {
+            assert_eq!(context.to_str(), Ok("u:object_r:shell_key:s0"));
+        }
+        Ok(())
+    }
+
+    #[test]
+    fn context_from_string() -> Result<()> {
+        let tctx = Context::new("u:object_r:keystore:s0").unwrap();
+        let sctx = Context::new("u:r:system_server:s0").unwrap();
+        check_access(&sctx, &tctx, "keystore2_key", "use")?;
+        Ok(())
+    }
+
+    mod perm {
+        use super::super::*;
+        use super::*;
+        use anyhow::Result;
+
+        /// check_key_perm(perm, privileged, priv_domain)
+        /// `perm` is a permission of the keystore2_key class and `privileged` is a boolean
+        /// indicating whether the permission is considered privileged.
+        /// Privileged permissions are expeced to be denied to `shell` users but granted
+        /// to the given priv_domain.
+        macro_rules! check_key_perm {
+            // "use" is a keyword and cannot be used as an identifier, but we must keep
+            // the permission string intact. So we map the identifier name on use_ while using
+            // the permission string "use". In all other cases we can simply use the stringified
+            // identifier as permission string.
+            (use, $privileged:expr) => {
+                check_key_perm!(use_, $privileged, "use");
+            };
+            ($perm:ident, $privileged:expr) => {
+                check_key_perm!($perm, $privileged, stringify!($perm));
+            };
+            ($perm:ident, $privileged:expr, $p_str:expr) => {
+                #[test]
+                fn $perm() -> Result<()> {
+                    android_logger::init_once(
+                        android_logger::Config::default()
+                            .with_tag("keystore_selinux_tests")
+                            .with_min_level(log::Level::Debug),
+                    );
+                    let scontext = Context::new("u:r:shell:s0")?;
+                    let backend = KeystoreKeyBackend::new()?;
+                    let tcontext = backend.lookup(SHELL_KEY_NAMESPACE)?;
+
+                    if $privileged {
+                        assert_eq!(
+                            Some(&Error::perm()),
+                            check_access(
+                                &scontext,
+                                &tcontext,
+                                "keystore2_key",
+                                $p_str
+                            )
+                            .err()
+                            .unwrap()
+                            .root_cause()
+                            .downcast_ref::<Error>()
+                        );
+                    } else {
+                        assert!(check_access(
+                            &scontext,
+                            &tcontext,
+                            "keystore2_key",
+                            $p_str
+                        )
+                        .is_ok());
+                    }
+                    Ok(())
+                }
+            };
+        }
+
+        check_key_perm!(manage_blob, true);
+        check_key_perm!(delete, false);
+        check_key_perm!(use_dev_id, true);
+        check_key_perm!(req_forced_op, true);
+        check_key_perm!(gen_unique_id, true);
+        check_key_perm!(grant, true);
+        check_key_perm!(get_info, false);
+        check_key_perm!(list, false);
+        check_key_perm!(rebind, false);
+        check_key_perm!(update, false);
+        check_key_perm!(use, false);
+
+        macro_rules! check_keystore_perm {
+            ($perm:ident) => {
+                #[test]
+                fn $perm() -> Result<()> {
+                    let ks_context = Context::new("u:object_r:keystore:s0")?;
+                    let priv_context = Context::new("u:r:system_server:s0")?;
+                    let unpriv_context = Context::new("u:r:shell:s0")?;
+                    assert!(check_access(
+                        &priv_context,
+                        &ks_context,
+                        "keystore2",
+                        stringify!($perm)
+                    )
+                    .is_ok());
+                    assert_eq!(
+                        Some(&Error::perm()),
+                        check_access(&unpriv_context, &ks_context, "keystore2", stringify!($perm))
+                            .err()
+                            .unwrap()
+                            .root_cause()
+                            .downcast_ref::<Error>()
+                    );
+                    Ok(())
+                }
+            };
+        }
+
+        check_keystore_perm!(add_auth);
+        check_keystore_perm!(clear_ns);
+        check_keystore_perm!(get_state);
+        check_keystore_perm!(lock);
+        check_keystore_perm!(reset);
+        check_keystore_perm!(unlock);
+    }
+}
diff --git a/keystore2/src/aidl_generated.rs b/keystore2/src/aidl_generated.rs
new file mode 100644
index 0000000..4b6a844
--- /dev/null
+++ b/keystore2/src/aidl_generated.rs
@@ -0,0 +1,99 @@
+// Copyright 2020, 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.
+
+#![allow(missing_docs)]
+
+//! This crate holds types that we are depending on and will be generated by the AIDL
+//! compiler.
+
+use std::cmp::PartialEq;
+use std::fmt;
+
+#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
+pub struct Result {
+    pub rc: ResponseCode,
+    pub km_error_code: i32,
+}
+
+impl fmt::Display for Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{:?}", self)
+    }
+}
+
+#[repr(i32)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
+pub enum ResponseCode {
+    Ok = 0,
+    // 1 Reserved - formerly NO_ERROR
+    Locked = 2,
+    Uninitialized = 3,
+    SystemError = 4,
+    // 5 Reserved - formerly "protocol error" was never used
+    PermissionDenied = 6,
+    KeyNotFound = 7,
+    ValueCorrupted = 8,
+    // 9 Reserved - formerly "undefined action" was never used
+    WrongPassword = 10,
+    // 11 - 13 Reserved - formerly password retry count indicators: obsolete
+    //
+    // 14 Reserved - formerly SIGNATURE_INVALID: Keystore does not perform public key
+    //               operations any more.
+
+    // Indicates to the caller that user authorization is required before the operation may
+    // commence.
+    OpAuthNeeded = 15,
+    // 16 Reserved
+    KeyPermanentlyInvalidated = 17,
+    NoSuchSecurityLevel = 18,
+    KeymintErrorCode = 19,
+    BackendBusy = 20,
+}
+
+pub type ErrorCode = i32;
+
+#[repr(i32)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
+pub enum KeyPermission {
+    None = 0,
+    Delete = 1,
+    GenUniqueId = 2,
+    GetInfo = 4,
+    Grant = 8,
+    List = 0x10,
+    ManageBlob = 0x20,
+    Rebind = 0x40,
+    ReqForcedOp = 0x80,
+    Update = 0x100,
+    Use = 0x200,
+    UseDevId = 0x400,
+}
+
+#[repr(i32)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
+pub enum Domain {
+    App = 0,
+    Grant = 1,
+    SELinux = 2,
+    Blob = 3,
+    KeyId = 4,
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
+pub struct KeyDescriptor {
+    pub domain: Domain,
+    pub namespace_: i64,
+    pub alias: Option<String>,
+    pub blob: Option<Vec<u8>>,
+}
diff --git a/keystore2/src/android_hardware_keymint.rs b/keystore2/src/android_hardware_keymint.rs
new file mode 100644
index 0000000..dcdf87f
--- /dev/null
+++ b/keystore2/src/android_hardware_keymint.rs
@@ -0,0 +1,1639 @@
+#![allow(non_snake_case)]
+#![allow(missing_docs)]
+#![allow(clippy::identity_op)]
+#![allow(clippy::excessive_precision)]
+#![allow(clippy::too_many_arguments)]
+pub use binder::public_api as binder;
+pub mod aidl {
+  pub mod android {
+    pub mod hardware {
+      pub mod keymint {
+        pub mod Algorithm {
+          #![allow(non_upper_case_globals)]
+          pub type Algorithm = i32;
+          pub const RSA: Algorithm = 1;
+          pub const EC: Algorithm = 3;
+          pub const AES: Algorithm = 32;
+          pub const TRIPLE_DES: Algorithm = 33;
+          pub const HMAC: Algorithm = 128;
+          pub(crate) mod mangled { pub use super::Algorithm as _7_android_8_hardware_7_keymint_9_Algorithm; }
+        }
+        pub mod BeginResult {
+          pub struct BeginResult {
+            pub challenge: i64, 
+            pub params: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter>, 
+            pub operation: Option<Box<dyn crate::mangled::_7_android_8_hardware_7_keymint_17_IKeyMintOperation>>, 
+          }
+          pub(crate) mod mangled { pub use super::BeginResult as _7_android_8_hardware_7_keymint_11_BeginResult; }
+          impl Default for BeginResult {
+            fn default() -> Self {
+              Self {
+                challenge: 0,
+                params: Default::default(),
+                operation: Default::default(),
+              }
+            }
+          }
+          impl binder::parcel::Serialize for BeginResult {
+            fn serialize(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
+              <Self as binder::parcel::SerializeOption>::serialize_option(Some(self), parcel)
+            }
+          }
+          impl binder::parcel::SerializeArray for BeginResult {}
+          impl binder::parcel::SerializeOption for BeginResult {
+            fn serialize_option(this: Option<&Self>, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
+              let this = if let Some(this) = this {
+                parcel.write(&1i32)?;
+                this
+              } else {
+                return parcel.write(&0i32);
+              };
+              let start_pos = parcel.get_data_position();
+              parcel.write(&0i32)?;
+              parcel.write(&this.challenge)?;
+              parcel.write(&this.params)?;
+              let __field_ref = this.operation.as_ref().ok_or(binder::StatusCode::UNEXPECTED_NULL)?;
+              parcel.write(__field_ref)?;
+              let end_pos = parcel.get_data_position();
+              let parcelable_size = (end_pos - start_pos) as i32;
+              unsafe { parcel.set_data_position(start_pos)?; }
+              parcel.write(&parcelable_size)?;
+              unsafe { parcel.set_data_position(end_pos)?; }
+              Ok(())
+            }
+          }
+          impl binder::parcel::Deserialize for BeginResult {
+            fn deserialize(parcel: &binder::parcel::Parcel) -> binder::Result<Self> {
+              <Self as binder::parcel::DeserializeOption>::deserialize_option(parcel)
+                 .transpose()
+                 .unwrap_or(Err(binder::StatusCode::UNEXPECTED_NULL))
+            }
+          }
+          impl binder::parcel::DeserializeArray for BeginResult {}
+          impl binder::parcel::DeserializeOption for BeginResult {
+            fn deserialize_option(parcel: &binder::parcel::Parcel) -> binder::Result<Option<Self>> {
+              let status: i32 = parcel.read()?;
+              if status == 0 { return Ok(None); }
+              let start_pos = parcel.get_data_position();
+              let parcelable_size: i32 = parcel.read()?;
+              if parcelable_size < 0 { return Err(binder::StatusCode::BAD_VALUE); }
+              let mut result = Self::default();
+              result.challenge = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) >= parcelable_size {
+                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
+                return Ok(Some(result));
+              }
+              result.params = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) >= parcelable_size {
+                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
+                return Ok(Some(result));
+              }
+              result.operation = Some(parcel.read()?);
+              if (parcel.get_data_position() - start_pos) >= parcelable_size {
+                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
+                return Ok(Some(result));
+              }
+              Ok(Some(result))
+            }
+          }
+        }
+        pub mod BlockMode {
+          #![allow(non_upper_case_globals)]
+          pub type BlockMode = i32;
+          pub const ECB: BlockMode = 1;
+          pub const CBC: BlockMode = 2;
+          pub const CTR: BlockMode = 3;
+          pub const GCM: BlockMode = 32;
+          pub(crate) mod mangled { pub use super::BlockMode as _7_android_8_hardware_7_keymint_9_BlockMode; }
+        }
+        pub mod Certificate {
+          pub struct Certificate {
+            pub encodedCertificate: Vec<u8>, 
+          }
+          pub(crate) mod mangled { pub use super::Certificate as _7_android_8_hardware_7_keymint_11_Certificate; }
+          impl Default for Certificate {
+            fn default() -> Self {
+              Self {
+                encodedCertificate: Default::default(),
+              }
+            }
+          }
+          impl binder::parcel::Serialize for Certificate {
+            fn serialize(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
+              <Self as binder::parcel::SerializeOption>::serialize_option(Some(self), parcel)
+            }
+          }
+          impl binder::parcel::SerializeArray for Certificate {}
+          impl binder::parcel::SerializeOption for Certificate {
+            fn serialize_option(this: Option<&Self>, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
+              let this = if let Some(this) = this {
+                parcel.write(&1i32)?;
+                this
+              } else {
+                return parcel.write(&0i32);
+              };
+              let start_pos = parcel.get_data_position();
+              parcel.write(&0i32)?;
+              parcel.write(&this.encodedCertificate)?;
+              let end_pos = parcel.get_data_position();
+              let parcelable_size = (end_pos - start_pos) as i32;
+              unsafe { parcel.set_data_position(start_pos)?; }
+              parcel.write(&parcelable_size)?;
+              unsafe { parcel.set_data_position(end_pos)?; }
+              Ok(())
+            }
+          }
+          impl binder::parcel::Deserialize for Certificate {
+            fn deserialize(parcel: &binder::parcel::Parcel) -> binder::Result<Self> {
+              <Self as binder::parcel::DeserializeOption>::deserialize_option(parcel)
+                 .transpose()
+                 .unwrap_or(Err(binder::StatusCode::UNEXPECTED_NULL))
+            }
+          }
+          impl binder::parcel::DeserializeArray for Certificate {}
+          impl binder::parcel::DeserializeOption for Certificate {
+            fn deserialize_option(parcel: &binder::parcel::Parcel) -> binder::Result<Option<Self>> {
+              let status: i32 = parcel.read()?;
+              if status == 0 { return Ok(None); }
+              let start_pos = parcel.get_data_position();
+              let parcelable_size: i32 = parcel.read()?;
+              if parcelable_size < 0 { return Err(binder::StatusCode::BAD_VALUE); }
+              let mut result = Self::default();
+              result.encodedCertificate = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) >= parcelable_size {
+                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
+                return Ok(Some(result));
+              }
+              Ok(Some(result))
+            }
+          }
+        }
+        pub mod Constants {
+          #![allow(non_upper_case_globals)]
+          pub type Constants = i32;
+          pub const AUTH_TOKEN_MAC_LENGTH: Constants = 32;
+          pub(crate) mod mangled { pub use super::Constants as _7_android_8_hardware_7_keymint_9_Constants; }
+        }
+        pub mod Digest {
+          #![allow(non_upper_case_globals)]
+          pub type Digest = i32;
+          pub const NONE: Digest = 0;
+          pub const MD5: Digest = 1;
+          pub const SHA1: Digest = 2;
+          pub const SHA_2_224: Digest = 3;
+          pub const SHA_2_256: Digest = 4;
+          pub const SHA_2_384: Digest = 5;
+          pub const SHA_2_512: Digest = 6;
+          pub(crate) mod mangled { pub use super::Digest as _7_android_8_hardware_7_keymint_6_Digest; }
+        }
+        pub mod EcCurve {
+          #![allow(non_upper_case_globals)]
+          pub type EcCurve = i32;
+          pub const P_224: EcCurve = 0;
+          pub const P_256: EcCurve = 1;
+          pub const P_384: EcCurve = 2;
+          pub const P_521: EcCurve = 3;
+          pub(crate) mod mangled { pub use super::EcCurve as _7_android_8_hardware_7_keymint_7_EcCurve; }
+        }
+        pub mod ErrorCode {
+          #![allow(non_upper_case_globals)]
+          pub type ErrorCode = i32;
+          pub const OK: ErrorCode = 0;
+          pub const ROOT_OF_TRUST_ALREADY_SET: ErrorCode = -1;
+          pub const UNSUPPORTED_PURPOSE: ErrorCode = -2;
+          pub const INCOMPATIBLE_PURPOSE: ErrorCode = -3;
+          pub const UNSUPPORTED_ALGORITHM: ErrorCode = -4;
+          pub const INCOMPATIBLE_ALGORITHM: ErrorCode = -5;
+          pub const UNSUPPORTED_KEY_SIZE: ErrorCode = -6;
+          pub const UNSUPPORTED_BLOCK_MODE: ErrorCode = -7;
+          pub const INCOMPATIBLE_BLOCK_MODE: ErrorCode = -8;
+          pub const UNSUPPORTED_MAC_LENGTH: ErrorCode = -9;
+          pub const UNSUPPORTED_PADDING_MODE: ErrorCode = -10;
+          pub const INCOMPATIBLE_PADDING_MODE: ErrorCode = -11;
+          pub const UNSUPPORTED_DIGEST: ErrorCode = -12;
+          pub const INCOMPATIBLE_DIGEST: ErrorCode = -13;
+          pub const INVALID_EXPIRATION_TIME: ErrorCode = -14;
+          pub const INVALID_USER_ID: ErrorCode = -15;
+          pub const INVALID_AUTHORIZATION_TIMEOUT: ErrorCode = -16;
+          pub const UNSUPPORTED_KEY_FORMAT: ErrorCode = -17;
+          pub const INCOMPATIBLE_KEY_FORMAT: ErrorCode = -18;
+          pub const UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM: ErrorCode = -19;
+          pub const UNSUPPORTED_KEY_VERIFICATION_ALGORITHM: ErrorCode = -20;
+          pub const INVALID_INPUT_LENGTH: ErrorCode = -21;
+          pub const KEY_EXPORT_OPTIONS_INVALID: ErrorCode = -22;
+          pub const DELEGATION_NOT_ALLOWED: ErrorCode = -23;
+          pub const KEY_NOT_YET_VALID: ErrorCode = -24;
+          pub const KEY_EXPIRED: ErrorCode = -25;
+          pub const KEY_USER_NOT_AUTHENTICATED: ErrorCode = -26;
+          pub const OUTPUT_PARAMETER_NULL: ErrorCode = -27;
+          pub const INVALID_OPERATION_HANDLE: ErrorCode = -28;
+          pub const INSUFFICIENT_BUFFER_SPACE: ErrorCode = -29;
+          pub const VERIFICATION_FAILED: ErrorCode = -30;
+          pub const TOO_MANY_OPERATIONS: ErrorCode = -31;
+          pub const UNEXPECTED_NULL_POINTER: ErrorCode = -32;
+          pub const INVALID_KEY_BLOB: ErrorCode = -33;
+          pub const IMPORTED_KEY_NOT_ENCRYPTED: ErrorCode = -34;
+          pub const IMPORTED_KEY_DECRYPTION_FAILED: ErrorCode = -35;
+          pub const IMPORTED_KEY_NOT_SIGNED: ErrorCode = -36;
+          pub const IMPORTED_KEY_VERIFICATION_FAILED: ErrorCode = -37;
+          pub const INVALID_ARGUMENT: ErrorCode = -38;
+          pub const UNSUPPORTED_TAG: ErrorCode = -39;
+          pub const INVALID_TAG: ErrorCode = -40;
+          pub const MEMORY_ALLOCATION_FAILED: ErrorCode = -41;
+          pub const IMPORT_PARAMETER_MISMATCH: ErrorCode = -44;
+          pub const SECURE_HW_ACCESS_DENIED: ErrorCode = -45;
+          pub const OPERATION_CANCELLED: ErrorCode = -46;
+          pub const CONCURRENT_ACCESS_CONFLICT: ErrorCode = -47;
+          pub const SECURE_HW_BUSY: ErrorCode = -48;
+          pub const SECURE_HW_COMMUNICATION_FAILED: ErrorCode = -49;
+          pub const UNSUPPORTED_EC_FIELD: ErrorCode = -50;
+          pub const MISSING_NONCE: ErrorCode = -51;
+          pub const INVALID_NONCE: ErrorCode = -52;
+          pub const MISSING_MAC_LENGTH: ErrorCode = -53;
+          pub const KEY_RATE_LIMIT_EXCEEDED: ErrorCode = -54;
+          pub const CALLER_NONCE_PROHIBITED: ErrorCode = -55;
+          pub const KEY_MAX_OPS_EXCEEDED: ErrorCode = -56;
+          pub const INVALID_MAC_LENGTH: ErrorCode = -57;
+          pub const MISSING_MIN_MAC_LENGTH: ErrorCode = -58;
+          pub const UNSUPPORTED_MIN_MAC_LENGTH: ErrorCode = -59;
+          pub const UNSUPPORTED_KDF: ErrorCode = -60;
+          pub const UNSUPPORTED_EC_CURVE: ErrorCode = -61;
+          pub const KEY_REQUIRES_UPGRADE: ErrorCode = -62;
+          pub const ATTESTATION_CHALLENGE_MISSING: ErrorCode = -63;
+          pub const KEYMASTER_NOT_CONFIGURED: ErrorCode = -64;
+          pub const ATTESTATION_APPLICATION_ID_MISSING: ErrorCode = -65;
+          pub const CANNOT_ATTEST_IDS: ErrorCode = -66;
+          pub const ROLLBACK_RESISTANCE_UNAVAILABLE: ErrorCode = -67;
+          pub const HARDWARE_TYPE_UNAVAILABLE: ErrorCode = -68;
+          pub const PROOF_OF_PRESENCE_REQUIRED: ErrorCode = -69;
+          pub const CONCURRENT_PROOF_OF_PRESENCE_REQUESTED: ErrorCode = -70;
+          pub const NO_USER_CONFIRMATION: ErrorCode = -71;
+          pub const DEVICE_LOCKED: ErrorCode = -72;
+          pub const EARLY_BOOT_ENDED: ErrorCode = -73;
+          pub const ATTESTATION_KEYS_NOT_PROVISIONED: ErrorCode = -74;
+          pub const ATTESTATION_IDS_NOT_PROVISIONED: ErrorCode = -75;
+          pub const INVALID_OPERATION: ErrorCode = -76;
+          pub const STORAGE_KEY_UNSUPPORTED: ErrorCode = -77;
+          pub const UNIMPLEMENTED: ErrorCode = -100;
+          pub const VERSION_MISMATCH: ErrorCode = -101;
+          pub const UNKNOWN_ERROR: ErrorCode = -1000;
+          pub(crate) mod mangled { pub use super::ErrorCode as _7_android_8_hardware_7_keymint_9_ErrorCode; }
+        }
+        pub mod HardwareAuthToken {
+          pub struct HardwareAuthToken {
+            pub challenge: i64, 
+            pub userId: i64, 
+            pub authenticatorId: i64, 
+            pub authenticatorType: crate::mangled::_7_android_8_hardware_7_keymint_25_HardwareAuthenticatorType, 
+            pub timestamp: crate::mangled::_7_android_8_hardware_7_keymint_9_Timestamp, 
+            pub mac: Vec<u8>, 
+          }
+          pub(crate) mod mangled { pub use super::HardwareAuthToken as _7_android_8_hardware_7_keymint_17_HardwareAuthToken; }
+          impl Default for HardwareAuthToken {
+            fn default() -> Self {
+              Self {
+                challenge: 0,
+                userId: 0,
+                authenticatorId: 0,
+                authenticatorType: Default::default(),
+                timestamp: Default::default(),
+                mac: Default::default(),
+              }
+            }
+          }
+          impl binder::parcel::Serialize for HardwareAuthToken {
+            fn serialize(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
+              <Self as binder::parcel::SerializeOption>::serialize_option(Some(self), parcel)
+            }
+          }
+          impl binder::parcel::SerializeArray for HardwareAuthToken {}
+          impl binder::parcel::SerializeOption for HardwareAuthToken {
+            fn serialize_option(this: Option<&Self>, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
+              let this = if let Some(this) = this {
+                parcel.write(&1i32)?;
+                this
+              } else {
+                return parcel.write(&0i32);
+              };
+              let start_pos = parcel.get_data_position();
+              parcel.write(&0i32)?;
+              parcel.write(&this.challenge)?;
+              parcel.write(&this.userId)?;
+              parcel.write(&this.authenticatorId)?;
+              parcel.write(&this.authenticatorType)?;
+              parcel.write(&this.timestamp)?;
+              parcel.write(&this.mac)?;
+              let end_pos = parcel.get_data_position();
+              let parcelable_size = (end_pos - start_pos) as i32;
+              unsafe { parcel.set_data_position(start_pos)?; }
+              parcel.write(&parcelable_size)?;
+              unsafe { parcel.set_data_position(end_pos)?; }
+              Ok(())
+            }
+          }
+          impl binder::parcel::Deserialize for HardwareAuthToken {
+            fn deserialize(parcel: &binder::parcel::Parcel) -> binder::Result<Self> {
+              <Self as binder::parcel::DeserializeOption>::deserialize_option(parcel)
+                 .transpose()
+                 .unwrap_or(Err(binder::StatusCode::UNEXPECTED_NULL))
+            }
+          }
+          impl binder::parcel::DeserializeArray for HardwareAuthToken {}
+          impl binder::parcel::DeserializeOption for HardwareAuthToken {
+            fn deserialize_option(parcel: &binder::parcel::Parcel) -> binder::Result<Option<Self>> {
+              let status: i32 = parcel.read()?;
+              if status == 0 { return Ok(None); }
+              let start_pos = parcel.get_data_position();
+              let parcelable_size: i32 = parcel.read()?;
+              if parcelable_size < 0 { return Err(binder::StatusCode::BAD_VALUE); }
+              let mut result = Self::default();
+              result.challenge = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) >= parcelable_size {
+                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
+                return Ok(Some(result));
+              }
+              result.userId = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) >= parcelable_size {
+                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
+                return Ok(Some(result));
+              }
+              result.authenticatorId = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) >= parcelable_size {
+                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
+                return Ok(Some(result));
+              }
+              result.authenticatorType = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) >= parcelable_size {
+                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
+                return Ok(Some(result));
+              }
+              result.timestamp = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) >= parcelable_size {
+                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
+                return Ok(Some(result));
+              }
+              result.mac = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) >= parcelable_size {
+                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
+                return Ok(Some(result));
+              }
+              Ok(Some(result))
+            }
+          }
+        }
+        pub mod HardwareAuthenticatorType {
+          #![allow(non_upper_case_globals)]
+          pub type HardwareAuthenticatorType = i32;
+          pub const NONE: HardwareAuthenticatorType = 0;
+          pub const PASSWORD: HardwareAuthenticatorType = 1;
+          pub const FINGERPRINT: HardwareAuthenticatorType = 2;
+          pub const ANY: HardwareAuthenticatorType = -1;
+          pub(crate) mod mangled { pub use super::HardwareAuthenticatorType as _7_android_8_hardware_7_keymint_25_HardwareAuthenticatorType; }
+        }
+        pub mod HmacSharingParameters {
+          pub struct HmacSharingParameters {
+            pub seed: Vec<u8>, 
+            pub nonce: Vec<u8>, 
+          }
+          pub(crate) mod mangled { pub use super::HmacSharingParameters as _7_android_8_hardware_7_keymint_21_HmacSharingParameters; }
+          impl Default for HmacSharingParameters {
+            fn default() -> Self {
+              Self {
+                seed: Default::default(),
+                nonce: Default::default(),
+              }
+            }
+          }
+          impl binder::parcel::Serialize for HmacSharingParameters {
+            fn serialize(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
+              <Self as binder::parcel::SerializeOption>::serialize_option(Some(self), parcel)
+            }
+          }
+          impl binder::parcel::SerializeArray for HmacSharingParameters {}
+          impl binder::parcel::SerializeOption for HmacSharingParameters {
+            fn serialize_option(this: Option<&Self>, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
+              let this = if let Some(this) = this {
+                parcel.write(&1i32)?;
+                this
+              } else {
+                return parcel.write(&0i32);
+              };
+              let start_pos = parcel.get_data_position();
+              parcel.write(&0i32)?;
+              parcel.write(&this.seed)?;
+              parcel.write(&this.nonce)?;
+              let end_pos = parcel.get_data_position();
+              let parcelable_size = (end_pos - start_pos) as i32;
+              unsafe { parcel.set_data_position(start_pos)?; }
+              parcel.write(&parcelable_size)?;
+              unsafe { parcel.set_data_position(end_pos)?; }
+              Ok(())
+            }
+          }
+          impl binder::parcel::Deserialize for HmacSharingParameters {
+            fn deserialize(parcel: &binder::parcel::Parcel) -> binder::Result<Self> {
+              <Self as binder::parcel::DeserializeOption>::deserialize_option(parcel)
+                 .transpose()
+                 .unwrap_or(Err(binder::StatusCode::UNEXPECTED_NULL))
+            }
+          }
+          impl binder::parcel::DeserializeArray for HmacSharingParameters {}
+          impl binder::parcel::DeserializeOption for HmacSharingParameters {
+            fn deserialize_option(parcel: &binder::parcel::Parcel) -> binder::Result<Option<Self>> {
+              let status: i32 = parcel.read()?;
+              if status == 0 { return Ok(None); }
+              let start_pos = parcel.get_data_position();
+              let parcelable_size: i32 = parcel.read()?;
+              if parcelable_size < 0 { return Err(binder::StatusCode::BAD_VALUE); }
+              let mut result = Self::default();
+              result.seed = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) >= parcelable_size {
+                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
+                return Ok(Some(result));
+              }
+              result.nonce = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) >= parcelable_size {
+                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
+                return Ok(Some(result));
+              }
+              Ok(Some(result))
+            }
+          }
+        }
+        pub mod IKeyMintDevice {
+          #![allow(non_upper_case_globals)]
+          #![allow(non_snake_case)]
+          #[allow(unused_imports)] use binder::IBinder;
+          use binder::declare_binder_interface;
+          declare_binder_interface! {
+            IKeyMintDevice["android.hardware.keymint.IKeyMintDevice"] {
+              native: BnKeyMintDevice(on_transact),
+              proxy: BpKeyMintDevice {
+              },
+            }
+          }
+          pub trait IKeyMintDevice: binder::Interface {
+            fn get_descriptor() -> &'static str where Self: Sized { "android.hardware.keymint.IKeyMintDevice" }
+            fn getHardwareInfo(&self) -> binder::public_api::Result<crate::mangled::_7_android_8_hardware_7_keymint_19_KeyMintHardwareInfo> {
+              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+            }
+            fn verifyAuthorization(&self, _arg_challenge: i64, _arg_parametersToVerify: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_token: &crate::mangled::_7_android_8_hardware_7_keymint_17_HardwareAuthToken) -> binder::public_api::Result<crate::mangled::_7_android_8_hardware_7_keymint_17_VerificationToken> {
+              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+            }
+            fn addRngEntropy(&self, _arg_data: &[u8]) -> binder::public_api::Result<()> {
+              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+            }
+            fn generateKey(&self, _arg_keyParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_generatedKeyBlob: &mut Vec<u8>, _arg_generatedKeyCharacteristics: &mut crate::mangled::_7_android_8_hardware_7_keymint_18_KeyCharacteristics, _arg_outCertChain: &mut Vec<crate::mangled::_7_android_8_hardware_7_keymint_11_Certificate>) -> binder::public_api::Result<()> {
+              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+            }
+            fn importKey(&self, _arg_inKeyParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_inKeyFormat: crate::mangled::_7_android_8_hardware_7_keymint_9_KeyFormat, _arg_inKeyData: &[u8], _arg_outImportedKeyBlob: &mut Vec<u8>, _arg_outImportedKeyCharacteristics: &mut crate::mangled::_7_android_8_hardware_7_keymint_18_KeyCharacteristics, _arg_outCertChain: &mut Vec<crate::mangled::_7_android_8_hardware_7_keymint_11_Certificate>) -> binder::public_api::Result<()> {
+              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+            }
+            fn importWrappedKey(&self, _arg_inWrappedKeyData: &[u8], _arg_inWrappingKeyBlob: &[u8], _arg_inMaskingKey: &[u8], _arg_inUnwrappingParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_inPasswordSid: i64, _arg_inBiometricSid: i64, _arg_outImportedKeyBlob: &mut Vec<u8>, _arg_outImportedKeyCharacteristics: &mut crate::mangled::_7_android_8_hardware_7_keymint_18_KeyCharacteristics) -> binder::public_api::Result<()> {
+              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+            }
+            fn upgradeKey(&self, _arg_inKeyBlobToUpgrade: &[u8], _arg_inUpgradeParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter]) -> binder::public_api::Result<Vec<u8>> {
+              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+            }
+            fn deleteKey(&self, _arg_inKeyBlob: &[u8]) -> binder::public_api::Result<()> {
+              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+            }
+            fn deleteAllKeys(&self) -> binder::public_api::Result<()> {
+              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+            }
+            fn destroyAttestationIds(&self) -> binder::public_api::Result<()> {
+              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+            }
+            fn begin(&self, _arg_inPurpose: crate::mangled::_7_android_8_hardware_7_keymint_10_KeyPurpose, _arg_inKeyBlob: &[u8], _arg_inParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_inAuthToken: &crate::mangled::_7_android_8_hardware_7_keymint_17_HardwareAuthToken) -> binder::public_api::Result<crate::mangled::_7_android_8_hardware_7_keymint_11_BeginResult> {
+              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+            }
+            fn getDefaultImpl() -> DefaultImpl where Self: Sized {
+              DEFAULT_IMPL.lock().unwrap().clone()
+            }
+            fn setDefaultImpl(d: DefaultImpl) -> DefaultImpl where Self: Sized {
+              std::mem::replace(&mut *DEFAULT_IMPL.lock().unwrap(), d)
+            }
+          }
+          pub const TRANSACTION_getHardwareInfo: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 0;
+          pub const TRANSACTION_verifyAuthorization: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 1;
+          pub const TRANSACTION_addRngEntropy: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 2;
+          pub const TRANSACTION_generateKey: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 3;
+          pub const TRANSACTION_importKey: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 4;
+          pub const TRANSACTION_importWrappedKey: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 5;
+          pub const TRANSACTION_upgradeKey: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 6;
+          pub const TRANSACTION_deleteKey: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 7;
+          pub const TRANSACTION_deleteAllKeys: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 8;
+          pub const TRANSACTION_destroyAttestationIds: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 9;
+          pub const TRANSACTION_begin: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 10;
+          pub type DefaultImpl = Option<std::sync::Arc<dyn IKeyMintDevice + Send + Sync>>;
+          use lazy_static::lazy_static;
+          lazy_static! {
+            static ref DEFAULT_IMPL: std::sync::Mutex<DefaultImpl> = std::sync::Mutex::new(None);
+          }
+          pub(crate) mod mangled { pub use super::IKeyMintDevice as _7_android_8_hardware_7_keymint_14_IKeyMintDevice; }
+          impl IKeyMintDevice for BpKeyMintDevice {
+            fn getHardwareInfo(&self) -> binder::public_api::Result<crate::mangled::_7_android_8_hardware_7_keymint_19_KeyMintHardwareInfo> {
+              let _aidl_reply = self.binder.transact(TRANSACTION_getHardwareInfo, 0, |_aidl_data| {
+                Ok(())
+              });
+              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+                if let Some(_aidl_default_impl) = <Self as IKeyMintDevice>::getDefaultImpl() {
+                  return _aidl_default_impl.getHardwareInfo();
+                }
+              }
+              let _aidl_reply = _aidl_reply?;
+              let _aidl_status: binder::Status = _aidl_reply.read()?;
+              if !_aidl_status.is_ok() { return Err(_aidl_status); }
+              let _aidl_return: crate::mangled::_7_android_8_hardware_7_keymint_19_KeyMintHardwareInfo = _aidl_reply.read()?;
+              Ok(_aidl_return)
+            }
+            fn verifyAuthorization(&self, _arg_challenge: i64, _arg_parametersToVerify: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_token: &crate::mangled::_7_android_8_hardware_7_keymint_17_HardwareAuthToken) -> binder::public_api::Result<crate::mangled::_7_android_8_hardware_7_keymint_17_VerificationToken> {
+              let _aidl_reply = self.binder.transact(TRANSACTION_verifyAuthorization, 0, |_aidl_data| {
+                _aidl_data.write(&_arg_challenge)?;
+                _aidl_data.write(_arg_parametersToVerify)?;
+                _aidl_data.write(_arg_token)?;
+                Ok(())
+              });
+              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+                if let Some(_aidl_default_impl) = <Self as IKeyMintDevice>::getDefaultImpl() {
+                  return _aidl_default_impl.verifyAuthorization(_arg_challenge, _arg_parametersToVerify, _arg_token);
+                }
+              }
+              let _aidl_reply = _aidl_reply?;
+              let _aidl_status: binder::Status = _aidl_reply.read()?;
+              if !_aidl_status.is_ok() { return Err(_aidl_status); }
+              let _aidl_return: crate::mangled::_7_android_8_hardware_7_keymint_17_VerificationToken = _aidl_reply.read()?;
+              Ok(_aidl_return)
+            }
+            fn addRngEntropy(&self, _arg_data: &[u8]) -> binder::public_api::Result<()> {
+              let _aidl_reply = self.binder.transact(TRANSACTION_addRngEntropy, 0, |_aidl_data| {
+                _aidl_data.write(_arg_data)?;
+                Ok(())
+              });
+              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+                if let Some(_aidl_default_impl) = <Self as IKeyMintDevice>::getDefaultImpl() {
+                  return _aidl_default_impl.addRngEntropy(_arg_data);
+                }
+              }
+              let _aidl_reply = _aidl_reply?;
+              let _aidl_status: binder::Status = _aidl_reply.read()?;
+              if !_aidl_status.is_ok() { return Err(_aidl_status); }
+              Ok(())
+            }
+            fn generateKey(&self, _arg_keyParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_generatedKeyBlob: &mut Vec<u8>, _arg_generatedKeyCharacteristics: &mut crate::mangled::_7_android_8_hardware_7_keymint_18_KeyCharacteristics, _arg_outCertChain: &mut Vec<crate::mangled::_7_android_8_hardware_7_keymint_11_Certificate>) -> binder::public_api::Result<()> {
+              let _aidl_reply = self.binder.transact(TRANSACTION_generateKey, 0, |_aidl_data| {
+                _aidl_data.write(_arg_keyParams)?;
+                _aidl_data.write_slice_size(Some(_arg_generatedKeyBlob))?;
+                _aidl_data.write_slice_size(Some(_arg_outCertChain))?;
+                Ok(())
+              });
+              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+                if let Some(_aidl_default_impl) = <Self as IKeyMintDevice>::getDefaultImpl() {
+                  return _aidl_default_impl.generateKey(_arg_keyParams, _arg_generatedKeyBlob, _arg_generatedKeyCharacteristics, _arg_outCertChain);
+                }
+              }
+              let _aidl_reply = _aidl_reply?;
+              let _aidl_status: binder::Status = _aidl_reply.read()?;
+              if !_aidl_status.is_ok() { return Err(_aidl_status); }
+              *_arg_generatedKeyBlob = _aidl_reply.read()?;
+              *_arg_generatedKeyCharacteristics = _aidl_reply.read()?;
+              *_arg_outCertChain = _aidl_reply.read()?;
+              Ok(())
+            }
+            fn importKey(&self, _arg_inKeyParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_inKeyFormat: crate::mangled::_7_android_8_hardware_7_keymint_9_KeyFormat, _arg_inKeyData: &[u8], _arg_outImportedKeyBlob: &mut Vec<u8>, _arg_outImportedKeyCharacteristics: &mut crate::mangled::_7_android_8_hardware_7_keymint_18_KeyCharacteristics, _arg_outCertChain: &mut Vec<crate::mangled::_7_android_8_hardware_7_keymint_11_Certificate>) -> binder::public_api::Result<()> {
+              let _aidl_reply = self.binder.transact(TRANSACTION_importKey, 0, |_aidl_data| {
+                _aidl_data.write(_arg_inKeyParams)?;
+                _aidl_data.write(&_arg_inKeyFormat)?;
+                _aidl_data.write(_arg_inKeyData)?;
+                _aidl_data.write_slice_size(Some(_arg_outImportedKeyBlob))?;
+                _aidl_data.write_slice_size(Some(_arg_outCertChain))?;
+                Ok(())
+              });
+              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+                if let Some(_aidl_default_impl) = <Self as IKeyMintDevice>::getDefaultImpl() {
+                  return _aidl_default_impl.importKey(_arg_inKeyParams, _arg_inKeyFormat, _arg_inKeyData, _arg_outImportedKeyBlob, _arg_outImportedKeyCharacteristics, _arg_outCertChain);
+                }
+              }
+              let _aidl_reply = _aidl_reply?;
+              let _aidl_status: binder::Status = _aidl_reply.read()?;
+              if !_aidl_status.is_ok() { return Err(_aidl_status); }
+              *_arg_outImportedKeyBlob = _aidl_reply.read()?;
+              *_arg_outImportedKeyCharacteristics = _aidl_reply.read()?;
+              *_arg_outCertChain = _aidl_reply.read()?;
+              Ok(())
+            }
+            fn importWrappedKey(&self, _arg_inWrappedKeyData: &[u8], _arg_inWrappingKeyBlob: &[u8], _arg_inMaskingKey: &[u8], _arg_inUnwrappingParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_inPasswordSid: i64, _arg_inBiometricSid: i64, _arg_outImportedKeyBlob: &mut Vec<u8>, _arg_outImportedKeyCharacteristics: &mut crate::mangled::_7_android_8_hardware_7_keymint_18_KeyCharacteristics) -> binder::public_api::Result<()> {
+              let _aidl_reply = self.binder.transact(TRANSACTION_importWrappedKey, 0, |_aidl_data| {
+                _aidl_data.write(_arg_inWrappedKeyData)?;
+                _aidl_data.write(_arg_inWrappingKeyBlob)?;
+                _aidl_data.write(_arg_inMaskingKey)?;
+                _aidl_data.write(_arg_inUnwrappingParams)?;
+                _aidl_data.write(&_arg_inPasswordSid)?;
+                _aidl_data.write(&_arg_inBiometricSid)?;
+                _aidl_data.write_slice_size(Some(_arg_outImportedKeyBlob))?;
+                Ok(())
+              });
+              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+                if let Some(_aidl_default_impl) = <Self as IKeyMintDevice>::getDefaultImpl() {
+                  return _aidl_default_impl.importWrappedKey(_arg_inWrappedKeyData, _arg_inWrappingKeyBlob, _arg_inMaskingKey, _arg_inUnwrappingParams, _arg_inPasswordSid, _arg_inBiometricSid, _arg_outImportedKeyBlob, _arg_outImportedKeyCharacteristics);
+                }
+              }
+              let _aidl_reply = _aidl_reply?;
+              let _aidl_status: binder::Status = _aidl_reply.read()?;
+              if !_aidl_status.is_ok() { return Err(_aidl_status); }
+              *_arg_outImportedKeyBlob = _aidl_reply.read()?;
+              *_arg_outImportedKeyCharacteristics = _aidl_reply.read()?;
+              Ok(())
+            }
+            fn upgradeKey(&self, _arg_inKeyBlobToUpgrade: &[u8], _arg_inUpgradeParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter]) -> binder::public_api::Result<Vec<u8>> {
+              let _aidl_reply = self.binder.transact(TRANSACTION_upgradeKey, 0, |_aidl_data| {
+                _aidl_data.write(_arg_inKeyBlobToUpgrade)?;
+                _aidl_data.write(_arg_inUpgradeParams)?;
+                Ok(())
+              });
+              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+                if let Some(_aidl_default_impl) = <Self as IKeyMintDevice>::getDefaultImpl() {
+                  return _aidl_default_impl.upgradeKey(_arg_inKeyBlobToUpgrade, _arg_inUpgradeParams);
+                }
+              }
+              let _aidl_reply = _aidl_reply?;
+              let _aidl_status: binder::Status = _aidl_reply.read()?;
+              if !_aidl_status.is_ok() { return Err(_aidl_status); }
+              let _aidl_return: Vec<u8> = _aidl_reply.read()?;
+              Ok(_aidl_return)
+            }
+            fn deleteKey(&self, _arg_inKeyBlob: &[u8]) -> binder::public_api::Result<()> {
+              let _aidl_reply = self.binder.transact(TRANSACTION_deleteKey, 0, |_aidl_data| {
+                _aidl_data.write(_arg_inKeyBlob)?;
+                Ok(())
+              });
+              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+                if let Some(_aidl_default_impl) = <Self as IKeyMintDevice>::getDefaultImpl() {
+                  return _aidl_default_impl.deleteKey(_arg_inKeyBlob);
+                }
+              }
+              let _aidl_reply = _aidl_reply?;
+              let _aidl_status: binder::Status = _aidl_reply.read()?;
+              if !_aidl_status.is_ok() { return Err(_aidl_status); }
+              Ok(())
+            }
+            fn deleteAllKeys(&self) -> binder::public_api::Result<()> {
+              let _aidl_reply = self.binder.transact(TRANSACTION_deleteAllKeys, 0, |_aidl_data| {
+                Ok(())
+              });
+              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+                if let Some(_aidl_default_impl) = <Self as IKeyMintDevice>::getDefaultImpl() {
+                  return _aidl_default_impl.deleteAllKeys();
+                }
+              }
+              let _aidl_reply = _aidl_reply?;
+              let _aidl_status: binder::Status = _aidl_reply.read()?;
+              if !_aidl_status.is_ok() { return Err(_aidl_status); }
+              Ok(())
+            }
+            fn destroyAttestationIds(&self) -> binder::public_api::Result<()> {
+              let _aidl_reply = self.binder.transact(TRANSACTION_destroyAttestationIds, 0, |_aidl_data| {
+                Ok(())
+              });
+              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+                if let Some(_aidl_default_impl) = <Self as IKeyMintDevice>::getDefaultImpl() {
+                  return _aidl_default_impl.destroyAttestationIds();
+                }
+              }
+              let _aidl_reply = _aidl_reply?;
+              let _aidl_status: binder::Status = _aidl_reply.read()?;
+              if !_aidl_status.is_ok() { return Err(_aidl_status); }
+              Ok(())
+            }
+            fn begin(&self, _arg_inPurpose: crate::mangled::_7_android_8_hardware_7_keymint_10_KeyPurpose, _arg_inKeyBlob: &[u8], _arg_inParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_inAuthToken: &crate::mangled::_7_android_8_hardware_7_keymint_17_HardwareAuthToken) -> binder::public_api::Result<crate::mangled::_7_android_8_hardware_7_keymint_11_BeginResult> {
+              let _aidl_reply = self.binder.transact(TRANSACTION_begin, 0, |_aidl_data| {
+                _aidl_data.write(&_arg_inPurpose)?;
+                _aidl_data.write(_arg_inKeyBlob)?;
+                _aidl_data.write(_arg_inParams)?;
+                _aidl_data.write(_arg_inAuthToken)?;
+                Ok(())
+              });
+              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+                if let Some(_aidl_default_impl) = <Self as IKeyMintDevice>::getDefaultImpl() {
+                  return _aidl_default_impl.begin(_arg_inPurpose, _arg_inKeyBlob, _arg_inParams, _arg_inAuthToken);
+                }
+              }
+              let _aidl_reply = _aidl_reply?;
+              let _aidl_status: binder::Status = _aidl_reply.read()?;
+              if !_aidl_status.is_ok() { return Err(_aidl_status); }
+              let _aidl_return: crate::mangled::_7_android_8_hardware_7_keymint_11_BeginResult = _aidl_reply.read()?;
+              Ok(_aidl_return)
+            }
+          }
+          impl IKeyMintDevice for binder::Binder<BnKeyMintDevice> {
+            fn getHardwareInfo(&self) -> binder::public_api::Result<crate::mangled::_7_android_8_hardware_7_keymint_19_KeyMintHardwareInfo> { self.0.getHardwareInfo() }
+            fn verifyAuthorization(&self, _arg_challenge: i64, _arg_parametersToVerify: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_token: &crate::mangled::_7_android_8_hardware_7_keymint_17_HardwareAuthToken) -> binder::public_api::Result<crate::mangled::_7_android_8_hardware_7_keymint_17_VerificationToken> { self.0.verifyAuthorization(_arg_challenge, _arg_parametersToVerify, _arg_token) }
+            fn addRngEntropy(&self, _arg_data: &[u8]) -> binder::public_api::Result<()> { self.0.addRngEntropy(_arg_data) }
+            fn generateKey(&self, _arg_keyParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_generatedKeyBlob: &mut Vec<u8>, _arg_generatedKeyCharacteristics: &mut crate::mangled::_7_android_8_hardware_7_keymint_18_KeyCharacteristics, _arg_outCertChain: &mut Vec<crate::mangled::_7_android_8_hardware_7_keymint_11_Certificate>) -> binder::public_api::Result<()> { self.0.generateKey(_arg_keyParams, _arg_generatedKeyBlob, _arg_generatedKeyCharacteristics, _arg_outCertChain) }
+            fn importKey(&self, _arg_inKeyParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_inKeyFormat: crate::mangled::_7_android_8_hardware_7_keymint_9_KeyFormat, _arg_inKeyData: &[u8], _arg_outImportedKeyBlob: &mut Vec<u8>, _arg_outImportedKeyCharacteristics: &mut crate::mangled::_7_android_8_hardware_7_keymint_18_KeyCharacteristics, _arg_outCertChain: &mut Vec<crate::mangled::_7_android_8_hardware_7_keymint_11_Certificate>) -> binder::public_api::Result<()> { self.0.importKey(_arg_inKeyParams, _arg_inKeyFormat, _arg_inKeyData, _arg_outImportedKeyBlob, _arg_outImportedKeyCharacteristics, _arg_outCertChain) }
+            fn importWrappedKey(&self, _arg_inWrappedKeyData: &[u8], _arg_inWrappingKeyBlob: &[u8], _arg_inMaskingKey: &[u8], _arg_inUnwrappingParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_inPasswordSid: i64, _arg_inBiometricSid: i64, _arg_outImportedKeyBlob: &mut Vec<u8>, _arg_outImportedKeyCharacteristics: &mut crate::mangled::_7_android_8_hardware_7_keymint_18_KeyCharacteristics) -> binder::public_api::Result<()> { self.0.importWrappedKey(_arg_inWrappedKeyData, _arg_inWrappingKeyBlob, _arg_inMaskingKey, _arg_inUnwrappingParams, _arg_inPasswordSid, _arg_inBiometricSid, _arg_outImportedKeyBlob, _arg_outImportedKeyCharacteristics) }
+            fn upgradeKey(&self, _arg_inKeyBlobToUpgrade: &[u8], _arg_inUpgradeParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter]) -> binder::public_api::Result<Vec<u8>> { self.0.upgradeKey(_arg_inKeyBlobToUpgrade, _arg_inUpgradeParams) }
+            fn deleteKey(&self, _arg_inKeyBlob: &[u8]) -> binder::public_api::Result<()> { self.0.deleteKey(_arg_inKeyBlob) }
+            fn deleteAllKeys(&self) -> binder::public_api::Result<()> { self.0.deleteAllKeys() }
+            fn destroyAttestationIds(&self) -> binder::public_api::Result<()> { self.0.destroyAttestationIds() }
+            fn begin(&self, _arg_inPurpose: crate::mangled::_7_android_8_hardware_7_keymint_10_KeyPurpose, _arg_inKeyBlob: &[u8], _arg_inParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_inAuthToken: &crate::mangled::_7_android_8_hardware_7_keymint_17_HardwareAuthToken) -> binder::public_api::Result<crate::mangled::_7_android_8_hardware_7_keymint_11_BeginResult> { self.0.begin(_arg_inPurpose, _arg_inKeyBlob, _arg_inParams, _arg_inAuthToken) }
+          }
+          fn on_transact(_aidl_service: &dyn IKeyMintDevice, _aidl_code: binder::TransactionCode, _aidl_data: &binder::parcel::Parcel, _aidl_reply: &mut binder::parcel::Parcel) -> binder::Result<()> {
+            match _aidl_code {
+              TRANSACTION_getHardwareInfo => {
+                let _aidl_return = _aidl_service.getHardwareInfo();
+                match &_aidl_return {
+                  Ok(_aidl_return) => {
+                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+                    _aidl_reply.write(_aidl_return)?;
+                  }
+                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+                }
+                Ok(())
+              }
+              TRANSACTION_verifyAuthorization => {
+                let _arg_challenge: i64 = _aidl_data.read()?;
+                let _arg_parametersToVerify: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter> = _aidl_data.read()?;
+                let _arg_token: crate::mangled::_7_android_8_hardware_7_keymint_17_HardwareAuthToken = _aidl_data.read()?;
+                let _aidl_return = _aidl_service.verifyAuthorization(_arg_challenge, &_arg_parametersToVerify, &_arg_token);
+                match &_aidl_return {
+                  Ok(_aidl_return) => {
+                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+                    _aidl_reply.write(_aidl_return)?;
+                  }
+                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+                }
+                Ok(())
+              }
+              TRANSACTION_addRngEntropy => {
+                let _arg_data: Vec<u8> = _aidl_data.read()?;
+                let _aidl_return = _aidl_service.addRngEntropy(&_arg_data);
+                match &_aidl_return {
+                  Ok(_aidl_return) => {
+                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+                  }
+                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+                }
+                Ok(())
+              }
+              TRANSACTION_generateKey => {
+                let _arg_keyParams: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter> = _aidl_data.read()?;
+                let mut _arg_generatedKeyBlob: Vec<u8> = Default::default();
+                _aidl_data.resize_out_vec(&mut _arg_generatedKeyBlob)?;
+                let mut _arg_generatedKeyCharacteristics: crate::mangled::_7_android_8_hardware_7_keymint_18_KeyCharacteristics = Default::default();
+                let mut _arg_outCertChain: Vec<crate::mangled::_7_android_8_hardware_7_keymint_11_Certificate> = Default::default();
+                _aidl_data.resize_out_vec(&mut _arg_outCertChain)?;
+                let _aidl_return = _aidl_service.generateKey(&_arg_keyParams, &mut _arg_generatedKeyBlob, &mut _arg_generatedKeyCharacteristics, &mut _arg_outCertChain);
+                match &_aidl_return {
+                  Ok(_aidl_return) => {
+                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+                    _aidl_reply.write(&_arg_generatedKeyBlob)?;
+                    _aidl_reply.write(&_arg_generatedKeyCharacteristics)?;
+                    _aidl_reply.write(&_arg_outCertChain)?;
+                  }
+                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+                }
+                Ok(())
+              }
+              TRANSACTION_importKey => {
+                let _arg_inKeyParams: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter> = _aidl_data.read()?;
+                let _arg_inKeyFormat: crate::mangled::_7_android_8_hardware_7_keymint_9_KeyFormat = _aidl_data.read()?;
+                let _arg_inKeyData: Vec<u8> = _aidl_data.read()?;
+                let mut _arg_outImportedKeyBlob: Vec<u8> = Default::default();
+                _aidl_data.resize_out_vec(&mut _arg_outImportedKeyBlob)?;
+                let mut _arg_outImportedKeyCharacteristics: crate::mangled::_7_android_8_hardware_7_keymint_18_KeyCharacteristics = Default::default();
+                let mut _arg_outCertChain: Vec<crate::mangled::_7_android_8_hardware_7_keymint_11_Certificate> = Default::default();
+                _aidl_data.resize_out_vec(&mut _arg_outCertChain)?;
+                let _aidl_return = _aidl_service.importKey(&_arg_inKeyParams, _arg_inKeyFormat, &_arg_inKeyData, &mut _arg_outImportedKeyBlob, &mut _arg_outImportedKeyCharacteristics, &mut _arg_outCertChain);
+                match &_aidl_return {
+                  Ok(_aidl_return) => {
+                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+                    _aidl_reply.write(&_arg_outImportedKeyBlob)?;
+                    _aidl_reply.write(&_arg_outImportedKeyCharacteristics)?;
+                    _aidl_reply.write(&_arg_outCertChain)?;
+                  }
+                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+                }
+                Ok(())
+              }
+              TRANSACTION_importWrappedKey => {
+                let _arg_inWrappedKeyData: Vec<u8> = _aidl_data.read()?;
+                let _arg_inWrappingKeyBlob: Vec<u8> = _aidl_data.read()?;
+                let _arg_inMaskingKey: Vec<u8> = _aidl_data.read()?;
+                let _arg_inUnwrappingParams: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter> = _aidl_data.read()?;
+                let _arg_inPasswordSid: i64 = _aidl_data.read()?;
+                let _arg_inBiometricSid: i64 = _aidl_data.read()?;
+                let mut _arg_outImportedKeyBlob: Vec<u8> = Default::default();
+                _aidl_data.resize_out_vec(&mut _arg_outImportedKeyBlob)?;
+                let mut _arg_outImportedKeyCharacteristics: crate::mangled::_7_android_8_hardware_7_keymint_18_KeyCharacteristics = Default::default();
+                let _aidl_return = _aidl_service.importWrappedKey(&_arg_inWrappedKeyData, &_arg_inWrappingKeyBlob, &_arg_inMaskingKey, &_arg_inUnwrappingParams, _arg_inPasswordSid, _arg_inBiometricSid, &mut _arg_outImportedKeyBlob, &mut _arg_outImportedKeyCharacteristics);
+                match &_aidl_return {
+                  Ok(_aidl_return) => {
+                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+                    _aidl_reply.write(&_arg_outImportedKeyBlob)?;
+                    _aidl_reply.write(&_arg_outImportedKeyCharacteristics)?;
+                  }
+                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+                }
+                Ok(())
+              }
+              TRANSACTION_upgradeKey => {
+                let _arg_inKeyBlobToUpgrade: Vec<u8> = _aidl_data.read()?;
+                let _arg_inUpgradeParams: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter> = _aidl_data.read()?;
+                let _aidl_return = _aidl_service.upgradeKey(&_arg_inKeyBlobToUpgrade, &_arg_inUpgradeParams);
+                match &_aidl_return {
+                  Ok(_aidl_return) => {
+                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+                    _aidl_reply.write(_aidl_return)?;
+                  }
+                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+                }
+                Ok(())
+              }
+              TRANSACTION_deleteKey => {
+                let _arg_inKeyBlob: Vec<u8> = _aidl_data.read()?;
+                let _aidl_return = _aidl_service.deleteKey(&_arg_inKeyBlob);
+                match &_aidl_return {
+                  Ok(_aidl_return) => {
+                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+                  }
+                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+                }
+                Ok(())
+              }
+              TRANSACTION_deleteAllKeys => {
+                let _aidl_return = _aidl_service.deleteAllKeys();
+                match &_aidl_return {
+                  Ok(_aidl_return) => {
+                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+                  }
+                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+                }
+                Ok(())
+              }
+              TRANSACTION_destroyAttestationIds => {
+                let _aidl_return = _aidl_service.destroyAttestationIds();
+                match &_aidl_return {
+                  Ok(_aidl_return) => {
+                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+                  }
+                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+                }
+                Ok(())
+              }
+              TRANSACTION_begin => {
+                let _arg_inPurpose: crate::mangled::_7_android_8_hardware_7_keymint_10_KeyPurpose = _aidl_data.read()?;
+                let _arg_inKeyBlob: Vec<u8> = _aidl_data.read()?;
+                let _arg_inParams: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter> = _aidl_data.read()?;
+                let _arg_inAuthToken: crate::mangled::_7_android_8_hardware_7_keymint_17_HardwareAuthToken = _aidl_data.read()?;
+                let _aidl_return = _aidl_service.begin(_arg_inPurpose, &_arg_inKeyBlob, &_arg_inParams, &_arg_inAuthToken);
+                match &_aidl_return {
+                  Ok(_aidl_return) => {
+                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+                    _aidl_reply.write(_aidl_return)?;
+                  }
+                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+                }
+                Ok(())
+              }
+              _ => Err(binder::StatusCode::UNKNOWN_TRANSACTION)
+            }
+          }
+        }
+        pub mod IKeyMintOperation {
+          #![allow(non_upper_case_globals)]
+          #![allow(non_snake_case)]
+          #[allow(unused_imports)] use binder::IBinder;
+          use binder::declare_binder_interface;
+          declare_binder_interface! {
+            IKeyMintOperation["android.hardware.keymint.IKeyMintOperation"] {
+              native: BnKeyMintOperation(on_transact),
+              proxy: BpKeyMintOperation {
+              },
+            }
+          }
+          pub trait IKeyMintOperation: binder::Interface {
+            fn get_descriptor() -> &'static str where Self: Sized { "android.hardware.keymint.IKeyMintOperation" }
+            fn update(&self, _arg_inParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_input: &[u8], _arg_inVerificationToken: &crate::mangled::_7_android_8_hardware_7_keymint_17_VerificationToken, _arg_outParams: &mut Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter>, _arg_output: &mut Vec<u8>) -> binder::public_api::Result<i32> {
+              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+            }
+            fn finish(&self, _arg_inParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_input: &[u8], _arg_inSignature: &[u8], _arg_authToken: &crate::mangled::_7_android_8_hardware_7_keymint_17_HardwareAuthToken, _arg_inVerificationToken: &crate::mangled::_7_android_8_hardware_7_keymint_17_VerificationToken, _arg_outParams: &mut Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter>, _arg_output: &mut Vec<u8>) -> binder::public_api::Result<()> {
+              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+            }
+            fn abort(&self) -> binder::public_api::Result<()> {
+              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+            }
+            fn getDefaultImpl() -> DefaultImpl where Self: Sized {
+              DEFAULT_IMPL.lock().unwrap().clone()
+            }
+            fn setDefaultImpl(d: DefaultImpl) -> DefaultImpl where Self: Sized {
+              std::mem::replace(&mut *DEFAULT_IMPL.lock().unwrap(), d)
+            }
+          }
+          pub const TRANSACTION_update: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 0;
+          pub const TRANSACTION_finish: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 1;
+          pub const TRANSACTION_abort: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 2;
+          pub type DefaultImpl = Option<std::sync::Arc<dyn IKeyMintOperation + Send + Sync>>;
+          use lazy_static::lazy_static;
+          lazy_static! {
+            static ref DEFAULT_IMPL: std::sync::Mutex<DefaultImpl> = std::sync::Mutex::new(None);
+          }
+          pub(crate) mod mangled { pub use super::IKeyMintOperation as _7_android_8_hardware_7_keymint_17_IKeyMintOperation; }
+          impl IKeyMintOperation for BpKeyMintOperation {
+            fn update(&self, _arg_inParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_input: &[u8], _arg_inVerificationToken: &crate::mangled::_7_android_8_hardware_7_keymint_17_VerificationToken, _arg_outParams: &mut Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter>, _arg_output: &mut Vec<u8>) -> binder::public_api::Result<i32> {
+              let _aidl_reply = self.binder.transact(TRANSACTION_update, 0, |_aidl_data| {
+                _aidl_data.write(_arg_inParams)?;
+                _aidl_data.write(_arg_input)?;
+                _aidl_data.write(_arg_inVerificationToken)?;
+                _aidl_data.write_slice_size(Some(_arg_outParams))?;
+                _aidl_data.write_slice_size(Some(_arg_output))?;
+                Ok(())
+              });
+              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+                if let Some(_aidl_default_impl) = <Self as IKeyMintOperation>::getDefaultImpl() {
+                  return _aidl_default_impl.update(_arg_inParams, _arg_input, _arg_inVerificationToken, _arg_outParams, _arg_output);
+                }
+              }
+              let _aidl_reply = _aidl_reply?;
+              let _aidl_status: binder::Status = _aidl_reply.read()?;
+              if !_aidl_status.is_ok() { return Err(_aidl_status); }
+              let _aidl_return: i32 = _aidl_reply.read()?;
+              *_arg_outParams = _aidl_reply.read()?;
+              *_arg_output = _aidl_reply.read()?;
+              Ok(_aidl_return)
+            }
+            fn finish(&self, _arg_inParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_input: &[u8], _arg_inSignature: &[u8], _arg_authToken: &crate::mangled::_7_android_8_hardware_7_keymint_17_HardwareAuthToken, _arg_inVerificationToken: &crate::mangled::_7_android_8_hardware_7_keymint_17_VerificationToken, _arg_outParams: &mut Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter>, _arg_output: &mut Vec<u8>) -> binder::public_api::Result<()> {
+              let _aidl_reply = self.binder.transact(TRANSACTION_finish, 0, |_aidl_data| {
+                _aidl_data.write(_arg_inParams)?;
+                _aidl_data.write(_arg_input)?;
+                _aidl_data.write(_arg_inSignature)?;
+                _aidl_data.write(_arg_authToken)?;
+                _aidl_data.write(_arg_inVerificationToken)?;
+                _aidl_data.write_slice_size(Some(_arg_outParams))?;
+                _aidl_data.write_slice_size(Some(_arg_output))?;
+                Ok(())
+              });
+              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+                if let Some(_aidl_default_impl) = <Self as IKeyMintOperation>::getDefaultImpl() {
+                  return _aidl_default_impl.finish(_arg_inParams, _arg_input, _arg_inSignature, _arg_authToken, _arg_inVerificationToken, _arg_outParams, _arg_output);
+                }
+              }
+              let _aidl_reply = _aidl_reply?;
+              let _aidl_status: binder::Status = _aidl_reply.read()?;
+              if !_aidl_status.is_ok() { return Err(_aidl_status); }
+              *_arg_outParams = _aidl_reply.read()?;
+              *_arg_output = _aidl_reply.read()?;
+              Ok(())
+            }
+            fn abort(&self) -> binder::public_api::Result<()> {
+              let _aidl_reply = self.binder.transact(TRANSACTION_abort, 0, |_aidl_data| {
+                Ok(())
+              });
+              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+                if let Some(_aidl_default_impl) = <Self as IKeyMintOperation>::getDefaultImpl() {
+                  return _aidl_default_impl.abort();
+                }
+              }
+              let _aidl_reply = _aidl_reply?;
+              let _aidl_status: binder::Status = _aidl_reply.read()?;
+              if !_aidl_status.is_ok() { return Err(_aidl_status); }
+              Ok(())
+            }
+          }
+          impl IKeyMintOperation for binder::Binder<BnKeyMintOperation> {
+            fn update(&self, _arg_inParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_input: &[u8], _arg_inVerificationToken: &crate::mangled::_7_android_8_hardware_7_keymint_17_VerificationToken, _arg_outParams: &mut Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter>, _arg_output: &mut Vec<u8>) -> binder::public_api::Result<i32> { self.0.update(_arg_inParams, _arg_input, _arg_inVerificationToken, _arg_outParams, _arg_output) }
+            fn finish(&self, _arg_inParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_input: &[u8], _arg_inSignature: &[u8], _arg_authToken: &crate::mangled::_7_android_8_hardware_7_keymint_17_HardwareAuthToken, _arg_inVerificationToken: &crate::mangled::_7_android_8_hardware_7_keymint_17_VerificationToken, _arg_outParams: &mut Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter>, _arg_output: &mut Vec<u8>) -> binder::public_api::Result<()> { self.0.finish(_arg_inParams, _arg_input, _arg_inSignature, _arg_authToken, _arg_inVerificationToken, _arg_outParams, _arg_output) }
+            fn abort(&self) -> binder::public_api::Result<()> { self.0.abort() }
+          }
+          fn on_transact(_aidl_service: &dyn IKeyMintOperation, _aidl_code: binder::TransactionCode, _aidl_data: &binder::parcel::Parcel, _aidl_reply: &mut binder::parcel::Parcel) -> binder::Result<()> {
+            match _aidl_code {
+              TRANSACTION_update => {
+                let _arg_inParams: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter> = _aidl_data.read()?;
+                let _arg_input: Vec<u8> = _aidl_data.read()?;
+                let _arg_inVerificationToken: crate::mangled::_7_android_8_hardware_7_keymint_17_VerificationToken = _aidl_data.read()?;
+                let mut _arg_outParams: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter> = Default::default();
+                _aidl_data.resize_out_vec(&mut _arg_outParams)?;
+                let mut _arg_output: Vec<u8> = Default::default();
+                _aidl_data.resize_out_vec(&mut _arg_output)?;
+                let _aidl_return = _aidl_service.update(&_arg_inParams, &_arg_input, &_arg_inVerificationToken, &mut _arg_outParams, &mut _arg_output);
+                match &_aidl_return {
+                  Ok(_aidl_return) => {
+                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+                    _aidl_reply.write(_aidl_return)?;
+                    _aidl_reply.write(&_arg_outParams)?;
+                    _aidl_reply.write(&_arg_output)?;
+                  }
+                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+                }
+                Ok(())
+              }
+              TRANSACTION_finish => {
+                let _arg_inParams: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter> = _aidl_data.read()?;
+                let _arg_input: Vec<u8> = _aidl_data.read()?;
+                let _arg_inSignature: Vec<u8> = _aidl_data.read()?;
+                let _arg_authToken: crate::mangled::_7_android_8_hardware_7_keymint_17_HardwareAuthToken = _aidl_data.read()?;
+                let _arg_inVerificationToken: crate::mangled::_7_android_8_hardware_7_keymint_17_VerificationToken = _aidl_data.read()?;
+                let mut _arg_outParams: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter> = Default::default();
+                _aidl_data.resize_out_vec(&mut _arg_outParams)?;
+                let mut _arg_output: Vec<u8> = Default::default();
+                _aidl_data.resize_out_vec(&mut _arg_output)?;
+                let _aidl_return = _aidl_service.finish(&_arg_inParams, &_arg_input, &_arg_inSignature, &_arg_authToken, &_arg_inVerificationToken, &mut _arg_outParams, &mut _arg_output);
+                match &_aidl_return {
+                  Ok(_aidl_return) => {
+                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+                    _aidl_reply.write(&_arg_outParams)?;
+                    _aidl_reply.write(&_arg_output)?;
+                  }
+                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+                }
+                Ok(())
+              }
+              TRANSACTION_abort => {
+                let _aidl_return = _aidl_service.abort();
+                match &_aidl_return {
+                  Ok(_aidl_return) => {
+                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+                  }
+                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+                }
+                Ok(())
+              }
+              _ => Err(binder::StatusCode::UNKNOWN_TRANSACTION)
+            }
+          }
+        }
+        pub mod KeyCharacteristics {
+          pub struct KeyCharacteristics {
+            pub softwareEnforced: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter>, 
+            pub hardwareEnforced: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter>, 
+          }
+          pub(crate) mod mangled { pub use super::KeyCharacteristics as _7_android_8_hardware_7_keymint_18_KeyCharacteristics; }
+          impl Default for KeyCharacteristics {
+            fn default() -> Self {
+              Self {
+                softwareEnforced: Default::default(),
+                hardwareEnforced: Default::default(),
+              }
+            }
+          }
+          impl binder::parcel::Serialize for KeyCharacteristics {
+            fn serialize(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
+              <Self as binder::parcel::SerializeOption>::serialize_option(Some(self), parcel)
+            }
+          }
+          impl binder::parcel::SerializeArray for KeyCharacteristics {}
+          impl binder::parcel::SerializeOption for KeyCharacteristics {
+            fn serialize_option(this: Option<&Self>, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
+              let this = if let Some(this) = this {
+                parcel.write(&1i32)?;
+                this
+              } else {
+                return parcel.write(&0i32);
+              };
+              let start_pos = parcel.get_data_position();
+              parcel.write(&0i32)?;
+              parcel.write(&this.softwareEnforced)?;
+              parcel.write(&this.hardwareEnforced)?;
+              let end_pos = parcel.get_data_position();
+              let parcelable_size = (end_pos - start_pos) as i32;
+              unsafe { parcel.set_data_position(start_pos)?; }
+              parcel.write(&parcelable_size)?;
+              unsafe { parcel.set_data_position(end_pos)?; }
+              Ok(())
+            }
+          }
+          impl binder::parcel::Deserialize for KeyCharacteristics {
+            fn deserialize(parcel: &binder::parcel::Parcel) -> binder::Result<Self> {
+              <Self as binder::parcel::DeserializeOption>::deserialize_option(parcel)
+                 .transpose()
+                 .unwrap_or(Err(binder::StatusCode::UNEXPECTED_NULL))
+            }
+          }
+          impl binder::parcel::DeserializeArray for KeyCharacteristics {}
+          impl binder::parcel::DeserializeOption for KeyCharacteristics {
+            fn deserialize_option(parcel: &binder::parcel::Parcel) -> binder::Result<Option<Self>> {
+              let status: i32 = parcel.read()?;
+              if status == 0 { return Ok(None); }
+              let start_pos = parcel.get_data_position();
+              let parcelable_size: i32 = parcel.read()?;
+              if parcelable_size < 0 { return Err(binder::StatusCode::BAD_VALUE); }
+              let mut result = Self::default();
+              result.softwareEnforced = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) >= parcelable_size {
+                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
+                return Ok(Some(result));
+              }
+              result.hardwareEnforced = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) >= parcelable_size {
+                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
+                return Ok(Some(result));
+              }
+              Ok(Some(result))
+            }
+          }
+        }
+        pub mod KeyDerivationFunction {
+          #![allow(non_upper_case_globals)]
+          pub type KeyDerivationFunction = i32;
+          pub const NONE: KeyDerivationFunction = 0;
+          pub const RFC5869_SHA256: KeyDerivationFunction = 1;
+          pub const ISO18033_2_KDF1_SHA1: KeyDerivationFunction = 2;
+          pub const ISO18033_2_KDF1_SHA256: KeyDerivationFunction = 3;
+          pub const ISO18033_2_KDF2_SHA1: KeyDerivationFunction = 4;
+          pub const ISO18033_2_KDF2_SHA256: KeyDerivationFunction = 5;
+          pub(crate) mod mangled { pub use super::KeyDerivationFunction as _7_android_8_hardware_7_keymint_21_KeyDerivationFunction; }
+        }
+        pub mod KeyFormat {
+          #![allow(non_upper_case_globals)]
+          pub type KeyFormat = i32;
+          pub const X509: KeyFormat = 0;
+          pub const PKCS8: KeyFormat = 1;
+          pub const RAW: KeyFormat = 3;
+          pub(crate) mod mangled { pub use super::KeyFormat as _7_android_8_hardware_7_keymint_9_KeyFormat; }
+        }
+        pub mod KeyMintHardwareInfo {
+          pub struct KeyMintHardwareInfo {
+            pub versionNumber: i32, 
+            pub securityLevel: crate::mangled::_7_android_8_hardware_7_keymint_13_SecurityLevel, 
+            pub keyMintName: String, 
+            pub keyMintAuthorName: String, 
+          }
+          pub(crate) mod mangled { pub use super::KeyMintHardwareInfo as _7_android_8_hardware_7_keymint_19_KeyMintHardwareInfo; }
+          impl Default for KeyMintHardwareInfo {
+            fn default() -> Self {
+              Self {
+                versionNumber: 0,
+                securityLevel: Default::default(),
+                keyMintName: Default::default(),
+                keyMintAuthorName: Default::default(),
+              }
+            }
+          }
+          impl binder::parcel::Serialize for KeyMintHardwareInfo {
+            fn serialize(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
+              <Self as binder::parcel::SerializeOption>::serialize_option(Some(self), parcel)
+            }
+          }
+          impl binder::parcel::SerializeArray for KeyMintHardwareInfo {}
+          impl binder::parcel::SerializeOption for KeyMintHardwareInfo {
+            fn serialize_option(this: Option<&Self>, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
+              let this = if let Some(this) = this {
+                parcel.write(&1i32)?;
+                this
+              } else {
+                return parcel.write(&0i32);
+              };
+              let start_pos = parcel.get_data_position();
+              parcel.write(&0i32)?;
+              parcel.write(&this.versionNumber)?;
+              parcel.write(&this.securityLevel)?;
+              parcel.write(&this.keyMintName)?;
+              parcel.write(&this.keyMintAuthorName)?;
+              let end_pos = parcel.get_data_position();
+              let parcelable_size = (end_pos - start_pos) as i32;
+              unsafe { parcel.set_data_position(start_pos)?; }
+              parcel.write(&parcelable_size)?;
+              unsafe { parcel.set_data_position(end_pos)?; }
+              Ok(())
+            }
+          }
+          impl binder::parcel::Deserialize for KeyMintHardwareInfo {
+            fn deserialize(parcel: &binder::parcel::Parcel) -> binder::Result<Self> {
+              <Self as binder::parcel::DeserializeOption>::deserialize_option(parcel)
+                 .transpose()
+                 .unwrap_or(Err(binder::StatusCode::UNEXPECTED_NULL))
+            }
+          }
+          impl binder::parcel::DeserializeArray for KeyMintHardwareInfo {}
+          impl binder::parcel::DeserializeOption for KeyMintHardwareInfo {
+            fn deserialize_option(parcel: &binder::parcel::Parcel) -> binder::Result<Option<Self>> {
+              let status: i32 = parcel.read()?;
+              if status == 0 { return Ok(None); }
+              let start_pos = parcel.get_data_position();
+              let parcelable_size: i32 = parcel.read()?;
+              if parcelable_size < 0 { return Err(binder::StatusCode::BAD_VALUE); }
+              let mut result = Self::default();
+              result.versionNumber = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) >= parcelable_size {
+                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
+                return Ok(Some(result));
+              }
+              result.securityLevel = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) >= parcelable_size {
+                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
+                return Ok(Some(result));
+              }
+              result.keyMintName = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) >= parcelable_size {
+                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
+                return Ok(Some(result));
+              }
+              result.keyMintAuthorName = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) >= parcelable_size {
+                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
+                return Ok(Some(result));
+              }
+              Ok(Some(result))
+            }
+          }
+        }
+        pub mod KeyOrigin {
+          #![allow(non_upper_case_globals)]
+          pub type KeyOrigin = i32;
+          pub const GENERATED: KeyOrigin = 0;
+          pub const DERIVED: KeyOrigin = 1;
+          pub const IMPORTED: KeyOrigin = 2;
+          pub const SECURELY_IMPORTED: KeyOrigin = 4;
+          pub(crate) mod mangled { pub use super::KeyOrigin as _7_android_8_hardware_7_keymint_9_KeyOrigin; }
+        }
+        pub mod KeyParameter {
+          pub struct KeyParameter {
+            pub tag: crate::mangled::_7_android_8_hardware_7_keymint_3_Tag, 
+            pub boolValue: bool, 
+            pub integer: i32, 
+            pub longInteger: i64, 
+            pub dateTime: i64, 
+            pub blob: Vec<u8>, 
+          }
+          pub(crate) mod mangled { pub use super::KeyParameter as _7_android_8_hardware_7_keymint_12_KeyParameter; }
+          impl Default for KeyParameter {
+            fn default() -> Self {
+              Self {
+                tag: Default::default(),
+                boolValue: false,
+                integer: 0,
+                longInteger: 0,
+                dateTime: 0,
+                blob: Default::default(),
+              }
+            }
+          }
+          impl binder::parcel::Serialize for KeyParameter {
+            fn serialize(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
+              <Self as binder::parcel::SerializeOption>::serialize_option(Some(self), parcel)
+            }
+          }
+          impl binder::parcel::SerializeArray for KeyParameter {}
+          impl binder::parcel::SerializeOption for KeyParameter {
+            fn serialize_option(this: Option<&Self>, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
+              let this = if let Some(this) = this {
+                parcel.write(&1i32)?;
+                this
+              } else {
+                return parcel.write(&0i32);
+              };
+              let start_pos = parcel.get_data_position();
+              parcel.write(&0i32)?;
+              parcel.write(&this.tag)?;
+              parcel.write(&this.boolValue)?;
+              parcel.write(&this.integer)?;
+              parcel.write(&this.longInteger)?;
+              parcel.write(&this.dateTime)?;
+              parcel.write(&this.blob)?;
+              let end_pos = parcel.get_data_position();
+              let parcelable_size = (end_pos - start_pos) as i32;
+              unsafe { parcel.set_data_position(start_pos)?; }
+              parcel.write(&parcelable_size)?;
+              unsafe { parcel.set_data_position(end_pos)?; }
+              Ok(())
+            }
+          }
+          impl binder::parcel::Deserialize for KeyParameter {
+            fn deserialize(parcel: &binder::parcel::Parcel) -> binder::Result<Self> {
+              <Self as binder::parcel::DeserializeOption>::deserialize_option(parcel)
+                 .transpose()
+                 .unwrap_or(Err(binder::StatusCode::UNEXPECTED_NULL))
+            }
+          }
+          impl binder::parcel::DeserializeArray for KeyParameter {}
+          impl binder::parcel::DeserializeOption for KeyParameter {
+            fn deserialize_option(parcel: &binder::parcel::Parcel) -> binder::Result<Option<Self>> {
+              let status: i32 = parcel.read()?;
+              if status == 0 { return Ok(None); }
+              let start_pos = parcel.get_data_position();
+              let parcelable_size: i32 = parcel.read()?;
+              if parcelable_size < 0 { return Err(binder::StatusCode::BAD_VALUE); }
+              let mut result = Self::default();
+              result.tag = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) >= parcelable_size {
+                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
+                return Ok(Some(result));
+              }
+              result.boolValue = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) >= parcelable_size {
+                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
+                return Ok(Some(result));
+              }
+              result.integer = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) >= parcelable_size {
+                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
+                return Ok(Some(result));
+              }
+              result.longInteger = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) >= parcelable_size {
+                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
+                return Ok(Some(result));
+              }
+              result.dateTime = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) >= parcelable_size {
+                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
+                return Ok(Some(result));
+              }
+              result.blob = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) >= parcelable_size {
+                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
+                return Ok(Some(result));
+              }
+              Ok(Some(result))
+            }
+          }
+        }
+        pub mod KeyPurpose {
+          #![allow(non_upper_case_globals)]
+          pub type KeyPurpose = i32;
+          pub const ENCRYPT: KeyPurpose = 0;
+          pub const DECRYPT: KeyPurpose = 1;
+          pub const SIGN: KeyPurpose = 2;
+          pub const VERIFY: KeyPurpose = 3;
+          pub const WRAP_KEY: KeyPurpose = 5;
+          pub(crate) mod mangled { pub use super::KeyPurpose as _7_android_8_hardware_7_keymint_10_KeyPurpose; }
+        }
+        pub mod PaddingMode {
+          #![allow(non_upper_case_globals)]
+          pub type PaddingMode = i32;
+          pub const NONE: PaddingMode = 1;
+          pub const RSA_OAEP: PaddingMode = 2;
+          pub const RSA_PSS: PaddingMode = 3;
+          pub const RSA_PKCS1_1_5_ENCRYPT: PaddingMode = 4;
+          pub const RSA_PKCS1_1_5_SIGN: PaddingMode = 5;
+          pub const PKCS7: PaddingMode = 64;
+          pub(crate) mod mangled { pub use super::PaddingMode as _7_android_8_hardware_7_keymint_11_PaddingMode; }
+        }
+        pub mod SecurityLevel {
+          #![allow(non_upper_case_globals)]
+          pub type SecurityLevel = i32;
+          pub const SOFTWARE: SecurityLevel = 0;
+          pub const TRUSTED_ENVIRONMENT: SecurityLevel = 1;
+          pub const STRONGBOX: SecurityLevel = 2;
+          pub(crate) mod mangled { pub use super::SecurityLevel as _7_android_8_hardware_7_keymint_13_SecurityLevel; }
+        }
+        pub mod Tag {
+          #![allow(non_upper_case_globals)]
+          pub type Tag = i32;
+          pub const INVALID: Tag = 0;
+          pub const PURPOSE: Tag = 536870913;
+          pub const ALGORITHM: Tag = 268435458;
+          pub const KEY_SIZE: Tag = 805306371;
+          pub const BLOCK_MODE: Tag = 536870916;
+          pub const DIGEST: Tag = 536870917;
+          pub const PADDING: Tag = 536870918;
+          pub const CALLER_NONCE: Tag = 1879048199;
+          pub const MIN_MAC_LENGTH: Tag = 805306376;
+          pub const EC_CURVE: Tag = 268435466;
+          pub const RSA_PUBLIC_EXPONENT: Tag = 1342177480;
+          pub const INCLUDE_UNIQUE_ID: Tag = 1879048394;
+          pub const BLOB_USAGE_REQUIREMENTS: Tag = 268435757;
+          pub const BOOTLOADER_ONLY: Tag = 1879048494;
+          pub const ROLLBACK_RESISTANCE: Tag = 1879048495;
+          pub const HARDWARE_TYPE: Tag = 268435760;
+          pub const EARLY_BOOT_ONLY: Tag = 1879048497;
+          pub const ACTIVE_DATETIME: Tag = 1610613136;
+          pub const ORIGINATION_EXPIRE_DATETIME: Tag = 1610613137;
+          pub const USAGE_EXPIRE_DATETIME: Tag = 1610613138;
+          pub const MIN_SECONDS_BETWEEN_OPS: Tag = 805306771;
+          pub const MAX_USES_PER_BOOT: Tag = 805306772;
+          pub const USER_ID: Tag = 805306869;
+          pub const USER_SECURE_ID: Tag = 1073742326;
+          pub const NO_AUTH_REQUIRED: Tag = 1879048695;
+          pub const USER_AUTH_TYPE: Tag = 268435960;
+          pub const AUTH_TIMEOUT: Tag = 805306873;
+          pub const ALLOW_WHILE_ON_BODY: Tag = 1879048698;
+          pub const TRUSTED_USER_PRESENCE_REQUIRED: Tag = 1879048699;
+          pub const TRUSTED_CONFIRMATION_REQUIRED: Tag = 1879048700;
+          pub const UNLOCKED_DEVICE_REQUIRED: Tag = 1879048701;
+          pub const APPLICATION_ID: Tag = -1879047591;
+          pub const APPLICATION_DATA: Tag = -1879047492;
+          pub const CREATION_DATETIME: Tag = 1610613437;
+          pub const ORIGIN: Tag = 268436158;
+          pub const ROOT_OF_TRUST: Tag = -1879047488;
+          pub const OS_VERSION: Tag = 805307073;
+          pub const OS_PATCHLEVEL: Tag = 805307074;
+          pub const UNIQUE_ID: Tag = -1879047485;
+          pub const ATTESTATION_CHALLENGE: Tag = -1879047484;
+          pub const ATTESTATION_APPLICATION_ID: Tag = -1879047483;
+          pub const ATTESTATION_ID_BRAND: Tag = -1879047482;
+          pub const ATTESTATION_ID_DEVICE: Tag = -1879047481;
+          pub const ATTESTATION_ID_PRODUCT: Tag = -1879047480;
+          pub const ATTESTATION_ID_SERIAL: Tag = -1879047479;
+          pub const ATTESTATION_ID_IMEI: Tag = -1879047478;
+          pub const ATTESTATION_ID_MEID: Tag = -1879047477;
+          pub const ATTESTATION_ID_MANUFACTURER: Tag = -1879047476;
+          pub const ATTESTATION_ID_MODEL: Tag = -1879047475;
+          pub const VENDOR_PATCHLEVEL: Tag = 805307086;
+          pub const BOOT_PATCHLEVEL: Tag = 805307087;
+          pub const DEVICE_UNIQUE_ATTESTATION: Tag = 1879048912;
+          pub const IDENTITY_CREDENTIAL_KEY: Tag = 1879048913;
+          pub const STORAGE_KEY: Tag = 1879048914;
+          pub const ASSOCIATED_DATA: Tag = -1879047192;
+          pub const NONCE: Tag = -1879047191;
+          pub const MAC_LENGTH: Tag = 805307371;
+          pub const RESET_SINCE_ID_ROTATION: Tag = 1879049196;
+          pub const CONFIRMATION_TOKEN: Tag = -1879047187;
+          pub(crate) mod mangled { pub use super::Tag as _7_android_8_hardware_7_keymint_3_Tag; }
+        }
+        pub mod TagType {
+          #![allow(non_upper_case_globals)]
+          pub type TagType = i32;
+          pub const INVALID: TagType = 0;
+          pub const ENUM: TagType = 268435456;
+          pub const ENUM_REP: TagType = 536870912;
+          pub const UINT: TagType = 805306368;
+          pub const UINT_REP: TagType = 1073741824;
+          pub const ULONG: TagType = 1342177280;
+          pub const DATE: TagType = 1610612736;
+          pub const BOOL: TagType = 1879048192;
+          pub const BIGNUM: TagType = -2147483648;
+          pub const BYTES: TagType = -1879048192;
+          pub const ULONG_REP: TagType = -1610612736;
+          pub(crate) mod mangled { pub use super::TagType as _7_android_8_hardware_7_keymint_7_TagType; }
+        }
+        pub mod Timestamp {
+          pub struct Timestamp {
+            pub milliSeconds: i64, 
+          }
+          pub(crate) mod mangled { pub use super::Timestamp as _7_android_8_hardware_7_keymint_9_Timestamp; }
+          impl Default for Timestamp {
+            fn default() -> Self {
+              Self {
+                milliSeconds: 0,
+              }
+            }
+          }
+          impl binder::parcel::Serialize for Timestamp {
+            fn serialize(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
+              <Self as binder::parcel::SerializeOption>::serialize_option(Some(self), parcel)
+            }
+          }
+          impl binder::parcel::SerializeArray for Timestamp {}
+          impl binder::parcel::SerializeOption for Timestamp {
+            fn serialize_option(this: Option<&Self>, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
+              let this = if let Some(this) = this {
+                parcel.write(&1i32)?;
+                this
+              } else {
+                return parcel.write(&0i32);
+              };
+              let start_pos = parcel.get_data_position();
+              parcel.write(&0i32)?;
+              parcel.write(&this.milliSeconds)?;
+              let end_pos = parcel.get_data_position();
+              let parcelable_size = (end_pos - start_pos) as i32;
+              unsafe { parcel.set_data_position(start_pos)?; }
+              parcel.write(&parcelable_size)?;
+              unsafe { parcel.set_data_position(end_pos)?; }
+              Ok(())
+            }
+          }
+          impl binder::parcel::Deserialize for Timestamp {
+            fn deserialize(parcel: &binder::parcel::Parcel) -> binder::Result<Self> {
+              <Self as binder::parcel::DeserializeOption>::deserialize_option(parcel)
+                 .transpose()
+                 .unwrap_or(Err(binder::StatusCode::UNEXPECTED_NULL))
+            }
+          }
+          impl binder::parcel::DeserializeArray for Timestamp {}
+          impl binder::parcel::DeserializeOption for Timestamp {
+            fn deserialize_option(parcel: &binder::parcel::Parcel) -> binder::Result<Option<Self>> {
+              let status: i32 = parcel.read()?;
+              if status == 0 { return Ok(None); }
+              let start_pos = parcel.get_data_position();
+              let parcelable_size: i32 = parcel.read()?;
+              if parcelable_size < 0 { return Err(binder::StatusCode::BAD_VALUE); }
+              let mut result = Self::default();
+              result.milliSeconds = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) >= parcelable_size {
+                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
+                return Ok(Some(result));
+              }
+              Ok(Some(result))
+            }
+          }
+        }
+        pub mod VerificationToken {
+          pub struct VerificationToken {
+            pub challenge: i64, 
+            pub timestamp: crate::mangled::_7_android_8_hardware_7_keymint_9_Timestamp, 
+            pub securityLevel: crate::mangled::_7_android_8_hardware_7_keymint_13_SecurityLevel, 
+            pub mac: Vec<u8>, 
+          }
+          pub(crate) mod mangled { pub use super::VerificationToken as _7_android_8_hardware_7_keymint_17_VerificationToken; }
+          impl Default for VerificationToken {
+            fn default() -> Self {
+              Self {
+                challenge: 0,
+                timestamp: Default::default(),
+                securityLevel: Default::default(),
+                mac: Default::default(),
+              }
+            }
+          }
+          impl binder::parcel::Serialize for VerificationToken {
+            fn serialize(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
+              <Self as binder::parcel::SerializeOption>::serialize_option(Some(self), parcel)
+            }
+          }
+          impl binder::parcel::SerializeArray for VerificationToken {}
+          impl binder::parcel::SerializeOption for VerificationToken {
+            fn serialize_option(this: Option<&Self>, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
+              let this = if let Some(this) = this {
+                parcel.write(&1i32)?;
+                this
+              } else {
+                return parcel.write(&0i32);
+              };
+              let start_pos = parcel.get_data_position();
+              parcel.write(&0i32)?;
+              parcel.write(&this.challenge)?;
+              parcel.write(&this.timestamp)?;
+              parcel.write(&this.securityLevel)?;
+              parcel.write(&this.mac)?;
+              let end_pos = parcel.get_data_position();
+              let parcelable_size = (end_pos - start_pos) as i32;
+              unsafe { parcel.set_data_position(start_pos)?; }
+              parcel.write(&parcelable_size)?;
+              unsafe { parcel.set_data_position(end_pos)?; }
+              Ok(())
+            }
+          }
+          impl binder::parcel::Deserialize for VerificationToken {
+            fn deserialize(parcel: &binder::parcel::Parcel) -> binder::Result<Self> {
+              <Self as binder::parcel::DeserializeOption>::deserialize_option(parcel)
+                 .transpose()
+                 .unwrap_or(Err(binder::StatusCode::UNEXPECTED_NULL))
+            }
+          }
+          impl binder::parcel::DeserializeArray for VerificationToken {}
+          impl binder::parcel::DeserializeOption for VerificationToken {
+            fn deserialize_option(parcel: &binder::parcel::Parcel) -> binder::Result<Option<Self>> {
+              let status: i32 = parcel.read()?;
+              if status == 0 { return Ok(None); }
+              let start_pos = parcel.get_data_position();
+              let parcelable_size: i32 = parcel.read()?;
+              if parcelable_size < 0 { return Err(binder::StatusCode::BAD_VALUE); }
+              let mut result = Self::default();
+              result.challenge = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) >= parcelable_size {
+                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
+                return Ok(Some(result));
+              }
+              result.timestamp = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) >= parcelable_size {
+                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
+                return Ok(Some(result));
+              }
+              result.securityLevel = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) >= parcelable_size {
+                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
+                return Ok(Some(result));
+              }
+              result.mac = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) >= parcelable_size {
+                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
+                return Ok(Some(result));
+              }
+              Ok(Some(result))
+            }
+          }
+        }
+      }
+    }
+  }
+}
+pub mod mangled {
+  pub use super::aidl::android::hardware::keymint::Algorithm::mangled::*;
+  pub use super::aidl::android::hardware::keymint::BeginResult::mangled::*;
+  pub use super::aidl::android::hardware::keymint::BlockMode::mangled::*;
+  pub use super::aidl::android::hardware::keymint::Certificate::mangled::*;
+  pub use super::aidl::android::hardware::keymint::Constants::mangled::*;
+  pub use super::aidl::android::hardware::keymint::Digest::mangled::*;
+  pub use super::aidl::android::hardware::keymint::EcCurve::mangled::*;
+  pub use super::aidl::android::hardware::keymint::ErrorCode::mangled::*;
+  pub use super::aidl::android::hardware::keymint::HardwareAuthToken::mangled::*;
+  pub use super::aidl::android::hardware::keymint::HardwareAuthenticatorType::mangled::*;
+  pub use super::aidl::android::hardware::keymint::HmacSharingParameters::mangled::*;
+  pub use super::aidl::android::hardware::keymint::IKeyMintDevice::mangled::*;
+  pub use super::aidl::android::hardware::keymint::IKeyMintOperation::mangled::*;
+  pub use super::aidl::android::hardware::keymint::KeyCharacteristics::mangled::*;
+  pub use super::aidl::android::hardware::keymint::KeyDerivationFunction::mangled::*;
+  pub use super::aidl::android::hardware::keymint::KeyFormat::mangled::*;
+  pub use super::aidl::android::hardware::keymint::KeyMintHardwareInfo::mangled::*;
+  pub use super::aidl::android::hardware::keymint::KeyOrigin::mangled::*;
+  pub use super::aidl::android::hardware::keymint::KeyParameter::mangled::*;
+  pub use super::aidl::android::hardware::keymint::KeyPurpose::mangled::*;
+  pub use super::aidl::android::hardware::keymint::PaddingMode::mangled::*;
+  pub use super::aidl::android::hardware::keymint::SecurityLevel::mangled::*;
+  pub use super::aidl::android::hardware::keymint::Tag::mangled::*;
+  pub use super::aidl::android::hardware::keymint::TagType::mangled::*;
+  pub use super::aidl::android::hardware::keymint::Timestamp::mangled::*;
+  pub use super::aidl::android::hardware::keymint::VerificationToken::mangled::*;
+}
\ No newline at end of file
diff --git a/keystore2/src/android_security_keystore2.rs b/keystore2/src/android_security_keystore2.rs
new file mode 100644
index 0000000..421885f
--- /dev/null
+++ b/keystore2/src/android_security_keystore2.rs
@@ -0,0 +1,1312 @@
+#![allow(non_snake_case)]
+#![allow(missing_docs)]
+#![allow(clippy::identity_op)]
+#![allow(clippy::excessive_precision)]
+#![allow(clippy::too_many_arguments)]
+pub use binder::public_api as binder;
+pub mod aidl {
+  pub mod android {
+    pub mod security {
+      pub mod keystore2 {
+        pub mod AuthenticatorSpec {
+          pub struct AuthenticatorSpec {
+            pub authenticatorType: crate::mangled::_7_android_8_hardware_7_keymint_25_HardwareAuthenticatorType, 
+            pub authenticatorId: i64, 
+          }
+          pub(crate) mod mangled { pub use super::AuthenticatorSpec as _7_android_8_security_9_keystore2_17_AuthenticatorSpec; }
+          impl Default for AuthenticatorSpec {
+            fn default() -> Self {
+              Self {
+                authenticatorType: Default::default(),
+                authenticatorId: 0,
+              }
+            }
+          }
+          impl binder::parcel::Serialize for AuthenticatorSpec {
+            fn serialize(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
+              <Self as binder::parcel::SerializeOption>::serialize_option(Some(self), parcel)
+            }
+          }
+          impl binder::parcel::SerializeArray for AuthenticatorSpec {}
+          impl binder::parcel::SerializeOption for AuthenticatorSpec {
+            fn serialize_option(this: Option<&Self>, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
+              let this = if let Some(this) = this {
+                parcel.write(&1i32)?;
+                this
+              } else {
+                return parcel.write(&0i32);
+              };
+              let start_pos = parcel.get_data_position();
+              parcel.write(&0i32)?;
+              parcel.write(&this.authenticatorType)?;
+              parcel.write(&this.authenticatorId)?;
+              let end_pos = parcel.get_data_position();
+              let parcelable_size = (end_pos - start_pos) as i32;
+              unsafe { parcel.set_data_position(start_pos)?; }
+              parcel.write(&parcelable_size)?;
+              unsafe { parcel.set_data_position(end_pos)?; }
+              Ok(())
+            }
+          }
+          impl binder::parcel::Deserialize for AuthenticatorSpec {
+            fn deserialize(parcel: &binder::parcel::Parcel) -> binder::Result<Self> {
+              <Self as binder::parcel::DeserializeOption>::deserialize_option(parcel)
+                 .transpose()
+                 .unwrap_or(Err(binder::StatusCode::UNEXPECTED_NULL))
+            }
+          }
+          impl binder::parcel::DeserializeArray for AuthenticatorSpec {}
+          impl binder::parcel::DeserializeOption for AuthenticatorSpec {
+            fn deserialize_option(parcel: &binder::parcel::Parcel) -> binder::Result<Option<Self>> {
+              let status: i32 = parcel.read()?;
+              if status == 0 { return Ok(None); }
+              let start_pos = parcel.get_data_position();
+              let parcelable_size: i32 = parcel.read()?;
+              if parcelable_size < 0 { return Err(binder::StatusCode::BAD_VALUE); }
+              let mut result = Self::default();
+              result.authenticatorType = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) >= parcelable_size {
+                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
+                return Ok(Some(result));
+              }
+              result.authenticatorId = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) >= parcelable_size {
+                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
+                return Ok(Some(result));
+              }
+              Ok(Some(result))
+            }
+          }
+        }
+        pub mod Certificate {
+          pub struct Certificate {
+            pub data: Vec<u8>, 
+          }
+          pub(crate) mod mangled { pub use super::Certificate as _7_android_8_security_9_keystore2_11_Certificate; }
+          impl Default for Certificate {
+            fn default() -> Self {
+              Self {
+                data: Default::default(),
+              }
+            }
+          }
+          impl binder::parcel::Serialize for Certificate {
+            fn serialize(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
+              <Self as binder::parcel::SerializeOption>::serialize_option(Some(self), parcel)
+            }
+          }
+          impl binder::parcel::SerializeArray for Certificate {}
+          impl binder::parcel::SerializeOption for Certificate {
+            fn serialize_option(this: Option<&Self>, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
+              let this = if let Some(this) = this {
+                parcel.write(&1i32)?;
+                this
+              } else {
+                return parcel.write(&0i32);
+              };
+              let start_pos = parcel.get_data_position();
+              parcel.write(&0i32)?;
+              parcel.write(&this.data)?;
+              let end_pos = parcel.get_data_position();
+              let parcelable_size = (end_pos - start_pos) as i32;
+              unsafe { parcel.set_data_position(start_pos)?; }
+              parcel.write(&parcelable_size)?;
+              unsafe { parcel.set_data_position(end_pos)?; }
+              Ok(())
+            }
+          }
+          impl binder::parcel::Deserialize for Certificate {
+            fn deserialize(parcel: &binder::parcel::Parcel) -> binder::Result<Self> {
+              <Self as binder::parcel::DeserializeOption>::deserialize_option(parcel)
+                 .transpose()
+                 .unwrap_or(Err(binder::StatusCode::UNEXPECTED_NULL))
+            }
+          }
+          impl binder::parcel::DeserializeArray for Certificate {}
+          impl binder::parcel::DeserializeOption for Certificate {
+            fn deserialize_option(parcel: &binder::parcel::Parcel) -> binder::Result<Option<Self>> {
+              let status: i32 = parcel.read()?;
+              if status == 0 { return Ok(None); }
+              let start_pos = parcel.get_data_position();
+              let parcelable_size: i32 = parcel.read()?;
+              if parcelable_size < 0 { return Err(binder::StatusCode::BAD_VALUE); }
+              let mut result = Self::default();
+              result.data = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) >= parcelable_size {
+                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
+                return Ok(Some(result));
+              }
+              Ok(Some(result))
+            }
+          }
+        }
+        pub mod CertificateChain {
+          pub struct CertificateChain {
+            pub certificates: Vec<crate::mangled::_7_android_8_security_9_keystore2_11_Certificate>, 
+          }
+          pub(crate) mod mangled { pub use super::CertificateChain as _7_android_8_security_9_keystore2_16_CertificateChain; }
+          impl Default for CertificateChain {
+            fn default() -> Self {
+              Self {
+                certificates: Default::default(),
+              }
+            }
+          }
+          impl binder::parcel::Serialize for CertificateChain {
+            fn serialize(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
+              <Self as binder::parcel::SerializeOption>::serialize_option(Some(self), parcel)
+            }
+          }
+          impl binder::parcel::SerializeArray for CertificateChain {}
+          impl binder::parcel::SerializeOption for CertificateChain {
+            fn serialize_option(this: Option<&Self>, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
+              let this = if let Some(this) = this {
+                parcel.write(&1i32)?;
+                this
+              } else {
+                return parcel.write(&0i32);
+              };
+              let start_pos = parcel.get_data_position();
+              parcel.write(&0i32)?;
+              parcel.write(&this.certificates)?;
+              let end_pos = parcel.get_data_position();
+              let parcelable_size = (end_pos - start_pos) as i32;
+              unsafe { parcel.set_data_position(start_pos)?; }
+              parcel.write(&parcelable_size)?;
+              unsafe { parcel.set_data_position(end_pos)?; }
+              Ok(())
+            }
+          }
+          impl binder::parcel::Deserialize for CertificateChain {
+            fn deserialize(parcel: &binder::parcel::Parcel) -> binder::Result<Self> {
+              <Self as binder::parcel::DeserializeOption>::deserialize_option(parcel)
+                 .transpose()
+                 .unwrap_or(Err(binder::StatusCode::UNEXPECTED_NULL))
+            }
+          }
+          impl binder::parcel::DeserializeArray for CertificateChain {}
+          impl binder::parcel::DeserializeOption for CertificateChain {
+            fn deserialize_option(parcel: &binder::parcel::Parcel) -> binder::Result<Option<Self>> {
+              let status: i32 = parcel.read()?;
+              if status == 0 { return Ok(None); }
+              let start_pos = parcel.get_data_position();
+              let parcelable_size: i32 = parcel.read()?;
+              if parcelable_size < 0 { return Err(binder::StatusCode::BAD_VALUE); }
+              let mut result = Self::default();
+              result.certificates = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) >= parcelable_size {
+                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
+                return Ok(Some(result));
+              }
+              Ok(Some(result))
+            }
+          }
+        }
+        pub mod Domain {
+          #![allow(non_upper_case_globals)]
+          pub type Domain = i32;
+          pub const App: Domain = 0;
+          pub const Grant: Domain = 1;
+          pub const SELinux: Domain = 2;
+          pub const Blob: Domain = 3;
+          pub const KeyId: Domain = 4;
+          pub(crate) mod mangled { pub use super::Domain as _7_android_8_security_9_keystore2_6_Domain; }
+        }
+        pub mod IKeystoreOperation {
+          #![allow(non_upper_case_globals)]
+          #![allow(non_snake_case)]
+          #[allow(unused_imports)] use binder::IBinder;
+          use binder::declare_binder_interface;
+          declare_binder_interface! {
+            IKeystoreOperation["android.security.keystore2.IKeystoreOperation"] {
+              native: BnKeystoreOperation(on_transact),
+              proxy: BpKeystoreOperation {
+              },
+            }
+          }
+          pub trait IKeystoreOperation: binder::Interface {
+            fn get_descriptor() -> &'static str where Self: Sized { "android.security.keystore2.IKeystoreOperation" }
+            fn update(&self, _arg_input: Option<&[u8]>, _arg_aadInput: Option<&[u8]>, _arg_output: &mut Option<Vec<u8>>) -> binder::public_api::Result<crate::mangled::_7_android_8_security_9_keystore2_6_Result> {
+              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+            }
+            fn finish(&self, _arg_input: Option<&[u8]>, _arg_signature: Option<&[u8]>, _arg_entropy: Option<&[u8]>, _arg_output: &mut Option<Vec<u8>>) -> binder::public_api::Result<crate::mangled::_7_android_8_security_9_keystore2_6_Result> {
+              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+            }
+            fn abort(&self) -> binder::public_api::Result<crate::mangled::_7_android_8_security_9_keystore2_6_Result> {
+              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+            }
+            fn getDefaultImpl() -> DefaultImpl where Self: Sized {
+              DEFAULT_IMPL.lock().unwrap().clone()
+            }
+            fn setDefaultImpl(d: DefaultImpl) -> DefaultImpl where Self: Sized {
+              std::mem::replace(&mut *DEFAULT_IMPL.lock().unwrap(), d)
+            }
+          }
+          pub const TRANSACTION_update: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 0;
+          pub const TRANSACTION_finish: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 1;
+          pub const TRANSACTION_abort: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 2;
+          pub type DefaultImpl = Option<std::sync::Arc<dyn IKeystoreOperation + Send + Sync>>;
+          use lazy_static::lazy_static;
+          lazy_static! {
+            static ref DEFAULT_IMPL: std::sync::Mutex<DefaultImpl> = std::sync::Mutex::new(None);
+          }
+          pub(crate) mod mangled { pub use super::IKeystoreOperation as _7_android_8_security_9_keystore2_18_IKeystoreOperation; }
+          impl IKeystoreOperation for BpKeystoreOperation {
+            fn update(&self, _arg_input: Option<&[u8]>, _arg_aadInput: Option<&[u8]>, _arg_output: &mut Option<Vec<u8>>) -> binder::public_api::Result<crate::mangled::_7_android_8_security_9_keystore2_6_Result> {
+              let _aidl_reply = self.binder.transact(TRANSACTION_update, 0, |_aidl_data| {
+                _aidl_data.write(&_arg_input)?;
+                _aidl_data.write(&_arg_aadInput)?;
+                _aidl_data.write_slice_size(_arg_output.as_deref())?;
+                Ok(())
+              });
+              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+                if let Some(_aidl_default_impl) = <Self as IKeystoreOperation>::getDefaultImpl() {
+                  return _aidl_default_impl.update(_arg_input, _arg_aadInput, _arg_output);
+                }
+              }
+              let _aidl_reply = _aidl_reply?;
+              let _aidl_status: binder::Status = _aidl_reply.read()?;
+              if !_aidl_status.is_ok() { return Err(_aidl_status); }
+              let _aidl_return: crate::mangled::_7_android_8_security_9_keystore2_6_Result = _aidl_reply.read()?;
+              *_arg_output = _aidl_reply.read()?;
+              Ok(_aidl_return)
+            }
+            fn finish(&self, _arg_input: Option<&[u8]>, _arg_signature: Option<&[u8]>, _arg_entropy: Option<&[u8]>, _arg_output: &mut Option<Vec<u8>>) -> binder::public_api::Result<crate::mangled::_7_android_8_security_9_keystore2_6_Result> {
+              let _aidl_reply = self.binder.transact(TRANSACTION_finish, 0, |_aidl_data| {
+                _aidl_data.write(&_arg_input)?;
+                _aidl_data.write(&_arg_signature)?;
+                _aidl_data.write(&_arg_entropy)?;
+                _aidl_data.write_slice_size(_arg_output.as_deref())?;
+                Ok(())
+              });
+              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+                if let Some(_aidl_default_impl) = <Self as IKeystoreOperation>::getDefaultImpl() {
+                  return _aidl_default_impl.finish(_arg_input, _arg_signature, _arg_entropy, _arg_output);
+                }
+              }
+              let _aidl_reply = _aidl_reply?;
+              let _aidl_status: binder::Status = _aidl_reply.read()?;
+              if !_aidl_status.is_ok() { return Err(_aidl_status); }
+              let _aidl_return: crate::mangled::_7_android_8_security_9_keystore2_6_Result = _aidl_reply.read()?;
+              *_arg_output = _aidl_reply.read()?;
+              Ok(_aidl_return)
+            }
+            fn abort(&self) -> binder::public_api::Result<crate::mangled::_7_android_8_security_9_keystore2_6_Result> {
+              let _aidl_reply = self.binder.transact(TRANSACTION_abort, 0, |_aidl_data| {
+                Ok(())
+              });
+              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+                if let Some(_aidl_default_impl) = <Self as IKeystoreOperation>::getDefaultImpl() {
+                  return _aidl_default_impl.abort();
+                }
+              }
+              let _aidl_reply = _aidl_reply?;
+              let _aidl_status: binder::Status = _aidl_reply.read()?;
+              if !_aidl_status.is_ok() { return Err(_aidl_status); }
+              let _aidl_return: crate::mangled::_7_android_8_security_9_keystore2_6_Result = _aidl_reply.read()?;
+              Ok(_aidl_return)
+            }
+          }
+          impl IKeystoreOperation for binder::Binder<BnKeystoreOperation> {
+            fn update(&self, _arg_input: Option<&[u8]>, _arg_aadInput: Option<&[u8]>, _arg_output: &mut Option<Vec<u8>>) -> binder::public_api::Result<crate::mangled::_7_android_8_security_9_keystore2_6_Result> { self.0.update(_arg_input, _arg_aadInput, _arg_output) }
+            fn finish(&self, _arg_input: Option<&[u8]>, _arg_signature: Option<&[u8]>, _arg_entropy: Option<&[u8]>, _arg_output: &mut Option<Vec<u8>>) -> binder::public_api::Result<crate::mangled::_7_android_8_security_9_keystore2_6_Result> { self.0.finish(_arg_input, _arg_signature, _arg_entropy, _arg_output) }
+            fn abort(&self) -> binder::public_api::Result<crate::mangled::_7_android_8_security_9_keystore2_6_Result> { self.0.abort() }
+          }
+          fn on_transact(_aidl_service: &dyn IKeystoreOperation, _aidl_code: binder::TransactionCode, _aidl_data: &binder::parcel::Parcel, _aidl_reply: &mut binder::parcel::Parcel) -> binder::Result<()> {
+            match _aidl_code {
+              TRANSACTION_update => {
+                let _arg_input: Option<Vec<u8>> = _aidl_data.read()?;
+                let _arg_aadInput: Option<Vec<u8>> = _aidl_data.read()?;
+                let mut _arg_output: Option<Vec<u8>> = Default::default();
+                _aidl_data.resize_nullable_out_vec(&mut _arg_output)?;
+                let _aidl_return = _aidl_service.update(_arg_input.as_deref(), _arg_aadInput.as_deref(), &mut _arg_output);
+                match &_aidl_return {
+                  Ok(_aidl_return) => {
+                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+                    _aidl_reply.write(_aidl_return)?;
+                    _aidl_reply.write(&_arg_output)?;
+                  }
+                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+                }
+                Ok(())
+              }
+              TRANSACTION_finish => {
+                let _arg_input: Option<Vec<u8>> = _aidl_data.read()?;
+                let _arg_signature: Option<Vec<u8>> = _aidl_data.read()?;
+                let _arg_entropy: Option<Vec<u8>> = _aidl_data.read()?;
+                let mut _arg_output: Option<Vec<u8>> = Default::default();
+                _aidl_data.resize_nullable_out_vec(&mut _arg_output)?;
+                let _aidl_return = _aidl_service.finish(_arg_input.as_deref(), _arg_signature.as_deref(), _arg_entropy.as_deref(), &mut _arg_output);
+                match &_aidl_return {
+                  Ok(_aidl_return) => {
+                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+                    _aidl_reply.write(_aidl_return)?;
+                    _aidl_reply.write(&_arg_output)?;
+                  }
+                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+                }
+                Ok(())
+              }
+              TRANSACTION_abort => {
+                let _aidl_return = _aidl_service.abort();
+                match &_aidl_return {
+                  Ok(_aidl_return) => {
+                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+                    _aidl_reply.write(_aidl_return)?;
+                  }
+                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+                }
+                Ok(())
+              }
+              _ => Err(binder::StatusCode::UNKNOWN_TRANSACTION)
+            }
+          }
+        }
+        pub mod IKeystoreSecurityLevel {
+          #![allow(non_upper_case_globals)]
+          #![allow(non_snake_case)]
+          #[allow(unused_imports)] use binder::IBinder;
+          use binder::declare_binder_interface;
+          declare_binder_interface! {
+            IKeystoreSecurityLevel["android.security.keystore2.IKeystoreSecurityLevel"] {
+              native: BnKeystoreSecurityLevel(on_transact),
+              proxy: BpKeystoreSecurityLevel {
+              },
+            }
+          }
+          pub trait IKeystoreSecurityLevel: binder::Interface {
+            fn get_descriptor() -> &'static str where Self: Sized { "android.security.keystore2.IKeystoreSecurityLevel" }
+            fn create(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_operationParameters: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_forced: bool, _arg_challenge: &mut crate::mangled::_7_android_8_security_9_keystore2_18_OperationChallenge, _arg_rc: &mut crate::mangled::_7_android_8_security_9_keystore2_6_Result) -> binder::public_api::Result<Box<dyn crate::mangled::_7_android_8_security_9_keystore2_18_IKeystoreOperation>> {
+              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+            }
+            fn updateSubcomponent(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_publicKey: Option<&crate::mangled::_7_android_8_security_9_keystore2_9_PublicKey>, _arg_certificateChain: Option<&crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain>) -> binder::public_api::Result<crate::mangled::_7_android_8_security_9_keystore2_6_Result> {
+              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+            }
+            fn generateKey(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_params: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_entropy: &[u8], _arg_resultKey: &mut crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_publicKey: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_9_PublicKey>, _arg_certificateChain: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain>) -> binder::public_api::Result<crate::mangled::_7_android_8_security_9_keystore2_6_Result> {
+              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+            }
+            fn importKey(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_params: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_keyData: &[u8], _arg_resultKey: &mut crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_publicKey: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_9_PublicKey>, _arg_certificateChain: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain>) -> binder::public_api::Result<crate::mangled::_7_android_8_security_9_keystore2_6_Result> {
+              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+            }
+            fn importWrappedKey(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_wrappingKey: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_maskingKey: &[u8], _arg_params: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_authenticators: &[crate::mangled::_7_android_8_security_9_keystore2_17_AuthenticatorSpec], _arg_resultKey: &mut crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_publicKey: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_9_PublicKey>, _arg_certificateChain: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain>) -> binder::public_api::Result<crate::mangled::_7_android_8_security_9_keystore2_6_Result> {
+              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+            }
+            fn getDefaultImpl() -> DefaultImpl where Self: Sized {
+              DEFAULT_IMPL.lock().unwrap().clone()
+            }
+            fn setDefaultImpl(d: DefaultImpl) -> DefaultImpl where Self: Sized {
+              std::mem::replace(&mut *DEFAULT_IMPL.lock().unwrap(), d)
+            }
+          }
+          pub const TRANSACTION_create: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 0;
+          pub const TRANSACTION_updateSubcomponent: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 1;
+          pub const TRANSACTION_generateKey: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 2;
+          pub const TRANSACTION_importKey: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 3;
+          pub const TRANSACTION_importWrappedKey: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 4;
+          pub type DefaultImpl = Option<std::sync::Arc<dyn IKeystoreSecurityLevel + Send + Sync>>;
+          use lazy_static::lazy_static;
+          lazy_static! {
+            static ref DEFAULT_IMPL: std::sync::Mutex<DefaultImpl> = std::sync::Mutex::new(None);
+          }
+          pub(crate) mod mangled { pub use super::IKeystoreSecurityLevel as _7_android_8_security_9_keystore2_22_IKeystoreSecurityLevel; }
+          impl IKeystoreSecurityLevel for BpKeystoreSecurityLevel {
+            fn create(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_operationParameters: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_forced: bool, _arg_challenge: &mut crate::mangled::_7_android_8_security_9_keystore2_18_OperationChallenge, _arg_rc: &mut crate::mangled::_7_android_8_security_9_keystore2_6_Result) -> binder::public_api::Result<Box<dyn crate::mangled::_7_android_8_security_9_keystore2_18_IKeystoreOperation>> {
+              let _aidl_reply = self.binder.transact(TRANSACTION_create, 0, |_aidl_data| {
+                _aidl_data.write(_arg_key)?;
+                _aidl_data.write(_arg_operationParameters)?;
+                _aidl_data.write(&_arg_forced)?;
+                Ok(())
+              });
+              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+                if let Some(_aidl_default_impl) = <Self as IKeystoreSecurityLevel>::getDefaultImpl() {
+                  return _aidl_default_impl.create(_arg_key, _arg_operationParameters, _arg_forced, _arg_challenge, _arg_rc);
+                }
+              }
+              let _aidl_reply = _aidl_reply?;
+              let _aidl_status: binder::Status = _aidl_reply.read()?;
+              if !_aidl_status.is_ok() { return Err(_aidl_status); }
+              let _aidl_return: Box<dyn crate::mangled::_7_android_8_security_9_keystore2_18_IKeystoreOperation> = _aidl_reply.read()?;
+              *_arg_challenge = _aidl_reply.read()?;
+              *_arg_rc = _aidl_reply.read()?;
+              Ok(_aidl_return)
+            }
+            fn updateSubcomponent(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_publicKey: Option<&crate::mangled::_7_android_8_security_9_keystore2_9_PublicKey>, _arg_certificateChain: Option<&crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain>) -> binder::public_api::Result<crate::mangled::_7_android_8_security_9_keystore2_6_Result> {
+              let _aidl_reply = self.binder.transact(TRANSACTION_updateSubcomponent, 0, |_aidl_data| {
+                _aidl_data.write(_arg_key)?;
+                _aidl_data.write(&_arg_publicKey)?;
+                _aidl_data.write(&_arg_certificateChain)?;
+                Ok(())
+              });
+              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+                if let Some(_aidl_default_impl) = <Self as IKeystoreSecurityLevel>::getDefaultImpl() {
+                  return _aidl_default_impl.updateSubcomponent(_arg_key, _arg_publicKey, _arg_certificateChain);
+                }
+              }
+              let _aidl_reply = _aidl_reply?;
+              let _aidl_status: binder::Status = _aidl_reply.read()?;
+              if !_aidl_status.is_ok() { return Err(_aidl_status); }
+              let _aidl_return: crate::mangled::_7_android_8_security_9_keystore2_6_Result = _aidl_reply.read()?;
+              Ok(_aidl_return)
+            }
+            fn generateKey(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_params: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_entropy: &[u8], _arg_resultKey: &mut crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_publicKey: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_9_PublicKey>, _arg_certificateChain: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain>) -> binder::public_api::Result<crate::mangled::_7_android_8_security_9_keystore2_6_Result> {
+              let _aidl_reply = self.binder.transact(TRANSACTION_generateKey, 0, |_aidl_data| {
+                _aidl_data.write(_arg_key)?;
+                _aidl_data.write(_arg_params)?;
+                _aidl_data.write(_arg_entropy)?;
+                Ok(())
+              });
+              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+                if let Some(_aidl_default_impl) = <Self as IKeystoreSecurityLevel>::getDefaultImpl() {
+                  return _aidl_default_impl.generateKey(_arg_key, _arg_params, _arg_entropy, _arg_resultKey, _arg_publicKey, _arg_certificateChain);
+                }
+              }
+              let _aidl_reply = _aidl_reply?;
+              let _aidl_status: binder::Status = _aidl_reply.read()?;
+              if !_aidl_status.is_ok() { return Err(_aidl_status); }
+              let _aidl_return: crate::mangled::_7_android_8_security_9_keystore2_6_Result = _aidl_reply.read()?;
+              *_arg_resultKey = _aidl_reply.read()?;
+              *_arg_publicKey = _aidl_reply.read()?;
+              *_arg_certificateChain = _aidl_reply.read()?;
+              Ok(_aidl_return)
+            }
+            fn importKey(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_params: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_keyData: &[u8], _arg_resultKey: &mut crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_publicKey: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_9_PublicKey>, _arg_certificateChain: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain>) -> binder::public_api::Result<crate::mangled::_7_android_8_security_9_keystore2_6_Result> {
+              let _aidl_reply = self.binder.transact(TRANSACTION_importKey, 0, |_aidl_data| {
+                _aidl_data.write(_arg_key)?;
+                _aidl_data.write(_arg_params)?;
+                _aidl_data.write(_arg_keyData)?;
+                Ok(())
+              });
+              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+                if let Some(_aidl_default_impl) = <Self as IKeystoreSecurityLevel>::getDefaultImpl() {
+                  return _aidl_default_impl.importKey(_arg_key, _arg_params, _arg_keyData, _arg_resultKey, _arg_publicKey, _arg_certificateChain);
+                }
+              }
+              let _aidl_reply = _aidl_reply?;
+              let _aidl_status: binder::Status = _aidl_reply.read()?;
+              if !_aidl_status.is_ok() { return Err(_aidl_status); }
+              let _aidl_return: crate::mangled::_7_android_8_security_9_keystore2_6_Result = _aidl_reply.read()?;
+              *_arg_resultKey = _aidl_reply.read()?;
+              *_arg_publicKey = _aidl_reply.read()?;
+              *_arg_certificateChain = _aidl_reply.read()?;
+              Ok(_aidl_return)
+            }
+            fn importWrappedKey(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_wrappingKey: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_maskingKey: &[u8], _arg_params: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_authenticators: &[crate::mangled::_7_android_8_security_9_keystore2_17_AuthenticatorSpec], _arg_resultKey: &mut crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_publicKey: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_9_PublicKey>, _arg_certificateChain: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain>) -> binder::public_api::Result<crate::mangled::_7_android_8_security_9_keystore2_6_Result> {
+              let _aidl_reply = self.binder.transact(TRANSACTION_importWrappedKey, 0, |_aidl_data| {
+                _aidl_data.write(_arg_key)?;
+                _aidl_data.write(_arg_wrappingKey)?;
+                _aidl_data.write(_arg_maskingKey)?;
+                _aidl_data.write(_arg_params)?;
+                _aidl_data.write(_arg_authenticators)?;
+                Ok(())
+              });
+              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+                if let Some(_aidl_default_impl) = <Self as IKeystoreSecurityLevel>::getDefaultImpl() {
+                  return _aidl_default_impl.importWrappedKey(_arg_key, _arg_wrappingKey, _arg_maskingKey, _arg_params, _arg_authenticators, _arg_resultKey, _arg_publicKey, _arg_certificateChain);
+                }
+              }
+              let _aidl_reply = _aidl_reply?;
+              let _aidl_status: binder::Status = _aidl_reply.read()?;
+              if !_aidl_status.is_ok() { return Err(_aidl_status); }
+              let _aidl_return: crate::mangled::_7_android_8_security_9_keystore2_6_Result = _aidl_reply.read()?;
+              *_arg_resultKey = _aidl_reply.read()?;
+              *_arg_publicKey = _aidl_reply.read()?;
+              *_arg_certificateChain = _aidl_reply.read()?;
+              Ok(_aidl_return)
+            }
+          }
+          impl IKeystoreSecurityLevel for binder::Binder<BnKeystoreSecurityLevel> {
+            fn create(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_operationParameters: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_forced: bool, _arg_challenge: &mut crate::mangled::_7_android_8_security_9_keystore2_18_OperationChallenge, _arg_rc: &mut crate::mangled::_7_android_8_security_9_keystore2_6_Result) -> binder::public_api::Result<Box<dyn crate::mangled::_7_android_8_security_9_keystore2_18_IKeystoreOperation>> { self.0.create(_arg_key, _arg_operationParameters, _arg_forced, _arg_challenge, _arg_rc) }
+            fn updateSubcomponent(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_publicKey: Option<&crate::mangled::_7_android_8_security_9_keystore2_9_PublicKey>, _arg_certificateChain: Option<&crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain>) -> binder::public_api::Result<crate::mangled::_7_android_8_security_9_keystore2_6_Result> { self.0.updateSubcomponent(_arg_key, _arg_publicKey, _arg_certificateChain) }
+            fn generateKey(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_params: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_entropy: &[u8], _arg_resultKey: &mut crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_publicKey: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_9_PublicKey>, _arg_certificateChain: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain>) -> binder::public_api::Result<crate::mangled::_7_android_8_security_9_keystore2_6_Result> { self.0.generateKey(_arg_key, _arg_params, _arg_entropy, _arg_resultKey, _arg_publicKey, _arg_certificateChain) }
+            fn importKey(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_params: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_keyData: &[u8], _arg_resultKey: &mut crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_publicKey: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_9_PublicKey>, _arg_certificateChain: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain>) -> binder::public_api::Result<crate::mangled::_7_android_8_security_9_keystore2_6_Result> { self.0.importKey(_arg_key, _arg_params, _arg_keyData, _arg_resultKey, _arg_publicKey, _arg_certificateChain) }
+            fn importWrappedKey(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_wrappingKey: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_maskingKey: &[u8], _arg_params: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_authenticators: &[crate::mangled::_7_android_8_security_9_keystore2_17_AuthenticatorSpec], _arg_resultKey: &mut crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_publicKey: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_9_PublicKey>, _arg_certificateChain: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain>) -> binder::public_api::Result<crate::mangled::_7_android_8_security_9_keystore2_6_Result> { self.0.importWrappedKey(_arg_key, _arg_wrappingKey, _arg_maskingKey, _arg_params, _arg_authenticators, _arg_resultKey, _arg_publicKey, _arg_certificateChain) }
+          }
+          fn on_transact(_aidl_service: &dyn IKeystoreSecurityLevel, _aidl_code: binder::TransactionCode, _aidl_data: &binder::parcel::Parcel, _aidl_reply: &mut binder::parcel::Parcel) -> binder::Result<()> {
+            match _aidl_code {
+              TRANSACTION_create => {
+                let _arg_key: crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor = _aidl_data.read()?;
+                let _arg_operationParameters: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter> = _aidl_data.read()?;
+                let _arg_forced: bool = _aidl_data.read()?;
+                let mut _arg_challenge: crate::mangled::_7_android_8_security_9_keystore2_18_OperationChallenge = Default::default();
+                let mut _arg_rc: crate::mangled::_7_android_8_security_9_keystore2_6_Result = Default::default();
+                let _aidl_return = _aidl_service.create(&_arg_key, &_arg_operationParameters, _arg_forced, &mut _arg_challenge, &mut _arg_rc);
+                match &_aidl_return {
+                  Ok(_aidl_return) => {
+                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+                    _aidl_reply.write(_aidl_return)?;
+                    _aidl_reply.write(&_arg_challenge)?;
+                    _aidl_reply.write(&_arg_rc)?;
+                  }
+                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+                }
+                Ok(())
+              }
+              TRANSACTION_updateSubcomponent => {
+                let _arg_key: crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor = _aidl_data.read()?;
+                let _arg_publicKey: Option<crate::mangled::_7_android_8_security_9_keystore2_9_PublicKey> = _aidl_data.read()?;
+                let _arg_certificateChain: Option<crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain> = _aidl_data.read()?;
+                let _aidl_return = _aidl_service.updateSubcomponent(&_arg_key, _arg_publicKey.as_ref(), _arg_certificateChain.as_ref());
+                match &_aidl_return {
+                  Ok(_aidl_return) => {
+                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+                    _aidl_reply.write(_aidl_return)?;
+                  }
+                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+                }
+                Ok(())
+              }
+              TRANSACTION_generateKey => {
+                let _arg_key: crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor = _aidl_data.read()?;
+                let _arg_params: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter> = _aidl_data.read()?;
+                let _arg_entropy: Vec<u8> = _aidl_data.read()?;
+                let mut _arg_resultKey: crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor = Default::default();
+                let mut _arg_publicKey: Option<crate::mangled::_7_android_8_security_9_keystore2_9_PublicKey> = Default::default();
+                let mut _arg_certificateChain: Option<crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain> = Default::default();
+                let _aidl_return = _aidl_service.generateKey(&_arg_key, &_arg_params, &_arg_entropy, &mut _arg_resultKey, &mut _arg_publicKey, &mut _arg_certificateChain);
+                match &_aidl_return {
+                  Ok(_aidl_return) => {
+                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+                    _aidl_reply.write(_aidl_return)?;
+                    _aidl_reply.write(&_arg_resultKey)?;
+                    _aidl_reply.write(&_arg_publicKey)?;
+                    _aidl_reply.write(&_arg_certificateChain)?;
+                  }
+                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+                }
+                Ok(())
+              }
+              TRANSACTION_importKey => {
+                let _arg_key: crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor = _aidl_data.read()?;
+                let _arg_params: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter> = _aidl_data.read()?;
+                let _arg_keyData: Vec<u8> = _aidl_data.read()?;
+                let mut _arg_resultKey: crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor = Default::default();
+                let mut _arg_publicKey: Option<crate::mangled::_7_android_8_security_9_keystore2_9_PublicKey> = Default::default();
+                let mut _arg_certificateChain: Option<crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain> = Default::default();
+                let _aidl_return = _aidl_service.importKey(&_arg_key, &_arg_params, &_arg_keyData, &mut _arg_resultKey, &mut _arg_publicKey, &mut _arg_certificateChain);
+                match &_aidl_return {
+                  Ok(_aidl_return) => {
+                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+                    _aidl_reply.write(_aidl_return)?;
+                    _aidl_reply.write(&_arg_resultKey)?;
+                    _aidl_reply.write(&_arg_publicKey)?;
+                    _aidl_reply.write(&_arg_certificateChain)?;
+                  }
+                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+                }
+                Ok(())
+              }
+              TRANSACTION_importWrappedKey => {
+                let _arg_key: crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor = _aidl_data.read()?;
+                let _arg_wrappingKey: crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor = _aidl_data.read()?;
+                let _arg_maskingKey: Vec<u8> = _aidl_data.read()?;
+                let _arg_params: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter> = _aidl_data.read()?;
+                let _arg_authenticators: Vec<crate::mangled::_7_android_8_security_9_keystore2_17_AuthenticatorSpec> = _aidl_data.read()?;
+                let mut _arg_resultKey: crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor = Default::default();
+                let mut _arg_publicKey: Option<crate::mangled::_7_android_8_security_9_keystore2_9_PublicKey> = Default::default();
+                let mut _arg_certificateChain: Option<crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain> = Default::default();
+                let _aidl_return = _aidl_service.importWrappedKey(&_arg_key, &_arg_wrappingKey, &_arg_maskingKey, &_arg_params, &_arg_authenticators, &mut _arg_resultKey, &mut _arg_publicKey, &mut _arg_certificateChain);
+                match &_aidl_return {
+                  Ok(_aidl_return) => {
+                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+                    _aidl_reply.write(_aidl_return)?;
+                    _aidl_reply.write(&_arg_resultKey)?;
+                    _aidl_reply.write(&_arg_publicKey)?;
+                    _aidl_reply.write(&_arg_certificateChain)?;
+                  }
+                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+                }
+                Ok(())
+              }
+              _ => Err(binder::StatusCode::UNKNOWN_TRANSACTION)
+            }
+          }
+        }
+        pub mod IKeystoreService {
+          #![allow(non_upper_case_globals)]
+          #![allow(non_snake_case)]
+          #[allow(unused_imports)] use binder::IBinder;
+          use binder::declare_binder_interface;
+          declare_binder_interface! {
+            IKeystoreService["android.security.keystore2.IKeystoreService"] {
+              native: BnKeystoreService(on_transact),
+              proxy: BpKeystoreService {
+              },
+            }
+          }
+          pub trait IKeystoreService: binder::Interface {
+            fn get_descriptor() -> &'static str where Self: Sized { "android.security.keystore2.IKeystoreService" }
+            fn getSecurityLevel(&self, _arg_securityLevel: crate::mangled::_7_android_8_hardware_7_keymint_13_SecurityLevel, _arg_rc: &mut crate::mangled::_7_android_8_security_9_keystore2_6_Result) -> binder::public_api::Result<Box<dyn crate::mangled::_7_android_8_security_9_keystore2_22_IKeystoreSecurityLevel>> {
+              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+            }
+            fn getKeyEntry(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_metadata: &mut crate::mangled::_7_android_8_security_9_keystore2_11_KeyMetadata, _arg_publicKey: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_9_PublicKey>, _arg_certificateChain: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain>, _arg_rc: &mut crate::mangled::_7_android_8_security_9_keystore2_6_Result) -> binder::public_api::Result<Box<dyn crate::mangled::_7_android_8_security_9_keystore2_22_IKeystoreSecurityLevel>> {
+              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+            }
+            fn listEntries(&self, _arg_domain: crate::mangled::_7_android_8_security_9_keystore2_6_Domain, _arg_nameSpace: i64, _arg_list: &mut Vec<crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor>) -> binder::public_api::Result<crate::mangled::_7_android_8_security_9_keystore2_6_Result> {
+              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+            }
+            fn deleteKey(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor) -> binder::public_api::Result<crate::mangled::_7_android_8_security_9_keystore2_6_Result> {
+              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+            }
+            fn grant(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_granteeUid: i32, _arg_accessVector: i32, _arg_grantKey: &mut crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor) -> binder::public_api::Result<crate::mangled::_7_android_8_security_9_keystore2_6_Result> {
+              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+            }
+            fn ungrant(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_granteeUid: i32) -> binder::public_api::Result<crate::mangled::_7_android_8_security_9_keystore2_6_Result> {
+              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+            }
+            fn getDefaultImpl() -> DefaultImpl where Self: Sized {
+              DEFAULT_IMPL.lock().unwrap().clone()
+            }
+            fn setDefaultImpl(d: DefaultImpl) -> DefaultImpl where Self: Sized {
+              std::mem::replace(&mut *DEFAULT_IMPL.lock().unwrap(), d)
+            }
+          }
+          pub const TRANSACTION_getSecurityLevel: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 0;
+          pub const TRANSACTION_getKeyEntry: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 1;
+          pub const TRANSACTION_listEntries: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 2;
+          pub const TRANSACTION_deleteKey: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 3;
+          pub const TRANSACTION_grant: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 4;
+          pub const TRANSACTION_ungrant: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 5;
+          pub type DefaultImpl = Option<std::sync::Arc<dyn IKeystoreService + Send + Sync>>;
+          use lazy_static::lazy_static;
+          lazy_static! {
+            static ref DEFAULT_IMPL: std::sync::Mutex<DefaultImpl> = std::sync::Mutex::new(None);
+          }
+          pub(crate) mod mangled { pub use super::IKeystoreService as _7_android_8_security_9_keystore2_16_IKeystoreService; }
+          impl IKeystoreService for BpKeystoreService {
+            fn getSecurityLevel(&self, _arg_securityLevel: crate::mangled::_7_android_8_hardware_7_keymint_13_SecurityLevel, _arg_rc: &mut crate::mangled::_7_android_8_security_9_keystore2_6_Result) -> binder::public_api::Result<Box<dyn crate::mangled::_7_android_8_security_9_keystore2_22_IKeystoreSecurityLevel>> {
+              let _aidl_reply = self.binder.transact(TRANSACTION_getSecurityLevel, 0, |_aidl_data| {
+                _aidl_data.write(&_arg_securityLevel)?;
+                Ok(())
+              });
+              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+                if let Some(_aidl_default_impl) = <Self as IKeystoreService>::getDefaultImpl() {
+                  return _aidl_default_impl.getSecurityLevel(_arg_securityLevel, _arg_rc);
+                }
+              }
+              let _aidl_reply = _aidl_reply?;
+              let _aidl_status: binder::Status = _aidl_reply.read()?;
+              if !_aidl_status.is_ok() { return Err(_aidl_status); }
+              let _aidl_return: Box<dyn crate::mangled::_7_android_8_security_9_keystore2_22_IKeystoreSecurityLevel> = _aidl_reply.read()?;
+              *_arg_rc = _aidl_reply.read()?;
+              Ok(_aidl_return)
+            }
+            fn getKeyEntry(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_metadata: &mut crate::mangled::_7_android_8_security_9_keystore2_11_KeyMetadata, _arg_publicKey: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_9_PublicKey>, _arg_certificateChain: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain>, _arg_rc: &mut crate::mangled::_7_android_8_security_9_keystore2_6_Result) -> binder::public_api::Result<Box<dyn crate::mangled::_7_android_8_security_9_keystore2_22_IKeystoreSecurityLevel>> {
+              let _aidl_reply = self.binder.transact(TRANSACTION_getKeyEntry, 0, |_aidl_data| {
+                _aidl_data.write(_arg_key)?;
+                Ok(())
+              });
+              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+                if let Some(_aidl_default_impl) = <Self as IKeystoreService>::getDefaultImpl() {
+                  return _aidl_default_impl.getKeyEntry(_arg_key, _arg_metadata, _arg_publicKey, _arg_certificateChain, _arg_rc);
+                }
+              }
+              let _aidl_reply = _aidl_reply?;
+              let _aidl_status: binder::Status = _aidl_reply.read()?;
+              if !_aidl_status.is_ok() { return Err(_aidl_status); }
+              let _aidl_return: Box<dyn crate::mangled::_7_android_8_security_9_keystore2_22_IKeystoreSecurityLevel> = _aidl_reply.read()?;
+              *_arg_metadata = _aidl_reply.read()?;
+              *_arg_publicKey = _aidl_reply.read()?;
+              *_arg_certificateChain = _aidl_reply.read()?;
+              *_arg_rc = _aidl_reply.read()?;
+              Ok(_aidl_return)
+            }
+            fn listEntries(&self, _arg_domain: crate::mangled::_7_android_8_security_9_keystore2_6_Domain, _arg_nameSpace: i64, _arg_list: &mut Vec<crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor>) -> binder::public_api::Result<crate::mangled::_7_android_8_security_9_keystore2_6_Result> {
+              let _aidl_reply = self.binder.transact(TRANSACTION_listEntries, 0, |_aidl_data| {
+                _aidl_data.write(&_arg_domain)?;
+                _aidl_data.write(&_arg_nameSpace)?;
+                _aidl_data.write_slice_size(Some(_arg_list))?;
+                Ok(())
+              });
+              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+                if let Some(_aidl_default_impl) = <Self as IKeystoreService>::getDefaultImpl() {
+                  return _aidl_default_impl.listEntries(_arg_domain, _arg_nameSpace, _arg_list);
+                }
+              }
+              let _aidl_reply = _aidl_reply?;
+              let _aidl_status: binder::Status = _aidl_reply.read()?;
+              if !_aidl_status.is_ok() { return Err(_aidl_status); }
+              let _aidl_return: crate::mangled::_7_android_8_security_9_keystore2_6_Result = _aidl_reply.read()?;
+              *_arg_list = _aidl_reply.read()?;
+              Ok(_aidl_return)
+            }
+            fn deleteKey(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor) -> binder::public_api::Result<crate::mangled::_7_android_8_security_9_keystore2_6_Result> {
+              let _aidl_reply = self.binder.transact(TRANSACTION_deleteKey, 0, |_aidl_data| {
+                _aidl_data.write(_arg_key)?;
+                Ok(())
+              });
+              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+                if let Some(_aidl_default_impl) = <Self as IKeystoreService>::getDefaultImpl() {
+                  return _aidl_default_impl.deleteKey(_arg_key);
+                }
+              }
+              let _aidl_reply = _aidl_reply?;
+              let _aidl_status: binder::Status = _aidl_reply.read()?;
+              if !_aidl_status.is_ok() { return Err(_aidl_status); }
+              let _aidl_return: crate::mangled::_7_android_8_security_9_keystore2_6_Result = _aidl_reply.read()?;
+              Ok(_aidl_return)
+            }
+            fn grant(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_granteeUid: i32, _arg_accessVector: i32, _arg_grantKey: &mut crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor) -> binder::public_api::Result<crate::mangled::_7_android_8_security_9_keystore2_6_Result> {
+              let _aidl_reply = self.binder.transact(TRANSACTION_grant, 0, |_aidl_data| {
+                _aidl_data.write(_arg_key)?;
+                _aidl_data.write(&_arg_granteeUid)?;
+                _aidl_data.write(&_arg_accessVector)?;
+                Ok(())
+              });
+              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+                if let Some(_aidl_default_impl) = <Self as IKeystoreService>::getDefaultImpl() {
+                  return _aidl_default_impl.grant(_arg_key, _arg_granteeUid, _arg_accessVector, _arg_grantKey);
+                }
+              }
+              let _aidl_reply = _aidl_reply?;
+              let _aidl_status: binder::Status = _aidl_reply.read()?;
+              if !_aidl_status.is_ok() { return Err(_aidl_status); }
+              let _aidl_return: crate::mangled::_7_android_8_security_9_keystore2_6_Result = _aidl_reply.read()?;
+              *_arg_grantKey = _aidl_reply.read()?;
+              Ok(_aidl_return)
+            }
+            fn ungrant(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_granteeUid: i32) -> binder::public_api::Result<crate::mangled::_7_android_8_security_9_keystore2_6_Result> {
+              let _aidl_reply = self.binder.transact(TRANSACTION_ungrant, 0, |_aidl_data| {
+                _aidl_data.write(_arg_key)?;
+                _aidl_data.write(&_arg_granteeUid)?;
+                Ok(())
+              });
+              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+                if let Some(_aidl_default_impl) = <Self as IKeystoreService>::getDefaultImpl() {
+                  return _aidl_default_impl.ungrant(_arg_key, _arg_granteeUid);
+                }
+              }
+              let _aidl_reply = _aidl_reply?;
+              let _aidl_status: binder::Status = _aidl_reply.read()?;
+              if !_aidl_status.is_ok() { return Err(_aidl_status); }
+              let _aidl_return: crate::mangled::_7_android_8_security_9_keystore2_6_Result = _aidl_reply.read()?;
+              Ok(_aidl_return)
+            }
+          }
+          impl IKeystoreService for binder::Binder<BnKeystoreService> {
+            fn getSecurityLevel(&self, _arg_securityLevel: crate::mangled::_7_android_8_hardware_7_keymint_13_SecurityLevel, _arg_rc: &mut crate::mangled::_7_android_8_security_9_keystore2_6_Result) -> binder::public_api::Result<Box<dyn crate::mangled::_7_android_8_security_9_keystore2_22_IKeystoreSecurityLevel>> { self.0.getSecurityLevel(_arg_securityLevel, _arg_rc) }
+            fn getKeyEntry(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_metadata: &mut crate::mangled::_7_android_8_security_9_keystore2_11_KeyMetadata, _arg_publicKey: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_9_PublicKey>, _arg_certificateChain: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain>, _arg_rc: &mut crate::mangled::_7_android_8_security_9_keystore2_6_Result) -> binder::public_api::Result<Box<dyn crate::mangled::_7_android_8_security_9_keystore2_22_IKeystoreSecurityLevel>> { self.0.getKeyEntry(_arg_key, _arg_metadata, _arg_publicKey, _arg_certificateChain, _arg_rc) }
+            fn listEntries(&self, _arg_domain: crate::mangled::_7_android_8_security_9_keystore2_6_Domain, _arg_nameSpace: i64, _arg_list: &mut Vec<crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor>) -> binder::public_api::Result<crate::mangled::_7_android_8_security_9_keystore2_6_Result> { self.0.listEntries(_arg_domain, _arg_nameSpace, _arg_list) }
+            fn deleteKey(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor) -> binder::public_api::Result<crate::mangled::_7_android_8_security_9_keystore2_6_Result> { self.0.deleteKey(_arg_key) }
+            fn grant(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_granteeUid: i32, _arg_accessVector: i32, _arg_grantKey: &mut crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor) -> binder::public_api::Result<crate::mangled::_7_android_8_security_9_keystore2_6_Result> { self.0.grant(_arg_key, _arg_granteeUid, _arg_accessVector, _arg_grantKey) }
+            fn ungrant(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_granteeUid: i32) -> binder::public_api::Result<crate::mangled::_7_android_8_security_9_keystore2_6_Result> { self.0.ungrant(_arg_key, _arg_granteeUid) }
+          }
+          fn on_transact(_aidl_service: &dyn IKeystoreService, _aidl_code: binder::TransactionCode, _aidl_data: &binder::parcel::Parcel, _aidl_reply: &mut binder::parcel::Parcel) -> binder::Result<()> {
+            match _aidl_code {
+              TRANSACTION_getSecurityLevel => {
+                let _arg_securityLevel: crate::mangled::_7_android_8_hardware_7_keymint_13_SecurityLevel = _aidl_data.read()?;
+                let mut _arg_rc: crate::mangled::_7_android_8_security_9_keystore2_6_Result = Default::default();
+                let _aidl_return = _aidl_service.getSecurityLevel(_arg_securityLevel, &mut _arg_rc);
+                match &_aidl_return {
+                  Ok(_aidl_return) => {
+                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+                    _aidl_reply.write(_aidl_return)?;
+                    _aidl_reply.write(&_arg_rc)?;
+                  }
+                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+                }
+                Ok(())
+              }
+              TRANSACTION_getKeyEntry => {
+                let _arg_key: crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor = _aidl_data.read()?;
+                let mut _arg_metadata: crate::mangled::_7_android_8_security_9_keystore2_11_KeyMetadata = Default::default();
+                let mut _arg_publicKey: Option<crate::mangled::_7_android_8_security_9_keystore2_9_PublicKey> = Default::default();
+                let mut _arg_certificateChain: Option<crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain> = Default::default();
+                let mut _arg_rc: crate::mangled::_7_android_8_security_9_keystore2_6_Result = Default::default();
+                let _aidl_return = _aidl_service.getKeyEntry(&_arg_key, &mut _arg_metadata, &mut _arg_publicKey, &mut _arg_certificateChain, &mut _arg_rc);
+                match &_aidl_return {
+                  Ok(_aidl_return) => {
+                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+                    _aidl_reply.write(_aidl_return)?;
+                    _aidl_reply.write(&_arg_metadata)?;
+                    _aidl_reply.write(&_arg_publicKey)?;
+                    _aidl_reply.write(&_arg_certificateChain)?;
+                    _aidl_reply.write(&_arg_rc)?;
+                  }
+                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+                }
+                Ok(())
+              }
+              TRANSACTION_listEntries => {
+                let _arg_domain: crate::mangled::_7_android_8_security_9_keystore2_6_Domain = _aidl_data.read()?;
+                let _arg_nameSpace: i64 = _aidl_data.read()?;
+                let mut _arg_list: Vec<crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor> = Default::default();
+                _aidl_data.resize_out_vec(&mut _arg_list)?;
+                let _aidl_return = _aidl_service.listEntries(_arg_domain, _arg_nameSpace, &mut _arg_list);
+                match &_aidl_return {
+                  Ok(_aidl_return) => {
+                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+                    _aidl_reply.write(_aidl_return)?;
+                    _aidl_reply.write(&_arg_list)?;
+                  }
+                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+                }
+                Ok(())
+              }
+              TRANSACTION_deleteKey => {
+                let _arg_key: crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor = _aidl_data.read()?;
+                let _aidl_return = _aidl_service.deleteKey(&_arg_key);
+                match &_aidl_return {
+                  Ok(_aidl_return) => {
+                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+                    _aidl_reply.write(_aidl_return)?;
+                  }
+                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+                }
+                Ok(())
+              }
+              TRANSACTION_grant => {
+                let _arg_key: crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor = _aidl_data.read()?;
+                let _arg_granteeUid: i32 = _aidl_data.read()?;
+                let _arg_accessVector: i32 = _aidl_data.read()?;
+                let mut _arg_grantKey: crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor = Default::default();
+                let _aidl_return = _aidl_service.grant(&_arg_key, _arg_granteeUid, _arg_accessVector, &mut _arg_grantKey);
+                match &_aidl_return {
+                  Ok(_aidl_return) => {
+                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+                    _aidl_reply.write(_aidl_return)?;
+                    _aidl_reply.write(&_arg_grantKey)?;
+                  }
+                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+                }
+                Ok(())
+              }
+              TRANSACTION_ungrant => {
+                let _arg_key: crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor = _aidl_data.read()?;
+                let _arg_granteeUid: i32 = _aidl_data.read()?;
+                let _aidl_return = _aidl_service.ungrant(&_arg_key, _arg_granteeUid);
+                match &_aidl_return {
+                  Ok(_aidl_return) => {
+                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+                    _aidl_reply.write(_aidl_return)?;
+                  }
+                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+                }
+                Ok(())
+              }
+              _ => Err(binder::StatusCode::UNKNOWN_TRANSACTION)
+            }
+          }
+        }
+        pub mod KeyDescriptor {
+          pub struct KeyDescriptor {
+            pub domain: crate::mangled::_7_android_8_security_9_keystore2_6_Domain, 
+            pub namespace_: i64, 
+            pub alias: Option<String>,
+            pub blob: Option<Vec<u8>>,
+          }
+          pub(crate) mod mangled { pub use super::KeyDescriptor as _7_android_8_security_9_keystore2_13_KeyDescriptor; }
+          impl Default for KeyDescriptor {
+            fn default() -> Self {
+              Self {
+                domain: Default::default(),
+                namespace_: 0,
+                alias: Default::default(),
+                blob: Default::default(),
+              }
+            }
+          }
+          impl binder::parcel::Serialize for KeyDescriptor {
+            fn serialize(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
+              <Self as binder::parcel::SerializeOption>::serialize_option(Some(self), parcel)
+            }
+          }
+          impl binder::parcel::SerializeArray for KeyDescriptor {}
+          impl binder::parcel::SerializeOption for KeyDescriptor {
+            fn serialize_option(this: Option<&Self>, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
+              let this = if let Some(this) = this {
+                parcel.write(&1i32)?;
+                this
+              } else {
+                return parcel.write(&0i32);
+              };
+              let start_pos = parcel.get_data_position();
+              parcel.write(&0i32)?;
+              parcel.write(&this.domain)?;
+              parcel.write(&this.namespace_)?;
+              parcel.write(&this.alias)?;
+              parcel.write(&this.blob)?;
+              let end_pos = parcel.get_data_position();
+              let parcelable_size = (end_pos - start_pos) as i32;
+              unsafe { parcel.set_data_position(start_pos)?; }
+              parcel.write(&parcelable_size)?;
+              unsafe { parcel.set_data_position(end_pos)?; }
+              Ok(())
+            }
+          }
+          impl binder::parcel::Deserialize for KeyDescriptor {
+            fn deserialize(parcel: &binder::parcel::Parcel) -> binder::Result<Self> {
+              <Self as binder::parcel::DeserializeOption>::deserialize_option(parcel)
+                 .transpose()
+                 .unwrap_or(Err(binder::StatusCode::UNEXPECTED_NULL))
+            }
+          }
+          impl binder::parcel::DeserializeArray for KeyDescriptor {}
+          impl binder::parcel::DeserializeOption for KeyDescriptor {
+            fn deserialize_option(parcel: &binder::parcel::Parcel) -> binder::Result<Option<Self>> {
+              let status: i32 = parcel.read()?;
+              if status == 0 { return Ok(None); }
+              let start_pos = parcel.get_data_position();
+              let parcelable_size: i32 = parcel.read()?;
+              if parcelable_size < 0 { return Err(binder::StatusCode::BAD_VALUE); }
+              let mut result = Self::default();
+              result.domain = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) >= parcelable_size {
+                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
+                return Ok(Some(result));
+              }
+              result.namespace_ = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) >= parcelable_size {
+                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
+                return Ok(Some(result));
+              }
+              result.alias = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) >= parcelable_size {
+                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
+                return Ok(Some(result));
+              }
+              result.blob = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) >= parcelable_size {
+                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
+                return Ok(Some(result));
+              }
+              Ok(Some(result))
+            }
+          }
+        }
+        pub mod KeyMetadata {
+          pub struct KeyMetadata {
+            pub key: crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, 
+            pub securityLevel: crate::mangled::_7_android_8_hardware_7_keymint_13_SecurityLevel, 
+            pub hardwareEnforced: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter>, 
+            pub softwareEnforced: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter>, 
+          }
+          pub(crate) mod mangled { pub use super::KeyMetadata as _7_android_8_security_9_keystore2_11_KeyMetadata; }
+          impl Default for KeyMetadata {
+            fn default() -> Self {
+              Self {
+                key: Default::default(),
+                securityLevel: Default::default(),
+                hardwareEnforced: Default::default(),
+                softwareEnforced: Default::default(),
+              }
+            }
+          }
+          impl binder::parcel::Serialize for KeyMetadata {
+            fn serialize(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
+              <Self as binder::parcel::SerializeOption>::serialize_option(Some(self), parcel)
+            }
+          }
+          impl binder::parcel::SerializeArray for KeyMetadata {}
+          impl binder::parcel::SerializeOption for KeyMetadata {
+            fn serialize_option(this: Option<&Self>, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
+              let this = if let Some(this) = this {
+                parcel.write(&1i32)?;
+                this
+              } else {
+                return parcel.write(&0i32);
+              };
+              let start_pos = parcel.get_data_position();
+              parcel.write(&0i32)?;
+              parcel.write(&this.key)?;
+              parcel.write(&this.securityLevel)?;
+              parcel.write(&this.hardwareEnforced)?;
+              parcel.write(&this.softwareEnforced)?;
+              let end_pos = parcel.get_data_position();
+              let parcelable_size = (end_pos - start_pos) as i32;
+              unsafe { parcel.set_data_position(start_pos)?; }
+              parcel.write(&parcelable_size)?;
+              unsafe { parcel.set_data_position(end_pos)?; }
+              Ok(())
+            }
+          }
+          impl binder::parcel::Deserialize for KeyMetadata {
+            fn deserialize(parcel: &binder::parcel::Parcel) -> binder::Result<Self> {
+              <Self as binder::parcel::DeserializeOption>::deserialize_option(parcel)
+                 .transpose()
+                 .unwrap_or(Err(binder::StatusCode::UNEXPECTED_NULL))
+            }
+          }
+          impl binder::parcel::DeserializeArray for KeyMetadata {}
+          impl binder::parcel::DeserializeOption for KeyMetadata {
+            fn deserialize_option(parcel: &binder::parcel::Parcel) -> binder::Result<Option<Self>> {
+              let status: i32 = parcel.read()?;
+              if status == 0 { return Ok(None); }
+              let start_pos = parcel.get_data_position();
+              let parcelable_size: i32 = parcel.read()?;
+              if parcelable_size < 0 { return Err(binder::StatusCode::BAD_VALUE); }
+              let mut result = Self::default();
+              result.key = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) >= parcelable_size {
+                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
+                return Ok(Some(result));
+              }
+              result.securityLevel = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) >= parcelable_size {
+                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
+                return Ok(Some(result));
+              }
+              result.hardwareEnforced = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) >= parcelable_size {
+                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
+                return Ok(Some(result));
+              }
+              result.softwareEnforced = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) >= parcelable_size {
+                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
+                return Ok(Some(result));
+              }
+              Ok(Some(result))
+            }
+          }
+        }
+        pub mod KeyPermission {
+          #![allow(non_upper_case_globals)]
+          pub type KeyPermission = i32;
+          pub const None: KeyPermission = 0;
+          pub const Delete: KeyPermission = 1;
+          pub const GenUniqueId: KeyPermission = 2;
+          pub const GetInfo: KeyPermission = 4;
+          pub const Grant: KeyPermission = 8;
+          pub const List: KeyPermission = 16;
+          pub const ManageBlob: KeyPermission = 32;
+          pub const Rebind: KeyPermission = 64;
+          pub const ReqForcedOp: KeyPermission = 128;
+          pub const Update: KeyPermission = 256;
+          pub const Use: KeyPermission = 512;
+          pub const UseDevId: KeyPermission = 1024;
+          pub(crate) mod mangled { pub use super::KeyPermission as _7_android_8_security_9_keystore2_13_KeyPermission; }
+        }
+        pub mod OperationChallenge {
+          pub struct OperationChallenge {
+            pub challenge: i64, 
+          }
+          pub(crate) mod mangled { pub use super::OperationChallenge as _7_android_8_security_9_keystore2_18_OperationChallenge; }
+          impl Default for OperationChallenge {
+            fn default() -> Self {
+              Self {
+                challenge: 0,
+              }
+            }
+          }
+          impl binder::parcel::Serialize for OperationChallenge {
+            fn serialize(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
+              <Self as binder::parcel::SerializeOption>::serialize_option(Some(self), parcel)
+            }
+          }
+          impl binder::parcel::SerializeArray for OperationChallenge {}
+          impl binder::parcel::SerializeOption for OperationChallenge {
+            fn serialize_option(this: Option<&Self>, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
+              let this = if let Some(this) = this {
+                parcel.write(&1i32)?;
+                this
+              } else {
+                return parcel.write(&0i32);
+              };
+              let start_pos = parcel.get_data_position();
+              parcel.write(&0i32)?;
+              parcel.write(&this.challenge)?;
+              let end_pos = parcel.get_data_position();
+              let parcelable_size = (end_pos - start_pos) as i32;
+              unsafe { parcel.set_data_position(start_pos)?; }
+              parcel.write(&parcelable_size)?;
+              unsafe { parcel.set_data_position(end_pos)?; }
+              Ok(())
+            }
+          }
+          impl binder::parcel::Deserialize for OperationChallenge {
+            fn deserialize(parcel: &binder::parcel::Parcel) -> binder::Result<Self> {
+              <Self as binder::parcel::DeserializeOption>::deserialize_option(parcel)
+                 .transpose()
+                 .unwrap_or(Err(binder::StatusCode::UNEXPECTED_NULL))
+            }
+          }
+          impl binder::parcel::DeserializeArray for OperationChallenge {}
+          impl binder::parcel::DeserializeOption for OperationChallenge {
+            fn deserialize_option(parcel: &binder::parcel::Parcel) -> binder::Result<Option<Self>> {
+              let status: i32 = parcel.read()?;
+              if status == 0 { return Ok(None); }
+              let start_pos = parcel.get_data_position();
+              let parcelable_size: i32 = parcel.read()?;
+              if parcelable_size < 0 { return Err(binder::StatusCode::BAD_VALUE); }
+              let mut result = Self::default();
+              result.challenge = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) >= parcelable_size {
+                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
+                return Ok(Some(result));
+              }
+              Ok(Some(result))
+            }
+          }
+        }
+        pub mod PublicKey {
+          pub struct PublicKey {
+            pub keyMaterial: Vec<u8>, 
+          }
+          pub(crate) mod mangled { pub use super::PublicKey as _7_android_8_security_9_keystore2_9_PublicKey; }
+          impl Default for PublicKey {
+            fn default() -> Self {
+              Self {
+                keyMaterial: Default::default(),
+              }
+            }
+          }
+          impl binder::parcel::Serialize for PublicKey {
+            fn serialize(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
+              <Self as binder::parcel::SerializeOption>::serialize_option(Some(self), parcel)
+            }
+          }
+          impl binder::parcel::SerializeArray for PublicKey {}
+          impl binder::parcel::SerializeOption for PublicKey {
+            fn serialize_option(this: Option<&Self>, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
+              let this = if let Some(this) = this {
+                parcel.write(&1i32)?;
+                this
+              } else {
+                return parcel.write(&0i32);
+              };
+              let start_pos = parcel.get_data_position();
+              parcel.write(&0i32)?;
+              parcel.write(&this.keyMaterial)?;
+              let end_pos = parcel.get_data_position();
+              let parcelable_size = (end_pos - start_pos) as i32;
+              unsafe { parcel.set_data_position(start_pos)?; }
+              parcel.write(&parcelable_size)?;
+              unsafe { parcel.set_data_position(end_pos)?; }
+              Ok(())
+            }
+          }
+          impl binder::parcel::Deserialize for PublicKey {
+            fn deserialize(parcel: &binder::parcel::Parcel) -> binder::Result<Self> {
+              <Self as binder::parcel::DeserializeOption>::deserialize_option(parcel)
+                 .transpose()
+                 .unwrap_or(Err(binder::StatusCode::UNEXPECTED_NULL))
+            }
+          }
+          impl binder::parcel::DeserializeArray for PublicKey {}
+          impl binder::parcel::DeserializeOption for PublicKey {
+            fn deserialize_option(parcel: &binder::parcel::Parcel) -> binder::Result<Option<Self>> {
+              let status: i32 = parcel.read()?;
+              if status == 0 { return Ok(None); }
+              let start_pos = parcel.get_data_position();
+              let parcelable_size: i32 = parcel.read()?;
+              if parcelable_size < 0 { return Err(binder::StatusCode::BAD_VALUE); }
+              let mut result = Self::default();
+              result.keyMaterial = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) >= parcelable_size {
+                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
+                return Ok(Some(result));
+              }
+              Ok(Some(result))
+            }
+          }
+        }
+        pub mod ResponseCode {
+          #![allow(non_upper_case_globals)]
+          pub type ResponseCode = i32;
+          pub const Ok: ResponseCode = 0;
+          pub const Locked: ResponseCode = 2;
+          pub const Uninitialized: ResponseCode = 3;
+          pub const SystemError: ResponseCode = 4;
+          pub const PermissionDenied: ResponseCode = 6;
+          pub const KeyNotFound: ResponseCode = 7;
+          pub const ValueCorrupted: ResponseCode = 8;
+          pub const WrongPassword: ResponseCode = 10;
+          pub const OpAuthNeeded: ResponseCode = 15;
+          pub const KeyPermanentlyInvalidated: ResponseCode = 17;
+          pub const NoSuchSecurityLevel: ResponseCode = 18;
+          pub const KeymintErrorCode: ResponseCode = 19;
+          pub const BackendBusy: ResponseCode = 20;
+          pub(crate) mod mangled { pub use super::ResponseCode as _7_android_8_security_9_keystore2_12_ResponseCode; }
+        }
+        pub mod Result {
+          #[derive(Debug, Copy, Clone, Eq, PartialEq)]
+          pub struct Result {
+            pub rc: crate::mangled::_7_android_8_security_9_keystore2_12_ResponseCode, 
+            pub errorCode: crate::mangled::_7_android_8_hardware_7_keymint_9_ErrorCode, 
+          }
+          pub(crate) mod mangled { pub use super::Result as _7_android_8_security_9_keystore2_6_Result; }
+          impl Default for Result {
+            fn default() -> Self {
+              Self {
+                rc: Default::default(),
+                errorCode: Default::default(),
+              }
+            }
+          }
+          impl binder::parcel::Serialize for Result {
+            fn serialize(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
+              <Self as binder::parcel::SerializeOption>::serialize_option(Some(self), parcel)
+            }
+          }
+          impl binder::parcel::SerializeArray for Result {}
+          impl binder::parcel::SerializeOption for Result {
+            fn serialize_option(this: Option<&Self>, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
+              let this = if let Some(this) = this {
+                parcel.write(&1i32)?;
+                this
+              } else {
+                return parcel.write(&0i32);
+              };
+              let start_pos = parcel.get_data_position();
+              parcel.write(&0i32)?;
+              parcel.write(&this.rc)?;
+              parcel.write(&this.errorCode)?;
+              let end_pos = parcel.get_data_position();
+              let parcelable_size = (end_pos - start_pos) as i32;
+              unsafe { parcel.set_data_position(start_pos)?; }
+              parcel.write(&parcelable_size)?;
+              unsafe { parcel.set_data_position(end_pos)?; }
+              Ok(())
+            }
+          }
+          impl binder::parcel::Deserialize for Result {
+            fn deserialize(parcel: &binder::parcel::Parcel) -> binder::Result<Self> {
+              <Self as binder::parcel::DeserializeOption>::deserialize_option(parcel)
+                 .transpose()
+                 .unwrap_or(Err(binder::StatusCode::UNEXPECTED_NULL))
+            }
+          }
+          impl binder::parcel::DeserializeArray for Result {}
+          impl binder::parcel::DeserializeOption for Result {
+            fn deserialize_option(parcel: &binder::parcel::Parcel) -> binder::Result<Option<Self>> {
+              let status: i32 = parcel.read()?;
+              if status == 0 { return Ok(None); }
+              let start_pos = parcel.get_data_position();
+              let parcelable_size: i32 = parcel.read()?;
+              if parcelable_size < 0 { return Err(binder::StatusCode::BAD_VALUE); }
+              let mut result = Self::default();
+              result.rc = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) >= parcelable_size {
+                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
+                return Ok(Some(result));
+              }
+              result.errorCode = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) >= parcelable_size {
+                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
+                return Ok(Some(result));
+              }
+              Ok(Some(result))
+            }
+          }
+        }
+      }
+    }
+  }
+}
+pub mod mangled {
+  pub use super::aidl::android::security::keystore2::AuthenticatorSpec::mangled::*;
+  pub use super::aidl::android::security::keystore2::Certificate::mangled::*;
+  pub use super::aidl::android::security::keystore2::CertificateChain::mangled::*;
+  pub use super::aidl::android::security::keystore2::Domain::mangled::*;
+  pub use super::aidl::android::security::keystore2::IKeystoreOperation::mangled::*;
+  pub use super::aidl::android::security::keystore2::IKeystoreSecurityLevel::mangled::*;
+  pub use super::aidl::android::security::keystore2::IKeystoreService::mangled::*;
+  pub use super::aidl::android::security::keystore2::KeyDescriptor::mangled::*;
+  pub use super::aidl::android::security::keystore2::KeyMetadata::mangled::*;
+  pub use super::aidl::android::security::keystore2::KeyPermission::mangled::*;
+  pub use super::aidl::android::security::keystore2::OperationChallenge::mangled::*;
+  pub use super::aidl::android::security::keystore2::PublicKey::mangled::*;
+  pub use super::aidl::android::security::keystore2::ResponseCode::mangled::*;
+  pub use super::aidl::android::security::keystore2::Result::mangled::*;
+  pub(crate) use android_hardware_keymint::mangled::*;
+}
\ No newline at end of file
diff --git a/keystore2/src/database.rs b/keystore2/src/database.rs
new file mode 100644
index 0000000..394b7be
--- /dev/null
+++ b/keystore2/src/database.rs
@@ -0,0 +1,397 @@
+// Copyright 2020, 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.
+
+// TODO: Once this is stable, remove this and document everything public.
+#![allow(missing_docs)]
+
+use crate::error::Error as KsError;
+use anyhow::{Context, Result};
+use keystore_aidl_generated as aidl;
+#[cfg(not(test))]
+use rand::prelude::random;
+use rusqlite::{params, Connection, TransactionBehavior, NO_PARAMS};
+#[cfg(test)]
+use tests::random;
+
+pub struct KeystoreDB {
+    conn: Connection,
+}
+
+impl KeystoreDB {
+    // TODO(b/160882985): Figure out the location for this file.
+    #[cfg(not(test))]
+    pub fn new() -> Result<KeystoreDB> {
+        KeystoreDB::new_with_filename("persistent.sql")
+    }
+
+    #[cfg(test)]
+    pub fn new() -> Result<KeystoreDB> {
+        KeystoreDB::new_with_filename("")
+    }
+
+    fn new_with_filename(persistent_file: &str) -> Result<KeystoreDB> {
+        let db = KeystoreDB {
+            conn: Connection::open_in_memory()
+                .context("Failed to initialize sqlite connection.")?,
+        };
+        db.attach_databases(persistent_file).context("Failed to create KeystoreDB.")?;
+        db.init_tables().context("Failed to create KeystoreDB.")?;
+        Ok(db)
+    }
+
+    fn attach_databases(&self, persistent_file: &str) -> Result<()> {
+        self.conn
+            .execute("ATTACH DATABASE ? as 'persistent';", params![persistent_file])
+            .context("Failed to attach databases.")?;
+        Ok(())
+    }
+
+    fn init_tables(&self) -> Result<()> {
+        self.conn
+            .execute(
+                "CREATE TABLE IF NOT EXISTS persistent.keyentry (
+                     id INTEGER UNIQUE,
+                     creation_date DATETIME,
+                     domain INTEGER,
+                     namespace INTEGER,
+                     alias TEXT);",
+                NO_PARAMS,
+            )
+            .context("Failed to initialize \"keyentry\" table.")?;
+        Ok(())
+    }
+
+    pub fn create_key_entry(&self, domain: aidl::Domain, namespace: i64) -> Result<i64> {
+        match domain {
+            aidl::Domain::App | aidl::Domain::SELinux => {}
+            _ => {
+                return Err(KsError::sys())
+                    .context(format!("Domain {:?} must be either App or SELinux.", domain));
+            }
+        }
+        // Loop until we get a unique id.
+        loop {
+            let newid: i64 = random();
+            let ret = self.conn.execute(
+                "INSERT into persistent.keyentry (id, creation_date, domain, namespace, alias)
+                     VALUES(?, datetime('now'), ?, ?, NULL);",
+                params![newid, domain as i64, namespace],
+            );
+            match ret {
+                // If the id already existed, try again.
+                Err(rusqlite::Error::SqliteFailure(
+                    libsqlite3_sys::Error {
+                        code: libsqlite3_sys::ErrorCode::ConstraintViolation,
+                        extended_code: libsqlite3_sys::SQLITE_CONSTRAINT_UNIQUE,
+                    },
+                    _,
+                )) => (),
+                _ => return Ok(newid),
+            }
+        }
+    }
+
+    pub fn rebind_alias(
+        &mut self,
+        newid: u32,
+        alias: &str,
+        domain: aidl::Domain,
+        namespace: i64,
+    ) -> Result<()> {
+        match domain {
+            aidl::Domain::App | aidl::Domain::SELinux => {}
+            _ => {
+                return Err(KsError::sys())
+                    .context(format!("Domain {:?} must be either App or SELinux.", domain));
+            }
+        }
+        let tx = self
+            .conn
+            .transaction_with_behavior(TransactionBehavior::Immediate)
+            .context("Failed to initialize transaction.")?;
+        tx.execute(
+            "UPDATE persistent.keyentry
+                 SET alias = NULL, domain = NULL, namespace = NULL
+                 WHERE alias = ? AND domain = ? AND namespace = ?;",
+            params![alias, domain as i64, namespace],
+        )
+        .context("Failed to rebind existing entry.")?;
+        let result = tx
+            .execute(
+                "UPDATE persistent.keyentry
+                 SET alias = ?
+                 WHERE id = ? AND domain = ? AND namespace = ?;",
+                params![alias, newid, domain as i64, namespace],
+            )
+            .context("Failed to set alias.")?;
+        if result != 1 {
+            // Note that this explicit rollback is not required, as
+            // the transaction should rollback if we do not commit it.
+            // We leave it here for readability.
+            tx.rollback().context("Failed to rollback a failed transaction.")?;
+            return Err(KsError::sys()).context(format!(
+                "Expected to update a single entry but instead updated {}.",
+                result
+            ));
+        }
+        tx.commit().context("Failed to commit transaction.")
+    }
+}
+
+#[cfg(test)]
+mod tests {
+
+    use super::*;
+    use std::cell::RefCell;
+
+    // Ensure that we're using the "injected" random function, not the real one.
+    #[test]
+    fn test_mocked_random() {
+        let rand1 = random();
+        let rand2 = random();
+        let rand3 = random();
+        if rand1 == rand2 {
+            assert_eq!(rand2 + 1, rand3);
+        } else {
+            assert_eq!(rand1 + 1, rand2);
+            assert_eq!(rand2, rand3);
+        }
+    }
+
+    // Ensure we can initialize the database.
+    #[test]
+    fn test_new() -> Result<()> {
+        KeystoreDB::new()?;
+        Ok(())
+    }
+
+    // Test that we have the correct tables.
+    #[test]
+    fn test_tables() -> Result<()> {
+        let db = KeystoreDB::new()?;
+        let tables = db
+            .conn
+            .prepare("SELECT name from persistent.sqlite_master WHERE type='table' ORDER BY name;")?
+            .query_map(params![], |row| row.get(0))?
+            .collect::<rusqlite::Result<Vec<String>>>()?;
+        assert_eq!(tables.len(), 1);
+        assert_eq!(tables[0], "keyentry");
+        Ok(())
+    }
+
+    #[test]
+    fn test_no_persistence_for_tests() -> Result<()> {
+        let db = KeystoreDB::new()?;
+
+        db.create_key_entry(aidl::Domain::App, 100)?;
+        let entries = get_keyentry(&db)?;
+        assert_eq!(entries.len(), 1);
+        let db = KeystoreDB::new()?;
+
+        let entries = get_keyentry(&db)?;
+        assert_eq!(entries.len(), 0);
+        Ok(())
+    }
+
+    #[test]
+    fn test_persistence_for_files() -> Result<()> {
+        let persistent = TempFile { filename: "/data/local/tmp/persistent.sql" };
+        let db = KeystoreDB::new_with_filename(persistent.filename)?;
+
+        db.create_key_entry(aidl::Domain::App, 100)?;
+        let entries = get_keyentry(&db)?;
+        assert_eq!(entries.len(), 1);
+        let db = KeystoreDB::new_with_filename(persistent.filename)?;
+
+        let entries_new = get_keyentry(&db)?;
+        assert_eq!(entries, entries_new);
+        Ok(())
+    }
+
+    #[test]
+    fn test_create_key_entry() -> Result<()> {
+        use aidl::Domain;
+
+        fn extractor(ke: &KeyEntryRow) -> (Domain, i64, Option<&str>) {
+            (ke.domain.unwrap(), ke.namespace.unwrap(), ke.alias.as_deref())
+        }
+
+        let db = KeystoreDB::new()?;
+
+        db.create_key_entry(Domain::App, 100)?;
+        db.create_key_entry(Domain::SELinux, 101)?;
+
+        let entries = get_keyentry(&db)?;
+        assert_eq!(entries.len(), 2);
+        assert_eq!(extractor(&entries[0]), (Domain::App, 100, None));
+        assert_eq!(extractor(&entries[1]), (Domain::SELinux, 101, None));
+
+        // Test that we must pass in a valid Domain.
+        check_result_is_error_containing_string(
+            db.create_key_entry(Domain::Grant, 102),
+            "Domain Grant must be either App or SELinux.",
+        );
+        check_result_is_error_containing_string(
+            db.create_key_entry(Domain::Blob, 103),
+            "Domain Blob must be either App or SELinux.",
+        );
+        check_result_is_error_containing_string(
+            db.create_key_entry(Domain::KeyId, 104),
+            "Domain KeyId must be either App or SELinux.",
+        );
+
+        Ok(())
+    }
+
+    #[test]
+    fn test_rebind_alias() -> Result<()> {
+        use aidl::Domain;
+
+        fn extractor(ke: &KeyEntryRow) -> (Option<Domain>, Option<i64>, Option<&str>) {
+            (ke.domain, ke.namespace, ke.alias.as_deref())
+        }
+
+        let mut db = KeystoreDB::new()?;
+        db.create_key_entry(Domain::App, 42)?;
+        db.create_key_entry(Domain::App, 42)?;
+        let entries = get_keyentry(&db)?;
+        assert_eq!(entries.len(), 2);
+        assert_eq!(extractor(&entries[0]), (Some(Domain::App), Some(42), None));
+        assert_eq!(extractor(&entries[1]), (Some(Domain::App), Some(42), None));
+
+        // Test that the first call to rebind_alias sets the alias.
+        db.rebind_alias(entries[0].id, "foo", Domain::App, 42)?;
+        let entries = get_keyentry(&db)?;
+        assert_eq!(entries.len(), 2);
+        assert_eq!(extractor(&entries[0]), (Some(Domain::App), Some(42), Some("foo")));
+        assert_eq!(extractor(&entries[1]), (Some(Domain::App), Some(42), None));
+
+        // Test that the second call to rebind_alias also empties the old one.
+        db.rebind_alias(entries[1].id, "foo", Domain::App, 42)?;
+        let entries = get_keyentry(&db)?;
+        assert_eq!(entries.len(), 2);
+        assert_eq!(extractor(&entries[0]), (None, None, None));
+        assert_eq!(extractor(&entries[1]), (Some(Domain::App), Some(42), Some("foo")));
+
+        // Test that we must pass in a valid Domain.
+        check_result_is_error_containing_string(
+            db.rebind_alias(0, "foo", Domain::Grant, 42),
+            "Domain Grant must be either App or SELinux.",
+        );
+        check_result_is_error_containing_string(
+            db.rebind_alias(0, "foo", Domain::Blob, 42),
+            "Domain Blob must be either App or SELinux.",
+        );
+        check_result_is_error_containing_string(
+            db.rebind_alias(0, "foo", Domain::KeyId, 42),
+            "Domain KeyId must be either App or SELinux.",
+        );
+
+        // Test that we correctly handle setting an alias for something that does not exist.
+        check_result_is_error_containing_string(
+            db.rebind_alias(0, "foo", Domain::SELinux, 42),
+            "Expected to update a single entry but instead updated 0",
+        );
+        // Test that we correctly abort the transaction in this case.
+        let entries = get_keyentry(&db)?;
+        assert_eq!(entries.len(), 2);
+        assert_eq!(extractor(&entries[0]), (None, None, None));
+        assert_eq!(extractor(&entries[1]), (Some(Domain::App), Some(42), Some("foo")));
+
+        Ok(())
+    }
+
+    // Helpers
+
+    // Checks that the given result is an error containing the given string.
+    fn check_result_is_error_containing_string<T>(result: Result<T>, target: &str) {
+        let error_str = format!(
+            "{:#?}",
+            result.err().unwrap_or_else(|| panic!("Expected the error: {}", target))
+        );
+        assert!(
+            error_str.contains(target),
+            "The string \"{}\" should contain \"{}\"",
+            error_str,
+            target
+        );
+    }
+
+    #[derive(Debug, PartialEq)]
+    #[allow(dead_code)]
+    struct KeyEntryRow {
+        id: u32,
+        creation_date: String,
+        domain: Option<aidl::Domain>,
+        namespace: Option<i64>,
+        alias: Option<String>,
+    }
+
+    fn get_keyentry(db: &KeystoreDB) -> Result<Vec<KeyEntryRow>> {
+        db.conn
+            .prepare("SELECT * FROM persistent.keyentry;")?
+            .query_map(NO_PARAMS, |row| {
+                let domain: Option<i32> = row.get(2)?;
+                Ok(KeyEntryRow {
+                    id: row.get(0)?,
+                    creation_date: row.get(1)?,
+                    domain: domain.map(domain_from_integer),
+                    namespace: row.get(3)?,
+                    alias: row.get(4)?,
+                })
+            })?
+            .map(|r| r.context("Could not read keyentry row."))
+            .collect::<Result<Vec<_>>>()
+    }
+
+    // TODO: Replace this with num_derive.
+    fn domain_from_integer(value: i32) -> aidl::Domain {
+        use aidl::Domain;
+        match value {
+            x if Domain::App as i32 == x => Domain::App,
+            x if Domain::Grant as i32 == x => Domain::Grant,
+            x if Domain::SELinux as i32 == x => Domain::SELinux,
+            x if Domain::Blob as i32 == x => Domain::Blob,
+            x if Domain::KeyId as i32 == x => Domain::KeyId,
+            _ => panic!("Unexpected domain: {}", value),
+        }
+    }
+
+    // A class that deletes a file when it is dropped.
+    // TODO: If we ever add a crate that does this, we can use it instead.
+    struct TempFile {
+        filename: &'static str,
+    }
+
+    impl Drop for TempFile {
+        fn drop(&mut self) {
+            std::fs::remove_file(self.filename).expect("Cannot delete temporary file");
+        }
+    }
+
+    // Use a custom random number generator that repeats each number once.
+    // This allows us to test repeated elements.
+
+    thread_local! {
+        static RANDOM_COUNTER: RefCell<i64> = RefCell::new(0);
+    }
+
+    pub fn random() -> i64 {
+        RANDOM_COUNTER.with(|counter| {
+            let result = *counter.borrow() / 2;
+            *counter.borrow_mut() += 1;
+            result
+        })
+    }
+}
diff --git a/keystore2/src/error.rs b/keystore2/src/error.rs
new file mode 100644
index 0000000..e6443b7
--- /dev/null
+++ b/keystore2/src/error.rs
@@ -0,0 +1,287 @@
+// Copyright 2020, 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.
+
+//! Keystore error provides convenience methods and types for Keystore error handling.
+//! Clients of Keystore expect one of two error codes, i.e., a Keystore ResponseCode as
+//! defined by the Keystore AIDL interface, or a Keymint ErrorCode as defined by
+//! the Keymint HAL specification.
+//! This crate provides `Error` which can wrap both. It is to be used
+//! internally by Keystore to diagnose error conditions that need to be reported to
+//! the client. To report the error condition to the client the Keystore AIDL
+//! interface defines a wire type `Result` which is distinctly different from Rust's
+//! `enum Result<T,E>`.
+//!
+//! This crate provides the convenience method `map_or_log_err` to convert `anyhow::Error`
+//! into this wire type. In addition to handling the conversion of `Error`
+//! to the `Result` wire type it handles any other error by mapping it to
+//! `ResponseCode::SystemError` and logs any error condition.
+//!
+//! Keystore functions should use `anyhow::Result` to return error conditions, and
+//! context should be added every time an error is forwarded.
+
+use std::cmp::PartialEq;
+use std::convert::From;
+
+use keystore_aidl_generated as aidl;
+use keystore_aidl_generated::ResponseCode as AidlRc;
+
+use keystore2_selinux as selinux;
+
+pub use aidl::ResponseCode;
+
+/// AidlResult wraps the `android.security.keystore2.Result` generated from AIDL
+#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
+pub struct AidlResult(aidl::Result);
+
+impl AidlResult {
+    /// Creates an instance of AidlResult indicating no error has occurred.
+    pub fn ok() -> Self {
+        Self(aidl::Result { rc: AidlRc::Ok, km_error_code: 0 })
+    }
+
+    /// Creates an instance of AidlResult indicating the given ResponseCode.
+    pub fn rc(rc: AidlRc) -> Self {
+        Self(aidl::Result { rc, km_error_code: 0 })
+    }
+
+    /// Creates an instance of AidlResult indicating the given KM ErrorCode.
+    pub fn ec(ec: aidl::ErrorCode) -> Self {
+        Self(aidl::Result { rc: AidlRc::KeymintErrorCode, km_error_code: ec })
+    }
+}
+
+/// This is the main Keystore error type. It wraps the Keystore `ResponseCode` generated
+/// from AIDL in the `Rc` variant and Keymint `ErrorCode` in the Km variant.
+#[derive(Debug, thiserror::Error, PartialEq)]
+pub enum Error {
+    /// Wraps a Keystore `ResponseCode` as defined by the Keystore AIDL interface specification.
+    #[error("Error::Rc({0:?})")]
+    Rc(AidlRc),
+    /// Wraps a Keymint `ErrorCode` as defined by the Keymint AIDL interface specification.
+    #[error("Error::Km({0:?})")]
+    Km(aidl::ErrorCode), // TODO Keymint ErrorCode is a generated AIDL type.
+}
+
+impl Error {
+    /// Short hand for `Error::Rc(ResponseCode::SystemError)`
+    pub fn sys() -> Self {
+        Error::Rc(AidlRc::SystemError)
+    }
+
+    /// Short hand for `Error::Rc(ResponseCode::PermissionDenied`
+    pub fn perm() -> Self {
+        Error::Rc(AidlRc::PermissionDenied)
+    }
+}
+
+impl From<anyhow::Error> for AidlResult {
+    fn from(error: anyhow::Error) -> Self {
+        let root_cause = error.root_cause();
+        match root_cause.downcast_ref::<Error>() {
+            Some(Error::Rc(rcode)) => AidlResult::rc(*rcode),
+            Some(Error::Km(ec)) => AidlResult::ec(*ec),
+            None => match root_cause.downcast_ref::<selinux::Error>() {
+                Some(selinux::Error::PermissionDenied) => AidlResult::rc(AidlRc::PermissionDenied),
+                _ => AidlResult::rc(AidlRc::SystemError),
+            },
+        }
+    }
+}
+
+/// This function should be used by Keystore service calls to translate error conditions
+/// into `android.security.keystore2.Result` which is imported here as `aidl::Result`
+/// and newtyped as AidlResult.
+/// All error conditions get logged by this function.
+/// All `Error::Rc(x)` variants get mapped onto `aidl::Result{x, 0}`.
+/// All `Error::Km(x)` variants get mapped onto
+/// `aidl::Result{aidl::ResponseCode::KeymintErrorCode, x}`.
+/// `selinux::Error::perm()` is mapped on `aidl::Result{aidl::ResponseCode::PermissionDenied, 0}`.
+///
+/// All non `Error` error conditions get mapped onto
+/// `aidl::Result{aidl::ResponseCode::SystemError}`.
+///
+/// `handle_ok` will be called if `result` is `Ok(value)` where `value` will be passed
+/// as argument to `handle_ok`. `handle_ok` must generate an `AidlResult`, typically
+/// `AidlResult::ok()`, but other response codes may be used, e.g.,
+/// `aidl::ResponseCode::OpAuthNeeded` which does not required logging.
+///
+/// # Examples
+///
+/// ```
+/// fn loadKey() -> anyhow::Result<aidl::ResponseCode> {
+///     if (good_but_auth_required) {
+///         Ok(aidl::ResponseCode::OpAuthRequired)
+///     } else {
+///         Err(anyhow!(Error::Rc(aidl::ResponseCode::KeyNotFound)))
+///     }
+/// }
+///
+/// aidl_result_ = map_or_log_err(loadKey(), |r| { some_side_effect(); AidlResult::rc(r) });
+/// ```
+pub fn map_or_log_err<T>(
+    result: anyhow::Result<T>,
+    handle_ok: impl FnOnce(T) -> AidlResult,
+) -> AidlResult {
+    result.map_or_else(
+        |e| {
+            log::error!("{:?}", e);
+            e.into()
+        },
+        handle_ok,
+    )
+}
+
+#[cfg(test)]
+mod tests {
+
+    use anyhow::{anyhow, Context};
+
+    use super::aidl::ErrorCode;
+    use super::*;
+
+    fn nested_nested_rc(rc: AidlRc) -> anyhow::Result<()> {
+        Err(anyhow!(Error::Rc(rc))).context("nested nested rc")
+    }
+
+    fn nested_rc(rc: AidlRc) -> anyhow::Result<()> {
+        nested_nested_rc(rc).context("nested rc")
+    }
+
+    fn nested_nested_ec(ec: ErrorCode) -> anyhow::Result<()> {
+        Err(anyhow!(Error::Km(ec))).context("nested nested ec")
+    }
+
+    fn nested_ec(ec: ErrorCode) -> anyhow::Result<()> {
+        nested_nested_ec(ec).context("nested ec")
+    }
+
+    fn nested_nested_ok(rc: AidlRc) -> anyhow::Result<AidlRc> {
+        Ok(rc)
+    }
+
+    fn nested_ok(rc: AidlRc) -> anyhow::Result<AidlRc> {
+        nested_nested_ok(rc).context("nested ok")
+    }
+
+    fn nested_nested_selinux_perm() -> anyhow::Result<()> {
+        Err(anyhow!(selinux::Error::perm())).context("nested nexted selinux permission denied")
+    }
+
+    fn nested_selinux_perm() -> anyhow::Result<()> {
+        nested_nested_selinux_perm().context("nested selinux permission denied")
+    }
+
+    #[derive(Debug, thiserror::Error)]
+    enum TestError {
+        #[error("TestError::Fail")]
+        Fail = 0,
+    }
+
+    fn nested_nested_other_error() -> anyhow::Result<()> {
+        Err(anyhow!(TestError::Fail)).context("nested nested other error")
+    }
+
+    fn nested_other_error() -> anyhow::Result<()> {
+        nested_nested_other_error().context("nested other error")
+    }
+
+    #[test]
+    fn keystore_error_test() -> anyhow::Result<(), String> {
+        android_logger::init_once(
+            android_logger::Config::default()
+                .with_tag("keystore_error_tests")
+                .with_min_level(log::Level::Debug),
+        );
+        // All Error::Rc(x) get mapped on aidl::Result{x, 0}
+        assert_eq!(
+            AidlResult::rc(AidlRc::Ok),
+            map_or_log_err(nested_rc(AidlRc::Ok), |_| AidlResult::ec(0))
+        );
+        assert_eq!(
+            AidlResult::rc(AidlRc::Locked),
+            map_or_log_err(nested_rc(AidlRc::Locked), |_| AidlResult::ec(0))
+        );
+        assert_eq!(
+            AidlResult::rc(AidlRc::Uninitialized),
+            map_or_log_err(nested_rc(AidlRc::Uninitialized), |_| AidlResult::ec(0))
+        );
+        assert_eq!(
+            AidlResult::rc(AidlRc::SystemError),
+            map_or_log_err(nested_rc(AidlRc::SystemError), |_| AidlResult::ec(0))
+        );
+        assert_eq!(
+            AidlResult::rc(AidlRc::PermissionDenied),
+            map_or_log_err(nested_rc(AidlRc::PermissionDenied), |_| AidlResult::ec(0))
+        );
+        assert_eq!(
+            AidlResult::rc(AidlRc::KeyNotFound),
+            map_or_log_err(nested_rc(AidlRc::KeyNotFound), |_| AidlResult::ec(0))
+        );
+        assert_eq!(
+            AidlResult::rc(AidlRc::ValueCorrupted),
+            map_or_log_err(nested_rc(AidlRc::ValueCorrupted), |_| AidlResult::ec(0))
+        );
+        assert_eq!(
+            AidlResult::rc(AidlRc::WrongPassword),
+            map_or_log_err(nested_rc(AidlRc::WrongPassword), |_| AidlResult::ec(0))
+        );
+        assert_eq!(
+            AidlResult::rc(AidlRc::OpAuthNeeded),
+            map_or_log_err(nested_rc(AidlRc::OpAuthNeeded), |_| AidlResult::ec(0))
+        );
+        assert_eq!(
+            AidlResult::rc(AidlRc::KeyPermanentlyInvalidated),
+            map_or_log_err(nested_rc(AidlRc::KeyPermanentlyInvalidated), |_| AidlResult::ec(0))
+        );
+        assert_eq!(
+            AidlResult::rc(AidlRc::NoSuchSecurityLevel),
+            map_or_log_err(nested_rc(AidlRc::NoSuchSecurityLevel), |_| AidlResult::ec(0))
+        );
+        assert_eq!(
+            AidlResult::rc(AidlRc::KeymintErrorCode),
+            map_or_log_err(nested_rc(AidlRc::KeymintErrorCode), |_| AidlResult::ec(0))
+        );
+        assert_eq!(
+            AidlResult::rc(AidlRc::BackendBusy),
+            map_or_log_err(nested_rc(AidlRc::BackendBusy), |_| AidlResult::ec(0))
+        );
+
+        // All KeystoreKerror::Km(x) get mapped on
+        // aidl::Result{AidlRc::KeymintErrorCode, x}
+        assert_eq!(
+            AidlResult::ec(-7),
+            map_or_log_err(nested_ec(-7), |_| AidlResult::rc(AidlRc::SystemError))
+        );
+
+        // All other get mapped on System Error.
+        assert_eq!(
+            AidlResult::rc(AidlRc::SystemError),
+            map_or_log_err(nested_other_error(), |_| AidlResult::ec(0))
+        );
+
+        // Result::Ok variants get passed to the ok handler.
+        assert_eq!(
+            AidlResult::rc(AidlRc::OpAuthNeeded),
+            map_or_log_err(nested_ok(AidlRc::OpAuthNeeded), AidlResult::rc)
+        );
+        assert_eq!(AidlResult::ok(), map_or_log_err(nested_ok(AidlRc::Ok), AidlResult::rc));
+
+        // selinux::Error::Perm() needs to be mapped to AidlRc::PermissionDenied
+        assert_eq!(
+            AidlResult::rc(AidlRc::PermissionDenied),
+            map_or_log_err(nested_selinux_perm(), |_| AidlResult::ec(0))
+        );
+        Ok(())
+    }
+} // mod tests
diff --git a/keystore2/src/key_parameter.rs b/keystore2/src/key_parameter.rs
new file mode 100644
index 0000000..d9ec7f3
--- /dev/null
+++ b/keystore2/src/key_parameter.rs
@@ -0,0 +1,251 @@
+// Copyright 2020, 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.
+
+//! KeyParameter is used to express different characteristics of a key requested by the user
+//! and enforced by the OEMs. This module implements the internal representation of KeyParameter
+//! and the methods to work with KeyParameter.
+
+use crate::keymint_definitions::{
+    Algorithm, BlockMode, Digest, EcCurve, HardwareAuthenticatorType, KeyBlobUsageRequirements,
+    KeyOrigin, KeyPurpose, PaddingMode, SecurityLevel, Tag,
+};
+
+/// KeyParameter wraps the KeyParameterValue and the security level at which it is enforced.
+pub struct KeyParameter {
+    key_parameter_value: KeyParameterValue,
+    security_level: SecurityLevel,
+}
+
+/// KeyParameterValue holds a value corresponding to one of the Tags defined in
+/// the AIDL spec at hardware/interfaces/keymint
+#[derive(PartialEq, Debug)]
+pub enum KeyParameterValue {
+    /// Associated with Tag:INVALID
+    Invalid,
+    /// Set of purposes for which the key may be used
+    KeyPurpose(KeyPurpose),
+    /// Cryptographic algorithm with which the key is used
+    Algorithm(Algorithm),
+    /// Size of the key , in bits
+    KeySize(u32),
+    /// Block cipher mode(s) with which the key may be used
+    BlockMode(BlockMode),
+    /// Digest algorithms that may be used with the key to perform signing and verification
+    Digest(Digest),
+    /// Padding modes that may be used with the key.  Relevant to RSA, AES and 3DES keys.
+    PaddingMode(PaddingMode),
+    /// Can the caller provide a nonce for nonce-requiring operations
+    CallerNonce,
+    /// Minimum length of MAC for HMAC keys and AES keys that support GCM mode
+    MinMacLength(u32),
+    /// The elliptic curve
+    EcCurve(EcCurve),
+    /// Value of the public exponent for an RSA key pair
+    RSAPublicExponent(u64),
+    /// An attestation certificate for the generated key should contain an application-scoped
+    /// and time-bounded device-unique ID
+    IncludeUniqueID,
+    /// Necessary system environment conditions for the generated key to be used
+    KeyBlobUsageRequirements(KeyBlobUsageRequirements),
+    /// Only the boot loader can use the key
+    BootLoaderOnly,
+    /// When deleted, the key is guaranteed to be permanently deleted and unusable
+    RollbackResistance,
+    //TODO: HARDWARE_TYPE reserved for future use
+    /// The date and time at which the key becomes active
+    ActiveDateTime(u64),
+    /// The date and time at which the key expires for signing and encryption
+    OriginationExpireDateTime(u64),
+    /// The date and time at which the key expires for verification and decryption
+    UsageExpireDateTime(u64),
+    /// Minimum amount of time that elapses between allowed operations
+    MinSecondsBetweenOps(u32),
+    /// Maximum number of times that a key may be used between system reboots
+    MaxUsesPerBoot(u32),
+    /// ID of the Android user that is permitted to use the key
+    UserID(u32),
+    /// A key may only be used under a particular secure user authentication state
+    UserSecureID(u64),
+    /// No authentication is required to use this key
+    NoAuthRequired,
+    /// The types of user authenticators that may be used to authorize this key
+    HardwareAuthenticatorType(HardwareAuthenticatorType),
+    /// The time in seconds for which the key is authorized for use, after user authentication
+    AuthTimeout(u32),
+    /// The key may be used after authentication timeout if device is still on-body
+    AllowWhileOnBody,
+    /// The key must be unusable except when the user has provided proof of physical presence
+    TrustedUserPresenceRequired,
+    /// Applicable to keys with KeyPurpose SIGN, and specifies that this key must not be usable
+    /// unless the user provides confirmation of the data to be signed
+    TrustedConfirmationRequired,
+    /// The key may only be used when the device is unlocked
+    UnlockedDeviceRequired,
+    /// When provided to generateKey or importKey, this tag specifies data
+    /// that is necessary during all uses of the key
+    ApplicationID(Vec<u8>),
+    /// When provided to generateKey or importKey, this tag specifies data
+    /// that is necessary during all uses of the key
+    ApplicationData(Vec<u8>),
+    /// Specifies the date and time the key was created
+    CreationDateTime(u64),
+    /// Specifies where the key was created, if known
+    KeyOrigin(KeyOrigin),
+    /// The key used by verified boot to validate the operating system booted
+    RootOfTrust(Vec<u8>),
+    /// System OS version with which the key may be used
+    OSVersion(u32),
+    /// Specifies the system security patch level with which the key may be used
+    OSPatchLevel(u32),
+    /// Specifies a unique, time-based identifier
+    UniqueID(Vec<u8>),
+    /// Used to deliver a "challenge" value to the attestKey() method
+    AttestationChallenge(Vec<u8>),
+    /// The set of applications which may use a key, used only with attestKey()
+    AttestationApplicationID(Vec<u8>),
+    /// Provides the device's brand name, to attestKey()
+    AttestationIdBrand(Vec<u8>),
+    /// Provides the device's device name, to attestKey()
+    AttestationIdDevice(Vec<u8>),
+    /// Provides the device's product name, to attestKey()
+    AttestationIdProduct(Vec<u8>),
+    /// Provides the device's serial number, to attestKey()
+    AttestationIdSerial(Vec<u8>),
+    /// Provides the IMEIs for all radios on the device, to attestKey()
+    AttestationIdIMEI(Vec<u8>),
+    /// Provides the MEIDs for all radios on the device, to attestKey()
+    AttestationIdMEID(Vec<u8>),
+    /// Provides the device's manufacturer name, to attestKey()
+    AttestationIdManufacturer(Vec<u8>),
+    /// Provides the device's model name, to attestKey()
+    AttestationIdModel(Vec<u8>),
+    /// Specifies the vendor image security patch level with which the key may be used
+    VendorPatchLevel(u32),
+    /// Specifies the boot image (kernel) security patch level with which the key may be used
+    BootPatchLevel(u32),
+    /// Provides "associated data" for AES-GCM encryption or decryption
+    AssociatedData(Vec<u8>),
+    /// Provides or returns a nonce or Initialization Vector (IV) for AES-GCM,
+    /// AES-CBC, AES-CTR, or 3DES-CBC encryption or decryption
+    Nonce(Vec<u8>),
+    /// Provides the requested length of a MAC or GCM authentication tag, in bits
+    MacLength(u32),
+    /// Specifies whether the device has been factory reset since the
+    /// last unique ID rotation.  Used for key attestation
+    ResetSinceIdRotation,
+    /// Used to deliver a cryptographic token proving that the user
+    ///  confirmed a signing request
+    ConfirmationToken(Vec<u8>),
+}
+
+impl KeyParameter {
+    /// Create an instance of KeyParameter, given the value and the security level.
+    pub fn new(key_parameter_value: KeyParameterValue, security_level: SecurityLevel) -> Self {
+        KeyParameter { key_parameter_value, security_level }
+    }
+
+    /// Returns the tag given the KeyParameter instance.
+    pub fn get_tag(&self) -> Tag {
+        match self.key_parameter_value {
+            KeyParameterValue::Invalid => Tag::INVALID,
+            KeyParameterValue::KeyPurpose(_) => Tag::PURPOSE,
+            KeyParameterValue::Algorithm(_) => Tag::ALGORITHM,
+            KeyParameterValue::KeySize(_) => Tag::KEY_SIZE,
+            KeyParameterValue::BlockMode(_) => Tag::BLOCK_MODE,
+            KeyParameterValue::Digest(_) => Tag::DIGEST,
+            KeyParameterValue::PaddingMode(_) => Tag::PADDING,
+            KeyParameterValue::CallerNonce => Tag::CALLER_NONCE,
+            KeyParameterValue::MinMacLength(_) => Tag::MIN_MAC_LENGTH,
+            KeyParameterValue::EcCurve(_) => Tag::EC_CURVE,
+            KeyParameterValue::RSAPublicExponent(_) => Tag::RSA_PUBLIC_EXPONENT,
+            KeyParameterValue::IncludeUniqueID => Tag::INCLUDE_UNIQUE_ID,
+            KeyParameterValue::KeyBlobUsageRequirements(_) => Tag::BLOB_USAGE_REQUIREMENTS,
+            KeyParameterValue::BootLoaderOnly => Tag::BOOTLOADER_ONLY,
+            KeyParameterValue::RollbackResistance => Tag::ROLLBACK_RESISTANCE,
+            KeyParameterValue::ActiveDateTime(_) => Tag::ACTIVE_DATETIME,
+            KeyParameterValue::OriginationExpireDateTime(_) => Tag::ORIGINATION_EXPIRE_DATETIME,
+            KeyParameterValue::UsageExpireDateTime(_) => Tag::USAGE_EXPIRE_DATETIME,
+            KeyParameterValue::MinSecondsBetweenOps(_) => Tag::MIN_SECONDS_BETWEEN_OPS,
+            KeyParameterValue::MaxUsesPerBoot(_) => Tag::MAX_USES_PER_BOOT,
+            KeyParameterValue::UserID(_) => Tag::USER_ID,
+            KeyParameterValue::UserSecureID(_) => Tag::USER_SECURE_ID,
+            KeyParameterValue::NoAuthRequired => Tag::NO_AUTH_REQUIRED,
+            KeyParameterValue::HardwareAuthenticatorType(_) => Tag::USER_AUTH_TYPE,
+            KeyParameterValue::AuthTimeout(_) => Tag::AUTH_TIMEOUT,
+            KeyParameterValue::AllowWhileOnBody => Tag::ALLOW_WHILE_ON_BODY,
+            KeyParameterValue::TrustedUserPresenceRequired => Tag::TRUSTED_USER_PRESENCE_REQUIRED,
+            KeyParameterValue::TrustedConfirmationRequired => Tag::TRUSTED_CONFIRMATION_REQUIRED,
+            KeyParameterValue::UnlockedDeviceRequired => Tag::UNLOCKED_DEVICE_REQUIRED,
+            KeyParameterValue::ApplicationID(_) => Tag::APPLICATION_ID,
+            KeyParameterValue::ApplicationData(_) => Tag::APPLICATION_DATA,
+            KeyParameterValue::CreationDateTime(_) => Tag::CREATION_DATETIME,
+            KeyParameterValue::KeyOrigin(_) => Tag::ORIGIN,
+            KeyParameterValue::RootOfTrust(_) => Tag::ROOT_OF_TRUST,
+            KeyParameterValue::OSVersion(_) => Tag::OS_VERSION,
+            KeyParameterValue::OSPatchLevel(_) => Tag::OS_PATCHLEVEL,
+            KeyParameterValue::UniqueID(_) => Tag::UNIQUE_ID,
+            KeyParameterValue::AttestationChallenge(_) => Tag::ATTESTATION_CHALLENGE,
+            KeyParameterValue::AttestationApplicationID(_) => Tag::ATTESTATION_APPLICATION_ID,
+            KeyParameterValue::AttestationIdBrand(_) => Tag::ATTESTATION_ID_BRAND,
+            KeyParameterValue::AttestationIdDevice(_) => Tag::ATTESTATION_ID_DEVICE,
+            KeyParameterValue::AttestationIdProduct(_) => Tag::ATTESTATION_ID_PRODUCT,
+            KeyParameterValue::AttestationIdSerial(_) => Tag::ATTESTATION_ID_SERIAL,
+            KeyParameterValue::AttestationIdIMEI(_) => Tag::ATTESTATION_ID_IMEI,
+            KeyParameterValue::AttestationIdMEID(_) => Tag::ATTESTATION_ID_MEID,
+            KeyParameterValue::AttestationIdManufacturer(_) => Tag::ATTESTATION_ID_MANUFACTURER,
+            KeyParameterValue::AttestationIdModel(_) => Tag::ATTESTATION_ID_MODEL,
+            KeyParameterValue::VendorPatchLevel(_) => Tag::VENDOR_PATCHLEVEL,
+            KeyParameterValue::BootPatchLevel(_) => Tag::BOOT_PATCHLEVEL,
+            KeyParameterValue::AssociatedData(_) => Tag::ASSOCIATED_DATA,
+            KeyParameterValue::Nonce(_) => Tag::NONCE,
+            KeyParameterValue::MacLength(_) => Tag::MAC_LENGTH,
+            KeyParameterValue::ResetSinceIdRotation => Tag::RESET_SINCE_ID_ROTATION,
+            KeyParameterValue::ConfirmationToken(_) => Tag::CONFIRMATION_TOKEN,
+        }
+    }
+
+    /// Returns key parameter value.
+    pub fn key_parameter_value(&self) -> &KeyParameterValue {
+        &self.key_parameter_value
+    }
+
+    /// Returns the security level of a KeyParameter.
+    pub fn security_level(&self) -> &SecurityLevel {
+        &self.security_level
+    }
+}
+
+#[cfg(test)]
+mod basic_tests {
+    use crate::key_parameter::*;
+    use crate::keymint_definitions::{SecurityLevel, Tag};
+
+    // Test basic functionality of KeyParameter.
+    #[test]
+    fn test_key_parameter() {
+        let key_parameter = KeyParameter::new(
+            KeyParameterValue::Algorithm(Algorithm::RSA),
+            SecurityLevel::STRONGBOX,
+        );
+
+        assert_eq!(key_parameter.get_tag(), Tag::ALGORITHM);
+
+        assert_eq!(
+            *key_parameter.key_parameter_value(),
+            KeyParameterValue::Algorithm(Algorithm::RSA)
+        );
+
+        assert_eq!(*key_parameter.security_level(), SecurityLevel::STRONGBOX);
+    }
+}
diff --git a/keystore2/src/keymint_definitions.rs b/keystore2/src/keymint_definitions.rs
new file mode 100644
index 0000000..2658a01
--- /dev/null
+++ b/keystore2/src/keymint_definitions.rs
@@ -0,0 +1,177 @@
+// Copyright 2020, 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.
+
+#![allow(non_camel_case_types)]
+#![allow(missing_docs)]
+
+/// This is the current interface for the code to-be-generated from the keymint AIDL.
+/// The AIDL spec is at" hardware/interfaces/keymint
+#[repr(u32)]
+#[derive(PartialEq, Debug)]
+pub enum TagType {
+    INVALID = 0 << 28,
+    ENUM = 1 << 28,
+    ENUM_REP = 2 << 28,
+    UINT = 3 << 28,
+    UINT_REP = 4 << 28,
+    ULONG = 5 << 28,
+    DATE = 6 << 28,
+    BOOL = 7 << 28,
+    BIGNUM = 8 << 28,
+    BYTES = 9 << 28,
+    ULONG_REP = 10 << 28,
+}
+#[repr(u32)]
+#[derive(PartialEq, Debug, Copy, Clone)]
+pub enum Tag {
+    INVALID = TagType::INVALID as u32,
+    PURPOSE = TagType::ENUM_REP as u32 | 1,
+    ALGORITHM = TagType::ENUM as u32 | 2,
+    KEY_SIZE = TagType::UINT as u32 | 3,
+    BLOCK_MODE = TagType::ENUM_REP as u32 | 4,
+    DIGEST = TagType::ENUM_REP as u32 | 5,
+    PADDING = TagType::ENUM_REP as u32 | 6,
+    CALLER_NONCE = TagType::BOOL as u32 | 7,
+    MIN_MAC_LENGTH = TagType::UINT as u32 | 8,
+    EC_CURVE = TagType::ENUM as u32 | 10,
+    RSA_PUBLIC_EXPONENT = TagType::ULONG as u32 | 200,
+    INCLUDE_UNIQUE_ID = TagType::BOOL as u32 | 202,
+    BLOB_USAGE_REQUIREMENTS = TagType::ENUM as u32 | 301,
+    BOOTLOADER_ONLY = TagType::BOOL as u32 | 302,
+    ROLLBACK_RESISTANCE = TagType::BOOL as u32 | 303,
+    ACTIVE_DATETIME = TagType::DATE as u32 | 400,
+    ORIGINATION_EXPIRE_DATETIME = TagType::DATE as u32 | 401,
+    USAGE_EXPIRE_DATETIME = TagType::DATE as u32 | 402,
+    MIN_SECONDS_BETWEEN_OPS = TagType::UINT as u32 | 403,
+    MAX_USES_PER_BOOT = TagType::UINT as u32 | 404,
+    USER_ID = TagType::UINT as u32 | 501,
+    USER_SECURE_ID = TagType::ULONG_REP as u32 | 502,
+    NO_AUTH_REQUIRED = TagType::BOOL as u32 | 503,
+    USER_AUTH_TYPE = TagType::ENUM as u32 | 504,
+    AUTH_TIMEOUT = TagType::UINT as u32 | 505,
+    ALLOW_WHILE_ON_BODY = TagType::BOOL as u32 | 506,
+    TRUSTED_USER_PRESENCE_REQUIRED = TagType::BOOL as u32 | 507,
+    TRUSTED_CONFIRMATION_REQUIRED = TagType::BOOL as u32 | 508,
+    UNLOCKED_DEVICE_REQUIRED = TagType::BOOL as u32 | 509,
+    APPLICATION_ID = TagType::BYTES as u32 | 601,
+    APPLICATION_DATA = TagType::BYTES as u32 | 700,
+    CREATION_DATETIME = TagType::DATE as u32 | 701,
+    ORIGIN = TagType::ENUM as u32 | 702,
+    ROOT_OF_TRUST = TagType::BYTES as u32 | 704,
+    OS_VERSION = TagType::UINT as u32 | 705,
+    OS_PATCHLEVEL = TagType::UINT as u32 | 706,
+    UNIQUE_ID = TagType::BYTES as u32 | 707,
+    ATTESTATION_CHALLENGE = TagType::BYTES as u32 | 708,
+    ATTESTATION_APPLICATION_ID = TagType::BYTES as u32 | 709,
+    ATTESTATION_ID_BRAND = TagType::BYTES as u32 | 710,
+    ATTESTATION_ID_DEVICE = TagType::BYTES as u32 | 711,
+    ATTESTATION_ID_PRODUCT = TagType::BYTES as u32 | 712,
+    ATTESTATION_ID_SERIAL = TagType::BYTES as u32 | 713,
+    ATTESTATION_ID_IMEI = TagType::BYTES as u32 | 714,
+    ATTESTATION_ID_MEID = TagType::BYTES as u32 | 715,
+    ATTESTATION_ID_MANUFACTURER = TagType::BYTES as u32 | 716,
+    ATTESTATION_ID_MODEL = TagType::BYTES as u32 | 717,
+    VENDOR_PATCHLEVEL = TagType::UINT as u32 | 718,
+    BOOT_PATCHLEVEL = TagType::UINT as u32 | 719,
+    ASSOCIATED_DATA = TagType::BYTES as u32 | 1000,
+    NONCE = TagType::BYTES as u32 | 1001,
+    MAC_LENGTH = TagType::UINT as u32 | 1003,
+    RESET_SINCE_ID_ROTATION = TagType::BOOL as u32 | 1004,
+    CONFIRMATION_TOKEN = TagType::BYTES as u32 | 1005,
+}
+#[repr(u32)]
+#[derive(PartialEq, Debug, Copy, Clone)]
+pub enum Algorithm {
+    RSA = 1,
+    EC = 3,
+    AES = 32,
+    TRIPLE_DES = 33,
+    HMAC = 128,
+}
+#[repr(u32)]
+#[derive(PartialEq, Debug, Copy, Clone)]
+pub enum BlockMode {
+    ECB = 1,
+    CBC = 2,
+    CTR = 3,
+    GCM = 32,
+}
+#[repr(u32)]
+#[derive(PartialEq, Debug, Copy, Clone)]
+pub enum PaddingMode {
+    NONE = 1,
+    RSA_OAEP = 2,
+    RSA_PSS = 3,
+    RSA_PKCS1_1_5_ENCRYPT = 4,
+    RSA_PKCS1_1_5_SIGN = 5,
+    PKCS7 = 64,
+}
+#[repr(u32)]
+#[derive(PartialEq, Debug, Copy, Clone)]
+pub enum Digest {
+    NONE = 0,
+    MD5 = 1,
+    SHA1 = 2,
+    SHA_2_224 = 3,
+    SHA_2_256 = 4,
+    SHA_2_384 = 5,
+    SHA_2_512 = 6,
+}
+#[repr(u32)]
+#[derive(PartialEq, Debug, Copy, Clone)]
+pub enum EcCurve {
+    P_224 = 0,
+    P_256 = 1,
+    P_384 = 2,
+    P_521 = 3,
+}
+#[repr(u32)]
+#[derive(PartialEq, Debug, Copy, Clone)]
+pub enum KeyOrigin {
+    GENERATED = 0,
+    DERIVED = 1,
+    IMPORTED = 2,
+    UNKNOWN = 3,
+    SECURELY_IMPORTED = 4,
+}
+#[repr(u32)]
+#[derive(PartialEq, Debug, Copy, Clone)]
+pub enum KeyBlobUsageRequirements {
+    STANDALONE = 0,
+    REQUIRES_FILE_SYSTEM = 1,
+}
+#[repr(u32)]
+#[derive(PartialEq, Debug, Copy, Clone)]
+pub enum KeyPurpose {
+    ENCRYPT = 0,
+    DECRYPT = 1,
+    SIGN = 2,
+    VERIFY = 3,
+    WRAP_KEY = 5,
+}
+#[repr(u32)]
+#[derive(PartialEq, Debug, Copy, Clone)]
+pub enum HardwareAuthenticatorType {
+    NONE = 0,
+    PASSWORD = 1,
+    FINGERPRINT = 1 << 1,
+    ANY = (0xFFFFFFFF as u32) as u32,
+}
+#[repr(u32)]
+#[derive(PartialEq, Debug, Copy, Clone)]
+pub enum SecurityLevel {
+    SOFTWARE = 0,
+    TRUSTED_ENVIRONMENT = 1,
+    STRONGBOX = 2,
+}
diff --git a/keystore2/src/lib.rs b/keystore2/src/lib.rs
new file mode 100644
index 0000000..13ef87d
--- /dev/null
+++ b/keystore2/src/lib.rs
@@ -0,0 +1,23 @@
+// Copyright 2020, 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.
+
+//! This crate implements the Android Keystore 2.0 service.
+
+pub mod database;
+pub mod error;
+/// Internal Representation of Key Parameter and convenience functions.
+pub mod key_parameter;
+/// Internal interface for the code to-be-generated from the keymint AIDL
+pub mod keymint_definitions;
+pub mod permission;
diff --git a/keystore2/src/permission.rs b/keystore2/src/permission.rs
new file mode 100644
index 0000000..0db56dd
--- /dev/null
+++ b/keystore2/src/permission.rs
@@ -0,0 +1,916 @@
+// Copyright 2020, 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.
+
+//! This crate provides access control primitives for Keystore 2.0.
+//! It provides high level functions for checking permissions in the keystore2 and keystore2_key
+//! SELinux classes based on the keystore2_selinux backend.
+//! It also provides KeystorePerm and KeyPerm as convenience wrappers for the SELinux permission
+//! defined by keystore2 and keystore2_key respectively.
+
+use keystore_aidl_generated as aidl;
+
+use std::cmp::PartialEq;
+use std::convert::From;
+
+use crate::error::Error as KsError;
+use keystore2_selinux as selinux;
+
+use anyhow::Context as AnyhowContext;
+
+use selinux::Backend;
+
+use lazy_static::lazy_static;
+
+// Replace getcon with a mock in the test situation
+#[cfg(not(test))]
+use selinux::getcon;
+#[cfg(test)]
+use tests::test_getcon as getcon;
+
+lazy_static! {
+    // Panicking here is allowed because keystore cannot function without this backend
+    // and it would happen early and indicate a gross misconfiguration of the device.
+    static ref KEYSTORE2_KEY_LABEL_BACKEND: selinux::KeystoreKeyBackend =
+            selinux::KeystoreKeyBackend::new().unwrap();
+}
+
+fn lookup_keystore2_key_context(namespace: i64) -> anyhow::Result<selinux::Context> {
+    KEYSTORE2_KEY_LABEL_BACKEND.lookup(&namespace.to_string())
+}
+
+/// The below example wraps the enum MyPermission in the tuple struct `MyPerm` and implements
+///  * `From<i32> for `MyPerm`, where each unknown numeric value is mapped to the given default,
+///    here `None`
+///  * `Into<MyPermission> for `MyPerm`
+///  * `MyPerm::foo()` and `MyPerm::bar()` which construct MyPerm instances representing
+///    `MyPermission::Foo` and `MyPermission::Bar` respectively.
+///  * `MyPerm.to_selinux(&self)`, which returns the selinux string representation of the
+///    represented permission.
+///  * Tests in the given test namespace for each permision that check that the numeric
+///    representations of MyPermission and MyPerm match. (TODO replace with static assert if
+///    they become available.)
+///
+/// ## Special behavior
+/// If the keyword `use` appears as an selinux name `use_` is used as identifier for the
+/// constructor function (e.g. `MePerm::use_()`) but the string returned by `to_selinux` will
+/// still be `"use"`.
+///
+/// ## Example
+/// ```
+/// #[i32]
+/// enum MyPermission {
+///     None = 0,
+///     Foo = 1,
+///     Bar = 2,
+/// }
+///
+/// implement_permission!(
+///     /// MyPerm documentation.
+///     #[derive(Clone, Copy, Debug, PartialEq)]
+///     MyPermission as MyPerm with default (None = 0, none)
+///     and test namespace my_perm_tests {
+///         Foo = 1,           selinux name: foo;
+///         Bar = 2,           selinux name: bar;
+///     }
+/// );
+/// ```
+macro_rules! implement_permission {
+    // This rule provides the public interface of the macro. And starts the preprocessing
+    // recursion (see below).
+    ($(#[$m:meta])* $t:ty as $name:ident with default ($($def:tt)*)
+        and test namespace $tn:ident { $($element:tt)* })
+    => {
+        implement_permission!(@replace_use $($m)*, $t, $name, $tn, ($($def)*), [] , $($element)*);
+    };
+
+
+    // The following three rules recurse through the elements of the form
+    // `<enum variant> = <integer_literal>, selinux name: <selinux_name>;`
+    // preprocessing the input.
+
+    // The first rule terminates the recursion and passes the processed arguments to the final
+    // rule that spills out the implementation.
+    (@replace_use $($m:meta)*, $t:ty, $name:ident, $tn:ident, ($($def:tt)*), [$($out:tt)*], ) => {
+        implement_permission!(@end $($m)*, $t, $name, $tn, ($($def)*) { $($out)* } );
+    };
+
+    // The second rule is triggered if the selinux name of an element is literally `use`.
+    // It produces the tuple `<enum variant> = <integer_literal>, use_, use;`
+    // and appends it to the out list.
+    (@replace_use $($m:meta)*, $t:ty, $name:ident, $tn:ident, ($($def:tt)*), [$($out:tt)*],
+        $e_name:ident = $e_val:expr, selinux name: use; $($element:tt)*)
+    => {
+        implement_permission!(@replace_use $($m)*, $t, $name, $tn, ($($def)*),
+                              [$($out)* $e_name = $e_val, use_, use;], $($element)*);
+    };
+
+    // The third rule is the default rule which replaces every input tuple with
+    // `<enum variant> = <integer_literal>, <selinux_name>, <selinux_name>;`
+    // and appends the result to the out list.
+    (@replace_use $($m:meta)*, $t:ty, $name:ident, $tn:ident, ($($def:tt)*), [$($out:tt)*],
+        $e_name:ident = $e_val:expr, selinux name: $e_str:ident; $($element:tt)*)
+    => {
+        implement_permission!(@replace_use $($m)*, $t, $name, $tn, ($($def)*),
+                              [$($out)* $e_name = $e_val, $e_str, $e_str;], $($element)*);
+    };
+
+    (@end $($m:meta)*, $t:ty, $name:ident, $tn:ident,
+        ($def_name:ident = $def:expr, $def_selinux_name:ident) {
+            $($element_name:ident = $element_val:expr, $element_identifier:ident,
+                $selinux_name:ident;)*
+        })
+    =>
+    {
+        $(#[$m])*
+        pub struct $name($t);
+
+        impl From<i32> for $name {
+            fn from (p: i32) -> Self {
+                match p {
+                    $def => Self(<$t>::$def_name),
+                    $($element_val => Self(<$t>::$element_name),)*
+                    _ => Self(<$t>::$def_name),
+                }
+            }
+        }
+
+        impl Into<$t> for $name {
+            fn into(self) -> $t {
+                self.0
+            }
+        }
+
+        impl $name {
+            /// Returns a string representation of the permission as required by
+            /// `selinux::check_access`.
+            pub fn to_selinux(&self) -> &'static str {
+                match self {
+                    Self(<$t>::$def_name) => stringify!($def_selinux_name),
+                    $(Self(<$t>::$element_name) => stringify!($selinux_name),)*
+                }
+            }
+
+            /// Creates an instance representing a permission with the same name.
+            pub const fn $def_selinux_name() -> Self { Self(<$t>::$def_name) }
+            $(
+                /// Creates an instance representing a permission with the same name.
+                pub const fn $element_identifier() -> Self { Self(<$t>::$element_name) }
+             )*
+        }
+        #[cfg(test)]
+        mod $tn {
+            use super::*;
+
+            #[test]
+            fn $def_selinux_name() {
+                assert_eq!($name::$def_selinux_name(), (<$t>::$def_name as i32).into());
+            }
+            $(
+                #[test]
+                fn $element_identifier() {
+                    assert_eq!($name::$element_identifier(), (<$t>::$element_name as i32).into());
+                }
+            )*
+        }
+    };
+
+
+}
+
+implement_permission!(
+    /// KeyPerm provides a convenient abstraction from the SELinux class `keystore2_key`.
+    /// At the same time it maps `KeyPermissions` from the Keystore 2.0 AIDL Grant interface to
+    /// the SELinux permissions. With the implement_permission macro, we conveniently
+    /// provide mappings between the wire type bit field values, the rust enum and the SELinux
+    /// string representation.
+    ///
+    /// ## Example
+    ///
+    /// In this access check `KeyPerm::get_info().to_selinux()` would return the SELinux representation
+    /// "info".
+    /// ```
+    /// selinux::check_access(source_context, target_context, "keystore2_key",
+    ///                       KeyPerm::get_info().to_selinux());
+    /// ```
+    #[derive(Clone, Copy, Debug, Eq, PartialEq)]
+    aidl::KeyPermission as KeyPerm with default (None = 0, none)
+    and test namespace key_perm_tests {
+        Delete = 1,         selinux name: delete;
+        GenUniqueId = 2,    selinux name: gen_unique_id;
+        GetInfo = 4,        selinux name: get_info;
+        Grant = 8,          selinux name: grant;
+        List = 0x10,        selinux name: list;
+        ManageBlob = 0x20,  selinux name: manage_blob;
+        Rebind = 0x40,      selinux name: rebind;
+        ReqForcedOp = 0x80, selinux name: req_forced_op;
+        Update = 0x100,     selinux name: update;
+        Use = 0x200,        selinux name: use;
+        UseDevId = 0x400,   selinux name: use_dev_id;
+    }
+);
+
+/// KeystorePermission defines values for the SELinux `keystore2` security class.
+/// Countrary to `KeyPermission`, this enum is not generated by AIDL and need not be
+/// wrapped by newtype pattern. But we conveniently use the implement_permission macro
+/// to provide the same feature that we did for `KeyPermission` to this set of permissions.
+#[repr(i32)]
+#[derive(Debug, Clone, Copy, Eq, PartialEq)]
+pub enum KeystorePermission {
+    /// `None` is not a permission that can ever be granted. It is not known to the SEPolicy.
+    None = 0,
+    /// Checked when a new auth token is installed.
+    AddAuth = 1,
+    /// Checked when an app is uninstalled or wiped.
+    ClearNs = 2,
+    /// Checked when the locked state of Keystore 2.0 is queried.
+    GetState = 4,
+    /// Checked when Keystore 2.0 gets locked.
+    Lock = 8,
+    /// Checked when Keystore 2.0 shall be reset.
+    Reset = 0x10,
+    /// Checked when Keystore 2.0 shall be unlocked.
+    Unlock = 0x20,
+}
+
+implement_permission!(
+    /// KeystorePerm provides a convenient abstraction from the SELinux class `keystore2`.
+    /// Using the implement_permission macro we get the same features as `KeyPerm`.
+    #[derive(Clone, Copy, Debug, PartialEq)]
+    KeystorePermission as KeystorePerm with default (None = 0, none)
+    and test namespace keystore_perm_tests {
+        AddAuth = 1,    selinux name: add_auth;
+        ClearNs = 2,    selinux name: clear_ns;
+        GetState = 4,   selinux name: get_state;
+        Lock = 8,       selinux name: lock;
+        Reset = 0x10,   selinux name: reset;
+        Unlock = 0x20,  selinux name: unlock;
+    }
+);
+
+/// Represents a set of `KeyPerm` permissions.
+/// `IntoIterator` is implemented for this struct allowing the iteration through all the
+/// permissions in the set.
+/// It also implements a function `includes(self, other)` that checks if the permissions
+/// in `other` are included in `self`.
+///
+/// KeyPermSet can be created with the macro `key_perm_set![]`.
+///
+/// ## Example
+/// ```
+/// let perms1 = key_perm_set![KeyPerm::use_(), KeyPerm::manage_blob(), KeyPerm::grant()];
+/// let perms2 = key_perm_set![KeyPerm::use_(), KeyPerm::manage_blob()];
+///
+/// assert!(perms1.includes(perms2))
+/// assert!(!perms2.includes(perms1))
+///
+/// let i = perms1.into_iter();
+/// // iteration in ascending order of the permission's numeric representation.
+/// assert_eq(Some(KeyPerm::manage_blob()), i.next());
+/// assert_eq(Some(KeyPerm::grant()), i.next());
+/// assert_eq(Some(KeyPerm::use_()), i.next());
+/// assert_eq(None, i.next());
+/// ```
+#[derive(Copy, Clone)]
+pub struct KeyPermSet(i32);
+
+mod perm {
+    use super::*;
+
+    pub struct IntoIter {
+        vec: KeyPermSet,
+        pos: u8,
+    }
+
+    impl IntoIter {
+        pub fn new(v: KeyPermSet) -> Self {
+            Self { vec: v, pos: 0 }
+        }
+    }
+
+    impl std::iter::Iterator for IntoIter {
+        type Item = KeyPerm;
+
+        fn next(&mut self) -> Option<Self::Item> {
+            loop {
+                if self.pos == 32 {
+                    return None;
+                }
+                let p = self.vec.0 & (1 << self.pos);
+                self.pos += 1;
+                if p != 0 {
+                    return Some(KeyPerm::from(p));
+                }
+            }
+        }
+    }
+}
+
+impl From<KeyPerm> for KeyPermSet {
+    fn from(p: KeyPerm) -> Self {
+        Self(p.0 as i32)
+    }
+}
+
+impl KeyPermSet {
+    /// Returns true iff this permission set has all of the permissions that are in `other`.
+    fn includes<T: Into<KeyPermSet>>(&self, other: T) -> bool {
+        let o: KeyPermSet = other.into();
+        (self.0 & o.0) == o.0
+    }
+}
+
+/// This macro can be used to create a `KeyPermSet` from a list of `KeyPerm` values.
+///
+/// ## Example
+/// ```
+/// let v = key_perm_set![Perm::delete(), Perm::manage_blob()];
+/// ```
+#[macro_export]
+macro_rules! key_perm_set {
+    () => { KeyPermSet(0) };
+    ($head:expr $(, $tail:expr)* $(,)?) => {
+        KeyPermSet($head.0 as i32 $(| $tail.0 as i32)*)
+    };
+}
+
+impl IntoIterator for KeyPermSet {
+    type Item = KeyPerm;
+    type IntoIter = perm::IntoIter;
+
+    fn into_iter(self) -> Self::IntoIter {
+        Self::IntoIter::new(self)
+    }
+}
+
+/// Uses `selinux::check_access` to check if the given caller context `caller_cxt` may access
+/// the given permision `perm` of the `keystore2` security class.
+pub fn check_keystore_permission(
+    caller_ctx: &selinux::Context,
+    perm: KeystorePerm,
+) -> anyhow::Result<()> {
+    let target_context = getcon().context("check_keystore_permission: getcon failed.")?;
+    selinux::check_access(caller_ctx, &target_context, "keystore2", perm.to_selinux())
+}
+
+/// Uses `selinux::check_access` to check if the given caller context `caller_cxt` has
+/// all the permissions indicated in `access_vec` for the target domain indicated by the key
+/// descriptor `key` in the security class `keystore2_key`.
+///
+/// Also checks if the caller has the grant permission for the given target domain.
+///
+/// Attempts to grant the grant permission are always denied.
+///
+/// The only viable target domains are
+///  * `Domain::App` in which case u:r:keystore:s0 is used as target context and
+///  * `Domain::SELinux` in which case the `key.namespace_` parameter is looked up in
+///                      SELinux keystore key backend, and the result is used
+///                      as target context.
+pub fn check_grant_permission(
+    caller_ctx: &selinux::Context,
+    access_vec: KeyPermSet,
+    key: &aidl::KeyDescriptor,
+) -> anyhow::Result<()> {
+    use aidl::Domain;
+
+    let target_context = match key.domain {
+        Domain::App => getcon().context("check_grant_permission: getcon failed.")?,
+        Domain::SELinux => lookup_keystore2_key_context(key.namespace_)
+            .context("check_grant_permission: Domain::SELinux: Failed to lookup namespace.")?,
+        _ => return Err(KsError::sys()).context(format!("Cannot grant {:?}.", key.domain)),
+    };
+
+    selinux::check_access(caller_ctx, &target_context, "keystore2_key", "grant")
+        .context("Grant permission is required when granting.")?;
+
+    if access_vec.includes(KeyPerm::grant()) {
+        return Err(selinux::Error::perm()).context("Grant permission cannot be granted.");
+    }
+
+    for p in access_vec.into_iter() {
+        selinux::check_access(caller_ctx, &target_context, "keystore2_key", p.to_selinux())
+            .context(concat!(
+                "check_grant_permission: check_access failed. ",
+                "The caller may have tried to grant a permission that they don't possess."
+            ))?
+    }
+    Ok(())
+}
+
+/// Uses `selinux::check_access` to check if the given caller context `caller_cxt`
+/// has the permissions indicated by `perm` for the target domain indicated by the key
+/// descriptor `key` in the security class `keystore2_key`.
+///
+/// The behavior differs slightly depending on the selected target domain:
+///  * `Domain::App` u:r:keystore:s0 is used as target context.
+///  * `Domain::SELinux` `key.namespace_` parameter is looked up in the SELinux keystore key
+///                      backend, and the result is used as target context.
+///  * `Domain::Blob` Same as SELinux but the "manage_blob" permission is always checked additionally
+///                   to the one supplied in `perm`.
+///  * `Domain::Grant` Does not use selinux::check_access. Instead the `access_vector`
+///                    parameter is queried for permission, which must be supplied in this case.
+///
+/// ## Return values.
+///  * Ok(()) If the requested permissions were granted.
+///  * Err(selinux::Error::perm()) If the requested permissions were denied.
+///  * Err(KsError::sys()) This error is produced if `Domain::Grant` is selected but no `access_vec`
+///                      was supplied. It is also produced if `Domain::KeyId` was selected, and
+///                      on various unexpected backend failures.
+pub fn check_key_permission(
+    caller_ctx: &selinux::Context,
+    perm: KeyPerm,
+    key: &aidl::KeyDescriptor,
+    access_vector: &Option<KeyPermSet>,
+) -> anyhow::Result<()> {
+    use aidl::Domain;
+
+    let target_context = match key.domain {
+        // apps get the default keystore context
+        Domain::App => getcon().context("check_key_permission: getcon failed.")?,
+        Domain::SELinux => lookup_keystore2_key_context(key.namespace_)
+            .context("check_key_permission: Domain::SELinux: Failed to lookup namespace.")?,
+        Domain::Grant => {
+            match access_vector {
+                Some(pv) => {
+                    if pv.includes(perm) {
+                        return Ok(());
+                    } else {
+                        return Err(selinux::Error::perm())
+                            .context(format!("\"{}\" not granted", perm.to_selinux()));
+                    }
+                }
+                None => {
+                    // If DOMAIN_GRANT was selected an access vector must be supplied.
+                    return Err(KsError::sys()).context(
+                        "Cannot check permission for Domain::Grant without access vector.",
+                    );
+                }
+            }
+        }
+        Domain::KeyId => {
+            // We should never be called with `Domain::KeyId. The database
+            // lookup should have converted this into one of `Domain::App`
+            // or `Domain::SELinux`.
+            return Err(KsError::sys()).context("Cannot check permission for Domain::KeyId.");
+        }
+        Domain::Blob => {
+            let tctx = lookup_keystore2_key_context(key.namespace_)
+                .context("Domain::Blob: Failed to lookup namespace.")?;
+            // If DOMAIN_KEY_BLOB was specified, we check for the "manage_blob"
+            // permission in addition to the requested permission.
+            selinux::check_access(
+                caller_ctx,
+                &tctx,
+                "keystore2_key",
+                KeyPerm::manage_blob().to_selinux(),
+            )?;
+
+            tctx
+        }
+    };
+
+    selinux::check_access(caller_ctx, &target_context, "keystore2_key", perm.to_selinux())
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use anyhow::anyhow;
+    use anyhow::Result;
+    use keystore2_selinux::*;
+    use keystore_aidl_generated as aidl;
+
+    const ALL_PERMS: KeyPermSet = key_perm_set![
+        KeyPerm::manage_blob(),
+        KeyPerm::delete(),
+        KeyPerm::use_dev_id(),
+        KeyPerm::req_forced_op(),
+        KeyPerm::gen_unique_id(),
+        KeyPerm::grant(),
+        KeyPerm::get_info(),
+        KeyPerm::list(),
+        KeyPerm::rebind(),
+        KeyPerm::update(),
+        KeyPerm::use_(),
+    ];
+
+    const NOT_GRANT_PERMS: KeyPermSet = key_perm_set![
+        KeyPerm::manage_blob(),
+        KeyPerm::delete(),
+        KeyPerm::use_dev_id(),
+        KeyPerm::req_forced_op(),
+        KeyPerm::gen_unique_id(),
+        // No KeyPerm::grant()
+        KeyPerm::get_info(),
+        KeyPerm::list(),
+        KeyPerm::rebind(),
+        KeyPerm::update(),
+        KeyPerm::use_(),
+    ];
+
+    const UNPRIV_PERMS: KeyPermSet = key_perm_set![
+        KeyPerm::delete(),
+        KeyPerm::get_info(),
+        KeyPerm::list(),
+        KeyPerm::rebind(),
+        KeyPerm::update(),
+        KeyPerm::use_(),
+    ];
+
+    /// The su_key namespace as defined in su.te and keystore_key_contexts of the
+    /// SePolicy (system/sepolicy).
+    const SU_KEY_NAMESPACE: i32 = 0;
+    /// The shell_key namespace as defined in shell.te and keystore_key_contexts of the
+    /// SePolicy (system/sepolicy).
+    const SHELL_KEY_NAMESPACE: i32 = 1;
+
+    pub fn test_getcon() -> Result<Context> {
+        Context::new("u:object_r:keystore:s0")
+    }
+
+    // This macro evaluates the given expression and checks that
+    // a) evaluated to Result::Err() and that
+    // b) the wrapped error is selinux::Error::perm() (permission denied).
+    // We use a macro here because a function would mask which invocation caused the failure.
+    //
+    // TODO b/164121720 Replace this macro with a function when `track_caller` is available.
+    macro_rules! assert_perm_failed {
+        ($test_function:expr) => {
+            let result = $test_function;
+            assert!(result.is_err(), "Permission check should have failed.");
+            assert_eq!(
+                Some(&selinux::Error::perm()),
+                result.err().unwrap().root_cause().downcast_ref::<selinux::Error>()
+            );
+        };
+    }
+
+    fn check_context() -> Result<(selinux::Context, i32, bool)> {
+        // Calling the non mocked selinux::getcon here intended.
+        let context = selinux::getcon()?;
+        match context.to_str().unwrap() {
+            "u:r:su:s0" => Ok((context, SU_KEY_NAMESPACE, true)),
+            "u:r:shell:s0" => Ok((context, SHELL_KEY_NAMESPACE, false)),
+            c => Err(anyhow!(format!(
+                "This test must be run as \"su\" or \"shell\". Current context: \"{}\"",
+                c
+            ))),
+        }
+    }
+
+    #[test]
+    fn check_keystore_permission_test() -> Result<()> {
+        let system_server_ctx = Context::new("u:r:system_server:s0")?;
+        assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::add_auth()).is_ok());
+        assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::clear_ns()).is_ok());
+        assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::get_state()).is_ok());
+        assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::lock()).is_ok());
+        assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::reset()).is_ok());
+        assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::unlock()).is_ok());
+        let shell_ctx = Context::new("u:r:shell:s0")?;
+        assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::add_auth()));
+        assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::clear_ns()));
+        assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::get_state()));
+        assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::lock()));
+        assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::reset()));
+        assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::unlock()));
+        Ok(())
+    }
+
+    #[test]
+    fn check_grant_permission_app() -> Result<()> {
+        let system_server_ctx = Context::new("u:r:system_server:s0")?;
+        let shell_ctx = Context::new("u:r:shell:s0")?;
+        use aidl::Domain;
+        let key =
+            aidl::KeyDescriptor { domain: Domain::App, namespace_: 0, alias: None, blob: None };
+        assert!(check_grant_permission(&system_server_ctx, NOT_GRANT_PERMS, &key).is_ok());
+        // attempts to grant the grant permission must always fail even when privileged.
+
+        assert_perm_failed!(check_grant_permission(
+            &system_server_ctx,
+            KeyPerm::grant().into(),
+            &key
+        ));
+        // unprivileged grant attempts always fail. shell does not have the grant permission.
+        assert_perm_failed!(check_grant_permission(&shell_ctx, UNPRIV_PERMS, &key));
+        Ok(())
+    }
+
+    #[test]
+    fn check_grant_permission_selinux() -> Result<()> {
+        use aidl::Domain;
+        let (sctx, namespace, is_su) = check_context()?;
+        let key = aidl::KeyDescriptor {
+            domain: Domain::SELinux,
+            namespace_: namespace as i64,
+            alias: None,
+            blob: None,
+        };
+        if is_su {
+            assert!(check_grant_permission(&sctx, NOT_GRANT_PERMS, &key).is_ok());
+            // attempts to grant the grant permission must always fail even when privileged.
+            assert_perm_failed!(check_grant_permission(&sctx, KeyPerm::grant().into(), &key));
+        } else {
+            // unprivileged grant attempts always fail. shell does not have the grant permission.
+            assert_perm_failed!(check_grant_permission(&sctx, UNPRIV_PERMS, &key));
+        }
+        Ok(())
+    }
+
+    #[test]
+    fn check_key_permission_domain_grant() -> Result<()> {
+        use aidl::Domain;
+        let key =
+            aidl::KeyDescriptor { domain: Domain::Grant, namespace_: 0, alias: None, blob: None };
+
+        assert_perm_failed!(check_key_permission(
+            &selinux::Context::new("ignored").unwrap(),
+            KeyPerm::grant(),
+            &key,
+            &Some(UNPRIV_PERMS)
+        ));
+
+        check_key_permission(
+            &selinux::Context::new("ignored").unwrap(),
+            KeyPerm::use_(),
+            &key,
+            &Some(ALL_PERMS),
+        )
+    }
+
+    #[test]
+    fn check_key_permission_domain_app() -> Result<()> {
+        let system_server_ctx = Context::new("u:r:system_server:s0")?;
+        let shell_ctx = Context::new("u:r:shell:s0")?;
+        let gmscore_app = Context::new("u:r:gmscore_app:s0")?;
+        use aidl::Domain;
+
+        let key =
+            aidl::KeyDescriptor { domain: Domain::App, namespace_: 0, alias: None, blob: None };
+
+        assert!(check_key_permission(&system_server_ctx, KeyPerm::use_(), &key, &None).is_ok());
+        assert!(check_key_permission(&system_server_ctx, KeyPerm::delete(), &key, &None).is_ok());
+        assert!(check_key_permission(&system_server_ctx, KeyPerm::get_info(), &key, &None).is_ok());
+        assert!(check_key_permission(&system_server_ctx, KeyPerm::rebind(), &key, &None).is_ok());
+        assert!(check_key_permission(&system_server_ctx, KeyPerm::list(), &key, &None).is_ok());
+        assert!(check_key_permission(&system_server_ctx, KeyPerm::update(), &key, &None).is_ok());
+        assert!(check_key_permission(&system_server_ctx, KeyPerm::grant(), &key, &None).is_ok());
+        assert!(
+            check_key_permission(&system_server_ctx, KeyPerm::use_dev_id(), &key, &None).is_ok()
+        );
+        assert!(check_key_permission(&gmscore_app, KeyPerm::gen_unique_id(), &key, &None).is_ok());
+
+        assert!(check_key_permission(&shell_ctx, KeyPerm::use_(), &key, &None).is_ok());
+        assert!(check_key_permission(&shell_ctx, KeyPerm::delete(), &key, &None).is_ok());
+        assert!(check_key_permission(&shell_ctx, KeyPerm::get_info(), &key, &None).is_ok());
+        assert!(check_key_permission(&shell_ctx, KeyPerm::rebind(), &key, &None).is_ok());
+        assert!(check_key_permission(&shell_ctx, KeyPerm::list(), &key, &None).is_ok());
+        assert!(check_key_permission(&shell_ctx, KeyPerm::update(), &key, &None).is_ok());
+        assert_perm_failed!(check_key_permission(&shell_ctx, KeyPerm::grant(), &key, &None));
+        assert_perm_failed!(check_key_permission(
+            &shell_ctx,
+            KeyPerm::req_forced_op(),
+            &key,
+            &None
+        ));
+        assert_perm_failed!(check_key_permission(&shell_ctx, KeyPerm::manage_blob(), &key, &None));
+        assert_perm_failed!(check_key_permission(&shell_ctx, KeyPerm::use_dev_id(), &key, &None));
+        assert_perm_failed!(check_key_permission(
+            &shell_ctx,
+            KeyPerm::gen_unique_id(),
+            &key,
+            &None
+        ));
+
+        Ok(())
+    }
+
+    #[test]
+    fn check_key_permission_domain_selinux() -> Result<()> {
+        use aidl::Domain;
+        let (sctx, namespace, is_su) = check_context()?;
+        let key = aidl::KeyDescriptor {
+            domain: Domain::SELinux,
+            namespace_: namespace as i64,
+            alias: None,
+            blob: None,
+        };
+
+        if is_su {
+            assert!(check_key_permission(&sctx, KeyPerm::use_(), &key, &None).is_ok());
+            assert!(check_key_permission(&sctx, KeyPerm::delete(), &key, &None).is_ok());
+            assert!(check_key_permission(&sctx, KeyPerm::get_info(), &key, &None).is_ok());
+            assert!(check_key_permission(&sctx, KeyPerm::rebind(), &key, &None).is_ok());
+            assert!(check_key_permission(&sctx, KeyPerm::list(), &key, &None).is_ok());
+            assert!(check_key_permission(&sctx, KeyPerm::update(), &key, &None).is_ok());
+            assert!(check_key_permission(&sctx, KeyPerm::grant(), &key, &None).is_ok());
+            assert!(check_key_permission(&sctx, KeyPerm::manage_blob(), &key, &None).is_ok());
+            assert!(check_key_permission(&sctx, KeyPerm::use_dev_id(), &key, &None).is_ok());
+            assert!(check_key_permission(&sctx, KeyPerm::gen_unique_id(), &key, &None).is_ok());
+            assert!(check_key_permission(&sctx, KeyPerm::req_forced_op(), &key, &None).is_ok());
+        } else {
+            assert!(check_key_permission(&sctx, KeyPerm::use_(), &key, &None).is_ok());
+            assert!(check_key_permission(&sctx, KeyPerm::delete(), &key, &None).is_ok());
+            assert!(check_key_permission(&sctx, KeyPerm::get_info(), &key, &None).is_ok());
+            assert!(check_key_permission(&sctx, KeyPerm::rebind(), &key, &None).is_ok());
+            assert!(check_key_permission(&sctx, KeyPerm::list(), &key, &None).is_ok());
+            assert!(check_key_permission(&sctx, KeyPerm::update(), &key, &None).is_ok());
+            assert_perm_failed!(check_key_permission(&sctx, KeyPerm::grant(), &key, &None));
+            assert_perm_failed!(check_key_permission(&sctx, KeyPerm::req_forced_op(), &key, &None));
+            assert_perm_failed!(check_key_permission(&sctx, KeyPerm::manage_blob(), &key, &None));
+            assert_perm_failed!(check_key_permission(&sctx, KeyPerm::use_dev_id(), &key, &None));
+            assert_perm_failed!(check_key_permission(&sctx, KeyPerm::gen_unique_id(), &key, &None));
+        }
+        Ok(())
+    }
+
+    #[test]
+    fn check_key_permission_domain_blob() -> Result<()> {
+        use aidl::Domain;
+        let (sctx, namespace, is_su) = check_context()?;
+        let key = aidl::KeyDescriptor {
+            domain: Domain::Blob,
+            namespace_: namespace as i64,
+            alias: None,
+            blob: None,
+        };
+
+        if is_su {
+            check_key_permission(&sctx, KeyPerm::use_(), &key, &None)
+        } else {
+            assert_perm_failed!(check_key_permission(&sctx, KeyPerm::use_(), &key, &None));
+            Ok(())
+        }
+    }
+
+    #[test]
+    fn check_key_permission_domain_key_id() -> Result<()> {
+        use aidl::Domain;
+        let key =
+            aidl::KeyDescriptor { domain: Domain::KeyId, namespace_: 0, alias: None, blob: None };
+
+        assert_eq!(
+            Some(&KsError::sys()),
+            check_key_permission(
+                &selinux::Context::new("ignored").unwrap(),
+                KeyPerm::use_(),
+                &key,
+                &None
+            )
+            .err()
+            .unwrap()
+            .root_cause()
+            .downcast_ref::<KsError>()
+        );
+        Ok(())
+    }
+
+    #[test]
+    fn key_perm_set_all_test() {
+        let v = key_perm_set![
+            KeyPerm::manage_blob(),
+            KeyPerm::delete(),
+            KeyPerm::use_dev_id(),
+            KeyPerm::req_forced_op(),
+            KeyPerm::gen_unique_id(),
+            KeyPerm::grant(),
+            KeyPerm::get_info(),
+            KeyPerm::list(),
+            KeyPerm::rebind(),
+            KeyPerm::update(),
+            KeyPerm::use_() // Test if the macro accepts missing comma at the end of the list.
+        ];
+        let mut i = v.into_iter();
+        assert_eq!(i.next().unwrap().to_selinux(), "delete");
+        assert_eq!(i.next().unwrap().to_selinux(), "gen_unique_id");
+        assert_eq!(i.next().unwrap().to_selinux(), "get_info");
+        assert_eq!(i.next().unwrap().to_selinux(), "grant");
+        assert_eq!(i.next().unwrap().to_selinux(), "list");
+        assert_eq!(i.next().unwrap().to_selinux(), "manage_blob");
+        assert_eq!(i.next().unwrap().to_selinux(), "rebind");
+        assert_eq!(i.next().unwrap().to_selinux(), "req_forced_op");
+        assert_eq!(i.next().unwrap().to_selinux(), "update");
+        assert_eq!(i.next().unwrap().to_selinux(), "use");
+        assert_eq!(i.next().unwrap().to_selinux(), "use_dev_id");
+        assert_eq!(None, i.next());
+    }
+    #[test]
+    fn key_perm_set_sparse_test() {
+        let v = key_perm_set![
+            KeyPerm::manage_blob(),
+            KeyPerm::req_forced_op(),
+            KeyPerm::gen_unique_id(),
+            KeyPerm::list(),
+            KeyPerm::update(),
+            KeyPerm::use_(), // Test if macro accepts the comma at the end of the list.
+        ];
+        let mut i = v.into_iter();
+        assert_eq!(i.next().unwrap().to_selinux(), "gen_unique_id");
+        assert_eq!(i.next().unwrap().to_selinux(), "list");
+        assert_eq!(i.next().unwrap().to_selinux(), "manage_blob");
+        assert_eq!(i.next().unwrap().to_selinux(), "req_forced_op");
+        assert_eq!(i.next().unwrap().to_selinux(), "update");
+        assert_eq!(i.next().unwrap().to_selinux(), "use");
+        assert_eq!(None, i.next());
+    }
+    #[test]
+    fn key_perm_set_empty_test() {
+        let v = key_perm_set![];
+        let mut i = v.into_iter();
+        assert_eq!(None, i.next());
+    }
+    #[test]
+    fn key_perm_set_include_subset_test() {
+        let v1 = key_perm_set![
+            KeyPerm::manage_blob(),
+            KeyPerm::delete(),
+            KeyPerm::use_dev_id(),
+            KeyPerm::req_forced_op(),
+            KeyPerm::gen_unique_id(),
+            KeyPerm::grant(),
+            KeyPerm::get_info(),
+            KeyPerm::list(),
+            KeyPerm::rebind(),
+            KeyPerm::update(),
+            KeyPerm::use_(),
+        ];
+        let v2 = key_perm_set![
+            KeyPerm::manage_blob(),
+            KeyPerm::delete(),
+            KeyPerm::list(),
+            KeyPerm::rebind(),
+            KeyPerm::update(),
+            KeyPerm::use_(),
+        ];
+        assert!(v1.includes(v2));
+        assert!(!v2.includes(v1));
+    }
+    #[test]
+    fn key_perm_set_include_equal_test() {
+        let v1 = key_perm_set![
+            KeyPerm::manage_blob(),
+            KeyPerm::delete(),
+            KeyPerm::list(),
+            KeyPerm::rebind(),
+            KeyPerm::update(),
+            KeyPerm::use_(),
+        ];
+        let v2 = key_perm_set![
+            KeyPerm::manage_blob(),
+            KeyPerm::delete(),
+            KeyPerm::list(),
+            KeyPerm::rebind(),
+            KeyPerm::update(),
+            KeyPerm::use_(),
+        ];
+        assert!(v1.includes(v2));
+        assert!(v2.includes(v1));
+    }
+    #[test]
+    fn key_perm_set_include_overlap_test() {
+        let v1 = key_perm_set![
+            KeyPerm::manage_blob(),
+            KeyPerm::delete(),
+            KeyPerm::grant(), // only in v1
+            KeyPerm::list(),
+            KeyPerm::rebind(),
+            KeyPerm::update(),
+            KeyPerm::use_(),
+        ];
+        let v2 = key_perm_set![
+            KeyPerm::manage_blob(),
+            KeyPerm::delete(),
+            KeyPerm::req_forced_op(), // only in v2
+            KeyPerm::list(),
+            KeyPerm::rebind(),
+            KeyPerm::update(),
+            KeyPerm::use_(),
+        ];
+        assert!(!v1.includes(v2));
+        assert!(!v2.includes(v1));
+    }
+    #[test]
+    fn key_perm_set_include_no_overlap_test() {
+        let v1 = key_perm_set![KeyPerm::manage_blob(), KeyPerm::delete(), KeyPerm::grant(),];
+        let v2 = key_perm_set![
+            KeyPerm::req_forced_op(),
+            KeyPerm::list(),
+            KeyPerm::rebind(),
+            KeyPerm::update(),
+            KeyPerm::use_(),
+        ];
+        assert!(!v1.includes(v2));
+        assert!(!v2.includes(v1));
+    }
+}