1 /*
2 * Copyright 2018 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 LOG_TAG "ASurfaceControlTest"
18
19 #include <ChoreographerTestUtils.h>
20 #include <android/choreographer.h>
21 #include <android/data_space.h>
22 #include <android/hardware_buffer.h>
23 #include <android/hardware_buffer_jni.h>
24 #include <android/log.h>
25 #include <android/looper.h>
26 #include <android/native_window_jni.h>
27 #include <android/surface_control.h>
28 #include <android/surface_control_jni.h>
29 #include <android/sync.h>
30 #include <android/trace.h>
31 #include <errno.h>
32 #include <jni.h>
33 #include <poll.h>
34 #include <sys/time.h>
35 #include <sys/types.h>
36 #include <time.h>
37 #include <unistd.h>
38
39 #include <array>
40 #include <cinttypes>
41 #include <string>
42
43 #define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
44
45 namespace {
46
47 static struct {
48 jclass clazz;
49 jmethodID onTransactionComplete;
50 } gTransactionCompleteListenerClassInfo;
51
allocateBuffer(int32_t width,int32_t height)52 static AHardwareBuffer* allocateBuffer(int32_t width, int32_t height) {
53 AHardwareBuffer* buffer = nullptr;
54 AHardwareBuffer_Desc desc = {};
55 desc.width = width;
56 desc.height = height;
57 desc.layers = 1;
58 desc.usage = AHARDWAREBUFFER_USAGE_COMPOSER_OVERLAY | AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN |
59 AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
60 desc.format = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
61
62 AHardwareBuffer_allocate(&desc, &buffer);
63
64 return buffer;
65 }
66
fillRegion(void * data,int32_t left,int32_t top,int32_t right,int32_t bottom,uint32_t color,uint32_t stride)67 static void fillRegion(void* data, int32_t left, int32_t top, int32_t right,
68 int32_t bottom, uint32_t color, uint32_t stride) {
69 uint32_t* ptr = static_cast<uint32_t*>(data);
70
71 ptr += stride * top;
72
73 // Convert color from incoming ARGB format to ABGR
74 uint32_t alpha = (color >> 24);
75 uint32_t red = (color >> 16) & 0xff;
76 uint32_t green = (color >> 8) & 0xff;
77 uint32_t blue = color & 0xff;
78 color = (alpha << 24) | (blue << 16) | (green << 8) | red;
79
80 for (uint32_t y = top; y < bottom; y++) {
81 for (uint32_t x = left; x < right; x++) {
82 ptr[x] = color;
83 }
84 ptr += stride;
85 }
86 }
87
getSolidBuffer(int32_t width,int32_t height,uint32_t color,AHardwareBuffer ** outHardwareBuffer,int * outFence)88 static bool getSolidBuffer(int32_t width, int32_t height, uint32_t color,
89 AHardwareBuffer** outHardwareBuffer,
90 int* outFence) {
91 AHardwareBuffer* buffer = allocateBuffer(width, height);
92 if (!buffer) {
93 return true;
94 }
95
96 AHardwareBuffer_Desc desc = {};
97 AHardwareBuffer_describe(buffer, &desc);
98
99 void* data = nullptr;
100 const ARect rect{0, 0, width, height};
101 AHardwareBuffer_lock(buffer, AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN, -1, &rect,
102 &data);
103 if (!data) {
104 AHardwareBuffer_release(buffer);
105 return true;
106 }
107
108 fillRegion(data, 0, 0, width, height, color, desc.stride);
109
110 AHardwareBuffer_unlock(buffer, outFence);
111
112 *outHardwareBuffer = buffer;
113 return false;
114 }
115
Utils_getSolidBuffer(JNIEnv * env,jobject,jint width,jint height,jint color)116 jobject Utils_getSolidBuffer(JNIEnv* env, jobject /*clazz*/, jint width, jint height, jint color) {
117 AHardwareBuffer* buffer;
118 if (getSolidBuffer(width, height, static_cast<uint32_t>(color), &buffer, nullptr)) {
119 return nullptr;
120 }
121 jobject result = AHardwareBuffer_toHardwareBuffer(env, buffer);
122 AHardwareBuffer_release(buffer);
123 return result;
124 }
125
getQuadrantBuffer(int32_t width,int32_t height,jint colorTopLeft,jint colorTopRight,jint colorBottomRight,jint colorBottomLeft,AHardwareBuffer ** outHardwareBuffer,int * outFence)126 static bool getQuadrantBuffer(int32_t width, int32_t height, jint colorTopLeft,
127 jint colorTopRight, jint colorBottomRight,
128 jint colorBottomLeft,
129 AHardwareBuffer** outHardwareBuffer,
130 int* outFence) {
131 AHardwareBuffer* buffer = allocateBuffer(width, height);
132 if (!buffer) {
133 return true;
134 }
135
136 AHardwareBuffer_Desc desc = {};
137 AHardwareBuffer_describe(buffer, &desc);
138
139 void* data = nullptr;
140 const ARect rect{0, 0, width, height};
141 AHardwareBuffer_lock(buffer, AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN, -1, &rect,
142 &data);
143 if (!data) {
144 return true;
145 }
146
147 fillRegion(data, 0, 0, width / 2, height / 2, colorTopLeft, desc.stride);
148 fillRegion(data, width / 2, 0, width, height / 2, colorTopRight, desc.stride);
149 fillRegion(data, 0, height / 2, width / 2, height, colorBottomLeft,
150 desc.stride);
151 fillRegion(data, width / 2, height / 2, width, height, colorBottomRight,
152 desc.stride);
153
154 AHardwareBuffer_unlock(buffer, outFence);
155
156 *outHardwareBuffer = buffer;
157 return false;
158 }
159
Utils_getQuadrantBuffer(JNIEnv * env,jobject,jint width,jint height,jint colorTopLeft,jint colorTopRight,jint colorBottomRight,jint colorBottomLeft)160 jobject Utils_getQuadrantBuffer(JNIEnv* env, jobject /*clazz*/, jint width, jint height,
161 jint colorTopLeft, jint colorTopRight, jint colorBottomRight,
162 jint colorBottomLeft) {
163 AHardwareBuffer* buffer;
164 if (getQuadrantBuffer(width, height, colorTopLeft, colorTopRight, colorBottomRight,
165 colorBottomLeft, &buffer, nullptr)) {
166 return nullptr;
167 }
168 jobject result = AHardwareBuffer_toHardwareBuffer(env, buffer);
169 AHardwareBuffer_release(buffer);
170 return result;
171 }
172
Utils_getBufferId(JNIEnv * env,jobject,jobject jHardwareBuffer)173 jlong Utils_getBufferId(JNIEnv* env, jobject /*clazz*/, jobject jHardwareBuffer) {
174 AHardwareBuffer* buffer = AHardwareBuffer_fromHardwareBuffer(env, jHardwareBuffer);
175 uint64_t id = 0;
176 AHardwareBuffer_getId(buffer, &id);
177 return id;
178 }
179
SurfaceTransaction_create(JNIEnv *,jclass)180 jlong SurfaceTransaction_create(JNIEnv* /*env*/, jclass) {
181 return reinterpret_cast<jlong>(ASurfaceTransaction_create());
182 }
183
SurfaceTransaction_delete(JNIEnv *,jclass,jlong surfaceTransaction)184 void SurfaceTransaction_delete(JNIEnv* /*env*/, jclass, jlong surfaceTransaction) {
185 ASurfaceTransaction_delete(
186 reinterpret_cast<ASurfaceTransaction*>(surfaceTransaction));
187 }
188
SurfaceTransaction_fromJava(JNIEnv * env,jclass,jobject transactionObj)189 jlong SurfaceTransaction_fromJava(JNIEnv* env, jclass, jobject transactionObj) {
190 return reinterpret_cast<jlong>(ASurfaceTransaction_fromJava(env, transactionObj));
191 }
192
SurfaceTransaction_apply(JNIEnv *,jclass,jlong surfaceTransaction)193 void SurfaceTransaction_apply(JNIEnv* /*env*/, jclass, jlong surfaceTransaction) {
194 ASurfaceTransaction_apply(
195 reinterpret_cast<ASurfaceTransaction*>(surfaceTransaction));
196 }
197
SurfaceControl_createFromWindow(JNIEnv * env,jclass,jobject jSurface)198 long SurfaceControl_createFromWindow(JNIEnv* env, jclass, jobject jSurface) {
199 if (!jSurface) {
200 return 0;
201 }
202
203 ANativeWindow* window = ANativeWindow_fromSurface(env, jSurface);
204 if (!window) {
205 return 0;
206 }
207
208 const std::string debugName = "SurfaceControl_createFromWindowLayer";
209 ASurfaceControl* surfaceControl =
210 ASurfaceControl_createFromWindow(window, debugName.c_str());
211 if (!surfaceControl) {
212 return 0;
213 }
214
215 ANativeWindow_release(window);
216
217 return reinterpret_cast<jlong>(surfaceControl);
218 }
219
SurfaceControl_create(JNIEnv *,jclass,jlong parentSurfaceControlId)220 jlong SurfaceControl_create(JNIEnv* /*env*/, jclass, jlong parentSurfaceControlId) {
221 ASurfaceControl* surfaceControl = nullptr;
222 const std::string debugName = "SurfaceControl_create";
223
224 surfaceControl = ASurfaceControl_create(
225 reinterpret_cast<ASurfaceControl*>(parentSurfaceControlId),
226 debugName.c_str());
227
228 return reinterpret_cast<jlong>(surfaceControl);
229 }
230
SurfaceControl_acquire(JNIEnv *,jclass,jlong surfaceControl)231 void SurfaceControl_acquire(JNIEnv* /*env*/, jclass, jlong surfaceControl) {
232 ASurfaceControl_acquire(reinterpret_cast<ASurfaceControl*>(surfaceControl));
233 }
234
SurfaceControl_fromJava(JNIEnv * env,jclass,jobject surfaceControlObj)235 jlong SurfaceControl_fromJava(JNIEnv* env, jclass, jobject surfaceControlObj) {
236 return reinterpret_cast<jlong>(ASurfaceControl_fromJava(env, surfaceControlObj));
237 }
238
SurfaceControl_release(JNIEnv *,jclass,jlong surfaceControl)239 void SurfaceControl_release(JNIEnv* /*env*/, jclass, jlong surfaceControl) {
240 ASurfaceControl_release(reinterpret_cast<ASurfaceControl*>(surfaceControl));
241 }
242
SurfaceTransaction_setSolidBuffer(JNIEnv *,jclass,jlong surfaceControl,jlong surfaceTransaction,jint width,jint height,jint color)243 jlong SurfaceTransaction_setSolidBuffer(JNIEnv* /*env*/, jclass,
244 jlong surfaceControl,
245 jlong surfaceTransaction, jint width,
246 jint height, jint color) {
247 AHardwareBuffer* buffer = nullptr;
248 int fence = -1;
249
250 bool err = getSolidBuffer(width, height, color, &buffer, &fence);
251 if (err) {
252 return 0;
253 }
254
255 ASurfaceTransaction_setBuffer(
256 reinterpret_cast<ASurfaceTransaction*>(surfaceTransaction),
257 reinterpret_cast<ASurfaceControl*>(surfaceControl), buffer, fence);
258
259 ASurfaceTransaction_setBufferDataSpace(
260 reinterpret_cast<ASurfaceTransaction*>(surfaceTransaction),
261 reinterpret_cast<ASurfaceControl*>(surfaceControl), ADATASPACE_UNKNOWN);
262
263 return reinterpret_cast<jlong>(buffer);
264 }
265
SurfaceTransaction_setBuffer(JNIEnv *,jclass,jlong surfaceControl,jlong surfaceTransaction,jlong buffer)266 void SurfaceTransaction_setBuffer(JNIEnv* /*env*/, jclass, jlong surfaceControl,
267 jlong surfaceTransaction, jlong buffer) {
268 ASurfaceTransaction_setBuffer(reinterpret_cast<ASurfaceTransaction*>(surfaceTransaction),
269 reinterpret_cast<ASurfaceControl*>(surfaceControl),
270 reinterpret_cast<AHardwareBuffer*>(buffer), -1 /* fence */);
271
272 ASurfaceTransaction_setBufferDataSpace(reinterpret_cast<ASurfaceTransaction*>(
273 surfaceTransaction),
274 reinterpret_cast<ASurfaceControl*>(surfaceControl),
275 ADATASPACE_UNKNOWN);
276 }
277
SurfaceTransaction_setQuadrantBuffer(JNIEnv *,jclass,jlong surfaceControl,jlong surfaceTransaction,jint width,jint height,jint colorTopLeft,jint colorTopRight,jint colorBottomRight,jint colorBottomLeft)278 jlong SurfaceTransaction_setQuadrantBuffer(
279 JNIEnv* /*env*/, jclass, jlong surfaceControl, jlong surfaceTransaction,
280 jint width, jint height, jint colorTopLeft, jint colorTopRight,
281 jint colorBottomRight, jint colorBottomLeft) {
282 AHardwareBuffer* buffer = nullptr;
283 int fence = -1;
284
285 bool err =
286 getQuadrantBuffer(width, height, colorTopLeft, colorTopRight,
287 colorBottomRight, colorBottomLeft, &buffer, &fence);
288 if (err) {
289 return 0;
290 }
291
292 ASurfaceTransaction_setBuffer(
293 reinterpret_cast<ASurfaceTransaction*>(surfaceTransaction),
294 reinterpret_cast<ASurfaceControl*>(surfaceControl), buffer, fence);
295
296 ASurfaceTransaction_setBufferDataSpace(
297 reinterpret_cast<ASurfaceTransaction*>(surfaceTransaction),
298 reinterpret_cast<ASurfaceControl*>(surfaceControl), ADATASPACE_UNKNOWN);
299
300 return reinterpret_cast<jlong>(buffer);
301 }
302
SurfaceTransaction_releaseBuffer(JNIEnv *,jclass,jlong buffer)303 void SurfaceTransaction_releaseBuffer(JNIEnv* /*env*/, jclass, jlong buffer) {
304 AHardwareBuffer_release(reinterpret_cast<AHardwareBuffer*>(buffer));
305 }
306
SurfaceTransaction_setVisibility(JNIEnv *,jclass,jlong surfaceControl,jlong surfaceTransaction,jboolean show)307 void SurfaceTransaction_setVisibility(JNIEnv* /*env*/, jclass,
308 jlong surfaceControl,
309 jlong surfaceTransaction, jboolean show) {
310 auto visibility = (show) ? ASURFACE_TRANSACTION_VISIBILITY_SHOW :
311 ASURFACE_TRANSACTION_VISIBILITY_HIDE;
312 ASurfaceTransaction_setVisibility(
313 reinterpret_cast<ASurfaceTransaction*>(surfaceTransaction),
314 reinterpret_cast<ASurfaceControl*>(surfaceControl), visibility);
315 }
316
SurfaceTransaction_setBufferOpaque(JNIEnv *,jclass,jlong surfaceControl,jlong surfaceTransaction,jboolean opaque)317 void SurfaceTransaction_setBufferOpaque(JNIEnv* /*env*/, jclass,
318 jlong surfaceControl,
319 jlong surfaceTransaction,
320 jboolean opaque) {
321 auto transparency = (opaque) ? ASURFACE_TRANSACTION_TRANSPARENCY_OPAQUE :
322 ASURFACE_TRANSACTION_TRANSPARENCY_TRANSPARENT;
323 ASurfaceTransaction_setBufferTransparency(
324 reinterpret_cast<ASurfaceTransaction*>(surfaceTransaction),
325 reinterpret_cast<ASurfaceControl*>(surfaceControl), transparency);
326 }
327
SurfaceTransaction_setGeometry(JNIEnv *,jclass,jlong surfaceControl,jlong surfaceTransaction,jint srcLeft,jint srcTop,jint srcRight,jint srcBottom,jint dstLeft,jint dstTop,jint dstRight,jint dstBottom,jint transform)328 void SurfaceTransaction_setGeometry(JNIEnv* /*env*/, jclass,
329 jlong surfaceControl,
330 jlong surfaceTransaction,
331 jint srcLeft, jint srcTop, jint srcRight, jint srcBottom,
332 jint dstLeft, jint dstTop, jint dstRight, jint dstBottom,
333 jint transform) {
334 const ARect src{srcLeft, srcTop, srcRight, srcBottom};
335 const ARect dst{dstLeft, dstTop, dstRight, dstBottom};
336 ASurfaceTransaction_setGeometry(
337 reinterpret_cast<ASurfaceTransaction*>(surfaceTransaction),
338 reinterpret_cast<ASurfaceControl*>(surfaceControl), src, dst, transform);
339 }
340
SurfaceTransaction_setCrop(JNIEnv *,jclass,jlong surfaceControl,jlong surfaceTransaction,jint left,jint top,jint right,jint bottom)341 void SurfaceTransaction_setCrop(JNIEnv* /*env*/, jclass, jlong surfaceControl,
342 jlong surfaceTransaction, jint left, jint top, jint right,
343 jint bottom) {
344 const ARect crop{left, top, right, bottom};
345 ASurfaceTransaction_setCrop(reinterpret_cast<ASurfaceTransaction*>(surfaceTransaction),
346 reinterpret_cast<ASurfaceControl*>(surfaceControl), crop);
347 }
348
SurfaceTransaction_setPosition(JNIEnv *,jclass,jlong surfaceControl,jlong surfaceTransaction,jint x,jint y)349 void SurfaceTransaction_setPosition(JNIEnv* /*env*/, jclass, jlong surfaceControl,
350 jlong surfaceTransaction, jint x, jint y) {
351 ASurfaceTransaction_setPosition(reinterpret_cast<ASurfaceTransaction*>(surfaceTransaction),
352 reinterpret_cast<ASurfaceControl*>(surfaceControl), x, y);
353 }
354
SurfaceTransaction_setBufferTransform(JNIEnv *,jclass,jlong surfaceControl,jlong surfaceTransaction,jint transform)355 void SurfaceTransaction_setBufferTransform(JNIEnv* /*env*/, jclass, jlong surfaceControl,
356 jlong surfaceTransaction, jint transform) {
357 ASurfaceTransaction_setBufferTransform(reinterpret_cast<ASurfaceTransaction*>(
358 surfaceTransaction),
359 reinterpret_cast<ASurfaceControl*>(surfaceControl),
360 transform);
361 }
362
SurfaceTransaction_setScale(JNIEnv *,jclass,jlong surfaceControl,jlong surfaceTransaction,jfloat xScale,jfloat yScale)363 void SurfaceTransaction_setScale(JNIEnv* /*env*/, jclass, jlong surfaceControl,
364 jlong surfaceTransaction, jfloat xScale, jfloat yScale) {
365 ASurfaceTransaction_setScale(reinterpret_cast<ASurfaceTransaction*>(surfaceTransaction),
366 reinterpret_cast<ASurfaceControl*>(surfaceControl), xScale,
367 yScale);
368 }
369
SurfaceTransaction_setDamageRegion(JNIEnv *,jclass,jlong surfaceControl,jlong surfaceTransaction,jint left,jint top,jint right,jint bottom)370 void SurfaceTransaction_setDamageRegion(JNIEnv* /*env*/, jclass,
371 jlong surfaceControl,
372 jlong surfaceTransaction, jint left,
373 jint top, jint right, jint bottom) {
374 const ARect rect[] = {{left, top, right, bottom}};
375 ASurfaceTransaction_setDamageRegion(
376 reinterpret_cast<ASurfaceTransaction*>(surfaceTransaction),
377 reinterpret_cast<ASurfaceControl*>(surfaceControl), rect, 1);
378 }
379
SurfaceTransaction_setZOrder(JNIEnv *,jclass,jlong surfaceControl,jlong surfaceTransaction,jint z)380 void SurfaceTransaction_setZOrder(JNIEnv* /*env*/, jclass, jlong surfaceControl,
381 jlong surfaceTransaction, jint z) {
382 ASurfaceTransaction_setZOrder(
383 reinterpret_cast<ASurfaceTransaction*>(surfaceTransaction),
384 reinterpret_cast<ASurfaceControl*>(surfaceControl), z);
385 }
386
387 class CallbackListenerWrapper {
388 public:
CallbackListenerWrapper(JNIEnv * env,jobject object,bool waitForFence)389 explicit CallbackListenerWrapper(JNIEnv* env, jobject object, bool waitForFence) {
390 env->GetJavaVM(&mVm);
391 mCallbackListenerObject = env->NewGlobalRef(object);
392 mWaitForFence = waitForFence;
393 if (!mCallbackListenerObject) {
394 ALOGE("Failed to make global ref");
395 }
396 }
397
~CallbackListenerWrapper()398 ~CallbackListenerWrapper() { getenv()->DeleteGlobalRef(mCallbackListenerObject); }
399
400 /**
401 * This is duplicate code from sync.c, but the sync_wait function is not exposed to the ndk.
402 * The documentation recommends using poll instead of exposing sync_wait, but the sync_wait
403 * also handles errors and retries so copied the code here.
404 */
sync_wait(int fd,int timeout)405 static int sync_wait(int fd, int timeout) {
406 struct pollfd fds;
407 int ret;
408
409 if (fd < 0) {
410 errno = EINVAL;
411 return -1;
412 }
413
414 fds.fd = fd;
415 fds.events = POLLIN;
416
417 do {
418 ret = poll(&fds, 1, timeout);
419 if (ret > 0) {
420 if (fds.revents & (POLLERR | POLLNVAL)) {
421 errno = EINVAL;
422 return -1;
423 }
424 return 0;
425 } else if (ret == 0) {
426 errno = ETIME;
427 return -1;
428 }
429 } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
430
431 return ret;
432 }
433
getPresentTime(int presentFence)434 static uint64_t getPresentTime(int presentFence) {
435 uint64_t presentTime = 0;
436 int error = sync_wait(presentFence, 500);
437 if (error < 0) {
438 ALOGE("Failed to sync fence error=%d", error);
439 return 0;
440 }
441
442 struct sync_file_info* syncFileInfo = sync_file_info(presentFence);
443 if (!syncFileInfo) {
444 ALOGE("invalid fence");
445 sync_file_info_free(syncFileInfo);
446 return 0;
447 }
448
449 if (syncFileInfo->status != 1) {
450 ALOGE("fence did not signal status=%d", syncFileInfo->status);
451 return 0;
452 }
453
454 struct sync_fence_info* syncFenceInfo = sync_get_fence_info(syncFileInfo);
455 for (size_t i = 0; i < syncFileInfo->num_fences; i++) {
456 if (syncFenceInfo[i].timestamp_ns > presentTime) {
457 presentTime = syncFenceInfo[i].timestamp_ns;
458 }
459 }
460
461 sync_file_info_free(syncFileInfo);
462 close(presentFence);
463 return presentTime;
464 }
465
callback(ASurfaceTransactionStats * stats)466 void callback(ASurfaceTransactionStats* stats) {
467 JNIEnv* env = getenv();
468 int64_t latchTime = ASurfaceTransactionStats_getLatchTime(stats);
469 uint64_t presentTime = systemTime();
470 if (mWaitForFence) {
471 int presentFence = ASurfaceTransactionStats_getPresentFenceFd(stats);
472 if (presentFence >= 0) {
473 presentTime = getPresentTime(presentFence);
474 }
475 }
476 env->CallVoidMethod(mCallbackListenerObject,
477 gTransactionCompleteListenerClassInfo.onTransactionComplete, latchTime,
478 presentTime);
479 }
480
transactionCallbackThunk(void * context,ASurfaceTransactionStats * stats)481 static void transactionCallbackThunk(void* context, ASurfaceTransactionStats* stats) {
482 CallbackListenerWrapper* listener = reinterpret_cast<CallbackListenerWrapper*>(context);
483 listener->callback(stats);
484 delete listener;
485 }
486
487 private:
488 jobject mCallbackListenerObject;
489 JavaVM* mVm;
490 bool mWaitForFence;
491
getenv()492 JNIEnv* getenv() {
493 JNIEnv* env;
494 mVm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6);
495 return env;
496 }
497 };
498
SurfaceTransaction_setDesiredPresentTime(JNIEnv *,jclass,jlong surfaceTransaction,jlong desiredPresentTimeOffset)499 jlong SurfaceTransaction_setDesiredPresentTime(JNIEnv* /*env*/, jclass, jlong surfaceTransaction,
500 jlong desiredPresentTimeOffset) {
501 struct timespec t;
502 t.tv_sec = t.tv_nsec = 0;
503 clock_gettime(CLOCK_MONOTONIC, &t);
504 int64_t currentTime = ((int64_t) t.tv_sec)*1000000000LL + t.tv_nsec;
505
506 int64_t desiredPresentTime = currentTime + desiredPresentTimeOffset;
507
508 ASurfaceTransaction_setDesiredPresentTime(
509 reinterpret_cast<ASurfaceTransaction*>(surfaceTransaction), desiredPresentTime);
510
511 return desiredPresentTime;
512 }
513
SurfaceTransaction_setBufferAlpha(JNIEnv *,jclass,jlong surfaceControl,jlong surfaceTransaction,jdouble alpha)514 void SurfaceTransaction_setBufferAlpha(JNIEnv* /*env*/, jclass,
515 jlong surfaceControl,
516 jlong surfaceTransaction, jdouble alpha) {
517 ASurfaceTransaction_setBufferAlpha(
518 reinterpret_cast<ASurfaceTransaction*>(surfaceTransaction),
519 reinterpret_cast<ASurfaceControl*>(surfaceControl), alpha);
520 }
521
SurfaceTransaction_reparent(JNIEnv *,jclass,jlong surfaceControl,jlong newParentSurfaceControl,jlong surfaceTransaction)522 void SurfaceTransaction_reparent(JNIEnv* /*env*/, jclass, jlong surfaceControl,
523 jlong newParentSurfaceControl, jlong surfaceTransaction) {
524 ASurfaceTransaction_reparent(
525 reinterpret_cast<ASurfaceTransaction*>(surfaceTransaction),
526 reinterpret_cast<ASurfaceControl*>(surfaceControl),
527 reinterpret_cast<ASurfaceControl*>(newParentSurfaceControl));
528 }
529
SurfaceTransaction_setColor(JNIEnv *,jclass,jlong surfaceControl,jlong surfaceTransaction,jfloat r,jfloat g,jfloat b,jfloat alpha)530 void SurfaceTransaction_setColor(JNIEnv* /*env*/, jclass, jlong surfaceControl,
531 jlong surfaceTransaction, jfloat r,
532 jfloat g, jfloat b, jfloat alpha) {
533 ASurfaceTransaction_setColor(
534 reinterpret_cast<ASurfaceTransaction*>(surfaceTransaction),
535 reinterpret_cast<ASurfaceControl*>(surfaceControl),
536 r, g, b, alpha, ADATASPACE_UNKNOWN);
537 }
538
SurfaceTransaction_setEnableBackPressure(JNIEnv *,jclass,jlong surfaceControl,jlong surfaceTransaction,jboolean enableBackPressure)539 void SurfaceTransaction_setEnableBackPressure(JNIEnv* /*env*/, jclass, jlong surfaceControl,
540 jlong surfaceTransaction,
541 jboolean enableBackPressure) {
542 ASurfaceTransaction_setEnableBackPressure(reinterpret_cast<ASurfaceTransaction*>(
543 surfaceTransaction),
544 reinterpret_cast<ASurfaceControl*>(surfaceControl),
545 enableBackPressure);
546 }
547
SurfaceTransaction_setOnCompleteCallback(JNIEnv * env,jclass,jlong surfaceTransaction,jboolean waitForFence,jobject callback)548 void SurfaceTransaction_setOnCompleteCallback(JNIEnv* env, jclass, jlong surfaceTransaction,
549 jboolean waitForFence, jobject callback) {
550 void* context = new CallbackListenerWrapper(env, callback, waitForFence);
551 ASurfaceTransaction_setOnComplete(reinterpret_cast<ASurfaceTransaction*>(surfaceTransaction),
552 reinterpret_cast<void*>(context),
553 CallbackListenerWrapper::transactionCallbackThunk);
554 }
555
SurfaceTransaction_setOnCommitCallback(JNIEnv * env,jclass,jlong surfaceTransaction,jobject callback)556 void SurfaceTransaction_setOnCommitCallback(JNIEnv* env, jclass, jlong surfaceTransaction,
557 jobject callback) {
558 void* context = new CallbackListenerWrapper(env, callback, false /* waitForFence */);
559 ASurfaceTransaction_setOnCommit(reinterpret_cast<ASurfaceTransaction*>(surfaceTransaction),
560 reinterpret_cast<void*>(context),
561 CallbackListenerWrapper::transactionCallbackThunk);
562 }
563
564 // Save context so we can test callbacks without a context provided.
565 static CallbackListenerWrapper* listener = nullptr;
transactionCallbackWithoutContextThunk(void *,ASurfaceTransactionStats * stats)566 static void transactionCallbackWithoutContextThunk(void* /* context */,
567 ASurfaceTransactionStats* stats) {
568 CallbackListenerWrapper::transactionCallbackThunk(listener, stats);
569 listener = nullptr;
570 }
571
SurfaceTransaction_setOnCompleteCallbackWithoutContext(JNIEnv * env,jclass,jlong surfaceTransaction,jboolean waitForFence,jobject callback)572 void SurfaceTransaction_setOnCompleteCallbackWithoutContext(JNIEnv* env, jclass,
573 jlong surfaceTransaction,
574 jboolean waitForFence,
575 jobject callback) {
576 listener = new CallbackListenerWrapper(env, callback, waitForFence);
577 ASurfaceTransaction_setOnComplete(reinterpret_cast<ASurfaceTransaction*>(surfaceTransaction),
578 nullptr, transactionCallbackWithoutContextThunk);
579 }
580
SurfaceTransaction_setOnCommitCallbackWithoutContext(JNIEnv * env,jclass,jlong surfaceTransaction,jobject callback)581 void SurfaceTransaction_setOnCommitCallbackWithoutContext(JNIEnv* env, jclass,
582 jlong surfaceTransaction,
583 jobject callback) {
584 listener = new CallbackListenerWrapper(env, callback, false /* waitForFence */);
585 ASurfaceTransaction_setOnCommit(reinterpret_cast<ASurfaceTransaction*>(surfaceTransaction),
586 nullptr, transactionCallbackWithoutContextThunk);
587 }
588
SurfaceTransaction_setFrameTimeline(JNIEnv *,jclass,jlong surfaceTransaction,jlong vsyncId)589 void SurfaceTransaction_setFrameTimeline(JNIEnv* /*env*/, jclass, jlong surfaceTransaction,
590 jlong vsyncId) {
591 ASurfaceTransaction_setFrameTimeline(reinterpret_cast<ASurfaceTransaction*>(surfaceTransaction),
592 vsyncId);
593 }
594
SurfaceTransaction_setExtendedRangeBrightness(JNIEnv *,jclass,jlong surfaceControl,jlong surfaceTransaction,jfloat currentRatio,jfloat desiredRatio)595 void SurfaceTransaction_setExtendedRangeBrightness(JNIEnv* /*env*/, jclass, jlong surfaceControl,
596 jlong surfaceTransaction, jfloat currentRatio,
597 jfloat desiredRatio) {
598 ASurfaceTransaction_setExtendedRangeBrightness(reinterpret_cast<ASurfaceTransaction*>(
599 surfaceTransaction),
600 reinterpret_cast<ASurfaceControl*>(
601 surfaceControl),
602 currentRatio, desiredRatio);
603 }
604
SurfaceTransaction_setDesiredHdrHeadroom(JNIEnv *,jclass,jlong surfaceControl,jlong surfaceTransaction,jfloat desiredRatio)605 void SurfaceTransaction_setDesiredHdrHeadroom(JNIEnv* /*env*/, jclass, jlong surfaceControl,
606 jlong surfaceTransaction, jfloat desiredRatio) {
607 ASurfaceTransaction_setDesiredHdrHeadroom(reinterpret_cast<ASurfaceTransaction*>(
608 surfaceTransaction),
609 reinterpret_cast<ASurfaceControl*>(
610 surfaceControl),
611 desiredRatio);
612 }
613
SurfaceTransaction_setDataSpace(JNIEnv *,jclass,jlong surfaceControl,jlong surfaceTransaction,jint dataspace)614 void SurfaceTransaction_setDataSpace(JNIEnv* /*env*/, jclass, jlong surfaceControl,
615 jlong surfaceTransaction, jint dataspace) {
616 ASurfaceTransaction_setBufferDataSpace(reinterpret_cast<ASurfaceTransaction*>(
617 surfaceTransaction),
618 reinterpret_cast<ASurfaceControl*>(surfaceControl),
619 static_cast<ADataSpace>(dataspace));
620 }
621
622 static struct {
623 jclass clazz;
624 jmethodID constructor;
625 } gFrameTimelineClassInfo;
626
627 static struct {
628 jclass clazz;
629 jmethodID constructor;
630 } gFrameCallbackDataClassInfo;
631
verifyChoreographer(JNIEnv * env,AChoreographer * choreographer)632 static void verifyChoreographer(JNIEnv* env, AChoreographer* choreographer) {
633 ASSERT(choreographer != nullptr, "Choreographer setup unsuccessful");
634 }
635
verifyPollCallback(JNIEnv * env,int result)636 static void verifyPollCallback(JNIEnv* env, int result) {
637 ASSERT(result == ALOOPER_POLL_CALLBACK, "Callback failed with error: %d", result);
638 }
639
640 /** Gets VSync information from Choreographer, including a collection of frame timelines and
641 * platform-preferred index using Choreographer. */
SurfaceControlTest_getFrameTimelines(JNIEnv * env,jclass)642 jobject SurfaceControlTest_getFrameTimelines(JNIEnv* env, jclass) {
643 ALooper_prepare(0);
644 ATrace_beginSection("Getting Choreographer instance");
645 AChoreographer* choreographer = AChoreographer_getInstance();
646 ATrace_endSection();
647 verifyChoreographer(env, choreographer);
648
649 VsyncCallback cb1("cb1", env);
650 auto start = now();
651 ATrace_beginSection("postVsyncCallback");
652 AChoreographer_postVsyncCallback(choreographer, vsyncCallback, &cb1);
653 ATrace_endSection();
654 auto delayPeriod = std::chrono::duration_cast<std::chrono::milliseconds>(DELAY_PERIOD).count();
655 ATrace_beginSection("ALooper_pollOnce");
656 int result = ALooper_pollOnce(delayPeriod * 5, nullptr, nullptr, nullptr);
657 ATrace_endSection();
658 verifyPollCallback(env, result);
659 verifyCallback(env, cb1, 1, start, NOMINAL_VSYNC_PERIOD * 3);
660
661 jobjectArray frameTimelineObjs =
662 env->NewObjectArray(cb1.getTimeline().size(), gFrameTimelineClassInfo.clazz,
663 /*initial element*/ NULL);
664 if (env->ExceptionCheck()) {
665 env->ExceptionDescribe();
666 env->ExceptionClear();
667 return NULL;
668 }
669 if (frameTimelineObjs == NULL) {
670 jniThrowRuntimeException(env, "Failed to create FrameTimeline array");
671 return NULL;
672 }
673 for (int i = 0; i < cb1.getTimeline().size(); i++) {
674 VsyncCallback::FrameTime frameTimeline = cb1.getTimeline()[i];
675 jobject frameTimelineObj =
676 env->NewObject(gFrameTimelineClassInfo.clazz, gFrameTimelineClassInfo.constructor,
677 frameTimeline.vsyncId, frameTimeline.expectedPresentTime,
678 frameTimeline.deadline);
679 env->SetObjectArrayElement(frameTimelineObjs, i, frameTimelineObj);
680 }
681
682 return env->NewObject(gFrameCallbackDataClassInfo.clazz,
683 gFrameCallbackDataClassInfo.constructor, frameTimelineObjs,
684 cb1.getPreferredFrameTimelineIndex());
685 }
686
687 static const JNINativeMethod JNI_METHODS[] = {
688 {"nSurfaceTransaction_create", "()J", (void*)SurfaceTransaction_create},
689 {"nSurfaceTransaction_delete", "(J)V", (void*)SurfaceTransaction_delete},
690 {"nSurfaceTransaction_fromJava", "(Landroid/view/SurfaceControl$Transaction;)J",
691 (void*)SurfaceTransaction_fromJava},
692 {"nSurfaceTransaction_apply", "(J)V", (void*)SurfaceTransaction_apply},
693 {"nSurfaceControl_createFromWindow", "(Landroid/view/Surface;)J",
694 (void*)SurfaceControl_createFromWindow},
695 {"nSurfaceControl_create", "(J)J", (void*)SurfaceControl_create},
696 {"nSurfaceControl_acquire", "(J)V", (void*)SurfaceControl_acquire},
697 {"nSurfaceControl_release", "(J)V", (void*)SurfaceControl_release},
698 {"nSurfaceControl_fromJava", "(Landroid/view/SurfaceControl;)J",
699 (void*)SurfaceControl_fromJava},
700 {"nSurfaceTransaction_setSolidBuffer", "(JJIII)J",
701 (void*)SurfaceTransaction_setSolidBuffer},
702 {"nSurfaceTransaction_setBuffer", "(JJJ)V", (void*)SurfaceTransaction_setBuffer},
703 {"nSurfaceTransaction_setQuadrantBuffer", "(JJIIIIII)J",
704 (void*)SurfaceTransaction_setQuadrantBuffer},
705 {"nSurfaceTransaction_releaseBuffer", "(J)V", (void*)SurfaceTransaction_releaseBuffer},
706 {"nSurfaceTransaction_setVisibility", "(JJZ)V", (void*)SurfaceTransaction_setVisibility},
707 {"nSurfaceTransaction_setBufferOpaque", "(JJZ)V",
708 (void*)SurfaceTransaction_setBufferOpaque},
709 {"nSurfaceTransaction_setGeometry", "(JJIIIIIIIII)V",
710 (void*)SurfaceTransaction_setGeometry},
711 {"nSurfaceTransaction_setDamageRegion", "(JJIIII)V",
712 (void*)SurfaceTransaction_setDamageRegion},
713 {"nSurfaceTransaction_setZOrder", "(JJI)V", (void*)SurfaceTransaction_setZOrder},
714 {"nSurfaceTransaction_setDesiredPresentTime", "(JJ)J",
715 (void*)SurfaceTransaction_setDesiredPresentTime},
716 {"nSurfaceTransaction_setBufferAlpha", "(JJD)V", (void*)SurfaceTransaction_setBufferAlpha},
717 {"nSurfaceTransaction_reparent", "(JJJ)V", (void*)SurfaceTransaction_reparent},
718 {"nSurfaceTransaction_setColor", "(JJFFFF)V", (void*)SurfaceTransaction_setColor},
719 {"nSurfaceTransaction_setEnableBackPressure", "(JJZ)V",
720 (void*)SurfaceTransaction_setEnableBackPressure},
721 {"nSurfaceTransaction_setOnCompleteCallback",
722 "(JZLandroid/view/cts/util/ASurfaceControlTestUtils$TransactionCompleteListener;)V",
723 (void*)SurfaceTransaction_setOnCompleteCallback},
724 {"nSurfaceTransaction_setOnCommitCallback",
725 "(JLandroid/view/cts/util/ASurfaceControlTestUtils$TransactionCompleteListener;)V",
726 (void*)SurfaceTransaction_setOnCommitCallback},
727 {"nSurfaceTransaction_setCrop", "(JJIIII)V", (void*)SurfaceTransaction_setCrop},
728 {"nSurfaceTransaction_setPosition", "(JJII)V", (void*)SurfaceTransaction_setPosition},
729 {"nSurfaceTransaction_setBufferTransform", "(JJI)V",
730 (void*)SurfaceTransaction_setBufferTransform},
731 {"nSurfaceTransaction_setScale", "(JJFF)V", (void*)SurfaceTransaction_setScale},
732 {"nSurfaceTransaction_setOnCompleteCallbackWithoutContext",
733 "(JZLandroid/view/cts/util/ASurfaceControlTestUtils$TransactionCompleteListener;)V",
734 (void*)SurfaceTransaction_setOnCompleteCallbackWithoutContext},
735 {"nSurfaceTransaction_setOnCommitCallbackWithoutContext",
736 "(JLandroid/view/cts/util/ASurfaceControlTestUtils$TransactionCompleteListener;)V",
737 (void*)SurfaceTransaction_setOnCommitCallbackWithoutContext},
738 {"nSurfaceTransaction_setFrameTimeline", "(JJ)V",
739 (void*)SurfaceTransaction_setFrameTimeline},
740 {"nSurfaceTransaction_setExtendedRangeBrightness", "(JJFF)V",
741 (void*)SurfaceTransaction_setExtendedRangeBrightness},
742 {"nSurfaceTransaction_setDesiredHdrHeadroom", "(JJF)V",
743 (void*)SurfaceTransaction_setDesiredHdrHeadroom},
744 {"nSurfaceTransaction_setDataSpace", "(JJI)V", (void*)SurfaceTransaction_setDataSpace},
745 {"getSolidBuffer", "(III)Landroid/hardware/HardwareBuffer;", (void*)Utils_getSolidBuffer},
746 {"getQuadrantBuffer", "(IIIIII)Landroid/hardware/HardwareBuffer;",
747 (void*)Utils_getQuadrantBuffer},
748 {"getBufferId", "(Landroid/hardware/HardwareBuffer;)J", (void*)Utils_getBufferId},
749 };
750
751 static const JNINativeMethod FRAME_TIMELINE_JNI_METHODS[] = {
752 {"nGetFrameTimelines", "()Landroid/view/cts/util/FrameCallbackData;",
753 (void*)SurfaceControlTest_getFrameTimelines},
754 };
755
756 } // anonymous namespace
757
register_android_view_cts_ASurfaceControlTest(JNIEnv * env)758 jint register_android_view_cts_ASurfaceControlTest(JNIEnv* env) {
759 jclass transactionCompleteListenerClazz = env->FindClass(
760 "android/view/cts/util/ASurfaceControlTestUtils$TransactionCompleteListener");
761 gTransactionCompleteListenerClassInfo.clazz =
762 static_cast<jclass>(env->NewGlobalRef(transactionCompleteListenerClazz));
763 gTransactionCompleteListenerClassInfo.onTransactionComplete =
764 env->GetMethodID(transactionCompleteListenerClazz, "onTransactionComplete", "(JJ)V");
765
766 gFrameTimelineClassInfo.clazz = static_cast<jclass>(env->NewGlobalRef(
767 env->FindClass("android/view/cts/util/FrameCallbackData$FrameTimeline")));
768 gFrameTimelineClassInfo.constructor =
769 env->GetMethodID(gFrameTimelineClassInfo.clazz, "<init>", "(JJJ)V");
770
771 gFrameCallbackDataClassInfo.clazz = static_cast<jclass>(
772 env->NewGlobalRef(env->FindClass("android/view/cts/util/FrameCallbackData")));
773 gFrameCallbackDataClassInfo.constructor =
774 env->GetMethodID(gFrameCallbackDataClassInfo.clazz, "<init>",
775 "([Landroid/view/cts/util/FrameCallbackData$FrameTimeline;I)V");
776
777 jclass frameCallbackDataClass = env->FindClass("android/view/cts/util/FrameCallbackData");
778 env->RegisterNatives(frameCallbackDataClass, FRAME_TIMELINE_JNI_METHODS,
779 sizeof(FRAME_TIMELINE_JNI_METHODS) / sizeof(JNINativeMethod));
780
781 jclass clazz = env->FindClass("android/view/cts/util/ASurfaceControlTestUtils");
782 return env->RegisterNatives(clazz, JNI_METHODS, sizeof(JNI_METHODS) / sizeof(JNINativeMethod));
783 }
784