Home | History | Annotate | Download | only in jni
      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