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