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