1 #pragma once
2 
3 /*
4  * Copyright (C) 2017 The Android Open Source Project
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 
19 
20 #include <condition_variable>
21 #include <memory>
22 #include <mutex>
23 #include <unordered_map>
24 
25 #include "common/libs/threads/thread_annotations.h"
26 #include "host/frontend/vnc_server/vnc_utils.h"
27 
28 namespace cuttlefish {
29 namespace vnc {
30 
31 class VncClientConnection;
32 class FrameBufferWatcher;
33 using StripePtrVec = std::vector<std::shared_ptr<const Stripe>>;
34 using SeqNumberVec = std::vector<StripeSeqNumber>;
35 
36 SeqNumberVec MakeSeqNumberVec();
37 
38 class BlackBoard {
39  private:
40   struct ClientFBUState {
41     bool ready_to_receive{};
42     ScreenOrientation orientation{};
43     std::condition_variable new_frame_cv;
44     SeqNumberVec stripe_seq_nums = MakeSeqNumberVec();
45     bool closed{};
46   };
47 
48  public:
49   class Registerer {
50    public:
Registerer(BlackBoard * bb,const VncClientConnection * conn)51     Registerer(BlackBoard* bb, const VncClientConnection* conn)
52         : bb_{bb}, conn_{conn} {
53       bb->Register(conn);
54     }
~Registerer()55     ~Registerer() { bb_->Unregister(conn_); }
56     Registerer(const Registerer&) = delete;
57     Registerer& operator=(const Registerer&) = delete;
58 
59    private:
60     BlackBoard* bb_{};
61     const VncClientConnection* conn_{};
62   };
63 
64   BlackBoard() = default;
65   BlackBoard(const BlackBoard&) = delete;
66   BlackBoard& operator=(const BlackBoard&) = delete;
67 
68   bool NoNewStripesFor(const SeqNumberVec& seq_nums) const REQUIRES(m_);
69   void NewStripeReady(int index, StripeSeqNumber seq_num);
70   void Register(const VncClientConnection* conn);
71   void Unregister(const VncClientConnection* conn);
72 
73   StripePtrVec WaitForSenderWork(const VncClientConnection* conn);
74 
75   void WaitForAtLeastOneClientConnection();
76 
77   void FrameBufferUpdateRequestReceived(const VncClientConnection* conn);
78   // Setting orientation implies needing the entire screen
79   void SetOrientation(const VncClientConnection* conn,
80                       ScreenOrientation orientation);
81   void SignalClientNeedsEntireScreen(const VncClientConnection* conn);
82 
83   void StopWaiting(const VncClientConnection* conn);
84 
85   void set_frame_buffer_watcher(FrameBufferWatcher* frame_buffer_watcher);
86 
87   // quality_level must be the value received from the client, in the range
88   // [kJpegMinQualityEncoding, kJpegMaxQualityEncoding], else it is ignored.
89   void set_jpeg_quality_level(int quality_level);
90 
jpeg_quality_level()91   int jpeg_quality_level() const {
92     std::lock_guard<std::mutex> guard(m_);
93     return jpeg_quality_level_;
94   }
95 
96  private:
97   ClientFBUState& GetStateForClient(const VncClientConnection* conn)
98       REQUIRES(m_);
99   static void ResetToZero(SeqNumberVec* seq_nums);
100 
101   mutable std::mutex m_;
102   SeqNumberVec most_recent_stripe_seq_nums_ GUARDED_BY(m_) = MakeSeqNumberVec();
103   std::unordered_map<const VncClientConnection*, ClientFBUState> clients_
104       GUARDED_BY(m_);
105   int jpeg_quality_level_ GUARDED_BY(m_) = 100;
106   std::condition_variable new_client_cv_;
107   // NOTE the FrameBufferWatcher pointer itself should be
108   // guarded, but not the pointee.
GUARDED_BY(m_)109   FrameBufferWatcher* frame_buffer_watcher_ GUARDED_BY(m_){};
110 };
111 
112 }  // namespace vnc
113 }  // namespace cuttlefish
114