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