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