1 /* 2 * Copyright 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 <device_layout.h> 20 #include <teeui/button.h> 21 #include <teeui/label.h> 22 #include <teeui/localization/ConfirmationUITranslations.h> 23 #include <teeui/utils.h> 24 #include <memory> 25 #include <tuple> 26 27 #include "fonts.h" 28 29 using teeui::localization::TranslationId; 30 31 namespace teeui { 32 33 DECLARE_PARAMETER(RightEdgeOfScreen); 34 DECLARE_PARAMETER(BottomOfScreen); 35 DECLARE_PARAMETER(PowerButtonTop); 36 DECLARE_PARAMETER(PowerButtonBottom); 37 DECLARE_PARAMETER(VolUpButtonTop); 38 DECLARE_PARAMETER(VolUpButtonBottom); 39 DECLARE_PARAMETER(DefaultFontSize); // 14_dp regular and 18_dp magnified 40 DECLARE_PARAMETER(BodyFontSize); // 16_dp regular and 20_dp magnified 41 DECLARE_TYPED_PARAMETER(ShieldColor, ::teeui::Color); 42 DECLARE_TYPED_PARAMETER(ColorText, ::teeui::Color); 43 DECLARE_TYPED_PARAMETER(ColorBG, ::teeui::Color); 44 DECLARE_TYPED_PARAMETER(ColorTextHint, ::teeui::Color); 45 DECLARE_TYPED_PARAMETER(ColorButton, ::teeui::Color); 46 DECLARE_TYPED_PARAMETER(ColorButtonBG, ::teeui::Color); 47 48 NEW_PARAMETER_SET(ConUIParameters, 49 RightEdgeOfScreen, 50 BottomOfScreen, 51 PowerButtonTop, 52 PowerButtonBottom, 53 VolUpButtonTop, 54 VolUpButtonBottom, 55 DefaultFontSize, 56 BodyFontSize, 57 ShieldColor, 58 ColorText, 59 ColorBG, 60 ColorTextHint, 61 ColorButton, 62 ColorButtonBG); 63 64 namespace layouts { 65 66 CONSTANT(BorderWidth, 24_dp); 67 CONSTANT(PowerButtonCenter, (PowerButtonTop() + PowerButtonBottom()) / 2_px); 68 CONSTANT(VolUpButtonCenter, (VolUpButtonTop() + VolUpButtonBottom()) / 2.0_px); 69 CONSTANT(GrayZone, 12_dp); 70 CONSTANT(RightLabelEdge, RightEdgeOfScreen() - BorderWidth - GrayZone); 71 CONSTANT(LabelWidth, RightLabelEdge - BorderWidth); 72 73 CONSTANT(SQRT2, 1.4142135623_dp); 74 CONSTANT(SQRT8, 2.828427125_dp); 75 76 CONSTANT(ARROW_SHAPE, 77 CONVEX_OBJECTS(CONVEX_OBJECT(Vec2d{.0_dp, .0_dp}, 78 Vec2d{6.0_dp, 6.0_dp}, 79 Vec2d{6.0_dp - SQRT8, 6.0_dp}, 80 Vec2d{-SQRT2, SQRT2}), 81 CONVEX_OBJECT(Vec2d{6.0_dp - SQRT8, 6.0_dp}, 82 Vec2d{6.0_dp, 6.0_dp}, 83 Vec2d{0.0_dp, 12.0_dp}, 84 Vec2d{-SQRT2, 12.0_dp - SQRT2}))); 85 86 DECLARE_FONT_BUFFER(RobotoMedium, RobotoMedium, RobotoMedium_length); 87 DECLARE_FONT_BUFFER(RobotoRegular, RobotoRegular, RobotoRegular_length); 88 DECLARE_FONT_BUFFER(Shield, Shield, Shield_length); 89 90 CONSTANT(DefaultFont, FONT(RobotoRegular)); 91 92 BEGIN_ELEMENT(LabelOK, teeui::Label) 93 FontSize(DefaultFontSize()); 94 LineHeight(20_dp); 95 NumberOfLines(2); 96 Dimension(LabelWidth, HeightFromLines); 97 Position(BorderWidth, PowerButtonCenter - dim_h / 2.0_px); 98 DefaultText("Wiggle your big toe to confirm"); 99 RightJustified; 100 VerticallyCentered; 101 TextColor(ColorText()); 102 Font(FONT(RobotoMedium)); 103 TextID(TEXT_ID(TranslationId::CONFIRM_PWR_BUTTON_DOUBLE_PRESS)); 104 END_ELEMENT(); 105 106 BEGIN_ELEMENT(IconPower, teeui::Button, ConvexObjectCount(2)) 107 Dimension(BorderWidth, PowerButtonBottom() - PowerButtonTop()); 108 Position(RightEdgeOfScreen() - BorderWidth, PowerButtonTop()); 109 CornerRadius(3_dp); 110 ButtonColor(ColorButton()); 111 RoundTopLeft; 112 RoundBottomLeft; 113 ConvexObjectColor(ColorButtonBG()); 114 ConvexObjects(ARROW_SHAPE); 115 END_ELEMENT(); 116 117 BEGIN_ELEMENT(LabelCancel, teeui::Label) 118 FontSize(DefaultFontSize()); 119 LineHeight(20_dp); 120 NumberOfLines(2); 121 Dimension(LabelWidth, HeightFromLines); 122 Position(BorderWidth, VolUpButtonCenter - dim_h / 2.0_px); 123 DefaultText("Wink left then right thrice to cancel"); 124 RightJustified; 125 VerticallyCentered; 126 TextColor(ColorText()); 127 Font(FONT(RobotoMedium)); 128 TextID(TEXT_ID(TranslationId::CANCEL)); 129 END_ELEMENT(); 130 131 BEGIN_ELEMENT(IconVolUp, teeui::Button, ConvexObjectCount(2)) 132 Dimension(BorderWidth, VolUpButtonBottom() - VolUpButtonTop()); 133 Position(RightEdgeOfScreen() - BorderWidth, VolUpButtonTop()); 134 CornerRadius(5_dp); 135 ButtonColor(ColorButtonBG()); 136 ConvexObjectColor(ColorButton()); 137 ConvexObjects(ARROW_SHAPE); 138 END_ELEMENT(); 139 140 BEGIN_ELEMENT(IconShield, teeui::Label) 141 FontSize(24_dp); 142 LineHeight(24_dp); 143 NumberOfLines(1); 144 Dimension(LabelWidth, HeightFromLines); 145 Position(BorderWidth, BOTTOM_EDGE_OF(LabelCancel) + 40_dp); 146 DefaultText( 147 "A"); // ShieldTTF has just one glyph at the code point for capital A 148 TextColor(ShieldColor()); 149 Font(FONT(Shield)); 150 END_ELEMENT(); 151 152 BEGIN_ELEMENT(LabelTitle, teeui::Label) 153 FontSize(20_dp); 154 LineHeight(20_dp); 155 NumberOfLines(1); 156 Dimension(RightEdgeOfScreen() - BorderWidth, HeightFromLines); 157 Position(BorderWidth, BOTTOM_EDGE_OF(IconShield) + 12_dp); 158 DefaultText("Android Protected Confirmation"); 159 Font(FONT(RobotoMedium)); 160 VerticallyCentered; 161 TextColor(ColorText()); 162 TextID(TEXT_ID(TranslationId::TITLE)); 163 END_ELEMENT(); 164 165 BEGIN_ELEMENT(LabelHint, teeui::Label) 166 FontSize(DefaultFontSize()); 167 LineHeight(DefaultFontSize() * 1.5_px); 168 NumberOfLines(4); 169 Dimension(LabelWidth, HeightFromLines); 170 Position(BorderWidth, BottomOfScreen() - BorderWidth - dim_h); 171 DefaultText( 172 "This confirmation provides an extra layer of security for the action you're " 173 "about to take."); 174 VerticalTextAlignment(Alignment::BOTTOM); 175 TextColor(ColorTextHint()); 176 Font(DefaultFont); 177 TextID(TEXT_ID(TranslationId::DESCRIPTION)); 178 END_ELEMENT(); 179 180 BEGIN_ELEMENT(LabelBody, teeui::Label) 181 FontSize(BodyFontSize()); 182 LineHeight(BodyFontSize() * 1.4_px); 183 NumberOfLines(20); 184 Position(BorderWidth, BOTTOM_EDGE_OF(LabelTitle) + 18_dp); 185 Dimension(LabelWidth, LabelHint::pos_y - pos_y - 24_dp); 186 DefaultText( 187 "12345678901234567890123456789012345678901234567890123456789012345678901234567890123456" 188 "78901234567890"); 189 TextColor(ColorText()); 190 Font(FONT(RobotoRegular)); 191 END_ELEMENT(); 192 193 NEW_LAYOUT(ConfUILayout, 194 LabelOK, 195 IconPower, 196 LabelCancel, 197 IconVolUp, 198 IconShield, 199 LabelTitle, 200 LabelHint, 201 LabelBody); 202 203 class DisplayLayout : public ILayout { 204 public: 205 layout_t<ConfUILayout> layoutInstance_ = {}; 206 DisplayLayout(bool inverted,const context<ConUIParameters> & ctx)207 DisplayLayout(bool inverted, const context<ConUIParameters>& ctx) 208 : ILayout(inverted) { 209 layoutInstance_ = instantiateLayout(ConfUILayout(), ctx); 210 }; 211 setLanguage(const char * language_id)212 void setLanguage(const char* language_id) override { 213 teeui::localization::selectLangId(language_id); 214 translate(&std::get<LabelOK>(layoutInstance_)); 215 translate(&std::get<LabelCancel>(layoutInstance_)); 216 translate(&std::get<LabelTitle>(layoutInstance_)); 217 translate(&std::get<LabelHint>(layoutInstance_)); 218 } 219 setConfirmationMessage(const char * prompt)220 void setConfirmationMessage(const char* prompt) override { 221 std::get<LabelBody>(layoutInstance_) 222 .setText({prompt, prompt + strlen(prompt)}); 223 } 224 showInstructions(bool enable)225 void showInstructions(bool enable) override { 226 Color color; 227 228 if (enable) { 229 color = inverted_ ? kColorEnabledInv : kColorEnabled; 230 } else { 231 color = inverted_ ? kColorDisabledInv : kColorDisabled; 232 } 233 234 std::get<LabelOK>(layoutInstance_).setTextColor(color); 235 std::get<LabelCancel>(layoutInstance_).setTextColor(color); 236 } 237 drawElements(const teeui::PixelDrawer & drawPixel)238 teeui::Error drawElements(const teeui::PixelDrawer& drawPixel) override { 239 return drawElements(layoutInstance_, drawPixel); 240 } 241 242 private: translate(LabelImpl * label)243 void translate(LabelImpl* label) { 244 uint64_t textId = label->textId(); 245 const char* translation = localization::lookup( 246 static_cast<localization::TranslationId>(textId)); 247 label->setText({&translation[0], &translation[strlen(translation)]}); 248 } 249 250 template <typename... Elements> drawElements(std::tuple<Elements...> & layout,const teeui::PixelDrawer & drawPixel)251 teeui::Error drawElements(std::tuple<Elements...>& layout, 252 const teeui::PixelDrawer& drawPixel) { 253 // Error::operator|| is overloaded, so we don't get short circuit 254 // evaluation. But we get the first error that occurs. We will still try 255 // and draw the remaining elements in the order they appear in the 256 // layout tuple. 257 return (std::get<Elements>(layout).draw(drawPixel) || ...); 258 } 259 }; 260 261 } // namespace layouts 262 } // namespace teeui 263