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