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