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