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