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