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