Merge "Revert "Add stable aidl memtrack HAL to product packages""
diff --git a/Android.bp b/Android.bp
index 5de274d..f8600e1 100644
--- a/Android.bp
+++ b/Android.bp
@@ -15,14 +15,8 @@
cc_library_headers {
name: "cuttlefish_common_headers",
- vendor: true,
- export_include_dirs: ["."],
- host_supported: true,
-}
-
-cc_library_headers {
- name: "cuttlefish_common_headers_product",
- product_specific: true,
+ vendor_available: true,
+ product_available: true,
export_include_dirs: ["."],
host_supported: true,
}
@@ -45,37 +39,29 @@
},
},
cflags: ["-Werror", "-Wall", "-D_FILE_OFFSET_BITS=64"],
- vendor: true,
}
cc_defaults {
name: "cuttlefish_guest_product_only",
product_specific: true,
- gnu_extensions: false,
- header_libs: [
- "cuttlefish_common_headers_product",
- ],
- target: {
- host: {
- host_ldlibs: ["-lrt"],
- cflags: ["-DCUTTLEFISH_HOST"],
- compile_multilib: "64",
- },
- // We don't need Darwin host-side builds
- darwin: {
- enabled: false,
- },
- },
- cflags: ["-Werror", "-Wall"],
+ defaults: ["cuttlefish_base"],
+}
+
+cc_defaults {
+ name: "cuttlefish_guest_system_ext_only",
+ system_ext_specific: true,
+ defaults: ["cuttlefish_base"],
}
cc_defaults {
name: "cuttlefish_guest_only",
+ vendor: true,
defaults: ["cuttlefish_base"],
}
cc_defaults {
name: "cuttlefish_host_only",
+ vendor: true,
device_supported: false,
host_supported: true,
defaults: ["cuttlefish_base"],
@@ -83,6 +69,7 @@
cc_defaults {
name: "cuttlefish_host_and_guest",
+ vendor: true,
host_supported: true,
defaults: ["cuttlefish_base"],
}
diff --git a/guest/hals/hwcomposer/base_composer.cpp b/guest/hals/hwcomposer/base_composer.cpp
index 1e97bd2..ed42143 100644
--- a/guest/hals/hwcomposer/base_composer.cpp
+++ b/guest/hals/hwcomposer/base_composer.cpp
@@ -30,9 +30,6 @@
void BaseComposer::Dump(char* buff __unused, int buff_len __unused) {}
int BaseComposer::PostFrameBufferTarget(buffer_handle_t buffer_handle) {
- auto buffer_id = screen_view_->NextBuffer();
- void* frame_buffer = screen_view_->GetBuffer(buffer_id);
-
auto imported_buffer_opt = gralloc_.Import(buffer_handle);
if (!imported_buffer_opt) {
ALOGE("Failed to Import() framebuffer for post.");
@@ -52,11 +49,15 @@
ALOGE("Failed to get buffer from view for post.");
return -1;
}
+ void* gralloc_buffer = *buffer_opt;
- void* buffer = *buffer_opt;
- memcpy(frame_buffer, buffer, screen_view_buffer_size_);
+ // TODO(b/173523487): remove hard coded display number.
+ const std::uint32_t display_number = 0;
- screen_view_->Broadcast(buffer_id);
+ std::uint8_t* frame_buffer = screen_view_->AcquireNextBuffer(display_number);
+ std::size_t frame_buffer_size = ScreenView::ScreenSizeBytes(display_number);
+ memcpy(frame_buffer, gralloc_buffer, frame_buffer_size);
+ screen_view_->PresentAcquiredBuffer(display_number);
return 0;
} // namespace cuttlefish
diff --git a/guest/hals/hwcomposer/cpu_composer.cpp b/guest/hals/hwcomposer/cpu_composer.cpp
index 42c3dba..086d610 100644
--- a/guest/hals/hwcomposer/cpu_composer.cpp
+++ b/guest/hals/hwcomposer/cpu_composer.cpp
@@ -651,11 +651,9 @@
int CpuComposer::SetLayers(size_t num_layers, hwc_layer_1_t* layers) {
int targetFbs = 0;
- int buffer_idx = screen_view_->NextBuffer();
const std::uint32_t display_number = 0;
- std::uint8_t* dst_buffer =
- reinterpret_cast<uint8_t*>(screen_view_->GetBuffer(buffer_idx));
+ std::uint8_t* dst_buffer = screen_view_->AcquireNextBuffer(display_number);
std::uint32_t dst_width = ScreenView::ScreenWidth(display_number);
std::uint32_t dst_height = ScreenView::ScreenHeight(display_number);
std::uint32_t dst_stride_bytes = ScreenView::ScreenStrideBytes(display_number);
@@ -709,7 +707,7 @@
if (targetFbs != 1) {
ALOGW("Saw %zu layers, posted=%d", num_layers, targetFbs);
}
- screen_view_->Broadcast(buffer_idx);
+ screen_view_->PresentAcquiredBuffer(display_number);
return 0;
}
diff --git a/guest/hals/hwcomposer/screen_view.cpp b/guest/hals/hwcomposer/screen_view.cpp
index 703dc04..18625bd 100644
--- a/guest/hals/hwcomposer/screen_view.cpp
+++ b/guest/hals/hwcomposer/screen_view.cpp
@@ -86,10 +86,4 @@
return ScreenStrideBytes(display_num) * ScreenHeight(display_num) + kMysteriousSwiftShaderPadding;
}
-int ScreenView::NextBuffer() {
- int num_buffers = this->num_buffers();
- last_buffer_ = num_buffers > 0 ? (last_buffer_ + 1) % num_buffers : -1;
- return last_buffer_;
-}
-
} // namespace cuttlefish
diff --git a/guest/hals/hwcomposer/screen_view.h b/guest/hals/hwcomposer/screen_view.h
index fdaf692..9e7bb0f 100644
--- a/guest/hals/hwcomposer/screen_view.h
+++ b/guest/hals/hwcomposer/screen_view.h
@@ -35,15 +35,17 @@
class ScreenView {
public:
ScreenView() = default;
- ScreenView(const ScreenView&) = delete;
virtual ~ScreenView() = default;
+ ScreenView(const ScreenView&) = delete;
ScreenView& operator=(const ScreenView&) = delete;
- virtual void Broadcast(int buffer_id,
- const CompositionStats* stats = nullptr) = 0;
- virtual int NextBuffer();
- virtual void* GetBuffer(int buffer_id) = 0;
+ // Gets the buffer for the next frame that should be sent to the host.
+ virtual std::uint8_t* AcquireNextBuffer(std::uint32_t display_number) = 0;
+
+ // Mark that the next buffer has been populated with the next frame and is
+ // ready to be sent to the host.
+ virtual void PresentAcquiredBuffer(std::uint32_t display_number) = 0;
static std::uint32_t ScreenCount();
static std::uint32_t ScreenWidth(std::uint32_t display_number);
@@ -53,10 +55,5 @@
static std::uint32_t ScreenStrideBytes(std::uint32_t display_number);
static std::uint32_t ScreenSizeBytes(std::uint32_t display_number);
static constexpr std::uint32_t ScreenBytesPerPixel() { return 4; }
-
- virtual int num_buffers() const = 0;
-
- private:
- int last_buffer_ = 0;
};
} // namespace cuttlefish
\ No newline at end of file
diff --git a/guest/hals/hwcomposer/stats_keeper.h b/guest/hals/hwcomposer/stats_keeper.h
index 771ac5f..8219fbf 100644
--- a/guest/hals/hwcomposer/stats_keeper.h
+++ b/guest/hals/hwcomposer/stats_keeper.h
@@ -153,20 +153,18 @@
: screen_view_(std::move(screen_view)), stats_getter_(stats_getter) {}
virtual ~WrappedScreenView() = default;
- void Broadcast(int buffer_id, const CompositionStats*) override {
+ std::uint8_t* AcquireNextBuffer(std::uint32_t display_number) override {
+ return screen_view_->AcquireNextBuffer(display_number);
+ }
+
+ void PresentAcquiredBuffer(std::uint32_t display_number) override {
// The composer object in stats_keeper produces null stats, use the ones
// provided by the stats_keeper instead.
CompositionStats stats;
stats_getter_(&stats);
- return screen_view_->Broadcast(buffer_id, &stats);
+ return screen_view_->PresentAcquiredBuffer(display_number);
}
- void* GetBuffer(int buffer_id) override {
- return screen_view_->GetBuffer(buffer_id);
- }
-
- int num_buffers() const override { return screen_view_->num_buffers(); }
-
private:
std::unique_ptr<ScreenView> screen_view_;
std::function<void(CompositionStats*)> stats_getter_;
diff --git a/guest/hals/hwcomposer/vsocket_screen_view.cpp b/guest/hals/hwcomposer/vsocket_screen_view.cpp
index c6ae365..8fea483 100644
--- a/guest/hals/hwcomposer/vsocket_screen_view.cpp
+++ b/guest/hals/hwcomposer/vsocket_screen_view.cpp
@@ -18,21 +18,23 @@
#include "guest/hals/hwcomposer/vsocket_screen_view.h"
+#include <algorithm>
+
#include <android-base/logging.h>
#include <cutils/properties.h>
#include <log/log.h>
#include "common/libs/device_config/device_config.h"
+#include "common/libs/fs/shared_buf.h"
namespace cuttlefish {
-VsocketScreenView::VsocketScreenView()
- : broadcast_thread_([this]() { BroadcastLoop(); }) {
- GetScreenParameters();
- // inner_buffer needs to be initialized after the final values of the screen
- // parameters are set (either from the config server or default).
- inner_buffer_size_ = ScreenSizeBytes(/*display_number=*/0);
- inner_buffer_ = std::vector<char>(inner_buffer_size_ * 8);
+VsocketScreenView::VsocketScreenView() {
+ for (std::uint32_t i = 0; i < ScreenCount(); i++) {
+ display_helpers_.emplace_back(new DisplayHelper(i));
+ }
+
+ broadcast_thread_ = std::thread([this]() { BroadcastLoop(); });
}
VsocketScreenView::~VsocketScreenView() {
@@ -40,22 +42,6 @@
broadcast_thread_.join();
}
-void VsocketScreenView::GetScreenParameters() {
- auto device_config_helper = DeviceConfigHelper::Get();
- if (!device_config_helper) {
- ALOGI(
- "Failed to obtain device configuration from server, running in "
- "headless mode");
- // It is impossible to ensure host and guest agree on the screen parameters
- // if these could not be read from the host configuration server. It's best
- // to not attempt to send frames in this case.
- running_ = false;
- // Do a phony Broadcast to ensure the broadcaster thread exits.
- Broadcast(-1);
- return;
- }
-}
-
bool VsocketScreenView::ConnectToScreenServer() {
auto vsock_frames_port = property_get_int64("ro.boot.vsock_frames_port", -1);
if (vsock_frames_port <= 0) {
@@ -81,54 +67,42 @@
"Compositions will occur, but frames won't be sent anywhere");
return;
}
+
// The client detector thread needs to be started after the connection to the
// socket has been made
client_detector_thread_ = std::thread([this]() { ClientDetectorLoop(); });
- unsigned int current_seq = 0;
- unsigned int last_sent_seq = 0;
- int current_offset;
ALOGI("Broadcaster thread loop starting");
while (true) {
{
std::unique_lock<std::mutex> lock(mutex_);
- while (running_ && current_seq == current_seq_ &&
- (!send_frames_ || last_sent_seq == current_seq)) {
+
+ while (running_) {
+ if (std::any_of(display_helpers_.begin(),
+ display_helpers_.end(),
+ [](const auto& display_helper) {
+ return display_helper->HasPresentBuffer();
+ })) {
+ break;
+ }
+
cond_var_.wait(lock);
}
if (!running_) {
ALOGI("Broadcaster thread exiting");
return;
}
- current_offset = current_offset_;
- current_seq = current_seq_;
}
- if (send_frames_ && last_sent_seq != current_seq) {
- last_sent_seq = current_seq;
- if (!SendFrame(current_offset)) {
- break;
+
+ for (auto& display_helper : display_helpers_) {
+ if (!display_helper->SendPresentBufferIfAvailable(&screen_server_)) {
+ ALOGE("Broadcaster thread failed to send frame. Exiting...");
+ return;
}
}
}
}
-bool VsocketScreenView::SendFrame(int offset) {
- int32_t size = static_cast<int32_t>(inner_buffer_size_);
- screen_server_->Write(&size, sizeof(size));
- auto buff = static_cast<char*>(GetBuffer(offset));
- while (size > 0) {
- auto written = screen_server_->Write(buff, size);
- if (written == -1) {
- ALOGE("Broadcaster thread failed to write frame: %s",
- screen_server_->StrError());
- return false;
- }
- size -= written;
- buff += written;
- }
- return true;
-}
-
void VsocketScreenView::ClientDetectorLoop() {
char buffer[8];
while (running_) {
@@ -151,19 +125,110 @@
}
}
-void VsocketScreenView::Broadcast(int offset, const CompositionStats*) {
+std::uint8_t* VsocketScreenView::AcquireNextBuffer(
+ std::uint32_t display_number) {
+ CHECK_GE(display_helpers_.size(), display_number);
+ return display_helpers_[display_number]->AcquireNextBuffer();
+}
+
+void VsocketScreenView::PresentAcquiredBuffer(std::uint32_t display_number) {
+ CHECK_GE(display_helpers_.size(), display_number);
+ display_helpers_[display_number]->PresentAcquiredBuffer();
+
std::lock_guard<std::mutex> lock(mutex_);
- current_offset_ = offset;
- current_seq_++;
cond_var_.notify_all();
}
-void* VsocketScreenView::GetBuffer(int buffer_id) {
- return &inner_buffer_[inner_buffer_size_ * buffer_id];
+VsocketScreenView::DisplayHelper::DisplayHelper(
+ std::uint32_t display_number) : display_number_(display_number) {
+ buffer_size_ = ScreenSizeBytes(display_number);
+ buffers_.resize(kNumBuffersPerDisplay * buffer_size_);
+
+ for (std::uint32_t i = 0; i < kNumBuffersPerDisplay; i++) {
+ acquirable_buffers_indexes_.push_back(i);
+ }
}
-int VsocketScreenView::num_buffers() const {
- return inner_buffer_.size() / inner_buffer_size_;
+std::uint8_t* VsocketScreenView::DisplayHelper::AcquireNextBuffer() {
+ std::uint32_t acquired = 0;
+ {
+ std::lock_guard<std::mutex> lock(acquire_mutex_);
+
+ CHECK(!acquirable_buffers_indexes_.empty());
+ CHECK(!acquired_buffer_index_.has_value());
+
+ acquired = acquirable_buffers_indexes_.front();
+ acquirable_buffers_indexes_.pop_front();
+ acquired_buffer_index_ = acquired;
+ }
+
+ return GetBuffer(acquired);
}
-} // namespace cuttlefish
+void VsocketScreenView::DisplayHelper::PresentAcquiredBuffer() {
+ {
+ std::lock_guard<std::mutex> present_lock(present_mutex_);
+ {
+ std::lock_guard<std::mutex> acquire_lock(acquire_mutex_);
+ CHECK(acquired_buffer_index_.has_value());
+
+ if (present_buffer_index_) {
+ acquirable_buffers_indexes_.push_back(*present_buffer_index_);
+ }
+
+ present_buffer_index_ = *acquired_buffer_index_;
+ acquired_buffer_index_.reset();
+ }
+ }
+}
+
+bool VsocketScreenView::DisplayHelper::HasPresentBuffer() {
+ std::lock_guard<std::mutex> present_lock(present_mutex_);
+ return present_buffer_index_.has_value();
+}
+
+
+bool VsocketScreenView::DisplayHelper::SendPresentBufferIfAvailable(
+ cuttlefish::SharedFD* connection) {
+ {
+ std::lock_guard<std::mutex> present_lock(present_mutex_);
+
+ if (present_buffer_index_) {
+ std::uint32_t frame_buffer_index = *present_buffer_index_;
+ std::uint8_t* frame_bytes = GetBuffer(frame_buffer_index);
+ std::size_t frame_size_bytes = buffer_size_;
+
+ if (WriteAllBinary(*connection, &display_number_) <= 0) {
+ ALOGE("Failed to write: %s", strerror(errno));
+ return false;
+ }
+ int32_t size = static_cast<int32_t>(frame_size_bytes);
+ if (WriteAllBinary(*connection, &size) <= 0) {
+ ALOGE("Failed to write: %s", strerror(errno));
+ return false;
+ }
+ auto* raw = reinterpret_cast<const char*>(frame_bytes);
+ if (WriteAll(*connection, raw, frame_size_bytes) <= 0) {
+ ALOGE("Failed to write: %s", strerror(errno));
+ return false;
+ }
+
+ {
+ std::lock_guard<std::mutex> acquire_lock(acquire_mutex_);
+ acquirable_buffers_indexes_.push_back(frame_buffer_index);
+ }
+
+ present_buffer_index_.reset();
+ }
+
+ return true;
+ }
+}
+
+std::uint8_t* VsocketScreenView::DisplayHelper::GetBuffer(
+ std::uint32_t buffer_index) {
+ buffer_index %= kNumBuffersPerDisplay;
+ return &buffers_[buffer_index * buffer_size_];
+}
+
+} // namespace cuttlefish
\ No newline at end of file
diff --git a/guest/hals/hwcomposer/vsocket_screen_view.h b/guest/hals/hwcomposer/vsocket_screen_view.h
index e0901c7..9a2049e 100644
--- a/guest/hals/hwcomposer/vsocket_screen_view.h
+++ b/guest/hals/hwcomposer/vsocket_screen_view.h
@@ -16,8 +16,10 @@
#pragma once
#include <condition_variable>
+#include <deque>
#include <functional>
#include <mutex>
+#include <optional>
#include <thread>
#include <vector>
@@ -31,30 +33,63 @@
VsocketScreenView();
virtual ~VsocketScreenView();
- void Broadcast(int buffer_id,
- const CompositionStats* stats = nullptr) override;
- void* GetBuffer(int fb_index) override;
+ std::uint8_t* AcquireNextBuffer(std::uint32_t display_number) override;
- int num_buffers() const override;
+ void PresentAcquiredBuffer(std::uint32_t display_number) override;
private:
bool ConnectToScreenServer();
- void GetScreenParameters();
- void BroadcastLoop();
- void ClientDetectorLoop();
- bool SendFrame(int offset);
- std::uint32_t inner_buffer_size_;
- std::vector<char> inner_buffer_;
+ void BroadcastLoop();
+
+ void ClientDetectorLoop();
+
+ class DisplayHelper {
+ public:
+ DisplayHelper(std::uint32_t display_number);
+
+ DisplayHelper(const DisplayHelper&) = delete;
+ DisplayHelper& operator=(const DisplayHelper&) = delete;
+
+ DisplayHelper(DisplayHelper&&) = delete;
+ DisplayHelper& operator=(DisplayHelper&&) = delete;
+
+ std::uint8_t* AcquireNextBuffer();
+
+ void PresentAcquiredBuffer();
+
+ // Returns true if this display has a new frame ready to be sent.
+ bool HasPresentBuffer();
+
+ bool SendPresentBufferIfAvailable(cuttlefish::SharedFD* connection);
+
+ private:
+ std::uint8_t* GetBuffer(std::uint32_t index);
+
+ static constexpr std::uint32_t kNumBuffersPerDisplay = 8;
+
+ std::uint32_t display_number_ = 0;
+
+ std::size_t buffer_size_ = 0;
+ std::vector<std::uint8_t> buffers_;
+
+ std::mutex acquire_mutex_;
+ std::deque<std::uint32_t> acquirable_buffers_indexes_;
+ std::optional<std::uint32_t> acquired_buffer_index_;
+
+ std::mutex present_mutex_;
+ std::optional<std::uint32_t> present_buffer_index_;
+ };
+
+ std::vector<std::unique_ptr<DisplayHelper>> display_helpers_;
+
cuttlefish::SharedFD screen_server_;
std::thread broadcast_thread_;
std::thread client_detector_thread_;
- int current_offset_ = 0;
- unsigned int current_seq_ = 0;
+ bool send_frames_ = false;
std::mutex mutex_;
std::condition_variable cond_var_;
bool running_ = true;
- bool send_frames_{false};
};
-} // namespace cuttlefish
+} // namespace cuttlefish
\ No newline at end of file
diff --git a/guest/hals/ril/reference-libril/ril.h b/guest/hals/ril/reference-libril/ril.h
index 7a070de..194ab5c 100644
--- a/guest/hals/ril/reference-libril/ril.h
+++ b/guest/hals/ril/reference-libril/ril.h
@@ -111,6 +111,7 @@
* RIL_REQUEST_SET_ALLOWED_NETWORK_TYPE_BITMAP
* RIL_REQUEST_SET_DATA_THROTTLING
* RIL_REQUEST_GET_SYSTEM_SELECTION_CHANNELS
+ * RIL_REQUEST_GET_ALLOWED_NETWORK_TYPE_BITMAP
*/
#define RIL_VERSION 12
#define LAST_IMPRECISE_RIL_VERSION 12 // Better self-documented name
@@ -7466,7 +7467,28 @@
*/
#define RIL_REQUEST_GET_SYSTEM_SELECTION_CHANNELS 167
-#define RIL_REQUEST_LAST RIL_REQUEST_GET_SYSTEM_SELECTION_CHANNELS
+/**
+ * RIL_REQUEST_GET_ALLOWED_NETWORK_TYPE_BITMAP
+ *
+ * Request previously set allowed network types from the radio.
+ *
+ * Valid errors:
+ * SUCCESS
+ * RADIO_NOT_AVAILABLE (radio resetting)
+ * OPERATION_NOT_ALLOWED
+ * MODE_NOT_SUPPORTED
+ * NO_MEMORY
+ * INTERNAL_ERR
+ * SYSTEM_ERR
+ * INVALID_ARGUMENTS
+ * MODEM_ERR
+ * REQUEST_NOT_SUPPORTED
+ * NO_RESOURCES
+ * CANCELLED
+ */
+#define RIL_REQUEST_GET_ALLOWED_NETWORK_TYPE_BITMAP 168
+
+#define RIL_REQUEST_LAST RIL_REQUEST_GET_ALLOWED_NETWORK_TYPE_BITMAP
/***********************************************************************/
diff --git a/guest/hals/ril/reference-libril/ril_commands.h b/guest/hals/ril/reference-libril/ril_commands.h
index 031593e..8080181 100644
--- a/guest/hals/ril/reference-libril/ril_commands.h
+++ b/guest/hals/ril/reference-libril/ril_commands.h
@@ -181,5 +181,7 @@
{RIL_REQUEST_START_HANDOVER, radio_1_6::startHandoverResponse},
{RIL_REQUEST_CANCEL_HANDOVER, radio_1_6::cancelHandoverResponse},
{RIL_REQUEST_SET_ALLOWED_NETWORK_TYPE_BITMAP, radio_1_6::setAllowedNetworkTypeBitmapResponse},
- {RIL_REQUEST_SET_DATA_THROTTLING, radio_1_6::setDataThrottlingResponse}
+ {RIL_REQUEST_SET_DATA_THROTTLING, radio_1_6::setDataThrottlingResponse},
+ {RIL_REQUEST_GET_SYSTEM_SELECTION_CHANNELS, radio_1_6::getSystemSelectionChannelsResponse},
+ {RIL_REQUEST_GET_ALLOWED_NETWORK_TYPE_BITMAP, radio_1_6::getAllowedNetworkTypeBitmapResponse}
diff --git a/guest/hals/ril/reference-libril/ril_service.cpp b/guest/hals/ril/reference-libril/ril_service.cpp
index 33635ad..8bb3230 100644
--- a/guest/hals/ril/reference-libril/ril_service.cpp
+++ b/guest/hals/ril/reference-libril/ril_service.cpp
@@ -190,6 +190,8 @@
Return<void> getCurrentCalls(int32_t serial);
+ Return<void> getCurrentCalls_1_6(int32_t serial);
+
Return<void> dial(int32_t serial, const Dial& dialInfo);
Return<void> getImsiForApp(int32_t serial,
@@ -626,6 +628,7 @@
Return<void> getSystemSelectionChannels(int32_t serial);
Return<void> getVoiceRegistrationState_1_6(int32_t serial);
Return<void> getDataRegistrationState_1_6(int32_t serial);
+ Return<void> getAllowedNetworkTypeBitmap(uint32_t serial);
};
struct OemHookImpl : public IOemHook {
@@ -1124,6 +1127,14 @@
return Void();
}
+Return<void> RadioImpl_1_6::getCurrentCalls_1_6(int32_t serial) {
+#if VDBG
+ RLOGD("getCurrentCalls_1_6: serial %d", serial);
+#endif
+ dispatchVoid(serial, mSlotId, RIL_REQUEST_GET_CURRENT_CALLS);
+ return Void();
+}
+
Return<void> RadioImpl_1_6::dial(int32_t serial, const Dial& dialInfo) {
#if VDBG
RLOGD("dial: serial %d", serial);
@@ -3816,6 +3827,14 @@
return Void();
}
+Return<void> RadioImpl_1_6::getAllowedNetworkTypeBitmap(uint32_t serial) {
+#if VDBG
+ RLOGD("getAllowedNetworkTypeBitmap: serial %d", serial);
+#endif
+ dispatchVoid(serial, mSlotId, RIL_REQUEST_GET_ALLOWED_NETWORK_TYPE_BITMAP);
+ return Void();
+}
+
Return<void> RadioImpl_1_6::getSignalStrength_1_4(int32_t serial) {
#if VDBG
RLOGD("getSignalStrength_1_4: serial %d", serial);
@@ -4647,6 +4666,21 @@
return ret;
}
+int responseInt_1_6(::android::hardware::radio::V1_6::RadioResponseInfo &responseInfo, int serial, int responseType, RIL_Errno e,
+ void *response, size_t responseLen) {
+ populateResponseInfo_1_6(responseInfo, serial, responseType, e);
+ int ret = -1;
+
+ if (response == NULL || responseLen != sizeof(int)) {
+ RLOGE("responseInt_1_6: Invalid response");
+ if (e == RIL_E_SUCCESS) responseInfo.error = ::android::hardware::radio::V1_6::RadioError::INVALID_RESPONSE;
+ } else {
+ int *p_int = (int *) response;
+ ret = p_int[0];
+ }
+ return ret;
+}
+
int radio_1_6::getIccCardStatusResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
@@ -7638,6 +7672,30 @@
return 0;
}
+int radio_1_6::getAllowedNetworkTypeBitmapResponse(int slotId,
+ int responseType, int serial, RIL_Errno e,
+ void *response, size_t responseLen) {
+#if VDBG
+ RLOGD("getAllowedNetworkTypeBitmapResponse: serial %d", serial);
+#endif
+
+ if (radioService[slotId]->mRadioResponseV1_6 != NULL) {
+ V1_6::RadioResponseInfo responseInfo = {};
+ int ret = responseInt_1_6(responseInfo, serial, responseType, e, response, responseLen);
+ Return<void> retStatus
+ = radioService[slotId]->mRadioResponseV1_6->getAllowedNetworkTypeBitmapResponse(
+ responseInfo,
+ (const ::android::hardware::hidl_bitfield<
+ ::android::hardware::radio::V1_4::RadioAccessFamily>) ret);
+ radioService[slotId]->checkReturnStatus(retStatus);
+ } else {
+ RLOGE("getAllowedNetworkTypeBitmapResponse: radioService[%d]->mRadioResponseV1_6 == NULL",
+ slotId);
+ }
+
+ return 0;
+}
+
int radio_1_6::getPreferredNetworkTypeResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
diff --git a/guest/hals/ril/reference-libril/ril_service.h b/guest/hals/ril/reference-libril/ril_service.h
index 1373451..36652fd 100644
--- a/guest/hals/ril/reference-libril/ril_service.h
+++ b/guest/hals/ril/reference-libril/ril_service.h
@@ -815,6 +815,10 @@
int setDataThrottlingResponse(int slotId, int responseType, int serial,
RIL_Errno e, void *response, size_t responselen);
+int getAllowedNetworkTypeBitmapResponse(int slotId, int responseType, int serial,
+ RIL_Errno e, void *response, size_t responselen);
+
+
pthread_rwlock_t * getRadioServiceRwlock(int slotId);
void setNitzTimeReceived(int slotId, long timeReceived);
diff --git a/guest/hals/ril/reference-ril/Android.bp b/guest/hals/ril/reference-ril/Android.bp
index 77e4e65..54b1c9f 100644
--- a/guest/hals/ril/reference-ril/Android.bp
+++ b/guest/hals/ril/reference-ril/Android.bp
@@ -45,7 +45,4 @@
"libril-modem-lib",
"libutils",
],
- static_libs: [
- "libqemu_pipe",
- ],
}
diff --git a/guest/hals/ril/reference-ril/reference-ril.c b/guest/hals/ril/reference-ril/reference-ril.c
index 333e4da..6580c0f 100644
--- a/guest/hals/ril/reference-ril/reference-ril.c
+++ b/guest/hals/ril/reference-ril/reference-ril.c
@@ -38,7 +38,6 @@
#include <cutils/properties.h>
#include <cutils/sockets.h>
#include <termios.h>
-#include <qemu_pipe.h>
#include <sys/wait.h>
#include <stdbool.h>
#include <net/if.h>
@@ -326,6 +325,7 @@
static RIL_RadioState sState = RADIO_STATE_UNAVAILABLE;
static bool isNrDualConnectivityEnabled = true;
+static unsigned int allowedNetworkTypeBitmap = UINT_MAX;
static pthread_mutex_t s_state_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t s_state_cond = PTHREAD_COND_INITIALIZER;
@@ -4797,8 +4797,17 @@
requestSetPreferredNetworkType(request, data, datalen, t);
break;
case RIL_REQUEST_SET_ALLOWED_NETWORK_TYPE_BITMAP:
+ if (data == NULL || datalen != sizeof(int)) {
+ RIL_onRequestComplete(t, RIL_E_INTERNAL_ERR, NULL, 0);
+ break;
+ }
+ allowedNetworkTypeBitmap = *(int *)data;
RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
break;
+ case RIL_REQUEST_GET_ALLOWED_NETWORK_TYPE_BITMAP:
+ RIL_onRequestComplete(t, RIL_E_SUCCESS, &allowedNetworkTypeBitmap,
+ sizeof(allowedNetworkTypeBitmap));
+ break;
case RIL_REQUEST_ENABLE_NR_DUAL_CONNECTIVITY:
if (data == NULL || datalen != sizeof(int)) {
RIL_onRequestComplete(t, RIL_E_INTERNAL_ERR, NULL, 0);
diff --git a/guest/services/suspend_blocker/Android.bp b/guest/services/suspend_blocker/Android.bp
index c87c4da..023befa 100644
--- a/guest/services/suspend_blocker/Android.bp
+++ b/guest/services/suspend_blocker/Android.bp
@@ -16,5 +16,5 @@
name: "suspend_blocker",
srcs: ["suspend_blocker.cpp"],
shared_libs: ["libpower"],
- defaults: ["cuttlefish_guest_product_only"],
+ defaults: ["cuttlefish_guest_system_ext_only"],
}
diff --git a/host/commands/assemble_cvd/boot_image_utils.cc b/host/commands/assemble_cvd/boot_image_utils.cc
index 23892e6..3022a09 100644
--- a/host/commands/assemble_cvd/boot_image_utils.cc
+++ b/host/commands/assemble_cvd/boot_image_utils.cc
@@ -68,6 +68,7 @@
return true;
}
+} // namespace
void RepackVendorRamdisk(const std::string& kernel_modules_ramdisk_path,
const std::string& original_ramdisk_path,
@@ -106,7 +107,6 @@
std::ifstream ramdisk_b(kernel_modules_ramdisk_path, std::ios_base::binary);
final_rd << ramdisk_a.rdbuf() << ramdisk_b.rdbuf();
}
-} // namespace
bool RepackBootImage(const std::string& new_kernel_path,
const std::string& boot_image_path,
@@ -141,6 +141,12 @@
return false;
}
+ auto fd = SharedFD::Open(tmp_boot_image_path, O_RDWR);
+ auto original_size = FileSize(boot_image_path);
+ CHECK(fd->Truncate(original_size) == 0)
+ << "`truncate --size=" << original_size << " " << tmp_boot_image_path << "` "
+ << "failed: " << fd->StrError();
+
return DeleteTmpFileIfNotChanged(tmp_boot_image_path, new_boot_image_path);
}
@@ -200,6 +206,12 @@
return false;
}
+ auto fd = SharedFD::Open(tmp_vendor_boot_image_path, O_RDWR);
+ auto original_size = FileSize(vendor_boot_image_path);
+ CHECK(fd->Truncate(original_size) == 0)
+ << "`truncate --size=" << original_size << " " << tmp_vendor_boot_image_path << "` "
+ << "failed: " << fd->StrError();
+
return DeleteTmpFileIfNotChanged(tmp_vendor_boot_image_path, new_vendor_boot_image_path);
}
diff --git a/host/commands/assemble_cvd/boot_image_utils.h b/host/commands/assemble_cvd/boot_image_utils.h
index 43938a7..2f6a9d1 100644
--- a/host/commands/assemble_cvd/boot_image_utils.h
+++ b/host/commands/assemble_cvd/boot_image_utils.h
@@ -30,4 +30,8 @@
const std::string& vendor_boot_image_path,
const std::string& new_vendor_boot_image_path,
const std::string& tmp_artifact_dir);
+void RepackVendorRamdisk(const std::string& kernel_modules_ramdisk_path,
+ const std::string& original_ramdisk_path,
+ const std::string& new_ramdisk_path,
+ const std::string& tmp_artifact_dir);
}
diff --git a/host/commands/assemble_cvd/disk_flags.cc b/host/commands/assemble_cvd/disk_flags.cc
index 273dede..129fce3 100644
--- a/host/commands/assemble_cvd/disk_flags.cc
+++ b/host/commands/assemble_cvd/disk_flags.cc
@@ -418,19 +418,33 @@
SetCommandLineOptionWithMode("vendor_boot_image", new_vendor_boot_image_path.c_str(),
google::FlagSettingMode::SET_FLAGS_DEFAULT);
}
- } else if (!FLAGS_use_bootloader && (!foreign_kernel.size() || foreign_ramdisk.size())) {
+ } else if (!FLAGS_use_bootloader) {
// This code path is taken when the virtual device kernel is launched
// directly by the hypervisor instead of the bootloader.
// This code path takes care of all the ramdisk processing that the
// bootloader normally does.
- const std::string& vendor_ramdisk_path =
- config->initramfs_path().size() ? config->initramfs_path()
+ bool success;
+ if (!foreign_ramdisk.size()) {
+ const std::string& vendor_ramdisk_path =
+ config->initramfs_path().size() ? config->initramfs_path()
: config->vendor_ramdisk_image_path();
- bool success = ConcatRamdisks(
- config->final_ramdisk_path(),
- config->ramdisk_image_path(),
- vendor_ramdisk_path);
- CHECK(success) << "Failed to concatenate ramdisk and vendor ramdisk";
+ success = ConcatRamdisks(
+ config->final_ramdisk_path(),
+ config->ramdisk_image_path(),
+ vendor_ramdisk_path);
+ } else {
+ std::string vendor_ramdisk_repacked_path = config->AssemblyPath("vendor_ramdisk_repacked");
+ RepackVendorRamdisk(
+ config->initramfs_path(),
+ config->vendor_ramdisk_image_path(),
+ vendor_ramdisk_repacked_path,
+ config->assembly_dir());
+ success = ConcatRamdisks(
+ config->final_ramdisk_path(),
+ config->ramdisk_image_path(),
+ vendor_ramdisk_repacked_path);
+ }
+ CHECK(success) << "Failed to concatenate boot ramdisk and vendor ramdisk";
}
if (config->decompress_kernel()) {
diff --git a/host/commands/powerwash_cvd/powerwash_cvd.cc b/host/commands/powerwash_cvd/powerwash_cvd.cc
index 4782e58..483ee61 100644
--- a/host/commands/powerwash_cvd/powerwash_cvd.cc
+++ b/host/commands/powerwash_cvd/powerwash_cvd.cc
@@ -49,7 +49,7 @@
DEFINE_int32(instance_num, cuttlefish::GetInstance(),
"Which instance to powerwash");
-DEFINE_int32(wait_for_launcher, 5,
+DEFINE_int32(wait_for_launcher, 30,
"How many seconds to wait for the launcher to respond to the status "
"command. A value of zero means wait indefinetly");
diff --git a/host/frontend/vnc_server/simulated_hw_composer.cpp b/host/frontend/vnc_server/simulated_hw_composer.cpp
index 354e62d..da9cd59 100644
--- a/host/frontend/vnc_server/simulated_hw_composer.cpp
+++ b/host/frontend/vnc_server/simulated_hw_composer.cpp
@@ -73,7 +73,7 @@
}
void SimulatedHWComposer::MakeStripes() {
- std::uint32_t previous_frame_number = 0;
+ std::uint32_t frame_number = 0;
const std::uint32_t display_number = 0;
const std::uint32_t display_w =
ScreenConnector::ScreenWidth(display_number);
@@ -89,8 +89,13 @@
Message raw_screen;
std::uint64_t stripe_seq_num = 1;
- const FrameCallback frame_callback = [&](uint32_t frame_number,
+ const FrameCallback frame_callback = [&](uint32_t display_number,
uint8_t* frame_pixels) {
+ // TODO(171305898): handle multiple displays.
+ if (display_number != 0) {
+ return;
+ }
+
raw_screen.assign(frame_pixels,
frame_pixels + display_size_bytes);
@@ -104,8 +109,7 @@
display_h / kNumStripes +
(i + 1 == kNumStripes ? display_h % kNumStripes : 0);
const auto* raw_start = &raw_screen[y * display_w * display_bpp];
- const auto* raw_end =
- raw_start + (height * display_w * display_bpp);
+ const auto* raw_end = raw_start + (height * display_w * display_bpp);
// creating a named object and setting individual data members in order
// to make klp happy
// TODO (haining) construct this inside the call when not compiling
@@ -124,13 +128,13 @@
stripes_.Push(std::move(s));
}
- previous_frame_number = frame_number;
+ ++frame_number;
};
while (!closed()) {
bb_->WaitForAtLeastOneClientConnection();
- screen_connector_->OnFrameAfter(previous_frame_number, frame_callback);
+ screen_connector_->OnNextFrame(frame_callback);
}
}
diff --git a/host/frontend/webrtc/connection_observer.cpp b/host/frontend/webrtc/connection_observer.cpp
index 2a22ec0..08ecef4 100644
--- a/host/frontend/webrtc/connection_observer.cpp
+++ b/host/frontend/webrtc/connection_observer.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#define LOG_TAG "ConnectionObserver"
+
#include "host/frontend/webrtc/connection_observer.h"
#include <linux/input.h>
@@ -44,6 +46,13 @@
int32_t value;
};
+struct multitouch_slot {
+ int32_t id;
+ int32_t slot;
+ int32_t x;
+ int32_t y;
+};
+
struct InputEventBuffer {
virtual ~InputEventBuffer() = default;
virtual void AddEvent(uint16_t type, uint16_t code, int32_t value) = 0;
@@ -67,6 +76,7 @@
std::vector<T> buffer_;
};
+// TODO: we could add an arg here to specify whether we want the multitouch buffer?
std::unique_ptr<InputEventBuffer> GetEventBuffer() {
if (FLAGS_write_virtio_input) {
return std::unique_ptr<InputEventBuffer>(
@@ -107,8 +117,10 @@
display_handler->SendLastFrame();
}
}
+
void OnTouchEvent(const std::string & /*display_label*/, int x, int y,
bool down) override {
+
auto buffer = GetEventBuffer();
if (!buffer) {
LOG(ERROR) << "Failed to allocate event buffer";
@@ -117,16 +129,62 @@
buffer->AddEvent(EV_ABS, ABS_X, x);
buffer->AddEvent(EV_ABS, ABS_Y, y);
buffer->AddEvent(EV_KEY, BTN_TOUCH, down);
- buffer->AddEvent(EV_SYN, 0, 0);
+ buffer->AddEvent(EV_SYN, SYN_REPORT, 0);
cuttlefish::WriteAll(input_sockets_.touch_client,
reinterpret_cast<const char *>(buffer->data()),
buffer->size());
}
- void OnMultiTouchEvent(const std::string &display_label, int /*id*/,
- int /*slot*/, int x, int y,
- bool initialDown) override {
- OnTouchEvent(display_label, x, y, initialDown);
+
+ void OnMultiTouchEvent(const std::string & /*display_label*/, Json::Value id,
+ Json::Value slot, Json::Value x, Json::Value y,
+ bool down, int size) override {
+ static bool button_touch = false;
+ static bool finger = false;
+
+ auto buffer = GetEventBuffer();
+ if (!buffer) {
+ LOG(ERROR) << "Failed to allocate event buffer";
+ return;
+ }
+
+ if (!finger) {
+ buffer->AddEvent(EV_KEY, BTN_TOOL_FINGER, 1);
+ finger = true;
+ }
+
+ for (int i=0; i<size; i++) {
+ buffer->AddEvent(EV_ABS, ABS_MT_SLOT, slot[i].asInt());
+
+ auto thisId = id[i].asInt();
+ if (thisId < 0 || down) {
+ buffer->AddEvent(EV_ABS, ABS_MT_TRACKING_ID, thisId);
+ }
+
+ if (thisId >= 0) {
+ // ABS_MT_POSITION_X: Reports the X coordinate of the tool.
+ // ABS_MT_POSITION_Y: Reports the Y coordinate of the tool.
+ buffer->AddEvent(EV_ABS, ABS_MT_POSITION_X, x[i].asInt());
+ buffer->AddEvent(EV_ABS, ABS_MT_POSITION_Y, y[i].asInt());
+ // ABS_{X,Y} must be reported with the location of the touch.
+ buffer->AddEvent(EV_ABS, ABS_X, x[i].asInt());
+ buffer->AddEvent(EV_ABS, ABS_Y, y[i].asInt());
+ }
+
+ if ((!button_touch && down) || (button_touch && !down)) {
+ // BTN_TOUCH must be used to report when a touch is active on the screen.
+ // BTN_TOUCH: Indicates whether the tool is touching the device.
+ buffer->AddEvent(EV_KEY, BTN_TOUCH, down);
+ LOG(VERBOSE) << "BTN_TOUCH " << down;
+ button_touch = !button_touch;
+ }
+ }
+
+ buffer->AddEvent(EV_SYN, SYN_REPORT, 0);
+ cuttlefish::WriteAll(input_sockets_.touch_client,
+ reinterpret_cast<const char *>(buffer->data()),
+ buffer->size());
}
+
void OnKeyboardEvent(uint16_t code, bool down) override {
auto buffer = GetEventBuffer();
if (!buffer) {
@@ -134,11 +192,12 @@
return;
}
buffer->AddEvent(EV_KEY, code, down);
- buffer->AddEvent(EV_SYN, 0, 0);
+ buffer->AddEvent(EV_SYN, SYN_REPORT, 0);
cuttlefish::WriteAll(input_sockets_.keyboard_client,
reinterpret_cast<const char *>(buffer->data()),
buffer->size());
}
+
void OnAdbChannelOpen(std::function<bool(const uint8_t *, size_t)>
adb_message_sender) override {
LOG(VERBOSE) << "Adb Channel open";
diff --git a/host/frontend/webrtc/display_handler.cpp b/host/frontend/webrtc/display_handler.cpp
index 86d6e8d..0d5f493 100644
--- a/host/frontend/webrtc/display_handler.cpp
+++ b/host/frontend/webrtc/display_handler.cpp
@@ -31,11 +31,16 @@
const int display_w = screen_connector_->ScreenWidth(display_num);
const int display_h = screen_connector_->ScreenHeight(display_num);
const int display_stride_bytes = screen_connector_->ScreenStrideBytes(display_num);
- std::uint32_t frame_num = 0;
+
for (;;) {
- auto have_frame = screen_connector_->OnFrameAfter(
- frame_num, [&, this](std::uint32_t fn, std::uint8_t* frame) {
- frame_num = fn;
+ auto have_frame = screen_connector_->OnNextFrame(
+ [&, this](
+ std::uint32_t display_number,
+ std::uint8_t* frame) {
+ // TODO(171305898): handle multiple displays.
+ if (display_number != 0) {
+ return;
+ }
std::shared_ptr<CvdVideoFrameBuffer> buffer(
new CvdVideoFrameBuffer(display_w, display_h));
libyuv::ABGRToI420(frame, display_stride_bytes,
diff --git a/host/frontend/webrtc/lib/client_handler.cpp b/host/frontend/webrtc/lib/client_handler.cpp
index d506238..6ea61fc 100644
--- a/host/frontend/webrtc/lib/client_handler.cpp
+++ b/host/frontend/webrtc/lib/client_handler.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#define LOG_TAG "ClientHandler"
+
#include "host/frontend/webrtc/lib/client_handler.h"
#include <vector>
@@ -205,24 +207,26 @@
} else if (event_type == "multi-touch") {
auto result =
ValidationResult::ValidateJsonObject(evt, "multi-touch",
- {{"id", Json::ValueType::intValue},
- {"initialDown", Json::ValueType::intValue},
- {"x", Json::ValueType::intValue},
- {"y", Json::ValueType::intValue},
- {"slot", Json::ValueType::intValue},
+ {{"id", Json::ValueType::arrayValue},
+ {"down", Json::ValueType::intValue},
+ {"x", Json::ValueType::arrayValue},
+ {"y", Json::ValueType::arrayValue},
+ {"slot", Json::ValueType::arrayValue},
{"display_label", Json::ValueType::stringValue}});
if (!result.ok()) {
LOG(ERROR) << result.error();
return;
}
- auto label = evt["display_label"].asString();
- int32_t id = evt["id"].asInt();
- int32_t initialDown = evt["initialDown"].asInt();
- int32_t x = evt["x"].asInt();
- int32_t y = evt["y"].asInt();
- int32_t slot = evt["slot"].asInt();
- observer_->OnMultiTouchEvent(label, id, slot, x, y, initialDown);
+ auto label = evt["display_label"].asString();
+ auto idArr = evt["id"];
+ int32_t down = evt["down"].asInt();
+ auto xArr = evt["x"];
+ auto yArr = evt["y"];
+ auto slotArr = evt["slot"];
+ int size = evt["id"].size();
+
+ observer_->OnMultiTouchEvent(label, idArr, slotArr, xArr, yArr, down, size);
} else if (event_type == "keyboard") {
auto result =
ValidationResult::ValidateJsonObject(evt, "keyboard",
diff --git a/host/frontend/webrtc/lib/connection_observer.h b/host/frontend/webrtc/lib/connection_observer.h
index 80965e9..9cd7286 100644
--- a/host/frontend/webrtc/lib/connection_observer.h
+++ b/host/frontend/webrtc/lib/connection_observer.h
@@ -32,8 +32,8 @@
std::function<void(const uint8_t*, size_t, bool)> ctrl_msg_sender) = 0;
virtual void OnTouchEvent(const std::string& display_label, int x, int y,
bool down) = 0;
- virtual void OnMultiTouchEvent(const std::string& label, int id, int slot,
- int x, int y, bool initialDown) = 0;
+ virtual void OnMultiTouchEvent(const std::string& label, Json::Value id, Json::Value slot,
+ Json::Value x, Json::Value y, bool down, int size) = 0;
virtual void OnKeyboardEvent(uint16_t keycode, bool down) = 0;
virtual void OnAdbChannelOpen(
std::function<bool(const uint8_t*, size_t)> adb_message_sender) = 0;
diff --git a/host/frontend/webrtc/lib/local_recorder.cpp b/host/frontend/webrtc/lib/local_recorder.cpp
index 54382c9..28f71b0 100644
--- a/host/frontend/webrtc/lib/local_recorder.cpp
+++ b/host/frontend/webrtc/lib/local_recorder.cpp
@@ -38,6 +38,11 @@
namespace cuttlefish {
namespace webrtc_streaming {
+constexpr double kRtpTicksPerSecond = 90000.;
+constexpr double kRtpTicksPerMs = kRtpTicksPerSecond / 1000.;
+constexpr double kRtpTicksPerUs = kRtpTicksPerMs / 1000.;
+constexpr double kRtpTicksPerNs = kRtpTicksPerUs / 1000.;
+
class LocalRecorder::Display
: public webrtc::EncodedImageCallback
, public rtc::VideoSinkInterface<webrtc::VideoFrame> {
@@ -60,7 +65,6 @@
std::shared_ptr<webrtc::VideoTrackSourceInterface> source_;
std::unique_ptr<webrtc::VideoEncoder> video_encoder_;
uint64_t video_track_number_;
- std::chrono::time_point<std::chrono::steady_clock> start_timestamp_;
// TODO(schuffelen): Use a WebRTC task queue?
std::thread encoder_thread_;
@@ -94,6 +98,9 @@
return {};
}
+ impl->segment_.AccurateClusterDuration(true);
+ impl->segment_.set_estimate_file_duration(true);
+
impl->encoder_factory_ = webrtc::CreateBuiltinVideoEncoderFactory();
if (!impl->encoder_factory_) {
LOG(ERROR) << "Failed to create webRTC built-in video encoder factory";
@@ -180,8 +187,7 @@
impl_->segment_.Finalize();
}
-LocalRecorder::Display::Display(LocalRecorder::Impl& impl)
- : impl_(impl), start_timestamp_(std::chrono::steady_clock::now()) {
+LocalRecorder::Display::Display(LocalRecorder::Impl& impl) : impl_(impl) {
}
void LocalRecorder::Display::OnFrame(const webrtc::VideoFrame& frame) {
@@ -196,6 +202,9 @@
}
void LocalRecorder::Display::EncoderLoop() {
+ int frames_since_keyframe = 0;
+ std::chrono::time_point<std::chrono::steady_clock> start_timestamp;
+ auto last_keyframe_time = std::chrono::steady_clock::now();
while (encoder_running_) {
std::unique_ptr<webrtc::VideoFrame> frame;
{
@@ -210,8 +219,27 @@
std::move(encode_queue_.front()));
encode_queue_.pop_front();
}
- std::vector<webrtc::VideoFrameType> types{
- webrtc::VideoFrameType::kVideoFrameDelta};
+
+ auto now = std::chrono::steady_clock::now();
+ if (start_timestamp.time_since_epoch().count() == 0) {
+ start_timestamp = now;
+ }
+ auto timestamp_diff =
+ std::chrono::duration_cast<std::chrono::microseconds>(
+ now - start_timestamp);
+ frame->set_timestamp_us(timestamp_diff.count());
+ frame->set_timestamp(timestamp_diff.count() * kRtpTicksPerUs);
+
+ std::vector<webrtc::VideoFrameType> types;
+ auto time_since_keyframe = now - last_keyframe_time;
+ const auto min_keyframe_time = std::chrono::seconds(10);
+ if (frames_since_keyframe > 60 || time_since_keyframe > min_keyframe_time) {
+ last_keyframe_time = now;
+ frames_since_keyframe = 0;
+ types.push_back(webrtc::VideoFrameType::kVideoFrameKey);
+ } else {
+ types.push_back(webrtc::VideoFrameType::kVideoFrameDelta);
+ }
auto rc = video_encoder_->Encode(*frame, &types);
if (rc != 0) {
LOG(ERROR) << "Failed to encode frame";
@@ -231,18 +259,18 @@
const webrtc::EncodedImage& encoded_image,
const webrtc::CodecSpecificInfo* codec_specific_info,
const webrtc::RTPFragmentationHeader* fragmentation) {
- auto timestamp_diff =
- std::chrono::duration_cast<std::chrono::nanoseconds>(
- std::chrono::steady_clock::now() - start_timestamp_).count();
+ uint64_t timestamp = encoded_image.Timestamp() / kRtpTicksPerNs;
std::lock_guard(impl_.mkv_mutex_);
+ bool is_key =
+ encoded_image._frameType == webrtc::VideoFrameType::kVideoFrameKey;
bool success = impl_.segment_.AddFrame(
encoded_image.data(),
encoded_image.size(),
video_track_number_,
- timestamp_diff,
- /* is_key */ false);
+ timestamp,
+ is_key);
webrtc::EncodedImageCallback::Result result(
success
diff --git a/host/frontend/webrtc_operator/assets/js/app.js b/host/frontend/webrtc_operator/assets/js/app.js
index 46931b5..5846e22 100644
--- a/host/frontend/webrtc_operator/assets/js/app.js
+++ b/host/frontend/webrtc_operator/assets/js/app.js
@@ -41,6 +41,8 @@
let buttonsWaitingOnAdbConnection = [];
let mouseIsDown = false;
let deviceConnection;
+ let touchIdSlotMap = new Map();
+ let touchSlots = new Array();
let rotation = 0;
let screenHasBeenResized = false;
@@ -305,7 +307,7 @@
// console.log("mousedown at " + e.pageX + " / " + e.pageY);
mouseIsDown = true;
- sendMouseUpdate(true, e);
+ sendEventUpdate(true, e);
}
function onEndDrag(e) {
@@ -314,7 +316,7 @@
// console.log("mouseup at " + e.pageX + " / " + e.pageY);
mouseIsDown = false;
- sendMouseUpdate(false, e);
+ sendEventUpdate(false, e);
}
function onContinueDrag(e) {
@@ -323,29 +325,33 @@
// console.log("mousemove at " + e.pageX + " / " + e.pageY + ", down=" +
// mouseIsDown);
if (mouseIsDown) {
- sendMouseUpdate(true, e);
+ sendEventUpdate(true, e);
}
}
- function sendMouseUpdate(down, e) {
+ function sendEventUpdate(down, e) {
console.assert(deviceConnection, 'Can\'t send mouse update without device');
- var x = e.offsetX;
- var y = e.offsetY;
+ var eventType = e.type.substring(0, 5);
- let elementWidth, elementHeight;
- if (screenHasBeenResized) {
- elementWidth = parseInt(deviceScreen.style.width, 10);
- elementHeight = parseInt(deviceScreen.style.height, 10);
- } else {
- // Before the first video frame arrives there is no way to know width and
- // height of the device's screen, so turn every click into a click at 0x0.
- // A click at that position is not more dangerous than anywhere else since
- // the user is clicking blind anyways.
- elementWidth = deviceScreen.offsetWidth? deviceScreen.offsetWidth: 1;
- elementHeight = deviceScreen.offsetHeight? deviceScreen.offsetHeight: 1;
- }
+ // Before the first video frame arrives there is no way to know width and
+ // height of the device's screen, so turn every click into a click at 0x0.
+ // A click at that position is not more dangerous than anywhere else since
+ // the user is clicking blind anyways.
const videoWidth = deviceScreen.videoWidth? deviceScreen.videoWidth: 1;
const videoHeight = deviceScreen.videoHeight? deviceScreen.videoHeight: 1;
+ const elementWidth = deviceScreen.offsetWidth? deviceScreen.offsetWidth: 1;
+ const elementHeight = deviceScreen.offsetHeight? deviceScreen.offsetHeight: 1;
+
+ // vh*ew > eh*vw? then scale h instead of w
+ const scaleHeight = videoHeight * elementWidth > videoWidth * elementHeight;
+ var elementScaling = 0, videoScaling = 0;
+ if (scaleHeight) {
+ elementScaling = elementHeight;
+ videoScaling = videoHeight;
+ } else {
+ elementScaling = elementWidth;
+ videoScaling = videoWidth;
+ }
// The screen uses the 'object-fit: cover' property in order to completely
// fill the element while maintaining the screen content's aspect ratio.
@@ -372,23 +378,101 @@
// - The sent ABS_X and ABS_Y values need to be scaled based on the
// ratio between the max size (video size) and in-browser size.
const scaling = scaleWidth ? videoWidth / elementWidth : videoHeight / elementHeight;
- x = x * scaling;
- y = y * scaling;
- // Substract the offset produced by the difference in aspect ratio, if any.
- if (scaleWidth) {
- // Width was scaled, leaving excess content height, so subtract from y.
- y -= (elementHeight * scaling - videoHeight) / 2;
- } else {
- // Height was scaled, leaving excess content width, so subtract from x.
- x -= (elementWidth * scaling - videoWidth) / 2;
+ var xArr = [];
+ var yArr = [];
+ var idArr = [];
+ var slotArr = [];
+
+ console.log('e.type: ' + e.type);
+ if (eventType == "mouse" || eventType == "point") {
+ xArr.push(e.offsetX);
+ yArr.push(e.offsetY);
+
+ let thisId = -1;
+ if (eventType == "point") {
+ thisId = e.pointerId;
+ }
+
+ slotArr.push(0);
+ idArr.push(thisId);
+ } else if (eventType == "touch") {
+ // touchstart: list of touch points that became active
+ // touchmove: list of touch points that changed
+ // touchend: list of touch points that were removed
+ let changes = e.changedTouches;
+ let rect = e.target.getBoundingClientRect();
+ for (var i=0; i < changes.length; i++) {
+ xArr.push(changes[i].pageX - rect.left);
+ yArr.push(changes[i].pageY - rect.top);
+ idArr.push(changes[i].identifier);
+ if (touchIdSlotMap.has(changes[i].identifier)) {
+ let slot = touchIdSlotMap.get(changes[i].identifier);
+
+ slotArr.push(slot);
+ if (e.type == 'touchstart') {
+ // error
+ console.error('touchstart when already have slot');
+ return;
+ } else if (e.type == 'touchmove') {
+ idArr.push(changes[i].identifier);
+ } else if (e.type == 'touchend') {
+ touchSlots[slot] = false;
+ touchIdSlotMap.delete(changes[i].identifier);
+ idArr.push(-1);
+ }
+ } else {
+ if (e.type == 'touchstart') {
+ let slot = -1;
+ for (var j=0; j < touchSlots.length; j++) {
+ if (!touchSlots[j]) {
+ slot = j;
+ break;
+ }
+ }
+ if (slot == -1) {
+ slot = touchSlots.length;
+ touchSlots.push(true);
+ }
+ slotArr.push(slot);
+ touchSlots[slot] = true;
+ touchIdSlotMap.set(changes[i].identifier, slot);
+ idArr.push(changes[i].identifier);
+ } else if (e.type == 'touchmove') {
+ // error
+ console.error('touchmove when no slot');
+ return;
+ } else if (e.type == 'touchend') {
+ // error
+ console.error('touchend when no slot');
+ return;
+ }
+ }
+ }
+ }
+
+ for (var i=0; i < xArr.length; i++) {
+ xArr[i] = xArr[i] * scaling;
+ yArr[i] = yArr[i] * scaling;
+
+ // Substract the offset produced by the difference in aspect ratio, if any.
+ if (scaleWidth) {
+ // Width was scaled, leaving excess content height, so subtract from y.
+ yArr[i] -= (elementHeight * scaling - videoHeight) / 2;
+ } else {
+ // Height was scaled, leaving excess content width, so subtract from x.
+ xArr[i] -= (elementWidth * scaling - videoWidth) / 2;
+ }
+
+ xArr[i] = Math.trunc(xArr[i]);
+ yArr[i] = Math.trunc(yArr[i]);
}
// NOTE: Rotation is handled automatically because the CSS rotation through
// transforms also rotates the coordinates of events on the object.
- deviceConnection.sendMousePosition(
- {x: Math.trunc(x), y: Math.trunc(y), down, display_label});
+ deviceConnection.sendMultiTouch(
+ {idArr, xArr, yArr, down, slotArr, display_label});
}
function onKeyEvent(e) {
diff --git a/host/frontend/webrtc_operator/assets/js/cf_webrtc.js b/host/frontend/webrtc_operator/assets/js/cf_webrtc.js
index ac40070..fb9114b 100644
--- a/host/frontend/webrtc_operator/assets/js/cf_webrtc.js
+++ b/host/frontend/webrtc_operator/assets/js/cf_webrtc.js
@@ -154,15 +154,15 @@
// TODO (b/124121375): This should probably be an array of pointer events and
// have different properties.
- sendMultiTouch({id, x, y, initialDown, slot, display_label}) {
+ sendMultiTouch({idArr, xArr, yArr, down, slotArr, display_label}) {
this._sendJsonInput({
type: 'multi-touch',
- id,
- x,
- y,
- initialDown: initialDown ? 1 : 0,
- slot,
- display_label,
+ id: idArr,
+ x: xArr,
+ y: yArr,
+ down: down ? 1 : 0,
+ slot: slotArr,
+ display_label: display_label,
});
}
diff --git a/host/libs/screen_connector/screen_connector.h b/host/libs/screen_connector/screen_connector.h
index b71dea4..dc0a367 100644
--- a/host/libs/screen_connector/screen_connector.h
+++ b/host/libs/screen_connector/screen_connector.h
@@ -24,7 +24,7 @@
namespace cuttlefish {
-using FrameCallback = std::function<void(std::uint32_t /*frame_number*/,
+using FrameCallback = std::function<void(std::uint32_t /*display_number*/,
std::uint8_t* /*frame_pixels*/)>;
class ScreenConnector {
@@ -33,10 +33,9 @@
virtual ~ScreenConnector() = default;
- // Runs the given callback on the next available frame after the given
- // frame number and returns true if successful.
- virtual bool OnFrameAfter(std::uint32_t frame_number,
- const FrameCallback& frame_callback) = 0;
+ // Runs the given callback on the next available frame and returns true if
+ // successful.
+ virtual bool OnNextFrame(const FrameCallback& frame_callback) = 0;
// Let the screen connector know when there are clients connected
virtual void ReportClientsConnected(bool have_clients);
diff --git a/host/libs/screen_connector/socket_based_screen_connector.cpp b/host/libs/screen_connector/socket_based_screen_connector.cpp
index 9f5252f..93b3bc2 100644
--- a/host/libs/screen_connector/socket_based_screen_connector.cpp
+++ b/host/libs/screen_connector/socket_based_screen_connector.cpp
@@ -23,34 +23,103 @@
namespace cuttlefish {
SocketBasedScreenConnector::SocketBasedScreenConnector(int frames_fd) {
+ for (std::uint32_t i = 0; i < ScreenCount(); i++) {
+ display_helpers_.emplace_back(new DisplayHelper(i));
+ }
+
screen_server_thread_ =
std::thread([this, frames_fd]() { ServerLoop(frames_fd); });
-
- buffer_size_ = ScreenSizeInBytes(/*display_number=*/0);
- buffer_.resize(kNumBuffersPerDisplay * buffer_size_);
}
-bool SocketBasedScreenConnector::OnFrameAfter(
- std::uint32_t frame_number, const FrameCallback& frame_callback) {
- int buffer_idx = WaitForNewFrameSince(&frame_number);
- void* buffer = GetBuffer(buffer_idx);
- frame_callback(frame_number, reinterpret_cast<uint8_t*>(buffer));
- return true;
-}
+SocketBasedScreenConnector::DisplayHelper::DisplayHelper(
+ std::uint32_t display_number) : display_number_(display_number) {
+ buffer_size_ = ScreenSizeInBytes(display_number);
+ buffers_.resize(kNumBuffersPerDisplay * buffer_size_);
-int SocketBasedScreenConnector::WaitForNewFrameSince(std::uint32_t* seq_num) {
- std::unique_lock<std::mutex> lock(new_frame_mtx_);
- while (seq_num_ == *seq_num) {
- new_frame_cond_var_.wait(lock);
+ for (std::uint32_t i = 0; i < kNumBuffersPerDisplay; i++) {
+ acquirable_buffers_indexes_.push_back(i);
}
- *seq_num = seq_num_;
- return newest_buffer_;
}
-void* SocketBasedScreenConnector::GetBuffer(int buffer_idx) {
- if (buffer_idx < 0) return nullptr;
- buffer_idx %= kNumBuffersPerDisplay;
- return &buffer_[buffer_idx * buffer_size_];
+std::uint8_t* SocketBasedScreenConnector::DisplayHelper::AcquireNextBuffer() {
+ std::uint32_t acquired = 0;
+ {
+ std::lock_guard<std::mutex> lock(acquire_mutex_);
+
+ CHECK(!acquirable_buffers_indexes_.empty());
+ CHECK(!acquired_buffer_index_.has_value());
+
+ acquired = acquirable_buffers_indexes_.front();
+ acquirable_buffers_indexes_.pop_front();
+ acquired_buffer_index_ = acquired;
+ }
+
+ return GetBuffer(acquired);
+}
+
+void SocketBasedScreenConnector::DisplayHelper::PresentAcquiredBuffer() {
+ {
+ std::lock_guard<std::mutex> present_lock(present_mutex_);
+ {
+ std::lock_guard<std::mutex> acquire_lock(acquire_mutex_);
+ CHECK(acquired_buffer_index_.has_value());
+
+ if (present_buffer_index_) {
+ acquirable_buffers_indexes_.push_back(*present_buffer_index_);
+ }
+
+ present_buffer_index_ = *acquired_buffer_index_;
+ acquired_buffer_index_.reset();
+ }
+ }
+}
+
+bool SocketBasedScreenConnector::DisplayHelper::ConsumePresentBuffer(
+ const FrameCallback& frame_callback) {
+ {
+ std::lock_guard<std::mutex> present_lock(present_mutex_);
+
+ if (present_buffer_index_) {
+ std::uint32_t frame_buffer_index = *present_buffer_index_;
+ std::uint8_t* frame_bytes = GetBuffer(frame_buffer_index);
+ frame_callback(display_number_, frame_bytes);
+
+ {
+ std::lock_guard<std::mutex> acquire_lock(acquire_mutex_);
+ acquirable_buffers_indexes_.push_back(frame_buffer_index);
+ }
+
+ present_buffer_index_.reset();
+ return true;
+ } else {
+ return false;
+ }
+ }
+}
+
+std::uint8_t* SocketBasedScreenConnector::DisplayHelper::GetBuffer(
+ std::uint32_t buffer_index) {
+ return &buffers_[buffer_index * buffer_size_];
+}
+
+bool SocketBasedScreenConnector::OnNextFrame(const FrameCallback& frame_callback) {
+ while (true) {
+ std::unique_lock<std::mutex> lock(frame_available_mutex_);
+
+ for (std::size_t i = 0; i < display_helpers_.size(); i++) {
+ auto& display_helper = display_helpers_[frame_available_display_index];
+ if (display_helper->ConsumePresentBuffer(frame_callback)) {
+ return true;
+ }
+
+ frame_available_display_index =
+ (frame_available_display_index + 1) % display_helpers_.size();
+ }
+
+ frame_available_cond_var_.wait(lock);
+ }
+
+ return false;
}
void SocketBasedScreenConnector::ServerLoop(int frames_fd) {
@@ -65,8 +134,6 @@
return;
}
- int current_buffer = 0;
-
while (1) {
LOG(DEBUG) << "Screen Connector accepting connections...";
client_connection_ = SharedFD::Accept(*server);
@@ -76,12 +143,21 @@
}
ReportClientsConnected(have_clients_);
while (client_connection_->IsOpen()) {
+ uint32_t display_number = 0;
+ if (client_connection_->Read(&display_number, sizeof(display_number)) < 0) {
+ LOG(ERROR) << "Failed to read from hwcomposer: " << client_connection_->StrError();
+ break;
+ }
+
int32_t size = 0;
if (client_connection_->Read(&size, sizeof(size)) < 0) {
LOG(ERROR) << "Failed to read from hwcomposer: " << client_connection_->StrError();
break;
}
- auto buff = reinterpret_cast<uint8_t*>(GetBuffer(current_buffer));
+
+ auto& display_helper = display_helpers_[display_number];
+
+ std::uint8_t* buff = display_helper->AcquireNextBuffer();
while (size > 0) {
auto read = client_connection_->Read(buff, size);
if (read < 0) {
@@ -92,8 +168,10 @@
size -= read;
buff += read;
}
- BroadcastNewFrame(current_buffer);
- current_buffer = (current_buffer + 1) % kNumBuffersPerDisplay;
+
+
+ display_helper->PresentAcquiredBuffer();
+ frame_available_cond_var_.notify_all();
}
}
}
@@ -104,12 +182,4 @@
(void)client_connection_->Write(&buffer, sizeof(buffer));
}
-void SocketBasedScreenConnector::BroadcastNewFrame(int buffer_idx) {
- {
- std::lock_guard<std::mutex> lock(new_frame_mtx_);
- seq_num_++;
- newest_buffer_ = buffer_idx;
- }
- new_frame_cond_var_.notify_all();
-}
} // namespace cuttlefish
diff --git a/host/libs/screen_connector/socket_based_screen_connector.h b/host/libs/screen_connector/socket_based_screen_connector.h
index 5033f5a..fad33bb 100644
--- a/host/libs/screen_connector/socket_based_screen_connector.h
+++ b/host/libs/screen_connector/socket_based_screen_connector.h
@@ -33,28 +33,55 @@
public:
explicit SocketBasedScreenConnector(int frames_fd);
- bool OnFrameAfter(std::uint32_t frame_number,
- const FrameCallback& frame_callback) override;
+ bool OnNextFrame(const FrameCallback& frame_callback) override;
void ReportClientsConnected(bool have_clients) override;
private:
- static constexpr std::uint32_t kNumBuffersPerDisplay = 4;
-
- int WaitForNewFrameSince(std::uint32_t* seq_num);
- void* GetBuffer(int buffer_idx);
void ServerLoop(int frames_fd);
- void BroadcastNewFrame(int buffer_idx);
- std::size_t buffer_size_ = 0;
- std::vector<std::uint8_t> buffer_;
- std::uint32_t seq_num_{0};
- int newest_buffer_ = 0;
- std::condition_variable new_frame_cond_var_;
- std::mutex new_frame_mtx_;
+ class DisplayHelper {
+ public:
+ DisplayHelper(std::uint32_t display_number);
+
+ DisplayHelper(const DisplayHelper&) = delete;
+ DisplayHelper& operator=(const DisplayHelper&) = delete;
+
+ DisplayHelper(DisplayHelper&&) = delete;
+ DisplayHelper& operator=(DisplayHelper&&) = delete;
+
+ std::uint8_t* AcquireNextBuffer();
+
+ void PresentAcquiredBuffer();
+
+ bool ConsumePresentBuffer(const FrameCallback& frame_callback);
+
+ private:
+ std::uint8_t* GetBuffer(std::uint32_t index);
+
+ static constexpr std::uint32_t kNumBuffersPerDisplay = 4;
+
+ std::uint32_t display_number_ = 0;
+
+ std::size_t buffer_size_ = 0;
+ std::vector<std::uint8_t> buffers_;
+
+ std::mutex acquire_mutex_;
+ std::deque<std::uint32_t> acquirable_buffers_indexes_;
+ std::optional<std::uint32_t> acquired_buffer_index_;
+
+ std::mutex present_mutex_;
+ std::optional<std::uint32_t> present_buffer_index_;
+ };
+
std::thread screen_server_thread_;
cuttlefish::SharedFD client_connection_;
bool have_clients_ = false;
+ std::vector<std::unique_ptr<DisplayHelper>> display_helpers_;
+
+ std::mutex frame_available_mutex_;
+ std::condition_variable frame_available_cond_var_;
+ std::size_t frame_available_display_index = 0;
};
} // namespace cuttlefish
diff --git a/host/libs/screen_connector/wayland_screen_connector.cpp b/host/libs/screen_connector/wayland_screen_connector.cpp
index 7713214..6c8b9c6 100644
--- a/host/libs/screen_connector/wayland_screen_connector.cpp
+++ b/host/libs/screen_connector/wayland_screen_connector.cpp
@@ -19,8 +19,6 @@
#include <unistd.h>
#include <fcntl.h>
-#include <future>
-
#include <android-base/logging.h>
#include "host/libs/wayland/wayland_server.h"
@@ -35,13 +33,8 @@
server_.reset(new wayland::WaylandServer(wayland_fd));
}
-bool WaylandScreenConnector::OnFrameAfter(
- std::uint32_t frame_number, const FrameCallback& frame_callback) {
- std::future<void> frame_callback_completed_future =
- server_->OnFrameAfter(frame_number, frame_callback);
-
- frame_callback_completed_future.get();
-
+bool WaylandScreenConnector::OnNextFrame(const FrameCallback& frame_callback) {
+ server_->OnNextFrame(frame_callback);
return true;
}
diff --git a/host/libs/screen_connector/wayland_screen_connector.h b/host/libs/screen_connector/wayland_screen_connector.h
index a3ab518..fd742bd 100644
--- a/host/libs/screen_connector/wayland_screen_connector.h
+++ b/host/libs/screen_connector/wayland_screen_connector.h
@@ -28,8 +28,7 @@
public:
WaylandScreenConnector(int frames_fd);
- bool OnFrameAfter(std::uint32_t frame_number,
- const FrameCallback& frame_callback) override;
+ bool OnNextFrame(const FrameCallback& frame_callback) override;
private:
std::unique_ptr<wayland::WaylandServer> server_;
diff --git a/host/libs/wayland/Android.bp b/host/libs/wayland/Android.bp
index 397ee12..ec143ee 100644
--- a/host/libs/wayland/Android.bp
+++ b/host/libs/wayland/Android.bp
@@ -23,6 +23,7 @@
"wayland_server.cpp",
"wayland_subcompositor.cpp",
"wayland_surface.cpp",
+ "wayland_surfaces.cpp",
],
shared_libs: [
"libbase",
diff --git a/host/libs/wayland/wayland_compositor.cpp b/host/libs/wayland/wayland_compositor.cpp
index 96fdd6d..6179092 100644
--- a/host/libs/wayland/wayland_compositor.cpp
+++ b/host/libs/wayland/wayland_compositor.cpp
@@ -21,6 +21,7 @@
#include <wayland-server-core.h>
#include <wayland-server-protocol.h>
+#include "host/libs/wayland/wayland_surface.h"
#include "host/libs/wayland/wayland_utils.h"
namespace wayland {
@@ -190,7 +191,12 @@
<< " compositor=" << compositor
<< " id=" << id;
- Surface* surface = GetUserData<Surface>(compositor);
+ // Wayland seems to use a single global id space for all objects.
+ static std::atomic<std::uint32_t> sNextDisplayId{0};
+ uint32_t display_id = sNextDisplayId++;
+
+ Surfaces* surfaces = GetUserData<Surfaces>(compositor);
+ Surface* surface = surfaces->GetOrCreateSurface(display_id);
wl_resource* surface_resource = wl_resource_create(
client, &wl_surface_interface, wl_resource_get_version(compositor), id);
@@ -239,9 +245,9 @@
} // namespace
-void BindCompositorInterface(wl_display* display, Surface* surface) {
+void BindCompositorInterface(wl_display* display, Surfaces* surfaces) {
wl_global_create(display, &wl_compositor_interface, kCompositorVersion,
- surface, bind_compositor);
+ surfaces, bind_compositor);
}
} // namespace wayland
diff --git a/host/libs/wayland/wayland_compositor.h b/host/libs/wayland/wayland_compositor.h
index 5054c40..18f0d7e 100644
--- a/host/libs/wayland/wayland_compositor.h
+++ b/host/libs/wayland/wayland_compositor.h
@@ -21,11 +21,11 @@
#include <wayland-server-core.h>
-#include "host/libs/wayland/wayland_surface.h"
+#include "host/libs/wayland/wayland_surfaces.h"
namespace wayland {
// Binds the compositor interface to the given wayland server.
-void BindCompositorInterface(wl_display* display, Surface* surface);
+void BindCompositorInterface(wl_display* display, Surfaces* surfaces);
} // namespace wayland
\ No newline at end of file
diff --git a/host/libs/wayland/wayland_server.cpp b/host/libs/wayland/wayland_server.cpp
index 699fda2..4dc4b88 100644
--- a/host/libs/wayland/wayland_server.cpp
+++ b/host/libs/wayland/wayland_server.cpp
@@ -35,7 +35,7 @@
struct WaylandServerState {
struct wl_display* display_ = nullptr;
- Surface surface_;
+ Surfaces surfaces_;
};
} // namespace internal
@@ -78,7 +78,7 @@
wl_display_init_shm(server_state_->display_);
- BindCompositorInterface(server_state_->display_, &server_state_->surface_);
+ BindCompositorInterface(server_state_->display_, &server_state_->surfaces_);
BindDmabufInterface(server_state_->display_);
BindSubcompositorInterface(server_state_->display_);
BindSeatInterface(server_state_->display_);
@@ -94,20 +94,8 @@
wl_display_destroy(server_state_->display_);
}
-std::future<void> WaylandServer::OnFrameAfter(
- uint32_t frame_number,
- const FrameCallback& frame_callback) {
- // Wraps the given callback in a callback that can be waited on using
- // std::future.
- Surface::FrameCallbackPackaged packaged([&frame_callback](std::uint32_t frame_number,
- std::uint8_t* frame_pixels){
- frame_callback(frame_number, frame_pixels);
- });
-
- std::future<void> frame_callback_complete = packaged.get_future();
-
- server_state_->surface_.OnFrameAfter(frame_number, std::move(packaged));
- return frame_callback_complete;
+void WaylandServer::OnNextFrame(const Surfaces::FrameCallback& callback) {
+ server_state_->surfaces_.OnNextFrame(callback);
}
-} // namespace wayland
\ No newline at end of file
+} // namespace wayland
diff --git a/host/libs/wayland/wayland_server.h b/host/libs/wayland/wayland_server.h
index e73d74a..b51818a 100644
--- a/host/libs/wayland/wayland_server.h
+++ b/host/libs/wayland/wayland_server.h
@@ -24,15 +24,14 @@
#include <string>
#include <thread>
+#include "host/libs/wayland/wayland_surfaces.h"
+
namespace wayland {
namespace internal {
struct WaylandServerState;
} // namespace internal
-using FrameCallback = std::function<void(std::uint32_t /*frame_number*/,
- std::uint8_t* /*frame_pixels*/)>;
-
// A Wayland compositing server that provides an interface for receiving frame
// updates from a connected client.
class WaylandServer {
@@ -49,10 +48,8 @@
WaylandServer(WaylandServer&& rhs) = delete;
WaylandServer& operator=(WaylandServer&& rhs) = delete;
- // Registers a callback to run on the next frame available after the given
- // frame number.
- std::future<void> OnFrameAfter(std::uint32_t frame_number,
- const FrameCallback& frame_callback);
+ // Blocks until the given callback is run on the next frame available.
+ void OnNextFrame(const Surfaces::FrameCallback& callback);
private:
void ServerLoop(int wayland_socket_fd);
diff --git a/host/libs/wayland/wayland_surface.cpp b/host/libs/wayland/wayland_surface.cpp
index eb4b401..f4c80ca 100644
--- a/host/libs/wayland/wayland_surface.cpp
+++ b/host/libs/wayland/wayland_surface.cpp
@@ -19,8 +19,13 @@
#include <android-base/logging.h>
#include <wayland-server-protocol.h>
+#include "host/libs/wayland/wayland_surfaces.h"
+
namespace wayland {
+Surface::Surface(std::uint32_t display_number, Surfaces& surfaces)
+ : display_number_(display_number), surfaces_(surfaces) {}
+
void Surface::SetRegion(const Region& region) {
std::unique_lock<std::mutex> lock(state_mutex_);
state_.region = region;
@@ -36,29 +41,22 @@
state_.current_buffer = state_.pending_buffer;
state_.pending_buffer = nullptr;
- {
- std::unique_lock<std::mutex> lock(callback_mutex_);
- if (callback_ && callback_->frame_number < state_.current_frame_number) {
- struct wl_shm_buffer* shm_buffer =
- wl_shm_buffer_get(state_.current_buffer);
- CHECK(shm_buffer != nullptr);
+ struct wl_shm_buffer* shm_buffer = wl_shm_buffer_get(state_.current_buffer);
+ CHECK(shm_buffer != nullptr);
- wl_shm_buffer_begin_access(shm_buffer);
+ wl_shm_buffer_begin_access(shm_buffer);
- const int32_t buffer_w = wl_shm_buffer_get_width(shm_buffer);
- CHECK(buffer_w == state_.region.w);
- const int32_t buffer_h = wl_shm_buffer_get_height(shm_buffer);
- CHECK(buffer_h == state_.region.h);
+ const int32_t buffer_w = wl_shm_buffer_get_width(shm_buffer);
+ CHECK(buffer_w == state_.region.w);
+ const int32_t buffer_h = wl_shm_buffer_get_height(shm_buffer);
+ CHECK(buffer_h == state_.region.h);
- uint8_t* buffer_pixels =
- reinterpret_cast<uint8_t*>(wl_shm_buffer_get_data(shm_buffer));
+ uint8_t* buffer_pixels =
+ reinterpret_cast<uint8_t*>(wl_shm_buffer_get_data(shm_buffer));
- callback_->frame_callback(state_.current_frame_number, buffer_pixels);
- callback_.reset();
+ surfaces_.HandleSurfaceFrame(display_number_, buffer_pixels);
- wl_shm_buffer_end_access(shm_buffer);
- }
- }
+ wl_shm_buffer_end_access(shm_buffer);
wl_buffer_send_release(state_.current_buffer);
wl_client_flush(wl_resource_get_client(state_.current_buffer));
@@ -67,11 +65,4 @@
state_.current_frame_number++;
}
-void Surface::OnFrameAfter(uint32_t frame_number,
- FrameCallbackPackaged frame_callback) {
- std::unique_lock<std::mutex> lock(callback_mutex_);
- callback_.emplace(PendingFrameCallback{frame_number,
- std::move(frame_callback)});
-}
-
} // namespace wayland
\ No newline at end of file
diff --git a/host/libs/wayland/wayland_surface.h b/host/libs/wayland/wayland_surface.h
index e0d0a12..ceb85b1 100644
--- a/host/libs/wayland/wayland_surface.h
+++ b/host/libs/wayland/wayland_surface.h
@@ -17,19 +17,19 @@
#pragma once
-#include <optional>
+#include <mutex>
#include <stdint.h>
-#include <thread>
-#include <future>
#include <wayland-server-core.h>
namespace wayland {
+class Surfaces;
+
// Tracks the buffer associated with a Wayland surface.
class Surface {
public:
- Surface() = default;
+ Surface(std::uint32_t display_number, Surfaces& surfaces);
virtual ~Surface() = default;
Surface(const Surface& rhs) = delete;
@@ -53,16 +53,10 @@
// Commits the pending frame state.
void Commit();
- using FrameCallbackPackaged =
- std::packaged_task<void(std::uint32_t /*frame_number*/,
- std::uint8_t* /*frame_pixels*/)>;
-
- // Registers a callback that should be invoked on the first frame after
- // the given frame number.
- void OnFrameAfter(uint32_t frame_number,
- FrameCallbackPackaged frame_callback);
-
private:
+ std::uint32_t display_number_;
+ Surfaces& surfaces_;
+
struct State {
uint32_t current_frame_number = 0;
@@ -78,15 +72,6 @@
std::mutex state_mutex_;
State state_;
-
- struct PendingFrameCallback {
- uint32_t frame_number;
-
- FrameCallbackPackaged frame_callback;
- };
-
- std::mutex callback_mutex_;
- std::optional<PendingFrameCallback> callback_;
};
-} // namespace wayland
\ No newline at end of file
+} // namespace wayland
diff --git a/host/libs/wayland/wayland_surfaces.cpp b/host/libs/wayland/wayland_surfaces.cpp
new file mode 100644
index 0000000..ca83b51
--- /dev/null
+++ b/host/libs/wayland/wayland_surfaces.cpp
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+#include "host/libs/wayland/wayland_surfaces.h"
+
+#include <android-base/logging.h>
+#include <wayland-server-protocol.h>
+
+#include "host/libs/wayland/wayland_surface.h"
+
+namespace wayland {
+
+Surface* Surfaces::GetOrCreateSurface(std::uint32_t id) {
+ std::unique_lock<std::mutex> lock(surfaces_mutex_);
+
+ auto [it, inserted] = surfaces_.try_emplace(id, nullptr);
+
+ std::unique_ptr<Surface>& surface_ptr = it->second;
+ if (inserted) {
+ surface_ptr.reset(new Surface(id, *this));
+ }
+ return surface_ptr.get();
+}
+
+void Surfaces::OnNextFrame(const FrameCallback& frame_callback) {
+ // Wraps the given callback in a std::package_task that can be waited upon
+ // for completion.
+ Surfaces::FrameCallbackPackaged frame_callback_packaged(
+ [&frame_callback](std::uint32_t display_number,
+ std::uint8_t* frame_pixels){
+ frame_callback(display_number, frame_pixels);
+ });
+
+ {
+ std::unique_lock<std::mutex> lock(callback_mutex_);
+ callback_.emplace(&frame_callback_packaged);
+ }
+
+ // Blocks until the frame_callback_packaged was called.
+ frame_callback_packaged.get_future().get();
+}
+
+void Surfaces::HandleSurfaceFrame(std::uint32_t display_number,
+ std::uint8_t* frame_bytes) {
+ std::unique_lock<std::mutex> lock(callback_mutex_);
+ if (callback_) {
+ (*callback_.value())(display_number, frame_bytes);
+ callback_.reset();
+ }
+}
+
+} // namespace wayland
\ No newline at end of file
diff --git a/host/libs/wayland/wayland_surfaces.h b/host/libs/wayland/wayland_surfaces.h
new file mode 100644
index 0000000..5d825c8
--- /dev/null
+++ b/host/libs/wayland/wayland_surfaces.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2020 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 <future>
+#include <memory>
+#include <mutex>
+#include <optional>
+#include <stdint.h>
+#include <thread>
+#include <unordered_map>
+
+namespace wayland {
+
+class Surface;
+
+class Surfaces {
+ public:
+ Surfaces() = default;
+ virtual ~Surfaces() = default;
+
+ Surfaces(const Surfaces& rhs) = delete;
+ Surfaces& operator=(const Surfaces& rhs) = delete;
+
+ Surfaces(Surfaces&& rhs) = delete;
+ Surfaces& operator=(Surfaces&& rhs) = delete;
+
+ Surface* GetOrCreateSurface(std::uint32_t id);
+
+ using FrameCallback = std::function<void(std::uint32_t /*display_number*/,
+ std::uint8_t* /*frame_pixels*/)>;
+
+ // Blocking
+ void OnNextFrame(const FrameCallback& callback);
+
+ private:
+ friend class Surface;
+ void HandleSurfaceFrame(std::uint32_t display_number,
+ std::uint8_t* frame_bytes);
+
+ std::mutex surfaces_mutex_;
+ std::unordered_map<std::uint32_t, std::unique_ptr<Surface>> surfaces_;
+
+ using FrameCallbackPackaged =
+ std::packaged_task<void(std::uint32_t /*display_number*/,
+ std::uint8_t* /*frame_bytes*/)>;
+
+ std::mutex callback_mutex_;
+ std::optional<FrameCallbackPackaged*> callback_;
+};
+
+} // namespace wayland
diff --git a/rustfmt.toml b/rustfmt.toml
deleted file mode 100644
index 617d425..0000000
--- a/rustfmt.toml
+++ /dev/null
@@ -1,5 +0,0 @@
-# Android Format Style
-
-edition = "2018"
-use_small_heuristics = "Max"
-newline_style = "Unix"
diff --git a/rustfmt.toml b/rustfmt.toml
new file mode 120000
index 0000000..475ba8f
--- /dev/null
+++ b/rustfmt.toml
@@ -0,0 +1 @@
+../../../build/soong/scripts/rustfmt.toml
\ No newline at end of file
diff --git a/shared/auto/device.mk b/shared/auto/device.mk
index fe15d28..347a29c 100644
--- a/shared/auto/device.mk
+++ b/shared/auto/device.mk
@@ -31,7 +31,6 @@
packages/services/Car/car_product/init/init.bootstat.rc:$(TARGET_COPY_OUT_VENDOR)/etc/init/hw//init.bootstat.rc \
packages/services/Car/car_product/init/init.car.rc:$(TARGET_COPY_OUT_VENDOR)/etc/init/hw//init.car.rc
-
ifneq ($(LOCAL_SENSOR_FILE_OVERRIDES),true)
PRODUCT_COPY_FILES += \
frameworks/native/data/etc/android.hardware.sensor.accelerometer.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.sensor.accelerometer.xml \
diff --git a/shared/config/init.product.rc b/shared/config/init.product.rc
index 111a4c6..22371a3 100644
--- a/shared/config/init.product.rc
+++ b/shared/config/init.product.rc
@@ -6,9 +6,3 @@
class late_start
group system
user root
-
-# TODO: disable this service once cuttlefish implements system suspend
-service suspend_blocker /product/bin/suspend_blocker
- class early_hal # Star together with system_suspend HAL
- group system
- user root
diff --git a/shared/config/init.system_ext.rc b/shared/config/init.system_ext.rc
new file mode 100644
index 0000000..6c34305
--- /dev/null
+++ b/shared/config/init.system_ext.rc
@@ -0,0 +1,5 @@
+# TODO: disable this service once cuttlefish implements system suspend
+service suspend_blocker /system_ext/bin/suspend_blocker
+ class early_hal # Start together with system_suspend HAL
+ group system
+ user root
diff --git a/shared/device.mk b/shared/device.mk
index e9748fd..a3ab713 100644
--- a/shared/device.mk
+++ b/shared/device.mk
@@ -63,6 +63,7 @@
PRODUCT_PRODUCT_PROPERTIES += \
persist.adb.tcp.port=5555 \
ro.com.google.locationfeatures=1 \
+ persist.sys.fuse.passthrough.enable=true \
# Explanation of specific properties:
# debug.hwui.swap_with_damage avoids boot failure on M http://b/25152138
@@ -226,6 +227,7 @@
hardware/google/camera/devices/EmulatedCamera/hwl/configs/emu_camera_depth.json:$(TARGET_COPY_OUT_VENDOR)/etc/config/emu_camera_depth.json \
device/google/cuttlefish/shared/config/init.vendor.rc:$(TARGET_COPY_OUT_VENDOR)/etc/init/hw/init.cutf_cvm.rc \
device/google/cuttlefish/shared/config/init.product.rc:$(TARGET_COPY_OUT_PRODUCT)/etc/init/init.rc \
+ device/google/cuttlefish/shared/config/init.system_ext.rc:$(TARGET_COPY_OUT_SYSTEM_EXT)/etc/init/init.rc \
device/google/cuttlefish/shared/config/ueventd.rc:$(TARGET_COPY_OUT_VENDOR)/ueventd.rc \
device/google/cuttlefish/shared/config/media_codecs.xml:$(TARGET_COPY_OUT_VENDOR)/etc/media_codecs.xml \
device/google/cuttlefish/shared/config/media_codecs_google_video.xml:$(TARGET_COPY_OUT_VENDOR)/etc/media_codecs_google_video.xml \
@@ -281,7 +283,8 @@
PRODUCT_COPY_FILES += \
frameworks/native/data/etc/android.hardware.vulkan.level-0.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.vulkan.level.xml \
frameworks/native/data/etc/android.hardware.vulkan.version-1_0_3.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.vulkan.version.xml \
- frameworks/native/data/etc/android.software.vulkan.deqp.level-2020-03-01.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.software.vulkan.deqp.level.xml
+ frameworks/native/data/etc/android.software.vulkan.deqp.level-2021-03-01.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.software.vulkan.deqp.level.xml \
+ frameworks/native/data/etc/android.software.opengles.deqp.level-2021-03-01.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.software.opengles.deqp.level.xml
endif
# Packages for HAL implementations
@@ -449,6 +452,15 @@
$(LOCAL_KEYMASTER_PRODUCT_PACKAGE)
#
+# KeyMint HAL
+#
+ifeq ($(LOCAL_KEYMINT_PRODUCT_PACKAGE),)
+ LOCAL_KEYMINT_PRODUCT_PACKAGE := android.hardware.security.keymint-service
+endif
+PRODUCT_PACKAGES += \
+ $(LOCAL_KEYMINT_PRODUCT_PACKAGE)
+
+#
# Power HAL
#
PRODUCT_PACKAGES += \
diff --git a/shared/sepolicy/product/private/file_contexts b/shared/sepolicy/product/private/file_contexts
index f0255a0..0b92144 100644
--- a/shared/sepolicy/product/private/file_contexts
+++ b/shared/sepolicy/product/private/file_contexts
@@ -1,5 +1,4 @@
#############################
# Product files
#
-/product/bin/suspend_blocker u:object_r:suspend_blocker_exec:s0
/product/bin/tombstone_transmit u:object_r:tombstone_transmit_exec:s0
diff --git a/shared/sepolicy/system_ext/private/file_contexts b/shared/sepolicy/system_ext/private/file_contexts
index fa35cd3..5d68b20 100644
--- a/shared/sepolicy/system_ext/private/file_contexts
+++ b/shared/sepolicy/system_ext/private/file_contexts
@@ -1 +1,6 @@
/data/vendor/radio(/.*)? u:object_r:radio_vendor_data_file:s0
+
+#############################
+# System_ext files
+#
+/system_ext/bin/suspend_blocker u:object_r:suspend_blocker_exec:s0
diff --git a/tests/hal/hal_implementation_test.cpp b/tests/hal/hal_implementation_test.cpp
index ab0affd..840c739 100644
--- a/tests/hal/hal_implementation_test.cpp
+++ b/tests/hal/hal_implementation_test.cpp
@@ -107,11 +107,6 @@
// b/170144267
"android.system.keystore2.",
- // The keymint service implementation is in progress but we cannot register
- // the service by default til all essential features landed.
- // b/171429297
- "android.hardware.keymint.",
-
// These KeyMaster types are in an AIDL types-only HAL because they're used
// by the Identity Credential AIDL HAL. Remove this when fully porting
// KeyMaster to AIDL.