147 lines
5.2 KiB
C++
147 lines
5.2 KiB
C++
/*
|
|
*
|
|
* Copyright 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 <android-base/logging.h>
|
|
#include <android/hardware/confirmationui/1.0/types.h>
|
|
#include <android/hardware/keymaster/4.0/types.h>
|
|
|
|
#include <condition_variable>
|
|
#include <cstdint>
|
|
#include <memory>
|
|
#include <mutex>
|
|
#include <string>
|
|
#include <tuple>
|
|
#include <vector>
|
|
|
|
#include "common/libs/concurrency/thread_safe_queue.h"
|
|
#include "common/libs/confui/confui.h"
|
|
#include "common/libs/fs/shared_fd.h"
|
|
|
|
namespace android {
|
|
namespace hardware {
|
|
namespace confirmationui {
|
|
namespace V1_0 {
|
|
namespace implementation {
|
|
class GuestSession {
|
|
public:
|
|
using ConfUiMessage = cuttlefish::confui::ConfUiMessage;
|
|
using ConfUiAckMessage = cuttlefish::confui::ConfUiAckMessage;
|
|
using Queue = cuttlefish::ThreadSafeQueue<std::unique_ptr<ConfUiMessage>>;
|
|
using QueueImpl = Queue::QueueImpl;
|
|
|
|
enum class ListenerState : uint32_t {
|
|
None = 0,
|
|
Starting = 1,
|
|
SetupDone = 2,
|
|
Interactive = 3,
|
|
Terminating = 4,
|
|
};
|
|
|
|
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)
|
|
: prompt_text_{promptText.begin(), promptText.end()}, extra_data_{extraData.begin(),
|
|
extraData.end()},
|
|
locale_{locale.begin(), locale.end()}, ui_options_{uiOptions.begin(), uiOptions.end()},
|
|
listener_state_(listener_state), listener_state_lock_(listener_state_lock),
|
|
listener_state_condv_(listener_state_condv), host_fd_{host_fd},
|
|
session_name_(MakeName(session_id)),
|
|
incoming_msg_queue_(
|
|
20, [this](GuestSession::QueueImpl* impl) { return QueueFullHandler(impl); }) {}
|
|
|
|
~GuestSession() {
|
|
// the thread for PromptUserConfirmation is still alive
|
|
// the host_fd_ may be alive
|
|
auto state = listener_state_;
|
|
if (state == ListenerState::SetupDone || state == ListenerState::Interactive) {
|
|
Abort();
|
|
}
|
|
// TODO(kwstephenkim): close fd once Session takes the ownership of fd
|
|
// join host_cmd_fetcher_thread_ once Session takes the ownership of fd
|
|
}
|
|
|
|
using ResultTriple =
|
|
std::tuple<ResponseCode, teeui::MsgVector<uint8_t>, teeui::MsgVector<uint8_t>>;
|
|
ResultTriple PromptUserConfirmation();
|
|
|
|
Return<ResponseCode> DeliverSecureInputEvent(
|
|
const ::android::hardware::keymaster::V4_0::HardwareAuthToken& secureInputToken);
|
|
|
|
Return<void> Abort();
|
|
std::string GetSessionId() const { return session_name_; }
|
|
|
|
void Push(std::unique_ptr<ConfUiMessage>&& msg) { incoming_msg_queue_.Push(std::move(msg)); }
|
|
|
|
private:
|
|
template <typename F, typename... Args>
|
|
bool SerializedSend(F&& f, cuttlefish::SharedFD fd, Args&&... args) {
|
|
if (!fd->IsOpen()) {
|
|
return false;
|
|
}
|
|
std::unique_lock<std::mutex> lock(send_serializer_mtx_);
|
|
return f(fd, std::forward<Args>(args)...);
|
|
}
|
|
|
|
void QueueFullHandler(QueueImpl* queue_impl) {
|
|
if (!queue_impl) {
|
|
LOG(ERROR) << "Registered queue handler is "
|
|
<< "seeing nullptr for queue implementation.";
|
|
return;
|
|
}
|
|
const auto n = (queue_impl->size()) / 2;
|
|
// pop front half
|
|
queue_impl->erase(queue_impl->begin(), queue_impl->begin() + n);
|
|
}
|
|
|
|
std::string MakeName(const std::uint32_t i) const {
|
|
return "ConfirmationUiSession" + std::to_string(i);
|
|
}
|
|
std::string prompt_text_;
|
|
std::vector<std::uint8_t> extra_data_;
|
|
std::string locale_;
|
|
std::vector<teeui::UIOption> ui_options_;
|
|
|
|
/*
|
|
* lister_state_lock_ coordinates multiple threads that may
|
|
* call the three Confirmation UI HAL APIs concurrently
|
|
*/
|
|
ListenerState& listener_state_;
|
|
std::mutex& listener_state_lock_;
|
|
std::condition_variable& listener_state_condv_;
|
|
cuttlefish::SharedFD host_fd_;
|
|
|
|
const std::string session_name_;
|
|
Queue incoming_msg_queue_;
|
|
|
|
/*
|
|
* multiple threads could try to write on the vsock at the
|
|
* same time. E.g. promptUserConfirmation() thread sends
|
|
* a command while abort() is being called. The abort() thread
|
|
* will try to write an abort command concurrently.
|
|
*/
|
|
std::mutex send_serializer_mtx_;
|
|
};
|
|
} // namespace implementation
|
|
} // namespace V1_0
|
|
} // namespace confirmationui
|
|
} // namespace hardware
|
|
} // namespace android
|