• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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