secure_fb_mock_impl: Add mock implementation of secure_fb service

Implement a mock backend for the secure_fb service.

Bug: 175731623
Change-Id: Ide15d2350904d15d3c80f95c2764cd1254f2ff2b
diff --git a/secure_fb_mock_impl/main.cpp b/secure_fb_mock_impl/main.cpp
new file mode 100644
index 0000000..58f5925
--- /dev/null
+++ b/secure_fb_mock_impl/main.cpp
@@ -0,0 +1,160 @@
+/*
+ * 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.
+ */
+
+#define TLOG_TAG "secure_fb_impl"
+
+#include <lib/secure_fb/srv/dev.h>
+#include <lib/secure_fb/srv/srv.h>
+#include <lib/tipc/tipc.h>
+#include <lk/err_ptr.h>
+#include <lk/macros.h>
+#include <memref.h>
+#include <sys/auxv.h>
+#include <sys/mman.h>
+#include <trusty_ipc.h>
+#include <trusty_log.h>
+
+#include <tuple>
+
+#define PAGE_SIZE() (getauxval(AT_PAGESZ))
+
+static constexpr const uint32_t kDeviceWidth = 400;
+static constexpr const uint32_t kDeviceHeight = 800;
+static constexpr const uint32_t kFbCount = 1;
+static constexpr const uint32_t kFbId = 0xdeadbeef;
+
+class SecureFbMockImpl {
+private:
+    struct FbDbEntry {
+        secure_fb_info fb_info;
+        handle_t handle;
+        ptrdiff_t offset;
+    };
+
+    FbDbEntry fb_db_[kFbCount];
+
+public:
+    int Init(uint32_t width, uint32_t height) {
+        uint32_t fb_size =
+                round_up(sizeof(uint32_t) * width * height, PAGE_SIZE());
+        /*
+         * Every secure_fb client (of which there can only be one at a time)
+         * gets the same framebuffer memory. We do this so to prevent running
+         * out of memory as the number of connections to secure_fb server grows
+         * over time.
+         */
+        static void* fb_base = memalign(PAGE_SIZE(), fb_size);
+        if (!fb_base) {
+            TLOGE("Failed to allocate framebuffer of size: %u\n", fb_size);
+            return SECURE_FB_ERROR_MEMORY_ALLOCATION;
+        }
+
+        /*
+         * Create a handle for the buffer by which it can be passed to the TUI
+         * app for rendering.
+         */
+        static int handle =
+                memref_create(fb_base, fb_size, PROT_READ | PROT_WRITE);
+        if (handle < 0) {
+            TLOGE("Failed to create memref (%d)\n", handle);
+            free(fb_base);
+            return SECURE_FB_ERROR_SHARED_MEMORY;
+        }
+
+        fb_db_[0] = {
+                .fb_info =
+                        {
+                                .buffer = (uint8_t*)fb_base,
+                                .size = fb_size,
+                                .pixel_stride = 4,
+                                .line_stride = 4 * width,
+                                .width = width,
+                                .height = height,
+                                .pixel_format = TTUI_PF_RGBA8,
+                        },
+                .handle = handle,
+        };
+
+        return SECURE_FB_ERROR_OK;
+    }
+
+    int GetFbs(struct secure_fb_impl_buffers* buffers) {
+        *buffers = {
+                .num_fbs = 1,
+                .fbs[0] =
+                        {
+                                .buffer_id = kFbId,
+                                .handle_index = 0,
+                                .fb_info = fb_db_[0].fb_info,
+                        },
+                .num_handles = 1,
+                .handles[0] = fb_db_[0].handle,
+        };
+        return SECURE_FB_ERROR_OK;
+    }
+
+    int Display(uint32_t buffer_id) {
+        if (buffer_id != kFbId) {
+            return SECURE_FB_ERROR_INVALID_REQUEST;
+        }
+
+        /* This is a no-op in the mock case. */
+        return SECURE_FB_ERROR_OK;
+    }
+};
+
+secure_fb_handle_t secure_fb_impl_init() {
+    auto sfb = new SecureFbMockImpl();
+    sfb->Init(kDeviceWidth, kDeviceHeight);
+    return sfb;
+}
+
+int secure_fb_impl_get_fbs(secure_fb_handle_t sfb_handle,
+                           struct secure_fb_impl_buffers* buffers) {
+    SecureFbMockImpl* sfb = reinterpret_cast<SecureFbMockImpl*>(sfb_handle);
+    return sfb->GetFbs(buffers);
+}
+
+int secure_fb_impl_display_fb(secure_fb_handle_t sfb_handle,
+                              uint32_t buffer_id) {
+    SecureFbMockImpl* sfb = reinterpret_cast<SecureFbMockImpl*>(sfb_handle);
+    return sfb->Display(buffer_id);
+}
+
+int secure_fb_impl_release(secure_fb_handle_t sfb_handle) {
+    SecureFbMockImpl* sfb = reinterpret_cast<SecureFbMockImpl*>(sfb_handle);
+    delete sfb;
+    return SECURE_FB_ERROR_OK;
+}
+
+int main(void) {
+    int rc;
+    struct tipc_hset* hset;
+
+    hset = tipc_hset_create();
+    if (IS_ERR(hset)) {
+        TLOGE("failed (%d) to create handle set\n", PTR_ERR(hset));
+        return PTR_ERR(hset);
+    }
+
+    rc = add_secure_fb_service(hset);
+    if (rc != NO_ERROR) {
+        TLOGE("failed (%d) to initialize secure_fb mock service\n", rc);
+        return rc;
+    }
+
+    return tipc_run_event_loop(hset);
+}
diff --git a/secure_fb_mock_impl/manifest.json b/secure_fb_mock_impl/manifest.json
new file mode 100644
index 0000000..b70efdd
--- /dev/null
+++ b/secure_fb_mock_impl/manifest.json
@@ -0,0 +1,5 @@
+{
+    "uuid": "405729b4-c12d-45d9-ae97-0f25aaa204e4",
+    "min_heap": 2097152,
+    "min_stack": 4096
+}
diff --git a/secure_fb_mock_impl/rules.mk b/secure_fb_mock_impl/rules.mk
new file mode 100644
index 0000000..f38f56b
--- /dev/null
+++ b/secure_fb_mock_impl/rules.mk
@@ -0,0 +1,33 @@
+# Copyright (C) 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.
+
+LOCAL_DIR := $(GET_LOCAL_DIR)
+
+MODULE := $(LOCAL_DIR)
+
+MANIFEST := $(LOCAL_DIR)/manifest.json
+
+MODULE_INCLUDES	+= \
+	$(LOCAL_DIR)/include \
+
+MODULE_SRCS += \
+	$(LOCAL_DIR)/main.cpp \
+
+MODULE_DEPS += \
+	trusty/user/base/lib/libc-trusty \
+	trusty/user/base/lib/libstdc++-trusty \
+	trusty/user/base/lib/tipc \
+	trusty/user/base/lib/secure_fb/srv \
+
+include make/module.mk