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