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