Home | History | Annotate | Download | only in jni
      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