• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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 <string>
23 #include <tuple>
24 #include <vector>
25 
26 #include <freetype/ftglyph.h>  // $(croot)/external/freetype
27 #include <teeui/utils.h>       // $(croot)/system/teeui/libteeui/.../include
28 
29 #include "common/libs/confui/confui.h"
30 #include "host/libs/confui/layouts/layout.h"
31 #include "host/libs/confui/server_common.h"
32 #include "host/libs/screen_connector/screen_connector_common.h"
33 
34 namespace cuttlefish {
35 namespace confui {
36 class TeeUiFrameWrapper {
37  public:
TeeUiFrameWrapper(const int w,const int h,const teeui::Color color)38   TeeUiFrameWrapper(const int w, const int h, const teeui::Color color)
39       : w_(w), h_(h), teeui_frame_(ScreenSizeInBytes(w, h), color) {}
40   TeeUiFrameWrapper() = delete;
data()41   auto data() { return teeui_frame_.data(); }
Width()42   int Width() const { return w_; }
Height()43   int Height() const { return h_; }
IsEmpty()44   bool IsEmpty() const { return teeui_frame_.empty(); }
Size()45   auto Size() const { return teeui_frame_.size(); }
46   auto& operator[](const int idx) { return teeui_frame_[idx]; }
ScreenStrideBytes()47   std::uint32_t ScreenStrideBytes() const {
48     return ScreenConnectorInfo::ComputeScreenStrideBytes(w_);
49   }
50 
51  private:
ScreenSizeInBytes(const int w,const int h)52   static std::uint32_t ScreenSizeInBytes(const int w, const int h) {
53     return ScreenConnectorInfo::ComputeScreenSizeInBytes(w, h);
54   }
55 
56   int w_;
57   int h_;
58   TeeUiFrame teeui_frame_;
59 };
60 
61 /**
62  * create a raw frame for confirmation UI dialog
63  *
64  * Many rendering code borrowed from the following source
65  *  https://android.googlesource.com/trusty/app/confirmationui/+/0429cc7/src
66  */
67 class ConfUiRenderer {
68  public:
69   using LabelConfMsg = teeui::LabelBody;
70 
71   static std::unique_ptr<ConfUiRenderer> GenerateRenderer(
72       const std::uint32_t display, const std::string& confirmation_msg,
73       const std::string& locale, const bool inverted, const bool magnified);
74 
75   /**
76    * this does not repaint from the scratch all the time
77    *
78    * It does repaint its frame buffer only when w/h of
79    * current display has changed
80    */
81   std::shared_ptr<TeeUiFrameWrapper> RenderRawFrame();
82 
IsFrameReady()83   bool IsFrameReady() const { return raw_frame_ && !raw_frame_->IsEmpty(); }
84 
IsInConfirm(const std::uint32_t x,const std::uint32_t y)85   bool IsInConfirm(const std::uint32_t x, const std::uint32_t y) {
86     return IsInside<teeui::LabelOK>(x, y);
87   }
IsInCancel(const std::uint32_t x,const std::uint32_t y)88   bool IsInCancel(const std::uint32_t x, const std::uint32_t y) {
89     return IsInside<teeui::LabelCancel>(x, y);
90   }
91 
92  private:
IsSetUpSuccessful()93   bool IsSetUpSuccessful() const { return is_setup_well_; }
94   ConfUiRenderer(const std::uint32_t display,
95                  const std::string& confirmation_msg, const std::string& locale,
96                  const bool inverted, const bool magnified);
97 
98   struct Boundary {            // inclusive but.. LayoutElement's size is float
99     std::uint32_t x, y, w, h;  // (x, y) is the top left
100   };
101 
102   template <typename LayoutElement>
GetBoundary(LayoutElement && e)103   Boundary GetBoundary(LayoutElement&& e) const {
104     auto box = e.bounds_;
105     Boundary b;
106     // (x,y) is left top. so floor() makes sense
107     // w, h are witdh and height in float. perhaps ceiling makes more
108     // sense
109     b.x = static_cast<std::uint32_t>(box.x().floor().count());
110     b.y = static_cast<std::uint32_t>(box.y().floor().count());
111     b.w = static_cast<std::uint32_t>(box.w().ceil().count());
112     b.h = static_cast<std::uint32_t>(box.h().ceil().count());
113     return b;
114   }
115 
116   template <typename Element>
IsInside(const std::uint32_t x,const std::uint32_t y)117   bool IsInside(const std::uint32_t x, const std::uint32_t y) const {
118     auto box = GetBoundary(std::get<Element>(layout_));
119     if (x >= box.x && x <= box.x + box.w && y >= box.y && y <= box.y + box.h) {
120       return true;
121     }
122     return false;
123   }
124   // essentially, to repaint from the scratch, so returns new frame
125   // when successful. Or, nullopt
126   std::unique_ptr<TeeUiFrameWrapper> RepaintRawFrame(const int w, const int h);
127 
128   bool InitLayout(const std::string& lang_id);
129   teeui::Error UpdateTranslations();
130   teeui::Error UpdateLocale();
131   void SetDeviceContext(const unsigned long long w, const unsigned long long h,
132                         bool is_inverted, bool is_magnified);
133 
134   // a callback function to be effectively sent to TeeUI library
135   teeui::Error UpdatePixels(TeeUiFrameWrapper& buffer, std::uint32_t x,
136                             std::uint32_t y, teeui::Color color);
137 
138   // second param is for type deduction
139   template <typename... Elements>
drawElements(std::tuple<Elements...> & layout,const teeui::PixelDrawer & drawPixel)140   static teeui::Error drawElements(std::tuple<Elements...>& layout,
141                                    const teeui::PixelDrawer& drawPixel) {
142     // Error::operator|| is overloaded, so we don't get short circuit
143     // evaluation. But we get the first error that occurs. We will still try and
144     // draw the remaining elements in the order they appear in the layout tuple.
145     return (std::get<Elements>(layout).draw(drawPixel) || ...);
146   }
147   void UpdateColorScheme(const bool is_inverted);
148   template <typename Label>
SetText(const std::string & text)149   auto SetText(const std::string& text) {
150     return std::get<Label>(layout_).setText(
151         {text.c_str(), text.c_str() + text.size()});
152   }
153 
154   template <typename Label>
155   teeui::Error UpdateString();
156 
157   std::uint32_t display_num_;
158   teeui::layout_t<teeui::ConfUILayout> layout_;
159   std::string lang_id_;
160   std::string prompt_text_;  // confirmation ui message
161 
162   /**
163    * Potentially, the same frame could be requested multiple times.
164    *
165    * While another thread/caller is using this frame, the frame should
166    * be kept here, too, to be returned upon future requests.
167    *
168    */
169   std::shared_ptr<TeeUiFrameWrapper> raw_frame_;
170   std::uint32_t current_height_;
171   std::uint32_t current_width_;
172   teeui::Color color_bg_;
173   teeui::Color color_text_;
174   teeui::Color shield_color_;
175   bool is_inverted_;
176   bool is_magnified_;
177   teeui::context<teeui::ConfUIParameters> ctx_;
178   bool is_setup_well_;
179 
180   static constexpr const teeui::Color kColorBackground = 0xffffffff;
181   static constexpr const teeui::Color kColorBackgroundInv = 0xff212121;
182   static constexpr const teeui::Color kColorDisabled = 0xffbdbdbd;
183   static constexpr const teeui::Color kColorDisabledInv = 0xff424242;
184   static constexpr const teeui::Color kColorEnabled = 0xff212121;
185   static constexpr const teeui::Color kColorEnabledInv = 0xffdedede;
186   static constexpr const teeui::Color kColorShield = 0xff778500;
187   static constexpr const teeui::Color kColorShieldInv = 0xffc4cb80;
188   static constexpr const teeui::Color kColorText = 0xff212121;
189   static constexpr const teeui::Color kColorTextInv = 0xffdedede;
190 };
191 }  // end of namespace confui
192 }  // end of namespace cuttlefish
193