Merge "Add more logging for fatal errors" into main
diff --git a/keystore/keystore_attestation_id.cpp b/keystore/keystore_attestation_id.cpp
index bcd3318..c91f86f 100644
--- a/keystore/keystore_attestation_id.cpp
+++ b/keystore/keystore_attestation_id.cpp
@@ -21,6 +21,7 @@
#include <log/log.h>
#include <memory>
+#include <mutex>
#include <string>
#include <vector>
@@ -51,6 +52,7 @@
constexpr const char* kAttestationSystemPackageName = "AndroidSystem";
constexpr const size_t kMaxAttempts = 3;
constexpr const unsigned long kRetryIntervalUsecs = 500000; // sleep for 500 ms
+constexpr const char* kProviderServiceName = "sec_key_att_app_id_provider";
std::vector<uint8_t> signature2SHA256(const security::keystore::Signature& sig) {
std::vector<uint8_t> digest_buffer(SHA256_DIGEST_LENGTH);
@@ -61,24 +63,24 @@
using ::aidl::android::system::keystore2::ResponseCode;
using ::android::security::keystore::BpKeyAttestationApplicationIdProvider;
-class KeyAttestationApplicationIdProvider : public BpKeyAttestationApplicationIdProvider {
- public:
- KeyAttestationApplicationIdProvider();
+[[clang::no_destroy]] std::mutex gServiceMu;
+[[clang::no_destroy]] std::shared_ptr<BpKeyAttestationApplicationIdProvider>
+ gService; // GUARDED_BY gServiceMu
- static KeyAttestationApplicationIdProvider& get();
-
- private:
- android::sp<android::IServiceManager> service_manager_;
-};
-
-KeyAttestationApplicationIdProvider& KeyAttestationApplicationIdProvider::get() {
- static KeyAttestationApplicationIdProvider mpm;
- return mpm;
+std::shared_ptr<BpKeyAttestationApplicationIdProvider> get_service() {
+ std::lock_guard<std::mutex> guard(gServiceMu);
+ if (gService.get() == nullptr) {
+ gService = std::make_shared<BpKeyAttestationApplicationIdProvider>(
+ android::defaultServiceManager()->waitForService(String16(kProviderServiceName)));
+ }
+ return gService;
}
-KeyAttestationApplicationIdProvider::KeyAttestationApplicationIdProvider()
- : BpKeyAttestationApplicationIdProvider(android::defaultServiceManager()->waitForService(
- String16("sec_key_att_app_id_provider"))) {}
+void reset_service() {
+ std::lock_guard<std::mutex> guard(gServiceMu);
+ // Drop the global reference; any thread that already has a reference can keep using it.
+ gService.reset();
+}
DECLARE_STACK_OF(ASN1_OCTET_STRING);
@@ -281,23 +283,31 @@
key_attestation_id.packageInfos.push_back(std::move(pinfo));
} else {
/* Get the attestation application ID from package manager */
- auto& pm = KeyAttestationApplicationIdProvider::get();
::android::binder::Status status;
- // Retry on failure if a service specific error code.
+ // Retry on failure.
for (size_t attempt{0}; attempt < kMaxAttempts; ++attempt) {
- status = pm.getKeyAttestationApplicationId(uid, &key_attestation_id);
+ auto pm = get_service();
+ status = pm->getKeyAttestationApplicationId(uid, &key_attestation_id);
if (status.isOk()) {
break;
- } else if (status.exceptionCode() != binder::Status::EX_SERVICE_SPECIFIC) {
- ALOGW("Retry: key attestation ID failed with service specific error: %s %d",
- status.exceptionMessage().c_str(), status.serviceSpecificErrorCode());
- usleep(kRetryIntervalUsecs);
- } else {
- ALOGW("Retry: key attestation ID failed with error: %s %d",
- status.exceptionMessage().c_str(), status.exceptionCode());
- usleep(kRetryIntervalUsecs);
}
+
+ if (status.exceptionCode() == binder::Status::EX_SERVICE_SPECIFIC) {
+ ALOGW("Retry: get attestation ID for %d failed with service specific error: %s %d",
+ uid, status.exceptionMessage().c_str(), status.serviceSpecificErrorCode());
+ } else if (status.exceptionCode() == binder::Status::EX_TRANSACTION_FAILED) {
+ // If the transaction failed, drop the package manager connection so that the next
+ // attempt will try again.
+ ALOGW(
+ "Retry: get attestation ID for %d transaction failed, reset connection: %s %d",
+ uid, status.exceptionMessage().c_str(), status.exceptionCode());
+ reset_service();
+ } else {
+ ALOGW("Retry: get attestation ID for %d failed with error: %s %d", uid,
+ status.exceptionMessage().c_str(), status.exceptionCode());
+ }
+ usleep(kRetryIntervalUsecs);
}
if (!status.isOk()) {