android_view_Surface.cpp revision 8451b25a4422656bbd6657a5855e69c0f4d53c74
1/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "Surface"
18
19#include <stdio.h>
20
21#include "android_util_Binder.h"
22#include "android/graphics/GraphicsJNI.h"
23
24#include <binder/IMemory.h>
25#include <surfaceflinger/SurfaceComposerClient.h>
26#include <surfaceflinger/Surface.h>
27#include <ui/Region.h>
28#include <ui/Rect.h>
29
30#include <EGL/egl.h>
31
32#include <SkCanvas.h>
33#include <SkBitmap.h>
34#include <SkRegion.h>
35#include <SkPixelRef.h>
36
37#include "jni.h"
38#include "JNIHelp.h"
39#include <android_runtime/AndroidRuntime.h>
40#include <android_runtime/android_view_Surface.h>
41#include <utils/misc.h>
42
43
44// ----------------------------------------------------------------------------
45
46namespace android {
47
48enum {
49    // should match Parcelable.java
50    PARCELABLE_WRITE_RETURN_VALUE = 0x0001
51};
52
53// ----------------------------------------------------------------------------
54
55static const char* const OutOfResourcesException =
56    "android/view/Surface$OutOfResourcesException";
57
58struct sso_t {
59    jfieldID client;
60};
61static sso_t sso;
62
63struct so_t {
64    jfieldID surfaceControl;
65    jfieldID surfaceGenerationId;
66    jfieldID surface;
67    jfieldID saveCount;
68    jfieldID canvas;
69};
70static so_t so;
71
72struct ro_t {
73    jfieldID l;
74    jfieldID t;
75    jfieldID r;
76    jfieldID b;
77};
78static ro_t ro;
79
80struct po_t {
81    jfieldID x;
82    jfieldID y;
83};
84static po_t po;
85
86struct co_t {
87    jfieldID surfaceFormat;
88};
89static co_t co;
90
91struct no_t {
92    jfieldID native_canvas;
93    jfieldID native_region;
94    jfieldID native_parcel;
95};
96static no_t no;
97
98
99// ----------------------------------------------------------------------------
100// ----------------------------------------------------------------------------
101// ----------------------------------------------------------------------------
102
103static void SurfaceSession_init(JNIEnv* env, jobject clazz)
104{
105    sp<SurfaceComposerClient> client = new SurfaceComposerClient;
106    client->incStrong(clazz);
107    env->SetIntField(clazz, sso.client, (int)client.get());
108}
109
110static void SurfaceSession_destroy(JNIEnv* env, jobject clazz)
111{
112    SurfaceComposerClient* client =
113            (SurfaceComposerClient*)env->GetIntField(clazz, sso.client);
114    if (client != 0) {
115        client->decStrong(clazz);
116        env->SetIntField(clazz, sso.client, 0);
117    }
118}
119
120static void SurfaceSession_kill(JNIEnv* env, jobject clazz)
121{
122    SurfaceComposerClient* client =
123            (SurfaceComposerClient*)env->GetIntField(clazz, sso.client);
124    if (client != 0) {
125        client->dispose();
126        client->decStrong(clazz);
127        env->SetIntField(clazz, sso.client, 0);
128    }
129}
130
131// ----------------------------------------------------------------------------
132
133static sp<SurfaceControl> getSurfaceControl(JNIEnv* env, jobject clazz)
134{
135    SurfaceControl* const p =
136        (SurfaceControl*)env->GetIntField(clazz, so.surfaceControl);
137    return sp<SurfaceControl>(p);
138}
139
140static void setSurfaceControl(JNIEnv* env, jobject clazz,
141        const sp<SurfaceControl>& surface)
142{
143    SurfaceControl* const p =
144        (SurfaceControl*)env->GetIntField(clazz, so.surfaceControl);
145    if (surface.get()) {
146        surface->incStrong(clazz);
147    }
148    if (p) {
149        p->decStrong(clazz);
150    }
151    env->SetIntField(clazz, so.surfaceControl, (int)surface.get());
152}
153
154static sp<Surface> getSurface(JNIEnv* env, jobject clazz)
155{
156    sp<Surface> result((Surface*)env->GetIntField(clazz, so.surface));
157    if (result == 0) {
158        /*
159         * if this method is called from the WindowManager's process, it means
160         * the client is is not remote, and therefore is allowed to have
161         * a Surface (data), so we create it here.
162         * If we don't have a SurfaceControl, it means we're in a different
163         * process.
164         */
165
166        SurfaceControl* const control =
167            (SurfaceControl*)env->GetIntField(clazz, so.surfaceControl);
168        if (control) {
169            result = control->getSurface();
170            if (result != 0) {
171                result->incStrong(clazz);
172                env->SetIntField(clazz, so.surface, (int)result.get());
173            }
174        }
175    }
176    return result;
177}
178
179sp<ANativeWindow> android_Surface_getNativeWindow(
180        JNIEnv* env, jobject clazz) {
181    return getSurface(env, clazz);
182}
183
184static void setSurface(JNIEnv* env, jobject clazz, const sp<Surface>& surface)
185{
186    Surface* const p = (Surface*)env->GetIntField(clazz, so.surface);
187    if (surface.get()) {
188        surface->incStrong(clazz);
189    }
190    if (p) {
191        p->decStrong(clazz);
192    }
193    env->SetIntField(clazz, so.surface, (int)surface.get());
194    // This test is conservative and it would be better to compare the ISurfaces
195    if (p && p != surface.get()) {
196        jint generationId = env->GetIntField(clazz, so.surfaceGenerationId);
197        generationId++;
198        env->SetIntField(clazz, so.surfaceGenerationId, generationId);
199    }
200}
201
202// ----------------------------------------------------------------------------
203
204static void Surface_init(
205        JNIEnv* env, jobject clazz,
206        jobject session,
207        jint pid, jstring jname, jint dpy, jint w, jint h, jint format, jint flags)
208{
209    if (session == NULL) {
210        doThrowNPE(env);
211        return;
212    }
213
214    SurfaceComposerClient* client =
215            (SurfaceComposerClient*)env->GetIntField(session, sso.client);
216
217    sp<SurfaceControl> surface;
218    if (jname == NULL) {
219        surface = client->createSurface(pid, dpy, w, h, format, flags);
220    } else {
221        const jchar* str = env->GetStringCritical(jname, 0);
222        const String8 name(str, env->GetStringLength(jname));
223        env->ReleaseStringCritical(jname, str);
224        surface = client->createSurface(pid, name, dpy, w, h, format, flags);
225    }
226
227    if (surface == 0) {
228        jniThrowException(env, OutOfResourcesException, NULL);
229        return;
230    }
231    setSurfaceControl(env, clazz, surface);
232}
233
234static void Surface_initParcel(JNIEnv* env, jobject clazz, jobject argParcel)
235{
236    Parcel* parcel = (Parcel*)env->GetIntField(argParcel, no.native_parcel);
237    if (parcel == NULL) {
238        doThrowNPE(env);
239        return;
240    }
241
242    sp<Surface> sur(Surface::readFromParcel(*parcel));
243    setSurface(env, clazz, sur);
244}
245
246static jint Surface_getIdentity(JNIEnv* env, jobject clazz)
247{
248    const sp<SurfaceControl>& control(getSurfaceControl(env, clazz));
249    if (control != 0) return (jint) control->getIdentity();
250    const sp<Surface>& surface(getSurface(env, clazz));
251    if (surface != 0) return (jint) surface->getIdentity();
252    return -1;
253}
254
255static void Surface_destroy(JNIEnv* env, jobject clazz, uintptr_t *ostack)
256{
257    const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
258    if (SurfaceControl::isValid(surface)) {
259        surface->clear();
260    }
261    setSurfaceControl(env, clazz, 0);
262    setSurface(env, clazz, 0);
263}
264
265static void Surface_release(JNIEnv* env, jobject clazz, uintptr_t *ostack)
266{
267    setSurfaceControl(env, clazz, 0);
268    setSurface(env, clazz, 0);
269}
270
271static jboolean Surface_isValid(JNIEnv* env, jobject clazz)
272{
273    const sp<SurfaceControl>& surfaceControl(getSurfaceControl(env, clazz));
274    if (surfaceControl != 0) {
275        return SurfaceControl::isValid(surfaceControl) ? JNI_TRUE : JNI_FALSE;
276    }
277    const sp<Surface>& surface(getSurface(env, clazz));
278    return Surface::isValid(surface) ? JNI_TRUE : JNI_FALSE;
279}
280
281static inline SkBitmap::Config convertPixelFormat(PixelFormat format)
282{
283    /* note: if PIXEL_FORMAT_RGBX_8888 means that all alpha bytes are 0xFF, then
284        we can map to SkBitmap::kARGB_8888_Config, and optionally call
285        bitmap.setIsOpaque(true) on the resulting SkBitmap (as an accelerator)
286    */
287    switch (format) {
288    case PIXEL_FORMAT_RGBX_8888:    return SkBitmap::kARGB_8888_Config;
289    case PIXEL_FORMAT_RGBA_8888:    return SkBitmap::kARGB_8888_Config;
290    case PIXEL_FORMAT_RGBA_4444:    return SkBitmap::kARGB_4444_Config;
291    case PIXEL_FORMAT_RGB_565:      return SkBitmap::kRGB_565_Config;
292    case PIXEL_FORMAT_A_8:          return SkBitmap::kA8_Config;
293    default:                        return SkBitmap::kNo_Config;
294    }
295}
296
297static jobject Surface_lockCanvas(JNIEnv* env, jobject clazz, jobject dirtyRect)
298{
299    const sp<Surface>& surface(getSurface(env, clazz));
300    if (!Surface::isValid(surface)) {
301        doThrowIAE(env);
302        return 0;
303    }
304
305    // get dirty region
306    Region dirtyRegion;
307    if (dirtyRect) {
308        Rect dirty;
309        dirty.left  = env->GetIntField(dirtyRect, ro.l);
310        dirty.top   = env->GetIntField(dirtyRect, ro.t);
311        dirty.right = env->GetIntField(dirtyRect, ro.r);
312        dirty.bottom= env->GetIntField(dirtyRect, ro.b);
313        if (!dirty.isEmpty()) {
314            dirtyRegion.set(dirty);
315        }
316    } else {
317        dirtyRegion.set(Rect(0x3FFF,0x3FFF));
318    }
319
320    Surface::SurfaceInfo info;
321    status_t err = surface->lock(&info, &dirtyRegion);
322    if (err < 0) {
323        const char* const exception = (err == NO_MEMORY) ?
324            OutOfResourcesException :
325            "java/lang/IllegalArgumentException";
326        jniThrowException(env, exception, NULL);
327        return 0;
328    }
329
330    // Associate a SkCanvas object to this surface
331    jobject canvas = env->GetObjectField(clazz, so.canvas);
332    env->SetIntField(canvas, co.surfaceFormat, info.format);
333
334    SkCanvas* nativeCanvas = (SkCanvas*)env->GetIntField(canvas, no.native_canvas);
335    SkBitmap bitmap;
336    ssize_t bpr = info.s * bytesPerPixel(info.format);
337    bitmap.setConfig(convertPixelFormat(info.format), info.w, info.h, bpr);
338    if (info.format == PIXEL_FORMAT_RGBX_8888) {
339        bitmap.setIsOpaque(true);
340    }
341    if (info.w > 0 && info.h > 0) {
342        bitmap.setPixels(info.bits);
343    } else {
344        // be safe with an empty bitmap.
345        bitmap.setPixels(NULL);
346    }
347    nativeCanvas->setBitmapDevice(bitmap);
348
349    SkRegion clipReg;
350    if (dirtyRegion.isRect()) { // very common case
351        const Rect b(dirtyRegion.getBounds());
352        clipReg.setRect(b.left, b.top, b.right, b.bottom);
353    } else {
354        size_t count;
355        Rect const* r = dirtyRegion.getArray(&count);
356        while (count) {
357            clipReg.op(r->left, r->top, r->right, r->bottom, SkRegion::kUnion_Op);
358            r++, count--;
359        }
360    }
361
362    nativeCanvas->clipRegion(clipReg);
363
364    int saveCount = nativeCanvas->save();
365    env->SetIntField(clazz, so.saveCount, saveCount);
366
367    if (dirtyRect) {
368        const Rect& bounds(dirtyRegion.getBounds());
369        env->SetIntField(dirtyRect, ro.l, bounds.left);
370        env->SetIntField(dirtyRect, ro.t, bounds.top);
371        env->SetIntField(dirtyRect, ro.r, bounds.right);
372        env->SetIntField(dirtyRect, ro.b, bounds.bottom);
373    }
374
375    return canvas;
376}
377
378static void Surface_unlockCanvasAndPost(
379        JNIEnv* env, jobject clazz, jobject argCanvas)
380{
381    jobject canvas = env->GetObjectField(clazz, so.canvas);
382    if (env->IsSameObject(canvas, argCanvas) == JNI_FALSE) {
383        doThrowIAE(env);
384        return;
385    }
386
387    const sp<Surface>& surface(getSurface(env, clazz));
388    if (!Surface::isValid(surface))
389        return;
390
391    // detach the canvas from the surface
392    SkCanvas* nativeCanvas = (SkCanvas*)env->GetIntField(canvas, no.native_canvas);
393    int saveCount = env->GetIntField(clazz, so.saveCount);
394    nativeCanvas->restoreToCount(saveCount);
395    nativeCanvas->setBitmapDevice(SkBitmap());
396    env->SetIntField(clazz, so.saveCount, 0);
397
398    // unlock surface
399    status_t err = surface->unlockAndPost();
400    if (err < 0) {
401        doThrowIAE(env);
402    }
403}
404
405static void Surface_unlockCanvas(
406        JNIEnv* env, jobject clazz, jobject argCanvas)
407{
408    // XXX: this API has been removed
409    doThrowIAE(env);
410}
411
412static void Surface_openTransaction(
413        JNIEnv* env, jobject clazz)
414{
415    SurfaceComposerClient::openGlobalTransaction();
416}
417
418static void Surface_closeTransaction(
419        JNIEnv* env, jobject clazz)
420{
421    SurfaceComposerClient::closeGlobalTransaction();
422}
423
424static void Surface_setOrientation(
425        JNIEnv* env, jobject clazz, jint display, jint orientation, jint flags)
426{
427    int err = SurfaceComposerClient::setOrientation(display, orientation, flags);
428    if (err < 0) {
429        doThrowIAE(env);
430    }
431}
432
433static void Surface_freezeDisplay(
434        JNIEnv* env, jobject clazz, jint display)
435{
436    int err = SurfaceComposerClient::freezeDisplay(display, 0);
437    if (err < 0) {
438        doThrowIAE(env);
439    }
440}
441
442static void Surface_unfreezeDisplay(
443        JNIEnv* env, jobject clazz, jint display)
444{
445    int err = SurfaceComposerClient::unfreezeDisplay(display, 0);
446    if (err < 0) {
447        doThrowIAE(env);
448    }
449}
450
451class ScreenshotPixelRef : public SkPixelRef {
452public:
453    ScreenshotPixelRef(SkColorTable* ctable) {
454        fCTable = ctable;
455        SkSafeRef(ctable);
456        setImmutable();
457    }
458    virtual ~ScreenshotPixelRef() {
459        SkSafeUnref(fCTable);
460    }
461
462    status_t update(int width, int height, int minLayer, int maxLayer, bool allLayers) {
463        status_t res = (width > 0 && height > 0)
464                ? (allLayers
465                        ? mScreenshot.update(width, height)
466                        : mScreenshot.update(width, height, minLayer, maxLayer))
467                : mScreenshot.update();
468        if (res != NO_ERROR) {
469            return res;
470        }
471
472        return NO_ERROR;
473    }
474
475    uint32_t getWidth() const {
476        return mScreenshot.getWidth();
477    }
478
479    uint32_t getHeight() const {
480        return mScreenshot.getHeight();
481    }
482
483    uint32_t getStride() const {
484        return mScreenshot.getStride();
485    }
486
487    uint32_t getFormat() const {
488        return mScreenshot.getFormat();
489    }
490
491protected:
492    // overrides from SkPixelRef
493    virtual void* onLockPixels(SkColorTable** ct) {
494        *ct = fCTable;
495        return (void*)mScreenshot.getPixels();
496    }
497
498    virtual void onUnlockPixels() {
499    }
500
501private:
502    ScreenshotClient mScreenshot;
503    SkColorTable*    fCTable;
504
505    typedef SkPixelRef INHERITED;
506};
507
508static jobject doScreenshot(JNIEnv* env, jobject clazz, jint width, jint height,
509        jint minLayer, jint maxLayer, bool allLayers)
510{
511    ScreenshotPixelRef* pixels = new ScreenshotPixelRef(NULL);
512    if (pixels->update(width, height, minLayer, maxLayer, allLayers) != NO_ERROR) {
513        delete pixels;
514        return 0;
515    }
516
517    uint32_t w = pixels->getWidth();
518    uint32_t h = pixels->getHeight();
519    uint32_t s = pixels->getStride();
520    uint32_t f = pixels->getFormat();
521    ssize_t bpr = s * android::bytesPerPixel(f);
522
523    SkBitmap* bitmap = new SkBitmap();
524    bitmap->setConfig(convertPixelFormat(f), w, h, bpr);
525    if (f == PIXEL_FORMAT_RGBX_8888) {
526        bitmap->setIsOpaque(true);
527    }
528
529    if (w > 0 && h > 0) {
530        bitmap->setPixelRef(pixels)->unref();
531        bitmap->lockPixels();
532    } else {
533        // be safe with an empty bitmap.
534        delete pixels;
535        bitmap->setPixels(NULL);
536    }
537
538    return GraphicsJNI::createBitmap(env, bitmap, false, NULL);
539}
540
541static jobject Surface_screenshotAll(JNIEnv* env, jobject clazz, jint width, jint height)
542{
543    return doScreenshot(env, clazz, width, height, 0, 0, true);
544}
545
546static jobject Surface_screenshot(JNIEnv* env, jobject clazz, jint width, jint height,
547        jint minLayer, jint maxLayer, bool allLayers)
548{
549    return doScreenshot(env, clazz, width, height, minLayer, maxLayer, false);
550}
551
552static void Surface_setLayer(
553        JNIEnv* env, jobject clazz, jint zorder)
554{
555    const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
556    if (surface == 0) return;
557    status_t err = surface->setLayer(zorder);
558    if (err<0 && err!=NO_INIT) {
559        doThrowIAE(env);
560    }
561}
562
563static void Surface_setPosition(
564        JNIEnv* env, jobject clazz, jint x, jint y)
565{
566    const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
567    if (surface == 0) return;
568    status_t err = surface->setPosition(x, y);
569    if (err<0 && err!=NO_INIT) {
570        doThrowIAE(env);
571    }
572}
573
574static void Surface_setSize(
575        JNIEnv* env, jobject clazz, jint w, jint h)
576{
577    const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
578    if (surface == 0) return;
579    status_t err = surface->setSize(w, h);
580    if (err<0 && err!=NO_INIT) {
581        doThrowIAE(env);
582    }
583}
584
585static void Surface_hide(
586        JNIEnv* env, jobject clazz)
587{
588    const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
589    if (surface == 0) return;
590    status_t err = surface->hide();
591    if (err<0 && err!=NO_INIT) {
592        doThrowIAE(env);
593    }
594}
595
596static void Surface_show(
597        JNIEnv* env, jobject clazz)
598{
599    const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
600    if (surface == 0) return;
601    status_t err = surface->show();
602    if (err<0 && err!=NO_INIT) {
603        doThrowIAE(env);
604    }
605}
606
607static void Surface_freeze(
608        JNIEnv* env, jobject clazz)
609{
610    const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
611    if (surface == 0) return;
612    status_t err = surface->freeze();
613    if (err<0 && err!=NO_INIT) {
614        doThrowIAE(env);
615    }
616}
617
618static void Surface_unfreeze(
619        JNIEnv* env, jobject clazz)
620{
621    const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
622    if (surface == 0) return;
623    status_t err = surface->unfreeze();
624    if (err<0 && err!=NO_INIT) {
625        doThrowIAE(env);
626    }
627}
628
629static void Surface_setFlags(
630        JNIEnv* env, jobject clazz, jint flags, jint mask)
631{
632    const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
633    if (surface == 0) return;
634    status_t err = surface->setFlags(flags, mask);
635    if (err<0 && err!=NO_INIT) {
636        doThrowIAE(env);
637    }
638}
639
640static void Surface_setTransparentRegion(
641        JNIEnv* env, jobject clazz, jobject argRegion)
642{
643    const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
644    if (surface == 0) return;
645    SkRegion* nativeRegion = (SkRegion*)env->GetIntField(argRegion, no.native_region);
646
647    const SkIRect& b(nativeRegion->getBounds());
648    Region reg(Rect(b.fLeft, b.fTop, b.fRight, b.fBottom));
649    if (nativeRegion->isComplex()) {
650        SkRegion::Iterator it(*nativeRegion);
651        while (!it.done()) {
652            const SkIRect& r(it.rect());
653            reg.addRectUnchecked(r.fLeft, r.fTop, r.fRight, r.fBottom);
654            it.next();
655        }
656    }
657
658    status_t err = surface->setTransparentRegionHint(reg);
659    if (err<0 && err!=NO_INIT) {
660        doThrowIAE(env);
661    }
662}
663
664static void Surface_setAlpha(
665        JNIEnv* env, jobject clazz, jfloat alpha)
666{
667    const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
668    if (surface == 0) return;
669    status_t err = surface->setAlpha(alpha);
670    if (err<0 && err!=NO_INIT) {
671        doThrowIAE(env);
672    }
673}
674
675static void Surface_setMatrix(
676        JNIEnv* env, jobject clazz,
677        jfloat dsdx, jfloat dtdx, jfloat dsdy, jfloat dtdy)
678{
679    const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
680    if (surface == 0) return;
681    status_t err = surface->setMatrix(dsdx, dtdx, dsdy, dtdy);
682    if (err<0 && err!=NO_INIT) {
683        doThrowIAE(env);
684    }
685}
686
687static void Surface_setFreezeTint(
688        JNIEnv* env, jobject clazz,
689        jint tint)
690{
691    const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
692    if (surface == 0) return;
693    status_t err = surface->setFreezeTint(tint);
694    if (err<0 && err!=NO_INIT) {
695        doThrowIAE(env);
696    }
697}
698
699// ----------------------------------------------------------------------------
700
701static void Surface_copyFrom(
702        JNIEnv* env, jobject clazz, jobject other)
703{
704    if (clazz == other)
705        return;
706
707    if (other == NULL) {
708        doThrowNPE(env);
709        return;
710    }
711
712    /*
713     * This is used by the WindowManagerService just after constructing
714     * a Surface and is necessary for returning the Surface reference to
715     * the caller. At this point, we should only have a SurfaceControl.
716     */
717
718    const sp<SurfaceControl>& surface = getSurfaceControl(env, clazz);
719    const sp<SurfaceControl>& rhs = getSurfaceControl(env, other);
720    if (!SurfaceControl::isSameSurface(surface, rhs)) {
721        // we reassign the surface only if it's a different one
722        // otherwise we would loose our client-side state.
723        setSurfaceControl(env, clazz, rhs);
724    }
725}
726
727static void Surface_readFromParcel(
728        JNIEnv* env, jobject clazz, jobject argParcel)
729{
730    Parcel* parcel = (Parcel*)env->GetIntField( argParcel, no.native_parcel);
731    if (parcel == NULL) {
732        doThrowNPE(env);
733        return;
734    }
735
736    sp<Surface> sur(Surface::readFromParcel(*parcel));
737    setSurface(env, clazz, sur);
738}
739
740static void Surface_writeToParcel(
741        JNIEnv* env, jobject clazz, jobject argParcel, jint flags)
742{
743    Parcel* parcel = (Parcel*)env->GetIntField(
744            argParcel, no.native_parcel);
745
746    if (parcel == NULL) {
747        doThrowNPE(env);
748        return;
749    }
750
751    const sp<SurfaceControl>& control(getSurfaceControl(env, clazz));
752    SurfaceControl::writeSurfaceToParcel(control, parcel);
753    if (flags & PARCELABLE_WRITE_RETURN_VALUE) {
754        setSurfaceControl(env, clazz, 0);
755    }
756}
757
758// ----------------------------------------------------------------------------
759// ----------------------------------------------------------------------------
760// ----------------------------------------------------------------------------
761
762const char* const kSurfaceSessionClassPathName = "android/view/SurfaceSession";
763const char* const kSurfaceClassPathName = "android/view/Surface";
764static void nativeClassInit(JNIEnv* env, jclass clazz);
765
766static JNINativeMethod gSurfaceSessionMethods[] = {
767    {"init",     "()V",  (void*)SurfaceSession_init },
768    {"destroy",  "()V",  (void*)SurfaceSession_destroy },
769    {"kill",     "()V",  (void*)SurfaceSession_kill },
770};
771
772static JNINativeMethod gSurfaceMethods[] = {
773    {"nativeClassInit",     "()V",  (void*)nativeClassInit },
774    {"init",                "(Landroid/view/SurfaceSession;ILjava/lang/String;IIIII)V",  (void*)Surface_init },
775    {"init",                "(Landroid/os/Parcel;)V",  (void*)Surface_initParcel },
776    {"getIdentity",         "()I",  (void*)Surface_getIdentity },
777    {"destroy",             "()V",  (void*)Surface_destroy },
778    {"release",             "()V",  (void*)Surface_release },
779    {"copyFrom",            "(Landroid/view/Surface;)V",  (void*)Surface_copyFrom },
780    {"isValid",             "()Z",  (void*)Surface_isValid },
781    {"lockCanvasNative",    "(Landroid/graphics/Rect;)Landroid/graphics/Canvas;",  (void*)Surface_lockCanvas },
782    {"unlockCanvasAndPost", "(Landroid/graphics/Canvas;)V", (void*)Surface_unlockCanvasAndPost },
783    {"unlockCanvas",        "(Landroid/graphics/Canvas;)V", (void*)Surface_unlockCanvas },
784    {"openTransaction",     "()V",  (void*)Surface_openTransaction },
785    {"closeTransaction",    "()V",  (void*)Surface_closeTransaction },
786    {"setOrientation",      "(III)V", (void*)Surface_setOrientation },
787    {"freezeDisplay",       "(I)V", (void*)Surface_freezeDisplay },
788    {"unfreezeDisplay",     "(I)V", (void*)Surface_unfreezeDisplay },
789    {"screenshot",          "(II)Landroid/graphics/Bitmap;", (void*)Surface_screenshotAll },
790    {"screenshot",          "(IIII)Landroid/graphics/Bitmap;", (void*)Surface_screenshot },
791    {"setLayer",            "(I)V", (void*)Surface_setLayer },
792    {"setPosition",         "(II)V",(void*)Surface_setPosition },
793    {"setSize",             "(II)V",(void*)Surface_setSize },
794    {"hide",                "()V",  (void*)Surface_hide },
795    {"show",                "()V",  (void*)Surface_show },
796    {"freeze",              "()V",  (void*)Surface_freeze },
797    {"unfreeze",            "()V",  (void*)Surface_unfreeze },
798    {"setFlags",            "(II)V",(void*)Surface_setFlags },
799    {"setTransparentRegionHint","(Landroid/graphics/Region;)V", (void*)Surface_setTransparentRegion },
800    {"setAlpha",            "(F)V", (void*)Surface_setAlpha },
801    {"setMatrix",           "(FFFF)V",  (void*)Surface_setMatrix },
802    {"setFreezeTint",       "(I)V",  (void*)Surface_setFreezeTint },
803    {"readFromParcel",      "(Landroid/os/Parcel;)V", (void*)Surface_readFromParcel },
804    {"writeToParcel",       "(Landroid/os/Parcel;I)V", (void*)Surface_writeToParcel },
805};
806
807void nativeClassInit(JNIEnv* env, jclass clazz)
808{
809    so.surface = env->GetFieldID(clazz, ANDROID_VIEW_SURFACE_JNI_ID, "I");
810    so.surfaceGenerationId = env->GetFieldID(clazz, "mSurfaceGenerationId", "I");
811    so.surfaceControl = env->GetFieldID(clazz, "mSurfaceControl", "I");
812    so.saveCount = env->GetFieldID(clazz, "mSaveCount", "I");
813    so.canvas    = env->GetFieldID(clazz, "mCanvas", "Landroid/graphics/Canvas;");
814
815    jclass surfaceSession = env->FindClass("android/view/SurfaceSession");
816    sso.client = env->GetFieldID(surfaceSession, "mClient", "I");
817
818    jclass canvas = env->FindClass("android/graphics/Canvas");
819    no.native_canvas = env->GetFieldID(canvas, "mNativeCanvas", "I");
820    co.surfaceFormat = env->GetFieldID(canvas, "mSurfaceFormat", "I");
821
822    jclass region = env->FindClass("android/graphics/Region");
823    no.native_region = env->GetFieldID(region, "mNativeRegion", "I");
824
825    jclass parcel = env->FindClass("android/os/Parcel");
826    no.native_parcel = env->GetFieldID(parcel, "mObject", "I");
827
828    jclass rect = env->FindClass("android/graphics/Rect");
829    ro.l = env->GetFieldID(rect, "left", "I");
830    ro.t = env->GetFieldID(rect, "top", "I");
831    ro.r = env->GetFieldID(rect, "right", "I");
832    ro.b = env->GetFieldID(rect, "bottom", "I");
833
834    jclass point = env->FindClass("android/graphics/Point");
835    po.x = env->GetFieldID(point, "x", "I");
836    po.y = env->GetFieldID(point, "y", "I");
837}
838
839int register_android_view_Surface(JNIEnv* env)
840{
841    int err;
842    err = AndroidRuntime::registerNativeMethods(env, kSurfaceSessionClassPathName,
843            gSurfaceSessionMethods, NELEM(gSurfaceSessionMethods));
844
845    err |= AndroidRuntime::registerNativeMethods(env, kSurfaceClassPathName,
846            gSurfaceMethods, NELEM(gSurfaceMethods));
847    return err;
848}
849
850};
851