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 19 #include <stdio.h> 20 21 #include "jni.h" 22 #include "JNIHelp.h" 23 24 #include "android_os_Parcel.h" 25 #include "android_util_Binder.h" 26 #include "android/graphics/GraphicsJNI.h" 27 #include "android/graphics/Region.h" 28 29 #include <android_runtime/AndroidRuntime.h> 30 #include <android_runtime/android_view_Surface.h> 31 #include <android_runtime/android_view_SurfaceSession.h> 32 33 #include <gui/Surface.h> 34 #include <gui/SurfaceComposerClient.h> 35 36 #include <ui/DisplayInfo.h> 37 #include <ui/FrameStats.h> 38 #include <ui/Rect.h> 39 #include <ui/Region.h> 40 41 #include <utils/Log.h> 42 43 #include <ScopedUtfChars.h> 44 45 #include "SkTemplates.h" 46 47 // ---------------------------------------------------------------------------- 48 49 namespace android { 50 51 static const char* const OutOfResourcesException = 52 "android/view/Surface$OutOfResourcesException"; 53 54 static struct { 55 jclass clazz; 56 jmethodID ctor; 57 jfieldID width; 58 jfieldID height; 59 jfieldID refreshRate; 60 jfieldID density; 61 jfieldID xDpi; 62 jfieldID yDpi; 63 jfieldID secure; 64 jfieldID appVsyncOffsetNanos; 65 jfieldID presentationDeadlineNanos; 66 } gPhysicalDisplayInfoClassInfo; 67 68 static struct { 69 jfieldID bottom; 70 jfieldID left; 71 jfieldID right; 72 jfieldID top; 73 } gRectClassInfo; 74 75 // Implements SkMallocPixelRef::ReleaseProc, to delete the screenshot on unref. 76 void DeleteScreenshot(void* addr, void* context) { 77 SkASSERT(addr == ((ScreenshotClient*) context)->getPixels()); 78 delete ((ScreenshotClient*) context); 79 } 80 81 static struct { 82 nsecs_t UNDEFINED_TIME_NANO; 83 jmethodID init; 84 } gWindowContentFrameStatsClassInfo; 85 86 static struct { 87 nsecs_t UNDEFINED_TIME_NANO; 88 jmethodID init; 89 } gWindowAnimationFrameStatsClassInfo; 90 91 // ---------------------------------------------------------------------------- 92 93 static jlong nativeCreate(JNIEnv* env, jclass clazz, jobject sessionObj, 94 jstring nameStr, jint w, jint h, jint format, jint flags) { 95 ScopedUtfChars name(env, nameStr); 96 sp<SurfaceComposerClient> client(android_view_SurfaceSession_getClient(env, sessionObj)); 97 sp<SurfaceControl> surface = client->createSurface( 98 String8(name.c_str()), w, h, format, flags); 99 if (surface == NULL) { 100 jniThrowException(env, OutOfResourcesException, NULL); 101 return 0; 102 } 103 surface->incStrong((void *)nativeCreate); 104 return reinterpret_cast<jlong>(surface.get()); 105 } 106 107 static void nativeRelease(JNIEnv* env, jclass clazz, jlong nativeObject) { 108 sp<SurfaceControl> ctrl(reinterpret_cast<SurfaceControl *>(nativeObject)); 109 ctrl->decStrong((void *)nativeCreate); 110 } 111 112 static void nativeDestroy(JNIEnv* env, jclass clazz, jlong nativeObject) { 113 sp<SurfaceControl> ctrl(reinterpret_cast<SurfaceControl *>(nativeObject)); 114 ctrl->clear(); 115 ctrl->decStrong((void *)nativeCreate); 116 } 117 118 static jobject nativeScreenshotBitmap(JNIEnv* env, jclass clazz, 119 jobject displayTokenObj, jobject sourceCropObj, jint width, jint height, 120 jint minLayer, jint maxLayer, bool allLayers, bool useIdentityTransform, 121 int rotation) { 122 sp<IBinder> displayToken = ibinderForJavaObject(env, displayTokenObj); 123 if (displayToken == NULL) { 124 return NULL; 125 } 126 127 int left = env->GetIntField(sourceCropObj, gRectClassInfo.left); 128 int top = env->GetIntField(sourceCropObj, gRectClassInfo.top); 129 int right = env->GetIntField(sourceCropObj, gRectClassInfo.right); 130 int bottom = env->GetIntField(sourceCropObj, gRectClassInfo.bottom); 131 Rect sourceCrop(left, top, right, bottom); 132 133 SkAutoTDelete<ScreenshotClient> screenshot(new ScreenshotClient()); 134 status_t res; 135 if (allLayers) { 136 minLayer = 0; 137 maxLayer = -1UL; 138 } 139 140 res = screenshot->update(displayToken, sourceCrop, width, height, 141 minLayer, maxLayer, useIdentityTransform, static_cast<uint32_t>(rotation)); 142 if (res != NO_ERROR) { 143 return NULL; 144 } 145 146 SkImageInfo screenshotInfo; 147 screenshotInfo.fWidth = screenshot->getWidth(); 148 screenshotInfo.fHeight = screenshot->getHeight(); 149 150 switch (screenshot->getFormat()) { 151 case PIXEL_FORMAT_RGBX_8888: { 152 screenshotInfo.fColorType = kRGBA_8888_SkColorType; 153 screenshotInfo.fAlphaType = kIgnore_SkAlphaType; 154 break; 155 } 156 case PIXEL_FORMAT_RGBA_8888: { 157 screenshotInfo.fColorType = kRGBA_8888_SkColorType; 158 screenshotInfo.fAlphaType = kPremul_SkAlphaType; 159 break; 160 } 161 case PIXEL_FORMAT_RGB_565: { 162 screenshotInfo.fColorType = kRGB_565_SkColorType; 163 screenshotInfo.fAlphaType = kIgnore_SkAlphaType; 164 break; 165 } 166 default: { 167 return NULL; 168 } 169 } 170 171 const ssize_t rowBytes = 172 screenshot->getStride() * android::bytesPerPixel(screenshot->getFormat()); 173 174 SkBitmap* bitmap = new SkBitmap(); 175 bitmap->setInfo(screenshotInfo, (size_t)rowBytes); 176 if (screenshotInfo.fWidth > 0 && screenshotInfo.fHeight > 0) { 177 // takes ownership of ScreenshotClient 178 SkMallocPixelRef* pixels = SkMallocPixelRef::NewWithProc(screenshotInfo, 179 (size_t) rowBytes, NULL, (void*) screenshot->getPixels(), &DeleteScreenshot, 180 (void*) (screenshot.get())); 181 screenshot.detach(); 182 pixels->setImmutable(); 183 bitmap->setPixelRef(pixels)->unref(); 184 bitmap->lockPixels(); 185 } 186 187 return GraphicsJNI::createBitmap(env, bitmap, 188 GraphicsJNI::kBitmapCreateFlag_Premultiplied, NULL); 189 } 190 191 static void nativeScreenshot(JNIEnv* env, jclass clazz, jobject displayTokenObj, 192 jobject surfaceObj, jobject sourceCropObj, jint width, jint height, 193 jint minLayer, jint maxLayer, bool allLayers, bool useIdentityTransform) { 194 sp<IBinder> displayToken = ibinderForJavaObject(env, displayTokenObj); 195 if (displayToken != NULL) { 196 sp<Surface> consumer = android_view_Surface_getSurface(env, surfaceObj); 197 if (consumer != NULL) { 198 int left = env->GetIntField(sourceCropObj, gRectClassInfo.left); 199 int top = env->GetIntField(sourceCropObj, gRectClassInfo.top); 200 int right = env->GetIntField(sourceCropObj, gRectClassInfo.right); 201 int bottom = env->GetIntField(sourceCropObj, gRectClassInfo.bottom); 202 Rect sourceCrop(left, top, right, bottom); 203 204 if (allLayers) { 205 minLayer = 0; 206 maxLayer = -1; 207 } 208 ScreenshotClient::capture(displayToken, 209 consumer->getIGraphicBufferProducer(), sourceCrop, 210 width, height, uint32_t(minLayer), uint32_t(maxLayer), 211 useIdentityTransform); 212 } 213 } 214 } 215 216 static void nativeOpenTransaction(JNIEnv* env, jclass clazz) { 217 SurfaceComposerClient::openGlobalTransaction(); 218 } 219 220 static void nativeCloseTransaction(JNIEnv* env, jclass clazz) { 221 SurfaceComposerClient::closeGlobalTransaction(); 222 } 223 224 static void nativeSetAnimationTransaction(JNIEnv* env, jclass clazz) { 225 SurfaceComposerClient::setAnimationTransaction(); 226 } 227 228 static void nativeSetLayer(JNIEnv* env, jclass clazz, jlong nativeObject, jint zorder) { 229 SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject); 230 status_t err = ctrl->setLayer(zorder); 231 if (err < 0 && err != NO_INIT) { 232 doThrowIAE(env); 233 } 234 } 235 236 static void nativeSetPosition(JNIEnv* env, jclass clazz, jlong nativeObject, jfloat x, jfloat y) { 237 SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject); 238 status_t err = ctrl->setPosition(x, y); 239 if (err < 0 && err != NO_INIT) { 240 doThrowIAE(env); 241 } 242 } 243 244 static void nativeSetSize(JNIEnv* env, jclass clazz, jlong nativeObject, jint w, jint h) { 245 SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject); 246 status_t err = ctrl->setSize(w, h); 247 if (err < 0 && err != NO_INIT) { 248 doThrowIAE(env); 249 } 250 } 251 252 static void nativeSetFlags(JNIEnv* env, jclass clazz, jlong nativeObject, jint flags, jint mask) { 253 SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject); 254 status_t err = ctrl->setFlags(flags, mask); 255 if (err < 0 && err != NO_INIT) { 256 doThrowIAE(env); 257 } 258 } 259 260 static void nativeSetTransparentRegionHint(JNIEnv* env, jclass clazz, jlong nativeObject, jobject regionObj) { 261 SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject); 262 SkRegion* region = android_graphics_Region_getSkRegion(env, regionObj); 263 if (!region) { 264 doThrowIAE(env); 265 return; 266 } 267 268 const SkIRect& b(region->getBounds()); 269 Region reg(Rect(b.fLeft, b.fTop, b.fRight, b.fBottom)); 270 if (region->isComplex()) { 271 SkRegion::Iterator it(*region); 272 while (!it.done()) { 273 const SkIRect& r(it.rect()); 274 reg.addRectUnchecked(r.fLeft, r.fTop, r.fRight, r.fBottom); 275 it.next(); 276 } 277 } 278 279 status_t err = ctrl->setTransparentRegionHint(reg); 280 if (err < 0 && err != NO_INIT) { 281 doThrowIAE(env); 282 } 283 } 284 285 static void nativeSetAlpha(JNIEnv* env, jclass clazz, jlong nativeObject, jfloat alpha) { 286 SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject); 287 status_t err = ctrl->setAlpha(alpha); 288 if (err < 0 && err != NO_INIT) { 289 doThrowIAE(env); 290 } 291 } 292 293 static void nativeSetMatrix(JNIEnv* env, jclass clazz, jlong nativeObject, 294 jfloat dsdx, jfloat dtdx, jfloat dsdy, jfloat dtdy) { 295 SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject); 296 status_t err = ctrl->setMatrix(dsdx, dtdx, dsdy, dtdy); 297 if (err < 0 && err != NO_INIT) { 298 doThrowIAE(env); 299 } 300 } 301 302 static void nativeSetWindowCrop(JNIEnv* env, jclass clazz, jlong nativeObject, 303 jint l, jint t, jint r, jint b) { 304 SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject); 305 Rect crop(l, t, r, b); 306 status_t err = ctrl->setCrop(crop); 307 if (err < 0 && err != NO_INIT) { 308 doThrowIAE(env); 309 } 310 } 311 312 static void nativeSetLayerStack(JNIEnv* env, jclass clazz, jlong nativeObject, jint layerStack) { 313 SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject); 314 status_t err = ctrl->setLayerStack(layerStack); 315 if (err < 0 && err != NO_INIT) { 316 doThrowIAE(env); 317 } 318 } 319 320 static jobject nativeGetBuiltInDisplay(JNIEnv* env, jclass clazz, jint id) { 321 sp<IBinder> token(SurfaceComposerClient::getBuiltInDisplay(id)); 322 return javaObjectForIBinder(env, token); 323 } 324 325 static jobject nativeCreateDisplay(JNIEnv* env, jclass clazz, jstring nameObj, 326 jboolean secure) { 327 ScopedUtfChars name(env, nameObj); 328 sp<IBinder> token(SurfaceComposerClient::createDisplay( 329 String8(name.c_str()), bool(secure))); 330 return javaObjectForIBinder(env, token); 331 } 332 333 static void nativeDestroyDisplay(JNIEnv* env, jclass clazz, jobject tokenObj) { 334 sp<IBinder> token(ibinderForJavaObject(env, tokenObj)); 335 if (token == NULL) return; 336 SurfaceComposerClient::destroyDisplay(token); 337 } 338 339 static void nativeSetDisplaySurface(JNIEnv* env, jclass clazz, 340 jobject tokenObj, jlong nativeSurfaceObject) { 341 sp<IBinder> token(ibinderForJavaObject(env, tokenObj)); 342 if (token == NULL) return; 343 sp<IGraphicBufferProducer> bufferProducer; 344 sp<Surface> sur(reinterpret_cast<Surface *>(nativeSurfaceObject)); 345 if (sur != NULL) { 346 bufferProducer = sur->getIGraphicBufferProducer(); 347 } 348 SurfaceComposerClient::setDisplaySurface(token, bufferProducer); 349 } 350 351 static void nativeSetDisplayLayerStack(JNIEnv* env, jclass clazz, 352 jobject tokenObj, jint layerStack) { 353 sp<IBinder> token(ibinderForJavaObject(env, tokenObj)); 354 if (token == NULL) return; 355 356 SurfaceComposerClient::setDisplayLayerStack(token, layerStack); 357 } 358 359 static void nativeSetDisplayProjection(JNIEnv* env, jclass clazz, 360 jobject tokenObj, jint orientation, 361 jint layerStackRect_left, jint layerStackRect_top, jint layerStackRect_right, jint layerStackRect_bottom, 362 jint displayRect_left, jint displayRect_top, jint displayRect_right, jint displayRect_bottom) { 363 sp<IBinder> token(ibinderForJavaObject(env, tokenObj)); 364 if (token == NULL) return; 365 Rect layerStackRect(layerStackRect_left, layerStackRect_top, layerStackRect_right, layerStackRect_bottom); 366 Rect displayRect(displayRect_left, displayRect_top, displayRect_right, displayRect_bottom); 367 SurfaceComposerClient::setDisplayProjection(token, orientation, layerStackRect, displayRect); 368 } 369 370 static void nativeSetDisplaySize(JNIEnv* env, jclass clazz, 371 jobject tokenObj, jint width, jint height) { 372 sp<IBinder> token(ibinderForJavaObject(env, tokenObj)); 373 if (token == NULL) return; 374 SurfaceComposerClient::setDisplaySize(token, width, height); 375 } 376 377 static jobjectArray nativeGetDisplayConfigs(JNIEnv* env, jclass clazz, 378 jobject tokenObj) { 379 sp<IBinder> token(ibinderForJavaObject(env, tokenObj)); 380 if (token == NULL) return NULL; 381 382 Vector<DisplayInfo> configs; 383 if (SurfaceComposerClient::getDisplayConfigs(token, &configs) != NO_ERROR || 384 configs.size() == 0) { 385 return NULL; 386 } 387 388 jobjectArray configArray = env->NewObjectArray(configs.size(), 389 gPhysicalDisplayInfoClassInfo.clazz, NULL); 390 391 for (size_t c = 0; c < configs.size(); ++c) { 392 const DisplayInfo& info = configs[c]; 393 jobject infoObj = env->NewObject(gPhysicalDisplayInfoClassInfo.clazz, 394 gPhysicalDisplayInfoClassInfo.ctor); 395 env->SetIntField(infoObj, gPhysicalDisplayInfoClassInfo.width, info.w); 396 env->SetIntField(infoObj, gPhysicalDisplayInfoClassInfo.height, info.h); 397 env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.refreshRate, info.fps); 398 env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.density, info.density); 399 env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.xDpi, info.xdpi); 400 env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.yDpi, info.ydpi); 401 env->SetBooleanField(infoObj, gPhysicalDisplayInfoClassInfo.secure, info.secure); 402 env->SetLongField(infoObj, gPhysicalDisplayInfoClassInfo.appVsyncOffsetNanos, 403 info.appVsyncOffset); 404 env->SetLongField(infoObj, gPhysicalDisplayInfoClassInfo.presentationDeadlineNanos, 405 info.presentationDeadline); 406 env->SetObjectArrayElement(configArray, static_cast<jsize>(c), infoObj); 407 env->DeleteLocalRef(infoObj); 408 } 409 410 return configArray; 411 } 412 413 static jint nativeGetActiveConfig(JNIEnv* env, jclass clazz, jobject tokenObj) { 414 sp<IBinder> token(ibinderForJavaObject(env, tokenObj)); 415 if (token == NULL) return -1; 416 return static_cast<jint>(SurfaceComposerClient::getActiveConfig(token)); 417 } 418 419 static jboolean nativeSetActiveConfig(JNIEnv* env, jclass clazz, jobject tokenObj, jint id) { 420 sp<IBinder> token(ibinderForJavaObject(env, tokenObj)); 421 if (token == NULL) return JNI_FALSE; 422 status_t err = SurfaceComposerClient::setActiveConfig(token, static_cast<int>(id)); 423 return err == NO_ERROR ? JNI_TRUE : JNI_FALSE; 424 } 425 426 static void nativeSetDisplayPowerMode(JNIEnv* env, jclass clazz, jobject tokenObj, jint mode) { 427 sp<IBinder> token(ibinderForJavaObject(env, tokenObj)); 428 if (token == NULL) return; 429 430 ALOGD_IF_SLOW(100, "Excessive delay in setPowerMode()"); 431 SurfaceComposerClient::setDisplayPowerMode(token, mode); 432 } 433 434 static jboolean nativeClearContentFrameStats(JNIEnv* env, jclass clazz, jlong nativeObject) { 435 SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject); 436 status_t err = ctrl->clearLayerFrameStats(); 437 438 if (err < 0 && err != NO_INIT) { 439 doThrowIAE(env); 440 } 441 442 // The other end is not ready, just report we failed. 443 if (err == NO_INIT) { 444 return JNI_FALSE; 445 } 446 447 return JNI_TRUE; 448 } 449 450 static jboolean nativeGetContentFrameStats(JNIEnv* env, jclass clazz, jlong nativeObject, 451 jobject outStats) { 452 FrameStats stats; 453 454 SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject); 455 status_t err = ctrl->getLayerFrameStats(&stats); 456 if (err < 0 && err != NO_INIT) { 457 doThrowIAE(env); 458 } 459 460 // The other end is not ready, fine just return empty stats. 461 if (err == NO_INIT) { 462 return JNI_FALSE; 463 } 464 465 jlong refreshPeriodNano = static_cast<jlong>(stats.refreshPeriodNano); 466 size_t frameCount = stats.desiredPresentTimesNano.size(); 467 468 jlongArray postedTimesNanoDst = env->NewLongArray(frameCount); 469 if (postedTimesNanoDst == NULL) { 470 return JNI_FALSE; 471 } 472 473 jlongArray presentedTimesNanoDst = env->NewLongArray(frameCount); 474 if (presentedTimesNanoDst == NULL) { 475 return JNI_FALSE; 476 } 477 478 jlongArray readyTimesNanoDst = env->NewLongArray(frameCount); 479 if (readyTimesNanoDst == NULL) { 480 return JNI_FALSE; 481 } 482 483 nsecs_t postedTimesNanoSrc[frameCount]; 484 nsecs_t presentedTimesNanoSrc[frameCount]; 485 nsecs_t readyTimesNanoSrc[frameCount]; 486 487 for (size_t i = 0; i < frameCount; i++) { 488 nsecs_t postedTimeNano = stats.desiredPresentTimesNano[i]; 489 if (postedTimeNano == INT64_MAX) { 490 postedTimeNano = gWindowContentFrameStatsClassInfo.UNDEFINED_TIME_NANO; 491 } 492 postedTimesNanoSrc[i] = postedTimeNano; 493 494 nsecs_t presentedTimeNano = stats.actualPresentTimesNano[i]; 495 if (presentedTimeNano == INT64_MAX) { 496 presentedTimeNano = gWindowContentFrameStatsClassInfo.UNDEFINED_TIME_NANO; 497 } 498 presentedTimesNanoSrc[i] = presentedTimeNano; 499 500 nsecs_t readyTimeNano = stats.frameReadyTimesNano[i]; 501 if (readyTimeNano == INT64_MAX) { 502 readyTimeNano = gWindowContentFrameStatsClassInfo.UNDEFINED_TIME_NANO; 503 } 504 readyTimesNanoSrc[i] = readyTimeNano; 505 } 506 507 env->SetLongArrayRegion(postedTimesNanoDst, 0, frameCount, postedTimesNanoSrc); 508 env->SetLongArrayRegion(presentedTimesNanoDst, 0, frameCount, presentedTimesNanoSrc); 509 env->SetLongArrayRegion(readyTimesNanoDst, 0, frameCount, readyTimesNanoSrc); 510 511 env->CallVoidMethod(outStats, gWindowContentFrameStatsClassInfo.init, refreshPeriodNano, 512 postedTimesNanoDst, presentedTimesNanoDst, readyTimesNanoDst); 513 514 if (env->ExceptionCheck()) { 515 return JNI_FALSE; 516 } 517 518 return JNI_TRUE; 519 } 520 521 static jboolean nativeClearAnimationFrameStats(JNIEnv* env, jclass clazz) { 522 status_t err = SurfaceComposerClient::clearAnimationFrameStats(); 523 524 if (err < 0 && err != NO_INIT) { 525 doThrowIAE(env); 526 } 527 528 // The other end is not ready, just report we failed. 529 if (err == NO_INIT) { 530 return JNI_FALSE; 531 } 532 533 return JNI_TRUE; 534 } 535 536 static jboolean nativeGetAnimationFrameStats(JNIEnv* env, jclass clazz, jobject outStats) { 537 FrameStats stats; 538 539 status_t err = SurfaceComposerClient::getAnimationFrameStats(&stats); 540 if (err < 0 && err != NO_INIT) { 541 doThrowIAE(env); 542 } 543 544 // The other end is not ready, fine just return empty stats. 545 if (err == NO_INIT) { 546 return JNI_FALSE; 547 } 548 549 jlong refreshPeriodNano = static_cast<jlong>(stats.refreshPeriodNano); 550 size_t frameCount = stats.desiredPresentTimesNano.size(); 551 552 jlongArray presentedTimesNanoDst = env->NewLongArray(frameCount); 553 if (presentedTimesNanoDst == NULL) { 554 return JNI_FALSE; 555 } 556 557 nsecs_t presentedTimesNanoSrc[frameCount]; 558 559 for (size_t i = 0; i < frameCount; i++) { 560 nsecs_t presentedTimeNano = stats.actualPresentTimesNano[i]; 561 if (presentedTimeNano == INT64_MAX) { 562 presentedTimeNano = gWindowContentFrameStatsClassInfo.UNDEFINED_TIME_NANO; 563 } 564 presentedTimesNanoSrc[i] = presentedTimeNano; 565 } 566 567 env->SetLongArrayRegion(presentedTimesNanoDst, 0, frameCount, presentedTimesNanoSrc); 568 569 env->CallVoidMethod(outStats, gWindowAnimationFrameStatsClassInfo.init, refreshPeriodNano, 570 presentedTimesNanoDst); 571 572 if (env->ExceptionCheck()) { 573 return JNI_FALSE; 574 } 575 576 return JNI_TRUE; 577 } 578 579 // ---------------------------------------------------------------------------- 580 581 static JNINativeMethod sSurfaceControlMethods[] = { 582 {"nativeCreate", "(Landroid/view/SurfaceSession;Ljava/lang/String;IIII)J", 583 (void*)nativeCreate }, 584 {"nativeRelease", "(J)V", 585 (void*)nativeRelease }, 586 {"nativeDestroy", "(J)V", 587 (void*)nativeDestroy }, 588 {"nativeScreenshot", "(Landroid/os/IBinder;Landroid/graphics/Rect;IIIIZZI)Landroid/graphics/Bitmap;", 589 (void*)nativeScreenshotBitmap }, 590 {"nativeScreenshot", "(Landroid/os/IBinder;Landroid/view/Surface;Landroid/graphics/Rect;IIIIZZ)V", 591 (void*)nativeScreenshot }, 592 {"nativeOpenTransaction", "()V", 593 (void*)nativeOpenTransaction }, 594 {"nativeCloseTransaction", "()V", 595 (void*)nativeCloseTransaction }, 596 {"nativeSetAnimationTransaction", "()V", 597 (void*)nativeSetAnimationTransaction }, 598 {"nativeSetLayer", "(JI)V", 599 (void*)nativeSetLayer }, 600 {"nativeSetPosition", "(JFF)V", 601 (void*)nativeSetPosition }, 602 {"nativeSetSize", "(JII)V", 603 (void*)nativeSetSize }, 604 {"nativeSetTransparentRegionHint", "(JLandroid/graphics/Region;)V", 605 (void*)nativeSetTransparentRegionHint }, 606 {"nativeSetAlpha", "(JF)V", 607 (void*)nativeSetAlpha }, 608 {"nativeSetMatrix", "(JFFFF)V", 609 (void*)nativeSetMatrix }, 610 {"nativeSetFlags", "(JII)V", 611 (void*)nativeSetFlags }, 612 {"nativeSetWindowCrop", "(JIIII)V", 613 (void*)nativeSetWindowCrop }, 614 {"nativeSetLayerStack", "(JI)V", 615 (void*)nativeSetLayerStack }, 616 {"nativeGetBuiltInDisplay", "(I)Landroid/os/IBinder;", 617 (void*)nativeGetBuiltInDisplay }, 618 {"nativeCreateDisplay", "(Ljava/lang/String;Z)Landroid/os/IBinder;", 619 (void*)nativeCreateDisplay }, 620 {"nativeDestroyDisplay", "(Landroid/os/IBinder;)V", 621 (void*)nativeDestroyDisplay }, 622 {"nativeSetDisplaySurface", "(Landroid/os/IBinder;J)V", 623 (void*)nativeSetDisplaySurface }, 624 {"nativeSetDisplayLayerStack", "(Landroid/os/IBinder;I)V", 625 (void*)nativeSetDisplayLayerStack }, 626 {"nativeSetDisplayProjection", "(Landroid/os/IBinder;IIIIIIIII)V", 627 (void*)nativeSetDisplayProjection }, 628 {"nativeSetDisplaySize", "(Landroid/os/IBinder;II)V", 629 (void*)nativeSetDisplaySize }, 630 {"nativeGetDisplayConfigs", "(Landroid/os/IBinder;)[Landroid/view/SurfaceControl$PhysicalDisplayInfo;", 631 (void*)nativeGetDisplayConfigs }, 632 {"nativeGetActiveConfig", "(Landroid/os/IBinder;)I", 633 (void*)nativeGetActiveConfig }, 634 {"nativeSetActiveConfig", "(Landroid/os/IBinder;I)Z", 635 (void*)nativeSetActiveConfig }, 636 {"nativeClearContentFrameStats", "(J)Z", 637 (void*)nativeClearContentFrameStats }, 638 {"nativeGetContentFrameStats", "(JLandroid/view/WindowContentFrameStats;)Z", 639 (void*)nativeGetContentFrameStats }, 640 {"nativeClearAnimationFrameStats", "()Z", 641 (void*)nativeClearAnimationFrameStats }, 642 {"nativeGetAnimationFrameStats", "(Landroid/view/WindowAnimationFrameStats;)Z", 643 (void*)nativeGetAnimationFrameStats }, 644 {"nativeSetDisplayPowerMode", "(Landroid/os/IBinder;I)V", 645 (void*)nativeSetDisplayPowerMode }, 646 }; 647 648 int register_android_view_SurfaceControl(JNIEnv* env) 649 { 650 int err = AndroidRuntime::registerNativeMethods(env, "android/view/SurfaceControl", 651 sSurfaceControlMethods, NELEM(sSurfaceControlMethods)); 652 653 jclass clazz = env->FindClass("android/view/SurfaceControl$PhysicalDisplayInfo"); 654 gPhysicalDisplayInfoClassInfo.clazz = static_cast<jclass>(env->NewGlobalRef(clazz)); 655 gPhysicalDisplayInfoClassInfo.ctor = env->GetMethodID(gPhysicalDisplayInfoClassInfo.clazz, 656 "<init>", "()V"); 657 gPhysicalDisplayInfoClassInfo.width = env->GetFieldID(clazz, "width", "I"); 658 gPhysicalDisplayInfoClassInfo.height = env->GetFieldID(clazz, "height", "I"); 659 gPhysicalDisplayInfoClassInfo.refreshRate = env->GetFieldID(clazz, "refreshRate", "F"); 660 gPhysicalDisplayInfoClassInfo.density = env->GetFieldID(clazz, "density", "F"); 661 gPhysicalDisplayInfoClassInfo.xDpi = env->GetFieldID(clazz, "xDpi", "F"); 662 gPhysicalDisplayInfoClassInfo.yDpi = env->GetFieldID(clazz, "yDpi", "F"); 663 gPhysicalDisplayInfoClassInfo.secure = env->GetFieldID(clazz, "secure", "Z"); 664 gPhysicalDisplayInfoClassInfo.appVsyncOffsetNanos = env->GetFieldID(clazz, 665 "appVsyncOffsetNanos", "J"); 666 gPhysicalDisplayInfoClassInfo.presentationDeadlineNanos = env->GetFieldID(clazz, 667 "presentationDeadlineNanos", "J"); 668 669 jclass rectClazz = env->FindClass("android/graphics/Rect"); 670 gRectClassInfo.bottom = env->GetFieldID(rectClazz, "bottom", "I"); 671 gRectClassInfo.left = env->GetFieldID(rectClazz, "left", "I"); 672 gRectClassInfo.right = env->GetFieldID(rectClazz, "right", "I"); 673 gRectClassInfo.top = env->GetFieldID(rectClazz, "top", "I"); 674 675 jclass frameStatsClazz = env->FindClass("android/view/FrameStats"); 676 jfieldID undefined_time_nano_field = env->GetStaticFieldID(frameStatsClazz, "UNDEFINED_TIME_NANO", "J"); 677 nsecs_t undefined_time_nano = env->GetStaticLongField(frameStatsClazz, undefined_time_nano_field); 678 679 jclass contFrameStatsClazz = env->FindClass("android/view/WindowContentFrameStats"); 680 gWindowContentFrameStatsClassInfo.init = env->GetMethodID(contFrameStatsClazz, "init", "(J[J[J[J)V"); 681 gWindowContentFrameStatsClassInfo.UNDEFINED_TIME_NANO = undefined_time_nano; 682 683 jclass animFrameStatsClazz = env->FindClass("android/view/WindowAnimationFrameStats"); 684 gWindowAnimationFrameStatsClassInfo.init = env->GetMethodID(animFrameStatsClazz, "init", "(J[J)V"); 685 gWindowAnimationFrameStatsClassInfo.UNDEFINED_TIME_NANO = undefined_time_nano; 686 687 return err; 688 } 689 690 }; 691