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_os_Parcel.h"
22#include "android_util_Binder.h"
23#include "android/graphics/GraphicsJNI.h"
24#include "android/graphics/Region.h"
25
26#include <binder/IMemory.h>
27
28#include <gui/ISurfaceComposer.h>
29#include <gui/Surface.h>
30#include <gui/SurfaceComposerClient.h>
31#include <gui/SurfaceTexture.h>
32
33#include <ui/DisplayInfo.h>
34#include <ui/Rect.h>
35#include <ui/Region.h>
36
37#include <EGL/egl.h>
38
39#include <SkCanvas.h>
40#include <SkBitmap.h>
41#include <SkRegion.h>
42#include <SkPixelRef.h>
43
44#include "jni.h"
45#include "JNIHelp.h"
46#include <android_runtime/AndroidRuntime.h>
47#include <android_runtime/android_view_Surface.h>
48#include <android_runtime/android_view_SurfaceSession.h>
49#include <android_runtime/android_graphics_SurfaceTexture.h>
50#include <utils/misc.h>
51#include <utils/Log.h>
52
53#include <ScopedUtfChars.h>
54
55
56// ----------------------------------------------------------------------------
57
58namespace android {
59
60static const char* const OutOfResourcesException =
61    "android/view/Surface$OutOfResourcesException";
62
63static struct {
64    jclass clazz;
65    jfieldID mNativeSurface;
66    jfieldID mNativeSurfaceControl;
67    jfieldID mGenerationId;
68    jfieldID mCanvas;
69    jfieldID mCanvasSaveCount;
70    jmethodID ctor;
71} gSurfaceClassInfo;
72
73static struct {
74    jfieldID left;
75    jfieldID top;
76    jfieldID right;
77    jfieldID bottom;
78} gRectClassInfo;
79
80static struct {
81    jfieldID mNativeCanvas;
82    jfieldID mSurfaceFormat;
83} gCanvasClassInfo;
84
85static struct {
86    jfieldID width;
87    jfieldID height;
88    jfieldID refreshRate;
89    jfieldID density;
90    jfieldID xDpi;
91    jfieldID yDpi;
92    jfieldID secure;
93} gPhysicalDisplayInfoClassInfo;
94
95
96class ScreenshotPixelRef : public SkPixelRef {
97public:
98    ScreenshotPixelRef(SkColorTable* ctable) {
99        fCTable = ctable;
100        SkSafeRef(ctable);
101        setImmutable();
102    }
103
104    virtual ~ScreenshotPixelRef() {
105        SkSafeUnref(fCTable);
106    }
107
108    status_t update(const sp<IBinder>& display, int width, int height,
109            int minLayer, int maxLayer, bool allLayers) {
110        status_t res = (width > 0 && height > 0)
111                ? (allLayers
112                        ? mScreenshot.update(display, width, height)
113                        : mScreenshot.update(display, width, height, minLayer, maxLayer))
114                : mScreenshot.update(display);
115        if (res != NO_ERROR) {
116            return res;
117        }
118
119        return NO_ERROR;
120    }
121
122    uint32_t getWidth() const {
123        return mScreenshot.getWidth();
124    }
125
126    uint32_t getHeight() const {
127        return mScreenshot.getHeight();
128    }
129
130    uint32_t getStride() const {
131        return mScreenshot.getStride();
132    }
133
134    uint32_t getFormat() const {
135        return mScreenshot.getFormat();
136    }
137
138protected:
139    // overrides from SkPixelRef
140    virtual void* onLockPixels(SkColorTable** ct) {
141        *ct = fCTable;
142        return (void*)mScreenshot.getPixels();
143    }
144
145    virtual void onUnlockPixels() {
146    }
147
148private:
149    ScreenshotClient mScreenshot;
150    SkColorTable*    fCTable;
151
152    typedef SkPixelRef INHERITED;
153};
154
155
156// ----------------------------------------------------------------------------
157
158static sp<SurfaceControl> getSurfaceControl(JNIEnv* env, jobject surfaceObj) {
159    return reinterpret_cast<SurfaceControl*>(
160            env->GetIntField(surfaceObj, gSurfaceClassInfo.mNativeSurfaceControl));
161}
162
163static void setSurfaceControl(JNIEnv* env, jobject surfaceObj,
164        const sp<SurfaceControl>& surface) {
165    SurfaceControl* const p = reinterpret_cast<SurfaceControl*>(
166            env->GetIntField(surfaceObj, gSurfaceClassInfo.mNativeSurfaceControl));
167    if (surface.get()) {
168        surface->incStrong(surfaceObj);
169    }
170    if (p) {
171        p->decStrong(surfaceObj);
172    }
173    env->SetIntField(surfaceObj, gSurfaceClassInfo.mNativeSurfaceControl,
174            reinterpret_cast<jint>(surface.get()));
175}
176
177static sp<Surface> getSurface(JNIEnv* env, jobject surfaceObj) {
178    sp<Surface> result(android_view_Surface_getSurface(env, surfaceObj));
179    if (result == NULL) {
180        /*
181         * if this method is called from the WindowManager's process, it means
182         * the client is is not remote, and therefore is allowed to have
183         * a Surface (data), so we create it here.
184         * If we don't have a SurfaceControl, it means we're in a different
185         * process.
186         */
187
188        SurfaceControl* const control = reinterpret_cast<SurfaceControl*>(
189                env->GetIntField(surfaceObj, gSurfaceClassInfo.mNativeSurfaceControl));
190        if (control) {
191            result = control->getSurface();
192            if (result != NULL) {
193                result->incStrong(surfaceObj);
194                env->SetIntField(surfaceObj, gSurfaceClassInfo.mNativeSurface,
195                        reinterpret_cast<jint>(result.get()));
196            }
197        }
198    }
199    return result;
200}
201
202sp<ANativeWindow> android_view_Surface_getNativeWindow(JNIEnv* env, jobject surfaceObj) {
203    return getSurface(env, surfaceObj);
204}
205
206bool android_view_Surface_isInstanceOf(JNIEnv* env, jobject obj) {
207    return env->IsInstanceOf(obj, gSurfaceClassInfo.clazz);
208}
209
210sp<Surface> android_view_Surface_getSurface(JNIEnv* env, jobject surfaceObj) {
211    return reinterpret_cast<Surface*>(
212            env->GetIntField(surfaceObj, gSurfaceClassInfo.mNativeSurface));
213}
214
215static void setSurface(JNIEnv* env, jobject surfaceObj, const sp<Surface>& surface) {
216    Surface* const p = reinterpret_cast<Surface*>(
217            env->GetIntField(surfaceObj, gSurfaceClassInfo.mNativeSurface));
218    if (surface.get()) {
219        surface->incStrong(surfaceObj);
220    }
221    if (p) {
222        p->decStrong(surfaceObj);
223    }
224    env->SetIntField(surfaceObj, gSurfaceClassInfo.mNativeSurface,
225            reinterpret_cast<jint>(surface.get()));
226
227    // This test is conservative and it would be better to compare the ISurfaces
228    if (p && p != surface.get()) {
229        jint generationId = env->GetIntField(surfaceObj,
230                gSurfaceClassInfo.mGenerationId);
231        generationId++;
232        env->SetIntField(surfaceObj,
233                gSurfaceClassInfo.mGenerationId, generationId);
234    }
235}
236
237static sp<ISurfaceTexture> getISurfaceTexture(JNIEnv* env, jobject surfaceObj) {
238    if (surfaceObj) {
239        sp<Surface> surface(getSurface(env, surfaceObj));
240        if (surface != NULL) {
241            return surface->getSurfaceTexture();
242        }
243    }
244    return NULL;
245}
246
247jobject android_view_Surface_createFromISurfaceTexture(JNIEnv* env,
248        const sp<ISurfaceTexture>& surfaceTexture) {
249    if (surfaceTexture == NULL) {
250        return NULL;
251    }
252
253    sp<Surface> surface(new Surface(surfaceTexture));
254    if (surface == NULL) {
255        return NULL;
256    }
257
258    jobject surfaceObj = env->NewObject(gSurfaceClassInfo.clazz, gSurfaceClassInfo.ctor);
259    if (surfaceObj == NULL) {
260        if (env->ExceptionCheck()) {
261            ALOGE("Could not create instance of Surface from ISurfaceTexture.");
262            LOGE_EX(env);
263            env->ExceptionClear();
264        }
265        return NULL;
266    }
267
268    setSurface(env, surfaceObj, surface);
269    return surfaceObj;
270}
271
272
273// ----------------------------------------------------------------------------
274
275static void nativeCreate(JNIEnv* env, jobject surfaceObj, jobject sessionObj,
276        jstring nameStr, jint w, jint h, jint format, jint flags) {
277    ScopedUtfChars name(env, nameStr);
278    sp<SurfaceComposerClient> client(android_view_SurfaceSession_getClient(env, sessionObj));
279
280    sp<SurfaceControl> surface = client->createSurface(
281            String8(name.c_str()), w, h, format, flags);
282    if (surface == NULL) {
283        jniThrowException(env, OutOfResourcesException, NULL);
284        return;
285    }
286
287    setSurfaceControl(env, surfaceObj, surface);
288}
289
290static void nativeCreateFromSurfaceTexture(JNIEnv* env, jobject surfaceObj,
291        jobject surfaceTextureObj) {
292    sp<SurfaceTexture> st(SurfaceTexture_getSurfaceTexture(env, surfaceTextureObj));
293    if (st == NULL) {
294        jniThrowException(env, "java/lang/IllegalArgumentException",
295                "SurfaceTexture has already been released");
296        return;
297    }
298
299    sp<ISurfaceTexture> bq = st->getBufferQueue();
300
301    sp<Surface> surface(new Surface(bq));
302    if (surface == NULL) {
303        jniThrowException(env, OutOfResourcesException, NULL);
304        return;
305    }
306
307    setSurface(env, surfaceObj, surface);
308}
309
310static void nativeRelease(JNIEnv* env, jobject surfaceObj) {
311    setSurfaceControl(env, surfaceObj, NULL);
312    setSurface(env, surfaceObj, NULL);
313}
314
315static void nativeDestroy(JNIEnv* env, jobject surfaceObj) {
316    sp<SurfaceControl> surfaceControl(getSurfaceControl(env, surfaceObj));
317    if (SurfaceControl::isValid(surfaceControl)) {
318        surfaceControl->clear();
319    }
320    setSurfaceControl(env, surfaceObj, NULL);
321    setSurface(env, surfaceObj, NULL);
322}
323
324static jboolean nativeIsValid(JNIEnv* env, jobject surfaceObj) {
325    sp<SurfaceControl> surfaceControl(getSurfaceControl(env, surfaceObj));
326    if (surfaceControl != NULL) {
327        return SurfaceControl::isValid(surfaceControl) ? JNI_TRUE : JNI_FALSE;
328    }
329
330    sp<Surface> surface(getSurface(env, surfaceObj));
331    return Surface::isValid(surface) ? JNI_TRUE : JNI_FALSE;
332}
333
334static jint nativeGetIdentity(JNIEnv* env, jobject surfaceObj) {
335    sp<SurfaceControl> control(getSurfaceControl(env, surfaceObj));
336    if (control != NULL) {
337        return jint(control->getIdentity());
338    }
339
340    sp<Surface> surface(getSurface(env, surfaceObj));
341    if (surface != NULL) {
342        return jint(surface->getIdentity());
343    }
344
345    return -1;
346}
347
348static jboolean nativeIsConsumerRunningBehind(JNIEnv* env, jobject surfaceObj) {
349    sp<Surface> surface(getSurface(env, surfaceObj));
350    if (!Surface::isValid(surface)) {
351        doThrowIAE(env);
352        return JNI_FALSE;
353    }
354
355    int value = 0;
356    ANativeWindow* anw = static_cast<ANativeWindow*>(surface.get());
357    anw->query(anw, NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND, &value);
358    return value;
359}
360
361static inline SkBitmap::Config convertPixelFormat(PixelFormat format) {
362    /* note: if PIXEL_FORMAT_RGBX_8888 means that all alpha bytes are 0xFF, then
363        we can map to SkBitmap::kARGB_8888_Config, and optionally call
364        bitmap.setIsOpaque(true) on the resulting SkBitmap (as an accelerator)
365    */
366    switch (format) {
367    case PIXEL_FORMAT_RGBX_8888:    return SkBitmap::kARGB_8888_Config;
368    case PIXEL_FORMAT_RGBA_8888:    return SkBitmap::kARGB_8888_Config;
369    case PIXEL_FORMAT_RGBA_4444:    return SkBitmap::kARGB_4444_Config;
370    case PIXEL_FORMAT_RGB_565:      return SkBitmap::kRGB_565_Config;
371    case PIXEL_FORMAT_A_8:          return SkBitmap::kA8_Config;
372    default:                        return SkBitmap::kNo_Config;
373    }
374}
375
376static jobject nativeLockCanvas(JNIEnv* env, jobject surfaceObj, jobject dirtyRectObj) {
377    sp<Surface> surface(getSurface(env, surfaceObj));
378    if (!Surface::isValid(surface)) {
379        doThrowIAE(env);
380        return NULL;
381    }
382
383    // get dirty region
384    Region dirtyRegion;
385    if (dirtyRectObj) {
386        Rect dirty;
387        dirty.left = env->GetIntField(dirtyRectObj, gRectClassInfo.left);
388        dirty.top = env->GetIntField(dirtyRectObj, gRectClassInfo.top);
389        dirty.right = env->GetIntField(dirtyRectObj, gRectClassInfo.right);
390        dirty.bottom = env->GetIntField(dirtyRectObj, gRectClassInfo.bottom);
391        if (!dirty.isEmpty()) {
392            dirtyRegion.set(dirty);
393        }
394    } else {
395        dirtyRegion.set(Rect(0x3FFF, 0x3FFF));
396    }
397
398    Surface::SurfaceInfo info;
399    status_t err = surface->lock(&info, &dirtyRegion);
400    if (err < 0) {
401        const char* const exception = (err == NO_MEMORY) ?
402                OutOfResourcesException :
403                "java/lang/IllegalArgumentException";
404        jniThrowException(env, exception, NULL);
405        return NULL;
406    }
407
408    // Associate a SkCanvas object to this surface
409    jobject canvasObj = env->GetObjectField(surfaceObj, gSurfaceClassInfo.mCanvas);
410    env->SetIntField(canvasObj, gCanvasClassInfo.mSurfaceFormat, info.format);
411
412    SkCanvas* nativeCanvas = reinterpret_cast<SkCanvas*>(
413            env->GetIntField(canvasObj, gCanvasClassInfo.mNativeCanvas));
414    SkBitmap bitmap;
415    ssize_t bpr = info.s * bytesPerPixel(info.format);
416    bitmap.setConfig(convertPixelFormat(info.format), info.w, info.h, bpr);
417    if (info.format == PIXEL_FORMAT_RGBX_8888) {
418        bitmap.setIsOpaque(true);
419    }
420    if (info.w > 0 && info.h > 0) {
421        bitmap.setPixels(info.bits);
422    } else {
423        // be safe with an empty bitmap.
424        bitmap.setPixels(NULL);
425    }
426    nativeCanvas->setBitmapDevice(bitmap);
427
428    SkRegion clipReg;
429    if (dirtyRegion.isRect()) { // very common case
430        const Rect b(dirtyRegion.getBounds());
431        clipReg.setRect(b.left, b.top, b.right, b.bottom);
432    } else {
433        size_t count;
434        Rect const* r = dirtyRegion.getArray(&count);
435        while (count) {
436            clipReg.op(r->left, r->top, r->right, r->bottom, SkRegion::kUnion_Op);
437            r++, count--;
438        }
439    }
440
441    nativeCanvas->clipRegion(clipReg);
442
443    int saveCount = nativeCanvas->save();
444    env->SetIntField(surfaceObj, gSurfaceClassInfo.mCanvasSaveCount, saveCount);
445
446    if (dirtyRectObj) {
447        const Rect& bounds(dirtyRegion.getBounds());
448        env->SetIntField(dirtyRectObj, gRectClassInfo.left, bounds.left);
449        env->SetIntField(dirtyRectObj, gRectClassInfo.top, bounds.top);
450        env->SetIntField(dirtyRectObj, gRectClassInfo.right, bounds.right);
451        env->SetIntField(dirtyRectObj, gRectClassInfo.bottom, bounds.bottom);
452    }
453
454    return canvasObj;
455}
456
457static void nativeUnlockCanvasAndPost(JNIEnv* env, jobject surfaceObj, jobject canvasObj) {
458    jobject ownCanvasObj = env->GetObjectField(surfaceObj, gSurfaceClassInfo.mCanvas);
459    if (!env->IsSameObject(ownCanvasObj, canvasObj)) {
460        doThrowIAE(env);
461        return;
462    }
463
464    sp<Surface> surface(getSurface(env, surfaceObj));
465    if (!Surface::isValid(surface)) {
466        return;
467    }
468
469    // detach the canvas from the surface
470    SkCanvas* nativeCanvas = reinterpret_cast<SkCanvas*>(
471            env->GetIntField(canvasObj, gCanvasClassInfo.mNativeCanvas));
472    int saveCount = env->GetIntField(surfaceObj, gSurfaceClassInfo.mCanvasSaveCount);
473    nativeCanvas->restoreToCount(saveCount);
474    nativeCanvas->setBitmapDevice(SkBitmap());
475    env->SetIntField(surfaceObj, gSurfaceClassInfo.mCanvasSaveCount, 0);
476
477    // unlock surface
478    status_t err = surface->unlockAndPost();
479    if (err < 0) {
480        doThrowIAE(env);
481    }
482}
483
484static jobject nativeScreenshot(JNIEnv* env, jclass clazz, jobject displayTokenObj,
485        jint width, jint height, jint minLayer, jint maxLayer, bool allLayers) {
486    sp<IBinder> displayToken = ibinderForJavaObject(env, displayTokenObj);
487    if (displayToken == NULL) {
488        return NULL;
489    }
490
491    ScreenshotPixelRef* pixels = new ScreenshotPixelRef(NULL);
492    if (pixels->update(displayToken, width, height,
493            minLayer, maxLayer, allLayers) != NO_ERROR) {
494        delete pixels;
495        return NULL;
496    }
497
498    uint32_t w = pixels->getWidth();
499    uint32_t h = pixels->getHeight();
500    uint32_t s = pixels->getStride();
501    uint32_t f = pixels->getFormat();
502    ssize_t bpr = s * android::bytesPerPixel(f);
503
504    SkBitmap* bitmap = new SkBitmap();
505    bitmap->setConfig(convertPixelFormat(f), w, h, bpr);
506    if (f == PIXEL_FORMAT_RGBX_8888) {
507        bitmap->setIsOpaque(true);
508    }
509
510    if (w > 0 && h > 0) {
511        bitmap->setPixelRef(pixels)->unref();
512        bitmap->lockPixels();
513    } else {
514        // be safe with an empty bitmap.
515        delete pixels;
516        bitmap->setPixels(NULL);
517    }
518
519    return GraphicsJNI::createBitmap(env, bitmap, false, NULL);
520}
521
522static void nativeOpenTransaction(JNIEnv* env, jclass clazz) {
523    SurfaceComposerClient::openGlobalTransaction();
524}
525
526static void nativeCloseTransaction(JNIEnv* env, jclass clazz) {
527    SurfaceComposerClient::closeGlobalTransaction();
528}
529
530static void nativeSetAnimationTransaction(JNIEnv* env, jclass clazz) {
531    SurfaceComposerClient::setAnimationTransaction();
532}
533
534static void nativeSetLayer(JNIEnv* env, jobject surfaceObj, jint zorder) {
535    sp<SurfaceControl> surface(getSurfaceControl(env, surfaceObj));
536    if (surface == NULL) return;
537
538    status_t err = surface->setLayer(zorder);
539    if (err < 0 && err != NO_INIT) {
540        doThrowIAE(env);
541    }
542}
543
544static void nativeSetPosition(JNIEnv* env, jobject surfaceObj, jfloat x, jfloat y) {
545    sp<SurfaceControl> surface(getSurfaceControl(env, surfaceObj));
546    if (surface == NULL) return;
547
548    status_t err = surface->setPosition(x, y);
549    if (err < 0 && err != NO_INIT) {
550        doThrowIAE(env);
551    }
552}
553
554static void nativeSetSize(JNIEnv* env, jobject surfaceObj, jint w, jint h) {
555    sp<SurfaceControl> surface(getSurfaceControl(env, surfaceObj));
556    if (surface == NULL) return;
557
558    status_t err = surface->setSize(w, h);
559    if (err < 0 && err != NO_INIT) {
560        doThrowIAE(env);
561    }
562}
563
564static void nativeSetFlags(JNIEnv* env, jobject surfaceObj, jint flags, jint mask) {
565    sp<SurfaceControl> surface(getSurfaceControl(env, surfaceObj));
566    if (surface == NULL) return;
567
568    status_t err = surface->setFlags(flags, mask);
569    if (err < 0 && err != NO_INIT) {
570        doThrowIAE(env);
571    }
572}
573
574static void nativeSetTransparentRegionHint(JNIEnv* env, jobject surfaceObj, jobject regionObj) {
575    sp<SurfaceControl> surface(getSurfaceControl(env, surfaceObj));
576    if (surface == NULL) return;
577
578    SkRegion* region = android_graphics_Region_getSkRegion(env, regionObj);
579    if (!region) {
580        doThrowIAE(env);
581        return;
582    }
583
584    const SkIRect& b(region->getBounds());
585    Region reg(Rect(b.fLeft, b.fTop, b.fRight, b.fBottom));
586    if (region->isComplex()) {
587        SkRegion::Iterator it(*region);
588        while (!it.done()) {
589            const SkIRect& r(it.rect());
590            reg.addRectUnchecked(r.fLeft, r.fTop, r.fRight, r.fBottom);
591            it.next();
592        }
593    }
594
595    status_t err = surface->setTransparentRegionHint(reg);
596    if (err < 0 && err != NO_INIT) {
597        doThrowIAE(env);
598    }
599}
600
601static void nativeSetAlpha(JNIEnv* env, jobject surfaceObj, jfloat alpha) {
602    sp<SurfaceControl> surface(getSurfaceControl(env, surfaceObj));
603    if (surface == NULL) return;
604
605    status_t err = surface->setAlpha(alpha);
606    if (err < 0 && err != NO_INIT) {
607        doThrowIAE(env);
608    }
609}
610
611static void nativeSetMatrix(JNIEnv* env, jobject surfaceObj,
612        jfloat dsdx, jfloat dtdx, jfloat dsdy, jfloat dtdy) {
613    sp<SurfaceControl> surface(getSurfaceControl(env, surfaceObj));
614    if (surface == NULL) return;
615
616    status_t err = surface->setMatrix(dsdx, dtdx, dsdy, dtdy);
617    if (err < 0 && err != NO_INIT) {
618        doThrowIAE(env);
619    }
620}
621
622static void nativeSetWindowCrop(JNIEnv* env, jobject surfaceObj, jobject cropObj) {
623    const sp<SurfaceControl>& surface(getSurfaceControl(env, surfaceObj));
624    if (surface == NULL) return;
625
626    Rect crop;
627    if (cropObj) {
628        crop.left = env->GetIntField(cropObj, gRectClassInfo.left);
629        crop.top = env->GetIntField(cropObj, gRectClassInfo.top);
630        crop.right = env->GetIntField(cropObj, gRectClassInfo.right);
631        crop.bottom = env->GetIntField(cropObj, gRectClassInfo.bottom);
632    } else {
633        crop.left = crop.top = crop.right = crop.bottom = 0;
634    }
635
636    status_t err = surface->setCrop(crop);
637    if (err < 0 && err != NO_INIT) {
638        doThrowIAE(env);
639    }
640}
641
642static void nativeSetLayerStack(JNIEnv* env, jobject surfaceObj, jint layerStack) {
643    sp<SurfaceControl> surface(getSurfaceControl(env, surfaceObj));
644    if (surface == NULL) return;
645
646    status_t err = surface->setLayerStack(layerStack);
647    if (err < 0 && err != NO_INIT) {
648        doThrowIAE(env);
649    }
650}
651
652static jobject nativeGetBuiltInDisplay(JNIEnv* env, jclass clazz, jint id) {
653    sp<IBinder> token(SurfaceComposerClient::getBuiltInDisplay(id));
654    return javaObjectForIBinder(env, token);
655}
656
657static jobject nativeCreateDisplay(JNIEnv* env, jclass clazz, jstring nameObj,
658        jboolean secure) {
659    ScopedUtfChars name(env, nameObj);
660    sp<IBinder> token(SurfaceComposerClient::createDisplay(
661            String8(name.c_str()), bool(secure)));
662    return javaObjectForIBinder(env, token);
663}
664
665static void nativeSetDisplaySurface(JNIEnv* env, jclass clazz,
666        jobject tokenObj, jobject surfaceObj) {
667    sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
668    if (token == NULL) return;
669
670    sp<ISurfaceTexture> surfaceTexture(getISurfaceTexture(env, surfaceObj));
671    SurfaceComposerClient::setDisplaySurface(token, surfaceTexture);
672}
673
674static void nativeSetDisplayLayerStack(JNIEnv* env, jclass clazz,
675        jobject tokenObj, jint layerStack) {
676    sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
677    if (token == NULL) return;
678
679    SurfaceComposerClient::setDisplayLayerStack(token, layerStack);
680}
681
682static void nativeSetDisplayProjection(JNIEnv* env, jclass clazz,
683        jobject tokenObj, jint orientation, jobject layerStackRectObj, jobject displayRectObj) {
684    sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
685    if (token == NULL) return;
686
687    Rect layerStackRect;
688    layerStackRect.left = env->GetIntField(layerStackRectObj, gRectClassInfo.left);
689    layerStackRect.top = env->GetIntField(layerStackRectObj, gRectClassInfo.top);
690    layerStackRect.right = env->GetIntField(layerStackRectObj, gRectClassInfo.right);
691    layerStackRect.bottom = env->GetIntField(layerStackRectObj, gRectClassInfo.bottom);
692
693    Rect displayRect;
694    displayRect.left = env->GetIntField(displayRectObj, gRectClassInfo.left);
695    displayRect.top = env->GetIntField(displayRectObj, gRectClassInfo.top);
696    displayRect.right = env->GetIntField(displayRectObj, gRectClassInfo.right);
697    displayRect.bottom = env->GetIntField(displayRectObj, gRectClassInfo.bottom);
698
699    SurfaceComposerClient::setDisplayProjection(token, orientation, layerStackRect, displayRect);
700}
701
702static jboolean nativeGetDisplayInfo(JNIEnv* env, jclass clazz,
703        jobject tokenObj, jobject infoObj) {
704    sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
705    if (token == NULL) return JNI_FALSE;
706
707    DisplayInfo info;
708    if (SurfaceComposerClient::getDisplayInfo(token, &info)) {
709        return JNI_FALSE;
710    }
711
712    env->SetIntField(infoObj, gPhysicalDisplayInfoClassInfo.width, info.w);
713    env->SetIntField(infoObj, gPhysicalDisplayInfoClassInfo.height, info.h);
714    env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.refreshRate, info.fps);
715    env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.density, info.density);
716    env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.xDpi, info.xdpi);
717    env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.yDpi, info.ydpi);
718    env->SetBooleanField(infoObj, gPhysicalDisplayInfoClassInfo.secure, info.secure);
719    return JNI_TRUE;
720}
721
722static void nativeBlankDisplay(JNIEnv* env, jclass clazz, jobject tokenObj) {
723    sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
724    if (token == NULL) return;
725
726    ALOGD_IF_SLOW(100, "Excessive delay in blankDisplay() while turning screen off");
727    SurfaceComposerClient::blankDisplay(token);
728}
729
730static void nativeUnblankDisplay(JNIEnv* env, jclass clazz, jobject tokenObj) {
731    sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
732    if (token == NULL) return;
733
734    ALOGD_IF_SLOW(100, "Excessive delay in unblankDisplay() while turning screen on");
735    SurfaceComposerClient::unblankDisplay(token);
736}
737
738// ----------------------------------------------------------------------------
739
740static void nativeCopyFrom(JNIEnv* env, jobject surfaceObj, jobject otherObj) {
741    /*
742     * This is used by the WindowManagerService just after constructing
743     * a Surface and is necessary for returning the Surface reference to
744     * the caller. At this point, we should only have a SurfaceControl.
745     */
746
747    sp<SurfaceControl> surface(getSurfaceControl(env, surfaceObj));
748    sp<SurfaceControl> other(getSurfaceControl(env, otherObj));
749    if (!SurfaceControl::isSameSurface(surface, other)) {
750        // we reassign the surface only if it's a different one
751        // otherwise we would loose our client-side state.
752        setSurfaceControl(env, surfaceObj, other);
753    }
754}
755
756static void nativeTransferFrom(JNIEnv* env, jobject surfaceObj, jobject otherObj) {
757    sp<SurfaceControl> control(getSurfaceControl(env, otherObj));
758    sp<Surface> surface(android_view_Surface_getSurface(env, otherObj));
759    setSurfaceControl(env, surfaceObj, control);
760    setSurface(env, surfaceObj, surface);
761    setSurfaceControl(env, otherObj, NULL);
762    setSurface(env, otherObj, NULL);
763}
764
765static void nativeReadFromParcel(JNIEnv* env, jobject surfaceObj, jobject parcelObj) {
766    Parcel* parcel = parcelForJavaObject(env, parcelObj);
767    if (parcel == NULL) {
768        doThrowNPE(env);
769        return;
770    }
771
772    sp<Surface> surface(Surface::readFromParcel(*parcel));
773    setSurfaceControl(env, surfaceObj, NULL);
774    setSurface(env, surfaceObj, surface);
775}
776
777static void nativeWriteToParcel(JNIEnv* env, jobject surfaceObj, jobject parcelObj) {
778    Parcel* parcel = parcelForJavaObject(env, parcelObj);
779    if (parcel == NULL) {
780        doThrowNPE(env);
781        return;
782    }
783
784    // The Java instance may have a SurfaceControl (in the case of the
785    // WindowManager or a system app). In that case, we defer to the
786    // SurfaceControl to send its ISurface. Otherwise, if the Surface is
787    // available we let it parcel itself. Finally, if the Surface is also
788    // NULL we fall back to using the SurfaceControl path which sends an
789    // empty surface; this matches legacy behavior.
790    sp<SurfaceControl> control(getSurfaceControl(env, surfaceObj));
791    if (control != NULL) {
792        SurfaceControl::writeSurfaceToParcel(control, parcel);
793    } else {
794        sp<Surface> surface(android_view_Surface_getSurface(env, surfaceObj));
795        if (surface != NULL) {
796            Surface::writeToParcel(surface, parcel);
797        } else {
798            SurfaceControl::writeSurfaceToParcel(NULL, parcel);
799        }
800    }
801}
802
803// ----------------------------------------------------------------------------
804
805static JNINativeMethod gSurfaceMethods[] = {
806    {"nativeCreate", "(Landroid/view/SurfaceSession;Ljava/lang/String;IIII)V",
807            (void*)nativeCreate },
808    {"nativeCreateFromSurfaceTexture", "(Landroid/graphics/SurfaceTexture;)V",
809            (void*)nativeCreateFromSurfaceTexture },
810    {"nativeRelease", "()V",
811            (void*)nativeRelease },
812    {"nativeDestroy", "()V",
813            (void*)nativeDestroy },
814    {"nativeIsValid", "()Z",
815            (void*)nativeIsValid },
816    {"nativeGetIdentity", "()I",
817            (void*)nativeGetIdentity },
818    {"nativeIsConsumerRunningBehind", "()Z",
819            (void*)nativeIsConsumerRunningBehind },
820    {"nativeLockCanvas", "(Landroid/graphics/Rect;)Landroid/graphics/Canvas;",
821            (void*)nativeLockCanvas },
822    {"nativeUnlockCanvasAndPost", "(Landroid/graphics/Canvas;)V",
823            (void*)nativeUnlockCanvasAndPost },
824    {"nativeScreenshot", "(Landroid/os/IBinder;IIIIZ)Landroid/graphics/Bitmap;",
825            (void*)nativeScreenshot },
826    {"nativeOpenTransaction", "()V",
827            (void*)nativeOpenTransaction },
828    {"nativeCloseTransaction", "()V",
829            (void*)nativeCloseTransaction },
830    {"nativeSetAnimationTransaction", "()V",
831            (void*)nativeSetAnimationTransaction },
832    {"nativeSetLayer", "(I)V",
833            (void*)nativeSetLayer },
834    {"nativeSetPosition", "(FF)V",
835            (void*)nativeSetPosition },
836    {"nativeSetSize", "(II)V",
837            (void*)nativeSetSize },
838    {"nativeSetTransparentRegionHint", "(Landroid/graphics/Region;)V",
839            (void*)nativeSetTransparentRegionHint },
840    {"nativeSetAlpha", "(F)V",
841            (void*)nativeSetAlpha },
842    {"nativeSetMatrix", "(FFFF)V",
843            (void*)nativeSetMatrix },
844    {"nativeSetFlags", "(II)V",
845            (void*)nativeSetFlags },
846    {"nativeSetWindowCrop", "(Landroid/graphics/Rect;)V",
847            (void*)nativeSetWindowCrop },
848    {"nativeSetLayerStack", "(I)V",
849            (void*)nativeSetLayerStack },
850    {"nativeGetBuiltInDisplay", "(I)Landroid/os/IBinder;",
851            (void*)nativeGetBuiltInDisplay },
852    {"nativeCreateDisplay", "(Ljava/lang/String;Z)Landroid/os/IBinder;",
853            (void*)nativeCreateDisplay },
854    {"nativeSetDisplaySurface", "(Landroid/os/IBinder;Landroid/view/Surface;)V",
855            (void*)nativeSetDisplaySurface },
856    {"nativeSetDisplayLayerStack", "(Landroid/os/IBinder;I)V",
857            (void*)nativeSetDisplayLayerStack },
858    {"nativeSetDisplayProjection", "(Landroid/os/IBinder;ILandroid/graphics/Rect;Landroid/graphics/Rect;)V",
859            (void*)nativeSetDisplayProjection },
860    {"nativeGetDisplayInfo", "(Landroid/os/IBinder;Landroid/view/Surface$PhysicalDisplayInfo;)Z",
861            (void*)nativeGetDisplayInfo },
862    {"nativeBlankDisplay", "(Landroid/os/IBinder;)V",
863            (void*)nativeBlankDisplay },
864    {"nativeUnblankDisplay", "(Landroid/os/IBinder;)V",
865            (void*)nativeUnblankDisplay },
866    {"nativeCopyFrom", "(Landroid/view/Surface;)V",
867            (void*)nativeCopyFrom },
868    {"nativeTransferFrom", "(Landroid/view/Surface;)V",
869            (void*)nativeTransferFrom },
870    {"nativeReadFromParcel", "(Landroid/os/Parcel;)V",
871            (void*)nativeReadFromParcel },
872    {"nativeWriteToParcel", "(Landroid/os/Parcel;)V",
873            (void*)nativeWriteToParcel },
874};
875
876int register_android_view_Surface(JNIEnv* env)
877{
878    int err = AndroidRuntime::registerNativeMethods(env, "android/view/Surface",
879            gSurfaceMethods, NELEM(gSurfaceMethods));
880
881    jclass clazz = env->FindClass("android/view/Surface");
882    gSurfaceClassInfo.clazz = jclass(env->NewGlobalRef(clazz));
883    gSurfaceClassInfo.mNativeSurface =
884            env->GetFieldID(gSurfaceClassInfo.clazz, ANDROID_VIEW_SURFACE_JNI_ID, "I");
885    gSurfaceClassInfo.mNativeSurfaceControl =
886            env->GetFieldID(gSurfaceClassInfo.clazz, "mNativeSurfaceControl", "I");
887    gSurfaceClassInfo.mGenerationId =
888            env->GetFieldID(gSurfaceClassInfo.clazz, "mGenerationId", "I");
889    gSurfaceClassInfo.mCanvas =
890            env->GetFieldID(gSurfaceClassInfo.clazz, "mCanvas", "Landroid/graphics/Canvas;");
891    gSurfaceClassInfo.mCanvasSaveCount =
892            env->GetFieldID(gSurfaceClassInfo.clazz, "mCanvasSaveCount", "I");
893    gSurfaceClassInfo.ctor = env->GetMethodID(gSurfaceClassInfo.clazz, "<init>", "()V");
894
895    clazz = env->FindClass("android/graphics/Canvas");
896    gCanvasClassInfo.mNativeCanvas = env->GetFieldID(clazz, "mNativeCanvas", "I");
897    gCanvasClassInfo.mSurfaceFormat = env->GetFieldID(clazz, "mSurfaceFormat", "I");
898
899    clazz = env->FindClass("android/graphics/Rect");
900    gRectClassInfo.left = env->GetFieldID(clazz, "left", "I");
901    gRectClassInfo.top = env->GetFieldID(clazz, "top", "I");
902    gRectClassInfo.right = env->GetFieldID(clazz, "right", "I");
903    gRectClassInfo.bottom = env->GetFieldID(clazz, "bottom", "I");
904
905    clazz = env->FindClass("android/view/Surface$PhysicalDisplayInfo");
906    gPhysicalDisplayInfoClassInfo.width = env->GetFieldID(clazz, "width", "I");
907    gPhysicalDisplayInfoClassInfo.height = env->GetFieldID(clazz, "height", "I");
908    gPhysicalDisplayInfoClassInfo.refreshRate = env->GetFieldID(clazz, "refreshRate", "F");
909    gPhysicalDisplayInfoClassInfo.density = env->GetFieldID(clazz, "density", "F");
910    gPhysicalDisplayInfoClassInfo.xDpi = env->GetFieldID(clazz, "xDpi", "F");
911    gPhysicalDisplayInfoClassInfo.yDpi = env->GetFieldID(clazz, "yDpi", "F");
912    gPhysicalDisplayInfoClassInfo.secure = env->GetFieldID(clazz, "secure", "Z");
913    return err;
914}
915
916};
917