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