android_view_SurfaceControl.cpp revision b933055cf3f7f8ea89bfd3bc9c37a3891ff7310a
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 jobjectArray nativeGetDisplayConfigs(JNIEnv* env, jclass clazz, 373 jobject tokenObj) { 374 sp<IBinder> token(ibinderForJavaObject(env, tokenObj)); 375 if (token == NULL) return NULL; 376 377 Vector<DisplayInfo> configs; 378 if (SurfaceComposerClient::getDisplayConfigs(token, &configs) != NO_ERROR || 379 configs.size() == 0) { 380 return NULL; 381 } 382 383 jobjectArray configArray = env->NewObjectArray(configs.size(), 384 gPhysicalDisplayInfoClassInfo.clazz, NULL); 385 386 for (size_t c = 0; c < configs.size(); ++c) { 387 const DisplayInfo& info = configs[c]; 388 jobject infoObj = env->NewObject(gPhysicalDisplayInfoClassInfo.clazz, 389 gPhysicalDisplayInfoClassInfo.ctor); 390 env->SetIntField(infoObj, gPhysicalDisplayInfoClassInfo.width, info.w); 391 env->SetIntField(infoObj, gPhysicalDisplayInfoClassInfo.height, info.h); 392 env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.refreshRate, info.fps); 393 env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.density, info.density); 394 env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.xDpi, info.xdpi); 395 env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.yDpi, info.ydpi); 396 env->SetBooleanField(infoObj, gPhysicalDisplayInfoClassInfo.secure, info.secure); 397 env->SetLongField(infoObj, gPhysicalDisplayInfoClassInfo.appVsyncOffsetNanos, 398 info.appVsyncOffset); 399 env->SetLongField(infoObj, gPhysicalDisplayInfoClassInfo.presentationDeadlineNanos, 400 info.presentationDeadline); 401 env->SetObjectArrayElement(configArray, static_cast<jsize>(c), infoObj); 402 env->DeleteLocalRef(infoObj); 403 } 404 405 return configArray; 406} 407 408static jint nativeGetActiveConfig(JNIEnv* env, jclass clazz, jobject tokenObj) { 409 sp<IBinder> token(ibinderForJavaObject(env, tokenObj)); 410 if (token == NULL) return -1; 411 return static_cast<jint>(SurfaceComposerClient::getActiveConfig(token)); 412} 413 414static jboolean nativeSetActiveConfig(JNIEnv* env, jclass clazz, jobject tokenObj, jint id) { 415 sp<IBinder> token(ibinderForJavaObject(env, tokenObj)); 416 if (token == NULL) return JNI_FALSE; 417 status_t err = SurfaceComposerClient::setActiveConfig(token, static_cast<int>(id)); 418 return err == NO_ERROR ? JNI_TRUE : JNI_FALSE; 419} 420 421static void nativeSetDisplayPowerMode(JNIEnv* env, jclass clazz, jobject tokenObj, jint mode) { 422 sp<IBinder> token(ibinderForJavaObject(env, tokenObj)); 423 if (token == NULL) return; 424 425 ALOGD_IF_SLOW(100, "Excessive delay in setPowerMode()"); 426 SurfaceComposerClient::setDisplayPowerMode(token, mode); 427} 428 429static jboolean nativeClearContentFrameStats(JNIEnv* env, jclass clazz, jlong nativeObject) { 430 SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject); 431 status_t err = ctrl->clearLayerFrameStats(); 432 433 if (err < 0 && err != NO_INIT) { 434 doThrowIAE(env); 435 } 436 437 // The other end is not ready, just report we failed. 438 if (err == NO_INIT) { 439 return JNI_FALSE; 440 } 441 442 return JNI_TRUE; 443} 444 445static jboolean nativeGetContentFrameStats(JNIEnv* env, jclass clazz, jlong nativeObject, 446 jobject outStats) { 447 FrameStats stats; 448 449 SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject); 450 status_t err = ctrl->getLayerFrameStats(&stats); 451 if (err < 0 && err != NO_INIT) { 452 doThrowIAE(env); 453 } 454 455 // The other end is not ready, fine just return empty stats. 456 if (err == NO_INIT) { 457 return JNI_FALSE; 458 } 459 460 jlong refreshPeriodNano = static_cast<jlong>(stats.refreshPeriodNano); 461 size_t frameCount = stats.desiredPresentTimesNano.size(); 462 463 jlongArray postedTimesNanoDst = env->NewLongArray(frameCount); 464 if (postedTimesNanoDst == NULL) { 465 return JNI_FALSE; 466 } 467 468 jlongArray presentedTimesNanoDst = env->NewLongArray(frameCount); 469 if (presentedTimesNanoDst == NULL) { 470 return JNI_FALSE; 471 } 472 473 jlongArray readyTimesNanoDst = env->NewLongArray(frameCount); 474 if (readyTimesNanoDst == NULL) { 475 return JNI_FALSE; 476 } 477 478 nsecs_t postedTimesNanoSrc[frameCount]; 479 nsecs_t presentedTimesNanoSrc[frameCount]; 480 nsecs_t readyTimesNanoSrc[frameCount]; 481 482 for (size_t i = 0; i < frameCount; i++) { 483 nsecs_t postedTimeNano = stats.desiredPresentTimesNano[i]; 484 if (postedTimeNano == INT64_MAX) { 485 postedTimeNano = gWindowContentFrameStatsClassInfo.UNDEFINED_TIME_NANO; 486 } 487 postedTimesNanoSrc[i] = postedTimeNano; 488 489 nsecs_t presentedTimeNano = stats.actualPresentTimesNano[i]; 490 if (presentedTimeNano == INT64_MAX) { 491 presentedTimeNano = gWindowContentFrameStatsClassInfo.UNDEFINED_TIME_NANO; 492 } 493 presentedTimesNanoSrc[i] = presentedTimeNano; 494 495 nsecs_t readyTimeNano = stats.frameReadyTimesNano[i]; 496 if (readyTimeNano == INT64_MAX) { 497 readyTimeNano = gWindowContentFrameStatsClassInfo.UNDEFINED_TIME_NANO; 498 } 499 readyTimesNanoSrc[i] = readyTimeNano; 500 } 501 502 env->SetLongArrayRegion(postedTimesNanoDst, 0, frameCount, postedTimesNanoSrc); 503 env->SetLongArrayRegion(presentedTimesNanoDst, 0, frameCount, presentedTimesNanoSrc); 504 env->SetLongArrayRegion(readyTimesNanoDst, 0, frameCount, readyTimesNanoSrc); 505 506 env->CallVoidMethod(outStats, gWindowContentFrameStatsClassInfo.init, refreshPeriodNano, 507 postedTimesNanoDst, presentedTimesNanoDst, readyTimesNanoDst); 508 509 if (env->ExceptionCheck()) { 510 return JNI_FALSE; 511 } 512 513 return JNI_TRUE; 514} 515 516static jboolean nativeClearAnimationFrameStats(JNIEnv* env, jclass clazz) { 517 status_t err = SurfaceComposerClient::clearAnimationFrameStats(); 518 519 if (err < 0 && err != NO_INIT) { 520 doThrowIAE(env); 521 } 522 523 // The other end is not ready, just report we failed. 524 if (err == NO_INIT) { 525 return JNI_FALSE; 526 } 527 528 return JNI_TRUE; 529} 530 531static jboolean nativeGetAnimationFrameStats(JNIEnv* env, jclass clazz, jobject outStats) { 532 FrameStats stats; 533 534 status_t err = SurfaceComposerClient::getAnimationFrameStats(&stats); 535 if (err < 0 && err != NO_INIT) { 536 doThrowIAE(env); 537 } 538 539 // The other end is not ready, fine just return empty stats. 540 if (err == NO_INIT) { 541 return JNI_FALSE; 542 } 543 544 jlong refreshPeriodNano = static_cast<jlong>(stats.refreshPeriodNano); 545 size_t frameCount = stats.desiredPresentTimesNano.size(); 546 547 jlongArray presentedTimesNanoDst = env->NewLongArray(frameCount); 548 if (presentedTimesNanoDst == NULL) { 549 return JNI_FALSE; 550 } 551 552 nsecs_t presentedTimesNanoSrc[frameCount]; 553 554 for (size_t i = 0; i < frameCount; i++) { 555 nsecs_t presentedTimeNano = stats.actualPresentTimesNano[i]; 556 if (presentedTimeNano == INT64_MAX) { 557 presentedTimeNano = gWindowContentFrameStatsClassInfo.UNDEFINED_TIME_NANO; 558 } 559 presentedTimesNanoSrc[i] = presentedTimeNano; 560 } 561 562 env->SetLongArrayRegion(presentedTimesNanoDst, 0, frameCount, presentedTimesNanoSrc); 563 564 env->CallVoidMethod(outStats, gWindowAnimationFrameStatsClassInfo.init, refreshPeriodNano, 565 presentedTimesNanoDst); 566 567 if (env->ExceptionCheck()) { 568 return JNI_FALSE; 569 } 570 571 return JNI_TRUE; 572} 573 574// ---------------------------------------------------------------------------- 575 576static JNINativeMethod sSurfaceControlMethods[] = { 577 {"nativeCreate", "(Landroid/view/SurfaceSession;Ljava/lang/String;IIII)J", 578 (void*)nativeCreate }, 579 {"nativeRelease", "(J)V", 580 (void*)nativeRelease }, 581 {"nativeDestroy", "(J)V", 582 (void*)nativeDestroy }, 583 {"nativeScreenshot", "(Landroid/os/IBinder;Landroid/graphics/Rect;IIIIZZ)Landroid/graphics/Bitmap;", 584 (void*)nativeScreenshotBitmap }, 585 {"nativeScreenshot", "(Landroid/os/IBinder;Landroid/view/Surface;Landroid/graphics/Rect;IIIIZZ)V", 586 (void*)nativeScreenshot }, 587 {"nativeOpenTransaction", "()V", 588 (void*)nativeOpenTransaction }, 589 {"nativeCloseTransaction", "()V", 590 (void*)nativeCloseTransaction }, 591 {"nativeSetAnimationTransaction", "()V", 592 (void*)nativeSetAnimationTransaction }, 593 {"nativeSetLayer", "(JI)V", 594 (void*)nativeSetLayer }, 595 {"nativeSetPosition", "(JFF)V", 596 (void*)nativeSetPosition }, 597 {"nativeSetSize", "(JII)V", 598 (void*)nativeSetSize }, 599 {"nativeSetTransparentRegionHint", "(JLandroid/graphics/Region;)V", 600 (void*)nativeSetTransparentRegionHint }, 601 {"nativeSetAlpha", "(JF)V", 602 (void*)nativeSetAlpha }, 603 {"nativeSetMatrix", "(JFFFF)V", 604 (void*)nativeSetMatrix }, 605 {"nativeSetFlags", "(JII)V", 606 (void*)nativeSetFlags }, 607 {"nativeSetWindowCrop", "(JIIII)V", 608 (void*)nativeSetWindowCrop }, 609 {"nativeSetLayerStack", "(JI)V", 610 (void*)nativeSetLayerStack }, 611 {"nativeGetBuiltInDisplay", "(I)Landroid/os/IBinder;", 612 (void*)nativeGetBuiltInDisplay }, 613 {"nativeCreateDisplay", "(Ljava/lang/String;Z)Landroid/os/IBinder;", 614 (void*)nativeCreateDisplay }, 615 {"nativeDestroyDisplay", "(Landroid/os/IBinder;)V", 616 (void*)nativeDestroyDisplay }, 617 {"nativeSetDisplaySurface", "(Landroid/os/IBinder;J)V", 618 (void*)nativeSetDisplaySurface }, 619 {"nativeSetDisplayLayerStack", "(Landroid/os/IBinder;I)V", 620 (void*)nativeSetDisplayLayerStack }, 621 {"nativeSetDisplayProjection", "(Landroid/os/IBinder;IIIIIIIII)V", 622 (void*)nativeSetDisplayProjection }, 623 {"nativeGetDisplayConfigs", "(Landroid/os/IBinder;)[Landroid/view/SurfaceControl$PhysicalDisplayInfo;", 624 (void*)nativeGetDisplayConfigs }, 625 {"nativeGetActiveConfig", "(Landroid/os/IBinder;)I", 626 (void*)nativeGetActiveConfig }, 627 {"nativeSetActiveConfig", "(Landroid/os/IBinder;I)Z", 628 (void*)nativeSetActiveConfig }, 629 {"nativeClearContentFrameStats", "(J)Z", 630 (void*)nativeClearContentFrameStats }, 631 {"nativeGetContentFrameStats", "(JLandroid/view/WindowContentFrameStats;)Z", 632 (void*)nativeGetContentFrameStats }, 633 {"nativeClearAnimationFrameStats", "()Z", 634 (void*)nativeClearAnimationFrameStats }, 635 {"nativeGetAnimationFrameStats", "(Landroid/view/WindowAnimationFrameStats;)Z", 636 (void*)nativeGetAnimationFrameStats }, 637 {"nativeSetDisplayPowerMode", "(Landroid/os/IBinder;I)V", 638 (void*)nativeSetDisplayPowerMode }, 639}; 640 641int register_android_view_SurfaceControl(JNIEnv* env) 642{ 643 int err = AndroidRuntime::registerNativeMethods(env, "android/view/SurfaceControl", 644 sSurfaceControlMethods, NELEM(sSurfaceControlMethods)); 645 646 jclass clazz = env->FindClass("android/view/SurfaceControl$PhysicalDisplayInfo"); 647 gPhysicalDisplayInfoClassInfo.clazz = static_cast<jclass>(env->NewGlobalRef(clazz)); 648 gPhysicalDisplayInfoClassInfo.ctor = env->GetMethodID(gPhysicalDisplayInfoClassInfo.clazz, 649 "<init>", "()V"); 650 gPhysicalDisplayInfoClassInfo.width = env->GetFieldID(clazz, "width", "I"); 651 gPhysicalDisplayInfoClassInfo.height = env->GetFieldID(clazz, "height", "I"); 652 gPhysicalDisplayInfoClassInfo.refreshRate = env->GetFieldID(clazz, "refreshRate", "F"); 653 gPhysicalDisplayInfoClassInfo.density = env->GetFieldID(clazz, "density", "F"); 654 gPhysicalDisplayInfoClassInfo.xDpi = env->GetFieldID(clazz, "xDpi", "F"); 655 gPhysicalDisplayInfoClassInfo.yDpi = env->GetFieldID(clazz, "yDpi", "F"); 656 gPhysicalDisplayInfoClassInfo.secure = env->GetFieldID(clazz, "secure", "Z"); 657 gPhysicalDisplayInfoClassInfo.appVsyncOffsetNanos = env->GetFieldID(clazz, 658 "appVsyncOffsetNanos", "J"); 659 gPhysicalDisplayInfoClassInfo.presentationDeadlineNanos = env->GetFieldID(clazz, 660 "presentationDeadlineNanos", "J"); 661 662 jclass rectClazz = env->FindClass("android/graphics/Rect"); 663 gRectClassInfo.bottom = env->GetFieldID(rectClazz, "bottom", "I"); 664 gRectClassInfo.left = env->GetFieldID(rectClazz, "left", "I"); 665 gRectClassInfo.right = env->GetFieldID(rectClazz, "right", "I"); 666 gRectClassInfo.top = env->GetFieldID(rectClazz, "top", "I"); 667 668 jclass frameStatsClazz = env->FindClass("android/view/FrameStats"); 669 jfieldID undefined_time_nano_field = env->GetStaticFieldID(frameStatsClazz, "UNDEFINED_TIME_NANO", "J"); 670 nsecs_t undefined_time_nano = env->GetStaticLongField(frameStatsClazz, undefined_time_nano_field); 671 672 jclass contFrameStatsClazz = env->FindClass("android/view/WindowContentFrameStats"); 673 gWindowContentFrameStatsClassInfo.init = env->GetMethodID(contFrameStatsClazz, "init", "(J[J[J[J)V"); 674 gWindowContentFrameStatsClassInfo.UNDEFINED_TIME_NANO = undefined_time_nano; 675 676 jclass animFrameStatsClazz = env->FindClass("android/view/WindowAnimationFrameStats"); 677 gWindowAnimationFrameStatsClassInfo.init = env->GetMethodID(animFrameStatsClazz, "init", "(J[J)V"); 678 gWindowAnimationFrameStatsClassInfo.UNDEFINED_TIME_NANO = undefined_time_nano; 679 680 return err; 681} 682 683}; 684