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