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