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