1 /* 2 * 3 * Copyright 2021, The Android Open Source Project 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 #pragma once 19 20 #include <aidl/android/hardware/security/keymint/HardwareAuthToken.h> 21 #include <android-base/logging.h> 22 23 #include <condition_variable> 24 #include <cstdint> 25 #include <memory> 26 #include <mutex> 27 #include <string> 28 #include <tuple> 29 #include <vector> 30 31 #include "common/libs/concurrency/thread_safe_queue.h" 32 #include "common/libs/confui/confui.h" 33 #include "common/libs/fs/shared_fd.h" 34 35 namespace aidl::android::hardware::confirmationui { 36 using ::aidl::android::hardware::security::keymint::HardwareAuthToken; 37 class GuestSession { 38 public: 39 using ConfUiMessage = cuttlefish::confui::ConfUiMessage; 40 using ConfUiAckMessage = cuttlefish::confui::ConfUiAckMessage; 41 using Queue = cuttlefish::ThreadSafeQueue<std::unique_ptr<ConfUiMessage>>; 42 using QueueImpl = Queue::QueueImpl; 43 44 enum class ListenerState : uint32_t { 45 None = 0, 46 Starting = 1, 47 SetupDone = 2, 48 Interactive = 3, 49 Terminating = 4, 50 }; 51 GuestSession(const std::uint32_t session_id,ListenerState & listener_state,std::mutex & listener_state_lock,std::condition_variable & listener_state_condv,cuttlefish::SharedFD host_fd,const teeui::MsgString & promptText,const teeui::MsgVector<uint8_t> & extraData,const teeui::MsgString & locale,const teeui::MsgVector<teeui::UIOption> & uiOptions)52 GuestSession(const std::uint32_t session_id, ListenerState& listener_state, 53 std::mutex& listener_state_lock, std::condition_variable& listener_state_condv, 54 cuttlefish::SharedFD host_fd, const teeui::MsgString& promptText, 55 const teeui::MsgVector<uint8_t>& extraData, const teeui::MsgString& locale, 56 const teeui::MsgVector<teeui::UIOption>& uiOptions) 57 : prompt_text_{promptText.begin(), promptText.end()}, extra_data_{extraData.begin(), 58 extraData.end()}, 59 locale_{locale.begin(), locale.end()}, ui_options_{uiOptions.begin(), uiOptions.end()}, 60 listener_state_(listener_state), listener_state_lock_(listener_state_lock), 61 listener_state_condv_(listener_state_condv), host_fd_{host_fd}, 62 session_name_(MakeName(session_id)), 63 incoming_msg_queue_( 64 20, [this](GuestSession::QueueImpl* impl) { return QueueFullHandler(impl); }) {} 65 ~GuestSession()66 ~GuestSession() { 67 // the thread for PromptUserConfirmation is still alive 68 // the host_fd_ may be alive 69 auto state = listener_state_; 70 if (state == ListenerState::SetupDone || state == ListenerState::Interactive) { 71 Abort(); 72 } 73 // TODO(kwstephenkim): close fd once Session takes the ownership of fd 74 // join host_cmd_fetcher_thread_ once Session takes the ownership of fd 75 } 76 77 using ResultTriple = std::tuple<int, teeui::MsgVector<uint8_t>, teeui::MsgVector<uint8_t>>; 78 ResultTriple PromptUserConfirmation(); 79 80 int DeliverSecureInputEvent(const HardwareAuthToken& secureInputToken); 81 82 void Abort(); GetSessionId()83 std::string GetSessionId() const { return session_name_; } 84 Push(std::unique_ptr<ConfUiMessage> && msg)85 void Push(std::unique_ptr<ConfUiMessage>&& msg) { incoming_msg_queue_.Push(std::move(msg)); } 86 87 private: 88 template <typename F, typename... Args> SerializedSend(F && f,cuttlefish::SharedFD fd,Args &&...args)89 bool SerializedSend(F&& f, cuttlefish::SharedFD fd, Args&&... args) { 90 if (!fd->IsOpen()) { 91 return false; 92 } 93 std::unique_lock<std::mutex> lock(send_serializer_mtx_); 94 return f(fd, std::forward<Args>(args)...); 95 } 96 QueueFullHandler(QueueImpl * queue_impl)97 void QueueFullHandler(QueueImpl* queue_impl) { 98 if (!queue_impl) { 99 LOG(ERROR) << "Registered queue handler is " 100 << "seeing nullptr for queue implementation."; 101 return; 102 } 103 const auto n = (queue_impl->size()) / 2; 104 // pop front half 105 queue_impl->erase(queue_impl->begin(), queue_impl->begin() + n); 106 } 107 MakeName(const std::uint32_t i)108 std::string MakeName(const std::uint32_t i) const { 109 return "ConfirmationUiSession" + std::to_string(i); 110 } 111 std::string prompt_text_; 112 std::vector<std::uint8_t> extra_data_; 113 std::string locale_; 114 std::vector<teeui::UIOption> ui_options_; 115 116 /* 117 * lister_state_lock_ coordinates multiple threads that may 118 * call the three Confirmation UI HAL APIs concurrently 119 */ 120 ListenerState& listener_state_; 121 std::mutex& listener_state_lock_; 122 std::condition_variable& listener_state_condv_; 123 cuttlefish::SharedFD host_fd_; 124 125 const std::string session_name_; 126 Queue incoming_msg_queue_; 127 128 /* 129 * multiple threads could try to write on the vsock at the 130 * same time. E.g. promptUserConfirmation() thread sends 131 * a command while abort() is being called. The abort() thread 132 * will try to write an abort command concurrently. 133 */ 134 std::mutex send_serializer_mtx_; 135 }; 136 } // namespace aidl::android::hardware::confirmationui 137