Home | History | Annotate | Download | only in jni
      1 /*
      2  * Copyright (C) 2013 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 "SurfaceControl"
     18 #define LOG_NDEBUG 0
     19 
     20 #include "android_os_Parcel.h"
     21 #include "android_util_Binder.h"
     22 #include "android/graphics/Bitmap.h"
     23 #include "android/graphics/GraphicsJNI.h"
     24 #include "android/graphics/Region.h"
     25 #include "core_jni_helpers.h"
     26 
     27 #include <android-base/chrono_utils.h>
     28 #include <nativehelper/JNIHelp.h>
     29 #include <nativehelper/ScopedUtfChars.h>
     30 #include <android_runtime/android_view_Surface.h>
     31 #include <android_runtime/android_view_SurfaceSession.h>
     32 #include <gui/Surface.h>
     33 #include <gui/SurfaceComposerClient.h>
     34 #include <jni.h>
     35 #include <memory>
     36 #include <stdio.h>
     37 #include <system/graphics.h>
     38 #include <ui/DisplayInfo.h>
     39 #include <ui/HdrCapabilities.h>
     40 #include <ui/FrameStats.h>
     41 #include <ui/Rect.h>
     42 #include <ui/Region.h>
     43 #include <utils/Log.h>
     44 
     45 // ----------------------------------------------------------------------------
     46 
     47 namespace android {
     48 
     49 static const char* const OutOfResourcesException =
     50     "android/view/Surface$OutOfResourcesException";
     51 
     52 static struct {
     53     jclass clazz;
     54     jmethodID ctor;
     55     jfieldID width;
     56     jfieldID height;
     57     jfieldID refreshRate;
     58     jfieldID density;
     59     jfieldID xDpi;
     60     jfieldID yDpi;
     61     jfieldID secure;
     62     jfieldID appVsyncOffsetNanos;
     63     jfieldID presentationDeadlineNanos;
     64 } gPhysicalDisplayInfoClassInfo;
     65 
     66 static struct {
     67     jfieldID bottom;
     68     jfieldID left;
     69     jfieldID right;
     70     jfieldID top;
     71 } gRectClassInfo;
     72 
     73 // Implements SkMallocPixelRef::ReleaseProc, to delete the screenshot on unref.
     74 void DeleteScreenshot(void* addr, void* context) {
     75     SkASSERT(addr == ((ScreenshotClient*) context)->getPixels());
     76     delete ((ScreenshotClient*) context);
     77 }
     78 
     79 static struct {
     80     nsecs_t UNDEFINED_TIME_NANO;
     81     jmethodID init;
     82 } gWindowContentFrameStatsClassInfo;
     83 
     84 static struct {
     85     nsecs_t UNDEFINED_TIME_NANO;
     86     jmethodID init;
     87 } gWindowAnimationFrameStatsClassInfo;
     88 
     89 static struct {
     90     jclass clazz;
     91     jmethodID ctor;
     92 } gHdrCapabilitiesClassInfo;
     93 
     94 static struct {
     95     jclass clazz;
     96     jmethodID builder;
     97 } gGraphicBufferClassInfo;
     98 
     99 // ----------------------------------------------------------------------------
    100 
    101 static jlong nativeCreate(JNIEnv* env, jclass clazz, jobject sessionObj,
    102         jstring nameStr, jint w, jint h, jint format, jint flags, jlong parentObject,
    103         jint windowType, jint ownerUid) {
    104     ScopedUtfChars name(env, nameStr);
    105     sp<SurfaceComposerClient> client(android_view_SurfaceSession_getClient(env, sessionObj));
    106     SurfaceControl *parent = reinterpret_cast<SurfaceControl*>(parentObject);
    107     sp<SurfaceControl> surface = client->createSurface(
    108             String8(name.c_str()), w, h, format, flags, parent, windowType, ownerUid);
    109     if (surface == NULL) {
    110         jniThrowException(env, OutOfResourcesException, NULL);
    111         return 0;
    112     }
    113 
    114     surface->incStrong((void *)nativeCreate);
    115     return reinterpret_cast<jlong>(surface.get());
    116 }
    117 
    118 static void nativeRelease(JNIEnv* env, jclass clazz, jlong nativeObject) {
    119     sp<SurfaceControl> ctrl(reinterpret_cast<SurfaceControl *>(nativeObject));
    120     ctrl->decStrong((void *)nativeCreate);
    121 }
    122 
    123 static void nativeDestroy(JNIEnv* env, jclass clazz, jlong nativeObject) {
    124     sp<SurfaceControl> ctrl(reinterpret_cast<SurfaceControl *>(nativeObject));
    125     ctrl->clear();
    126     ctrl->decStrong((void *)nativeCreate);
    127 }
    128 
    129 static void nativeDisconnect(JNIEnv* env, jclass clazz, jlong nativeObject) {
    130     SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
    131     if (ctrl != NULL) {
    132         ctrl->disconnect();
    133     }
    134 }
    135 
    136 static Rect rectFromObj(JNIEnv* env, jobject rectObj) {
    137     int left = env->GetIntField(rectObj, gRectClassInfo.left);
    138     int top = env->GetIntField(rectObj, gRectClassInfo.top);
    139     int right = env->GetIntField(rectObj, gRectClassInfo.right);
    140     int bottom = env->GetIntField(rectObj, gRectClassInfo.bottom);
    141     return Rect(left, top, right, bottom);
    142 }
    143 
    144 static jobject nativeScreenshotToBuffer(JNIEnv* env, jclass clazz,
    145         jobject displayTokenObj, jobject sourceCropObj, jint width, jint height,
    146         jint minLayer, jint maxLayer, bool allLayers, bool useIdentityTransform,
    147         int rotation) {
    148     sp<IBinder> displayToken = ibinderForJavaObject(env, displayTokenObj);
    149     if (displayToken == NULL) {
    150         return NULL;
    151     }
    152     Rect sourceCrop = rectFromObj(env, sourceCropObj);
    153     if (allLayers) {
    154         minLayer = INT32_MIN;
    155         maxLayer = INT32_MAX;
    156     }
    157     sp<GraphicBuffer> buffer;
    158     status_t res = ScreenshotClient::captureToBuffer(displayToken,
    159             sourceCrop, width, height, minLayer, maxLayer, useIdentityTransform,
    160             rotation, &buffer);
    161     if (res != NO_ERROR) {
    162         return NULL;
    163     }
    164 
    165     return env->CallStaticObjectMethod(gGraphicBufferClassInfo.clazz,
    166             gGraphicBufferClassInfo.builder,
    167             buffer->getWidth(),
    168             buffer->getHeight(),
    169             buffer->getPixelFormat(),
    170             (jint)buffer->getUsage(),
    171             (jlong)buffer.get());
    172 }
    173 
    174 static jobject nativeScreenshotBitmap(JNIEnv* env, jclass clazz,
    175         jobject displayTokenObj, jobject sourceCropObj, jint width, jint height,
    176         jint minLayer, jint maxLayer, bool allLayers, bool useIdentityTransform,
    177         int rotation) {
    178     sp<IBinder> displayToken = ibinderForJavaObject(env, displayTokenObj);
    179     if (displayToken == NULL) {
    180         return NULL;
    181     }
    182 
    183     Rect sourceCrop = rectFromObj(env, sourceCropObj);
    184 
    185     std::unique_ptr<ScreenshotClient> screenshot(new ScreenshotClient());
    186     status_t res;
    187     if (allLayers) {
    188         minLayer = INT32_MIN;
    189         maxLayer = INT32_MAX;
    190     }
    191 
    192     res = screenshot->update(displayToken, sourceCrop, width, height,
    193         minLayer, maxLayer, useIdentityTransform, static_cast<uint32_t>(rotation));
    194     if (res != NO_ERROR) {
    195         return NULL;
    196     }
    197 
    198     SkColorType colorType;
    199     SkAlphaType alphaType;
    200     switch (screenshot->getFormat()) {
    201         case PIXEL_FORMAT_RGBX_8888: {
    202             colorType = kRGBA_8888_SkColorType;
    203             alphaType = kOpaque_SkAlphaType;
    204             break;
    205         }
    206         case PIXEL_FORMAT_RGBA_8888: {
    207             colorType = kRGBA_8888_SkColorType;
    208             alphaType = kPremul_SkAlphaType;
    209             break;
    210         }
    211         case PIXEL_FORMAT_RGBA_FP16: {
    212             colorType = kRGBA_F16_SkColorType;
    213             alphaType = kPremul_SkAlphaType;
    214             break;
    215         }
    216         case PIXEL_FORMAT_RGB_565: {
    217             colorType = kRGB_565_SkColorType;
    218             alphaType = kOpaque_SkAlphaType;
    219             break;
    220         }
    221         default: {
    222             return NULL;
    223         }
    224     }
    225 
    226     sk_sp<SkColorSpace> colorSpace;
    227     if (screenshot->getDataSpace() == HAL_DATASPACE_DISPLAY_P3) {
    228         colorSpace = SkColorSpace::MakeRGB(
    229                 SkColorSpace::kSRGB_RenderTargetGamma, SkColorSpace::kDCIP3_D65_Gamut);
    230     } else {
    231         colorSpace = SkColorSpace::MakeSRGB();
    232     }
    233 
    234     SkImageInfo screenshotInfo = SkImageInfo::Make(screenshot->getWidth(),
    235                                                    screenshot->getHeight(),
    236                                                    colorType,
    237                                                    alphaType,
    238                                                    colorSpace);
    239 
    240     const size_t rowBytes =
    241             screenshot->getStride() * android::bytesPerPixel(screenshot->getFormat());
    242 
    243     if (!screenshotInfo.width() || !screenshotInfo.height()) {
    244         return NULL;
    245     }
    246 
    247     auto bitmap = new Bitmap(
    248             (void*) screenshot->getPixels(), (void*) screenshot.get(), DeleteScreenshot,
    249             screenshotInfo, rowBytes);
    250     screenshot.release();
    251     bitmap->setImmutable();
    252     return bitmap::createBitmap(env, bitmap,
    253             android::bitmap::kBitmapCreateFlag_Premultiplied, NULL);
    254 }
    255 
    256 static void nativeScreenshot(JNIEnv* env, jclass clazz, jobject displayTokenObj,
    257         jobject surfaceObj, jobject sourceCropObj, jint width, jint height,
    258         jint minLayer, jint maxLayer, bool allLayers, bool useIdentityTransform) {
    259     sp<IBinder> displayToken = ibinderForJavaObject(env, displayTokenObj);
    260     if (displayToken != NULL) {
    261         sp<Surface> consumer = android_view_Surface_getSurface(env, surfaceObj);
    262         if (consumer != NULL) {
    263             int left = env->GetIntField(sourceCropObj, gRectClassInfo.left);
    264             int top = env->GetIntField(sourceCropObj, gRectClassInfo.top);
    265             int right = env->GetIntField(sourceCropObj, gRectClassInfo.right);
    266             int bottom = env->GetIntField(sourceCropObj, gRectClassInfo.bottom);
    267             Rect sourceCrop(left, top, right, bottom);
    268 
    269             if (allLayers) {
    270                 minLayer = INT32_MIN;
    271                 maxLayer = INT32_MAX;
    272             }
    273             ScreenshotClient::capture(displayToken,
    274                     consumer->getIGraphicBufferProducer(), sourceCrop,
    275                     width, height, minLayer, maxLayer,
    276                     useIdentityTransform);
    277         }
    278     }
    279 }
    280 
    281 static void nativeOpenTransaction(JNIEnv* env, jclass clazz) {
    282     SurfaceComposerClient::openGlobalTransaction();
    283 }
    284 
    285 
    286 static void nativeCloseTransaction(JNIEnv* env, jclass clazz, jboolean sync) {
    287     SurfaceComposerClient::closeGlobalTransaction(sync);
    288 }
    289 
    290 static void nativeSetAnimationTransaction(JNIEnv* env, jclass clazz) {
    291     SurfaceComposerClient::setAnimationTransaction();
    292 }
    293 
    294 static void nativeSetLayer(JNIEnv* env, jclass clazz, jlong nativeObject, jint zorder) {
    295     SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
    296     status_t err = ctrl->setLayer(zorder);
    297     if (err < 0 && err != NO_INIT) {
    298         doThrowIAE(env);
    299     }
    300 }
    301 
    302 static void nativeSetRelativeLayer(JNIEnv* env, jclass clazz, jlong nativeObject,
    303         jobject relativeTo, jint zorder) {
    304     auto ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
    305     sp<IBinder> handle = ibinderForJavaObject(env, relativeTo);
    306 
    307     ctrl->setRelativeLayer(handle, zorder);
    308 }
    309 
    310 static void nativeSetPosition(JNIEnv* env, jclass clazz, jlong nativeObject, jfloat x, jfloat y) {
    311     SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
    312     status_t err = ctrl->setPosition(x, y);
    313     if (err < 0 && err != NO_INIT) {
    314         doThrowIAE(env);
    315     }
    316 }
    317 
    318 static void nativeSetGeometryAppliesWithResize(JNIEnv* env, jclass clazz,
    319         jlong nativeObject) {
    320     SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
    321     status_t err = ctrl->setGeometryAppliesWithResize();
    322     if (err < 0 && err != NO_INIT) {
    323         doThrowIAE(env);
    324     }
    325 }
    326 
    327 static void nativeSetSize(JNIEnv* env, jclass clazz, jlong nativeObject, jint w, jint h) {
    328     SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
    329     status_t err = ctrl->setSize(w, h);
    330     if (err < 0 && err != NO_INIT) {
    331         doThrowIAE(env);
    332     }
    333 }
    334 
    335 static void nativeSetFlags(JNIEnv* env, jclass clazz, jlong nativeObject, jint flags, jint mask) {
    336     SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
    337     status_t err = ctrl->setFlags(flags, mask);
    338     if (err < 0 && err != NO_INIT) {
    339         doThrowIAE(env);
    340     }
    341 }
    342 
    343 static void nativeSetTransparentRegionHint(JNIEnv* env, jclass clazz, jlong nativeObject, jobject regionObj) {
    344     SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
    345     SkRegion* region = android_graphics_Region_getSkRegion(env, regionObj);
    346     if (!region) {
    347         doThrowIAE(env);
    348         return;
    349     }
    350 
    351     const SkIRect& b(region->getBounds());
    352     Region reg(Rect(b.fLeft, b.fTop, b.fRight, b.fBottom));
    353     if (region->isComplex()) {
    354         SkRegion::Iterator it(*region);
    355         while (!it.done()) {
    356             const SkIRect& r(it.rect());
    357             reg.addRectUnchecked(r.fLeft, r.fTop, r.fRight, r.fBottom);
    358             it.next();
    359         }
    360     }
    361 
    362     status_t err = ctrl->setTransparentRegionHint(reg);
    363     if (err < 0 && err != NO_INIT) {
    364         doThrowIAE(env);
    365     }
    366 }
    367 
    368 static void nativeSetAlpha(JNIEnv* env, jclass clazz, jlong nativeObject, jfloat alpha) {
    369     SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
    370     status_t err = ctrl->setAlpha(alpha);
    371     if (err < 0 && err != NO_INIT) {
    372         doThrowIAE(env);
    373     }
    374 }
    375 
    376 static void nativeSetMatrix(JNIEnv* env, jclass clazz, jlong nativeObject,
    377         jfloat dsdx, jfloat dtdx, jfloat dtdy, jfloat dsdy) {
    378     SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
    379     status_t err = ctrl->setMatrix(dsdx, dtdx, dtdy, dsdy);
    380     if (err < 0 && err != NO_INIT) {
    381         doThrowIAE(env);
    382     }
    383 }
    384 
    385 static void nativeSetWindowCrop(JNIEnv* env, jclass clazz, jlong nativeObject,
    386         jint l, jint t, jint r, jint b) {
    387     SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
    388     Rect crop(l, t, r, b);
    389     status_t err = ctrl->setCrop(crop);
    390     if (err < 0 && err != NO_INIT) {
    391         doThrowIAE(env);
    392     }
    393 }
    394 
    395 static void nativeSetFinalCrop(JNIEnv* env, jclass clazz, jlong nativeObject,
    396         jint l, jint t, jint r, jint b) {
    397     SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
    398     Rect crop(l, t, r, b);
    399     status_t err = ctrl->setFinalCrop(crop);
    400     if (err < 0 && err != NO_INIT) {
    401         doThrowIAE(env);
    402     }
    403 }
    404 
    405 static void nativeSetLayerStack(JNIEnv* env, jclass clazz, jlong nativeObject, jint layerStack) {
    406     SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
    407     status_t err = ctrl->setLayerStack(layerStack);
    408     if (err < 0 && err != NO_INIT) {
    409         doThrowIAE(env);
    410     }
    411 }
    412 
    413 static jobject nativeGetBuiltInDisplay(JNIEnv* env, jclass clazz, jint id) {
    414     sp<IBinder> token(SurfaceComposerClient::getBuiltInDisplay(id));
    415     return javaObjectForIBinder(env, token);
    416 }
    417 
    418 static jobject nativeCreateDisplay(JNIEnv* env, jclass clazz, jstring nameObj,
    419         jboolean secure) {
    420     ScopedUtfChars name(env, nameObj);
    421     sp<IBinder> token(SurfaceComposerClient::createDisplay(
    422             String8(name.c_str()), bool(secure)));
    423     return javaObjectForIBinder(env, token);
    424 }
    425 
    426 static void nativeDestroyDisplay(JNIEnv* env, jclass clazz, jobject tokenObj) {
    427     sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
    428     if (token == NULL) return;
    429     SurfaceComposerClient::destroyDisplay(token);
    430 }
    431 
    432 static void nativeSetDisplaySurface(JNIEnv* env, jclass clazz,
    433         jobject tokenObj, jlong nativeSurfaceObject) {
    434     sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
    435     if (token == NULL) return;
    436     sp<IGraphicBufferProducer> bufferProducer;
    437     sp<Surface> sur(reinterpret_cast<Surface *>(nativeSurfaceObject));
    438     if (sur != NULL) {
    439         bufferProducer = sur->getIGraphicBufferProducer();
    440     }
    441     status_t err = SurfaceComposerClient::setDisplaySurface(token,
    442             bufferProducer);
    443     if (err != NO_ERROR) {
    444         doThrowIAE(env, "Illegal Surface, could not enable async mode. Was this"
    445                 " Surface created with singleBufferMode?");
    446     }
    447 }
    448 
    449 static void nativeSetDisplayLayerStack(JNIEnv* env, jclass clazz,
    450         jobject tokenObj, jint layerStack) {
    451     sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
    452     if (token == NULL) return;
    453 
    454     SurfaceComposerClient::setDisplayLayerStack(token, layerStack);
    455 }
    456 
    457 static void nativeSetDisplayProjection(JNIEnv* env, jclass clazz,
    458         jobject tokenObj, jint orientation,
    459         jint layerStackRect_left, jint layerStackRect_top, jint layerStackRect_right, jint layerStackRect_bottom,
    460         jint displayRect_left, jint displayRect_top, jint displayRect_right, jint displayRect_bottom) {
    461     sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
    462     if (token == NULL) return;
    463     Rect layerStackRect(layerStackRect_left, layerStackRect_top, layerStackRect_right, layerStackRect_bottom);
    464     Rect displayRect(displayRect_left, displayRect_top, displayRect_right, displayRect_bottom);
    465     SurfaceComposerClient::setDisplayProjection(token, orientation, layerStackRect, displayRect);
    466 }
    467 
    468 static void nativeSetDisplaySize(JNIEnv* env, jclass clazz,
    469         jobject tokenObj, jint width, jint height) {
    470     sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
    471     if (token == NULL) return;
    472     SurfaceComposerClient::setDisplaySize(token, width, height);
    473 }
    474 
    475 static jobjectArray nativeGetDisplayConfigs(JNIEnv* env, jclass clazz,
    476         jobject tokenObj) {
    477     sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
    478     if (token == NULL) return NULL;
    479 
    480     Vector<DisplayInfo> configs;
    481     if (SurfaceComposerClient::getDisplayConfigs(token, &configs) != NO_ERROR ||
    482             configs.size() == 0) {
    483         return NULL;
    484     }
    485 
    486     jobjectArray configArray = env->NewObjectArray(configs.size(),
    487             gPhysicalDisplayInfoClassInfo.clazz, NULL);
    488 
    489     for (size_t c = 0; c < configs.size(); ++c) {
    490         const DisplayInfo& info = configs[c];
    491         jobject infoObj = env->NewObject(gPhysicalDisplayInfoClassInfo.clazz,
    492                 gPhysicalDisplayInfoClassInfo.ctor);
    493         env->SetIntField(infoObj, gPhysicalDisplayInfoClassInfo.width, info.w);
    494         env->SetIntField(infoObj, gPhysicalDisplayInfoClassInfo.height, info.h);
    495         env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.refreshRate, info.fps);
    496         env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.density, info.density);
    497         env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.xDpi, info.xdpi);
    498         env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.yDpi, info.ydpi);
    499         env->SetBooleanField(infoObj, gPhysicalDisplayInfoClassInfo.secure, info.secure);
    500         env->SetLongField(infoObj, gPhysicalDisplayInfoClassInfo.appVsyncOffsetNanos,
    501                 info.appVsyncOffset);
    502         env->SetLongField(infoObj, gPhysicalDisplayInfoClassInfo.presentationDeadlineNanos,
    503                 info.presentationDeadline);
    504         env->SetObjectArrayElement(configArray, static_cast<jsize>(c), infoObj);
    505         env->DeleteLocalRef(infoObj);
    506     }
    507 
    508     return configArray;
    509 }
    510 
    511 static jint nativeGetActiveConfig(JNIEnv* env, jclass clazz, jobject tokenObj) {
    512     sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
    513     if (token == NULL) return -1;
    514     return static_cast<jint>(SurfaceComposerClient::getActiveConfig(token));
    515 }
    516 
    517 static jboolean nativeSetActiveConfig(JNIEnv* env, jclass clazz, jobject tokenObj, jint id) {
    518     sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
    519     if (token == NULL) return JNI_FALSE;
    520     status_t err = SurfaceComposerClient::setActiveConfig(token, static_cast<int>(id));
    521     return err == NO_ERROR ? JNI_TRUE : JNI_FALSE;
    522 }
    523 
    524 static jintArray nativeGetDisplayColorModes(JNIEnv* env, jclass, jobject tokenObj) {
    525     sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
    526     if (token == NULL) return NULL;
    527     Vector<android_color_mode_t> colorModes;
    528     if (SurfaceComposerClient::getDisplayColorModes(token, &colorModes) != NO_ERROR ||
    529             colorModes.isEmpty()) {
    530         return NULL;
    531     }
    532 
    533     jintArray colorModesArray = env->NewIntArray(colorModes.size());
    534     if (colorModesArray == NULL) {
    535         jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
    536         return NULL;
    537     }
    538     jint* colorModesArrayValues = env->GetIntArrayElements(colorModesArray, 0);
    539     for (size_t i = 0; i < colorModes.size(); i++) {
    540         colorModesArrayValues[i] = static_cast<jint>(colorModes[i]);
    541     }
    542     env->ReleaseIntArrayElements(colorModesArray, colorModesArrayValues, 0);
    543     return colorModesArray;
    544 }
    545 
    546 static jint nativeGetActiveColorMode(JNIEnv* env, jclass, jobject tokenObj) {
    547     sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
    548     if (token == NULL) return -1;
    549     return static_cast<jint>(SurfaceComposerClient::getActiveColorMode(token));
    550 }
    551 
    552 static jboolean nativeSetActiveColorMode(JNIEnv* env, jclass,
    553         jobject tokenObj, jint colorMode) {
    554     sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
    555     if (token == NULL) return JNI_FALSE;
    556     status_t err = SurfaceComposerClient::setActiveColorMode(token,
    557             static_cast<android_color_mode_t>(colorMode));
    558     return err == NO_ERROR ? JNI_TRUE : JNI_FALSE;
    559 }
    560 
    561 static void nativeSetDisplayPowerMode(JNIEnv* env, jclass clazz, jobject tokenObj, jint mode) {
    562     sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
    563     if (token == NULL) return;
    564 
    565     android::base::Timer t;
    566     SurfaceComposerClient::setDisplayPowerMode(token, mode);
    567     if (t.duration() > 100ms) ALOGD("Excessive delay in setPowerMode()");
    568 }
    569 
    570 static jboolean nativeClearContentFrameStats(JNIEnv* env, jclass clazz, jlong nativeObject) {
    571     SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
    572     status_t err = ctrl->clearLayerFrameStats();
    573 
    574     if (err < 0 && err != NO_INIT) {
    575         doThrowIAE(env);
    576     }
    577 
    578     // The other end is not ready, just report we failed.
    579     if (err == NO_INIT) {
    580         return JNI_FALSE;
    581     }
    582 
    583     return JNI_TRUE;
    584 }
    585 
    586 static jboolean nativeGetContentFrameStats(JNIEnv* env, jclass clazz, jlong nativeObject,
    587     jobject outStats) {
    588     FrameStats stats;
    589 
    590     SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
    591     status_t err = ctrl->getLayerFrameStats(&stats);
    592     if (err < 0 && err != NO_INIT) {
    593         doThrowIAE(env);
    594     }
    595 
    596     // The other end is not ready, fine just return empty stats.
    597     if (err == NO_INIT) {
    598         return JNI_FALSE;
    599     }
    600 
    601     jlong refreshPeriodNano = static_cast<jlong>(stats.refreshPeriodNano);
    602     size_t frameCount = stats.desiredPresentTimesNano.size();
    603 
    604     jlongArray postedTimesNanoDst = env->NewLongArray(frameCount);
    605     if (postedTimesNanoDst == NULL) {
    606         return JNI_FALSE;
    607     }
    608 
    609     jlongArray presentedTimesNanoDst = env->NewLongArray(frameCount);
    610     if (presentedTimesNanoDst == NULL) {
    611         return JNI_FALSE;
    612     }
    613 
    614     jlongArray readyTimesNanoDst = env->NewLongArray(frameCount);
    615     if (readyTimesNanoDst == NULL) {
    616         return JNI_FALSE;
    617     }
    618 
    619     nsecs_t postedTimesNanoSrc[frameCount];
    620     nsecs_t presentedTimesNanoSrc[frameCount];
    621     nsecs_t readyTimesNanoSrc[frameCount];
    622 
    623     for (size_t i = 0; i < frameCount; i++) {
    624         nsecs_t postedTimeNano = stats.desiredPresentTimesNano[i];
    625         if (postedTimeNano == INT64_MAX) {
    626             postedTimeNano = gWindowContentFrameStatsClassInfo.UNDEFINED_TIME_NANO;
    627         }
    628         postedTimesNanoSrc[i] = postedTimeNano;
    629 
    630         nsecs_t presentedTimeNano = stats.actualPresentTimesNano[i];
    631         if (presentedTimeNano == INT64_MAX) {
    632             presentedTimeNano = gWindowContentFrameStatsClassInfo.UNDEFINED_TIME_NANO;
    633         }
    634         presentedTimesNanoSrc[i] = presentedTimeNano;
    635 
    636         nsecs_t readyTimeNano = stats.frameReadyTimesNano[i];
    637         if (readyTimeNano == INT64_MAX) {
    638             readyTimeNano = gWindowContentFrameStatsClassInfo.UNDEFINED_TIME_NANO;
    639         }
    640         readyTimesNanoSrc[i] = readyTimeNano;
    641     }
    642 
    643     env->SetLongArrayRegion(postedTimesNanoDst, 0, frameCount, postedTimesNanoSrc);
    644     env->SetLongArrayRegion(presentedTimesNanoDst, 0, frameCount, presentedTimesNanoSrc);
    645     env->SetLongArrayRegion(readyTimesNanoDst, 0, frameCount, readyTimesNanoSrc);
    646 
    647     env->CallVoidMethod(outStats, gWindowContentFrameStatsClassInfo.init, refreshPeriodNano,
    648             postedTimesNanoDst, presentedTimesNanoDst, readyTimesNanoDst);
    649 
    650     if (env->ExceptionCheck()) {
    651         return JNI_FALSE;
    652     }
    653 
    654     return JNI_TRUE;
    655 }
    656 
    657 static jboolean nativeClearAnimationFrameStats(JNIEnv* env, jclass clazz) {
    658     status_t err = SurfaceComposerClient::clearAnimationFrameStats();
    659 
    660     if (err < 0 && err != NO_INIT) {
    661         doThrowIAE(env);
    662     }
    663 
    664     // The other end is not ready, just report we failed.
    665     if (err == NO_INIT) {
    666         return JNI_FALSE;
    667     }
    668 
    669     return JNI_TRUE;
    670 }
    671 
    672 static jboolean nativeGetAnimationFrameStats(JNIEnv* env, jclass clazz, jobject outStats) {
    673     FrameStats stats;
    674 
    675     status_t err = SurfaceComposerClient::getAnimationFrameStats(&stats);
    676     if (err < 0 && err != NO_INIT) {
    677         doThrowIAE(env);
    678     }
    679 
    680     // The other end is not ready, fine just return empty stats.
    681     if (err == NO_INIT) {
    682         return JNI_FALSE;
    683     }
    684 
    685     jlong refreshPeriodNano = static_cast<jlong>(stats.refreshPeriodNano);
    686     size_t frameCount = stats.desiredPresentTimesNano.size();
    687 
    688     jlongArray presentedTimesNanoDst = env->NewLongArray(frameCount);
    689     if (presentedTimesNanoDst == NULL) {
    690         return JNI_FALSE;
    691     }
    692 
    693     nsecs_t presentedTimesNanoSrc[frameCount];
    694 
    695     for (size_t i = 0; i < frameCount; i++) {
    696         nsecs_t presentedTimeNano = stats.actualPresentTimesNano[i];
    697         if (presentedTimeNano == INT64_MAX) {
    698             presentedTimeNano = gWindowContentFrameStatsClassInfo.UNDEFINED_TIME_NANO;
    699         }
    700         presentedTimesNanoSrc[i] = presentedTimeNano;
    701     }
    702 
    703     env->SetLongArrayRegion(presentedTimesNanoDst, 0, frameCount, presentedTimesNanoSrc);
    704 
    705     env->CallVoidMethod(outStats, gWindowAnimationFrameStatsClassInfo.init, refreshPeriodNano,
    706             presentedTimesNanoDst);
    707 
    708     if (env->ExceptionCheck()) {
    709         return JNI_FALSE;
    710     }
    711 
    712     return JNI_TRUE;
    713 }
    714 
    715 static void nativeDeferTransactionUntil(JNIEnv* env, jclass clazz, jlong nativeObject,
    716         jobject handleObject, jlong frameNumber) {
    717     auto ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
    718     sp<IBinder> handle = ibinderForJavaObject(env, handleObject);
    719 
    720     ctrl->deferTransactionUntil(handle, frameNumber);
    721 }
    722 
    723 static void nativeDeferTransactionUntilSurface(JNIEnv* env, jclass clazz, jlong nativeObject,
    724         jlong surfaceObject, jlong frameNumber) {
    725     auto ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
    726     sp<Surface> barrier = reinterpret_cast<Surface *>(surfaceObject);
    727 
    728     ctrl->deferTransactionUntil(barrier, frameNumber);
    729 }
    730 
    731 static void nativeReparentChildren(JNIEnv* env, jclass clazz, jlong nativeObject,
    732         jobject newParentObject) {
    733     auto ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
    734     sp<IBinder> handle = ibinderForJavaObject(env, newParentObject);
    735 
    736     ctrl->reparentChildren(handle);
    737 }
    738 
    739 static void nativeSeverChildren(JNIEnv* env, jclass clazz, jlong nativeObject) {
    740     auto ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
    741     ctrl->detachChildren();
    742 }
    743 
    744 static void nativeSetOverrideScalingMode(JNIEnv* env, jclass clazz, jlong nativeObject,
    745         jint scalingMode) {
    746     auto ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
    747 
    748     ctrl->setOverrideScalingMode(scalingMode);
    749 }
    750 
    751 static jobject nativeGetHandle(JNIEnv* env, jclass clazz, jlong nativeObject) {
    752     auto ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
    753 
    754     return javaObjectForIBinder(env, ctrl->getHandle());
    755 }
    756 
    757 static jobject nativeGetHdrCapabilities(JNIEnv* env, jclass clazz, jobject tokenObject) {
    758     sp<IBinder> token(ibinderForJavaObject(env, tokenObject));
    759     if (token == NULL) return NULL;
    760 
    761     HdrCapabilities capabilities;
    762     SurfaceComposerClient::getHdrCapabilities(token, &capabilities);
    763 
    764     const auto& types = capabilities.getSupportedHdrTypes();
    765     auto typesArray = env->NewIntArray(types.size());
    766     env->SetIntArrayRegion(typesArray, 0, types.size(), types.data());
    767 
    768     return env->NewObject(gHdrCapabilitiesClassInfo.clazz, gHdrCapabilitiesClassInfo.ctor,
    769             typesArray, capabilities.getDesiredMaxLuminance(),
    770             capabilities.getDesiredMaxAverageLuminance(), capabilities.getDesiredMinLuminance());
    771 }
    772 
    773 // ----------------------------------------------------------------------------
    774 
    775 static const JNINativeMethod sSurfaceControlMethods[] = {
    776     {"nativeCreate", "(Landroid/view/SurfaceSession;Ljava/lang/String;IIIIJII)J",
    777             (void*)nativeCreate },
    778     {"nativeRelease", "(J)V",
    779             (void*)nativeRelease },
    780     {"nativeDestroy", "(J)V",
    781             (void*)nativeDestroy },
    782     {"nativeDisconnect", "(J)V",
    783             (void*)nativeDisconnect },
    784     {"nativeScreenshot", "(Landroid/os/IBinder;Landroid/graphics/Rect;IIIIZZI)Landroid/graphics/Bitmap;",
    785             (void*)nativeScreenshotBitmap },
    786     {"nativeScreenshot", "(Landroid/os/IBinder;Landroid/view/Surface;Landroid/graphics/Rect;IIIIZZ)V",
    787             (void*)nativeScreenshot },
    788     {"nativeOpenTransaction", "()V",
    789             (void*)nativeOpenTransaction },
    790     {"nativeCloseTransaction", "(Z)V",
    791             (void*)nativeCloseTransaction },
    792     {"nativeSetAnimationTransaction", "()V",
    793             (void*)nativeSetAnimationTransaction },
    794     {"nativeSetLayer", "(JI)V",
    795             (void*)nativeSetLayer },
    796     {"nativeSetRelativeLayer", "(JLandroid/os/IBinder;I)V",
    797             (void*)nativeSetRelativeLayer },
    798     {"nativeSetPosition", "(JFF)V",
    799             (void*)nativeSetPosition },
    800     {"nativeSetGeometryAppliesWithResize", "(J)V",
    801             (void*)nativeSetGeometryAppliesWithResize },
    802     {"nativeSetSize", "(JII)V",
    803             (void*)nativeSetSize },
    804     {"nativeSetTransparentRegionHint", "(JLandroid/graphics/Region;)V",
    805             (void*)nativeSetTransparentRegionHint },
    806     {"nativeSetAlpha", "(JF)V",
    807             (void*)nativeSetAlpha },
    808     {"nativeSetMatrix", "(JFFFF)V",
    809             (void*)nativeSetMatrix },
    810     {"nativeSetFlags", "(JII)V",
    811             (void*)nativeSetFlags },
    812     {"nativeSetWindowCrop", "(JIIII)V",
    813             (void*)nativeSetWindowCrop },
    814     {"nativeSetFinalCrop", "(JIIII)V",
    815             (void*)nativeSetFinalCrop },
    816     {"nativeSetLayerStack", "(JI)V",
    817             (void*)nativeSetLayerStack },
    818     {"nativeGetBuiltInDisplay", "(I)Landroid/os/IBinder;",
    819             (void*)nativeGetBuiltInDisplay },
    820     {"nativeCreateDisplay", "(Ljava/lang/String;Z)Landroid/os/IBinder;",
    821             (void*)nativeCreateDisplay },
    822     {"nativeDestroyDisplay", "(Landroid/os/IBinder;)V",
    823             (void*)nativeDestroyDisplay },
    824     {"nativeSetDisplaySurface", "(Landroid/os/IBinder;J)V",
    825             (void*)nativeSetDisplaySurface },
    826     {"nativeSetDisplayLayerStack", "(Landroid/os/IBinder;I)V",
    827             (void*)nativeSetDisplayLayerStack },
    828     {"nativeSetDisplayProjection", "(Landroid/os/IBinder;IIIIIIIII)V",
    829             (void*)nativeSetDisplayProjection },
    830     {"nativeSetDisplaySize", "(Landroid/os/IBinder;II)V",
    831             (void*)nativeSetDisplaySize },
    832     {"nativeGetDisplayConfigs", "(Landroid/os/IBinder;)[Landroid/view/SurfaceControl$PhysicalDisplayInfo;",
    833             (void*)nativeGetDisplayConfigs },
    834     {"nativeGetActiveConfig", "(Landroid/os/IBinder;)I",
    835             (void*)nativeGetActiveConfig },
    836     {"nativeSetActiveConfig", "(Landroid/os/IBinder;I)Z",
    837             (void*)nativeSetActiveConfig },
    838     {"nativeGetDisplayColorModes", "(Landroid/os/IBinder;)[I",
    839             (void*)nativeGetDisplayColorModes},
    840     {"nativeGetActiveColorMode", "(Landroid/os/IBinder;)I",
    841             (void*)nativeGetActiveColorMode},
    842     {"nativeSetActiveColorMode", "(Landroid/os/IBinder;I)Z",
    843             (void*)nativeSetActiveColorMode},
    844     {"nativeGetHdrCapabilities", "(Landroid/os/IBinder;)Landroid/view/Display$HdrCapabilities;",
    845             (void*)nativeGetHdrCapabilities },
    846     {"nativeClearContentFrameStats", "(J)Z",
    847             (void*)nativeClearContentFrameStats },
    848     {"nativeGetContentFrameStats", "(JLandroid/view/WindowContentFrameStats;)Z",
    849             (void*)nativeGetContentFrameStats },
    850     {"nativeClearAnimationFrameStats", "()Z",
    851             (void*)nativeClearAnimationFrameStats },
    852     {"nativeGetAnimationFrameStats", "(Landroid/view/WindowAnimationFrameStats;)Z",
    853             (void*)nativeGetAnimationFrameStats },
    854     {"nativeSetDisplayPowerMode", "(Landroid/os/IBinder;I)V",
    855             (void*)nativeSetDisplayPowerMode },
    856     {"nativeDeferTransactionUntil", "(JLandroid/os/IBinder;J)V",
    857             (void*)nativeDeferTransactionUntil },
    858     {"nativeDeferTransactionUntilSurface", "(JJJ)V",
    859             (void*)nativeDeferTransactionUntilSurface },
    860     {"nativeReparentChildren", "(JLandroid/os/IBinder;)V",
    861             (void*)nativeReparentChildren } ,
    862     {"nativeSeverChildren", "(J)V",
    863             (void*)nativeSeverChildren } ,
    864     {"nativeSetOverrideScalingMode", "(JI)V",
    865             (void*)nativeSetOverrideScalingMode },
    866     {"nativeGetHandle", "(J)Landroid/os/IBinder;",
    867             (void*)nativeGetHandle },
    868     {"nativeScreenshotToBuffer",
    869      "(Landroid/os/IBinder;Landroid/graphics/Rect;IIIIZZI)Landroid/graphics/GraphicBuffer;",
    870      (void*)nativeScreenshotToBuffer },
    871 };
    872 
    873 int register_android_view_SurfaceControl(JNIEnv* env)
    874 {
    875     int err = RegisterMethodsOrDie(env, "android/view/SurfaceControl",
    876             sSurfaceControlMethods, NELEM(sSurfaceControlMethods));
    877 
    878     jclass clazz = FindClassOrDie(env, "android/view/SurfaceControl$PhysicalDisplayInfo");
    879     gPhysicalDisplayInfoClassInfo.clazz = MakeGlobalRefOrDie(env, clazz);
    880     gPhysicalDisplayInfoClassInfo.ctor = GetMethodIDOrDie(env,
    881             gPhysicalDisplayInfoClassInfo.clazz, "<init>", "()V");
    882     gPhysicalDisplayInfoClassInfo.width =       GetFieldIDOrDie(env, clazz, "width", "I");
    883     gPhysicalDisplayInfoClassInfo.height =      GetFieldIDOrDie(env, clazz, "height", "I");
    884     gPhysicalDisplayInfoClassInfo.refreshRate = GetFieldIDOrDie(env, clazz, "refreshRate", "F");
    885     gPhysicalDisplayInfoClassInfo.density =     GetFieldIDOrDie(env, clazz, "density", "F");
    886     gPhysicalDisplayInfoClassInfo.xDpi =        GetFieldIDOrDie(env, clazz, "xDpi", "F");
    887     gPhysicalDisplayInfoClassInfo.yDpi =        GetFieldIDOrDie(env, clazz, "yDpi", "F");
    888     gPhysicalDisplayInfoClassInfo.secure =      GetFieldIDOrDie(env, clazz, "secure", "Z");
    889     gPhysicalDisplayInfoClassInfo.appVsyncOffsetNanos = GetFieldIDOrDie(env,
    890             clazz, "appVsyncOffsetNanos", "J");
    891     gPhysicalDisplayInfoClassInfo.presentationDeadlineNanos = GetFieldIDOrDie(env,
    892             clazz, "presentationDeadlineNanos", "J");
    893 
    894     jclass rectClazz = FindClassOrDie(env, "android/graphics/Rect");
    895     gRectClassInfo.bottom = GetFieldIDOrDie(env, rectClazz, "bottom", "I");
    896     gRectClassInfo.left =   GetFieldIDOrDie(env, rectClazz, "left", "I");
    897     gRectClassInfo.right =  GetFieldIDOrDie(env, rectClazz, "right", "I");
    898     gRectClassInfo.top =    GetFieldIDOrDie(env, rectClazz, "top", "I");
    899 
    900     jclass frameStatsClazz = FindClassOrDie(env, "android/view/FrameStats");
    901     jfieldID undefined_time_nano_field = GetStaticFieldIDOrDie(env,
    902             frameStatsClazz, "UNDEFINED_TIME_NANO", "J");
    903     nsecs_t undefined_time_nano = env->GetStaticLongField(frameStatsClazz, undefined_time_nano_field);
    904 
    905     jclass contFrameStatsClazz = FindClassOrDie(env, "android/view/WindowContentFrameStats");
    906     gWindowContentFrameStatsClassInfo.init = GetMethodIDOrDie(env,
    907             contFrameStatsClazz, "init", "(J[J[J[J)V");
    908     gWindowContentFrameStatsClassInfo.UNDEFINED_TIME_NANO = undefined_time_nano;
    909 
    910     jclass animFrameStatsClazz = FindClassOrDie(env, "android/view/WindowAnimationFrameStats");
    911     gWindowAnimationFrameStatsClassInfo.init =  GetMethodIDOrDie(env,
    912             animFrameStatsClazz, "init", "(J[J)V");
    913     gWindowAnimationFrameStatsClassInfo.UNDEFINED_TIME_NANO = undefined_time_nano;
    914 
    915     jclass hdrCapabilitiesClazz = FindClassOrDie(env, "android/view/Display$HdrCapabilities");
    916     gHdrCapabilitiesClassInfo.clazz = MakeGlobalRefOrDie(env, hdrCapabilitiesClazz);
    917     gHdrCapabilitiesClassInfo.ctor = GetMethodIDOrDie(env, hdrCapabilitiesClazz, "<init>",
    918             "([IFFF)V");
    919 
    920     jclass graphicsBufferClazz = FindClassOrDie(env, "android/graphics/GraphicBuffer");
    921     gGraphicBufferClassInfo.clazz = MakeGlobalRefOrDie(env, graphicsBufferClazz);
    922     gGraphicBufferClassInfo.builder = GetStaticMethodIDOrDie(env, graphicsBufferClazz,
    923             "createFromExisting", "(IIIIJ)Landroid/graphics/GraphicBuffer;");
    924 
    925     return err;
    926 }
    927 
    928 };
    929