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