Changes to adapt confirmationui AIDL spec.

Replaced HIDL spec implementation with AIDL spec in confirmationui
module.

Ignore-AOSP-First: Dependent on internal change.
Bug: b/205760172
Test: Run confirmation UI test using CTS Verifier, atest VtsHalConfirmationUITargetTest
Change-Id: I49b9cb6d93fa35fd611003f7545d2ce4976eec7c
diff --git a/trusty/confirmationui/Android.bp b/trusty/confirmationui/Android.bp
index 0922415..29ef3c0 100644
--- a/trusty/confirmationui/Android.bp
+++ b/trusty/confirmationui/Android.bp
@@ -24,21 +24,23 @@
 }
 
 cc_binary {
-    name: "android.hardware.confirmationui@1.0-service.trusty",
+    name: "android.hardware.confirmationui-service.trusty",
     relative_install_path: "hw",
     vendor: true,
     shared_libs: [
-        "android.hardware.confirmationui@1.0",
+        "android.hardware.confirmationui-V1-ndk",
         "android.hardware.confirmationui.not-so-secure-input",
-        "android.hardware.confirmationui@1.0-lib.trusty",
+        "android.hardware.confirmationui-lib.trusty",
+        "libbinder_ndk",
+        "libteeui_hal_support",
         "libbase",
         "libhidlbase",
         "libutils",
     ],
 
-    init_rc: ["android.hardware.confirmationui@1.0-service.trusty.rc"],
+    init_rc: ["android.hardware.confirmationui-service.trusty.rc"],
 
-    vintf_fragments: ["android.hardware.confirmationui@1.0-service.trusty.xml"],
+    vintf_fragments: ["android.hardware.confirmationui-service.trusty.xml"],
 
     srcs: [
         "service.cpp",
@@ -52,17 +54,20 @@
 }
 
 cc_library {
-    name: "android.hardware.confirmationui@1.0-lib.trusty",
+    name: "android.hardware.confirmationui-lib.trusty",
+    defaults: [
+        "keymint_use_latest_hal_aidl_ndk_shared",
+    ],
     vendor: true,
     shared_libs: [
-        "android.hardware.confirmationui@1.0",
-        "android.hardware.keymaster@4.0",
+        "android.hardware.confirmationui-V1-ndk",
         "libbase",
+        "libcutils",
         "libdmabufheap",
-        "libhidlbase",
         "libteeui_hal_support",
         "libtrusty",
         "libutils",
+        "libbinder_ndk",
     ],
 
     export_include_dirs: ["include"],
diff --git a/trusty/confirmationui/TrustyConfirmationUI.cpp b/trusty/confirmationui/TrustyConfirmationUI.cpp
index c6625e0..f01a4e1 100644
--- a/trusty/confirmationui/TrustyConfirmationUI.cpp
+++ b/trusty/confirmationui/TrustyConfirmationUI.cpp
@@ -18,8 +18,6 @@
 #include "TrustyConfirmationUI.h"
 
 #include <android-base/logging.h>
-#include <android/hardware/confirmationui/1.0/types.h>
-#include <android/hardware/keymaster/4.0/types.h>
 #include <fcntl.h>
 #include <linux/input.h>
 #include <poll.h>
@@ -42,12 +40,7 @@
 #include <tuple>
 #include <vector>
 
-namespace android {
-namespace hardware {
-namespace confirmationui {
-namespace V1_0 {
-namespace implementation {
-
+namespace aidl::android::hardware::confirmationui {
 using namespace secure_input;
 
 using ::android::trusty::confirmationui::TrustyAppError;
@@ -64,8 +57,6 @@
 
 using ::secure_input::createSecureInput;
 
-using ::android::hardware::keymaster::V4_0::HardwareAuthToken;
-
 using ::std::tie;
 
 using TeeuiRc = ::teeui::ResponseCode;
@@ -87,46 +78,47 @@
     void release() { f_ = {}; }
 };
 
-ResponseCode convertRc(TeeuiRc trc) {
+int convertRc(TeeuiRc trc) {
     static_assert(
-        uint32_t(TeeuiRc::OK) == uint32_t(ResponseCode::OK) &&
-            uint32_t(TeeuiRc::Canceled) == uint32_t(ResponseCode::Canceled) &&
-            uint32_t(TeeuiRc::Aborted) == uint32_t(ResponseCode::Aborted) &&
-            uint32_t(TeeuiRc::OperationPending) == uint32_t(ResponseCode::OperationPending) &&
-            uint32_t(TeeuiRc::Ignored) == uint32_t(ResponseCode::Ignored) &&
-            uint32_t(TeeuiRc::SystemError) == uint32_t(ResponseCode::SystemError) &&
-            uint32_t(TeeuiRc::Unimplemented) == uint32_t(ResponseCode::Unimplemented) &&
-            uint32_t(TeeuiRc::Unexpected) == uint32_t(ResponseCode::Unexpected) &&
-            uint32_t(TeeuiRc::UIError) == uint32_t(ResponseCode::UIError) &&
-            uint32_t(TeeuiRc::UIErrorMissingGlyph) == uint32_t(ResponseCode::UIErrorMissingGlyph) &&
+        uint32_t(TeeuiRc::OK) == uint32_t(IConfirmationUI::OK) &&
+            uint32_t(TeeuiRc::Canceled) == uint32_t(IConfirmationUI::CANCELED) &&
+            uint32_t(TeeuiRc::Aborted) == uint32_t(IConfirmationUI::ABORTED) &&
+            uint32_t(TeeuiRc::OperationPending) == uint32_t(IConfirmationUI::OPERATION_PENDING) &&
+            uint32_t(TeeuiRc::Ignored) == uint32_t(IConfirmationUI::IGNORED) &&
+            uint32_t(TeeuiRc::SystemError) == uint32_t(IConfirmationUI::SYSTEM_ERROR) &&
+            uint32_t(TeeuiRc::Unimplemented) == uint32_t(IConfirmationUI::UNIMPLEMENTED) &&
+            uint32_t(TeeuiRc::Unexpected) == uint32_t(IConfirmationUI::UNEXPECTED) &&
+            uint32_t(TeeuiRc::UIError) == uint32_t(IConfirmationUI::UI_ERROR) &&
+            uint32_t(TeeuiRc::UIErrorMissingGlyph) ==
+                uint32_t(IConfirmationUI::UI_ERROR_MISSING_GLYPH) &&
             uint32_t(TeeuiRc::UIErrorMessageTooLong) ==
-                uint32_t(ResponseCode::UIErrorMessageTooLong) &&
+                uint32_t(IConfirmationUI::UI_ERROR_MESSAGE_TOO_LONG) &&
             uint32_t(TeeuiRc::UIErrorMalformedUTF8Encoding) ==
-                uint32_t(ResponseCode::UIErrorMalformedUTF8Encoding),
+                uint32_t(IConfirmationUI::UI_ERROR_MALFORMED_UTF8ENCODING),
         "teeui::ResponseCode and "
         "::android::hardware::confirmationui::V1_0::Responsecude are out of "
         "sync");
-    return ResponseCode(trc);
+    return static_cast<int>(trc);
 }
 
 teeui::UIOption convertUIOption(UIOption uio) {
-    static_assert(uint32_t(UIOption::AccessibilityInverted) ==
+    static_assert(uint32_t(UIOption::ACCESSIBILITY_INVERTED) ==
                           uint32_t(teeui::UIOption::AccessibilityInverted) &&
-                      uint32_t(UIOption::AccessibilityMagnified) ==
+                      uint32_t(UIOption::ACCESSIBILITY_MAGNIFIED) ==
                           uint32_t(teeui::UIOption::AccessibilityMagnified),
                   "teeui::UIOPtion and ::android::hardware::confirmationui::V1_0::UIOption "
-                  "anre out of sync");
+                  "are out of sync");
     return teeui::UIOption(uio);
 }
 
-inline MsgString hidl2MsgString(const hidl_string& s) {
+inline MsgString stdString2MsgString(const string& s) {
     return {s.c_str(), s.c_str() + s.size()};
 }
-template <typename T> inline MsgVector<T> hidl2MsgVector(const hidl_vec<T>& v) {
+template <typename T> inline MsgVector<T> stdVector2MsgVector(const vector<T>& v) {
     return {v};
 }
 
-inline MsgVector<teeui::UIOption> hidl2MsgVector(const hidl_vec<UIOption>& v) {
+inline MsgVector<teeui::UIOption> stdVector2MsgVector(const vector<UIOption>& v) {
     MsgVector<teeui::UIOption> result(v.size());
     for (unsigned int i = 0; i < v.size(); ++i) {
         result[i] = convertUIOption(v[i]);
@@ -137,7 +129,7 @@
 }  // namespace
 
 TrustyConfirmationUI::TrustyConfirmationUI()
-    : listener_state_(ListenerState::None), prompt_result_(ResponseCode::Ignored) {}
+    : listener_state_(ListenerState::None), prompt_result_(IConfirmationUI::IGNORED) {}
 
 TrustyConfirmationUI::~TrustyConfirmationUI() {
     ListenerState state = listener_state_;
@@ -385,15 +377,16 @@
     //  ############################## Start 4th Phase - cleanup ##################################
 }
 
-// Methods from ::android::hardware::confirmationui::V1_0::IConfirmationUI
+// Methods from ::aidl::android::hardware::confirmationui::IConfirmationUI
 // follow.
-Return<ResponseCode> TrustyConfirmationUI::promptUserConfirmation(
-    const sp<IConfirmationResultCallback>& resultCB, const hidl_string& promptText,
-    const hidl_vec<uint8_t>& extraData, const hidl_string& locale,
-    const hidl_vec<UIOption>& uiOptions) {
+::ndk::ScopedAStatus TrustyConfirmationUI::promptUserConfirmation(
+    const shared_ptr<IConfirmationResultCallback>& resultCB, const vector<uint8_t>& promptTextBytes,
+    const vector<uint8_t>& extraData, const string& locale, const vector<UIOption>& uiOptions) {
     std::unique_lock<std::mutex> stateLock(listener_state_lock_, std::defer_lock);
+    string promptText(promptTextBytes.begin(), promptTextBytes.end());
     if (!stateLock.try_lock()) {
-        return ResponseCode::OperationPending;
+        return ndk::ScopedAStatus(
+            AStatus_fromServiceSpecificError(IConfirmationUI::OPERATION_PENDING));
     }
     switch (listener_state_) {
     case ListenerState::None:
@@ -401,23 +394,25 @@
     case ListenerState::Starting:
     case ListenerState::SetupDone:
     case ListenerState::Interactive:
-        return ResponseCode::OperationPending;
+        return ndk::ScopedAStatus(
+            AStatus_fromServiceSpecificError(IConfirmationUI::OPERATION_PENDING));
     case ListenerState::Terminating:
         callback_thread_.join();
         listener_state_ = ListenerState::None;
         break;
     default:
-        return ResponseCode::Unexpected;
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificError(IConfirmationUI::UNEXPECTED));
     }
 
     assert(listener_state_ == ListenerState::None);
 
     callback_thread_ = std::thread(
-        [this](sp<IConfirmationResultCallback> resultCB, hidl_string promptText,
-               hidl_vec<uint8_t> extraData, hidl_string locale, hidl_vec<UIOption> uiOptions) {
-            auto [trc, msg, token] =
-                promptUserConfirmation_(hidl2MsgString(promptText), hidl2MsgVector(extraData),
-                                        hidl2MsgString(locale), hidl2MsgVector(uiOptions));
+        [this](const shared_ptr<IConfirmationResultCallback>& resultCB, const string& promptText,
+               const vector<uint8_t>& extraData, const string& locale,
+               const vector<UIOption>& uiOptions) {
+            auto [trc, msg, token] = promptUserConfirmation_(
+                stdString2MsgString(promptText), stdVector2MsgVector(extraData),
+                stdString2MsgString(locale), stdVector2MsgVector(uiOptions));
             bool do_callback = (listener_state_ == ListenerState::Interactive ||
                                 listener_state_ == ListenerState::SetupDone) &&
                                resultCB;
@@ -426,7 +421,7 @@
             if (do_callback) {
                 auto error = resultCB->result(prompt_result_, msg, token);
                 if (!error.isOk()) {
-                    LOG(ERROR) << "Result callback failed " << error.description();
+                    LOG(ERROR) << "Result callback failed " << error.getDescription();
                 }
             } else {
                 listener_state_condv_.notify_all();
@@ -442,14 +437,14 @@
     if (listener_state_ == ListenerState::Terminating) {
         callback_thread_.join();
         listener_state_ = ListenerState::None;
-        return prompt_result_;
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificError(prompt_result_));
     }
-    return ResponseCode::OK;
+    return ndk::ScopedAStatus::ok();
 }
 
-Return<ResponseCode>
+::ndk::ScopedAStatus
 TrustyConfirmationUI::deliverSecureInputEvent(const HardwareAuthToken& secureInputToken) {
-    ResponseCode rc = ResponseCode::Ignored;
+    int rc = IConfirmationUI::IGNORED;
     {
         /*
          * deliverSecureInputEvent is only used by the VTS test to mock human input. A correct
@@ -467,13 +462,17 @@
         listener_state_condv_.wait(stateLock,
                                    [this] { return listener_state_ != ListenerState::SetupDone; });
 
-        if (listener_state_ != ListenerState::Interactive) return ResponseCode::Ignored;
+        if (listener_state_ != ListenerState::Interactive)
+            return ndk::ScopedAStatus(AStatus_fromServiceSpecificError(IConfirmationUI::IGNORED));
         auto sapp = app_.lock();
-        if (!sapp) return ResponseCode::Ignored;
+        if (!sapp)
+            return ndk::ScopedAStatus(AStatus_fromServiceSpecificError(IConfirmationUI::IGNORED));
         auto [error, response] =
             sapp->issueCmd<DeliverTestCommandMessage, DeliverTestCommandResponse>(
                 static_cast<teeui::TestModeCommands>(secureInputToken.challenge));
-        if (error != TrustyAppError::OK) return ResponseCode::SystemError;
+        if (error != TrustyAppError::OK)
+            return ndk::ScopedAStatus(
+                AStatus_fromServiceSpecificError(IConfirmationUI::SYSTEM_ERROR));
         auto& [trc] = response;
         if (trc != TeeuiRc::Ignored) secureInputDelivered_ = true;
         rc = convertRc(trc);
@@ -484,11 +483,14 @@
     // Canceled into OK. Canceled is only returned if the delivered event canceled
     // the operation, which means that the event was successfully delivered. Thus
     // we return OK.
-    if (rc == ResponseCode::Canceled) return ResponseCode::OK;
-    return rc;
+    if (rc == IConfirmationUI::CANCELED) return ndk::ScopedAStatus::ok();
+    if (rc != IConfirmationUI::OK) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificError(rc));
+    }
+    return ndk::ScopedAStatus::ok();
 }
 
-Return<void> TrustyConfirmationUI::abort() {
+::ndk::ScopedAStatus TrustyConfirmationUI::abort() {
     {
         std::unique_lock<std::mutex> stateLock(listener_state_lock_);
         if (listener_state_ == ListenerState::SetupDone ||
@@ -499,15 +501,11 @@
         }
     }
     listener_state_condv_.notify_all();
-    return Void();
+    return ndk::ScopedAStatus::ok();
 }
 
-android::sp<IConfirmationUI> createTrustyConfirmationUI() {
-    return new TrustyConfirmationUI();
+std::shared_ptr<IConfirmationUI> createTrustyConfirmationUI() {
+    return ndk::SharedRefBase::make<TrustyConfirmationUI>();
 }
 
-}  // namespace implementation
-}  // namespace V1_0
-}  // namespace confirmationui
-}  // namespace hardware
-}  // namespace android
+}  // namespace aidl::android::hardware::confirmationui
diff --git a/trusty/confirmationui/TrustyConfirmationUI.h b/trusty/confirmationui/TrustyConfirmationUI.h
index 0bd703c..6e85704 100644
--- a/trusty/confirmationui/TrustyConfirmationUI.h
+++ b/trusty/confirmationui/TrustyConfirmationUI.h
@@ -17,9 +17,11 @@
 #ifndef ANDROID_HARDWARE_CONFIRMATIONUI_V1_0_TRUSTY_CONFIRMATIONUI_H
 #define ANDROID_HARDWARE_CONFIRMATIONUI_V1_0_TRUSTY_CONFIRMATIONUI_H
 
-#include <android/hardware/confirmationui/1.0/IConfirmationUI.h>
-#include <android/hardware/keymaster/4.0/types.h>
-#include <hidl/Status.h>
+#include <aidl/android/hardware/confirmationui/BnConfirmationUI.h>
+#include <aidl/android/hardware/confirmationui/IConfirmationResultCallback.h>
+#include <aidl/android/hardware/confirmationui/UIOption.h>
+#include <aidl/android/hardware/security/keymint/HardwareAuthToken.h>
+#include <android/binder_manager.h>
 
 #include <atomic>
 #include <condition_variable>
@@ -30,35 +32,29 @@
 
 #include "TrustyApp.h"
 
-namespace android {
-namespace hardware {
-namespace confirmationui {
-namespace V1_0 {
-namespace implementation {
+namespace aidl::android::hardware::confirmationui {
 
-using ::android::sp;
-using ::android::hardware::hidl_array;
-using ::android::hardware::hidl_string;
-using ::android::hardware::hidl_vec;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
+using std::shared_ptr;
+using std::string;
+using std::vector;
 
+using ::aidl::android::hardware::security::keymint::HardwareAuthToken;
 using ::android::trusty::confirmationui::TrustyApp;
 
-class TrustyConfirmationUI : public IConfirmationUI {
+class TrustyConfirmationUI : public BnConfirmationUI {
   public:
     TrustyConfirmationUI();
     virtual ~TrustyConfirmationUI();
-    // Methods from ::android::hardware::confirmationui::V1_0::IConfirmationUI
+    // Methods from ::aidl::android::hardware::confirmationui::IConfirmationUI
     // follow.
-    Return<ResponseCode> promptUserConfirmation(const sp<IConfirmationResultCallback>& resultCB,
-                                                const hidl_string& promptText,
-                                                const hidl_vec<uint8_t>& extraData,
-                                                const hidl_string& locale,
-                                                const hidl_vec<UIOption>& uiOptions) override;
-    Return<ResponseCode> deliverSecureInputEvent(
-        const ::android::hardware::keymaster::V4_0::HardwareAuthToken& secureInputToken) override;
-    Return<void> abort() override;
+    ::ndk::ScopedAStatus
+    promptUserConfirmation(const shared_ptr<IConfirmationResultCallback>& resultCB,
+                           const vector<uint8_t>& promptText, const vector<uint8_t>& extraData,
+                           const string& locale, const vector<UIOption>& uiOptions) override;
+    ::ndk::ScopedAStatus
+    deliverSecureInputEvent(const HardwareAuthToken& secureInputToken) override;
+
+    ::ndk::ScopedAStatus abort() override;
 
   private:
     std::weak_ptr<TrustyApp> app_;
@@ -85,7 +81,7 @@
     bool abort_called_;
     std::mutex listener_state_lock_;
     std::condition_variable listener_state_condv_;
-    ResponseCode prompt_result_;
+    int prompt_result_;
     bool secureInputDelivered_;
 
     std::tuple<teeui::ResponseCode, teeui::MsgVector<uint8_t>, teeui::MsgVector<uint8_t>>
@@ -95,10 +91,6 @@
                             const teeui::MsgVector<teeui::UIOption>& uiOptions);
 };
 
-}  // namespace implementation
-}  // namespace V1_0
-}  // namespace confirmationui
-}  // namespace hardware
-}  // namespace android
+}  // namespace aidl::android::hardware::confirmationui
 
 #endif  // ANDROID_HARDWARE_CONFIRMATIONUI_V1_0_TRUSTY_CONFIRMATIONUI_H
diff --git a/trusty/confirmationui/android.hardware.confirmationui-service.trusty.rc b/trusty/confirmationui/android.hardware.confirmationui-service.trusty.rc
new file mode 100644
index 0000000..b5c3159
--- /dev/null
+++ b/trusty/confirmationui/android.hardware.confirmationui-service.trusty.rc
@@ -0,0 +1,5 @@
+service vendor.confirmationui_default /vendor/bin/hw/android.hardware.confirmationui-service.trusty
+    interface aidl android.hardware.confirmationui.IConfirmationUI/default
+    class hal
+    user system
+    group drmrpc input system
diff --git a/trusty/confirmationui/android.hardware.confirmationui@1.0-service.trusty.xml b/trusty/confirmationui/android.hardware.confirmationui-service.trusty.xml
similarity index 71%
rename from trusty/confirmationui/android.hardware.confirmationui@1.0-service.trusty.xml
rename to trusty/confirmationui/android.hardware.confirmationui-service.trusty.xml
index 9008b87..afa2e8e 100644
--- a/trusty/confirmationui/android.hardware.confirmationui@1.0-service.trusty.xml
+++ b/trusty/confirmationui/android.hardware.confirmationui-service.trusty.xml
@@ -1,8 +1,7 @@
 <manifest version="1.0" type="device">
-    <hal format="hidl">
+    <hal format="aidl">
         <name>android.hardware.confirmationui</name>
-        <transport>hwbinder</transport>
-        <version>1.0</version>
+        <version>1</version>
         <interface>
         <name>IConfirmationUI</name>
             <instance>default</instance>
diff --git a/trusty/confirmationui/android.hardware.confirmationui@1.0-service.trusty.rc b/trusty/confirmationui/android.hardware.confirmationui@1.0-service.trusty.rc
deleted file mode 100644
index 3ba6fc0..0000000
--- a/trusty/confirmationui/android.hardware.confirmationui@1.0-service.trusty.rc
+++ /dev/null
@@ -1,4 +0,0 @@
-service confirmationui-1-0 /vendor/bin/hw/android.hardware.confirmationui@1.0-service.trusty
-    class hal
-    user system
-    group drmrpc input system
diff --git a/trusty/confirmationui/include/TrustyConfirmationuiHal.h b/trusty/confirmationui/include/TrustyConfirmationuiHal.h
index 2ab9389..8000ee2 100644
--- a/trusty/confirmationui/include/TrustyConfirmationuiHal.h
+++ b/trusty/confirmationui/include/TrustyConfirmationuiHal.h
@@ -16,18 +16,10 @@
 
 #pragma once
 
-#include <android/hardware/confirmationui/1.0/IConfirmationUI.h>
+#include <aidl/android/hardware/confirmationui/IConfirmationUI.h>
 
-namespace android {
-namespace hardware {
-namespace confirmationui {
-namespace V1_0 {
-namespace implementation {
+namespace aidl::android::hardware::confirmationui {
 
-android::sp<IConfirmationUI> createTrustyConfirmationUI();
+std::shared_ptr<IConfirmationUI> createTrustyConfirmationUI();
 
-}  // namespace implementation
-}  // namespace V1_0
-}  // namespace confirmationui
-}  // namespace hardware
-}  // namespace android
+}  // namespace aidl::android::hardware::confirmationui
diff --git a/trusty/confirmationui/service.cpp b/trusty/confirmationui/service.cpp
index dd7e84b..b286c0a 100644
--- a/trusty/confirmationui/service.cpp
+++ b/trusty/confirmationui/service.cpp
@@ -15,21 +15,28 @@
  */
 
 #include <android-base/logging.h>
-#include <hidl/HidlTransportSupport.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
 
 #include <TrustyConfirmationuiHal.h>
 
-using android::sp;
-using android::hardware::confirmationui::V1_0::implementation::createTrustyConfirmationUI;
+using ::aidl::android::hardware::confirmationui::createTrustyConfirmationUI;
+using ::aidl::android::hardware::confirmationui::IConfirmationUI;
 
 int main() {
-    ::android::hardware::configureRpcThreadpool(1, true /*willJoinThreadpool*/);
-    auto service = createTrustyConfirmationUI();
-    auto status = service->registerAsService();
-    if (status != android::OK) {
-        LOG(FATAL) << "Could not register service for ConfirmationUI 1.0 (" << status << ")";
+    ABinderProcess_setThreadPoolMaxThreadCount(0);
+
+    auto confirmationui = createTrustyConfirmationUI();
+
+    const auto instance = std::string(IConfirmationUI::descriptor) + "/default";
+    binder_status_t status =
+        AServiceManager_addService(confirmationui->asBinder().get(), instance.c_str());
+
+    if (status != STATUS_OK) {
+        LOG(FATAL) << "Could not register service for " << instance.c_str() << "(" << status << ")";
         return -1;
     }
-    ::android::hardware::joinRpcThreadpool();
+
+    ABinderProcess_joinThreadPool();
     return -1;
 }