android_view_Surface.cpp revision d2835935d2df8be70d1b37d3ef3b2fe0155b3422
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, int minLayer, int maxLayer, bool allLayers) {
453        status_t res = (width > 0 && height > 0)
454                ? (allLayers
455                        ? mScreenshot.update(width, height)
456                        : mScreenshot.update(width, height, minLayer, maxLayer))
457                : mScreenshot.update();
458        if (res != NO_ERROR) {
459            return res;
460        }
461
462        return NO_ERROR;
463    }
464
465    uint32_t getWidth() const {
466        return mScreenshot.getWidth();
467    }
468
469    uint32_t getHeight() const {
470        return mScreenshot.getHeight();
471    }
472
473    uint32_t getStride() const {
474        return mScreenshot.getStride();
475    }
476
477    uint32_t getFormat() const {
478        return mScreenshot.getFormat();
479    }
480
481protected:
482    // overrides from SkPixelRef
483    virtual void* onLockPixels(SkColorTable** ct) {
484        *ct = fCTable;
485        return (void*)mScreenshot.getPixels();
486    }
487
488    virtual void onUnlockPixels() {
489    }
490
491private:
492    ScreenshotClient mScreenshot;
493    SkColorTable*    fCTable;
494
495    typedef SkPixelRef INHERITED;
496};
497
498static jobject doScreenshot(JNIEnv* env, jobject clazz, jint width, jint height,
499        jint minLayer, jint maxLayer, bool allLayers)
500{
501    ScreenshotPixelRef* pixels = new ScreenshotPixelRef(NULL);
502    if (pixels->update(width, height, minLayer, maxLayer, allLayers) != NO_ERROR) {
503        delete pixels;
504        return 0;
505    }
506
507    uint32_t w = pixels->getWidth();
508    uint32_t h = pixels->getHeight();
509    uint32_t s = pixels->getStride();
510    uint32_t f = pixels->getFormat();
511    ssize_t bpr = s * android::bytesPerPixel(f);
512
513    SkBitmap* bitmap = new SkBitmap();
514    bitmap->setConfig(convertPixelFormat(f), w, h, bpr);
515    if (f == PIXEL_FORMAT_RGBX_8888) {
516        bitmap->setIsOpaque(true);
517    }
518
519    if (w > 0 && h > 0) {
520        bitmap->setPixelRef(pixels)->unref();
521        bitmap->lockPixels();
522    } else {
523        // be safe with an empty bitmap.
524        delete pixels;
525        bitmap->setPixels(NULL);
526    }
527
528    return GraphicsJNI::createBitmap(env, bitmap, false, NULL);
529}
530
531static jobject Surface_screenshotAll(JNIEnv* env, jobject clazz, jint width, jint height)
532{
533    return doScreenshot(env, clazz, width, height, 0, 0, true);
534}
535
536static jobject Surface_screenshot(JNIEnv* env, jobject clazz, jint width, jint height,
537        jint minLayer, jint maxLayer, bool allLayers)
538{
539    return doScreenshot(env, clazz, width, height, minLayer, maxLayer, false);
540}
541
542static void Surface_setLayer(
543        JNIEnv* env, jobject clazz, jint zorder)
544{
545    const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
546    if (surface == 0) return;
547    status_t err = surface->setLayer(zorder);
548    if (err<0 && err!=NO_INIT)
549        doThrow(env, "java/lang/IllegalArgumentException", NULL);
550}
551
552static void Surface_setPosition(
553        JNIEnv* env, jobject clazz, jint x, jint y)
554{
555    const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
556    if (surface == 0) return;
557    status_t err = surface->setPosition(x, y);
558    if (err<0 && err!=NO_INIT)
559        doThrow(env, "java/lang/IllegalArgumentException", NULL);
560}
561
562static void Surface_setSize(
563        JNIEnv* env, jobject clazz, jint w, jint h)
564{
565    const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
566    if (surface == 0) return;
567    status_t err = surface->setSize(w, h);
568    if (err<0 && err!=NO_INIT)
569        doThrow(env, "java/lang/IllegalArgumentException", NULL);
570}
571
572static void Surface_hide(
573        JNIEnv* env, jobject clazz)
574{
575    const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
576    if (surface == 0) return;
577    status_t err = surface->hide();
578    if (err<0 && err!=NO_INIT)
579        doThrow(env, "java/lang/IllegalArgumentException", NULL);
580}
581
582static void Surface_show(
583        JNIEnv* env, jobject clazz)
584{
585    const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
586    if (surface == 0) return;
587    status_t err = surface->show();
588    if (err<0 && err!=NO_INIT)
589        doThrow(env, "java/lang/IllegalArgumentException", NULL);
590}
591
592static void Surface_freeze(
593        JNIEnv* env, jobject clazz)
594{
595    const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
596    if (surface == 0) return;
597    status_t err = surface->freeze();
598    if (err<0 && err!=NO_INIT)
599        doThrow(env, "java/lang/IllegalArgumentException", NULL);
600}
601
602static void Surface_unfreeze(
603        JNIEnv* env, jobject clazz)
604{
605    const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
606    if (surface == 0) return;
607    status_t err = surface->unfreeze();
608    if (err<0 && err!=NO_INIT)
609        doThrow(env, "java/lang/IllegalArgumentException", NULL);
610}
611
612static void Surface_setFlags(
613        JNIEnv* env, jobject clazz, jint flags, jint mask)
614{
615    const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
616    if (surface == 0) return;
617    status_t err = surface->setFlags(flags, mask);
618    if (err<0 && err!=NO_INIT)
619        doThrow(env, "java/lang/IllegalArgumentException", NULL);
620}
621
622static void Surface_setTransparentRegion(
623        JNIEnv* env, jobject clazz, jobject argRegion)
624{
625    const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
626    if (surface == 0) return;
627    SkRegion* nativeRegion = (SkRegion*)env->GetIntField(argRegion, no.native_region);
628
629    const SkIRect& b(nativeRegion->getBounds());
630    Region reg(Rect(b.fLeft, b.fTop, b.fRight, b.fBottom));
631    if (nativeRegion->isComplex()) {
632        SkRegion::Iterator it(*nativeRegion);
633        while (!it.done()) {
634            const SkIRect& r(it.rect());
635            reg.addRectUnchecked(r.fLeft, r.fTop, r.fRight, r.fBottom);
636            it.next();
637        }
638    }
639
640    status_t err = surface->setTransparentRegionHint(reg);
641    if (err<0 && err!=NO_INIT)
642        doThrow(env, "java/lang/IllegalArgumentException", NULL);
643}
644
645static void Surface_setAlpha(
646        JNIEnv* env, jobject clazz, jfloat alpha)
647{
648    const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
649    if (surface == 0) return;
650    status_t err = surface->setAlpha(alpha);
651    if (err<0 && err!=NO_INIT)
652        doThrow(env, "java/lang/IllegalArgumentException", NULL);
653}
654
655static void Surface_setMatrix(
656        JNIEnv* env, jobject clazz,
657        jfloat dsdx, jfloat dtdx, jfloat dsdy, jfloat dtdy)
658{
659    const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
660    if (surface == 0) return;
661    status_t err = surface->setMatrix(dsdx, dtdx, dsdy, dtdy);
662    if (err<0 && err!=NO_INIT)
663        doThrow(env, "java/lang/IllegalArgumentException", NULL);
664}
665
666static void Surface_setFreezeTint(
667        JNIEnv* env, jobject clazz,
668        jint tint)
669{
670    const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
671    if (surface == 0) return;
672    status_t err = surface->setFreezeTint(tint);
673    if (err<0 && err!=NO_INIT)
674        doThrow(env, "java/lang/IllegalArgumentException", NULL);
675}
676
677// ----------------------------------------------------------------------------
678
679static void Surface_copyFrom(
680        JNIEnv* env, jobject clazz, jobject other)
681{
682    if (clazz == other)
683        return;
684
685    if (other == NULL) {
686        doThrow(env, "java/lang/NullPointerException", NULL);
687        return;
688    }
689
690    /*
691     * This is used by the WindowManagerService just after constructing
692     * a Surface and is necessary for returning the Surface reference to
693     * the caller. At this point, we should only have a SurfaceControl.
694     */
695
696    const sp<SurfaceControl>& surface = getSurfaceControl(env, clazz);
697    const sp<SurfaceControl>& rhs = getSurfaceControl(env, other);
698    if (!SurfaceControl::isSameSurface(surface, rhs)) {
699        // we reassign the surface only if it's a different one
700        // otherwise we would loose our client-side state.
701        setSurfaceControl(env, clazz, rhs);
702    }
703}
704
705static void Surface_readFromParcel(
706        JNIEnv* env, jobject clazz, jobject argParcel)
707{
708    Parcel* parcel = (Parcel*)env->GetIntField( argParcel, no.native_parcel);
709    if (parcel == NULL) {
710        doThrow(env, "java/lang/NullPointerException", NULL);
711        return;
712    }
713
714    sp<Surface> sur(Surface::readFromParcel(*parcel));
715    setSurface(env, clazz, sur);
716}
717
718static void Surface_writeToParcel(
719        JNIEnv* env, jobject clazz, jobject argParcel, jint flags)
720{
721    Parcel* parcel = (Parcel*)env->GetIntField(
722            argParcel, no.native_parcel);
723
724    if (parcel == NULL) {
725        doThrow(env, "java/lang/NullPointerException", NULL);
726        return;
727    }
728
729    const sp<SurfaceControl>& control(getSurfaceControl(env, clazz));
730    SurfaceControl::writeSurfaceToParcel(control, parcel);
731    if (flags & PARCELABLE_WRITE_RETURN_VALUE) {
732        setSurfaceControl(env, clazz, 0);
733    }
734}
735
736// ----------------------------------------------------------------------------
737// ----------------------------------------------------------------------------
738// ----------------------------------------------------------------------------
739
740const char* const kSurfaceSessionClassPathName = "android/view/SurfaceSession";
741const char* const kSurfaceClassPathName = "android/view/Surface";
742static void nativeClassInit(JNIEnv* env, jclass clazz);
743
744static JNINativeMethod gSurfaceSessionMethods[] = {
745    {"init",     "()V",  (void*)SurfaceSession_init },
746    {"destroy",  "()V",  (void*)SurfaceSession_destroy },
747    {"kill",     "()V",  (void*)SurfaceSession_kill },
748};
749
750static JNINativeMethod gSurfaceMethods[] = {
751    {"nativeClassInit",     "()V",  (void*)nativeClassInit },
752    {"init",                "(Landroid/view/SurfaceSession;ILjava/lang/String;IIIII)V",  (void*)Surface_init },
753    {"init",                "(Landroid/os/Parcel;)V",  (void*)Surface_initParcel },
754    {"getIdentity",         "()I",  (void*)Surface_getIdentity },
755    {"destroy",             "()V",  (void*)Surface_destroy },
756    {"release",             "()V",  (void*)Surface_release },
757    {"copyFrom",            "(Landroid/view/Surface;)V",  (void*)Surface_copyFrom },
758    {"isValid",             "()Z",  (void*)Surface_isValid },
759    {"lockCanvasNative",    "(Landroid/graphics/Rect;)Landroid/graphics/Canvas;",  (void*)Surface_lockCanvas },
760    {"unlockCanvasAndPost", "(Landroid/graphics/Canvas;)V", (void*)Surface_unlockCanvasAndPost },
761    {"unlockCanvas",        "(Landroid/graphics/Canvas;)V", (void*)Surface_unlockCanvas },
762    {"openTransaction",     "()V",  (void*)Surface_openTransaction },
763    {"closeTransaction",    "()V",  (void*)Surface_closeTransaction },
764    {"setOrientation",      "(III)V", (void*)Surface_setOrientation },
765    {"freezeDisplay",       "(I)V", (void*)Surface_freezeDisplay },
766    {"unfreezeDisplay",     "(I)V", (void*)Surface_unfreezeDisplay },
767    {"screenshot",          "(II)Landroid/graphics/Bitmap;", (void*)Surface_screenshotAll },
768    {"screenshot",          "(IIII)Landroid/graphics/Bitmap;", (void*)Surface_screenshot },
769    {"setLayer",            "(I)V", (void*)Surface_setLayer },
770    {"setPosition",         "(II)V",(void*)Surface_setPosition },
771    {"setSize",             "(II)V",(void*)Surface_setSize },
772    {"hide",                "()V",  (void*)Surface_hide },
773    {"show",                "()V",  (void*)Surface_show },
774    {"freeze",              "()V",  (void*)Surface_freeze },
775    {"unfreeze",            "()V",  (void*)Surface_unfreeze },
776    {"setFlags",            "(II)V",(void*)Surface_setFlags },
777    {"setTransparentRegionHint","(Landroid/graphics/Region;)V", (void*)Surface_setTransparentRegion },
778    {"setAlpha",            "(F)V", (void*)Surface_setAlpha },
779    {"setMatrix",           "(FFFF)V",  (void*)Surface_setMatrix },
780    {"setFreezeTint",       "(I)V",  (void*)Surface_setFreezeTint },
781    {"readFromParcel",      "(Landroid/os/Parcel;)V", (void*)Surface_readFromParcel },
782    {"writeToParcel",       "(Landroid/os/Parcel;I)V", (void*)Surface_writeToParcel },
783};
784
785void nativeClassInit(JNIEnv* env, jclass clazz)
786{
787    so.surface = env->GetFieldID(clazz, ANDROID_VIEW_SURFACE_JNI_ID, "I");
788    so.surfaceControl = env->GetFieldID(clazz, "mSurfaceControl", "I");
789    so.saveCount = env->GetFieldID(clazz, "mSaveCount", "I");
790    so.canvas    = env->GetFieldID(clazz, "mCanvas", "Landroid/graphics/Canvas;");
791
792    jclass surfaceSession = env->FindClass("android/view/SurfaceSession");
793    sso.client = env->GetFieldID(surfaceSession, "mClient", "I");
794
795    jclass canvas = env->FindClass("android/graphics/Canvas");
796    no.native_canvas = env->GetFieldID(canvas, "mNativeCanvas", "I");
797    co.surfaceFormat = env->GetFieldID(canvas, "mSurfaceFormat", "I");
798
799    jclass region = env->FindClass("android/graphics/Region");
800    no.native_region = env->GetFieldID(region, "mNativeRegion", "I");
801
802    jclass parcel = env->FindClass("android/os/Parcel");
803    no.native_parcel = env->GetFieldID(parcel, "mObject", "I");
804
805    jclass rect = env->FindClass("android/graphics/Rect");
806    ro.l = env->GetFieldID(rect, "left", "I");
807    ro.t = env->GetFieldID(rect, "top", "I");
808    ro.r = env->GetFieldID(rect, "right", "I");
809    ro.b = env->GetFieldID(rect, "bottom", "I");
810
811    jclass point = env->FindClass("android/graphics/Point");
812    po.x = env->GetFieldID(point, "x", "I");
813    po.y = env->GetFieldID(point, "y", "I");
814}
815
816int register_android_view_Surface(JNIEnv* env)
817{
818    int err;
819    err = AndroidRuntime::registerNativeMethods(env, kSurfaceSessionClassPathName,
820            gSurfaceSessionMethods, NELEM(gSurfaceSessionMethods));
821
822    err |= AndroidRuntime::registerNativeMethods(env, kSurfaceClassPathName,
823            gSurfaceMethods, NELEM(gSurfaceMethods));
824    return err;
825}
826
827};
828