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