1 /*
2 * Copyright (C) 2017 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 "AHardwareBufferTest.h"
18
19 #include <errno.h>
20 #include <sys/types.h>
21 #include <sys/socket.h>
22 #include <sys/un.h>
23 #include <unistd.h>
24
25 #include <sstream>
26 #include <string>
27
28 #include <android/hardware_buffer.h>
29 #define LOG_TAG "AHardwareBufferTest"
30 #include "NativeTestHelper.h"
31
32 namespace android {
33
34 //#define LOG_NDEBUG 0
35
36 #define BAD_VALUE -EINVAL
37 #define NO_ERROR 0
38
BuildHexFailureMessage(uint64_t expected,uint64_t actual,const char * type)39 static std::string BuildHexFailureMessage(uint64_t expected,
40 uint64_t actual, const char* type) {
41 std::ostringstream ss;
42 ss << type << " 0x" << std::hex << actual
43 << " does not match expected " << type << " 0x" << std::hex
44 << expected;
45 return ss.str();
46 }
47
BuildFailureMessage(uint32_t expected,uint32_t actual,const char * type)48 static std::string BuildFailureMessage(uint32_t expected,
49 uint32_t actual, const char* type) {
50 std::ostringstream ss;
51 ss << "Buffer " << type << " do not match" << ": " << actual << " != " << expected;
52 return ss.str();
53 }
54
CheckAHardwareBufferMatchesDesc(AHardwareBuffer * abuffer,const AHardwareBuffer_Desc & desc)55 static std::string CheckAHardwareBufferMatchesDesc(
56 AHardwareBuffer* abuffer, const AHardwareBuffer_Desc& desc) {
57 AHardwareBuffer_Desc bufferDesc;
58 AHardwareBuffer_describe(abuffer, &bufferDesc);
59 if (bufferDesc.width != desc.width)
60 return BuildFailureMessage(desc.width, bufferDesc.width, "widths");
61 if (bufferDesc.height != desc.height)
62 return BuildFailureMessage(desc.height, bufferDesc.height, "heights");
63 if (bufferDesc.layers != desc.layers)
64 return BuildFailureMessage(desc.layers, bufferDesc.layers, "layers");
65 if (bufferDesc.usage != desc.usage)
66 return BuildHexFailureMessage(desc.usage, bufferDesc.usage, "usage");
67 if (bufferDesc.format != desc.format)
68 return BuildFailureMessage(desc.format, bufferDesc.format, "formats");
69 return std::string();
70 }
71
SetUp()72 bool AHardwareBufferTest::SetUp() { return true; }
73
TearDown()74 void AHardwareBufferTest::TearDown() {}
75
76 // Test that passing in NULL values to allocate works as expected.
testAHardwareBuffer_allocate_FailsWithNullInput(JNIEnv * env)77 void AHardwareBufferTest::testAHardwareBuffer_allocate_FailsWithNullInput(JNIEnv* env) {
78 AHardwareBuffer* buffer;
79 AHardwareBuffer_Desc desc;
80
81 memset(&desc, 0, sizeof(AHardwareBuffer_Desc));
82
83 int res = AHardwareBuffer_allocate(&desc, NULL);
84 ASSERT_EQ(BAD_VALUE, res);
85 res = AHardwareBuffer_allocate(NULL, &buffer);
86 ASSERT_EQ(BAD_VALUE, res);
87 res = AHardwareBuffer_allocate(NULL, NULL);
88 ASSERT_EQ(BAD_VALUE, res);
89 }
90
91 // Test that passing in NULL values to allocate works as expected.
testAHardwareBuffer_allocate_BlobFormatRequiresHeight1(JNIEnv * env)92 void AHardwareBufferTest::testAHardwareBuffer_allocate_BlobFormatRequiresHeight1(JNIEnv* env) {
93 AHardwareBuffer* buffer;
94 AHardwareBuffer_Desc desc = {};
95
96 desc.width = 2;
97 desc.height = 4;
98 desc.layers = 1;
99 desc.usage = AHARDWAREBUFFER_USAGE_CPU_READ_RARELY;
100 desc.format = AHARDWAREBUFFER_FORMAT_BLOB;
101 int res = AHardwareBuffer_allocate(&desc, &buffer);
102 ASSERT_EQ(BAD_VALUE, res);
103
104 desc.height = 1;
105 res = AHardwareBuffer_allocate(&desc, &buffer);
106 ASSERT_EQ(NO_ERROR, res);
107 ASSERT_EQ(std::string(), CheckAHardwareBufferMatchesDesc(buffer, desc));
108 AHardwareBuffer_release(buffer);
109 buffer = NULL;
110 }
111
112 // Test that allocate can create an AHardwareBuffer correctly.
testAHardwareBuffer_allocate_Succeeds(JNIEnv * env)113 void AHardwareBufferTest::testAHardwareBuffer_allocate_Succeeds(JNIEnv* env) {
114 AHardwareBuffer* buffer = NULL;
115 AHardwareBuffer_Desc desc = {};
116
117 desc.width = 2;
118 desc.height = 4;
119 desc.layers = 1;
120 desc.usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
121 desc.format = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
122 int res = AHardwareBuffer_allocate(&desc, &buffer);
123 ASSERT_EQ(NO_ERROR, res);
124 ASSERT_EQ(std::string(), CheckAHardwareBufferMatchesDesc(buffer, desc));
125 AHardwareBuffer_release(buffer);
126 buffer = NULL;
127
128 desc.width = 4;
129 desc.height = 12;
130 desc.layers = 1;
131 desc.usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
132 desc.format = AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM;
133 res = AHardwareBuffer_allocate(&desc, &buffer);
134 ASSERT_EQ(NO_ERROR, res);
135 ASSERT_EQ(std::string(), CheckAHardwareBufferMatchesDesc(buffer, desc));
136 AHardwareBuffer_release(buffer);
137 }
138
testAHardwareBuffer_describe_Succeeds(JNIEnv * env)139 void AHardwareBufferTest::testAHardwareBuffer_describe_Succeeds(JNIEnv* env) {
140 AHardwareBuffer* buffer = NULL;
141 AHardwareBuffer_Desc desc = {};
142
143 desc.width = 2;
144 desc.height = 4;
145 desc.layers = 1;
146 desc.usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
147 desc.format = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
148 int res = AHardwareBuffer_allocate(&desc, &buffer);
149 ASSERT_EQ(NO_ERROR, res);
150
151 AHardwareBuffer_Desc expected_desc;
152 memset(&expected_desc, 0, sizeof(AHardwareBuffer_Desc));
153 AHardwareBuffer_describe(NULL, &desc);
154 ASSERT_EQ(0U, expected_desc.width);
155 AHardwareBuffer_describe(buffer, NULL);
156 ASSERT_EQ(0U, expected_desc.width);
157 AHardwareBuffer_describe(buffer, &desc);
158 ASSERT_EQ(std::string(), CheckAHardwareBufferMatchesDesc(buffer, desc));
159
160 AHardwareBuffer_release(buffer);
161 }
162
163 struct ClientData {
164 int fd;
165 JNIEnv* env;
166 AHardwareBuffer* buffer;
ClientDataandroid::ClientData167 ClientData(int fd_in, JNIEnv* env_in, AHardwareBuffer* buffer_in)
168 : fd(fd_in), env(env_in), buffer(buffer_in) {}
169 };
170
clientFunction(void * data)171 static void* clientFunction(void* data) {
172 ClientData* pdata = reinterpret_cast<ClientData*>(data);
173 int err = AHardwareBuffer_sendHandleToUnixSocket(pdata->buffer, pdata->fd);
174 if (err != NO_ERROR) {
175 fail(pdata->env, "Error sending handle to socket: %d", err);
176 }
177 close(pdata->fd);
178 return 0;
179 }
180
testAHardwareBuffer_SendAndRecv_Succeeds(JNIEnv * env)181 void AHardwareBufferTest::testAHardwareBuffer_SendAndRecv_Succeeds(JNIEnv* env) {
182 AHardwareBuffer* buffer = NULL;
183 AHardwareBuffer_Desc desc = {};
184
185 desc.width = 2;
186 desc.height = 4;
187 desc.layers = 1;
188 desc.usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
189 desc.format = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
190
191 // Test that an invalid buffer fails.
192 int err = AHardwareBuffer_sendHandleToUnixSocket(NULL, 0);
193 ASSERT_EQ(BAD_VALUE, err);
194 err = 0;
195 err = AHardwareBuffer_sendHandleToUnixSocket(buffer, 0);
196 ASSERT_EQ(BAD_VALUE, err);
197
198 // Allocate the buffer.
199 err = AHardwareBuffer_allocate(&desc, &buffer);
200 ASSERT_EQ(NO_ERROR, err);
201
202 int fds[2];
203 err = socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, fds);
204
205 // Launch a client that will send the buffer back.
206 ClientData data(fds[1], env, buffer);
207 pthread_t thread;
208 ASSERT_EQ(0, pthread_create(&thread, NULL, clientFunction, &data));
209
210 // Receive the buffer.
211 err = AHardwareBuffer_recvHandleFromUnixSocket(fds[0], NULL);
212 ASSERT_EQ(BAD_VALUE, err);
213
214 AHardwareBuffer* received = NULL;
215 err = AHardwareBuffer_recvHandleFromUnixSocket(fds[0], &received);
216 ASSERT_EQ(NO_ERROR, err);
217 ASSERT_TRUE(received != NULL);
218 ASSERT_EQ(std::string(), CheckAHardwareBufferMatchesDesc(received, desc));
219
220 void* ret_val;
221 ASSERT_EQ(0, pthread_join(thread, &ret_val));
222 ASSERT_EQ(NULL, ret_val);
223 close(fds[0]);
224
225 AHardwareBuffer_release(buffer);
226 AHardwareBuffer_release(received);
227 }
228
testAHardwareBuffer_Lock_and_Unlock_Succeed(JNIEnv * env)229 void AHardwareBufferTest::testAHardwareBuffer_Lock_and_Unlock_Succeed(JNIEnv* env) {
230 AHardwareBuffer* buffer = NULL;
231 AHardwareBuffer_Desc desc = {};
232
233 desc.width = 2;
234 desc.height = 4;
235 desc.layers = 1;
236 desc.usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE | AHARDWAREBUFFER_USAGE_CPU_READ_RARELY;
237 desc.format = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
238
239 // Test that an invalid buffer fails.
240 int err = AHardwareBuffer_lock(NULL, 0, -1, NULL, NULL);
241 ASSERT_EQ(BAD_VALUE, err);
242 err = 0;
243
244 // Allocate the buffer.
245 err = AHardwareBuffer_allocate(&desc, &buffer);
246 ASSERT_EQ(NO_ERROR, err);
247 void* bufferData = NULL;
248 err = AHardwareBuffer_lock(buffer, AHARDWAREBUFFER_USAGE_CPU_READ_RARELY, -1,
249 NULL, &bufferData);
250 ASSERT_EQ(NO_ERROR, err);
251 ASSERT_TRUE(bufferData != NULL);
252 int32_t fence = -1;
253 err = AHardwareBuffer_unlock(buffer, &fence);
254
255 AHardwareBuffer_release(buffer);
256 }
257
testAHardwareBufferSupportsLayeredBuffersForVr(JNIEnv * env)258 void AHardwareBufferTest::testAHardwareBufferSupportsLayeredBuffersForVr(JNIEnv* env) {
259 AHardwareBuffer* buffer = NULL;
260 AHardwareBuffer_Desc desc = {};
261
262 desc.width = 2;
263 desc.height = 4;
264 desc.layers = 2;
265 desc.usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
266 desc.format = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
267 int res = AHardwareBuffer_allocate(&desc, &buffer);
268 ASSERT_EQ(NO_ERROR, res);
269 ASSERT_EQ(std::string(), CheckAHardwareBufferMatchesDesc(buffer, desc));
270 AHardwareBuffer_release(buffer);
271 buffer = NULL;
272
273 desc.width = 4;
274 desc.height = 12;
275 desc.layers = 3;
276 desc.usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
277 desc.format = AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM;
278 res = AHardwareBuffer_allocate(&desc, &buffer);
279 ASSERT_EQ(NO_ERROR, res);
280 ASSERT_EQ(std::string(), CheckAHardwareBufferMatchesDesc(buffer, desc));
281 }
282
283 } // namespace android
284