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