android_view_Surface.cpp revision 64a55af0ac700baecb0877235eb42caac59a3560
1/* 2 * Copyright (C) 2007 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 "Surface" 18 19#include <stdio.h> 20 21#include "android_os_Parcel.h" 22#include "android_util_Binder.h" 23#include "android/graphics/GraphicsJNI.h" 24#include "android/graphics/Region.h" 25 26#include <binder/IMemory.h> 27 28#include <gui/ISurfaceComposer.h> 29#include <gui/Surface.h> 30#include <gui/SurfaceComposerClient.h> 31#include <gui/SurfaceTexture.h> 32 33#include <ui/DisplayInfo.h> 34#include <ui/Rect.h> 35#include <ui/Region.h> 36 37#include <EGL/egl.h> 38 39#include <SkCanvas.h> 40#include <SkBitmap.h> 41#include <SkRegion.h> 42#include <SkPixelRef.h> 43 44#include "jni.h" 45#include "JNIHelp.h" 46#include <android_runtime/AndroidRuntime.h> 47#include <android_runtime/android_view_Surface.h> 48#include <android_runtime/android_view_SurfaceSession.h> 49#include <android_runtime/android_graphics_SurfaceTexture.h> 50#include <utils/misc.h> 51 52#include <ScopedUtfChars.h> 53 54 55// ---------------------------------------------------------------------------- 56 57namespace android { 58 59static const char* const OutOfResourcesException = 60 "android/view/Surface$OutOfResourcesException"; 61 62static struct { 63 jclass clazz; 64 jfieldID mNativeSurface; 65 jfieldID mNativeSurfaceControl; 66 jfieldID mGenerationId; 67 jfieldID mCanvas; 68 jfieldID mCanvasSaveCount; 69} gSurfaceClassInfo; 70 71static struct { 72 jfieldID left; 73 jfieldID top; 74 jfieldID right; 75 jfieldID bottom; 76} gRectClassInfo; 77 78static struct { 79 jfieldID mNativeCanvas; 80 jfieldID mSurfaceFormat; 81} gCanvasClassInfo; 82 83static struct { 84 jfieldID width; 85 jfieldID height; 86 jfieldID refreshRate; 87 jfieldID density; 88 jfieldID xDpi; 89 jfieldID yDpi; 90} gPhysicalDisplayInfoClassInfo; 91 92 93class ScreenshotPixelRef : public SkPixelRef { 94public: 95 ScreenshotPixelRef(SkColorTable* ctable) { 96 fCTable = ctable; 97 SkSafeRef(ctable); 98 setImmutable(); 99 } 100 101 virtual ~ScreenshotPixelRef() { 102 SkSafeUnref(fCTable); 103 } 104 105 status_t update(const sp<IBinder>& display, int width, int height, 106 int minLayer, int maxLayer, bool allLayers) { 107 status_t res = (width > 0 && height > 0) 108 ? (allLayers 109 ? mScreenshot.update(display, width, height) 110 : mScreenshot.update(display, width, height, minLayer, maxLayer)) 111 : mScreenshot.update(display); 112 if (res != NO_ERROR) { 113 return res; 114 } 115 116 return NO_ERROR; 117 } 118 119 uint32_t getWidth() const { 120 return mScreenshot.getWidth(); 121 } 122 123 uint32_t getHeight() const { 124 return mScreenshot.getHeight(); 125 } 126 127 uint32_t getStride() const { 128 return mScreenshot.getStride(); 129 } 130 131 uint32_t getFormat() const { 132 return mScreenshot.getFormat(); 133 } 134 135protected: 136 // overrides from SkPixelRef 137 virtual void* onLockPixels(SkColorTable** ct) { 138 *ct = fCTable; 139 return (void*)mScreenshot.getPixels(); 140 } 141 142 virtual void onUnlockPixels() { 143 } 144 145private: 146 ScreenshotClient mScreenshot; 147 SkColorTable* fCTable; 148 149 typedef SkPixelRef INHERITED; 150}; 151 152 153// ---------------------------------------------------------------------------- 154 155static sp<SurfaceControl> getSurfaceControl(JNIEnv* env, jobject surfaceObj) { 156 return reinterpret_cast<SurfaceControl*>( 157 env->GetIntField(surfaceObj, gSurfaceClassInfo.mNativeSurfaceControl)); 158} 159 160static void setSurfaceControl(JNIEnv* env, jobject surfaceObj, 161 const sp<SurfaceControl>& surface) { 162 SurfaceControl* const p = reinterpret_cast<SurfaceControl*>( 163 env->GetIntField(surfaceObj, gSurfaceClassInfo.mNativeSurfaceControl)); 164 if (surface.get()) { 165 surface->incStrong(surfaceObj); 166 } 167 if (p) { 168 p->decStrong(surfaceObj); 169 } 170 env->SetIntField(surfaceObj, gSurfaceClassInfo.mNativeSurfaceControl, 171 reinterpret_cast<jint>(surface.get())); 172} 173 174static sp<Surface> getSurface(JNIEnv* env, jobject surfaceObj) { 175 sp<Surface> result(android_view_Surface_getSurface(env, surfaceObj)); 176 if (result == NULL) { 177 /* 178 * if this method is called from the WindowManager's process, it means 179 * the client is is not remote, and therefore is allowed to have 180 * a Surface (data), so we create it here. 181 * If we don't have a SurfaceControl, it means we're in a different 182 * process. 183 */ 184 185 SurfaceControl* const control = reinterpret_cast<SurfaceControl*>( 186 env->GetIntField(surfaceObj, gSurfaceClassInfo.mNativeSurfaceControl)); 187 if (control) { 188 result = control->getSurface(); 189 if (result != NULL) { 190 result->incStrong(surfaceObj); 191 env->SetIntField(surfaceObj, gSurfaceClassInfo.mNativeSurface, 192 reinterpret_cast<jint>(result.get())); 193 } 194 } 195 } 196 return result; 197} 198 199sp<ANativeWindow> android_view_Surface_getNativeWindow(JNIEnv* env, jobject surfaceObj) { 200 return getSurface(env, surfaceObj); 201} 202 203bool android_view_Surface_isInstanceOf(JNIEnv* env, jobject obj) { 204 return env->IsInstanceOf(obj, gSurfaceClassInfo.clazz); 205} 206 207sp<Surface> android_view_Surface_getSurface(JNIEnv* env, jobject surfaceObj) { 208 return reinterpret_cast<Surface*>( 209 env->GetIntField(surfaceObj, gSurfaceClassInfo.mNativeSurface)); 210} 211 212static void setSurface(JNIEnv* env, jobject surfaceObj, const sp<Surface>& surface) { 213 Surface* const p = reinterpret_cast<Surface*>( 214 env->GetIntField(surfaceObj, gSurfaceClassInfo.mNativeSurface)); 215 if (surface.get()) { 216 surface->incStrong(surfaceObj); 217 } 218 if (p) { 219 p->decStrong(surfaceObj); 220 } 221 env->SetIntField(surfaceObj, gSurfaceClassInfo.mNativeSurface, 222 reinterpret_cast<jint>(surface.get())); 223 224 // This test is conservative and it would be better to compare the ISurfaces 225 if (p && p != surface.get()) { 226 jint generationId = env->GetIntField(surfaceObj, 227 gSurfaceClassInfo.mGenerationId); 228 generationId++; 229 env->SetIntField(surfaceObj, 230 gSurfaceClassInfo.mGenerationId, generationId); 231 } 232} 233 234// ---------------------------------------------------------------------------- 235 236static void nativeCreate(JNIEnv* env, jobject surfaceObj, jobject sessionObj, 237 jstring nameStr, jint w, jint h, jint format, jint flags) { 238 ScopedUtfChars name(env, nameStr); 239 sp<SurfaceComposerClient> client(android_view_SurfaceSession_getClient(env, sessionObj)); 240 241 sp<SurfaceControl> surface = client->createSurface( 242 String8(name.c_str()), w, h, format, flags); 243 if (surface == NULL) { 244 jniThrowException(env, OutOfResourcesException, NULL); 245 return; 246 } 247 248 setSurfaceControl(env, surfaceObj, surface); 249} 250 251static void nativeCreateFromSurfaceTexture(JNIEnv* env, jobject surfaceObj, 252 jobject surfaceTextureObj) { 253 sp<SurfaceTexture> st(SurfaceTexture_getSurfaceTexture(env, surfaceTextureObj)); 254 if (st == NULL) { 255 jniThrowException(env, "java/lang/IllegalArgumentException", 256 "SurfaceTexture has already been released"); 257 return; 258 } 259 260 sp<ISurfaceTexture> bq = st->getBufferQueue(); 261 262 sp<Surface> surface(new Surface(bq)); 263 if (surface == NULL) { 264 jniThrowException(env, OutOfResourcesException, NULL); 265 return; 266 } 267 268 setSurface(env, surfaceObj, surface); 269} 270 271static void nativeRelease(JNIEnv* env, jobject surfaceObj) { 272 setSurfaceControl(env, surfaceObj, NULL); 273 setSurface(env, surfaceObj, NULL); 274} 275 276static void nativeDestroy(JNIEnv* env, jobject surfaceObj) { 277 sp<SurfaceControl> surfaceControl(getSurfaceControl(env, surfaceObj)); 278 if (SurfaceControl::isValid(surfaceControl)) { 279 surfaceControl->clear(); 280 } 281 setSurfaceControl(env, surfaceObj, NULL); 282 setSurface(env, surfaceObj, NULL); 283} 284 285static jboolean nativeIsValid(JNIEnv* env, jobject surfaceObj) { 286 sp<SurfaceControl> surfaceControl(getSurfaceControl(env, surfaceObj)); 287 if (surfaceControl != NULL) { 288 return SurfaceControl::isValid(surfaceControl) ? JNI_TRUE : JNI_FALSE; 289 } 290 291 sp<Surface> surface(getSurface(env, surfaceObj)); 292 return Surface::isValid(surface) ? JNI_TRUE : JNI_FALSE; 293} 294 295static jint nativeGetIdentity(JNIEnv* env, jobject surfaceObj) { 296 sp<SurfaceControl> control(getSurfaceControl(env, surfaceObj)); 297 if (control != NULL) { 298 return jint(control->getIdentity()); 299 } 300 301 sp<Surface> surface(getSurface(env, surfaceObj)); 302 if (surface != NULL) { 303 return jint(surface->getIdentity()); 304 } 305 306 return -1; 307} 308 309static jboolean nativeIsConsumerRunningBehind(JNIEnv* env, jobject surfaceObj) { 310 sp<Surface> surface(getSurface(env, surfaceObj)); 311 if (!Surface::isValid(surface)) { 312 doThrowIAE(env); 313 return JNI_FALSE; 314 } 315 316 int value = 0; 317 ANativeWindow* anw = static_cast<ANativeWindow*>(surface.get()); 318 anw->query(anw, NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND, &value); 319 return value; 320} 321 322static inline SkBitmap::Config convertPixelFormat(PixelFormat format) { 323 /* note: if PIXEL_FORMAT_RGBX_8888 means that all alpha bytes are 0xFF, then 324 we can map to SkBitmap::kARGB_8888_Config, and optionally call 325 bitmap.setIsOpaque(true) on the resulting SkBitmap (as an accelerator) 326 */ 327 switch (format) { 328 case PIXEL_FORMAT_RGBX_8888: return SkBitmap::kARGB_8888_Config; 329 case PIXEL_FORMAT_RGBA_8888: return SkBitmap::kARGB_8888_Config; 330 case PIXEL_FORMAT_RGBA_4444: return SkBitmap::kARGB_4444_Config; 331 case PIXEL_FORMAT_RGB_565: return SkBitmap::kRGB_565_Config; 332 case PIXEL_FORMAT_A_8: return SkBitmap::kA8_Config; 333 default: return SkBitmap::kNo_Config; 334 } 335} 336 337static jobject nativeLockCanvas(JNIEnv* env, jobject surfaceObj, jobject dirtyRectObj) { 338 sp<Surface> surface(getSurface(env, surfaceObj)); 339 if (!Surface::isValid(surface)) { 340 doThrowIAE(env); 341 return NULL; 342 } 343 344 // get dirty region 345 Region dirtyRegion; 346 if (dirtyRectObj) { 347 Rect dirty; 348 dirty.left = env->GetIntField(dirtyRectObj, gRectClassInfo.left); 349 dirty.top = env->GetIntField(dirtyRectObj, gRectClassInfo.top); 350 dirty.right = env->GetIntField(dirtyRectObj, gRectClassInfo.right); 351 dirty.bottom = env->GetIntField(dirtyRectObj, gRectClassInfo.bottom); 352 if (!dirty.isEmpty()) { 353 dirtyRegion.set(dirty); 354 } 355 } else { 356 dirtyRegion.set(Rect(0x3FFF, 0x3FFF)); 357 } 358 359 Surface::SurfaceInfo info; 360 status_t err = surface->lock(&info, &dirtyRegion); 361 if (err < 0) { 362 const char* const exception = (err == NO_MEMORY) ? 363 OutOfResourcesException : 364 "java/lang/IllegalArgumentException"; 365 jniThrowException(env, exception, NULL); 366 return NULL; 367 } 368 369 // Associate a SkCanvas object to this surface 370 jobject canvasObj = env->GetObjectField(surfaceObj, gSurfaceClassInfo.mCanvas); 371 env->SetIntField(canvasObj, gCanvasClassInfo.mSurfaceFormat, info.format); 372 373 SkCanvas* nativeCanvas = reinterpret_cast<SkCanvas*>( 374 env->GetIntField(canvasObj, gCanvasClassInfo.mNativeCanvas)); 375 SkBitmap bitmap; 376 ssize_t bpr = info.s * bytesPerPixel(info.format); 377 bitmap.setConfig(convertPixelFormat(info.format), info.w, info.h, bpr); 378 if (info.format == PIXEL_FORMAT_RGBX_8888) { 379 bitmap.setIsOpaque(true); 380 } 381 if (info.w > 0 && info.h > 0) { 382 bitmap.setPixels(info.bits); 383 } else { 384 // be safe with an empty bitmap. 385 bitmap.setPixels(NULL); 386 } 387 nativeCanvas->setBitmapDevice(bitmap); 388 389 SkRegion clipReg; 390 if (dirtyRegion.isRect()) { // very common case 391 const Rect b(dirtyRegion.getBounds()); 392 clipReg.setRect(b.left, b.top, b.right, b.bottom); 393 } else { 394 size_t count; 395 Rect const* r = dirtyRegion.getArray(&count); 396 while (count) { 397 clipReg.op(r->left, r->top, r->right, r->bottom, SkRegion::kUnion_Op); 398 r++, count--; 399 } 400 } 401 402 nativeCanvas->clipRegion(clipReg); 403 404 int saveCount = nativeCanvas->save(); 405 env->SetIntField(surfaceObj, gSurfaceClassInfo.mCanvasSaveCount, saveCount); 406 407 if (dirtyRectObj) { 408 const Rect& bounds(dirtyRegion.getBounds()); 409 env->SetIntField(dirtyRectObj, gRectClassInfo.left, bounds.left); 410 env->SetIntField(dirtyRectObj, gRectClassInfo.top, bounds.top); 411 env->SetIntField(dirtyRectObj, gRectClassInfo.right, bounds.right); 412 env->SetIntField(dirtyRectObj, gRectClassInfo.bottom, bounds.bottom); 413 } 414 415 return canvasObj; 416} 417 418static void nativeUnlockCanvasAndPost(JNIEnv* env, jobject surfaceObj, jobject canvasObj) { 419 jobject ownCanvasObj = env->GetObjectField(surfaceObj, gSurfaceClassInfo.mCanvas); 420 if (!env->IsSameObject(ownCanvasObj, canvasObj)) { 421 doThrowIAE(env); 422 return; 423 } 424 425 sp<Surface> surface(getSurface(env, surfaceObj)); 426 if (!Surface::isValid(surface)) { 427 return; 428 } 429 430 // detach the canvas from the surface 431 SkCanvas* nativeCanvas = reinterpret_cast<SkCanvas*>( 432 env->GetIntField(canvasObj, gCanvasClassInfo.mNativeCanvas)); 433 int saveCount = env->GetIntField(surfaceObj, gSurfaceClassInfo.mCanvasSaveCount); 434 nativeCanvas->restoreToCount(saveCount); 435 nativeCanvas->setBitmapDevice(SkBitmap()); 436 env->SetIntField(surfaceObj, gSurfaceClassInfo.mCanvasSaveCount, 0); 437 438 // unlock surface 439 status_t err = surface->unlockAndPost(); 440 if (err < 0) { 441 doThrowIAE(env); 442 } 443} 444 445static jobject nativeScreenshot(JNIEnv* env, jclass clazz, jobject displayTokenObj, 446 jint width, jint height, jint minLayer, jint maxLayer, bool allLayers) { 447 sp<IBinder> displayToken = ibinderForJavaObject(env, displayTokenObj); 448 if (displayToken == NULL) { 449 return NULL; 450 } 451 452 ScreenshotPixelRef* pixels = new ScreenshotPixelRef(NULL); 453 if (pixels->update(displayToken, width, height, 454 minLayer, maxLayer, allLayers) != NO_ERROR) { 455 delete pixels; 456 return NULL; 457 } 458 459 uint32_t w = pixels->getWidth(); 460 uint32_t h = pixels->getHeight(); 461 uint32_t s = pixels->getStride(); 462 uint32_t f = pixels->getFormat(); 463 ssize_t bpr = s * android::bytesPerPixel(f); 464 465 SkBitmap* bitmap = new SkBitmap(); 466 bitmap->setConfig(convertPixelFormat(f), w, h, bpr); 467 if (f == PIXEL_FORMAT_RGBX_8888) { 468 bitmap->setIsOpaque(true); 469 } 470 471 if (w > 0 && h > 0) { 472 bitmap->setPixelRef(pixels)->unref(); 473 bitmap->lockPixels(); 474 } else { 475 // be safe with an empty bitmap. 476 delete pixels; 477 bitmap->setPixels(NULL); 478 } 479 480 return GraphicsJNI::createBitmap(env, bitmap, false, NULL); 481} 482 483static void nativeOpenTransaction(JNIEnv* env, jclass clazz) { 484 SurfaceComposerClient::openGlobalTransaction(); 485} 486 487static void nativeCloseTransaction(JNIEnv* env, jclass clazz) { 488 SurfaceComposerClient::closeGlobalTransaction(); 489} 490 491static void nativeSetLayer(JNIEnv* env, jobject surfaceObj, jint zorder) { 492 sp<SurfaceControl> surface(getSurfaceControl(env, surfaceObj)); 493 if (surface == NULL) return; 494 495 status_t err = surface->setLayer(zorder); 496 if (err < 0 && err != NO_INIT) { 497 doThrowIAE(env); 498 } 499} 500 501static void nativeSetPosition(JNIEnv* env, jobject surfaceObj, jfloat x, jfloat y) { 502 sp<SurfaceControl> surface(getSurfaceControl(env, surfaceObj)); 503 if (surface == NULL) return; 504 505 status_t err = surface->setPosition(x, y); 506 if (err < 0 && err != NO_INIT) { 507 doThrowIAE(env); 508 } 509} 510 511static void nativeSetSize(JNIEnv* env, jobject surfaceObj, jint w, jint h) { 512 sp<SurfaceControl> surface(getSurfaceControl(env, surfaceObj)); 513 if (surface == NULL) return; 514 515 status_t err = surface->setSize(w, h); 516 if (err < 0 && err != NO_INIT) { 517 doThrowIAE(env); 518 } 519} 520 521static void nativeSetFlags(JNIEnv* env, jobject surfaceObj, jint flags, jint mask) { 522 sp<SurfaceControl> surface(getSurfaceControl(env, surfaceObj)); 523 if (surface == NULL) return; 524 525 status_t err = surface->setFlags(flags, mask); 526 if (err < 0 && err != NO_INIT) { 527 doThrowIAE(env); 528 } 529} 530 531static void nativeSetTransparentRegionHint(JNIEnv* env, jobject surfaceObj, jobject regionObj) { 532 sp<SurfaceControl> surface(getSurfaceControl(env, surfaceObj)); 533 if (surface == NULL) return; 534 535 SkRegion* region = android_graphics_Region_getSkRegion(env, regionObj); 536 if (!region) { 537 doThrowIAE(env); 538 return; 539 } 540 541 const SkIRect& b(region->getBounds()); 542 Region reg(Rect(b.fLeft, b.fTop, b.fRight, b.fBottom)); 543 if (region->isComplex()) { 544 SkRegion::Iterator it(*region); 545 while (!it.done()) { 546 const SkIRect& r(it.rect()); 547 reg.addRectUnchecked(r.fLeft, r.fTop, r.fRight, r.fBottom); 548 it.next(); 549 } 550 } 551 552 status_t err = surface->setTransparentRegionHint(reg); 553 if (err < 0 && err != NO_INIT) { 554 doThrowIAE(env); 555 } 556} 557 558static void nativeSetAlpha(JNIEnv* env, jobject surfaceObj, jfloat alpha) { 559 sp<SurfaceControl> surface(getSurfaceControl(env, surfaceObj)); 560 if (surface == NULL) return; 561 562 status_t err = surface->setAlpha(alpha); 563 if (err < 0 && err != NO_INIT) { 564 doThrowIAE(env); 565 } 566} 567 568static void nativeSetMatrix(JNIEnv* env, jobject surfaceObj, 569 jfloat dsdx, jfloat dtdx, jfloat dsdy, jfloat dtdy) { 570 sp<SurfaceControl> surface(getSurfaceControl(env, surfaceObj)); 571 if (surface == NULL) return; 572 573 status_t err = surface->setMatrix(dsdx, dtdx, dsdy, dtdy); 574 if (err < 0 && err != NO_INIT) { 575 doThrowIAE(env); 576 } 577} 578 579static void nativeSetWindowCrop(JNIEnv* env, jobject surfaceObj, jobject cropObj) { 580 const sp<SurfaceControl>& surface(getSurfaceControl(env, surfaceObj)); 581 if (surface == NULL) return; 582 583 Rect crop; 584 if (cropObj) { 585 crop.left = env->GetIntField(cropObj, gRectClassInfo.left); 586 crop.top = env->GetIntField(cropObj, gRectClassInfo.top); 587 crop.right = env->GetIntField(cropObj, gRectClassInfo.right); 588 crop.bottom = env->GetIntField(cropObj, gRectClassInfo.bottom); 589 } else { 590 crop.left = crop.top = crop.right = crop.bottom = 0; 591 } 592 593 status_t err = surface->setCrop(crop); 594 if (err < 0 && err != NO_INIT) { 595 doThrowIAE(env); 596 } 597} 598 599static void nativeSetLayerStack(JNIEnv* env, jobject surfaceObj, jint layerStack) { 600 sp<SurfaceControl> surface(getSurfaceControl(env, surfaceObj)); 601 if (surface == NULL) return; 602 603 status_t err = surface->setLayerStack(layerStack); 604 if (err < 0 && err != NO_INIT) { 605 doThrowIAE(env); 606 } 607} 608 609static jobject nativeGetBuiltInDisplay(JNIEnv* env, jclass clazz, jint id) { 610 sp<IBinder> token(SurfaceComposerClient::getBuiltInDisplay(id)); 611 return javaObjectForIBinder(env, token); 612} 613 614static jobject nativeCreateDisplay(JNIEnv* env, jclass clazz, jstring nameObj) { 615 ScopedUtfChars name(env, nameObj); 616 // TODO: pass the name to SF. 617 sp<IBinder> token(SurfaceComposerClient::createDisplay()); 618 return javaObjectForIBinder(env, token); 619} 620 621static void nativeSetDisplaySurface(JNIEnv* env, jclass clazz, 622 jobject tokenObj, jobject surfaceTextureObj) { 623 sp<IBinder> token(ibinderForJavaObject(env, tokenObj)); 624 if (token == NULL) return; 625 626 if (!surfaceTextureObj) { 627 SurfaceComposerClient::setDisplaySurface(token, NULL); 628 return; 629 } 630 631 sp<SurfaceTexture> st(SurfaceTexture_getSurfaceTexture(env, surfaceTextureObj)); 632 if (st == NULL) { 633 jniThrowException(env, "java/lang/IllegalArgumentException", 634 "SurfaceTexture has already been released"); 635 return; 636 } 637 638 sp<ISurfaceTexture> bq = st->getBufferQueue(); 639 SurfaceComposerClient::setDisplaySurface(token, bq); 640} 641 642static void nativeSetDisplayLayerStack(JNIEnv* env, jclass clazz, 643 jobject tokenObj, jint layerStack) { 644 sp<IBinder> token(ibinderForJavaObject(env, tokenObj)); 645 if (token == NULL) return; 646 647 SurfaceComposerClient::setDisplayLayerStack(token, layerStack); 648} 649 650static void nativeSetDisplayOrientation(JNIEnv* env, jclass clazz, 651 jobject tokenObj, jint orientation) { 652 sp<IBinder> token(ibinderForJavaObject(env, tokenObj)); 653 if (token == NULL) return; 654 655 SurfaceComposerClient::setDisplayOrientation(token, orientation); 656} 657 658static void nativeSetDisplayViewport(JNIEnv* env, jclass clazz, 659 jobject tokenObj, jobject rectObj) { 660 sp<IBinder> token(ibinderForJavaObject(env, tokenObj)); 661 if (token == NULL) return; 662 663 Rect rect; 664 rect.left = env->GetIntField(rectObj, gRectClassInfo.left); 665 rect.top = env->GetIntField(rectObj, gRectClassInfo.top); 666 rect.right = env->GetIntField(rectObj, gRectClassInfo.right); 667 rect.bottom = env->GetIntField(rectObj, gRectClassInfo.bottom); 668 SurfaceComposerClient::setDisplayViewport(token, rect); 669} 670 671static void nativeSetDisplayFrame(JNIEnv* env, jclass clazz, 672 jobject tokenObj, jobject rectObj) { 673 sp<IBinder> token(ibinderForJavaObject(env, tokenObj)); 674 if (token == NULL) return; 675 676 Rect rect; 677 rect.left = env->GetIntField(rectObj, gRectClassInfo.left); 678 rect.top = env->GetIntField(rectObj, gRectClassInfo.top); 679 rect.right = env->GetIntField(rectObj, gRectClassInfo.right); 680 rect.bottom = env->GetIntField(rectObj, gRectClassInfo.bottom); 681 SurfaceComposerClient::setDisplayFrame(token, rect); 682} 683 684static jboolean nativeGetDisplayInfo(JNIEnv* env, jclass clazz, 685 jobject tokenObj, jobject infoObj) { 686 sp<IBinder> token(ibinderForJavaObject(env, tokenObj)); 687 if (token == NULL) return JNI_FALSE; 688 689 DisplayInfo info; 690 if (SurfaceComposerClient::getDisplayInfo(token, &info)) { 691 return JNI_FALSE; 692 } 693 694 env->SetIntField(infoObj, gPhysicalDisplayInfoClassInfo.width, info.w); 695 env->SetIntField(infoObj, gPhysicalDisplayInfoClassInfo.height, info.h); 696 env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.refreshRate, info.fps); 697 env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.density, info.density); 698 env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.xDpi, info.xdpi); 699 env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.yDpi, info.ydpi); 700 return JNI_TRUE; 701} 702 703// ---------------------------------------------------------------------------- 704 705static void nativeCopyFrom(JNIEnv* env, jobject surfaceObj, jobject otherObj) { 706 /* 707 * This is used by the WindowManagerService just after constructing 708 * a Surface and is necessary for returning the Surface reference to 709 * the caller. At this point, we should only have a SurfaceControl. 710 */ 711 712 sp<SurfaceControl> surface(getSurfaceControl(env, surfaceObj)); 713 sp<SurfaceControl> other(getSurfaceControl(env, otherObj)); 714 if (!SurfaceControl::isSameSurface(surface, other)) { 715 // we reassign the surface only if it's a different one 716 // otherwise we would loose our client-side state. 717 setSurfaceControl(env, surfaceObj, other); 718 } 719} 720 721static void nativeTransferFrom(JNIEnv* env, jobject surfaceObj, jobject otherObj) { 722 sp<SurfaceControl> control(getSurfaceControl(env, otherObj)); 723 sp<Surface> surface(android_view_Surface_getSurface(env, otherObj)); 724 setSurfaceControl(env, surfaceObj, control); 725 setSurface(env, surfaceObj, surface); 726 setSurfaceControl(env, otherObj, NULL); 727 setSurface(env, otherObj, NULL); 728} 729 730static void nativeReadFromParcel(JNIEnv* env, jobject surfaceObj, jobject parcelObj) { 731 Parcel* parcel = parcelForJavaObject(env, parcelObj); 732 if (parcel == NULL) { 733 doThrowNPE(env); 734 return; 735 } 736 737 sp<Surface> surface(Surface::readFromParcel(*parcel)); 738 setSurfaceControl(env, surfaceObj, NULL); 739 setSurface(env, surfaceObj, surface); 740} 741 742static void nativeWriteToParcel(JNIEnv* env, jobject surfaceObj, jobject parcelObj) { 743 Parcel* parcel = parcelForJavaObject(env, parcelObj); 744 if (parcel == NULL) { 745 doThrowNPE(env); 746 return; 747 } 748 749 // The Java instance may have a SurfaceControl (in the case of the 750 // WindowManager or a system app). In that case, we defer to the 751 // SurfaceControl to send its ISurface. Otherwise, if the Surface is 752 // available we let it parcel itself. Finally, if the Surface is also 753 // NULL we fall back to using the SurfaceControl path which sends an 754 // empty surface; this matches legacy behavior. 755 sp<SurfaceControl> control(getSurfaceControl(env, surfaceObj)); 756 if (control != NULL) { 757 SurfaceControl::writeSurfaceToParcel(control, parcel); 758 } else { 759 sp<Surface> surface(android_view_Surface_getSurface(env, surfaceObj)); 760 if (surface != NULL) { 761 Surface::writeToParcel(surface, parcel); 762 } else { 763 SurfaceControl::writeSurfaceToParcel(NULL, parcel); 764 } 765 } 766} 767 768// ---------------------------------------------------------------------------- 769 770static JNINativeMethod gSurfaceMethods[] = { 771 {"nativeCreate", "(Landroid/view/SurfaceSession;Ljava/lang/String;IIII)V", 772 (void*)nativeCreate }, 773 {"nativeCreateFromSurfaceTexture", "(Landroid/graphics/SurfaceTexture;)V", 774 (void*)nativeCreateFromSurfaceTexture }, 775 {"nativeRelease", "()V", 776 (void*)nativeRelease }, 777 {"nativeDestroy", "()V", 778 (void*)nativeDestroy }, 779 {"nativeIsValid", "()Z", 780 (void*)nativeIsValid }, 781 {"nativeGetIdentity", "()I", 782 (void*)nativeGetIdentity }, 783 {"nativeIsConsumerRunningBehind", "()Z", 784 (void*)nativeIsConsumerRunningBehind }, 785 {"nativeLockCanvas", "(Landroid/graphics/Rect;)Landroid/graphics/Canvas;", 786 (void*)nativeLockCanvas }, 787 {"nativeUnlockCanvasAndPost", "(Landroid/graphics/Canvas;)V", 788 (void*)nativeUnlockCanvasAndPost }, 789 {"nativeScreenshot", "(Landroid/os/IBinder;IIIIZ)Landroid/graphics/Bitmap;", 790 (void*)nativeScreenshot }, 791 {"nativeOpenTransaction", "()V", 792 (void*)nativeOpenTransaction }, 793 {"nativeCloseTransaction", "()V", 794 (void*)nativeCloseTransaction }, 795 {"nativeSetLayer", "(I)V", 796 (void*)nativeSetLayer }, 797 {"nativeSetPosition", "(FF)V", 798 (void*)nativeSetPosition }, 799 {"nativeSetSize", "(II)V", 800 (void*)nativeSetSize }, 801 {"nativeSetTransparentRegionHint", "(Landroid/graphics/Region;)V", 802 (void*)nativeSetTransparentRegionHint }, 803 {"nativeSetAlpha", "(F)V", 804 (void*)nativeSetAlpha }, 805 {"nativeSetMatrix", "(FFFF)V", 806 (void*)nativeSetMatrix }, 807 {"nativeSetFlags", "(II)V", 808 (void*)nativeSetFlags }, 809 {"nativeSetWindowCrop", "(Landroid/graphics/Rect;)V", 810 (void*)nativeSetWindowCrop }, 811 {"nativeSetLayerStack", "(I)V", 812 (void*)nativeSetLayerStack }, 813 {"nativeGetBuiltInDisplay", "(I)Landroid/os/IBinder;", 814 (void*)nativeGetBuiltInDisplay }, 815 {"nativeCreateDisplay", "(Ljava/lang/String;)Landroid/os/IBinder;", 816 (void*)nativeCreateDisplay }, 817 {"nativeSetDisplaySurface", "(Landroid/os/IBinder;Landroid/graphics/SurfaceTexture;)V", 818 (void*)nativeSetDisplaySurface }, 819 {"nativeSetDisplayLayerStack", "(Landroid/os/IBinder;I)V", 820 (void*)nativeSetDisplayLayerStack }, 821 {"nativeSetDisplayOrientation", "(Landroid/os/IBinder;I)V", 822 (void*)nativeSetDisplayOrientation }, 823 {"nativeSetDisplayViewport", "(Landroid/os/IBinder;Landroid/graphics/Rect;)V", 824 (void*)nativeSetDisplayViewport }, 825 {"nativeSetDisplayFrame", "(Landroid/os/IBinder;Landroid/graphics/Rect;)V", 826 (void*)nativeSetDisplayFrame }, 827 {"nativeGetDisplayInfo", "(Landroid/os/IBinder;Landroid/view/Surface$PhysicalDisplayInfo;)Z", 828 (void*)nativeGetDisplayInfo }, 829 {"nativeCopyFrom", "(Landroid/view/Surface;)V", 830 (void*)nativeCopyFrom }, 831 {"nativeTransferFrom", "(Landroid/view/Surface;)V", 832 (void*)nativeTransferFrom }, 833 {"nativeReadFromParcel", "(Landroid/os/Parcel;)V", 834 (void*)nativeReadFromParcel }, 835 {"nativeWriteToParcel", "(Landroid/os/Parcel;)V", 836 (void*)nativeWriteToParcel }, 837}; 838 839int register_android_view_Surface(JNIEnv* env) 840{ 841 int err = AndroidRuntime::registerNativeMethods(env, "android/view/Surface", 842 gSurfaceMethods, NELEM(gSurfaceMethods)); 843 844 jclass clazz = env->FindClass("android/view/Surface"); 845 gSurfaceClassInfo.clazz = jclass(env->NewGlobalRef(clazz)); 846 gSurfaceClassInfo.mNativeSurface = 847 env->GetFieldID(gSurfaceClassInfo.clazz, ANDROID_VIEW_SURFACE_JNI_ID, "I"); 848 gSurfaceClassInfo.mNativeSurfaceControl = 849 env->GetFieldID(gSurfaceClassInfo.clazz, "mNativeSurfaceControl", "I"); 850 gSurfaceClassInfo.mGenerationId = 851 env->GetFieldID(gSurfaceClassInfo.clazz, "mGenerationId", "I"); 852 gSurfaceClassInfo.mCanvas = 853 env->GetFieldID(gSurfaceClassInfo.clazz, "mCanvas", "Landroid/graphics/Canvas;"); 854 gSurfaceClassInfo.mCanvasSaveCount = 855 env->GetFieldID(gSurfaceClassInfo.clazz, "mCanvasSaveCount", "I"); 856 857 clazz = env->FindClass("android/graphics/Canvas"); 858 gCanvasClassInfo.mNativeCanvas = env->GetFieldID(clazz, "mNativeCanvas", "I"); 859 gCanvasClassInfo.mSurfaceFormat = env->GetFieldID(clazz, "mSurfaceFormat", "I"); 860 861 clazz = env->FindClass("android/graphics/Rect"); 862 gRectClassInfo.left = env->GetFieldID(clazz, "left", "I"); 863 gRectClassInfo.top = env->GetFieldID(clazz, "top", "I"); 864 gRectClassInfo.right = env->GetFieldID(clazz, "right", "I"); 865 gRectClassInfo.bottom = env->GetFieldID(clazz, "bottom", "I"); 866 867 clazz = env->FindClass("android/view/Surface$PhysicalDisplayInfo"); 868 gPhysicalDisplayInfoClassInfo.width = env->GetFieldID(clazz, "width", "I"); 869 gPhysicalDisplayInfoClassInfo.height = env->GetFieldID(clazz, "height", "I"); 870 gPhysicalDisplayInfoClassInfo.refreshRate = env->GetFieldID(clazz, "refreshRate", "F"); 871 gPhysicalDisplayInfoClassInfo.density = env->GetFieldID(clazz, "density", "F"); 872 gPhysicalDisplayInfoClassInfo.xDpi = env->GetFieldID(clazz, "xDpi", "F"); 873 gPhysicalDisplayInfoClassInfo.yDpi = env->GetFieldID(clazz, "yDpi", "F"); 874 return err; 875} 876 877}; 878