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 "jni.h"
     22 #include "JNIHelp.h"
     23 #include "android_os_Parcel.h"
     24 #include "android/graphics/GraphicsJNI.h"
     25 
     26 #include "core_jni_helpers.h"
     27 #include <android_runtime/android_view_Surface.h>
     28 #include <android_runtime/android_graphics_SurfaceTexture.h>
     29 #include <android_runtime/Log.h>
     30 
     31 #include <binder/Parcel.h>
     32 
     33 #include <gui/Surface.h>
     34 #include <gui/SurfaceControl.h>
     35 #include <gui/GLConsumer.h>
     36 
     37 #include <ui/Rect.h>
     38 #include <ui/Region.h>
     39 
     40 #include <SkCanvas.h>
     41 #include <SkBitmap.h>
     42 #include <SkImage.h>
     43 #include <SkRegion.h>
     44 
     45 #include <utils/misc.h>
     46 #include <utils/Log.h>
     47 
     48 #include <ScopedUtfChars.h>
     49 
     50 #include <AnimationContext.h>
     51 #include <FrameInfo.h>
     52 #include <RenderNode.h>
     53 #include <renderthread/RenderProxy.h>
     54 
     55 // ----------------------------------------------------------------------------
     56 
     57 namespace android {
     58 
     59 static const char* const OutOfResourcesException =
     60     "android/view/Surface$OutOfResourcesException";
     61 
     62 static struct {
     63     jclass clazz;
     64     jfieldID mNativeObject;
     65     jfieldID mLock;
     66     jmethodID ctor;
     67 } gSurfaceClassInfo;
     68 
     69 static struct {
     70     jfieldID left;
     71     jfieldID top;
     72     jfieldID right;
     73     jfieldID bottom;
     74 } gRectClassInfo;
     75 
     76 // ----------------------------------------------------------------------------
     77 
     78 // this is just a pointer we use to pass to inc/decStrong
     79 static const void *sRefBaseOwner;
     80 
     81 bool android_view_Surface_isInstanceOf(JNIEnv* env, jobject obj) {
     82     return env->IsInstanceOf(obj, gSurfaceClassInfo.clazz);
     83 }
     84 
     85 sp<ANativeWindow> android_view_Surface_getNativeWindow(JNIEnv* env, jobject surfaceObj) {
     86     return android_view_Surface_getSurface(env, surfaceObj);
     87 }
     88 
     89 sp<Surface> android_view_Surface_getSurface(JNIEnv* env, jobject surfaceObj) {
     90     sp<Surface> sur;
     91     jobject lock = env->GetObjectField(surfaceObj,
     92             gSurfaceClassInfo.mLock);
     93     if (env->MonitorEnter(lock) == JNI_OK) {
     94         sur = reinterpret_cast<Surface *>(
     95                 env->GetLongField(surfaceObj, gSurfaceClassInfo.mNativeObject));
     96         env->MonitorExit(lock);
     97     }
     98     env->DeleteLocalRef(lock);
     99     return sur;
    100 }
    101 
    102 jobject android_view_Surface_createFromIGraphicBufferProducer(JNIEnv* env,
    103         const sp<IGraphicBufferProducer>& bufferProducer) {
    104     if (bufferProducer == NULL) {
    105         return NULL;
    106     }
    107 
    108     sp<Surface> surface(new Surface(bufferProducer, true));
    109     if (surface == NULL) {
    110         return NULL;
    111     }
    112 
    113     jobject surfaceObj = env->NewObject(gSurfaceClassInfo.clazz,
    114             gSurfaceClassInfo.ctor, (jlong)surface.get());
    115     if (surfaceObj == NULL) {
    116         if (env->ExceptionCheck()) {
    117             ALOGE("Could not create instance of Surface from IGraphicBufferProducer.");
    118             LOGE_EX(env);
    119             env->ExceptionClear();
    120         }
    121         return NULL;
    122     }
    123     surface->incStrong(&sRefBaseOwner);
    124     return surfaceObj;
    125 }
    126 
    127 int android_view_Surface_mapPublicFormatToHalFormat(PublicFormat f) {
    128 
    129     switch(f) {
    130         case PublicFormat::JPEG:
    131         case PublicFormat::DEPTH_POINT_CLOUD:
    132             return HAL_PIXEL_FORMAT_BLOB;
    133         case PublicFormat::DEPTH16:
    134             return HAL_PIXEL_FORMAT_Y16;
    135         case PublicFormat::RAW_SENSOR:
    136             return HAL_PIXEL_FORMAT_RAW16;
    137         default:
    138             // Most formats map 1:1
    139             return static_cast<int>(f);
    140     }
    141 }
    142 
    143 android_dataspace android_view_Surface_mapPublicFormatToHalDataspace(
    144         PublicFormat f) {
    145     switch(f) {
    146         case PublicFormat::JPEG:
    147             return HAL_DATASPACE_V0_JFIF;
    148         case PublicFormat::DEPTH_POINT_CLOUD:
    149         case PublicFormat::DEPTH16:
    150             return HAL_DATASPACE_DEPTH;
    151         case PublicFormat::RAW_SENSOR:
    152         case PublicFormat::RAW_PRIVATE:
    153         case PublicFormat::RAW10:
    154         case PublicFormat::RAW12:
    155             return HAL_DATASPACE_ARBITRARY;
    156         case PublicFormat::YUV_420_888:
    157         case PublicFormat::NV21:
    158         case PublicFormat::YV12:
    159             return HAL_DATASPACE_V0_JFIF;
    160         default:
    161             // Most formats map to UNKNOWN
    162             return HAL_DATASPACE_UNKNOWN;
    163     }
    164 }
    165 
    166 PublicFormat android_view_Surface_mapHalFormatDataspaceToPublicFormat(
    167         int format, android_dataspace dataSpace) {
    168     switch(format) {
    169         case HAL_PIXEL_FORMAT_RGBA_8888:
    170         case HAL_PIXEL_FORMAT_RGBX_8888:
    171         case HAL_PIXEL_FORMAT_RGB_888:
    172         case HAL_PIXEL_FORMAT_RGB_565:
    173         case HAL_PIXEL_FORMAT_Y8:
    174         case HAL_PIXEL_FORMAT_RAW10:
    175         case HAL_PIXEL_FORMAT_RAW12:
    176         case HAL_PIXEL_FORMAT_YCbCr_420_888:
    177         case HAL_PIXEL_FORMAT_YV12:
    178             // Enums overlap in both name and value
    179             return static_cast<PublicFormat>(format);
    180         case HAL_PIXEL_FORMAT_RAW16:
    181             // Name differs, though value is the same
    182             return PublicFormat::RAW_SENSOR;
    183         case HAL_PIXEL_FORMAT_RAW_OPAQUE:
    184             // Name differs, though value is the same
    185             return PublicFormat::RAW_PRIVATE;
    186         case HAL_PIXEL_FORMAT_YCbCr_422_SP:
    187             // Name differs, though the value is the same
    188             return PublicFormat::NV16;
    189         case HAL_PIXEL_FORMAT_YCrCb_420_SP:
    190             // Name differs, though the value is the same
    191             return PublicFormat::NV21;
    192         case HAL_PIXEL_FORMAT_YCbCr_422_I:
    193             // Name differs, though the value is the same
    194             return PublicFormat::YUY2;
    195         case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
    196             // Name differs, though the value is the same
    197             return PublicFormat::PRIVATE;
    198         case HAL_PIXEL_FORMAT_Y16:
    199             // Dataspace-dependent
    200             switch (dataSpace) {
    201                 case HAL_DATASPACE_DEPTH:
    202                     return PublicFormat::DEPTH16;
    203                 default:
    204                     // Assume non-depth Y16 is just Y16.
    205                     return PublicFormat::Y16;
    206             }
    207             break;
    208         case HAL_PIXEL_FORMAT_BLOB:
    209             // Dataspace-dependent
    210             switch (dataSpace) {
    211                 case HAL_DATASPACE_DEPTH:
    212                     return PublicFormat::DEPTH_POINT_CLOUD;
    213                 case HAL_DATASPACE_V0_JFIF:
    214                     return PublicFormat::JPEG;
    215                 default:
    216                     // Assume otherwise-marked blobs are also JPEG
    217                     return PublicFormat::JPEG;
    218             }
    219             break;
    220         case HAL_PIXEL_FORMAT_BGRA_8888:
    221             // Not defined in public API
    222             return PublicFormat::UNKNOWN;
    223 
    224         default:
    225             return PublicFormat::UNKNOWN;
    226     }
    227 }
    228 // ----------------------------------------------------------------------------
    229 
    230 static inline bool isSurfaceValid(const sp<Surface>& sur) {
    231     return Surface::isValid(sur);
    232 }
    233 
    234 // ----------------------------------------------------------------------------
    235 
    236 static jlong nativeCreateFromSurfaceTexture(JNIEnv* env, jclass clazz,
    237         jobject surfaceTextureObj) {
    238     sp<IGraphicBufferProducer> producer(SurfaceTexture_getProducer(env, surfaceTextureObj));
    239     if (producer == NULL) {
    240         jniThrowException(env, "java/lang/IllegalArgumentException",
    241                 "SurfaceTexture has already been released");
    242         return 0;
    243     }
    244 
    245     sp<Surface> surface(new Surface(producer, true));
    246     if (surface == NULL) {
    247         jniThrowException(env, OutOfResourcesException, NULL);
    248         return 0;
    249     }
    250 
    251     surface->incStrong(&sRefBaseOwner);
    252     return jlong(surface.get());
    253 }
    254 
    255 static void nativeRelease(JNIEnv* env, jclass clazz, jlong nativeObject) {
    256     sp<Surface> sur(reinterpret_cast<Surface *>(nativeObject));
    257     sur->decStrong(&sRefBaseOwner);
    258 }
    259 
    260 static jboolean nativeIsValid(JNIEnv* env, jclass clazz, jlong nativeObject) {
    261     sp<Surface> sur(reinterpret_cast<Surface *>(nativeObject));
    262     return isSurfaceValid(sur) ? JNI_TRUE : JNI_FALSE;
    263 }
    264 
    265 static jboolean nativeIsConsumerRunningBehind(JNIEnv* env, jclass clazz, jlong nativeObject) {
    266     sp<Surface> sur(reinterpret_cast<Surface *>(nativeObject));
    267     if (!isSurfaceValid(sur)) {
    268         doThrowIAE(env);
    269         return JNI_FALSE;
    270     }
    271     int value = 0;
    272     ANativeWindow* anw = static_cast<ANativeWindow*>(sur.get());
    273     anw->query(anw, NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND, &value);
    274     return value;
    275 }
    276 
    277 static inline SkColorType convertPixelFormat(PixelFormat format) {
    278     /* note: if PIXEL_FORMAT_RGBX_8888 means that all alpha bytes are 0xFF, then
    279         we can map to kN32_SkColorType, and optionally call
    280         bitmap.setAlphaType(kOpaque_SkAlphaType) on the resulting SkBitmap
    281         (as an accelerator)
    282     */
    283     switch (format) {
    284     case PIXEL_FORMAT_RGBX_8888:    return kN32_SkColorType;
    285     case PIXEL_FORMAT_RGBA_8888:    return kN32_SkColorType;
    286     case PIXEL_FORMAT_RGB_565:      return kRGB_565_SkColorType;
    287     default:                        return kUnknown_SkColorType;
    288     }
    289 }
    290 
    291 static jlong nativeLockCanvas(JNIEnv* env, jclass clazz,
    292         jlong nativeObject, jobject canvasObj, jobject dirtyRectObj) {
    293     sp<Surface> surface(reinterpret_cast<Surface *>(nativeObject));
    294 
    295     if (!isSurfaceValid(surface)) {
    296         doThrowIAE(env);
    297         return 0;
    298     }
    299 
    300     Rect dirtyRect(Rect::EMPTY_RECT);
    301     Rect* dirtyRectPtr = NULL;
    302 
    303     if (dirtyRectObj) {
    304         dirtyRect.left   = env->GetIntField(dirtyRectObj, gRectClassInfo.left);
    305         dirtyRect.top    = env->GetIntField(dirtyRectObj, gRectClassInfo.top);
    306         dirtyRect.right  = env->GetIntField(dirtyRectObj, gRectClassInfo.right);
    307         dirtyRect.bottom = env->GetIntField(dirtyRectObj, gRectClassInfo.bottom);
    308         dirtyRectPtr = &dirtyRect;
    309     }
    310 
    311     ANativeWindow_Buffer outBuffer;
    312     status_t err = surface->lock(&outBuffer, dirtyRectPtr);
    313     if (err < 0) {
    314         const char* const exception = (err == NO_MEMORY) ?
    315                 OutOfResourcesException :
    316                 "java/lang/IllegalArgumentException";
    317         jniThrowException(env, exception, NULL);
    318         return 0;
    319     }
    320 
    321 
    322     SkImageInfo info = SkImageInfo::Make(outBuffer.width, outBuffer.height,
    323                                          convertPixelFormat(outBuffer.format),
    324                                          outBuffer.format == PIXEL_FORMAT_RGBX_8888 ?
    325                                          kOpaque_SkAlphaType : kPremul_SkAlphaType);
    326 
    327     SkBitmap bitmap;
    328     ssize_t bpr = outBuffer.stride * bytesPerPixel(outBuffer.format);
    329     bitmap.setInfo(info, bpr);
    330     if (outBuffer.width > 0 && outBuffer.height > 0) {
    331         bitmap.setPixels(outBuffer.bits);
    332     } else {
    333         // be safe with an empty bitmap.
    334         bitmap.setPixels(NULL);
    335     }
    336 
    337     Canvas* nativeCanvas = GraphicsJNI::getNativeCanvas(env, canvasObj);
    338     nativeCanvas->setBitmap(bitmap);
    339 
    340     if (dirtyRectPtr) {
    341         nativeCanvas->clipRect(dirtyRect.left, dirtyRect.top,
    342                 dirtyRect.right, dirtyRect.bottom);
    343     }
    344 
    345     if (dirtyRectObj) {
    346         env->SetIntField(dirtyRectObj, gRectClassInfo.left,   dirtyRect.left);
    347         env->SetIntField(dirtyRectObj, gRectClassInfo.top,    dirtyRect.top);
    348         env->SetIntField(dirtyRectObj, gRectClassInfo.right,  dirtyRect.right);
    349         env->SetIntField(dirtyRectObj, gRectClassInfo.bottom, dirtyRect.bottom);
    350     }
    351 
    352     // Create another reference to the surface and return it.  This reference
    353     // should be passed to nativeUnlockCanvasAndPost in place of mNativeObject,
    354     // because the latter could be replaced while the surface is locked.
    355     sp<Surface> lockedSurface(surface);
    356     lockedSurface->incStrong(&sRefBaseOwner);
    357     return (jlong) lockedSurface.get();
    358 }
    359 
    360 static void nativeUnlockCanvasAndPost(JNIEnv* env, jclass clazz,
    361         jlong nativeObject, jobject canvasObj) {
    362     sp<Surface> surface(reinterpret_cast<Surface *>(nativeObject));
    363     if (!isSurfaceValid(surface)) {
    364         return;
    365     }
    366 
    367     // detach the canvas from the surface
    368     Canvas* nativeCanvas = GraphicsJNI::getNativeCanvas(env, canvasObj);
    369     nativeCanvas->setBitmap(SkBitmap());
    370 
    371     // unlock surface
    372     status_t err = surface->unlockAndPost();
    373     if (err < 0) {
    374         doThrowIAE(env);
    375     }
    376 }
    377 
    378 static void nativeAllocateBuffers(JNIEnv* /* env */ , jclass /* clazz */,
    379         jlong nativeObject) {
    380     sp<Surface> surface(reinterpret_cast<Surface *>(nativeObject));
    381     if (!isSurfaceValid(surface)) {
    382         return;
    383     }
    384 
    385     surface->allocateBuffers();
    386 }
    387 
    388 // ----------------------------------------------------------------------------
    389 
    390 static jlong nativeCreateFromSurfaceControl(JNIEnv* env, jclass clazz,
    391         jlong surfaceControlNativeObj) {
    392     /*
    393      * This is used by the WindowManagerService just after constructing
    394      * a Surface and is necessary for returning the Surface reference to
    395      * the caller. At this point, we should only have a SurfaceControl.
    396      */
    397 
    398     sp<SurfaceControl> ctrl(reinterpret_cast<SurfaceControl *>(surfaceControlNativeObj));
    399     sp<Surface> surface(ctrl->getSurface());
    400     if (surface != NULL) {
    401         surface->incStrong(&sRefBaseOwner);
    402     }
    403     return reinterpret_cast<jlong>(surface.get());
    404 }
    405 
    406 static jlong nativeReadFromParcel(JNIEnv* env, jclass clazz,
    407         jlong nativeObject, jobject parcelObj) {
    408     Parcel* parcel = parcelForJavaObject(env, parcelObj);
    409     if (parcel == NULL) {
    410         doThrowNPE(env);
    411         return 0;
    412     }
    413 
    414     android::view::Surface surfaceShim;
    415 
    416     // Calling code in Surface.java has already read the name of the Surface
    417     // from the Parcel
    418     surfaceShim.readFromParcel(parcel, /*nameAlreadyRead*/true);
    419 
    420     sp<Surface> self(reinterpret_cast<Surface *>(nativeObject));
    421 
    422     // update the Surface only if the underlying IGraphicBufferProducer
    423     // has changed.
    424     if (self != nullptr
    425             && (IInterface::asBinder(self->getIGraphicBufferProducer()) ==
    426                     IInterface::asBinder(surfaceShim.graphicBufferProducer))) {
    427         // same IGraphicBufferProducer, return ourselves
    428         return jlong(self.get());
    429     }
    430 
    431     sp<Surface> sur;
    432     if (surfaceShim.graphicBufferProducer != nullptr) {
    433         // we have a new IGraphicBufferProducer, create a new Surface for it
    434         sur = new Surface(surfaceShim.graphicBufferProducer, true);
    435         // and keep a reference before passing to java
    436         sur->incStrong(&sRefBaseOwner);
    437     }
    438 
    439     if (self != NULL) {
    440         // and loose the java reference to ourselves
    441         self->decStrong(&sRefBaseOwner);
    442     }
    443 
    444     return jlong(sur.get());
    445 }
    446 
    447 static void nativeWriteToParcel(JNIEnv* env, jclass clazz,
    448         jlong nativeObject, jobject parcelObj) {
    449     Parcel* parcel = parcelForJavaObject(env, parcelObj);
    450     if (parcel == NULL) {
    451         doThrowNPE(env);
    452         return;
    453     }
    454     sp<Surface> self(reinterpret_cast<Surface *>(nativeObject));
    455     android::view::Surface surfaceShim;
    456     if (self != nullptr) {
    457         surfaceShim.graphicBufferProducer = self->getIGraphicBufferProducer();
    458     }
    459     // Calling code in Surface.java has already written the name of the Surface
    460     // to the Parcel
    461     surfaceShim.writeToParcel(parcel, /*nameAlreadyWritten*/true);
    462 }
    463 
    464 static jint nativeGetWidth(JNIEnv* env, jclass clazz, jlong nativeObject) {
    465     Surface* surface = reinterpret_cast<Surface*>(nativeObject);
    466     ANativeWindow* anw = static_cast<ANativeWindow*>(surface);
    467     int value = 0;
    468     anw->query(anw, NATIVE_WINDOW_WIDTH, &value);
    469     return value;
    470 }
    471 
    472 static jint nativeGetHeight(JNIEnv* env, jclass clazz, jlong nativeObject) {
    473     Surface* surface = reinterpret_cast<Surface*>(nativeObject);
    474     ANativeWindow* anw = static_cast<ANativeWindow*>(surface);
    475     int value = 0;
    476     anw->query(anw, NATIVE_WINDOW_HEIGHT, &value);
    477     return value;
    478 }
    479 
    480 static jlong nativeGetNextFrameNumber(JNIEnv *env, jclass clazz, jlong nativeObject) {
    481     Surface* surface = reinterpret_cast<Surface*>(nativeObject);
    482     return surface->getNextFrameNumber();
    483 }
    484 
    485 static jint nativeSetScalingMode(JNIEnv *env, jclass clazz, jlong nativeObject, jint scalingMode) {
    486     Surface* surface = reinterpret_cast<Surface*>(nativeObject);
    487     return surface->setScalingMode(scalingMode);
    488 }
    489 
    490 namespace uirenderer {
    491 
    492 using namespace android::uirenderer::renderthread;
    493 
    494 class ContextFactory : public IContextFactory {
    495 public:
    496     virtual AnimationContext* createAnimationContext(renderthread::TimeLord& clock) {
    497         return new AnimationContext(clock);
    498     }
    499 };
    500 
    501 static jlong create(JNIEnv* env, jclass clazz, jlong rootNodePtr, jlong surfacePtr) {
    502     RenderNode* rootNode = reinterpret_cast<RenderNode*>(rootNodePtr);
    503     sp<Surface> surface(reinterpret_cast<Surface*>(surfacePtr));
    504     ContextFactory factory;
    505     RenderProxy* proxy = new RenderProxy(false, rootNode, &factory);
    506     proxy->loadSystemProperties();
    507     proxy->setSwapBehavior(kSwap_discardBuffer);
    508     proxy->initialize(surface);
    509     // Shadows can't be used via this interface, so just set the light source
    510     // to all 0s. (and width & height are unused, TODO remove them)
    511     proxy->setup(0, 0, 0, 0, 0);
    512     proxy->setLightCenter((Vector3){0, 0, 0});
    513     return (jlong) proxy;
    514 }
    515 
    516 static void setSurface(JNIEnv* env, jclass clazz, jlong rendererPtr, jlong surfacePtr) {
    517     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(rendererPtr);
    518     sp<Surface> surface(reinterpret_cast<Surface*>(surfacePtr));
    519     proxy->updateSurface(surface);
    520 }
    521 
    522 static void draw(JNIEnv* env, jclass clazz, jlong rendererPtr) {
    523     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(rendererPtr);
    524     nsecs_t vsync = systemTime(CLOCK_MONOTONIC);
    525     UiFrameInfoBuilder(proxy->frameInfo())
    526             .setVsync(vsync, vsync)
    527             .addFlag(FrameInfoFlags::SurfaceCanvas);
    528     proxy->syncAndDrawFrame(nullptr);
    529 }
    530 
    531 static void destroy(JNIEnv* env, jclass clazz, jlong rendererPtr) {
    532     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(rendererPtr);
    533     delete proxy;
    534 }
    535 
    536 } // uirenderer
    537 
    538 // ----------------------------------------------------------------------------
    539 
    540 namespace hwui = android::uirenderer;
    541 
    542 static const JNINativeMethod gSurfaceMethods[] = {
    543     {"nativeCreateFromSurfaceTexture", "(Landroid/graphics/SurfaceTexture;)J",
    544             (void*)nativeCreateFromSurfaceTexture },
    545     {"nativeRelease", "(J)V",
    546             (void*)nativeRelease },
    547     {"nativeIsValid", "(J)Z",
    548             (void*)nativeIsValid },
    549     {"nativeIsConsumerRunningBehind", "(J)Z",
    550             (void*)nativeIsConsumerRunningBehind },
    551     {"nativeLockCanvas", "(JLandroid/graphics/Canvas;Landroid/graphics/Rect;)J",
    552             (void*)nativeLockCanvas },
    553     {"nativeUnlockCanvasAndPost", "(JLandroid/graphics/Canvas;)V",
    554             (void*)nativeUnlockCanvasAndPost },
    555     {"nativeAllocateBuffers", "(J)V",
    556             (void*)nativeAllocateBuffers },
    557     {"nativeCreateFromSurfaceControl", "(J)J",
    558             (void*)nativeCreateFromSurfaceControl },
    559     {"nativeReadFromParcel", "(JLandroid/os/Parcel;)J",
    560             (void*)nativeReadFromParcel },
    561     {"nativeWriteToParcel", "(JLandroid/os/Parcel;)V",
    562             (void*)nativeWriteToParcel },
    563     {"nativeGetWidth", "(J)I", (void*)nativeGetWidth },
    564     {"nativeGetHeight", "(J)I", (void*)nativeGetHeight },
    565     {"nativeGetNextFrameNumber", "(J)J", (void*)nativeGetNextFrameNumber },
    566     {"nativeSetScalingMode", "(JI)I", (void*)nativeSetScalingMode },
    567 
    568     // HWUI context
    569     {"nHwuiCreate", "(JJ)J", (void*) hwui::create },
    570     {"nHwuiSetSurface", "(JJ)V", (void*) hwui::setSurface },
    571     {"nHwuiDraw", "(J)V", (void*) hwui::draw },
    572     {"nHwuiDestroy", "(J)V", (void*) hwui::destroy },
    573 };
    574 
    575 int register_android_view_Surface(JNIEnv* env)
    576 {
    577     int err = RegisterMethodsOrDie(env, "android/view/Surface",
    578             gSurfaceMethods, NELEM(gSurfaceMethods));
    579 
    580     jclass clazz = FindClassOrDie(env, "android/view/Surface");
    581     gSurfaceClassInfo.clazz = MakeGlobalRefOrDie(env, clazz);
    582     gSurfaceClassInfo.mNativeObject = GetFieldIDOrDie(env,
    583             gSurfaceClassInfo.clazz, "mNativeObject", "J");
    584     gSurfaceClassInfo.mLock = GetFieldIDOrDie(env,
    585             gSurfaceClassInfo.clazz, "mLock", "Ljava/lang/Object;");
    586     gSurfaceClassInfo.ctor = GetMethodIDOrDie(env, gSurfaceClassInfo.clazz, "<init>", "(J)V");
    587 
    588     clazz = FindClassOrDie(env, "android/graphics/Rect");
    589     gRectClassInfo.left = GetFieldIDOrDie(env, clazz, "left", "I");
    590     gRectClassInfo.top = GetFieldIDOrDie(env, clazz, "top", "I");
    591     gRectClassInfo.right = GetFieldIDOrDie(env, clazz, "right", "I");
    592     gRectClassInfo.bottom = GetFieldIDOrDie(env, clazz, "bottom", "I");
    593 
    594     return err;
    595 }
    596 
    597 };
    598