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 <sys/types.h> 20 #include <sys/time.h> 21 #include <unistd.h> 22 23 #include <array> 24 #include <cinttypes> 25 #include <string> 26 27 #include <android/data_space.h> 28 #include <android/hardware_buffer.h> 29 #include <android/log.h> 30 #include <android/native_window_jni.h> 31 #include <android/surface_control.h> 32 #include <android/sync.h> 33 34 #include <errno.h> 35 #include <jni.h> 36 #include <time.h> 37 38 namespace { 39 40 // Raises a java exception 41 static void fail(JNIEnv* env, const char* format, ...) { 42 va_list args; 43 44 va_start(args, format); 45 char* msg; 46 vasprintf(&msg, format, args); 47 va_end(args); 48 49 jclass exClass; 50 const char* className = "java/lang/AssertionError"; 51 exClass = env->FindClass(className); 52 env->ThrowNew(exClass, msg); 53 free(msg); 54 } 55 56 #define ASSERT(condition, format, args...) \ 57 if (!(condition)) { \ 58 fail(env, format, ##args); \ 59 return; \ 60 } 61 62 #define NANOS_PER_SECOND 1000000000LL 63 int64_t systemTime() { 64 struct timespec time; 65 int result = clock_gettime(CLOCK_MONOTONIC, &time); 66 if (result < 0) { 67 return -errno; 68 } 69 return (time.tv_sec * NANOS_PER_SECOND) + time.tv_nsec; 70 } 71 72 static AHardwareBuffer* allocateBuffer(int32_t width, int32_t height) { 73 AHardwareBuffer* buffer = nullptr; 74 AHardwareBuffer_Desc desc = {}; 75 desc.width = width; 76 desc.height = height; 77 desc.layers = 1; 78 desc.usage = AHARDWAREBUFFER_USAGE_COMPOSER_OVERLAY | AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN; 79 desc.format = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM; 80 81 AHardwareBuffer_allocate(&desc, &buffer); 82 83 return buffer; 84 } 85 86 static void fillRegion(void* data, int32_t left, int32_t top, int32_t right, 87 int32_t bottom, uint32_t color, uint32_t stride) { 88 uint32_t* ptr = static_cast<uint32_t*>(data); 89 90 ptr += stride * top; 91 92 for (uint32_t y = top; y < bottom; y++) { 93 for (uint32_t x = left; x < right; x++) { 94 ptr[x] = color; 95 } 96 ptr += stride; 97 } 98 } 99 100 static bool getSolidBuffer(int32_t width, int32_t height, uint32_t color, 101 AHardwareBuffer** outHardwareBuffer, 102 int* outFence) { 103 AHardwareBuffer* buffer = allocateBuffer(width, height); 104 if (!buffer) { 105 return true; 106 } 107 108 AHardwareBuffer_Desc desc = {}; 109 AHardwareBuffer_describe(buffer, &desc); 110 111 void* data = nullptr; 112 const ARect rect{0, 0, width, height}; 113 AHardwareBuffer_lock(buffer, AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN, -1, &rect, 114 &data); 115 if (!data) { 116 return true; 117 } 118 119 fillRegion(data, 0, 0, width, height, color, desc.stride); 120 121 AHardwareBuffer_unlock(buffer, outFence); 122 123 *outHardwareBuffer = buffer; 124 return false; 125 } 126 127 static bool getQuadrantBuffer(int32_t width, int32_t height, jint colorTopLeft, 128 jint colorTopRight, jint colorBottomRight, 129 jint colorBottomLeft, 130 AHardwareBuffer** outHardwareBuffer, 131 int* outFence) { 132 AHardwareBuffer* buffer = allocateBuffer(width, height); 133 if (!buffer) { 134 return true; 135 } 136 137 AHardwareBuffer_Desc desc = {}; 138 AHardwareBuffer_describe(buffer, &desc); 139 140 void* data = nullptr; 141 const ARect rect{0, 0, width, height}; 142 AHardwareBuffer_lock(buffer, AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN, -1, &rect, 143 &data); 144 if (!data) { 145 return true; 146 } 147 148 fillRegion(data, 0, 0, width / 2, height / 2, colorTopLeft, desc.stride); 149 fillRegion(data, width / 2, 0, width, height / 2, colorTopRight, desc.stride); 150 fillRegion(data, 0, height / 2, width / 2, height, colorBottomLeft, 151 desc.stride); 152 fillRegion(data, width / 2, height / 2, width, height, colorBottomRight, 153 desc.stride); 154 155 AHardwareBuffer_unlock(buffer, outFence); 156 157 *outHardwareBuffer = buffer; 158 return false; 159 } 160 161 jlong SurfaceTransaction_create(JNIEnv* /*env*/, jclass) { 162 return reinterpret_cast<jlong>(ASurfaceTransaction_create()); 163 } 164 165 void SurfaceTransaction_delete(JNIEnv* /*env*/, jclass, jlong surfaceTransaction) { 166 ASurfaceTransaction_delete( 167 reinterpret_cast<ASurfaceTransaction*>(surfaceTransaction)); 168 } 169 170 void SurfaceTransaction_apply(JNIEnv* /*env*/, jclass, jlong surfaceTransaction) { 171 ASurfaceTransaction_apply( 172 reinterpret_cast<ASurfaceTransaction*>(surfaceTransaction)); 173 } 174 175 long SurfaceControl_createFromWindow(JNIEnv* env, jclass, jobject jSurface) { 176 if (!jSurface) { 177 return 0; 178 } 179 180 ANativeWindow* window = ANativeWindow_fromSurface(env, jSurface); 181 if (!window) { 182 return 0; 183 } 184 185 const std::string debugName = "SurfaceControl_createFromWindowLayer"; 186 ASurfaceControl* surfaceControl = 187 ASurfaceControl_createFromWindow(window, debugName.c_str()); 188 if (!surfaceControl) { 189 return 0; 190 } 191 192 ANativeWindow_release(window); 193 194 return reinterpret_cast<jlong>(surfaceControl); 195 } 196 197 jlong SurfaceControl_create(JNIEnv* /*env*/, jclass, jlong parentSurfaceControlId) { 198 ASurfaceControl* surfaceControl = nullptr; 199 const std::string debugName = "SurfaceControl_create"; 200 201 surfaceControl = ASurfaceControl_create( 202 reinterpret_cast<ASurfaceControl*>(parentSurfaceControlId), 203 debugName.c_str()); 204 205 return reinterpret_cast<jlong>(surfaceControl); 206 } 207 208 void SurfaceControl_release(JNIEnv* /*env*/, jclass, jlong surfaceControl) { 209 ASurfaceControl_release(reinterpret_cast<ASurfaceControl*>(surfaceControl)); 210 } 211 212 jlong SurfaceTransaction_setSolidBuffer(JNIEnv* /*env*/, jclass, 213 jlong surfaceControl, 214 jlong surfaceTransaction, jint width, 215 jint height, jint color) { 216 AHardwareBuffer* buffer = nullptr; 217 int fence = -1; 218 219 bool err = getSolidBuffer(width, height, color, &buffer, &fence); 220 if (err) { 221 return 0; 222 } 223 224 ASurfaceTransaction_setBuffer( 225 reinterpret_cast<ASurfaceTransaction*>(surfaceTransaction), 226 reinterpret_cast<ASurfaceControl*>(surfaceControl), buffer, fence); 227 228 ASurfaceTransaction_setBufferDataSpace( 229 reinterpret_cast<ASurfaceTransaction*>(surfaceTransaction), 230 reinterpret_cast<ASurfaceControl*>(surfaceControl), ADATASPACE_UNKNOWN); 231 232 return reinterpret_cast<jlong>(buffer); 233 } 234 235 jlong SurfaceTransaction_setQuadrantBuffer( 236 JNIEnv* /*env*/, jclass, jlong surfaceControl, jlong surfaceTransaction, 237 jint width, jint height, jint colorTopLeft, jint colorTopRight, 238 jint colorBottomRight, jint colorBottomLeft) { 239 AHardwareBuffer* buffer = nullptr; 240 int fence = -1; 241 242 bool err = 243 getQuadrantBuffer(width, height, colorTopLeft, colorTopRight, 244 colorBottomRight, colorBottomLeft, &buffer, &fence); 245 if (err) { 246 return 0; 247 } 248 249 ASurfaceTransaction_setBuffer( 250 reinterpret_cast<ASurfaceTransaction*>(surfaceTransaction), 251 reinterpret_cast<ASurfaceControl*>(surfaceControl), buffer, fence); 252 253 ASurfaceTransaction_setBufferDataSpace( 254 reinterpret_cast<ASurfaceTransaction*>(surfaceTransaction), 255 reinterpret_cast<ASurfaceControl*>(surfaceControl), ADATASPACE_UNKNOWN); 256 257 return reinterpret_cast<jlong>(buffer); 258 } 259 260 void SurfaceTransaction_releaseBuffer(JNIEnv* /*env*/, jclass, jlong buffer) { 261 AHardwareBuffer_release(reinterpret_cast<AHardwareBuffer*>(buffer)); 262 } 263 264 void SurfaceTransaction_setVisibility(JNIEnv* /*env*/, jclass, 265 jlong surfaceControl, 266 jlong surfaceTransaction, jboolean show) { 267 int8_t visibility = (show) ? ASURFACE_TRANSACTION_VISIBILITY_SHOW : 268 ASURFACE_TRANSACTION_VISIBILITY_HIDE; 269 ASurfaceTransaction_setVisibility( 270 reinterpret_cast<ASurfaceTransaction*>(surfaceTransaction), 271 reinterpret_cast<ASurfaceControl*>(surfaceControl), visibility); 272 } 273 274 void SurfaceTransaction_setBufferOpaque(JNIEnv* /*env*/, jclass, 275 jlong surfaceControl, 276 jlong surfaceTransaction, 277 jboolean opaque) { 278 int8_t transparency = (opaque) ? ASURFACE_TRANSACTION_TRANSPARENCY_OPAQUE : 279 ASURFACE_TRANSACTION_TRANSPARENCY_TRANSPARENT; 280 ASurfaceTransaction_setBufferTransparency( 281 reinterpret_cast<ASurfaceTransaction*>(surfaceTransaction), 282 reinterpret_cast<ASurfaceControl*>(surfaceControl), transparency); 283 } 284 285 void SurfaceTransaction_setGeometry(JNIEnv* /*env*/, jclass, 286 jlong surfaceControl, 287 jlong surfaceTransaction, 288 jint srcLeft, jint srcTop, jint srcRight, jint srcBottom, 289 jint dstLeft, jint dstTop, jint dstRight, jint dstBottom, 290 jint transform) { 291 const ARect src{srcLeft, srcTop, srcRight, srcBottom}; 292 const ARect dst{dstLeft, dstTop, dstRight, dstBottom}; 293 ASurfaceTransaction_setGeometry( 294 reinterpret_cast<ASurfaceTransaction*>(surfaceTransaction), 295 reinterpret_cast<ASurfaceControl*>(surfaceControl), src, dst, transform); 296 } 297 298 void SurfaceTransaction_setDamageRegion(JNIEnv* /*env*/, jclass, 299 jlong surfaceControl, 300 jlong surfaceTransaction, jint left, 301 jint top, jint right, jint bottom) { 302 const ARect rect[] = {{left, top, right, bottom}}; 303 ASurfaceTransaction_setDamageRegion( 304 reinterpret_cast<ASurfaceTransaction*>(surfaceTransaction), 305 reinterpret_cast<ASurfaceControl*>(surfaceControl), rect, 1); 306 } 307 308 void SurfaceTransaction_setZOrder(JNIEnv* /*env*/, jclass, jlong surfaceControl, 309 jlong surfaceTransaction, jint z) { 310 ASurfaceTransaction_setZOrder( 311 reinterpret_cast<ASurfaceTransaction*>(surfaceTransaction), 312 reinterpret_cast<ASurfaceControl*>(surfaceControl), z); 313 } 314 315 static void onComplete(void* context, ASurfaceTransactionStats* stats) { 316 if (!stats) { 317 return; 318 } 319 320 int64_t latchTime = ASurfaceTransactionStats_getLatchTime(stats); 321 if (latchTime < 0) { 322 return; 323 } 324 325 ASurfaceControl** surfaceControls = nullptr; 326 size_t surfaceControlsSize = 0; 327 ASurfaceTransactionStats_getASurfaceControls(stats, &surfaceControls, &surfaceControlsSize); 328 329 for (int i = 0; i < surfaceControlsSize; i++) { 330 ASurfaceControl* surfaceControl = surfaceControls[i]; 331 332 int64_t acquireTime = ASurfaceTransactionStats_getAcquireTime(stats, surfaceControl); 333 if (acquireTime < -1) { 334 return; 335 } 336 337 int previousReleaseFence = ASurfaceTransactionStats_getPreviousReleaseFenceFd( 338 stats, surfaceControl); 339 close(previousReleaseFence); 340 } 341 342 int presentFence = ASurfaceTransactionStats_getPresentFenceFd(stats); 343 344 if (!context) { 345 close(presentFence); 346 return; 347 } 348 349 int* contextIntPtr = reinterpret_cast<int*>(context); 350 contextIntPtr[0]++; 351 contextIntPtr[1] = presentFence; 352 int64_t* systemTimeLongPtr = reinterpret_cast<int64_t*>(contextIntPtr + 2); 353 *systemTimeLongPtr = systemTime(); 354 } 355 356 jlong SurfaceTransaction_setOnComplete(JNIEnv* /*env*/, jclass, jlong surfaceTransaction) { 357 int* context = new int[4]; 358 context[0] = 0; 359 context[1] = -1; 360 context[2] = -1; 361 context[3] = -1; 362 363 ASurfaceTransaction_setOnComplete( 364 reinterpret_cast<ASurfaceTransaction*>(surfaceTransaction), 365 reinterpret_cast<void*>(context), onComplete); 366 return reinterpret_cast<jlong>(context); 367 } 368 369 void SurfaceTransaction_checkOnComplete(JNIEnv* env, jclass, jlong context, 370 jlong desiredPresentTime) { 371 ASSERT(context != 0, "invalid context") 372 373 int* contextPtr = reinterpret_cast<int*>(context); 374 int data = contextPtr[0]; 375 int presentFence = contextPtr[1]; 376 377 int64_t* callbackTimePtr = reinterpret_cast<int64_t*>(contextPtr + 2); 378 int64_t callbackTime = *callbackTimePtr; 379 380 delete[] contextPtr; 381 382 if (desiredPresentTime < 0) { 383 close(presentFence); 384 ASSERT(data >= 1, "did not receive a callback") 385 ASSERT(data <= 1, "received too many callbacks") 386 return; 387 } 388 389 if (presentFence >= 0) { 390 struct sync_file_info* syncFileInfo = sync_file_info(presentFence); 391 ASSERT(syncFileInfo, "invalid fence"); 392 393 if (syncFileInfo->status != 1) { 394 sync_file_info_free(syncFileInfo); 395 ASSERT(syncFileInfo->status == 1, "fence did not signal") 396 } 397 398 uint64_t presentTime = 0; 399 struct sync_fence_info* syncFenceInfo = sync_get_fence_info(syncFileInfo); 400 for (size_t i = 0; i < syncFileInfo->num_fences; i++) { 401 if (syncFenceInfo[i].timestamp_ns > presentTime) { 402 presentTime = syncFenceInfo[i].timestamp_ns; 403 } 404 } 405 406 sync_file_info_free(syncFileInfo); 407 close(presentFence); 408 409 // In the worst case the worst present time should be no more than three frames off from the 410 // desired present time. Since the test case is using a virtual display and there are no 411 // requirements for virtual display refresh rate timing, lets assume a refresh rate of 16fps. 412 ASSERT(presentTime < desiredPresentTime + 0.188 * 1e9, "transaction was presented too late"); 413 ASSERT(presentTime >= desiredPresentTime, "transaction was presented too early"); 414 } else { 415 ASSERT(presentFence == -1, "invalid fences should be -1"); 416 // The device doesn't support present fences. We will use the callback time to roughly 417 // verify the result. Since the callback could take up to half a frame, do the normal bound 418 // check plus an additional half frame. 419 ASSERT(callbackTime < desiredPresentTime + (0.188 + 0.031) * 1e9, 420 "transaction was presented too late"); 421 ASSERT(callbackTime >= desiredPresentTime, "transaction was presented too early"); 422 } 423 424 ASSERT(data >= 1, "did not receive a callback") 425 ASSERT(data <= 1, "received too many callbacks") 426 } 427 428 jlong SurfaceTransaction_setDesiredPresentTime(JNIEnv* /*env*/, jclass, jlong surfaceTransaction, 429 jlong desiredPresentTimeOffset) { 430 struct timespec t; 431 t.tv_sec = t.tv_nsec = 0; 432 clock_gettime(CLOCK_MONOTONIC, &t); 433 int64_t currentTime = ((int64_t) t.tv_sec)*1000000000LL + t.tv_nsec; 434 435 int64_t desiredPresentTime = currentTime + desiredPresentTimeOffset; 436 437 ASurfaceTransaction_setDesiredPresentTime( 438 reinterpret_cast<ASurfaceTransaction*>(surfaceTransaction), desiredPresentTime); 439 440 return desiredPresentTime; 441 } 442 443 void SurfaceTransaction_setBufferAlpha(JNIEnv* /*env*/, jclass, 444 jlong surfaceControl, 445 jlong surfaceTransaction, jdouble alpha) { 446 ASurfaceTransaction_setBufferAlpha( 447 reinterpret_cast<ASurfaceTransaction*>(surfaceTransaction), 448 reinterpret_cast<ASurfaceControl*>(surfaceControl), alpha); 449 } 450 451 void SurfaceTransaction_reparent(JNIEnv* /*env*/, jclass, jlong surfaceControl, 452 jlong newParentSurfaceControl, jlong surfaceTransaction) { 453 ASurfaceTransaction_reparent( 454 reinterpret_cast<ASurfaceTransaction*>(surfaceTransaction), 455 reinterpret_cast<ASurfaceControl*>(surfaceControl), 456 reinterpret_cast<ASurfaceControl*>(newParentSurfaceControl)); 457 } 458 459 void SurfaceTransaction_setColor(JNIEnv* /*env*/, jclass, jlong surfaceControl, 460 jlong surfaceTransaction, jfloat r, 461 jfloat g, jfloat b, jfloat alpha) { 462 ASurfaceTransaction_setColor( 463 reinterpret_cast<ASurfaceTransaction*>(surfaceTransaction), 464 reinterpret_cast<ASurfaceControl*>(surfaceControl), 465 r, g, b, alpha, ADATASPACE_UNKNOWN); 466 } 467 468 const std::array<JNINativeMethod, 20> JNI_METHODS = {{ 469 {"nSurfaceTransaction_create", "()J", (void*)SurfaceTransaction_create}, 470 {"nSurfaceTransaction_delete", "(J)V", (void*)SurfaceTransaction_delete}, 471 {"nSurfaceTransaction_apply", "(J)V", (void*)SurfaceTransaction_apply}, 472 {"nSurfaceControl_createFromWindow", "(Landroid/view/Surface;)J", 473 (void*)SurfaceControl_createFromWindow}, 474 {"nSurfaceControl_create", "(J)J", (void*)SurfaceControl_create}, 475 {"nSurfaceControl_release", "(J)V", (void*)SurfaceControl_release}, 476 {"nSurfaceTransaction_setSolidBuffer", "(JJIII)J", (void*)SurfaceTransaction_setSolidBuffer}, 477 {"nSurfaceTransaction_setQuadrantBuffer", "(JJIIIIII)J", 478 (void*)SurfaceTransaction_setQuadrantBuffer}, 479 {"nSurfaceTransaction_releaseBuffer", "(J)V", (void*)SurfaceTransaction_releaseBuffer}, 480 {"nSurfaceTransaction_setVisibility", "(JJZ)V", (void*)SurfaceTransaction_setVisibility}, 481 {"nSurfaceTransaction_setBufferOpaque", "(JJZ)V", (void*)SurfaceTransaction_setBufferOpaque}, 482 {"nSurfaceTransaction_setGeometry", "(JJIIIIIIIII)V", (void*)SurfaceTransaction_setGeometry}, 483 {"nSurfaceTransaction_setDamageRegion", "(JJIIII)V", (void*)SurfaceTransaction_setDamageRegion}, 484 {"nSurfaceTransaction_setZOrder", "(JJI)V", (void*)SurfaceTransaction_setZOrder}, 485 {"nSurfaceTransaction_setOnComplete", "(J)J", (void*)SurfaceTransaction_setOnComplete}, 486 {"nSurfaceTransaction_checkOnComplete", "(JJ)V", (void*)SurfaceTransaction_checkOnComplete}, 487 {"nSurfaceTransaction_setDesiredPresentTime", "(JJ)J", 488 (void*)SurfaceTransaction_setDesiredPresentTime}, 489 {"nSurfaceTransaction_setBufferAlpha", "(JJD)V", (void*)SurfaceTransaction_setBufferAlpha}, 490 {"nSurfaceTransaction_reparent", "(JJJ)V", (void*)SurfaceTransaction_reparent}, 491 {"nSurfaceTransaction_setColor", "(JJFFFF)V", (void*)SurfaceTransaction_setColor}, 492 }}; 493 494 } // anonymous namespace 495 496 jint register_android_view_cts_ASurfaceControlTest(JNIEnv* env) { 497 jclass clazz = env->FindClass("android/view/cts/ASurfaceControlTest"); 498 return env->RegisterNatives(clazz, JNI_METHODS.data(), JNI_METHODS.size()); 499 } 500