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 
     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