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.h" 33 34 namespace cuttlefish { 35 namespace confui { 36 37 /** 38 * create a raw frame for confirmation UI dialog 39 */ 40 class ConfUiRenderer { 41 public: 42 using LabelConfMsg = teeui::LabelBody; 43 44 ConfUiRenderer(const std::uint32_t display); 45 46 /** 47 * this does not repaint from the scratch all the time 48 * 49 * Unless repainting the whole thing is needed, it remove the message 50 * label, and re-draw there. There seems yet no fancy way of doing this. 51 * Thus, it repaint the background color on the top of the label, and 52 * draw the label on the new background 53 * 54 * As HostRenderer is intended to be shared across sessions, HostRender 55 * owns the buffer, and returns reference to the buffer. Note that no 56 * 2 or more sessions are concurrently executed. Only 1 or 0 is active 57 * at the given moment. 58 */ 59 std::tuple<TeeUiFrame&, bool> RenderRawFrame( 60 const std::string& confirmation_msg, const std::string& lang_id = "en"); 61 IsFrameReady()62 bool IsFrameReady() const { return !raw_frame_.empty(); } 63 64 private: 65 struct Boundary { // inclusive but.. LayoutElement's size is float 66 std::uint32_t x, y, w, h; // (x, y) is the top left 67 }; 68 69 template <typename LayoutElement> GetBoundary(LayoutElement && e)70 Boundary GetBoundary(LayoutElement&& e) { 71 auto box = e.bounds_; 72 Boundary b; 73 // (x,y) is left top. so floor() makes sense 74 // w, h are witdh and height in float. perhaps ceiling makes more 75 // sense 76 b.x = static_cast<std::uint32_t>(box.x().floor().count()); 77 b.y = static_cast<std::uint32_t>(box.y().floor().count()); 78 b.w = static_cast<std::uint32_t>(box.w().ceil().count()); 79 b.h = static_cast<std::uint32_t>(box.h().ceil().count()); 80 return b; 81 } 82 83 // essentially, to repaint from the scratch, so returns new frame 84 // when successful. Or, nullopt 85 std::optional<TeeUiFrame> RepaintRawFrame(const std::string& confirmation_msg, 86 const std::string& lang_id = "en"); 87 88 bool InitLayout(const std::string& lang_id); 89 teeui::Error UpdateTranslations(); 90 /** 91 * could be confusing. update prompt_, and update the text_ in the Label 92 * object, the GUI components. This does not render immediately. And.. 93 * to render it, we must clean up the existing dirty pixels, which 94 * this method does not do. 95 */ 96 void SetConfUiMessage(const std::string& s); 97 teeui::Error SetLangId(const std::string& lang_id); 98 teeui::context<teeui::ConUIParameters> GetDeviceContext(); 99 100 // effectively, will be send to teeui as a callback function 101 teeui::Error UpdatePixels(TeeUiFrame& buffer, std::uint32_t x, 102 std::uint32_t y, teeui::Color color); 103 104 // from Trusty 105 // second param is for type deduction 106 template <typename... Elements> drawElements(std::tuple<Elements...> & layout,const teeui::PixelDrawer & drawPixel)107 static teeui::Error drawElements(std::tuple<Elements...>& layout, 108 const teeui::PixelDrawer& drawPixel) { 109 // Error::operator|| is overloaded, so we don't get short circuit 110 // evaluation. But we get the first error that occurs. We will still try and 111 // draw the remaining elements in the order they appear in the layout tuple. 112 return (std::get<Elements>(layout).draw(drawPixel) || ...); 113 } 114 115 // repaint the confirmation UI label only 116 teeui::Error RenderConfirmationMsgOnly(const std::string& confirmation_msg); 117 118 // from Trusty 119 template <typename Context> UpdateColorScheme(Context * ctx)120 void UpdateColorScheme(Context* ctx) { 121 using namespace teeui; 122 color_text_ = is_inverted_ ? kColorDisabledInv : kColorDisabled; 123 shield_color_ = is_inverted_ ? kColorShieldInv : kColorShield; 124 color_bg_ = is_inverted_ ? kColorBackgroundInv : kColorBackground; 125 126 ctx->template setParam<ShieldColor>(shield_color_); 127 ctx->template setParam<ColorText>(color_text_); 128 ctx->template setParam<ColorBG>(color_bg_); 129 return; 130 } 131 132 template <typename Label> SetText(const std::string & text)133 auto SetText(const std::string& text) { 134 return std::get<Label>(layout_).setText( 135 {text.c_str(), text.c_str() + text.size()}); 136 } 137 138 /** 139 * source: 140 * https://android.googlesource.com/trusty/app/confirmationui/+/0429cc7/src/trusty_confirmation_ui.cpp#49 141 */ 142 template <typename Label> UpdateString()143 teeui::Error UpdateString() { 144 using namespace teeui; 145 const char* str; 146 auto& label = std::get<Label>(layout_); 147 str = localization::lookup(TranslationId(label.textId())); 148 if (str == nullptr) { 149 ConfUiLog(ERROR) << "Given translation_id" << label.textId() 150 << "not found"; 151 return Error::Localization; 152 } 153 label.setText({str, str + strlen(str)}); 154 return Error::OK; 155 } 156 157 const int display_num_; 158 teeui::layout_t<teeui::ConfUILayout> layout_; 159 std::string lang_id_; 160 std::string prompt_; // confirmation ui message 161 TeeUiFrame raw_frame_; 162 std::uint32_t current_height_; 163 std::uint32_t current_width_; 164 teeui::Color color_bg_; 165 teeui::Color color_text_; 166 teeui::Color shield_color_; 167 bool is_inverted_; 168 teeui::context<teeui::ConUIParameters> ctx_; 169 170 static constexpr const teeui::Color kColorEnabled = 0xff212121; 171 static constexpr const teeui::Color kColorDisabled = 0xffbdbdbd; 172 static constexpr const teeui::Color kColorEnabledInv = 0xffdedede; 173 static constexpr const teeui::Color kColorDisabledInv = 0xff424242; 174 static constexpr const teeui::Color kColorBackground = 0xffffffff; 175 static constexpr const teeui::Color kColorBackgroundInv = 0xff212121; 176 static constexpr const teeui::Color kColorShieldInv = 0xffc4cb80; 177 static constexpr const teeui::Color kColorShield = 0xff778500; 178 }; 179 } // end of namespace confui 180 } // end of namespace cuttlefish 181