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_util_Binder.h" 22 #include "android/graphics/GraphicsJNI.h" 23 24 #include <binder/IMemory.h> 25 26 #include <gui/Surface.h> 27 #include <gui/SurfaceComposerClient.h> 28 #include <gui/SurfaceTexture.h> 29 30 #include <ui/Rect.h> 31 #include <ui/Region.h> 32 33 #include <EGL/egl.h> 34 35 #include <SkCanvas.h> 36 #include <SkBitmap.h> 37 #include <SkRegion.h> 38 #include <SkPixelRef.h> 39 40 #include "jni.h" 41 #include "JNIHelp.h" 42 #include <android_runtime/AndroidRuntime.h> 43 #include <android_runtime/android_view_Surface.h> 44 #include <android_runtime/android_graphics_SurfaceTexture.h> 45 #include <utils/misc.h> 46 47 48 // ---------------------------------------------------------------------------- 49 50 namespace android { 51 52 enum { 53 // should match Parcelable.java 54 PARCELABLE_WRITE_RETURN_VALUE = 0x0001 55 }; 56 57 // ---------------------------------------------------------------------------- 58 59 static const char* const OutOfResourcesException = 60 "android/view/Surface$OutOfResourcesException"; 61 62 const char* const kSurfaceSessionClassPathName = "android/view/SurfaceSession"; 63 const char* const kSurfaceClassPathName = "android/view/Surface"; 64 65 struct sso_t { 66 jfieldID client; 67 }; 68 static sso_t sso; 69 70 struct so_t { 71 jfieldID surfaceControl; 72 jfieldID surfaceGenerationId; 73 jfieldID surface; 74 jfieldID saveCount; 75 jfieldID canvas; 76 }; 77 static so_t so; 78 79 struct ro_t { 80 jfieldID l; 81 jfieldID t; 82 jfieldID r; 83 jfieldID b; 84 }; 85 static ro_t ro; 86 87 struct po_t { 88 jfieldID x; 89 jfieldID y; 90 }; 91 static po_t po; 92 93 struct co_t { 94 jfieldID surfaceFormat; 95 }; 96 static co_t co; 97 98 struct no_t { 99 jfieldID native_canvas; 100 jfieldID native_region; 101 jfieldID native_parcel; 102 }; 103 static no_t no; 104 105 106 // ---------------------------------------------------------------------------- 107 // ---------------------------------------------------------------------------- 108 // ---------------------------------------------------------------------------- 109 110 static void SurfaceSession_init(JNIEnv* env, jobject clazz) 111 { 112 sp<SurfaceComposerClient> client = new SurfaceComposerClient; 113 client->incStrong(clazz); 114 env->SetIntField(clazz, sso.client, (int)client.get()); 115 } 116 117 static void SurfaceSession_destroy(JNIEnv* env, jobject clazz) 118 { 119 SurfaceComposerClient* client = 120 (SurfaceComposerClient*)env->GetIntField(clazz, sso.client); 121 if (client != 0) { 122 client->decStrong(clazz); 123 env->SetIntField(clazz, sso.client, 0); 124 } 125 } 126 127 static void SurfaceSession_kill(JNIEnv* env, jobject clazz) 128 { 129 SurfaceComposerClient* client = 130 (SurfaceComposerClient*)env->GetIntField(clazz, sso.client); 131 if (client != 0) { 132 client->dispose(); 133 client->decStrong(clazz); 134 env->SetIntField(clazz, sso.client, 0); 135 } 136 } 137 138 // ---------------------------------------------------------------------------- 139 140 static sp<SurfaceControl> getSurfaceControl(JNIEnv* env, jobject clazz) 141 { 142 SurfaceControl* const p = 143 (SurfaceControl*)env->GetIntField(clazz, so.surfaceControl); 144 return sp<SurfaceControl>(p); 145 } 146 147 static void setSurfaceControl(JNIEnv* env, jobject clazz, 148 const sp<SurfaceControl>& surface) 149 { 150 SurfaceControl* const p = 151 (SurfaceControl*)env->GetIntField(clazz, so.surfaceControl); 152 if (surface.get()) { 153 surface->incStrong(clazz); 154 } 155 if (p) { 156 p->decStrong(clazz); 157 } 158 env->SetIntField(clazz, so.surfaceControl, (int)surface.get()); 159 } 160 161 static sp<Surface> getSurface(JNIEnv* env, jobject clazz) 162 { 163 sp<Surface> result(Surface_getSurface(env, clazz)); 164 if (result == 0) { 165 /* 166 * if this method is called from the WindowManager's process, it means 167 * the client is is not remote, and therefore is allowed to have 168 * a Surface (data), so we create it here. 169 * If we don't have a SurfaceControl, it means we're in a different 170 * process. 171 */ 172 173 SurfaceControl* const control = 174 (SurfaceControl*)env->GetIntField(clazz, so.surfaceControl); 175 if (control) { 176 result = control->getSurface(); 177 if (result != 0) { 178 result->incStrong(clazz); 179 env->SetIntField(clazz, so.surface, (int)result.get()); 180 } 181 } 182 } 183 return result; 184 } 185 186 sp<ANativeWindow> android_Surface_getNativeWindow( 187 JNIEnv* env, jobject clazz) { 188 return getSurface(env, clazz); 189 } 190 191 bool android_Surface_isInstanceOf(JNIEnv* env, jobject obj) { 192 jclass surfaceClass = env->FindClass(kSurfaceClassPathName); 193 return env->IsInstanceOf(obj, surfaceClass); 194 } 195 196 sp<Surface> Surface_getSurface(JNIEnv* env, jobject clazz) { 197 sp<Surface> surface((Surface*)env->GetIntField(clazz, so.surface)); 198 return surface; 199 } 200 201 void setSurface(JNIEnv* env, jobject clazz, const sp<Surface>& surface) 202 { 203 Surface* const p = (Surface*)env->GetIntField(clazz, so.surface); 204 if (surface.get()) { 205 surface->incStrong(clazz); 206 } 207 if (p) { 208 p->decStrong(clazz); 209 } 210 env->SetIntField(clazz, so.surface, (int)surface.get()); 211 // This test is conservative and it would be better to compare the ISurfaces 212 if (p && p != surface.get()) { 213 jint generationId = env->GetIntField(clazz, so.surfaceGenerationId); 214 generationId++; 215 env->SetIntField(clazz, so.surfaceGenerationId, generationId); 216 } 217 } 218 219 // ---------------------------------------------------------------------------- 220 221 static void Surface_init( 222 JNIEnv* env, jobject clazz, 223 jobject session, 224 jint, jstring jname, jint dpy, jint w, jint h, jint format, jint flags) 225 { 226 if (session == NULL) { 227 doThrowNPE(env); 228 return; 229 } 230 231 SurfaceComposerClient* client = 232 (SurfaceComposerClient*)env->GetIntField(session, sso.client); 233 234 sp<SurfaceControl> surface; 235 if (jname == NULL) { 236 surface = client->createSurface(dpy, w, h, format, flags); 237 } else { 238 const jchar* str = env->GetStringCritical(jname, 0); 239 const String8 name(str, env->GetStringLength(jname)); 240 env->ReleaseStringCritical(jname, str); 241 surface = client->createSurface(name, dpy, w, h, format, flags); 242 } 243 244 if (surface == 0) { 245 jniThrowException(env, OutOfResourcesException, NULL); 246 return; 247 } 248 setSurfaceControl(env, clazz, surface); 249 } 250 251 static void Surface_initFromSurfaceTexture( 252 JNIEnv* env, jobject clazz, jobject jst) 253 { 254 sp<SurfaceTexture> st(SurfaceTexture_getSurfaceTexture(env, jst)); 255 256 if (st == NULL) { 257 jniThrowException(env, "java/lang/IllegalArgumentException", 258 "SurfaceTexture has already been released"); 259 return; 260 } 261 sp<ISurfaceTexture> bq = st->getBufferQueue(); 262 263 sp<Surface> surface(new Surface(bq)); 264 if (surface == NULL) { 265 jniThrowException(env, OutOfResourcesException, NULL); 266 return; 267 } 268 setSurfaceControl(env, clazz, NULL); 269 setSurface(env, clazz, surface); 270 } 271 272 static void Surface_initParcel(JNIEnv* env, jobject clazz, jobject argParcel) 273 { 274 Parcel* parcel = (Parcel*)env->GetIntField(argParcel, no.native_parcel); 275 if (parcel == NULL) { 276 doThrowNPE(env); 277 return; 278 } 279 280 sp<Surface> sur(Surface::readFromParcel(*parcel)); 281 setSurface(env, clazz, sur); 282 } 283 284 static jint Surface_getIdentity(JNIEnv* env, jobject clazz) 285 { 286 const sp<SurfaceControl>& control(getSurfaceControl(env, clazz)); 287 if (control != 0) return (jint) control->getIdentity(); 288 const sp<Surface>& surface(getSurface(env, clazz)); 289 if (surface != 0) return (jint) surface->getIdentity(); 290 return -1; 291 } 292 293 static void Surface_destroy(JNIEnv* env, jobject clazz, uintptr_t *ostack) 294 { 295 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz)); 296 if (SurfaceControl::isValid(surface)) { 297 surface->clear(); 298 } 299 setSurfaceControl(env, clazz, 0); 300 setSurface(env, clazz, 0); 301 } 302 303 static void Surface_release(JNIEnv* env, jobject clazz, uintptr_t *ostack) 304 { 305 setSurfaceControl(env, clazz, 0); 306 setSurface(env, clazz, 0); 307 } 308 309 static jboolean Surface_isValid(JNIEnv* env, jobject clazz) 310 { 311 const sp<SurfaceControl>& surfaceControl(getSurfaceControl(env, clazz)); 312 if (surfaceControl != 0) { 313 return SurfaceControl::isValid(surfaceControl) ? JNI_TRUE : JNI_FALSE; 314 } 315 const sp<Surface>& surface(getSurface(env, clazz)); 316 return Surface::isValid(surface) ? JNI_TRUE : JNI_FALSE; 317 } 318 319 static jboolean Surface_isConsumerRunningBehind(JNIEnv* env, jobject clazz) 320 { 321 int value = 0; 322 const sp<Surface>& surface(getSurface(env, clazz)); 323 if (!Surface::isValid(surface)) { 324 doThrowIAE(env); 325 return 0; 326 } 327 ANativeWindow* anw = static_cast<ANativeWindow *>(surface.get()); 328 anw->query(anw, NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND, &value); 329 return (jboolean)value; 330 } 331 332 static inline SkBitmap::Config convertPixelFormat(PixelFormat format) 333 { 334 /* note: if PIXEL_FORMAT_RGBX_8888 means that all alpha bytes are 0xFF, then 335 we can map to SkBitmap::kARGB_8888_Config, and optionally call 336 bitmap.setIsOpaque(true) on the resulting SkBitmap (as an accelerator) 337 */ 338 switch (format) { 339 case PIXEL_FORMAT_RGBX_8888: return SkBitmap::kARGB_8888_Config; 340 case PIXEL_FORMAT_RGBA_8888: return SkBitmap::kARGB_8888_Config; 341 case PIXEL_FORMAT_RGBA_4444: return SkBitmap::kARGB_4444_Config; 342 case PIXEL_FORMAT_RGB_565: return SkBitmap::kRGB_565_Config; 343 case PIXEL_FORMAT_A_8: return SkBitmap::kA8_Config; 344 default: return SkBitmap::kNo_Config; 345 } 346 } 347 348 static jobject Surface_lockCanvas(JNIEnv* env, jobject clazz, jobject dirtyRect) 349 { 350 const sp<Surface>& surface(getSurface(env, clazz)); 351 if (!Surface::isValid(surface)) { 352 doThrowIAE(env); 353 return 0; 354 } 355 356 // get dirty region 357 Region dirtyRegion; 358 if (dirtyRect) { 359 Rect dirty; 360 dirty.left = env->GetIntField(dirtyRect, ro.l); 361 dirty.top = env->GetIntField(dirtyRect, ro.t); 362 dirty.right = env->GetIntField(dirtyRect, ro.r); 363 dirty.bottom= env->GetIntField(dirtyRect, ro.b); 364 if (!dirty.isEmpty()) { 365 dirtyRegion.set(dirty); 366 } 367 } else { 368 dirtyRegion.set(Rect(0x3FFF,0x3FFF)); 369 } 370 371 Surface::SurfaceInfo info; 372 status_t err = surface->lock(&info, &dirtyRegion); 373 if (err < 0) { 374 const char* const exception = (err == NO_MEMORY) ? 375 OutOfResourcesException : 376 "java/lang/IllegalArgumentException"; 377 jniThrowException(env, exception, NULL); 378 return 0; 379 } 380 381 // Associate a SkCanvas object to this surface 382 jobject canvas = env->GetObjectField(clazz, so.canvas); 383 env->SetIntField(canvas, co.surfaceFormat, info.format); 384 385 SkCanvas* nativeCanvas = (SkCanvas*)env->GetIntField(canvas, no.native_canvas); 386 SkBitmap bitmap; 387 ssize_t bpr = info.s * bytesPerPixel(info.format); 388 bitmap.setConfig(convertPixelFormat(info.format), info.w, info.h, bpr); 389 if (info.format == PIXEL_FORMAT_RGBX_8888) { 390 bitmap.setIsOpaque(true); 391 } 392 if (info.w > 0 && info.h > 0) { 393 bitmap.setPixels(info.bits); 394 } else { 395 // be safe with an empty bitmap. 396 bitmap.setPixels(NULL); 397 } 398 nativeCanvas->setBitmapDevice(bitmap); 399 400 SkRegion clipReg; 401 if (dirtyRegion.isRect()) { // very common case 402 const Rect b(dirtyRegion.getBounds()); 403 clipReg.setRect(b.left, b.top, b.right, b.bottom); 404 } else { 405 size_t count; 406 Rect const* r = dirtyRegion.getArray(&count); 407 while (count) { 408 clipReg.op(r->left, r->top, r->right, r->bottom, SkRegion::kUnion_Op); 409 r++, count--; 410 } 411 } 412 413 nativeCanvas->clipRegion(clipReg); 414 415 int saveCount = nativeCanvas->save(); 416 env->SetIntField(clazz, so.saveCount, saveCount); 417 418 if (dirtyRect) { 419 const Rect& bounds(dirtyRegion.getBounds()); 420 env->SetIntField(dirtyRect, ro.l, bounds.left); 421 env->SetIntField(dirtyRect, ro.t, bounds.top); 422 env->SetIntField(dirtyRect, ro.r, bounds.right); 423 env->SetIntField(dirtyRect, ro.b, bounds.bottom); 424 } 425 426 return canvas; 427 } 428 429 static void Surface_unlockCanvasAndPost( 430 JNIEnv* env, jobject clazz, jobject argCanvas) 431 { 432 jobject canvas = env->GetObjectField(clazz, so.canvas); 433 if (env->IsSameObject(canvas, argCanvas) == JNI_FALSE) { 434 doThrowIAE(env); 435 return; 436 } 437 438 const sp<Surface>& surface(getSurface(env, clazz)); 439 if (!Surface::isValid(surface)) 440 return; 441 442 // detach the canvas from the surface 443 SkCanvas* nativeCanvas = (SkCanvas*)env->GetIntField(canvas, no.native_canvas); 444 int saveCount = env->GetIntField(clazz, so.saveCount); 445 nativeCanvas->restoreToCount(saveCount); 446 nativeCanvas->setBitmapDevice(SkBitmap()); 447 env->SetIntField(clazz, so.saveCount, 0); 448 449 // unlock surface 450 status_t err = surface->unlockAndPost(); 451 if (err < 0) { 452 doThrowIAE(env); 453 } 454 } 455 456 static void Surface_unlockCanvas( 457 JNIEnv* env, jobject clazz, jobject argCanvas) 458 { 459 // XXX: this API has been removed 460 doThrowIAE(env); 461 } 462 463 static void Surface_openTransaction( 464 JNIEnv* env, jobject clazz) 465 { 466 SurfaceComposerClient::openGlobalTransaction(); 467 } 468 469 static void Surface_closeTransaction( 470 JNIEnv* env, jobject clazz) 471 { 472 SurfaceComposerClient::closeGlobalTransaction(); 473 } 474 475 static void Surface_setOrientation( 476 JNIEnv* env, jobject clazz, jint display, jint orientation, jint flags) 477 { 478 int err = SurfaceComposerClient::setOrientation(display, orientation, flags); 479 if (err < 0) { 480 doThrowIAE(env); 481 } 482 } 483 484 static void Surface_freezeDisplay( 485 JNIEnv* env, jobject clazz, jint display) 486 { 487 int err = SurfaceComposerClient::freezeDisplay(display, 0); 488 if (err < 0) { 489 doThrowIAE(env); 490 } 491 } 492 493 static void Surface_unfreezeDisplay( 494 JNIEnv* env, jobject clazz, jint display) 495 { 496 int err = SurfaceComposerClient::unfreezeDisplay(display, 0); 497 if (err < 0) { 498 doThrowIAE(env); 499 } 500 } 501 502 class ScreenshotPixelRef : public SkPixelRef { 503 public: 504 ScreenshotPixelRef(SkColorTable* ctable) { 505 fCTable = ctable; 506 SkSafeRef(ctable); 507 setImmutable(); 508 } 509 virtual ~ScreenshotPixelRef() { 510 SkSafeUnref(fCTable); 511 } 512 513 status_t update(int width, int height, int minLayer, int maxLayer, bool allLayers) { 514 status_t res = (width > 0 && height > 0) 515 ? (allLayers 516 ? mScreenshot.update(width, height) 517 : mScreenshot.update(width, height, minLayer, maxLayer)) 518 : mScreenshot.update(); 519 if (res != NO_ERROR) { 520 return res; 521 } 522 523 return NO_ERROR; 524 } 525 526 uint32_t getWidth() const { 527 return mScreenshot.getWidth(); 528 } 529 530 uint32_t getHeight() const { 531 return mScreenshot.getHeight(); 532 } 533 534 uint32_t getStride() const { 535 return mScreenshot.getStride(); 536 } 537 538 uint32_t getFormat() const { 539 return mScreenshot.getFormat(); 540 } 541 542 protected: 543 // overrides from SkPixelRef 544 virtual void* onLockPixels(SkColorTable** ct) { 545 *ct = fCTable; 546 return (void*)mScreenshot.getPixels(); 547 } 548 549 virtual void onUnlockPixels() { 550 } 551 552 private: 553 ScreenshotClient mScreenshot; 554 SkColorTable* fCTable; 555 556 typedef SkPixelRef INHERITED; 557 }; 558 559 static jobject doScreenshot(JNIEnv* env, jobject clazz, jint width, jint height, 560 jint minLayer, jint maxLayer, bool allLayers) 561 { 562 ScreenshotPixelRef* pixels = new ScreenshotPixelRef(NULL); 563 if (pixels->update(width, height, minLayer, maxLayer, allLayers) != NO_ERROR) { 564 delete pixels; 565 return 0; 566 } 567 568 uint32_t w = pixels->getWidth(); 569 uint32_t h = pixels->getHeight(); 570 uint32_t s = pixels->getStride(); 571 uint32_t f = pixels->getFormat(); 572 ssize_t bpr = s * android::bytesPerPixel(f); 573 574 SkBitmap* bitmap = new SkBitmap(); 575 bitmap->setConfig(convertPixelFormat(f), w, h, bpr); 576 if (f == PIXEL_FORMAT_RGBX_8888) { 577 bitmap->setIsOpaque(true); 578 } 579 580 if (w > 0 && h > 0) { 581 bitmap->setPixelRef(pixels)->unref(); 582 bitmap->lockPixels(); 583 } else { 584 // be safe with an empty bitmap. 585 delete pixels; 586 bitmap->setPixels(NULL); 587 } 588 589 return GraphicsJNI::createBitmap(env, bitmap, false, NULL); 590 } 591 592 static jobject Surface_screenshotAll(JNIEnv* env, jobject clazz, jint width, jint height) 593 { 594 return doScreenshot(env, clazz, width, height, 0, 0, true); 595 } 596 597 static jobject Surface_screenshot(JNIEnv* env, jobject clazz, jint width, jint height, 598 jint minLayer, jint maxLayer) 599 { 600 return doScreenshot(env, clazz, width, height, minLayer, maxLayer, false); 601 } 602 603 static void Surface_setLayer( 604 JNIEnv* env, jobject clazz, jint zorder) 605 { 606 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz)); 607 if (surface == 0) return; 608 status_t err = surface->setLayer(zorder); 609 if (err<0 && err!=NO_INIT) { 610 doThrowIAE(env); 611 } 612 } 613 614 static void Surface_setPosition( 615 JNIEnv* env, jobject clazz, jfloat x, jfloat y) 616 { 617 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz)); 618 if (surface == 0) return; 619 status_t err = surface->setPosition(x, y); 620 if (err<0 && err!=NO_INIT) { 621 doThrowIAE(env); 622 } 623 } 624 625 static void Surface_setSize( 626 JNIEnv* env, jobject clazz, jint w, jint h) 627 { 628 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz)); 629 if (surface == 0) return; 630 status_t err = surface->setSize(w, h); 631 if (err<0 && err!=NO_INIT) { 632 doThrowIAE(env); 633 } 634 } 635 636 static void Surface_hide( 637 JNIEnv* env, jobject clazz) 638 { 639 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz)); 640 if (surface == 0) return; 641 status_t err = surface->hide(); 642 if (err<0 && err!=NO_INIT) { 643 doThrowIAE(env); 644 } 645 } 646 647 static void Surface_show( 648 JNIEnv* env, jobject clazz) 649 { 650 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz)); 651 if (surface == 0) return; 652 status_t err = surface->show(); 653 if (err<0 && err!=NO_INIT) { 654 doThrowIAE(env); 655 } 656 } 657 658 static void Surface_freeze( 659 JNIEnv* env, jobject clazz) 660 { 661 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz)); 662 if (surface == 0) return; 663 status_t err = surface->freeze(); 664 if (err<0 && err!=NO_INIT) { 665 doThrowIAE(env); 666 } 667 } 668 669 static void Surface_unfreeze( 670 JNIEnv* env, jobject clazz) 671 { 672 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz)); 673 if (surface == 0) return; 674 status_t err = surface->unfreeze(); 675 if (err<0 && err!=NO_INIT) { 676 doThrowIAE(env); 677 } 678 } 679 680 static void Surface_setFlags( 681 JNIEnv* env, jobject clazz, jint flags, jint mask) 682 { 683 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz)); 684 if (surface == 0) return; 685 status_t err = surface->setFlags(flags, mask); 686 if (err<0 && err!=NO_INIT) { 687 doThrowIAE(env); 688 } 689 } 690 691 static void Surface_setTransparentRegion( 692 JNIEnv* env, jobject clazz, jobject argRegion) 693 { 694 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz)); 695 if (surface == 0) return; 696 SkRegion* nativeRegion = (SkRegion*)env->GetIntField(argRegion, no.native_region); 697 698 const SkIRect& b(nativeRegion->getBounds()); 699 Region reg(Rect(b.fLeft, b.fTop, b.fRight, b.fBottom)); 700 if (nativeRegion->isComplex()) { 701 SkRegion::Iterator it(*nativeRegion); 702 while (!it.done()) { 703 const SkIRect& r(it.rect()); 704 reg.addRectUnchecked(r.fLeft, r.fTop, r.fRight, r.fBottom); 705 it.next(); 706 } 707 } 708 709 status_t err = surface->setTransparentRegionHint(reg); 710 if (err<0 && err!=NO_INIT) { 711 doThrowIAE(env); 712 } 713 } 714 715 static void Surface_setAlpha( 716 JNIEnv* env, jobject clazz, jfloat alpha) 717 { 718 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz)); 719 if (surface == 0) return; 720 status_t err = surface->setAlpha(alpha); 721 if (err<0 && err!=NO_INIT) { 722 doThrowIAE(env); 723 } 724 } 725 726 static void Surface_setMatrix( 727 JNIEnv* env, jobject clazz, 728 jfloat dsdx, jfloat dtdx, jfloat dsdy, jfloat dtdy) 729 { 730 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz)); 731 if (surface == 0) return; 732 status_t err = surface->setMatrix(dsdx, dtdx, dsdy, dtdy); 733 if (err<0 && err!=NO_INIT) { 734 doThrowIAE(env); 735 } 736 } 737 738 static void Surface_setFreezeTint( 739 JNIEnv* env, jobject clazz, 740 jint tint) 741 { 742 const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz)); 743 if (surface == 0) return; 744 status_t err = surface->setFreezeTint(tint); 745 if (err<0 && err!=NO_INIT) { 746 doThrowIAE(env); 747 } 748 } 749 750 static void Surface_setWindowCrop(JNIEnv* env, jobject thiz, jobject crop) 751 { 752 const sp<SurfaceControl>& surface(getSurfaceControl(env, thiz)); 753 if (surface == 0) return; 754 755 Rect nativeCrop; 756 if (crop) { 757 nativeCrop.left = env->GetIntField(crop, ro.l); 758 nativeCrop.top = env->GetIntField(crop, ro.t); 759 nativeCrop.right = env->GetIntField(crop, ro.r); 760 nativeCrop.bottom= env->GetIntField(crop, ro.b); 761 } else { 762 nativeCrop.left = nativeCrop.top = nativeCrop.right = 763 nativeCrop.bottom = 0; 764 } 765 766 status_t err = surface->setCrop(nativeCrop); 767 if (err<0 && err!=NO_INIT) { 768 doThrowIAE(env); 769 } 770 } 771 772 // ---------------------------------------------------------------------------- 773 774 static void Surface_copyFrom( 775 JNIEnv* env, jobject clazz, jobject other) 776 { 777 if (clazz == other) 778 return; 779 780 if (other == NULL) { 781 doThrowNPE(env); 782 return; 783 } 784 785 /* 786 * This is used by the WindowManagerService just after constructing 787 * a Surface and is necessary for returning the Surface reference to 788 * the caller. At this point, we should only have a SurfaceControl. 789 */ 790 791 const sp<SurfaceControl>& surface = getSurfaceControl(env, clazz); 792 const sp<SurfaceControl>& rhs = getSurfaceControl(env, other); 793 if (!SurfaceControl::isSameSurface(surface, rhs)) { 794 // we reassign the surface only if it's a different one 795 // otherwise we would loose our client-side state. 796 setSurfaceControl(env, clazz, rhs); 797 } 798 } 799 800 static void Surface_transferFrom( 801 JNIEnv* env, jobject clazz, jobject other) 802 { 803 if (clazz == other) 804 return; 805 806 if (other == NULL) { 807 doThrowNPE(env); 808 return; 809 } 810 811 sp<SurfaceControl> control(getSurfaceControl(env, other)); 812 sp<Surface> surface(Surface_getSurface(env, other)); 813 setSurfaceControl(env, clazz, control); 814 setSurface(env, clazz, surface); 815 setSurfaceControl(env, other, 0); 816 setSurface(env, other, 0); 817 } 818 819 static void Surface_readFromParcel( 820 JNIEnv* env, jobject clazz, jobject argParcel) 821 { 822 Parcel* parcel = (Parcel*)env->GetIntField( argParcel, no.native_parcel); 823 if (parcel == NULL) { 824 doThrowNPE(env); 825 return; 826 } 827 828 sp<Surface> sur(Surface::readFromParcel(*parcel)); 829 setSurface(env, clazz, sur); 830 } 831 832 static void Surface_writeToParcel( 833 JNIEnv* env, jobject clazz, jobject argParcel, jint flags) 834 { 835 Parcel* parcel = (Parcel*)env->GetIntField( 836 argParcel, no.native_parcel); 837 838 if (parcel == NULL) { 839 doThrowNPE(env); 840 return; 841 } 842 843 // The Java instance may have a SurfaceControl (in the case of the 844 // WindowManager or a system app). In that case, we defer to the 845 // SurfaceControl to send its ISurface. Otherwise, if the Surface is 846 // available we let it parcel itself. Finally, if the Surface is also 847 // NULL we fall back to using the SurfaceControl path which sends an 848 // empty surface; this matches legacy behavior. 849 const sp<SurfaceControl>& control(getSurfaceControl(env, clazz)); 850 if (control != NULL) { 851 SurfaceControl::writeSurfaceToParcel(control, parcel); 852 } else { 853 sp<Surface> surface(Surface_getSurface(env, clazz)); 854 if (surface != NULL) { 855 Surface::writeToParcel(surface, parcel); 856 } else { 857 SurfaceControl::writeSurfaceToParcel(NULL, parcel); 858 } 859 } 860 if (flags & PARCELABLE_WRITE_RETURN_VALUE) { 861 setSurfaceControl(env, clazz, NULL); 862 setSurface(env, clazz, NULL); 863 } 864 } 865 866 // ---------------------------------------------------------------------------- 867 // ---------------------------------------------------------------------------- 868 // ---------------------------------------------------------------------------- 869 870 static void nativeClassInit(JNIEnv* env, jclass clazz); 871 872 static JNINativeMethod gSurfaceSessionMethods[] = { 873 {"init", "()V", (void*)SurfaceSession_init }, 874 {"destroy", "()V", (void*)SurfaceSession_destroy }, 875 {"kill", "()V", (void*)SurfaceSession_kill }, 876 }; 877 878 static JNINativeMethod gSurfaceMethods[] = { 879 {"nativeClassInit", "()V", (void*)nativeClassInit }, 880 {"init", "(Landroid/view/SurfaceSession;ILjava/lang/String;IIIII)V", (void*)Surface_init }, 881 {"init", "(Landroid/os/Parcel;)V", (void*)Surface_initParcel }, 882 {"initFromSurfaceTexture", "(Landroid/graphics/SurfaceTexture;)V", (void*)Surface_initFromSurfaceTexture }, 883 {"getIdentity", "()I", (void*)Surface_getIdentity }, 884 {"destroy", "()V", (void*)Surface_destroy }, 885 {"release", "()V", (void*)Surface_release }, 886 {"copyFrom", "(Landroid/view/Surface;)V", (void*)Surface_copyFrom }, 887 {"transferFrom", "(Landroid/view/Surface;)V", (void*)Surface_transferFrom }, 888 {"isValid", "()Z", (void*)Surface_isValid }, 889 {"lockCanvasNative", "(Landroid/graphics/Rect;)Landroid/graphics/Canvas;", (void*)Surface_lockCanvas }, 890 {"unlockCanvasAndPost", "(Landroid/graphics/Canvas;)V", (void*)Surface_unlockCanvasAndPost }, 891 {"unlockCanvas", "(Landroid/graphics/Canvas;)V", (void*)Surface_unlockCanvas }, 892 {"openTransaction", "()V", (void*)Surface_openTransaction }, 893 {"closeTransaction", "()V", (void*)Surface_closeTransaction }, 894 {"setOrientation", "(III)V", (void*)Surface_setOrientation }, 895 {"freezeDisplay", "(I)V", (void*)Surface_freezeDisplay }, 896 {"unfreezeDisplay", "(I)V", (void*)Surface_unfreezeDisplay }, 897 {"screenshot", "(II)Landroid/graphics/Bitmap;", (void*)Surface_screenshotAll }, 898 {"screenshot", "(IIII)Landroid/graphics/Bitmap;", (void*)Surface_screenshot }, 899 {"setLayer", "(I)V", (void*)Surface_setLayer }, 900 {"setPosition", "(FF)V",(void*)Surface_setPosition }, 901 {"setSize", "(II)V",(void*)Surface_setSize }, 902 {"hide", "()V", (void*)Surface_hide }, 903 {"show", "()V", (void*)Surface_show }, 904 {"freeze", "()V", (void*)Surface_freeze }, 905 {"unfreeze", "()V", (void*)Surface_unfreeze }, 906 {"setFlags", "(II)V",(void*)Surface_setFlags }, 907 {"setTransparentRegionHint","(Landroid/graphics/Region;)V", (void*)Surface_setTransparentRegion }, 908 {"setAlpha", "(F)V", (void*)Surface_setAlpha }, 909 {"setMatrix", "(FFFF)V", (void*)Surface_setMatrix }, 910 {"setFreezeTint", "(I)V", (void*)Surface_setFreezeTint }, 911 {"readFromParcel", "(Landroid/os/Parcel;)V", (void*)Surface_readFromParcel }, 912 {"writeToParcel", "(Landroid/os/Parcel;I)V", (void*)Surface_writeToParcel }, 913 {"isConsumerRunningBehind", "()Z", (void*)Surface_isConsumerRunningBehind }, 914 {"setWindowCrop", "(Landroid/graphics/Rect;)V", (void*)Surface_setWindowCrop }, 915 }; 916 917 void nativeClassInit(JNIEnv* env, jclass clazz) 918 { 919 so.surface = env->GetFieldID(clazz, ANDROID_VIEW_SURFACE_JNI_ID, "I"); 920 so.surfaceGenerationId = env->GetFieldID(clazz, "mSurfaceGenerationId", "I"); 921 so.surfaceControl = env->GetFieldID(clazz, "mSurfaceControl", "I"); 922 so.saveCount = env->GetFieldID(clazz, "mSaveCount", "I"); 923 so.canvas = env->GetFieldID(clazz, "mCanvas", "Landroid/graphics/Canvas;"); 924 925 jclass surfaceSession = env->FindClass("android/view/SurfaceSession"); 926 sso.client = env->GetFieldID(surfaceSession, "mClient", "I"); 927 928 jclass canvas = env->FindClass("android/graphics/Canvas"); 929 no.native_canvas = env->GetFieldID(canvas, "mNativeCanvas", "I"); 930 co.surfaceFormat = env->GetFieldID(canvas, "mSurfaceFormat", "I"); 931 932 jclass region = env->FindClass("android/graphics/Region"); 933 no.native_region = env->GetFieldID(region, "mNativeRegion", "I"); 934 935 jclass parcel = env->FindClass("android/os/Parcel"); 936 no.native_parcel = env->GetFieldID(parcel, "mNativePtr", "I"); 937 938 jclass rect = env->FindClass("android/graphics/Rect"); 939 ro.l = env->GetFieldID(rect, "left", "I"); 940 ro.t = env->GetFieldID(rect, "top", "I"); 941 ro.r = env->GetFieldID(rect, "right", "I"); 942 ro.b = env->GetFieldID(rect, "bottom", "I"); 943 944 jclass point = env->FindClass("android/graphics/Point"); 945 po.x = env->GetFieldID(point, "x", "I"); 946 po.y = env->GetFieldID(point, "y", "I"); 947 } 948 949 int register_android_view_Surface(JNIEnv* env) 950 { 951 int err; 952 err = AndroidRuntime::registerNativeMethods(env, kSurfaceSessionClassPathName, 953 gSurfaceSessionMethods, NELEM(gSurfaceSessionMethods)); 954 955 err |= AndroidRuntime::registerNativeMethods(env, kSurfaceClassPathName, 956 gSurfaceMethods, NELEM(gSurfaceMethods)); 957 return err; 958 } 959 960 }; 961