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