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