1 /*
2  * Copyright (C) 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 #define TLOG_TAG "secure_fb_test"
18 
19 #include <lib/secure_fb/secure_fb.h>
20 #include <trusty/time.h>
21 #include <trusty_unittest.h>
22 #include <uapi/err.h>
23 
24 typedef struct {
25     secure_fb_handle_t session;
26     struct secure_fb_info fb_info;
27 } secure_fb_t;
28 
TEST_F_SETUP(secure_fb)29 TEST_F_SETUP(secure_fb) {
30     int rc;
31 
32     _state->session = 0;
33     rc = secure_fb_open(&_state->session, &_state->fb_info, 0);
34     ASSERT_EQ(rc, 0);
35 
36 test_abort:;
37 }
38 
TEST_F_TEARDOWN(secure_fb)39 TEST_F_TEARDOWN(secure_fb) {
40     secure_fb_close(_state->session);
41 }
42 
TEST_F(secure_fb,open_and_close)43 TEST_F(secure_fb, open_and_close) {
44     /* Only need Setup() and Teardown() to run. */
45 }
46 
TEST_F(secure_fb,fb_info)47 TEST_F(secure_fb, fb_info) {
48     struct secure_fb_info* fb_info = &_state->fb_info;
49 
50     EXPECT_NE(fb_info->buffer, NULL);
51     EXPECT_GT(fb_info->size, 0);
52     EXPECT_GT(fb_info->pixel_stride, 0);
53     EXPECT_GT(fb_info->line_stride, 0);
54     EXPECT_GT(fb_info->width, 0);
55     EXPECT_GT(fb_info->height, 0);
56     EXPECT_NE(fb_info->pixel_format, TTUI_PF_INVALID);
57 
58     EXPECT_LE(fb_info->width * fb_info->pixel_stride, fb_info->line_stride);
59     EXPECT_LE(fb_info->height * fb_info->line_stride, fb_info->size);
60 
61 test_abort:;
62 }
63 
64 /*
65  * Pixel colouring function.
66  * This divides the screen into 9 horizonal bars and then displays a blend
67  * from each channel into the other.  The first 3 bars blend from red, the
68  * second from green, the last 3 from blue.
69  */
set_pixel(uint8_t * pixel,const uint32_t x,const uint32_t y,const uint32_t w,const uint32_t h)70 static void set_pixel(uint8_t* pixel,
71                       const uint32_t x,
72                       const uint32_t y,
73                       const uint32_t w,
74                       const uint32_t h) {
75     const uint32_t bar_height = (h + 8) / 9;
76     const uint8_t bar = y / bar_height;
77     float rgb_left[3] = {0, 0, 0};
78     float rgb_right[3] = {0, 0, 0};
79 
80     rgb_left[bar / 3] = 1.0f;
81     rgb_right[bar % 3] = 1.0f;
82 
83     float blend = (float)x / (float)w;
84 
85     /* Set RGB */
86     for (uint8_t i = 0; i < 3; i++) {
87         float v = (rgb_left[i] * (1.0f - blend)) + (rgb_right[i] * blend);
88         *pixel = 255.0f * v;
89         pixel++;
90     }
91 
92     /* Set alpha */
93     *pixel = 0xff;
94 }
95 
TEST_F(secure_fb,display)96 TEST_F(secure_fb, display) {
97     int rc;
98     const struct secure_fb_info* fb_info = &_state->fb_info;
99 
100     ASSERT_EQ(fb_info->pixel_format, TTUI_PF_RGBA8);
101 
102     for (uint32_t y = 0; y < fb_info->height; y++) {
103         uint8_t* pixel = &fb_info->buffer[y * fb_info->line_stride];
104 
105         for (uint32_t x = 0; x < fb_info->width; x++) {
106             set_pixel(pixel, x, y, fb_info->width, fb_info->height);
107             pixel += fb_info->pixel_stride;
108         }
109     }
110 
111     rc = secure_fb_display_next(_state->session, &_state->fb_info);
112     ASSERT_EQ(rc, 0);
113 
114     /* Wait 2 seconds to allow screen to be viewed */
115     trusty_nanosleep(0, 0, 2000 * 1000 * 1000);
116 
117 test_abort:;
118 }
119 
TEST(secure_fb,stress)120 TEST(secure_fb, stress) {
121     secure_fb_handle_t session = NULL;
122     struct secure_fb_info fb_info;
123     int i, rc;
124 
125     for (i = 0; i < 256; i++) {
126         rc = secure_fb_open(&session, &fb_info, 0);
127         ASSERT_EQ(rc, 0);
128 
129         /* Fill with grey level */
130         memset(fb_info.buffer, i, fb_info.size);
131 
132         rc = secure_fb_display_next(session, &fb_info);
133         ASSERT_EQ(rc, 0);
134 
135         secure_fb_close(session);
136         session = NULL;
137     }
138 
139     return;
140 
141 test_abort:
142     trusty_unittest_printf("[   INFO   ] failed after %d iterations\n", i);
143 
144     if (session) {
145         secure_fb_close(session);
146     }
147 }
148 
149 PORT_TEST(secure_fb, "com.android.trusty.secure_fb.test");
150