1 /*
2  * Copyright 2021 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 <jni.h>
20 #include <string>
21 #include <poll.h>
22 #include <unistd.h>
23 #include <ctime>
24 #include <unistd.h>
25 #include <android/native_activity.h>
26 #include <android/surface_control.h>
27 #include <android/api-level.h>
28 #include <android/native_window_jni.h>
29 #include <android/hardware_buffer_jni.h>
30 #include <android/data_space.h>
31 #include <android/log.h>
32 #include <android/sync.h>
33 #include <sys/system_properties.h>
34 #include "egl_utils.h"
35 #include "sync_fence.h"
36 
37 #define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
38 
39 static struct {
40     jclass clazz{};
41     jfieldID left{};
42     jfieldID top{};
43     jfieldID right{};
44     jfieldID bottom{};
45 } gRectInfo;
46 
JniBindings_nCreate(JNIEnv * env,jclass,jlong surfaceControl,jstring debug_name)47 jlong JniBindings_nCreate(JNIEnv *env, jclass,
48                                                    jlong surfaceControl,
49                                                    jstring debug_name) {
50     if (android_get_device_api_level() >= 29) {
51         auto aSurfaceControl = reinterpret_cast<ASurfaceControl *>(surfaceControl);
52         auto debugName = env->GetStringUTFChars(debug_name, nullptr);
53         return reinterpret_cast<jlong>(ASurfaceControl_create(aSurfaceControl,
54                                                               debugName));
55     } else {
56         return 0;
57     }
58 }
59 
JniBindings_nCreateFromSurface(JNIEnv * env,jclass,jobject surface,jstring debug_name)60 jlong JniBindings_nCreateFromSurface(JNIEnv *env,
61                                                               jclass,
62                                                               jobject surface,
63                                                               jstring debug_name) {
64     if (android_get_device_api_level() >= 29) {
65         auto AWindow = ANativeWindow_fromSurface(env, surface);
66         auto debugName = env->GetStringUTFChars(debug_name, nullptr);
67         auto surfaceControl = reinterpret_cast<jlong>(ASurfaceControl_createFromWindow(AWindow,
68                                                                                        debugName));
69         ANativeWindow_release(AWindow);
70         return surfaceControl;
71     } else {
72         return 0;
73     }
74 }
75 
JniBindings_nRelease(JNIEnv * env,jclass,jlong surfaceControl)76 void JniBindings_nRelease(JNIEnv *env, jclass, jlong surfaceControl) {
77     if (android_get_device_api_level() >= 29) {
78         ASurfaceControl_release(reinterpret_cast<ASurfaceControl *>(surfaceControl));
79     } else {
80         return;
81     }
82 }
83 
JniBindings_nTransactionCreate(JNIEnv * env,jclass)84 jlong JniBindings_nTransactionCreate(JNIEnv *env, jclass) {
85     if (android_get_device_api_level() >= 29) {
86         return reinterpret_cast<jlong>(ASurfaceTransaction_create());
87     } else {
88         return 0;
89     }
90 }
91 
JniBindings_nTransactionDelete(JNIEnv * env,jclass,jlong surfaceTransaction)92 void JniBindings_nTransactionDelete(JNIEnv *env, jclass, jlong surfaceTransaction) {
93     if (android_get_device_api_level() >= 29) {
94         ASurfaceTransaction_delete(reinterpret_cast<ASurfaceTransaction *>(surfaceTransaction));
95     }
96 }
97 
JniBindings_nTransactionApply(JNIEnv * env,jclass,jlong surfaceTransaction)98 void JniBindings_nTransactionApply(JNIEnv *env, jclass, jlong surfaceTransaction) {
99     if (android_get_device_api_level() >= 29) {
100         ASurfaceTransaction_apply(reinterpret_cast<ASurfaceTransaction *>(surfaceTransaction));
101     }
102 }
103 
JniBindings_nTransactionReparent(JNIEnv * env,jclass,jlong surfaceTransaction,jlong surfaceControl,jlong newParent)104 void JniBindings_nTransactionReparent(JNIEnv *env, jclass, jlong surfaceTransaction,
105                                       jlong surfaceControl, jlong newParent) {
106     if (android_get_device_api_level() >= 29) {
107         auto parent = (newParent != 0L) ? reinterpret_cast<ASurfaceControl *>(newParent) : nullptr;
108         ASurfaceTransaction_reparent(reinterpret_cast<ASurfaceTransaction *>(surfaceTransaction),
109                                      reinterpret_cast<ASurfaceControl *>(surfaceControl),
110                                      parent);
111     }
112 }
113 
114 static struct {
115     bool CLASS_INFO_INITIALIZED = false;
116     jclass clazz{};
117     jmethodID onComplete{};
118 } gTransactionCompletedListenerClassInfo;
119 
120 static struct {
121     bool CLASS_INFO_INITIALIZED = false;
122     jclass clazz{};
123     jmethodID onCommit{};
124 } gTransactionCommittedListenerClassInfo;
125 
126 static struct {
127     bool CLASS_INFO_INITIALIZED = false;
128     jclass clazz{};
129     jmethodID dupeFileDescriptor{};
130 } gSyncFenceClassInfo;
131 
132 #define NANO_SECONDS 1000000000LL
133 
getSystemTime()134 int64_t getSystemTime() {
135     struct timespec time;
136     int result = clock_gettime(CLOCK_MONOTONIC, &time);
137     if (result < 0) {
138         return -errno;
139     }
140     return (time.tv_sec * NANO_SECONDS) + time.tv_nsec;
141 }
142 
143 /**
144  * This wrapper class mimics the one found in CTS tests, specifcally
145  * android_view_cts_ASurfaceControlTest.cpp and serves
146  * to allow us to set a callback for Transaction onComplete.
147  */
148 class CallbackWrapper {
149 public:
150     virtual ~CallbackWrapper() = default;
151 
152     virtual void callback(ASurfaceTransactionStats *stats) = 0;
153 
transactionCallbackThunk(void * context,ASurfaceTransactionStats * stats)154     static void transactionCallbackThunk(void *context, ASurfaceTransactionStats *stats) {
155         CallbackWrapper *listener = reinterpret_cast<CallbackWrapper *>(context);
156         listener->callback(stats);
157         delete listener;
158     }
159 
160 protected:
161     JavaVM *mVm{};
162     jobject mCallbackObject{};
163 
getEnv()164     JNIEnv *getEnv() {
165         JNIEnv *env;
166         mVm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_6);
167         return env;
168     }
169 };
170 
171 class OnCompleteCallbackWrapper : public CallbackWrapper {
172 public:
OnCompleteCallbackWrapper(JNIEnv * env,jobject object)173     explicit OnCompleteCallbackWrapper(JNIEnv *env, jobject object) {
174         env->GetJavaVM(&mVm);
175         mCallbackObject = env->NewGlobalRef(object);
176     }
177 
~OnCompleteCallbackWrapper()178     ~OnCompleteCallbackWrapper() override {
179         getEnv()->DeleteGlobalRef(mCallbackObject);
180     }
181 
callback(ASurfaceTransactionStats * stats)182     void callback(ASurfaceTransactionStats *stats) override {
183         JNIEnv *env = getEnv();
184         env->CallVoidMethod(mCallbackObject,
185                             gTransactionCompletedListenerClassInfo.onComplete,
186                             reinterpret_cast<jlong>(stats));
187     }
188 };
189 
190 class OnCommitCallbackWrapper : public CallbackWrapper {
191 public:
OnCommitCallbackWrapper(JNIEnv * env,jobject object)192     explicit OnCommitCallbackWrapper(JNIEnv *env, jobject object) {
193         env->GetJavaVM(&mVm);
194         mCallbackObject = env->NewGlobalRef(object);
195     }
196 
~OnCommitCallbackWrapper()197     ~OnCommitCallbackWrapper() override {
198         getEnv()->DeleteGlobalRef(mCallbackObject);
199     }
200 
callback(ASurfaceTransactionStats * stats)201     void callback(ASurfaceTransactionStats *stats) override {
202         JNIEnv *env = getEnv();
203         env->CallVoidMethod(mCallbackObject,
204                             gTransactionCommittedListenerClassInfo.onCommit);
205     }
206 };
207 
setupTransactionCompletedListenerClassInfo(JNIEnv * env)208 void setupTransactionCompletedListenerClassInfo(JNIEnv *env) {
209     //ensure we only ever initialize class info once
210     if (!gTransactionCompletedListenerClassInfo.CLASS_INFO_INITIALIZED) {
211         //setup transactionCompleteListenerClassInfo for test usage
212         jclass transactionCompletedListenerClazz =
213                 env->FindClass(
214                         "androidx/graphics/surface/"
215                         "SurfaceControlCompat$TransactionCompletedListener");
216         gTransactionCompletedListenerClassInfo.clazz =
217                 static_cast<jclass>(env->NewGlobalRef(transactionCompletedListenerClazz));
218         gTransactionCompletedListenerClassInfo.onComplete =
219                 env->GetMethodID(transactionCompletedListenerClazz, "onTransactionCompleted",
220                                  "(J)V");
221 
222         gTransactionCompletedListenerClassInfo.CLASS_INFO_INITIALIZED = true;
223     }
224 
225 }
226 
setupTransactionCommittedListenerClassInfo(JNIEnv * env)227 void setupTransactionCommittedListenerClassInfo(JNIEnv *env) {
228     //ensure we only ever initialize class info once
229     if (!gTransactionCommittedListenerClassInfo.CLASS_INFO_INITIALIZED) {
230         //setup transactionCommittedListenerClassInfo for test usage
231         jclass transactionCommittedListenerClazz =
232                 env->FindClass(
233                         "androidx/graphics/surface/"
234                         "SurfaceControlCompat$TransactionCommittedListener");
235         gTransactionCommittedListenerClassInfo.clazz =
236                 static_cast<jclass>(env->NewGlobalRef(transactionCommittedListenerClazz));
237         gTransactionCommittedListenerClassInfo.onCommit =
238                 env->GetMethodID(transactionCommittedListenerClazz, "onTransactionCommitted",
239                                  "()V");
240 
241         gTransactionCommittedListenerClassInfo.CLASS_INFO_INITIALIZED = true;
242     }
243 }
244 
JniBindings_nTransactionSetOnComplete(JNIEnv * env,jclass,jlong surfaceTransaction,jobject callback)245 void JniBindings_nTransactionSetOnComplete(JNIEnv *env, jclass, jlong surfaceTransaction,
246                                            jobject callback) {
247     if (android_get_device_api_level() >= 29) {
248         setupTransactionCompletedListenerClassInfo(env);
249         void *context = new OnCompleteCallbackWrapper(env, callback);
250         ASurfaceTransaction_setOnComplete(
251                 reinterpret_cast<ASurfaceTransaction *>(surfaceTransaction),
252                 reinterpret_cast<void *>(context),
253                 CallbackWrapper::transactionCallbackThunk);
254     }
255 }
256 
JniBindings_nTransactionSetOnCommit(JNIEnv * env,jclass,jlong surfaceTransaction,jobject listener)257 void JniBindings_nTransactionSetOnCommit(JNIEnv *env, jclass, jlong surfaceTransaction,
258                                          jobject listener) {
259     if (android_get_device_api_level() >= 31) {
260         setupTransactionCommittedListenerClassInfo(env);
261         void *context = new OnCommitCallbackWrapper(env, listener);
262         ASurfaceTransaction_setOnCommit(
263                 reinterpret_cast<ASurfaceTransaction *>(surfaceTransaction),
264                 reinterpret_cast<void *>(context),
265                 CallbackWrapper::transactionCallbackThunk);
266     }
267 }
268 
setupSyncFenceClassInfo(JNIEnv * env)269 void setupSyncFenceClassInfo(JNIEnv *env) {
270     if (!gSyncFenceClassInfo.CLASS_INFO_INITIALIZED) {
271         jclass syncFenceClazz = env->FindClass("androidx/hardware/SyncFenceV19");
272         gSyncFenceClassInfo.clazz = static_cast<jclass>(env->NewGlobalRef(syncFenceClazz));
273         gSyncFenceClassInfo.dupeFileDescriptor =
274                 env->GetMethodID(gSyncFenceClassInfo.clazz, "dupeFileDescriptor", "()I");
275         gSyncFenceClassInfo.CLASS_INFO_INITIALIZED = true;
276     }
277 }
278 
dup_fence_fd(JNIEnv * env,jobject syncFence)279 int dup_fence_fd(JNIEnv *env, jobject syncFence) {
280     setupSyncFenceClassInfo(env);
281     return env->CallIntMethod(syncFence, gSyncFenceClassInfo.dupeFileDescriptor);
282 }
283 
284 /* Helper method to extract the SyncFence file descriptor
285  */
JniBindings_nDupFenceFd(JNIEnv * env,jclass,jobject syncFence)286 jint JniBindings_nDupFenceFd(JNIEnv *env, jclass, jobject syncFence) {
287     return dup_fence_fd(env, syncFence);
288 }
289 
JniBindings_nSetBuffer(JNIEnv * env,jclass,jlong surfaceTransaction,jlong surfaceControl,jobject hBuffer,jobject syncFence)290 void JniBindings_nSetBuffer(JNIEnv *env, jclass, jlong surfaceTransaction,
291                             jlong surfaceControl, jobject hBuffer,
292                             jobject syncFence) {
293     if (android_get_device_api_level() >= 29) {
294         auto transaction = reinterpret_cast<ASurfaceTransaction *>(surfaceTransaction);
295         auto sc = reinterpret_cast<ASurfaceControl *>(surfaceControl);
296         AHardwareBuffer* hardwareBuffer = nullptr;
297         auto fence_fd = -1;
298         if (hBuffer) {
299             hardwareBuffer = AHardwareBuffer_fromHardwareBuffer(env, hBuffer);
300             fence_fd = dup_fence_fd(env, syncFence);
301         }
302         ASurfaceTransaction_setBuffer(transaction, sc, hardwareBuffer, fence_fd);
303     }
304 }
305 
JniBindings_nSetVisibility(JNIEnv * env,jclass,jlong surfaceTransaction,jlong surfaceControl,jbyte jVisibility)306 void JniBindings_nSetVisibility(
307         JNIEnv *env, jclass,
308         jlong surfaceTransaction, jlong surfaceControl, jbyte jVisibility) {
309     if (android_get_device_api_level() >= 29) {
310         auto st = reinterpret_cast<ASurfaceTransaction *>(surfaceTransaction);
311         auto sc = reinterpret_cast<ASurfaceControl *>(surfaceControl);
312         auto stv = static_cast<ASurfaceTransactionVisibility>(jVisibility);
313         ASurfaceTransaction_setVisibility(st, sc, stv);
314     }
315 }
316 
JniBindings_nSetZOrder(JNIEnv * env,jclass,jlong surfaceTransaction,jlong surfaceControl,jint z_order)317 void JniBindings_nSetZOrder(
318         JNIEnv *env, jclass,
319         jlong surfaceTransaction, jlong surfaceControl, jint z_order) {
320     if (android_get_device_api_level() >= 29) {
321         auto st = reinterpret_cast<ASurfaceTransaction *>(surfaceTransaction);
322         auto sc = reinterpret_cast<ASurfaceControl *>(surfaceControl);
323         ASurfaceTransaction_setZOrder(st, sc, z_order);
324     }
325 }
326 
extract_arect(JNIEnv * env,jobject rect)327 ARect extract_arect(JNIEnv *env, jobject rect) {
328     ARect result;
329     result.left = env->GetIntField(rect, gRectInfo.left);
330     result.top = env->GetIntField(rect, gRectInfo.top);
331     result.right = env->GetIntField(rect, gRectInfo.right);
332     result.bottom = env->GetIntField(rect, gRectInfo.bottom);
333     return result;
334 }
335 
JniBindings_nSetDamageRegion(JNIEnv * env,jclass,jlong surfaceTransaction,jlong surfaceControl,jobject rect)336 void JniBindings_nSetDamageRegion(
337         JNIEnv *env, jclass,
338         jlong surfaceTransaction, jlong surfaceControl,
339         jobject rect) {
340     if (android_get_device_api_level() >= 29) {
341         auto st = reinterpret_cast<ASurfaceTransaction *>(surfaceTransaction);
342         auto sc = reinterpret_cast<ASurfaceControl *>(surfaceControl);
343 
344         if (rect == nullptr) {
345             ASurfaceTransaction_setDamageRegion(st, sc, nullptr, 0);
346             return;
347         }
348 
349         ARect result = extract_arect(env, rect);
350 
351         ASurfaceTransaction_setDamageRegion(st, sc, &result, 1);
352     }
353 }
354 
JniBindings_nSetDesiredPresentTime(JNIEnv * env,jclass,jlong surfaceTransaction,int64_t desiredPresentTimeNano)355 void JniBindings_nSetDesiredPresentTime(
356         JNIEnv *env, jclass,
357         jlong surfaceTransaction, int64_t desiredPresentTimeNano) {
358     if (android_get_device_api_level() >= 29) {
359         ASurfaceTransaction_setDesiredPresentTime(
360                 reinterpret_cast<ASurfaceTransaction *>(surfaceTransaction),
361                 desiredPresentTimeNano);
362     }
363 }
364 
JniBindings_nSetBufferTransparency(JNIEnv * env,jclass,jlong surfaceTransaction,jlong surfaceControl,jbyte transparency)365 void JniBindings_nSetBufferTransparency(
366         JNIEnv *env, jclass,
367         jlong surfaceTransaction, jlong surfaceControl, jbyte transparency) {
368     if (android_get_device_api_level() >= 29) {
369         ASurfaceTransaction_setBufferTransparency(
370                 reinterpret_cast<ASurfaceTransaction *>(surfaceTransaction),
371                 reinterpret_cast<ASurfaceControl *>(surfaceControl),
372                 static_cast<ASurfaceTransactionTransparency>(transparency));
373     }
374 }
375 
JniBindings_nSetBufferAlpha(JNIEnv * env,jclass,jlong surfaceTransaction,jlong surfaceControl,jfloat alpha)376 void JniBindings_nSetBufferAlpha(
377         JNIEnv *env, jclass,
378         jlong surfaceTransaction, jlong surfaceControl, jfloat alpha) {
379     if (android_get_device_api_level() >= 29) {
380         ASurfaceTransaction_setBufferAlpha(
381                 reinterpret_cast<ASurfaceTransaction *>(surfaceTransaction),
382                 reinterpret_cast<ASurfaceControl *>(surfaceControl),
383                 alpha);
384     }
385 }
386 
JniBindings_nSetCrop(JNIEnv * env,jclass,jlong surfaceTransaction,jlong surfaceControl,jint left,jint top,jint right,jint bottom)387 void JniBindings_nSetCrop(JNIEnv *env, jclass,
388                                                     jlong surfaceTransaction,
389                                                     jlong surfaceControl,
390                                                     jint left,
391                                                     jint top,
392                                                     jint right,
393                                                     jint bottom) {
394     auto st = reinterpret_cast<ASurfaceTransaction *>(surfaceTransaction);
395     auto sc = reinterpret_cast<ASurfaceControl *>(surfaceControl);
396 
397     ARect result = ARect{left, top, right, bottom};
398 
399     ASurfaceTransaction_setCrop(st, sc, result);
400 }
401 
JniBindings_nSetPosition(JNIEnv * env,jclass,jlong surfaceTransaction,jlong surfaceControl,jfloat x,jfloat y)402 void JniBindings_nSetPosition(JNIEnv *env, jclass,
403                                                         jlong surfaceTransaction,
404                                                         jlong surfaceControl,
405                                                         jfloat x, jfloat y) {
406     auto st = reinterpret_cast<ASurfaceTransaction *>(surfaceTransaction);
407     auto sc = reinterpret_cast<ASurfaceControl *>(surfaceControl);
408     ASurfaceTransaction_setPosition(st, sc, x, y);
409 }
410 
JniBindings_nSetScale(JNIEnv * env,jclass,jlong surfaceTransaction,jlong surfaceControl,jfloat scale_x,jfloat scale_y)411 void JniBindings_nSetScale(JNIEnv *env, jclass,
412                                                      jlong surfaceTransaction,
413                                                      jlong surfaceControl,
414                                                      jfloat scale_x,
415                                                      jfloat scale_y) {
416     auto st = reinterpret_cast<ASurfaceTransaction *>(surfaceTransaction);
417     auto sc = reinterpret_cast<ASurfaceControl *>(surfaceControl);
418     ASurfaceTransaction_setScale(st, sc, scale_x, scale_y);
419 }
420 
JniBindings_nSetBufferTransform(JNIEnv * env,jclass,jlong surfaceTransaction,jlong surfaceControl,jint transformation)421 void JniBindings_nSetBufferTransform(JNIEnv *env,
422                                                                jclass,
423                                                                jlong
424                                                                surfaceTransaction,
425                                                                jlong surfaceControl,
426                                                                jint transformation) {
427     auto st = reinterpret_cast<ASurfaceTransaction *>(surfaceTransaction);
428     auto sc = reinterpret_cast<ASurfaceControl *>(surfaceControl);
429     ASurfaceTransaction_setBufferTransform(st, sc, transformation);
430 }
431 
JniBindings_nSetDataSpace(JNIEnv * env,jclass,jlong surfaceTransaction,jlong surfaceControl,jint dataspace)432 void JniBindings_nSetDataSpace(JNIEnv *env,
433                                 jclass,
434                                 jlong surfaceTransaction,
435                                 jlong surfaceControl,
436                                 jint dataspace) {
437     auto st = reinterpret_cast<ASurfaceTransaction *>(surfaceTransaction);
438     auto sc = reinterpret_cast<ASurfaceControl *>(surfaceControl);
439 
440     ASurfaceTransaction_setBufferDataSpace(st, sc, static_cast<ADataSpace>(dataspace));
441 }
442 
JniBindings_nSetGeometry(JNIEnv * env,jclass,jlong surfaceTransaction,jlong surfaceControl,jint bufferWidth,jint bufferHeight,jint dstWidth,jint dstHeight,jint transformation)443 void JniBindings_nSetGeometry(JNIEnv *env, jclass,
444                                                                        jlong surfaceTransaction,
445                                                                        jlong surfaceControl,
446                                                                        jint bufferWidth,
447                                                                        jint bufferHeight,
448                                                                        jint dstWidth,
449                                                                        jint dstHeight,
450                                                                        jint transformation) {
451     auto st = reinterpret_cast<ASurfaceTransaction *>(surfaceTransaction);
452     auto sc = reinterpret_cast<ASurfaceControl *>(surfaceControl);
453     auto src = ARect{0, 0, bufferWidth, bufferHeight};
454     auto dest = ARect{0, 0, dstWidth, dstHeight};
455     ASurfaceTransaction_setGeometry(st, sc, src, dest, transformation);
456 }
457 
JniBindings_nGetDisplayOrientation(JNIEnv * env,jclass)458 jstring JniBindings_nGetDisplayOrientation(JNIEnv *env, jclass) {
459     char name[PROP_VALUE_MAX];
460     __system_property_get("ro.surface_flinger.primary_display_orientation", name);
461     return (*env).NewStringUTF(name);
462 }
463 
JniBindings_nIsHwuiUsingVulkanRenderer(JNIEnv *,jclass)464 jboolean JniBindings_nIsHwuiUsingVulkanRenderer(JNIEnv*, jclass) {
465     char value[PROP_VALUE_MAX];
466     __system_property_get("ro.hwui.use_vulkan", value);
467     bool device_is_vulkan = strcmp(value, "true") == 0;
468     __system_property_get("debug.hwui.renderer", value);
469     bool is_debug_vulkan = strcmp(value, "skiavk") == 0;
470     return device_is_vulkan || is_debug_vulkan;
471 }
472 
JniBindings_nGetPreviousReleaseFenceFd(JNIEnv * env,jclass,jlong surfaceControl,jlong transactionStats)473 jint JniBindings_nGetPreviousReleaseFenceFd(JNIEnv *env, jclass,
474                                             jlong surfaceControl,
475                                             jlong transactionStats) {
476     auto sc = reinterpret_cast<ASurfaceControl *>(surfaceControl);
477     auto stats = reinterpret_cast<ASurfaceTransactionStats *>(transactionStats);
478     int fd = -1;
479     if (stats) {
480         // Sometimes even though a SurfaceControl is part of a transaction it will not show up in
481         // the list of transaction provided by ASurfaceTransactionStats.
482         // So query the SurfaceControls that are within ASurfaceTransactionStats and only query
483         // getPreviousReleaseFenceFd is the target SurfaceControl is included.
484         // If we do not do this search in advance, getPreviousReleaseFenceFd will crash.
485         size_t numSurfaceControls;
486         ASurfaceControl** surfaceControls;
487         ASurfaceTransactionStats_getASurfaceControls(stats, &surfaceControls, &numSurfaceControls);
488         for (int i = 0; i < numSurfaceControls; i++) {
489             if (surfaceControls[i] == sc) {
490                 fd = ASurfaceTransactionStats_getPreviousReleaseFenceFd(stats, sc);
491                 break;
492             }
493         }
494         ASurfaceTransactionStats_releaseASurfaceControls(surfaceControls);
495     }
496     return static_cast<jint>(fd);
497 }
498 
JniBindings_nSetFrameRate(JNIEnv * env,jclass,jlong surfaceTransaction,jlong surfaceControl,jfloat framerate,jint compatibility,jint changeFrameRateStrategy)499 void JniBindings_nSetFrameRate(JNIEnv *env, jclass,
500                                jlong surfaceTransaction,
501                                jlong surfaceControl,
502                                jfloat framerate,
503                                jint compatibility,
504                                jint changeFrameRateStrategy) {
505     auto st = reinterpret_cast<ASurfaceTransaction *>(surfaceTransaction);
506     auto sc = reinterpret_cast<ASurfaceControl *>(surfaceControl);
507 
508     if (android_get_device_api_level() >= 31) {
509         ASurfaceTransaction_setFrameRateWithChangeStrategy(
510                 st,
511                 sc,
512                 framerate,
513                 compatibility,
514                 changeFrameRateStrategy
515         );
516     } else if (android_get_device_api_level() >= 30) {
517         ASurfaceTransaction_setFrameRate(st, sc, framerate, compatibility);
518     }
519 }
520 
loadRectInfo(JNIEnv * env)521 void loadRectInfo(JNIEnv *env) {
522     gRectInfo.clazz = env->FindClass("android/graphics/Rect");
523 
524     gRectInfo.left = env->GetFieldID(gRectInfo.clazz, "left", "I");
525     gRectInfo.top = env->GetFieldID(gRectInfo.clazz, "top", "I");
526     gRectInfo.right = env->GetFieldID(gRectInfo.clazz, "right", "I");
527     gRectInfo.bottom = env->GetFieldID(gRectInfo.clazz, "bottom", "I");
528 }
529 
530 static const JNINativeMethod JNI_METHOD_TABLE[] = {
531         {
532                 "nCreate",
533                 "(JLjava/lang/String;)J",
534                 (void *) JniBindings_nCreate
535         },
536         {
537                 "nCreateFromSurface",
538                 "(Landroid/view/Surface;Ljava/lang/String;)J",
539                 (void *) JniBindings_nCreateFromSurface
540         },
541         {
542                 "nRelease",
543                 "(J)V",
544                 (void *) JniBindings_nRelease
545         },
546         {
547                 "nTransactionCreate",
548                 "()J",
549                 (void *) JniBindings_nTransactionCreate
550         },
551         {
552                 "nTransactionDelete",
553                 "(J)V",
554                 (void *) JniBindings_nTransactionDelete
555         },
556         {
557                 "nTransactionApply",
558                 "(J)V",
559                 (void *) JniBindings_nTransactionApply
560         },
561         {
562                 "nTransactionReparent",
563                 "(JJJ)V",
564                 (void *) JniBindings_nTransactionReparent
565         },
566         {
567 
568                 "nTransactionSetOnComplete",
569                 "(JLandroidx/graphics/surface/SurfaceControlCompat$TransactionCompletedListener;)V",
570                 (void *) JniBindings_nTransactionSetOnComplete
571         },
572         {
573                 "nTransactionSetOnCommit",
574                 "(JLandroidx/graphics/surface/SurfaceControlCompat$TransactionCommittedListener;)V",
575                 (void *) JniBindings_nTransactionSetOnCommit
576         },
577         {
578                 "nDupFenceFd",
579                 "(Landroidx/hardware/SyncFenceV19;)I",
580                 (void *) JniBindings_nDupFenceFd
581         },
582         {
583                 "nSetBuffer",
584                 "(JJLandroid/hardware/HardwareBuffer;Landroidx/hardware/SyncFenceV19;)V",
585                 (void *) JniBindings_nSetBuffer
586         },
587         {
588                 "nSetVisibility",
589                 "(JJB)V",
590                 (void *) JniBindings_nSetVisibility
591         },
592         {
593                 "nSetZOrder",
594                 "(JJI)V",
595                 (void *) JniBindings_nSetZOrder
596         },
597         {
598                 "nSetDamageRegion",
599                 "(JJLandroid/graphics/Rect;)V",
600                 (void *) JniBindings_nSetDamageRegion
601         },
602         {
603                 "nSetDesiredPresentTime",
604                 "(JJ)V",
605                 (void *) JniBindings_nSetDesiredPresentTime
606         },
607         {
608                 "nSetBufferTransparency",
609                 "(JJB)V",
610                 (void *) JniBindings_nSetBufferTransparency
611         },
612         {
613                 "nSetBufferAlpha",
614                 "(JJF)V",
615                 (void *) JniBindings_nSetBufferAlpha
616         },
617         {
618                 "nSetCrop",
619                 "(JJIIII)V",
620                 (void *) JniBindings_nSetCrop
621         },
622         {
623                 "nSetPosition",
624                 "(JJFF)V",
625                 (void *) JniBindings_nSetPosition
626         },
627         {
628                 "nSetScale",
629                 "(JJFF)V",
630                 (void *) JniBindings_nSetScale
631         },
632         {
633                 "nSetBufferTransform",
634                 "(JJI)V",
635                 (void *) JniBindings_nSetBufferTransform
636         },
637         {
638                 "nSetDataSpace",
639                 "(JJI)V",
640                 (void *) JniBindings_nSetDataSpace
641         },
642         {
643                 "nSetGeometry",
644                 "(JJIIIII)V",
645                 (void *) JniBindings_nSetGeometry
646         },
647         {
648             "nGetDisplayOrientation",
649                 "()Ljava/lang/String;",
650                 (void *)JniBindings_nGetDisplayOrientation
651         },
652         {
653             "nGetPreviousReleaseFenceFd",
654                 "(JJ)I",
655                 (void *)JniBindings_nGetPreviousReleaseFenceFd
656         },
657         {
658             "nSetFrameRate",
659                 "(JJFII)V",
660                 (void *) JniBindings_nSetFrameRate
661         },
662         {
663             "nIsHwuiUsingVulkanRenderer",
664                 "()Z",
665                 (void *) JniBindings_nIsHwuiUsingVulkanRenderer
666         }
667 };
668 
669 extern "C"
JNI_OnLoad(JavaVM * vm,void *)670 JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) {
671     JNIEnv *env;
672     ALOGE("GraphicsCore JNI_OnLoad start");
673     if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) {
674         return JNI_ERR;
675     }
676 
677     jclass clazz = env->FindClass("androidx/graphics/surface/JniBindings");
678     if(clazz == nullptr) {
679         return JNI_ERR;
680     }
681 
682     if (env->RegisterNatives(clazz, JNI_METHOD_TABLE,
683                              sizeof(JNI_METHOD_TABLE) / sizeof(JNINativeMethod)) != JNI_OK) {
684         return JNI_ERR;
685     }
686 
687     loadRectInfo(env);
688 
689     if (loadEGLMethods(env) != JNI_OK) {
690         return JNI_ERR;
691     }
692 
693     if (loadSyncFenceMethods(env) != JNI_OK) {
694         return JNI_ERR;
695     }
696 
697     return JNI_VERSION_1_6;
698 }
699