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