1 /*
2  * Copyright 2020, 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 #include "phys_button_example.h"
18 
19 #include <stddef.h>
20 #include <stdint.h>
21 
22 #include "example_utils.h"
23 #include "layout/phys_button_layout.h"
24 
25 #include <memory>
26 
27 namespace teeui {
28 namespace example {
29 namespace phys_button {
30 
translateLabels(Layout * layout)31 template <typename Layout> static void translateLabels(Layout* layout) {
32     translateLabel<LabelOK>(layout);
33     translateLabel<LabelCancel>(layout);
34     translateLabel<LabelTitle>(layout);
35     translateLabel<LabelHint>(layout);
36 }
37 
38 class GUIStatePhysButtons : public ITeeuiExample {
39   public:
40     bool inverted_;
41     std::string confirmationMessage_;
42     layout_t<ConfUILayout> layoutInstance_ = {};
43 
GUIStatePhysButtons()44     GUIStatePhysButtons() : inverted_(false), layoutInstance_{} {}
45 
selectLanguage(const char * language_id)46     void selectLanguage(const char* language_id) override {
47         teeui::localization::selectLangId(language_id);
48         translateLabels(&layoutInstance_);
49     }
50 
setConfirmationMessage(std::string confirmationMessage)51     void setConfirmationMessage(std::string confirmationMessage) override {
52         confirmationMessage_ = std::move(confirmationMessage);
53         std::get<LabelBody>(layoutInstance_)
54             .setText({&*confirmationMessage_.begin(), &*confirmationMessage_.end()});
55     }
56 
57     uint32_t setDeviceInfo(DeviceInfo device_info, bool magnified, bool inverted = false) override;
onEvent(uint32_t,uint32_t,uint32_t)58     EventResult onEvent(uint32_t, uint32_t, uint32_t) override { return EventResult::NONE; }
59 
60     uint32_t renderUIIntoBuffer(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint32_t lineStride,
61                                 uint32_t* buffer,
62                                 size_t buffer_size_in_elements_not_bytes) override;
63 };
64 
createTeeuiExample()65 std::unique_ptr<ITeeuiExample> createTeeuiExample() {
66     return std::make_unique<GUIStatePhysButtons>();
67 }
68 
setLayoutParams(DeviceInfo & deviceInfo,bool magnified,bool inverted)69 static context<ConUIParameters> setLayoutParams(DeviceInfo& deviceInfo, bool magnified,
70                                                 bool inverted) {
71     context<ConUIParameters> ctx(deviceInfo.mm2px_, deviceInfo.dp2px_);
72     ctx.setParam<RightEdgeOfScreen>(pxs(deviceInfo.width_));
73     ctx.setParam<BottomOfScreen>(pxs(deviceInfo.height_));
74     ctx.setParam<PowerButtonTop>(mms(deviceInfo.powerButtonTopMm_));
75     ctx.setParam<PowerButtonBottom>(mms(deviceInfo.powerButtonBottomMm_));
76     ctx.setParam<VolUpButtonTop>(mms(deviceInfo.volUpButtonTopMm_));
77     ctx.setParam<VolUpButtonBottom>(mms(deviceInfo.volUpButtonBottomMm_));
78     if (magnified) {
79         ctx.setParam<DefaultFontSize>(18_dp);
80         ctx.setParam<BodyFontSize>(20_dp);
81     } else {
82         ctx.setParam<DefaultFontSize>(14_dp);
83         ctx.setParam<BodyFontSize>(16_dp);
84     }
85     if (inverted) {
86         ctx.setParam<ShieldColor>(kShieldColorInv);
87         ctx.setParam<ColorText>(kTextColorInv);
88         ctx.setParam<ColorBG>(kBackGroundColorInv);
89     } else {
90         ctx.setParam<ShieldColor>(kShieldColor);
91         ctx.setParam<ColorText>(kTextColor);
92         ctx.setParam<ColorBG>(kBackGroundColor);
93     }
94     return ctx;
95 }
96 
setDeviceInfo(DeviceInfo device_info,bool magnified,bool inverted)97 uint32_t GUIStatePhysButtons::setDeviceInfo(DeviceInfo device_info, bool magnified, bool inverted) {
98     layoutInstance_ =
99         instantiateLayout(ConfUILayout(), setLayoutParams(device_info, magnified, inverted));
100     inverted_ = inverted;
101 
102     return 0;
103 }
104 
renderUIIntoBuffer(uint32_t x,uint32_t y,uint32_t w,uint32_t h,uint32_t lineStride,uint32_t * buffer,size_t buffer_size_in_elements_not_bytes)105 uint32_t GUIStatePhysButtons::renderUIIntoBuffer(uint32_t x, uint32_t y, uint32_t w, uint32_t h,
106                                                  uint32_t lineStride, uint32_t* buffer,
107                                                  size_t buffer_size_in_elements_not_bytes) {
108     uint32_t afterLastPixelIndex = 0;
109     if (__builtin_add_overflow(y, h, &afterLastPixelIndex) ||
110         __builtin_add_overflow(afterLastPixelIndex, -1, &afterLastPixelIndex) ||
111         __builtin_mul_overflow(afterLastPixelIndex, lineStride, &afterLastPixelIndex) ||
112         __builtin_add_overflow(afterLastPixelIndex, x, &afterLastPixelIndex) ||
113         __builtin_add_overflow(afterLastPixelIndex, w, &afterLastPixelIndex) ||
114         afterLastPixelIndex > buffer_size_in_elements_not_bytes) {
115         return uint32_t(Error::OutOfBoundsDrawing);
116     }
117 
118     uint32_t* begin = buffer + (y * lineStride + x);
119 
120     Color bgColor = inverted_ ? kBackGroundColorInv : kBackGroundColor;
121 
122     for (uint32_t yi = 0; yi < h; ++yi) {
123         for (uint32_t xi = 0; xi < w; ++xi) {
124             begin[xi] = bgColor;
125         }
126         begin += lineStride;
127     }
128     FrameBuffer fb;
129     fb.left_ = x;
130     fb.top_ = y;
131     fb.width_ = w;
132     fb.height_ = h;
133     fb.buffer_ = buffer;
134     fb.size_in_elements_ = buffer_size_in_elements_not_bytes;
135     fb.lineStride_ = lineStride;
136 
137     auto pixelDrawer = makePixelDrawer(
138         [&fb](uint32_t x, uint32_t y, Color color) -> Error { return fb.drawPixel(x, y, color); });
139 
140     if (auto error = drawElements(layoutInstance_, pixelDrawer)) {
141         return uint32_t(error.code());
142     }
143 
144     return 0;  // OK
145 }
146 
147 }  // namespace phys_button
148 }  // namespace example
149 }  // namespace teeui