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