1 //
2 // Copyright (C) 2021 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 
16 #pragma once
17 
18 #include <cstdint>
19 #include <string>
20 #include <utility>
21 #include <vector>
22 
23 #include <teeui/common_message_types.h>  // /system/teeui/libteeui/.../include
24 
25 #include "common/libs/confui/packet.h"
26 #include "common/libs/confui/packet_types.h"
27 
28 #include "common/libs/confui/utils.h"
29 #include "common/libs/fs/shared_fd.h"
30 
31 namespace cuttlefish {
32 namespace confui {
33 // When you update this, please update all the utility functions
34 // in conf.cpp: e.g. ToString, etc
35 enum class ConfUiCmd : std::uint32_t {
36   kUnknown = 100,
37   kStart = 111,   // start rendering, send confirmation msg, & wait respond
38   kStop = 112,    // start rendering, send confirmation msg, & wait respond
39   kCliAck = 113,  // client acknowledged. "error:err_msg" or "success:command"
40   kCliRespond = 114,  //  with "confirm" or "cancel" or "abort"
41   kAbort = 115,       // to abort the current session
42   kUserInputEvent = 200,
43   kUserTouchEvent = 201
44 };
45 
46 // this is for short messages
47 constexpr const ssize_t kMaxMessageLength = packet::kMaxPayloadLength;
48 
49 std::string ToString(const ConfUiCmd& cmd);
50 std::string ToDebugString(const ConfUiCmd& cmd, const bool is_debug);
51 ConfUiCmd ToCmd(const std::string& cmd_str);
52 ConfUiCmd ToCmd(std::uint32_t i);
53 
54 std::string ToString(const teeui::UIOption ui_opt);
55 std::optional<teeui::UIOption> ToUiOption(const std::string&);
56 
57 struct HostError {
58   static constexpr char kSystemError[] = "system_error";
59   static constexpr char kUIError[] = "ui_error";
60   static constexpr char kMessageTooLongError[] = "msg_too_long_error";
61   static constexpr char kIncorrectUTF8[] = "msg_incorrect_utf8";
62 };
63 
64 struct UserResponse {
65   using type = std::string;
66   constexpr static const auto kConfirm = "user_confirm";
67   constexpr static const auto kCancel = "user_cancel";
68   constexpr static const auto kTouchEvent = "user_touch";
69   // user may close x button on the virtual window or so
70   // or.. scroll the session up and throw to trash bin
71   constexpr static const auto kUserAbort = "user_abort";
72   constexpr static const auto kUnknown = "user_unknown";
73 };
74 
75 class ConfUiMessage {
76  public:
ConfUiMessage(const std::string & session_id)77   ConfUiMessage(const std::string& session_id) : session_id_{session_id} {}
78   virtual ~ConfUiMessage() = default;
79   virtual std::string ToString() const = 0;
SetSessionId(const std::string session_id)80   void SetSessionId(const std::string session_id) { session_id_ = session_id; }
GetSessionId()81   std::string GetSessionId() const { return session_id_; }
82   virtual ConfUiCmd GetType() const = 0;
83   virtual bool SendOver(SharedFD fd) = 0;
84   bool IsUserInput() const;
85 
86  protected:
87   std::string session_id_;
88   template <typename... Args>
CreateString(Args &&...args)89   static std::string CreateString(Args&&... args) {
90     return "[" + ArgsToStringWithDelim(",", std::forward<Args>(args)...) + "]";
91   }
92   template <typename... Args>
Send_(SharedFD fd,const ConfUiCmd cmd,const std::string & session_id,Args &&...args)93   static bool Send_(SharedFD fd, const ConfUiCmd cmd,
94                     const std::string& session_id, Args&&... args) {
95     return packet::WritePayload(fd, confui::ToString(cmd), session_id,
96                                 std::forward<Args>(args)...);
97   }
98 };
99 
100 template <ConfUiCmd cmd>
101 class ConfUiGenericMessage : public ConfUiMessage {
102  public:
ConfUiGenericMessage(const std::string & session_id)103   ConfUiGenericMessage(const std::string& session_id)
104       : ConfUiMessage{session_id} {}
105   virtual ~ConfUiGenericMessage() = default;
ToString()106   std::string ToString() const override {
107     return CreateString(session_id_, confui::ToString(GetType()));
108   }
GetType()109   ConfUiCmd GetType() const override { return cmd; }
SendOver(SharedFD fd)110   bool SendOver(SharedFD fd) override {
111     return Send_(fd, GetType(), session_id_);
112   }
113 };
114 
115 class ConfUiAckMessage : public ConfUiMessage {
116  public:
ConfUiAckMessage(const std::string & session_id,const bool is_success,const std::string & status)117   ConfUiAckMessage(const std::string& session_id, const bool is_success,
118                    const std::string& status)
119       : ConfUiMessage{session_id},
120         is_success_(is_success),
121         status_message_(status) {}
122   virtual ~ConfUiAckMessage() = default;
123   std::string ToString() const override;
GetType()124   ConfUiCmd GetType() const override { return ConfUiCmd::kCliAck; }
125   bool SendOver(SharedFD fd) override;
IsSuccess()126   bool IsSuccess() const { return is_success_; }
GetStatusMessage()127   std::string GetStatusMessage() const { return status_message_; }
128 
129  private:
130   bool is_success_;
131   std::string status_message_;
132 };
133 
134 // the signed user response sent to the guest
135 class ConfUiCliResponseMessage : public ConfUiMessage {
136  public:
137   ConfUiCliResponseMessage(const std::string& session_id,
138                            const UserResponse::type& response,
139                            const std::vector<std::uint8_t>& sign = {},
140                            const std::vector<std::uint8_t>& msg = {})
ConfUiMessage(session_id)141       : ConfUiMessage(session_id),
142         response_(response),
143         sign_(sign),
144         message_{msg} {}
145   virtual ~ConfUiCliResponseMessage() = default;
146   std::string ToString() const override;
GetType()147   ConfUiCmd GetType() const override { return ConfUiCmd::kCliRespond; }
GetResponse()148   auto GetResponse() const { return response_; }
GetMessage()149   auto GetMessage() const { return message_; }
GetSign()150   auto GetSign() const { return sign_; }
151   bool SendOver(SharedFD fd) override;
152 
153  private:
154   UserResponse::type response_;     // plain format
155   std::vector<std::uint8_t> sign_;  // signed format
156   // second argument to pass via resultCB of promptUserConfirmation
157   std::vector<std::uint8_t> message_;
158 };
159 
160 class ConfUiStartMessage : public ConfUiMessage {
161  public:
162   ConfUiStartMessage(const std::string session_id,
163                      const std::string& prompt_text = "",
164                      const std::vector<std::uint8_t>& extra_data = {},
165                      const std::string& locale = "C",
166                      const std::vector<teeui::UIOption> ui_opts = {})
ConfUiMessage(session_id)167       : ConfUiMessage(session_id),
168         prompt_text_(prompt_text),
169         extra_data_(extra_data),
170         locale_(locale),
171         ui_opts_(ui_opts) {}
172   virtual ~ConfUiStartMessage() = default;
173   std::string ToString() const override;
GetType()174   ConfUiCmd GetType() const override { return ConfUiCmd::kStart; }
GetPromptText()175   std::string GetPromptText() const { return prompt_text_; }
GetExtraData()176   std::vector<std::uint8_t> GetExtraData() const { return extra_data_; }
GetLocale()177   std::string GetLocale() const { return locale_; }
GetUiOpts()178   std::vector<teeui::UIOption> GetUiOpts() const { return ui_opts_; }
179   bool SendOver(SharedFD fd) override;
180 
181  private:
182   std::string prompt_text_;
183   std::vector<std::uint8_t> extra_data_;
184   std::string locale_;
185   std::vector<teeui::UIOption> ui_opts_;
186 
187   std::string UiOptsToString() const;
188 };
189 
190 // this one is for deliverSecureInputEvent() as well as
191 // physical-input based implementation
192 class ConfUiUserSelectionMessage : public ConfUiMessage {
193  public:
ConfUiUserSelectionMessage(const std::string & session_id,const UserResponse::type & response)194   ConfUiUserSelectionMessage(const std::string& session_id,
195                              const UserResponse::type& response)
196       : ConfUiMessage(session_id), response_(response) {}
197   virtual ~ConfUiUserSelectionMessage() = default;
198   std::string ToString() const override;
GetType()199   ConfUiCmd GetType() const override { return ConfUiCmd::kUserInputEvent; }
GetResponse()200   auto GetResponse() const { return response_; }
201   bool SendOver(SharedFD fd) override;
202 
203  private:
204   UserResponse::type response_;
205 };
206 
207 class ConfUiUserTouchMessage : public ConfUiMessage {
208  public:
ConfUiUserTouchMessage(const std::string & session_id,const int x,const int y)209   ConfUiUserTouchMessage(const std::string& session_id, const int x,
210                          const int y)
211       : ConfUiMessage(session_id),
212         x_(x),
213         y_(y),
214         response_(UserResponse::kTouchEvent) {}
215   virtual ~ConfUiUserTouchMessage() = default;
216   std::string ToString() const override;
GetType()217   ConfUiCmd GetType() const override { return ConfUiCmd::kUserTouchEvent; }
GetResponse()218   auto GetResponse() const { return response_; }
219   bool SendOver(SharedFD fd) override;
GetLocation()220   std::pair<int, int> GetLocation() const { return {x_, y_}; }
221 
222  private:
223   int x_;
224   int y_;
225   UserResponse::type response_;
226 };
227 
228 using ConfUiAbortMessage = ConfUiGenericMessage<ConfUiCmd::kAbort>;
229 using ConfUiStopMessage = ConfUiGenericMessage<ConfUiCmd::kStop>;
230 
231 }  // end of namespace confui
232 }  // end of namespace cuttlefish
233