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