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