1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include <cstdint>
20 #include <functional>
21 #include <memory>
22 #include <mutex>
23 #include <optional>
24 #include <string>
25 #include <string_view>
26 #include <thread>
27 #include <type_traits>
28 #include <unordered_set>
29 
30 #include <android-base/logging.h>
31 #include <fruit/fruit.h>
32 
33 #include "common/libs/confui/confui.h"
34 #include "common/libs/fs/shared_fd.h"
35 #include "common/libs/utils/contains.h"
36 #include "common/libs/utils/size_utils.h"
37 #include "host/libs/config/cuttlefish_config.h"
38 #include "host/libs/confui/host_mode_ctrl.h"
39 #include "host/libs/confui/host_utils.h"
40 #include "host/libs/screen_connector/screen_connector_common.h"
41 #include "host/libs/screen_connector/screen_connector_multiplexer.h"
42 #include "host/libs/screen_connector/screen_connector_queue.h"
43 #include "host/libs/screen_connector/wayland_screen_connector.h"
44 
45 namespace cuttlefish {
46 
47 template <typename ProcessedFrameType>
48 class ScreenConnector : public ScreenConnectorInfo,
49                         public ScreenConnectorFrameRenderer {
50  public:
51   static_assert(cuttlefish::is_movable<ProcessedFrameType>::value,
52                 "ProcessedFrameType should be std::move-able.");
53   static_assert(
54       std::is_base_of<ScreenConnectorFrameInfo, ProcessedFrameType>::value,
55       "ProcessedFrameType should inherit ScreenConnectorFrameInfo");
56 
57   using FrameMultiplexer = ScreenConnectorInputMultiplexer<ProcessedFrameType>;
58 
INJECT(ScreenConnector (WaylandScreenConnector & sc_android_src,HostModeCtrl & host_mode_ctrl))59   INJECT(ScreenConnector(WaylandScreenConnector& sc_android_src,
60                          HostModeCtrl& host_mode_ctrl))
61       : sc_android_src_(sc_android_src),
62         host_mode_ctrl_{host_mode_ctrl},
63         on_next_frame_cnt_{0},
64         render_confui_cnt_{0},
65         sc_frame_multiplexer_{host_mode_ctrl_} {
66     auto config = cuttlefish::CuttlefishConfig::Get();
67     if (!config) {
68       LOG(FATAL) << "CuttlefishConfig is not available.";
69     }
70     auto instance = config->ForDefaultInstance();
71     std::unordered_set<std::string_view> valid_gpu_modes{
72         cuttlefish::kGpuModeCustom,
73         cuttlefish::kGpuModeDrmVirgl,
74         cuttlefish::kGpuModeGfxstream,
75         cuttlefish::kGpuModeGfxstreamGuestAngle,
76         cuttlefish::kGpuModeGfxstreamGuestAngleHostSwiftShader,
77         cuttlefish::kGpuModeGuestSwiftshader};
78     if (!Contains(valid_gpu_modes, instance.gpu_mode())) {
79       LOG(FATAL) << "Invalid gpu mode: " << instance.gpu_mode();
80     }
81   }
82 
83   /**
84    * This is the type of the callback function WebRTC is supposed to provide
85    * ScreenConnector with.
86    *
87    * The callback function is how a raw bytes frame should be processed for
88    * WebRTC
89    *
90    */
91   using GenerateProcessedFrameCallback = std::function<void(
92       std::uint32_t /*display_number*/, std::uint32_t /*frame_width*/,
93       std::uint32_t /*frame_height*/, std::uint32_t /*frame_fourcc_format*/,
94       std::uint32_t /*frame_stride_bytes*/, std::uint8_t* /*frame_bytes*/,
95       /* ScImpl enqueues this type into the Q */
96       ProcessedFrameType& msg)>;
97 
98   virtual ~ScreenConnector() = default;
99 
100   /**
101    * set the callback function to be eventually used by Wayland-Based
102    * Connector
103    *
104    */
SetCallback(GenerateProcessedFrameCallback && frame_callback)105   void SetCallback(GenerateProcessedFrameCallback&& frame_callback) {
106     std::lock_guard<std::mutex> lock(streamer_callback_mutex_);
107     callback_from_streamer_ = std::move(frame_callback);
108     streamer_callback_set_cv_.notify_all();
109 
110     sc_android_src_.SetFrameCallback(
111         [this](std::uint32_t display_number, std::uint32_t frame_w,
112                std::uint32_t frame_h, std::uint32_t frame_fourcc_format,
113                std::uint32_t frame_stride_bytes, std::uint8_t* frame_bytes) {
114           const bool is_confui_mode = host_mode_ctrl_.IsConfirmatioUiMode();
115           if (is_confui_mode) {
116             return;
117           }
118 
119           ProcessedFrameType processed_frame;
120 
121           {
122             std::lock_guard<std::mutex> lock(streamer_callback_mutex_);
123             callback_from_streamer_(display_number, frame_w, frame_h,
124                                     frame_fourcc_format, frame_stride_bytes,
125                                     frame_bytes, processed_frame);
126           }
127 
128           sc_frame_multiplexer_.PushToAndroidQueue(std::move(processed_frame));
129         });
130   }
131 
IsCallbackSet()132   bool IsCallbackSet() const override {
133     if (callback_from_streamer_) {
134       return true;
135     }
136     return false;
137   }
138 
SetDisplayEventCallback(DisplayEventCallback event_callback)139   void SetDisplayEventCallback(DisplayEventCallback event_callback) {
140     sc_android_src_.SetDisplayEventCallback(std::move(event_callback));
141   }
142 
143   /* returns the processed frame that also includes meta-info such as
144    * success/fail and display number from the guest
145    *
146    * NOTE THAT THIS IS THE ONLY CONSUMER OF THE TWO QUEUES
147    */
OnNextFrame()148   ProcessedFrameType OnNextFrame() { return sc_frame_multiplexer_.Pop(); }
149 
150   /**
151    * ConfUi calls this when it has frames to render
152    *
153    * This won't be called if not by Confirmation UI. This won't affect rendering
154    * Android guest frames if Confirmation UI HAL is not active.
155    *
156    */
RenderConfirmationUi(std::uint32_t display_number,std::uint32_t frame_width,std::uint32_t frame_height,std::uint32_t frame_fourcc_format,std::uint32_t frame_stride_bytes,std::uint8_t * frame_bytes)157   bool RenderConfirmationUi(std::uint32_t display_number,
158                             std::uint32_t frame_width,
159                             std::uint32_t frame_height,
160                             std::uint32_t frame_fourcc_format,
161                             std::uint32_t frame_stride_bytes,
162                             std::uint8_t* frame_bytes) override {
163     render_confui_cnt_++;
164     // wait callback is not set, the streamer is not ready
165     // return with LOG(ERROR)
166     if (!IsCallbackSet()) {
167       ConfUiLog(ERROR) << "callback function to process frames is not yet set";
168       return false;
169     }
170     ProcessedFrameType processed_frame;
171     auto this_thread_name = cuttlefish::confui::thread::GetName();
172     ConfUiLog(DEBUG) << this_thread_name
173                      << "is sending a #" + std::to_string(render_confui_cnt_)
174                      << "Conf UI frame";
175     callback_from_streamer_(display_number, frame_width, frame_height,
176                             frame_fourcc_format, frame_stride_bytes,
177                             frame_bytes, processed_frame);
178     // now add processed_frame to the queue
179     sc_frame_multiplexer_.PushToConfUiQueue(std::move(processed_frame));
180     return true;
181   }
182 
183  protected:
184   ScreenConnector() = delete;
185 
186  private:
187   WaylandScreenConnector& sc_android_src_;
188   HostModeCtrl& host_mode_ctrl_;
189   unsigned long long int on_next_frame_cnt_;
190   unsigned long long int render_confui_cnt_;
191   /**
192    * internally has conf ui & android queues.
193    *
194    * multiplexting the two input queues, so the consumer gets one input
195    * at a time from the right queue
196    */
197   FrameMultiplexer sc_frame_multiplexer_;
198   GenerateProcessedFrameCallback callback_from_streamer_;
199   std::mutex
200       streamer_callback_mutex_;  // mutex to set & read callback_from_streamer_
201   std::condition_variable streamer_callback_set_cv_;
202 };
203 
204 }  // namespace cuttlefish
205