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