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