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