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