Extract screen connectors from vnc server
The webrtc streamer also needs to use this stuff, by extracting from
here code duplication is avoided.
Bug: 141887532
Test: m; launch_cvd
Change-Id: Ie7494dceb9166105c2783c53626d90f78e47cde6
diff --git a/host/frontend/vnc_server/Android.bp b/host/frontend/vnc_server/Android.bp
index 344e47b..3df8d5f 100644
--- a/host/frontend/vnc_server/Android.bp
+++ b/host/frontend/vnc_server/Android.bp
@@ -20,7 +20,6 @@
"frame_buffer_watcher.cpp",
"jpeg_compressor.cpp",
"main.cpp",
- "screen_connector.cpp",
"simulated_hw_composer.cpp",
"virtual_inputs.cpp",
"vnc_client_connection.cpp",
@@ -38,6 +37,7 @@
],
static_libs: [
"libcuttlefish_host_config",
+ "libcuttlefish_screen_connector",
"libcuttlefish_wayland_server",
"libffi",
"libjsoncpp",
diff --git a/host/frontend/vnc_server/frame_buffer_watcher.cpp b/host/frontend/vnc_server/frame_buffer_watcher.cpp
index 592b88e..126fb6b 100644
--- a/host/frontend/vnc_server/frame_buffer_watcher.cpp
+++ b/host/frontend/vnc_server/frame_buffer_watcher.cpp
@@ -27,6 +27,7 @@
#include <glog/logging.h>
#include "host/frontend/vnc_server/vnc_utils.h"
+#include "host/libs/screen_connector/screen_connector.h"
using cvd::vnc::FrameBufferWatcher;
@@ -70,17 +71,17 @@
Message rotated(raw.size(), 0xAA);
for (std::uint16_t i = 0; i < w; ++i) {
for (std::uint16_t j = 0; j < h; ++j) {
- size_t to = (i * h + j) * BytesPerPixel();
- size_t from = (w - (i + 1)) * BytesPerPixel() + s * j;
+ size_t to = (i * h + j) * ScreenConnector::BytesPerPixel();
+ size_t from = (w - (i + 1)) * ScreenConnector::BytesPerPixel() + s * j;
CHECK(from < raw.size());
CHECK(to < rotated.size());
- std::memcpy(&rotated[to], &raw[from], BytesPerPixel());
+ std::memcpy(&rotated[to], &raw[from], ScreenConnector::BytesPerPixel());
}
}
std::swap(stripe.x, stripe.y);
std::swap(stripe.width, stripe.height);
// The new stride after rotating is the height, as it is not aligned again.
- stripe.stride = stripe.width * BytesPerPixel();
+ stripe.stride = stripe.width * ScreenConnector::BytesPerPixel();
stripe.raw_data = std::move(rotated);
stripe.orientation = ScreenOrientation::Landscape;
return stripe;
diff --git a/host/frontend/vnc_server/jpeg_compressor.cpp b/host/frontend/vnc_server/jpeg_compressor.cpp
index 2d57707..3bd3753 100644
--- a/host/frontend/vnc_server/jpeg_compressor.cpp
+++ b/host/frontend/vnc_server/jpeg_compressor.cpp
@@ -20,6 +20,7 @@
#include <glog/logging.h>
#include "host/frontend/vnc_server/jpeg_compressor.h"
#include "host/frontend/vnc_server/vnc_utils.h"
+#include "host/libs/screen_connector/screen_connector.h"
using cvd::vnc::JpegCompressor;
@@ -31,7 +32,7 @@
cinfo->image_width = width;
cinfo->image_height = height;
- cinfo->input_components = cvd::vnc::BytesPerPixel();
+ cinfo->input_components = cvd::ScreenConnector::BytesPerPixel();
cinfo->in_color_space = JCS_EXT_RGBX;
jpeg_set_defaults(cinfo);
@@ -57,7 +58,7 @@
auto row = static_cast<JSAMPROW>(const_cast<std::uint8_t*>(
&frame[(y * stride) +
(cinfo.next_scanline * stride) +
- (x * BytesPerPixel())]));
+ (x * cvd::ScreenConnector::BytesPerPixel())]));
jpeg_write_scanlines(&cinfo, &row, 1);
}
jpeg_finish_compress(&cinfo);
diff --git a/host/frontend/vnc_server/screen_connector.cpp b/host/frontend/vnc_server/screen_connector.cpp
deleted file mode 100644
index 333c03e..0000000
--- a/host/frontend/vnc_server/screen_connector.cpp
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * Copyright (C) 2019 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/frontend/vnc_server/screen_connector.h"
-
-#include <atomic>
-#include <condition_variable>
-#include <thread>
-
-#include <glog/logging.h>
-#include <gflags/gflags.h>
-
-#include "host/frontend/vnc_server/vnc_utils.h"
-#include "host/libs/wayland/wayland_server.h"
-
-DEFINE_int32(frame_server_fd, -1, "");
-
-namespace cvd {
-namespace vnc {
-
-namespace {
-
-// TODO(b/128852363): Substitute with one based on memory shared with the
-// wayland mock
-class SocketBasedScreenConnector : public ScreenConnector {
- public:
- SocketBasedScreenConnector() {
- screen_server_thread_ = std::thread([this]() { ServerLoop(); });
- }
-
- bool OnFrameAfter(std::uint32_t frame_number,
- const FrameCallback& frame_callback) override {
- int buffer_idx = WaitForNewFrameSince(&frame_number);
- void* buffer = GetBuffer(buffer_idx);
- frame_callback(frame_number, reinterpret_cast<uint8_t*>(buffer));
- return true;
- }
-
- private:
- static constexpr int NUM_BUFFERS_ = 4;
-
- int 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);
- }
- *seq_num = seq_num_;
- return newest_buffer_;
- }
-
- void* GetBuffer(int buffer_idx) {
- if (buffer_idx < 0) return nullptr;
- buffer_idx %= NUM_BUFFERS_;
- return &buffer_[buffer_idx * ScreenSizeInBytes()];
- }
-
- void ServerLoop() {
- if (FLAGS_frame_server_fd < 0) {
- LOG(FATAL) << "Invalid file descriptor: " << FLAGS_frame_server_fd;
- return;
- }
- auto server = SharedFD::Dup(FLAGS_frame_server_fd);
- close(FLAGS_frame_server_fd);
- if (!server->IsOpen()) {
- LOG(FATAL) << "Unable to dup screen server: " << server->StrError();
- return;
- }
-
- int current_buffer = 0;
-
- while (1) {
- LOG(INFO) << "Screen Connector accepting connections...";
- auto conn = SharedFD::Accept(*server);
- if (!conn->IsOpen()) {
- LOG(ERROR) << "Disconnected fd returned from accept";
- continue;
- }
- while (conn->IsOpen()) {
- int32_t size = 0;
- if (conn->Read(&size, sizeof(size)) < 0) {
- LOG(ERROR) << "Failed to read from hwcomposer: "
- << conn->StrError();
- break;
- }
- auto buff = reinterpret_cast<uint8_t*>(GetBuffer(current_buffer));
- while (size > 0) {
- auto read = conn->Read(buff, size);
- if (read < 0) {
- LOG(ERROR) << "Failed to read from hwcomposer: "
- << conn->StrError();
- conn->Close();
- break;
- }
- size -= read;
- buff += read;
- }
- BroadcastNewFrame(current_buffer);
- current_buffer = (current_buffer + 1) % NUM_BUFFERS_;
- }
- }
- }
-
- void 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();
- }
-
- std::vector<std::uint8_t> buffer_ =
- std::vector<std::uint8_t>(NUM_BUFFERS_ * ScreenSizeInBytes());
- std::uint32_t seq_num_{0};
- int newest_buffer_ = 0;
- std::condition_variable new_frame_cond_var_;
- std::mutex new_frame_mtx_;
- std::thread screen_server_thread_;
-};
-
-class WaylandScreenConnector : public ScreenConnector {
- public:
- WaylandScreenConnector() {
- int wayland_fd = fcntl(FLAGS_frame_server_fd, F_DUPFD_CLOEXEC, 3);
- CHECK(wayland_fd != -1) << "Unable to dup server, errno " << errno;
- close(FLAGS_frame_server_fd);
-
- server_.reset(new wayland::WaylandServer(wayland_fd));
- }
-
- bool OnFrameAfter(std::uint32_t frame_number,
- const FrameCallback& frame_callback) override {
- std::future<void> frame_callback_completed_future =
- server_->OnFrameAfter(frame_number, frame_callback);
-
- frame_callback_completed_future.get();
-
- return true;
- }
-
- private:
- std::unique_ptr<wayland::WaylandServer> server_;
-};
-
-} // namespace
-
-ScreenConnector* ScreenConnector::Get() {
- auto config = vsoc::CuttlefishConfig::Get();
- if (config->gpu_mode() == vsoc::kGpuModeDrmVirgl) {
- return new WaylandScreenConnector();
- } else {
- return new SocketBasedScreenConnector();
- }
-}
-
-} // namespace vnc
-} // namespace cvd
diff --git a/host/frontend/vnc_server/simulated_hw_composer.cpp b/host/frontend/vnc_server/simulated_hw_composer.cpp
index 8eb6d39..7b478f4 100644
--- a/host/frontend/vnc_server/simulated_hw_composer.cpp
+++ b/host/frontend/vnc_server/simulated_hw_composer.cpp
@@ -16,9 +16,13 @@
#include "host/frontend/vnc_server/simulated_hw_composer.h"
+#include <gflags/gflags.h>
+
#include "host/frontend/vnc_server/vnc_utils.h"
#include "host/libs/config/cuttlefish_config.h"
+DEFINE_int32(frame_server_fd, -1, "");
+
using cvd::vnc::SimulatedHWComposer;
SimulatedHWComposer::SimulatedHWComposer(BlackBoard* bb)
@@ -27,7 +31,8 @@
engine_{std::random_device{}()},
#endif
bb_{bb},
- stripes_(kMaxQueueElements, &SimulatedHWComposer::EraseHalfOfElements) {
+ stripes_(kMaxQueueElements, &SimulatedHWComposer::EraseHalfOfElements),
+ screen_connector_(ScreenConnector::Get(FLAGS_frame_server_fd)) {
stripe_maker_ = std::thread(&SimulatedHWComposer::MakeStripes, this);
}
@@ -69,13 +74,14 @@
void SimulatedHWComposer::MakeStripes() {
std::uint32_t previous_frame_number = 0;
- auto screen_height = ActualScreenHeight();
+ auto screen_height = ScreenConnector::ScreenHeight();
Message raw_screen;
std::uint64_t stripe_seq_num = 1;
const FrameCallback frame_callback = [&](uint32_t frame_number,
uint8_t* frame_pixels) {
- raw_screen.assign(frame_pixels, frame_pixels + ScreenSizeInBytes());
+ raw_screen.assign(frame_pixels,
+ frame_pixels + ScreenConnector::ScreenSizeInBytes());
for (int i = 0; i < kNumStripes; ++i) {
++stripe_seq_num;
@@ -86,10 +92,11 @@
std::uint16_t height =
screen_height / kNumStripes +
(i + 1 == kNumStripes ? screen_height % kNumStripes : 0);
- const auto* raw_start =
- &raw_screen[y * ActualScreenWidth() * BytesPerPixel()];
+ const auto* raw_start = &raw_screen[y * ScreenConnector::ScreenWidth() *
+ ScreenConnector::BytesPerPixel()];
const auto* raw_end =
- raw_start + (height * ActualScreenWidth() * BytesPerPixel());
+ raw_start + (height * ScreenConnector::ScreenWidth() *
+ ScreenConnector::BytesPerPixel());
// 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
@@ -99,8 +106,8 @@
s.frame_id = frame_number;
s.x = 0;
s.y = y;
- s.width = ActualScreenWidth();
- s.stride = ActualScreenStride();
+ s.width = ScreenConnector::ScreenWidth();
+ s.stride = ScreenConnector::ScreenStride();
s.height = height;
s.raw_data.assign(raw_start, raw_end);
s.seq_number = StripeSeqNumber{stripe_seq_num};
diff --git a/host/frontend/vnc_server/simulated_hw_composer.h b/host/frontend/vnc_server/simulated_hw_composer.h
index 802cc7f..4a51f78 100644
--- a/host/frontend/vnc_server/simulated_hw_composer.h
+++ b/host/frontend/vnc_server/simulated_hw_composer.h
@@ -26,7 +26,7 @@
#include "common/libs/thread_safe_queue/thread_safe_queue.h"
#include "common/libs/threads/thread_annotations.h"
#include "host/frontend/vnc_server/blackboard.h"
-#include "host/frontend/vnc_server/screen_connector.h"
+#include "host/libs/screen_connector/screen_connector.h"
namespace cvd {
namespace vnc {
@@ -60,7 +60,7 @@
BlackBoard* bb_{};
ThreadSafeQueue<Stripe> stripes_;
std::thread stripe_maker_;
- std::shared_ptr<ScreenConnector> screen_connector_{ScreenConnector::Get()};
+ std::shared_ptr<ScreenConnector> screen_connector_;
};
} // namespace vnc
} // namespace cvd
diff --git a/host/frontend/vnc_server/vnc_client_connection.cpp b/host/frontend/vnc_server/vnc_client_connection.cpp
index b81bb88..8394e65 100644
--- a/host/frontend/vnc_server/vnc_client_connection.cpp
+++ b/host/frontend/vnc_server/vnc_client_connection.cpp
@@ -37,6 +37,7 @@
#include "host/frontend/vnc_server/mocks.h"
#include "host/frontend/vnc_server/vnc_utils.h"
#include "host/libs/config/cuttlefish_config.h"
+#include "host/libs/screen_connector/screen_connector.h"
using cvd::Message;
using cvd::vnc::Stripe;
@@ -475,7 +476,7 @@
std::lock_guard<std::mutex> guard(m_);
if (current_orientation_ == ScreenOrientation::Landscape) {
std::tie(x_pos, y_pos) =
- std::make_pair(ActualScreenWidth() - y_pos, x_pos);
+ std::make_pair(ScreenConnector::ScreenWidth() - y_pos, x_pos);
}
}
virtual_inputs_->HandlePointerEvent(button_mask, x_pos, y_pos);
@@ -505,14 +506,14 @@
int VncClientConnection::ScreenWidth() const {
return current_orientation_ == ScreenOrientation::Portrait
- ? ActualScreenWidth()
- : ActualScreenHeight();
+ ? ScreenConnector::ScreenWidth()
+ : ScreenConnector::ScreenHeight();
}
int VncClientConnection::ScreenHeight() const {
return current_orientation_ == ScreenOrientation::Portrait
- ? ActualScreenHeight()
- : ActualScreenWidth();
+ ? ScreenConnector::ScreenHeight()
+ : ScreenConnector::ScreenWidth();
}
void VncClientConnection::SetScreenOrientation(ScreenOrientation orientation) {
diff --git a/host/frontend/vnc_server/vnc_utils.h b/host/frontend/vnc_server/vnc_utils.h
index db88131..7a80518 100644
--- a/host/frontend/vnc_server/vnc_utils.h
+++ b/host/frontend/vnc_server/vnc_utils.h
@@ -63,28 +63,5 @@
ScreenOrientation orientation{};
};
-inline constexpr int BytesPerPixel() {
- return sizeof(uint32_t);
-}
-
-// The width of the screen regardless of orientation. Does not change.
-inline int ActualScreenWidth() {
- return vsoc::CuttlefishConfig::Get()->x_res();
-}
-
-// The length of the screen stride regardless of orientation. Does not change.
-inline int ActualScreenStride() {
- return AlignToPowerOf2(ActualScreenWidth() * BytesPerPixel(), 4);
-}
-
-// The height of the screen regardless of orientation. Does not change.
-inline int ActualScreenHeight() {
- return vsoc::CuttlefishConfig::Get()->y_res();
-}
-
-inline int ScreenSizeInBytes() {
- return ActualScreenWidth() * ActualScreenHeight() * BytesPerPixel();
-}
-
} // namespace vnc
} // namespace cvd
diff --git a/host/libs/screen_connector/Android.bp b/host/libs/screen_connector/Android.bp
new file mode 100644
index 0000000..69fa002
--- /dev/null
+++ b/host/libs/screen_connector/Android.bp
@@ -0,0 +1,38 @@
+//
+// 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.
+
+cc_library_host_static {
+ name: "libcuttlefish_screen_connector",
+ srcs: [
+ "screen_connector.cpp",
+ "socket_based_screen_connector.cpp",
+ "wayland_screen_connector.cpp",
+ ],
+ header_libs: [
+ "cuttlefish_glog",
+ ],
+ shared_libs: [
+ "libcuttlefish_fs",
+ "libbase",
+ "liblog",
+ ],
+ static_libs: [
+ "libcuttlefish_host_config",
+ "libcuttlefish_utils",
+ "libcuttlefish_wayland_server",
+ "libjsoncpp",
+ ],
+ defaults: ["cuttlefish_host_only"],
+}
diff --git a/host/libs/screen_connector/screen_connector.cpp b/host/libs/screen_connector/screen_connector.cpp
new file mode 100644
index 0000000..906435a
--- /dev/null
+++ b/host/libs/screen_connector/screen_connector.cpp
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2019 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/screen_connector/screen_connector.h"
+
+#include <glog/logging.h>
+
+#include "host/libs/config/cuttlefish_config.h"
+#include "host/libs/screen_connector/socket_based_screen_connector.h"
+#include "host/libs/screen_connector/wayland_screen_connector.h"
+
+namespace cvd {
+
+ScreenConnector* ScreenConnector::Get(int frames_fd) {
+ auto config = vsoc::CuttlefishConfig::Get();
+ if (config->gpu_mode() == vsoc::kGpuModeDrmVirgl) {
+ return new WaylandScreenConnector(frames_fd);
+ } else if (config->gpu_mode() == vsoc::kGpuModeGuestSwiftshader) {
+ return new SocketBasedScreenConnector(frames_fd);
+ } else {
+ LOG(ERROR) << "Invalid gpu mode: " << config->gpu_mode();
+ return nullptr;
+ }
+}
+
+} // namespace cvd
diff --git a/host/frontend/vnc_server/screen_connector.h b/host/libs/screen_connector/screen_connector.h
similarity index 66%
rename from host/frontend/vnc_server/screen_connector.h
rename to host/libs/screen_connector/screen_connector.h
index ef62a4a..c369ab0 100644
--- a/host/frontend/vnc_server/screen_connector.h
+++ b/host/libs/screen_connector/screen_connector.h
@@ -19,15 +19,17 @@
#include <cstdint>
#include <functional>
+#include "common/libs/utils/size_utils.h"
+#include "host/libs/config/cuttlefish_config.h"
+
namespace cvd {
-namespace vnc {
using FrameCallback = std::function<void(std::uint32_t /*frame_number*/,
std::uint8_t* /*frame_pixels*/)>;
class ScreenConnector {
public:
- static ScreenConnector* Get();
+ static ScreenConnector* Get(int frames_fd);
virtual ~ScreenConnector() = default;
@@ -36,9 +38,28 @@
virtual bool OnFrameAfter(std::uint32_t frame_number,
const FrameCallback& frame_callback) = 0;
+ static inline constexpr int BytesPerPixel() {
+ return sizeof(int32_t);
+ }
+
+ static inline int ScreenHeight() {
+ return vsoc::CuttlefishConfig::Get()->y_res();
+ }
+
+ static inline int ScreenWidth() {
+ return vsoc::CuttlefishConfig::Get()->x_res();
+ }
+
+ static inline int ScreenStride() {
+ return AlignToPowerOf2(ScreenWidth() * BytesPerPixel(), 4);
+ }
+
+ static inline int ScreenSizeInBytes() {
+ return ScreenStride() * ScreenHeight() * BytesPerPixel();
+ }
+
protected:
ScreenConnector() = default;
};
-} // namespace vnc
} // namespace cvd
\ No newline at end of file
diff --git a/host/libs/screen_connector/socket_based_screen_connector.cpp b/host/libs/screen_connector/socket_based_screen_connector.cpp
new file mode 100644
index 0000000..7e6333a
--- /dev/null
+++ b/host/libs/screen_connector/socket_based_screen_connector.cpp
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2019 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/screen_connector/socket_based_screen_connector.h"
+
+#include <glog/logging.h>
+
+#include "common/libs/fs/shared_fd.h"
+
+namespace cvd {
+
+SocketBasedScreenConnector::SocketBasedScreenConnector(int frames_fd) {
+screen_server_thread_ =
+ std::thread([this, frames_fd]() { ServerLoop(frames_fd); });
+}
+
+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;
+}
+
+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);
+ }
+ *seq_num = seq_num_;
+ return newest_buffer_;
+}
+
+void* SocketBasedScreenConnector::GetBuffer(int buffer_idx) {
+ if (buffer_idx < 0) return nullptr;
+ buffer_idx %= NUM_BUFFERS_;
+ return &buffer_[buffer_idx * ScreenSizeInBytes()];
+}
+
+void SocketBasedScreenConnector::ServerLoop(int frames_fd) {
+ if (frames_fd < 0) {
+ LOG(FATAL) << "Invalid file descriptor: " << frames_fd;
+ return;
+ }
+ auto server = SharedFD::Dup(frames_fd);
+ close(frames_fd);
+ if (!server->IsOpen()) {
+ LOG(FATAL) << "Unable to dup screen server: " << server->StrError();
+ return;
+ }
+
+ int current_buffer = 0;
+
+ while (1) {
+ LOG(INFO) << "Screen Connector accepting connections...";
+ auto conn = SharedFD::Accept(*server);
+ if (!conn->IsOpen()) {
+ LOG(ERROR) << "Disconnected fd returned from accept";
+ continue;
+ }
+ while (conn->IsOpen()) {
+ int32_t size = 0;
+ if (conn->Read(&size, sizeof(size)) < 0) {
+ LOG(ERROR) << "Failed to read from hwcomposer: " << conn->StrError();
+ break;
+ }
+ auto buff = reinterpret_cast<uint8_t*>(GetBuffer(current_buffer));
+ while (size > 0) {
+ auto read = conn->Read(buff, size);
+ if (read < 0) {
+ LOG(ERROR) << "Failed to read from hwcomposer: " << conn->StrError();
+ conn->Close();
+ break;
+ }
+ size -= read;
+ buff += read;
+ }
+ BroadcastNewFrame(current_buffer);
+ current_buffer = (current_buffer + 1) % NUM_BUFFERS_;
+ }
+ }
+}
+
+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 cvd
diff --git a/host/libs/screen_connector/socket_based_screen_connector.h b/host/libs/screen_connector/socket_based_screen_connector.h
new file mode 100644
index 0000000..0ed8414
--- /dev/null
+++ b/host/libs/screen_connector/socket_based_screen_connector.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2019 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 "host/libs/screen_connector/screen_connector.h"
+
+#include <atomic>
+#include <cinttypes>
+#include <condition_variable>
+#include <mutex>
+#include <thread>
+#include <vector>
+
+namespace cvd {
+
+class SocketBasedScreenConnector : public ScreenConnector {
+ public:
+ explicit SocketBasedScreenConnector(int frames_fd);
+
+ bool OnFrameAfter(std::uint32_t frame_number,
+ const FrameCallback& frame_callback) override;
+
+ private:
+ static constexpr int NUM_BUFFERS_ = 4;
+
+ int WaitForNewFrameSince(std::uint32_t* seq_num);
+ void* GetBuffer(int buffer_idx);
+ void ServerLoop(int frames_fd);
+ void BroadcastNewFrame(int buffer_idx);
+
+ std::vector<std::uint8_t> buffer_ =
+ std::vector<std::uint8_t>(NUM_BUFFERS_ * ScreenSizeInBytes());
+ std::uint32_t seq_num_{0};
+ int newest_buffer_ = 0;
+ std::condition_variable new_frame_cond_var_;
+ std::mutex new_frame_mtx_;
+ std::thread screen_server_thread_;
+};
+
+} // namespace cvd
\ No newline at end of file
diff --git a/host/libs/screen_connector/wayland_screen_connector.cpp b/host/libs/screen_connector/wayland_screen_connector.cpp
new file mode 100644
index 0000000..8059290
--- /dev/null
+++ b/host/libs/screen_connector/wayland_screen_connector.cpp
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2019 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/screen_connector/wayland_screen_connector.h"
+
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <future>
+
+#include <glog/logging.h>
+
+#include "host/libs/wayland/wayland_server.h"
+
+namespace cvd {
+
+WaylandScreenConnector::WaylandScreenConnector(int frames_fd) {
+ int wayland_fd = fcntl(frames_fd, F_DUPFD_CLOEXEC, 3);
+ CHECK(wayland_fd != -1) << "Unable to dup server, errno " << errno;
+ close(frames_fd);
+
+ 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();
+
+ return true;
+}
+
+} // namespace cvd
\ No newline at end of file
diff --git a/host/libs/screen_connector/wayland_screen_connector.h b/host/libs/screen_connector/wayland_screen_connector.h
new file mode 100644
index 0000000..537bb31
--- /dev/null
+++ b/host/libs/screen_connector/wayland_screen_connector.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2019 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 "host/libs/screen_connector/screen_connector.h"
+
+#include <memory>
+
+#include "host/libs/wayland/wayland_server.h"
+
+namespace cvd {
+
+class WaylandScreenConnector : public ScreenConnector {
+ public:
+ WaylandScreenConnector(int frames_fd);
+
+ bool OnFrameAfter(std::uint32_t frame_number,
+ const FrameCallback& frame_callback) override;
+
+ private:
+ std::unique_ptr<wayland::WaylandServer> server_;
+};
+
+}
\ No newline at end of file
diff --git a/host/libs/wayland/Android.bp b/host/libs/wayland/Android.bp
index 0fd6526..6123d67 100644
--- a/host/libs/wayland/Android.bp
+++ b/host/libs/wayland/Android.bp
@@ -32,7 +32,6 @@
static_libs: [
"libdrm",
"libffi",
- "libgflags",
"libwayland_server",
"libwayland_extension_server_protocols",
],