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