You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
187 lines
6.2 KiB
187 lines
6.2 KiB
/*
|
|
* Copyright (C) 2021 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <atomic>
|
|
#include <cstdint>
|
|
#include <memory>
|
|
#include <mutex>
|
|
#include <string>
|
|
#include <thread>
|
|
#include <unordered_map>
|
|
#include <vector>
|
|
|
|
#include <android-base/logging.h>
|
|
#include <teeui/utils.h>
|
|
|
|
#include "common/libs/concurrency/multiplexer.h"
|
|
#include "common/libs/concurrency/semaphore.h"
|
|
#include "common/libs/confui/confui.h"
|
|
#include "common/libs/fs/shared_fd.h"
|
|
#include "host/commands/kernel_log_monitor/utils.h"
|
|
#include "host/libs/config/logging.h"
|
|
#include "host/libs/confui/host_mode_ctrl.h"
|
|
#include "host/libs/confui/host_renderer.h"
|
|
#include "host/libs/confui/host_virtual_input.h"
|
|
#include "host/libs/confui/server_common.h"
|
|
#include "host/libs/confui/session.h"
|
|
#include "host/libs/screen_connector/screen_connector.h"
|
|
|
|
namespace cuttlefish {
|
|
namespace confui {
|
|
class HostServer : public HostVirtualInput {
|
|
public:
|
|
static HostServer& Get(
|
|
HostModeCtrl& host_mode_ctrl,
|
|
cuttlefish::ScreenConnectorFrameRenderer& screen_connector);
|
|
|
|
void Start(); // start this server itself
|
|
virtual ~HostServer() = default;
|
|
|
|
// implement input interfaces. called by webRTC & vnc
|
|
void PressConfirmButton(const bool is_down) override;
|
|
void PressCancelButton(const bool is_down) override;
|
|
bool IsConfUiActive() override;
|
|
|
|
private:
|
|
explicit HostServer(
|
|
cuttlefish::HostModeCtrl& host_mode_ctrl,
|
|
cuttlefish::ScreenConnectorFrameRenderer& screen_connector);
|
|
HostServer() = delete;
|
|
|
|
/**
|
|
* basic prompt flow:
|
|
* (1) Without preemption
|
|
* send "kStart" with confirmation message
|
|
* wait kCliAck from the host service with the echoed command
|
|
* wait the confirmation/cancellation (or perhaps reset?)
|
|
* send kStop
|
|
* wait kCliAck from the host service with the echoed command
|
|
*
|
|
* (2) With preemption (e.g.)
|
|
* send "kStart" with confirmation message
|
|
* wait kCliAck from the host service with the echoed command
|
|
* wait the confirmation/cancellation (or perhaps reset?)
|
|
* send kSuspend // when HAL is preempted
|
|
* send kRestore // when HAL resumes
|
|
* send kStop
|
|
*
|
|
* From the host end, it is a close-to-Mealy FSM.
|
|
* There are four states S = {init, session, wait_ack, suspended}
|
|
*
|
|
* 'session' means in a confirmation session. 'wait_ack' means
|
|
* server sends the confirmation and waiting "stop" command from HAL
|
|
* 'suspended' means the HAL service is preemptied. So, the host
|
|
* should render the Android guest frames but keep the confirmation
|
|
* UI session and frame
|
|
*
|
|
* The inputs are I = {u, g}. 'u' is the user input from vnc/webRTC
|
|
* clients. Note that the host service serialized the concurrent user
|
|
* inputs from multiple clients. 'g' is the command from the HAL service
|
|
*
|
|
* The transition rules:
|
|
* (S, I) --> (S, O) where O is the output
|
|
*
|
|
* init, g(start) --> session, set Conf UI mode, render a frame
|
|
* session, u(cancel/confirm) --> waitstop, send the result to HAL
|
|
* session, g(suspend) --> suspend, create a saved session
|
|
* session, g(abort) --> init, clear saved frame
|
|
* waitstop, g(stop) --> init, clear saved frame
|
|
* waitstop, g(suspend) --> suspend, no need to save the session
|
|
* waitstop, g(abort) --> init, clear saved frame
|
|
* suspend, g(restore) --> return to the saved state, restore if there's a
|
|
* saved session
|
|
* suspend, g(abort) --> init, clear saved frame
|
|
*
|
|
* For now, we did not yet implement suspend or abort.
|
|
*
|
|
*/
|
|
[[noreturn]] void MainLoop();
|
|
void HalCmdFetcherLoop();
|
|
|
|
SharedFD EstablishHalConnection();
|
|
|
|
// failed to start dialog, etc
|
|
// basically, will reset the session, so start from the beginning in the same
|
|
// session
|
|
void ResetOnCommandFailure();
|
|
|
|
// note: the picked session will be removed from session_map_
|
|
std::unique_ptr<Session> GetSession(const std::string& session_id) {
|
|
if (session_map_.find(session_id) == session_map_.end()) {
|
|
return nullptr;
|
|
}
|
|
std::unique_ptr<Session> temp = std::move(session_map_[session_id]);
|
|
session_map_.erase(session_id);
|
|
return temp;
|
|
}
|
|
|
|
std::string GetCurrentSessionId() {
|
|
if (curr_session_) {
|
|
return curr_session_->GetId();
|
|
}
|
|
return SESSION_ANY;
|
|
}
|
|
|
|
std::string GetCurrentState() {
|
|
if (!curr_session_) {
|
|
return {"kInvalid"};
|
|
}
|
|
return ToString(curr_session_->GetState());
|
|
}
|
|
std::unique_ptr<Session> ComputeCurrentSession(const std::string& session_id);
|
|
bool SendUserSelection(UserResponse::type selection);
|
|
|
|
const std::uint32_t display_num_;
|
|
HostModeCtrl& host_mode_ctrl_;
|
|
ScreenConnectorFrameRenderer& screen_connector_;
|
|
|
|
// this member creates a raw frame
|
|
ConfUiRenderer renderer_;
|
|
|
|
std::string input_socket_path_;
|
|
std::string hal_socket_path_;
|
|
|
|
// session id to Session object map, for those that are suspended
|
|
std::unordered_map<std::string, std::unique_ptr<Session>> session_map_;
|
|
// curr_session_ doesn't belong to session_map_
|
|
std::unique_ptr<Session> curr_session_;
|
|
|
|
SharedFD guest_hal_socket_;
|
|
// ACCEPTED fd on guest_hal_socket_
|
|
SharedFD hal_cli_socket_;
|
|
std::mutex input_socket_mtx_;
|
|
|
|
/*
|
|
* Multiplexer has N queues. When pop(), it is going to sleep until
|
|
* there's at least one item in at least one queue. The lower the Q
|
|
* index is, the higher the priority is.
|
|
*
|
|
* For HostServer, we have a queue for the user input events, and
|
|
* another for hal cmd/msg queues
|
|
*/
|
|
Multiplexer<ConfUiMessage> input_multiplexer_;
|
|
int hal_cmd_q_id_; // Q id in input_multiplexer_
|
|
int user_input_evt_q_id_; // Q id in input_multiplexer_
|
|
|
|
std::thread main_loop_thread_;
|
|
std::thread hal_input_fetcher_thread_;
|
|
};
|
|
|
|
} // end of namespace confui
|
|
} // end of namespace cuttlefish
|