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