Restructure teeui methods into device class.

Bug: 155226926
Test: N/A
Change-Id: I8dbfde5605e82b8c094db3fb8ceadf88316ee27b
diff --git a/libteeui/example/Android.bp b/libteeui/example/Android.bp
index b2e8a26..5ed3621 100644
--- a/libteeui/example/Android.bp
+++ b/libteeui/example/Android.bp
@@ -2,8 +2,10 @@
     name: "libteeui_example_layout",
     defaults: ["keystore_defaults"],
     srcs: [
+        "examples.cpp",
+        "example_utils.cpp",
         "fonts.S",
-        "teeui.cpp",
+        "phys_button_example.cpp",
     ],
     static_libs: [
         "libft2.nodep",
diff --git a/libteeui/example/example_utils.cpp b/libteeui/example/example_utils.cpp
new file mode 100644
index 0000000..b707356
--- /dev/null
+++ b/libteeui/example/example_utils.cpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2020, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stddef.h>
+
+#include <teeui/label.h>
+#include <teeui/localization/ConfirmationUITranslations.h>
+
+#include "example_utils.h"
+
+namespace teeui {
+namespace example {
+
+uint32_t alfaCombineChannel(uint32_t shift, double alfa, uint32_t a, uint32_t b) {
+    a >>= shift;
+    a &= 0xff;
+    b >>= shift;
+    b &= 0xff;
+    double acc = alfa * a + (1 - alfa) * b;
+    if (acc <= 0) return 0;
+    uint32_t result = acc;
+    if (result > 255) return 255 << shift;
+    return result << shift;
+}
+
+Error FrameBuffer::drawPixel(uint32_t x, uint32_t y, uint32_t color) const {
+    size_t pos = (top_ + y) * lineStride_ + x + left_;
+    if (pos >= size_in_elements_) {
+        return Error::OutOfBoundsDrawing;
+    }
+    double alfa = (color & 0xff000000) >> 24;
+    alfa /= 255.0;
+    auto acc = buffer_[pos];
+    buffer_[pos] = alfaCombineChannel(0, alfa, color, acc) |
+                   alfaCombineChannel(8, alfa, color, acc) |
+                   alfaCombineChannel(16, alfa, color, acc);
+    return Error::OK;
+}
+
+void translate(LabelImpl* label) {
+    uint64_t textId = label->textId();
+    const char* translation =
+        localization::lookup(static_cast<localization::TranslationId>(textId));
+    label->setText({&translation[0], &translation[strlen(translation)]});
+}
+
+}  // namespace example
+}  // namespace teeui
\ No newline at end of file
diff --git a/libteeui/example/example_utils.h b/libteeui/example/example_utils.h
new file mode 100644
index 0000000..3a4f841
--- /dev/null
+++ b/libteeui/example/example_utils.h
@@ -0,0 +1,69 @@
+/*
+ *
+ * Copyright 2019, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <stddef.h>
+
+#include <teeui/label.h>
+
+namespace teeui {
+namespace example {
+
+/*
+ * AOSP color scheme constants.
+ */
+constexpr static const Color kShieldColor = Color(0xff778500);
+constexpr static const Color kShieldColorInv = Color(0xffc4cb80);
+constexpr static const Color kTextColor = Color(0xff212121);
+constexpr static const Color kTextColorInv = Color(0xffdedede);
+constexpr static const Color kBackGroundColor = Color(0xffffffff);
+constexpr static const Color kBackGroundColorInv = Color(0xff212121);
+
+uint32_t alfaCombineChannel(uint32_t shift, double alfa, uint32_t a, uint32_t b);
+
+template <typename T> uint32_t renderPixel(uint32_t x, uint32_t y, const T& e) {
+    return e.bounds_.drawPoint(Point<pxs>(x, y));
+}
+
+struct FrameBuffer {
+    uint32_t left_;
+    uint32_t top_;
+    uint32_t width_;
+    uint32_t height_;
+    uint32_t* buffer_;
+    size_t size_in_elements_;
+    uint32_t lineStride_;
+
+    Error drawPixel(uint32_t x, uint32_t y, uint32_t color) const;
+};
+
+template <typename... Elements>
+Error drawElements(std::tuple<Elements...>& layout, const PixelDrawer& drawPixel) {
+    // Error::operator|| is overloaded, so we don't get short circuit evaluation.
+    // But we get the first error that occurs. We will still try and draw the remaining
+    // elements in the order they appear in the layout tuple.
+    return (std::get<Elements>(layout).draw(drawPixel) || ...);
+}
+
+void translate(LabelImpl* label);
+
+template <typename T, typename Layout> void translateLabel(Layout* layout) {
+    translate(&std::get<T>(*layout));
+}
+}  // namespace example
+}  // namespace teeui
\ No newline at end of file
diff --git a/libteeui/example/examples.cpp b/libteeui/example/examples.cpp
new file mode 100644
index 0000000..d51a9ff
--- /dev/null
+++ b/libteeui/example/examples.cpp
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2020, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "phys_button_example.h"
+
+namespace teeui {
+namespace example {
+
+std::unique_ptr<ITeeuiExample> createExample(Examples example) {
+    switch (example) {
+    case Examples::PhysButton:
+        return phys_button::createTeeuiExample();
+    }
+}
+}  // namespace example
+}  // namespace teeui
\ No newline at end of file
diff --git a/libteeui/example/layout/common_layout_params.h b/libteeui/example/layout/common_layout_params.h
new file mode 100644
index 0000000..9ba2537
--- /dev/null
+++ b/libteeui/example/layout/common_layout_params.h
@@ -0,0 +1,27 @@
+#pragma once
+
+#include <teeui/utils.h>
+
+#include "fonts.h"
+
+namespace teeui {
+namespace example {
+
+DECLARE_PARAMETER(RightEdgeOfScreen);
+DECLARE_PARAMETER(BottomOfScreen);
+DECLARE_PARAMETER(DefaultFontSize);  // 14_dp regular and 18_dp magnified
+DECLARE_PARAMETER(BodyFontSize);     // 16_dp regular and 20_dp magnified
+DECLARE_TYPED_PARAMETER(ShieldColor, ::teeui::Color);
+DECLARE_TYPED_PARAMETER(ColorText, ::teeui::Color);
+DECLARE_TYPED_PARAMETER(ColorBG, ::teeui::Color);
+
+CONSTANT(BorderWidth, 24_dp);
+
+DECLARE_FONT_BUFFER(RobotoMedium, RobotoMedium, RobotoMedium_length);
+DECLARE_FONT_BUFFER(RobotoRegular, RobotoRegular, RobotoRegular_length);
+DECLARE_FONT_BUFFER(Shield, Shield, Shield_length);
+
+CONSTANT(DefaultFont, FONT(RobotoRegular));
+
+}  // namespace example
+}  // namespace teeui
\ No newline at end of file
diff --git a/libteeui/example/layout.h b/libteeui/example/layout/phys_button_layout.h
similarity index 87%
rename from libteeui/example/layout.h
rename to libteeui/example/layout/phys_button_layout.h
index 7318a0c..a3f1fe7 100644
--- a/libteeui/example/layout.h
+++ b/libteeui/example/layout/phys_button_layout.h
@@ -19,31 +19,24 @@
 #include <teeui/button.h>
 #include <teeui/label.h>
 #include <teeui/localization/ConfirmationUITranslations.h>
-#include <teeui/utils.h>
 
-#include "fonts.h"
+#include "common_layout_params.h"
 
 using teeui::localization::TranslationId;
 
 namespace teeui {
+namespace example {
+namespace phys_button {
 
-DECLARE_PARAMETER(RightEdgeOfScreen);
-DECLARE_PARAMETER(BottomOfScreen);
 DECLARE_PARAMETER(PowerButtonTop);
 DECLARE_PARAMETER(PowerButtonBottom);
 DECLARE_PARAMETER(VolUpButtonTop);
 DECLARE_PARAMETER(VolUpButtonBottom);
-DECLARE_PARAMETER(DefaultFontSize);  // 14_dp regular and 18_dp magnified
-DECLARE_PARAMETER(BodyFontSize);     // 16_dp regular and 20_dp magnified
-DECLARE_TYPED_PARAMETER(ShieldColor, ::teeui::Color);
-DECLARE_TYPED_PARAMETER(ColorText, ::teeui::Color);
-DECLARE_TYPED_PARAMETER(ColorBG, ::teeui::Color);
 
 NEW_PARAMETER_SET(ConUIParameters, RightEdgeOfScreen, BottomOfScreen, PowerButtonTop,
                   PowerButtonBottom, VolUpButtonTop, VolUpButtonBottom, DefaultFontSize,
                   BodyFontSize, ShieldColor, ColorText, ColorBG);
 
-CONSTANT(BorderWidth, 24_dp);
 CONSTANT(PowerButtonCenter, (PowerButtonTop() + PowerButtonBottom()) / 2_px);
 CONSTANT(VolUpButtonCenter, (VolUpButtonTop() + VolUpButtonBottom()) / 2.0_px);
 CONSTANT(GrayZone, 12_dp);
@@ -59,12 +52,6 @@
                         CONVEX_OBJECT(Vec2d{6.0_dp - SQRT8, 6.0_dp}, Vec2d{6.0_dp, 6.0_dp},
                                       Vec2d{0.0_dp, 12.0_dp}, Vec2d{-SQRT2, 12.0_dp - SQRT2})));
 
-DECLARE_FONT_BUFFER(RobotoMedium, RobotoMedium, RobotoMedium_length);
-DECLARE_FONT_BUFFER(RobotoRegular, RobotoRegular, RobotoRegular_length);
-DECLARE_FONT_BUFFER(Shield, Shield, Shield_length);
-
-CONSTANT(DefaultFont, FONT(RobotoRegular));
-
 BEGIN_ELEMENT(LabelOK, teeui::Label)
 FontSize(DefaultFontSize());
 LineHeight(20_dp);
@@ -166,4 +153,6 @@
 NEW_LAYOUT(ConfUILayout, LabelOK, IconPower, LabelCancel, IconVolUp, IconShield, LabelTitle,
            LabelHint, LabelBody);
 
-}  // namespace teeui
+}  // namespace phys_button
+}  // namespace example
+}  // namespace teeui
\ No newline at end of file
diff --git a/libteeui/example/phys_button_example.cpp b/libteeui/example/phys_button_example.cpp
new file mode 100644
index 0000000..5f6365e
--- /dev/null
+++ b/libteeui/example/phys_button_example.cpp
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2020, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "phys_button_example.h"
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "example_utils.h"
+#include "layout/phys_button_layout.h"
+
+#include <memory>
+
+namespace teeui {
+namespace example {
+namespace phys_button {
+
+template <typename Layout> static void translateLabels(Layout* layout) {
+    translateLabel<LabelOK>(layout);
+    translateLabel<LabelCancel>(layout);
+    translateLabel<LabelTitle>(layout);
+    translateLabel<LabelHint>(layout);
+}
+
+class GUIStatePhysButtons : public ITeeuiExample {
+  public:
+    bool inverted_;
+    std::string confirmationMessage_;
+    layout_t<ConfUILayout> layoutInstance_ = {};
+
+    GUIStatePhysButtons() : inverted_(false), layoutInstance_{} {}
+
+    void selectLanguage(const char* language_id) override {
+        teeui::localization::selectLangId(language_id);
+        translateLabels(&layoutInstance_);
+    }
+
+    void setConfirmationMessage(std::string confirmationMessage) override {
+        confirmationMessage_ = std::move(confirmationMessage);
+        std::get<LabelBody>(layoutInstance_)
+            .setText({&*confirmationMessage_.begin(), &*confirmationMessage_.end()});
+    }
+
+    uint32_t setDeviceInfo(DeviceInfo device_info, bool magnified, bool inverted = false) override;
+    void onEvent(uint32_t, uint32_t, uint32_t) override {}
+
+    uint32_t 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) override;
+};
+
+std::unique_ptr<ITeeuiExample> createTeeuiExample() {
+    return std::make_unique<GUIStatePhysButtons>();
+}
+
+static context<ConUIParameters> setLayoutParams(DeviceInfo& deviceInfo, bool magnified,
+                                                bool inverted) {
+    context<ConUIParameters> ctx(deviceInfo.mm2px_, deviceInfo.dp2px_);
+    ctx.setParam<RightEdgeOfScreen>(pxs(deviceInfo.width_));
+    ctx.setParam<BottomOfScreen>(pxs(deviceInfo.height_));
+    ctx.setParam<PowerButtonTop>(mms(deviceInfo.powerButtonTopMm_));
+    ctx.setParam<PowerButtonBottom>(mms(deviceInfo.powerButtonBottomMm_));
+    ctx.setParam<VolUpButtonTop>(mms(deviceInfo.volUpButtonTopMm_));
+    ctx.setParam<VolUpButtonBottom>(mms(deviceInfo.volUpButtonBottomMm_));
+    if (magnified) {
+        ctx.setParam<DefaultFontSize>(18_dp);
+        ctx.setParam<BodyFontSize>(20_dp);
+    } else {
+        ctx.setParam<DefaultFontSize>(14_dp);
+        ctx.setParam<BodyFontSize>(16_dp);
+    }
+    if (inverted) {
+        ctx.setParam<ShieldColor>(kShieldColorInv);
+        ctx.setParam<ColorText>(kTextColorInv);
+        ctx.setParam<ColorBG>(kBackGroundColorInv);
+    } else {
+        ctx.setParam<ShieldColor>(kShieldColor);
+        ctx.setParam<ColorText>(kTextColor);
+        ctx.setParam<ColorBG>(kBackGroundColor);
+    }
+    return ctx;
+}
+
+uint32_t GUIStatePhysButtons::setDeviceInfo(DeviceInfo device_info, bool magnified, bool inverted) {
+    layoutInstance_ =
+        instantiateLayout(ConfUILayout(), setLayoutParams(device_info, magnified, inverted));
+    inverted_ = inverted;
+
+    return 0;
+}
+
+uint32_t GUIStatePhysButtons::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) {
+    uint32_t afterLastPixelIndex = 0;
+    if (__builtin_add_overflow(y, h, &afterLastPixelIndex) ||
+        __builtin_add_overflow(afterLastPixelIndex, -1, &afterLastPixelIndex) ||
+        __builtin_mul_overflow(afterLastPixelIndex, lineStride, &afterLastPixelIndex) ||
+        __builtin_add_overflow(afterLastPixelIndex, x, &afterLastPixelIndex) ||
+        __builtin_add_overflow(afterLastPixelIndex, w, &afterLastPixelIndex) ||
+        afterLastPixelIndex > buffer_size_in_elements_not_bytes) {
+        return uint32_t(Error::OutOfBoundsDrawing);
+    }
+
+    uint32_t* begin = buffer + (y * lineStride + x);
+
+    Color bgColor = inverted_ ? kBackGroundColorInv : kBackGroundColor;
+
+    for (uint32_t yi = 0; yi < h; ++yi) {
+        for (uint32_t xi = 0; xi < w; ++xi) {
+            begin[xi] = bgColor;
+        }
+        begin += lineStride;
+    }
+    FrameBuffer fb;
+    fb.left_ = x;
+    fb.top_ = y;
+    fb.width_ = w;
+    fb.height_ = h;
+    fb.buffer_ = buffer;
+    fb.size_in_elements_ = buffer_size_in_elements_not_bytes;
+    fb.lineStride_ = lineStride;
+
+    auto pixelDrawer = makePixelDrawer(
+        [&fb](uint32_t x, uint32_t y, Color color) -> Error { return fb.drawPixel(x, y, color); });
+
+    if (auto error = drawElements(layoutInstance_, pixelDrawer)) {
+        return uint32_t(error.code());
+    }
+
+    return 0;  // OK
+}
+
+}  // namespace phys_button
+}  // namespace example
+}  // namespace teeui
\ No newline at end of file
diff --git a/libteeui/example/phys_button_example.h b/libteeui/example/phys_button_example.h
new file mode 100644
index 0000000..268f2d4
--- /dev/null
+++ b/libteeui/example/phys_button_example.h
@@ -0,0 +1,31 @@
+/*
+ *
+ * Copyright 2019, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <memory>
+#include <teeui/example/example.h>
+
+namespace teeui {
+namespace example {
+namespace phys_button {
+
+std::unique_ptr<ITeeuiExample> createTeeuiExample();
+
+}  // namespace phys_button
+}  // namespace example
+}  // namespace teeui
\ No newline at end of file
diff --git a/libteeui/example/teeui.cpp b/libteeui/example/teeui.cpp
deleted file mode 100644
index b415283..0000000
--- a/libteeui/example/teeui.cpp
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- *
- * Copyright 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#include "layout.h"
-#include <cassert>
-#include <iostream>
-#include <teeui/example/teeui.h>
-#include <teeui/localization/ConfirmationUITranslations.h>
-#include <typeinfo>
-
-using namespace teeui;
-
-static DeviceInfo sDeviceInfo;
-static bool sMagnified;
-static bool sInverted;
-static std::string sConfirmationMessage;
-
-/*
- * AOSP color scheme constants.
- */
-constexpr static const Color kShieldColor = Color(0xff778500);
-constexpr static const Color kShieldColorInv = Color(0xffc4cb80);
-constexpr static const Color kTextColor = Color(0xff212121);
-constexpr static const Color kTextColorInv = Color(0xffdedede);
-constexpr static const Color kBackGroundColor = Color(0xffffffff);
-constexpr static const Color kBackGroundColorInv = Color(0xff212121);
-
-void setConfirmationMessage(const char* confirmationMessage) {
-    sConfirmationMessage = confirmationMessage;
-}
-
-uint32_t alfaCombineChannel(uint32_t shift, double alfa, uint32_t a, uint32_t b) {
-    a >>= shift;
-    a &= 0xff;
-    b >>= shift;
-    b &= 0xff;
-    double acc = alfa * a + (1 - alfa) * b;
-    if (acc <= 0) return 0;
-    uint32_t result = acc;
-    if (result > 255) return 255 << shift;
-    return result << shift;
-}
-
-template <typename T> uint32_t renderPixel(uint32_t x, uint32_t y, const T& e) {
-    return e.bounds_.drawPoint(Point<pxs>(x, y));
-}
-
-struct FrameBuffer {
-    uint32_t left_;
-    uint32_t top_;
-    uint32_t width_;
-    uint32_t height_;
-    uint32_t* buffer_;
-    size_t size_in_elements_;
-    uint32_t lineStride_;
-
-    Error drawPixel(uint32_t x, uint32_t y, uint32_t color) const {
-        size_t pos = (top_ + y) * lineStride_ + x + left_;
-        if (pos >= size_in_elements_) {
-            return Error::OutOfBoundsDrawing;
-        }
-        double alfa = (color & 0xff000000) >> 24;
-        alfa /= 255.0;
-        auto acc = buffer_[pos];
-        buffer_[pos] = alfaCombineChannel(0, alfa, color, acc) |
-                       alfaCombineChannel(8, alfa, color, acc) |
-                       alfaCombineChannel(16, alfa, color, acc);
-        return Error::OK;
-    }
-};
-
-template <typename... Elements>
-Error drawElements(std::tuple<Elements...>& layout, const PixelDrawer& drawPixel) {
-    // Error::operator|| is overloaded, so we don't get short circuit evaluation.
-    // But we get the first error that occurs. We will still try and draw the remaining
-    // elements in the order they appear in the layout tuple.
-    return (std::get<Elements>(layout).draw(drawPixel) || ...);
-}
-
-uint32_t setDeviceInfo(DeviceInfo deviceInfo, bool magnified, bool inverted) {
-    sDeviceInfo = deviceInfo;
-    sMagnified = magnified;
-    sInverted = inverted;
-    return 0;
-}
-
-void selectLanguage(const char* language_id) {
-    teeui::localization::selectLangId(language_id);
-}
-
-void translate(LabelImpl* label) {
-    uint64_t textId = label->textId();
-    const char* translation =
-        teeui::localization::lookup(static_cast<teeui::localization::TranslationId>(textId));
-    label->setText({&translation[0], &translation[strlen(translation)]});
-}
-
-template <typename... Elements> void translateLabels(std::tuple<Elements...>& layout) {
-    translate(&std::get<LabelOK>(layout));
-    translate(&std::get<LabelCancel>(layout));
-    translate(&std::get<LabelTitle>(layout));
-    translate(&std::get<LabelHint>(layout));
-}
-
-uint32_t 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) {
-    uint32_t afterLastPixelIndex = 0;
-    if (__builtin_add_overflow(y, h, &afterLastPixelIndex) ||
-        __builtin_add_overflow(afterLastPixelIndex, -1, &afterLastPixelIndex) ||
-        __builtin_mul_overflow(afterLastPixelIndex, lineStride, &afterLastPixelIndex) ||
-        __builtin_add_overflow(afterLastPixelIndex, x, &afterLastPixelIndex) ||
-        __builtin_add_overflow(afterLastPixelIndex, w, &afterLastPixelIndex) ||
-        afterLastPixelIndex > buffer_size_in_elements_not_bytes) {
-        return uint32_t(Error::OutOfBoundsDrawing);
-    }
-    context<ConUIParameters> ctx(sDeviceInfo.mm2px_, sDeviceInfo.dp2px_);
-    ctx.setParam<RightEdgeOfScreen>(pxs(sDeviceInfo.width_));
-    ctx.setParam<BottomOfScreen>(pxs(sDeviceInfo.height_));
-    ctx.setParam<PowerButtonTop>(mms(sDeviceInfo.powerButtonTopMm_));
-    ctx.setParam<PowerButtonBottom>(mms(sDeviceInfo.powerButtonBottomMm_));
-    ctx.setParam<VolUpButtonTop>(mms(sDeviceInfo.volUpButtonTopMm_));
-    ctx.setParam<VolUpButtonBottom>(mms(sDeviceInfo.volUpButtonBottomMm_));
-    if (sMagnified) {
-        ctx.setParam<DefaultFontSize>(18_dp);
-        ctx.setParam<BodyFontSize>(20_dp);
-    } else {
-        ctx.setParam<DefaultFontSize>(14_dp);
-        ctx.setParam<BodyFontSize>(16_dp);
-    }
-
-    if (sInverted) {
-        ctx.setParam<ShieldColor>(kShieldColorInv);
-        ctx.setParam<ColorText>(kTextColorInv);
-        ctx.setParam<ColorBG>(kBackGroundColorInv);
-    } else {
-        ctx.setParam<ShieldColor>(kShieldColor);
-        ctx.setParam<ColorText>(kTextColor);
-        ctx.setParam<ColorBG>(kBackGroundColor);
-    }
-
-    auto layoutInstance = instantiateLayout(ConfUILayout(), ctx);
-
-    translateLabels(layoutInstance);
-
-    uint32_t* begin = buffer + (y * lineStride + x);
-
-    Color bgColor = sInverted ? kBackGroundColorInv : kBackGroundColor;
-
-    for (uint32_t yi = 0; yi < h; ++yi) {
-        for (uint32_t xi = 0; xi < w; ++xi) {
-            begin[xi] = bgColor;
-        }
-        begin += lineStride;
-    }
-    FrameBuffer fb;
-    fb.left_ = x;
-    fb.top_ = y;
-    fb.width_ = w;
-    fb.height_ = h;
-    fb.buffer_ = buffer;
-    fb.size_in_elements_ = buffer_size_in_elements_not_bytes;
-    fb.lineStride_ = lineStride;
-
-    auto pixelDrawer = makePixelDrawer(
-        [&fb](uint32_t x, uint32_t y, Color color) -> Error { return fb.drawPixel(x, y, color); });
-
-    std::get<LabelBody>(layoutInstance)
-        .setText({&*sConfirmationMessage.begin(), &*sConfirmationMessage.end()});
-
-    if (auto error = drawElements(layoutInstance, pixelDrawer)) {
-        return uint32_t(error.code());
-    }
-
-    return 0;  // OK
-}
diff --git a/libteeui/include/teeui/example/example.h b/libteeui/include/teeui/example/example.h
new file mode 100644
index 0000000..827a72d
--- /dev/null
+++ b/libteeui/include/teeui/example/example.h
@@ -0,0 +1,59 @@
+/*
+ *
+ * Copyright 2019, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stddef.h>
+#include <string>
+
+#pragma once
+
+namespace teeui {
+namespace example {
+
+struct DeviceInfo {
+    uint32_t width_;
+    uint32_t height_;
+    double dp2px_;
+    double mm2px_;
+    double powerButtonTopMm_;
+    double powerButtonBottomMm_;
+    double volUpButtonTopMm_;
+    double volUpButtonBottomMm_;
+};
+
+class ITeeuiExample {
+  public:
+    virtual void selectLanguage(const char*) = 0;
+    virtual void setConfirmationMessage(std::string) = 0;
+    virtual uint32_t setDeviceInfo(DeviceInfo, bool, bool) = 0;
+    virtual uint32_t renderUIIntoBuffer(uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t*,
+                                        size_t) = 0;
+    virtual void onEvent(uint32_t x, uint32_t y, uint32_t) = 0;
+
+    virtual ~ITeeuiExample() {}
+};
+
+enum class Examples : uint32_t {
+    PhysButton,
+};
+
+static constexpr const int8_t kFrameBufferError = -1;
+static constexpr const int8_t kLayoutExampleError = -2;
+
+std::unique_ptr<ITeeuiExample> createExample(Examples example);
+
+}  // namespace example
+}  // namespace teeui
diff --git a/libteeui/include/teeui/example/teeui.h b/libteeui/include/teeui/example/teeui.h
deleted file mode 100644
index 3ee37f4..0000000
--- a/libteeui/include/teeui/example/teeui.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- *
- * Copyright 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef TEEUI_LIBTEEUI_INCLUDE_TEEUI_H_
-#define TEEUI_LIBTEEUI_INCLUDE_TEEUI_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-struct DeviceInfo {
-    uint32_t width_;
-    uint32_t height_;
-    double dp2px_;
-    double mm2px_;
-    double powerButtonTopMm_;
-    double powerButtonBottomMm_;
-    double volUpButtonTopMm_;
-    double volUpButtonBottomMm_;
-};
-
-uint32_t setDeviceInfo(DeviceInfo device_info, bool magnified, bool inverted = false);
-uint32_t 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);
-
-void selectLanguage(const char* language_id);
-
-void setConfirmationMessage(const char* confirmationMessage);
-
-#endif  // TEEUI_LIBTEEUI_INCLUDE_TEEUI_H_
diff --git a/libteeui/include/teeui/utils.h b/libteeui/include/teeui/utils.h
index 850d1b0..33da519 100644
--- a/libteeui/include/teeui/utils.h
+++ b/libteeui/include/teeui/utils.h
@@ -259,7 +259,6 @@
     }
 };
 
-template <typename Param, typename Numeric = DefaultNumericType> class context;
 template <typename T1, typename T2, typename Numeric, template <typename> class Op> struct BinOp;
 
 template <typename T1, typename T2, typename Numeric> using add = BinOp<T1, T2, Numeric, Add>;
@@ -435,6 +434,8 @@
     constexpr static const bool value = true;
 };
 
+template <typename Param, typename Numeric = DefaultNumericType> class context;
+
 template <typename... ParamsNames, typename... ParamTypes, typename Numeric>
 class context<MetaList<MetaParam<ParamsNames, ParamTypes>...>, Numeric> {
     Numeric mm2px_;
diff --git a/libteeui_jni/libteeui_jni.cpp b/libteeui_jni/libteeui_jni.cpp
index 960140b..342e8b0 100644
--- a/libteeui_jni/libteeui_jni.cpp
+++ b/libteeui_jni/libteeui_jni.cpp
@@ -16,7 +16,7 @@
  */
 
 #include <jni.h>
-#include <teeui/example/teeui.h>
+#include <teeui/example/example.h>
 #include <teeui/localization/ConfirmationUITranslations.h>
 
 using teeui::localization::getLanguages;
@@ -124,6 +124,8 @@
 using JByteArray = JArray<jbyteArray>;
 using JString = JArray<jstring>;
 
+static std::unique_ptr<teeui::example::ITeeuiExample> sCurrentExample;
+
 /*
  * Class:     com_android_framebufferizer_NativeRenderer
  * Method:    setDeviceInfo
@@ -131,6 +133,7 @@
  */
 extern "C" JNIEXPORT jint JNICALL Java_com_android_framebufferizer_NativeRenderer_setDeviceInfo(
     JNIEnv* env, jclass, jobject jDeviceInfo, jboolean magnified, jboolean inverted) {
+    using namespace teeui::example;
     jclass cDeviceInfo = env->FindClass("Lcom/android/framebufferizer/utils/DeviceInfo;");
     jmethodID method = env->GetMethodID(cDeviceInfo, "getWidthPx", "()I");
     DeviceInfo device_info;
@@ -149,7 +152,8 @@
     device_info.volUpButtonTopMm_ = env->CallDoubleMethod(jDeviceInfo, method);
     method = env->GetMethodID(cDeviceInfo, "getVolUpButtonBottomMm", "()D");
     device_info.volUpButtonBottomMm_ = env->CallDoubleMethod(jDeviceInfo, method);
-    return setDeviceInfo(device_info, magnified, inverted);
+    sCurrentExample = createExample(Examples::PhysButton);
+    return sCurrentExample->setDeviceInfo(device_info, magnified, inverted);
 }
 
 /*
@@ -161,9 +165,12 @@
     JNIEnv* env, jclass, jint x, jint y, jint width, jint height, jint lineStride,
     jintArray jbuffer) {
     JIntArray buffer(env, jbuffer);
-    if (!buffer) return 1;
-    return renderUIIntoBuffer((uint32_t)x, (uint32_t)y, (uint32_t)width, (uint32_t)height,
-                              (uint32_t)lineStride, (uint32_t*)buffer.begin(), buffer.size());
+    using namespace teeui::example;
+    if (!buffer) return kFrameBufferError;
+    if (!sCurrentExample) return kLayoutExampleError;
+    return sCurrentExample->renderUIIntoBuffer((uint32_t)x, (uint32_t)y, (uint32_t)width,
+                                               (uint32_t)height, (uint32_t)lineStride,
+                                               (uint32_t*)buffer.begin(), buffer.size());
 }
 /*
  * Class:     com_android_confirmationui_Translation_selectLangID
@@ -172,10 +179,8 @@
  */
 extern "C" JNIEXPORT void JNICALL
 Java_com_android_framebufferizer_NativeRenderer_setLanguage(JNIEnv* env, jclass, jstring jlang_id) {
-    jboolean isCopy = false;
-    const char* lang_id = (env)->GetStringUTFChars(jlang_id, &isCopy);
-    selectLanguage(lang_id);
-    (env)->ReleaseStringUTFChars(jlang_id, lang_id);
+    JString lang_id(env, jlang_id);
+    if (sCurrentExample) sCurrentExample->selectLanguage(lang_id.begin());
 }
 /*
  * Class:     com_android_confirmationui_Translation_selectLangID
@@ -206,5 +211,5 @@
 Java_com_android_framebufferizer_NativeRenderer_setConfimationMessage(
     JNIEnv* env, jclass, jstring jConfirmationMessage) {
     JString confirmationMessage(env, jConfirmationMessage);
-    setConfirmationMessage(confirmationMessage.begin());
+    if (sCurrentExample) sCurrentExample->setConfirmationMessage(confirmationMessage.begin());
 }
diff --git a/tools/framebufferizer/src/com/android/framebufferizer/utils/FrameBufferBuffer.java b/tools/framebufferizer/src/com/android/framebufferizer/utils/FrameBufferBuffer.java
index e627e47..6953f77 100644
--- a/tools/framebufferizer/src/com/android/framebufferizer/utils/FrameBufferBuffer.java
+++ b/tools/framebufferizer/src/com/android/framebufferizer/utils/FrameBufferBuffer.java
@@ -332,11 +332,12 @@
     }
 
     public void renderNativeBuffer() {
+        final int LAYOUT_EXAMPLE_ERROR = -2;
+        final int FRAME_BUFFER_ERROR = -1;
         DeviceInfo deviceInfo = DeviceInfoDB.getDeviceInfo(getConfigSelector().currentDevice());
         boolean magnified = getConfigSelector().magnified();
         boolean inverted = getConfigSelector().inverted();
-        NativeRenderer.setLanguage(getConfigSelector().currentLocale());
-        NativeRenderer.setConfimationMessage(getConfigSelector().confirmationMessage());
+
         int w = deviceInfo.getWidthPx();
         int h = deviceInfo.getHeightPx();
         final int linestride = w;
@@ -352,8 +353,14 @@
             ColorModel colorModel = new DirectColorModel(bpp, rMask, gMask, bMask);
             BufferedImage image = new BufferedImage(colorModel, raster, true, null);
             NativeRenderer.setDeviceInfo(deviceInfo, magnified, inverted);
+            NativeRenderer.setLanguage(getConfigSelector().currentLocale());
+            NativeRenderer.setConfimationMessage(getConfigSelector().confirmationMessage());
             error = NativeRenderer.renderBuffer(0, 0, w, h, linestride, mBuffer.getData());
-            if (error != 0) {
+            if(error == FRAME_BUFFER_ERROR){
+                System.out.println("Error framebuffer not initilized " + error);
+            } else if(error == LAYOUT_EXAMPLE_ERROR){
+                System.out.println("Error layout example not initilized " + error);
+            } else if (error != 0) {
                 System.out.println("Error rendering native buffer " + error);
             }