Implement rate limiting on a per app basis for confirmationui

Implements the following strategy per app:
* Every attempted prompt increments a try counter.
* A prompt that was confirmed by the user resets the try counter.
* No penalty is applied after the first two cancelled attempts.
* A penalty of 30s is applied after attempt 3, 4, and 5 when
  cancelled by the user
* A penalty of 60s * 2**(N - 6) after the Nth cancelled attempt
  for attempts 6...
* A try counter that was not updated in 24h gets garbage collected.

Test: /data/nativetest64/keystore_unit_tests/keystore_unit_tests
Bug: 73892492
Change-Id: I0b50869259bfe920338c0c049cb9a715143ab103
diff --git a/keystore/confirmation_manager.cpp b/keystore/confirmation_manager.cpp
index acca304..0dee4aa 100644
--- a/keystore/confirmation_manager.cpp
+++ b/keystore/confirmation_manager.cpp
@@ -23,6 +23,7 @@
 #include <android/hardware/confirmationui/1.0/types.h>
 #include <android/security/BpConfirmationPromptCallback.h>
 #include <binder/BpBinder.h>
+#include <binder/IPCThreadState.h>
 #include <binder/Parcel.h>
 
 #include "keystore_aidl_hidl_marshalling_utils.h"
@@ -69,6 +70,12 @@
         return Status::ok();
     }
 
+    uid_t callingUid = android::IPCThreadState::self()->getCallingUid();
+    if (!mRateLimiting.tryPrompt(callingUid)) {
+        *aidl_return = static_cast<int32_t>(ConfirmationResponseCode::SystemError);
+        return Status::ok();
+    }
+
     String8 promptText8(promptText);
     String8 locale8(locale);
     vector<UIOption> uiOptionsVector;
@@ -137,6 +144,7 @@
     // and b) ensure state has been cleared; before doing this...
 
     mMutex.lock();
+    mRateLimiting.processResult(responseCode);
     sp<IBinder> listener = mCurrentListener;
     if (mCurrentListener != nullptr) {
         mCurrentListener->unlinkToDeath(mDeathRecipient);