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