• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 #pragma once
18 
19 #include <atomic>
20 #include <cstdint>
21 #include <memory>
22 #include <mutex>
23 #include <string>
24 #include <thread>
25 #include <unordered_map>
26 #include <vector>
27 
28 #include <android-base/logging.h>
29 #include <teeui/utils.h>
30 
31 #include "common/libs/concurrency/multiplexer.h"
32 #include "common/libs/concurrency/semaphore.h"
33 #include "common/libs/confui/confui.h"
34 #include "common/libs/fs/shared_fd.h"
35 #include "host/commands/kernel_log_monitor/utils.h"
36 #include "host/libs/config/logging.h"
37 #include "host/libs/confui/host_mode_ctrl.h"
38 #include "host/libs/confui/host_renderer.h"
39 #include "host/libs/confui/host_virtual_input.h"
40 #include "host/libs/confui/server_common.h"
41 #include "host/libs/confui/session.h"
42 #include "host/libs/screen_connector/screen_connector.h"
43 
44 namespace cuttlefish {
45 namespace confui {
46 class HostServer : public HostVirtualInput {
47  public:
48   static HostServer& Get(
49       HostModeCtrl& host_mode_ctrl,
50       cuttlefish::ScreenConnectorFrameRenderer& screen_connector);
51 
52   void Start();  // start this server itself
53   virtual ~HostServer() = default;
54 
55   // implement input interfaces. called by webRTC & vnc
56   void PressConfirmButton(const bool is_down) override;
57   void PressCancelButton(const bool is_down) override;
58   bool IsConfUiActive() override;
59 
60  private:
61   explicit HostServer(
62       cuttlefish::HostModeCtrl& host_mode_ctrl,
63       cuttlefish::ScreenConnectorFrameRenderer& screen_connector);
64   HostServer() = delete;
65 
66   /**
67    * basic prompt flow:
68    * (1) Without preemption
69    *  send "kStart" with confirmation message
70    *  wait kCliAck from the host service with the echoed command
71    *  wait the confirmation/cancellation (or perhaps reset?)
72    *  send kStop
73    *  wait kCliAck from the host service with the echoed command
74    *
75    * (2) With preemption (e.g.)
76    *  send "kStart" with confirmation message
77    *  wait kCliAck from the host service with the echoed command
78    *  wait the confirmation/cancellation (or perhaps reset?)
79    *  send kSuspend  // when HAL is preempted
80    *  send kRestore  // when HAL resumes
81    *  send kStop
82    *
83    *  From the host end, it is a close-to-Mealy FSM.
84    *  There are four states S = {init, session, wait_ack, suspended}
85    *
86    *  'session' means in a confirmation session. 'wait_ack' means
87    *  server sends the confirmation and waiting "stop" command from HAL
88    *  'suspended' means the HAL service is preemptied. So, the host
89    *  should render the Android guest frames but keep the confirmation
90    *  UI session and frame
91    *
92    *  The inputs are I = {u, g}. 'u' is the user input from vnc/webRTC
93    *  clients. Note that the host service serialized the concurrent user
94    *  inputs from multiple clients. 'g' is the command from the HAL service
95    *
96    *  The transition rules:
97    *    (S, I) --> (S, O) where O is the output
98    *
99    *   init, g(start) -->  session, set Conf UI mode, render a frame
100    *   session, u(cancel/confirm) --> waitstop, send the result to HAL
101    *   session, g(suspend) --> suspend, create a saved session
102    *   session, g(abort)   --> init, clear saved frame
103    *   waitstop, g(stop) --> init, clear saved frame
104    *   waitstop, g(suspend) --> suspend, no need to save the session
105    *   waitstop, g(abort) --> init, clear saved frame
106    *   suspend, g(restore) --> return to the saved state, restore if there's a
107    *                           saved session
108    *   suspend, g(abort) --> init, clear saved frame
109    *
110    * For now, we did not yet implement suspend or abort.
111    *
112    */
113   [[noreturn]] void MainLoop();
114   void HalCmdFetcherLoop();
115 
116   SharedFD EstablishHalConnection();
117 
118   // failed to start dialog, etc
119   // basically, will reset the session, so start from the beginning in the same
120   // session
121   void ResetOnCommandFailure();
122 
123   // note: the picked session will be removed from session_map_
GetSession(const std::string & session_id)124   std::unique_ptr<Session> GetSession(const std::string& session_id) {
125     if (session_map_.find(session_id) == session_map_.end()) {
126       return nullptr;
127     }
128     std::unique_ptr<Session> temp = std::move(session_map_[session_id]);
129     session_map_.erase(session_id);
130     return temp;
131   }
132 
GetCurrentSessionId()133   std::string GetCurrentSessionId() {
134     if (curr_session_) {
135       return curr_session_->GetId();
136     }
137     return SESSION_ANY;
138   }
139 
GetCurrentState()140   std::string GetCurrentState() {
141     if (!curr_session_) {
142       return {"kInvalid"};
143     }
144     return ToString(curr_session_->GetState());
145   }
146   std::unique_ptr<Session> ComputeCurrentSession(const std::string& session_id);
147   bool SendUserSelection(UserResponse::type selection);
148 
149   const std::uint32_t display_num_;
150   HostModeCtrl& host_mode_ctrl_;
151   ScreenConnectorFrameRenderer& screen_connector_;
152 
153   // this member creates a raw frame
154   ConfUiRenderer renderer_;
155 
156   std::string input_socket_path_;
157   std::string hal_socket_path_;
158 
159   // session id to Session object map, for those that are suspended
160   std::unordered_map<std::string, std::unique_ptr<Session>> session_map_;
161   // curr_session_ doesn't belong to session_map_
162   std::unique_ptr<Session> curr_session_;
163 
164   SharedFD guest_hal_socket_;
165   // ACCEPTED fd on guest_hal_socket_
166   SharedFD hal_cli_socket_;
167   std::mutex input_socket_mtx_;
168 
169   /*
170    * Multiplexer has N queues. When pop(), it is going to sleep until
171    * there's at least one item in at least one queue. The lower the Q
172    * index is, the higher the priority is.
173    *
174    * For HostServer, we have a queue for the user input events, and
175    * another for hal cmd/msg queues
176    */
177   Multiplexer<ConfUiMessage> input_multiplexer_;
178   int hal_cmd_q_id_;         // Q id in input_multiplexer_
179   int user_input_evt_q_id_;  // Q id in input_multiplexer_
180 
181   std::thread main_loop_thread_;
182   std::thread hal_input_fetcher_thread_;
183 };
184 
185 }  // end of namespace confui
186 }  // end of namespace cuttlefish
187