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