diff options
Diffstat (limited to 'core/jni')
-rw-r--r-- | core/jni/Android.mk | 1 | ||||
-rw-r--r-- | core/jni/AndroidRuntime.cpp | 4 | ||||
-rw-r--r-- | core/jni/android_hardware_Camera.cpp | 9 | ||||
-rw-r--r-- | core/jni/android_view_Surface.cpp | 661 | ||||
-rw-r--r-- | core/jni/android_view_SurfaceControl.cpp | 451 |
5 files changed, 534 insertions, 592 deletions
diff --git a/core/jni/Android.mk b/core/jni/Android.mk index d705024..f47865e 100644 --- a/core/jni/Android.mk +++ b/core/jni/Android.mk @@ -42,6 +42,7 @@ LOCAL_SRC_FILES:= \ android_emoji_EmojiFactory.cpp \ android_view_DisplayEventReceiver.cpp \ android_view_Surface.cpp \ + android_view_SurfaceControl.cpp \ android_view_SurfaceSession.cpp \ android_view_TextureView.cpp \ android_view_InputChannel.cpp \ diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index 94324f8..74fd391 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -47,8 +47,6 @@ using namespace android; -extern void register_BindTest(); - extern int register_android_os_Binder(JNIEnv* env); extern int register_android_os_Process(JNIEnv* env); extern int register_android_graphics_Bitmap(JNIEnv*); @@ -121,6 +119,7 @@ extern int register_android_view_GLES20DisplayList(JNIEnv* env); extern int register_android_view_GLES20Canvas(JNIEnv* env); extern int register_android_view_HardwareRenderer(JNIEnv* env); extern int register_android_view_Surface(JNIEnv* env); +extern int register_android_view_SurfaceControl(JNIEnv* env); extern int register_android_view_SurfaceSession(JNIEnv* env); extern int register_android_view_TextureView(JNIEnv* env); extern int register_android_database_CursorWindow(JNIEnv* env); @@ -1112,6 +1111,7 @@ static const RegJNIRec gRegJNI[] = { REG_JNI(register_android_view_GLES20Canvas), REG_JNI(register_android_view_HardwareRenderer), REG_JNI(register_android_view_Surface), + REG_JNI(register_android_view_SurfaceControl), REG_JNI(register_android_view_SurfaceSession), REG_JNI(register_android_view_TextureView), REG_JNI(register_com_google_android_gles_jni_EGLImpl), diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp index 0e0893b..7c65662 100644 --- a/core/jni/android_hardware_Camera.cpp +++ b/core/jni/android_hardware_Camera.cpp @@ -23,6 +23,7 @@ #include "JNIHelp.h" #include "android_runtime/AndroidRuntime.h" #include <android_runtime/android_graphics_SurfaceTexture.h> +#include <android_runtime/android_view_Surface.h> #include <cutils/properties.h> #include <utils/Vector.h> @@ -36,7 +37,6 @@ using namespace android; struct fields_t { jfieldID context; - jfieldID surface; jfieldID facing; jfieldID orientation; jfieldID canDisableShutterSound; @@ -537,10 +537,8 @@ static void android_hardware_Camera_setPreviewDisplay(JNIEnv *env, jobject thiz, sp<Camera> camera = get_native_camera(env, thiz, NULL); if (camera == 0) return; - sp<Surface> surface = NULL; - if (jSurface != NULL) { - surface = reinterpret_cast<Surface*>(env->GetIntField(jSurface, fields.surface)); - } + sp<Surface> surface = android_view_Surface_getSurface(env, jSurface); + if (camera->setPreviewDisplay(surface) != NO_ERROR) { jniThrowException(env, "java/io/IOException", "setPreviewDisplay failed"); } @@ -965,7 +963,6 @@ int register_android_hardware_Camera(JNIEnv *env) { field fields_to_find[] = { { "android/hardware/Camera", "mNativeContext", "I", &fields.context }, - { "android/view/Surface", ANDROID_VIEW_SURFACE_JNI_ID, "I", &fields.surface }, { "android/hardware/Camera$CameraInfo", "facing", "I", &fields.facing }, { "android/hardware/Camera$CameraInfo", "orientation", "I", &fields.orientation }, { "android/hardware/Camera$CameraInfo", "canDisableShutterSound", "Z", diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp index 40b505c..6f71868 100644 --- a/core/jni/android_view_Surface.cpp +++ b/core/jni/android_view_Surface.cpp @@ -18,41 +18,30 @@ #include <stdio.h> +#include "jni.h" +#include "JNIHelp.h" #include "android_os_Parcel.h" -#include "android_util_Binder.h" #include "android/graphics/GraphicsJNI.h" -#include "android/graphics/Region.h" -#include <binder/IMemory.h> +#include <android_runtime/AndroidRuntime.h> +#include <android_runtime/android_view_Surface.h> +#include <android_runtime/android_graphics_SurfaceTexture.h> -#include <gui/ISurfaceComposer.h> #include <gui/Surface.h> -#include <gui/SurfaceComposerClient.h> #include <gui/GLConsumer.h> -#include <ui/DisplayInfo.h> #include <ui/Rect.h> #include <ui/Region.h> -#include <EGL/egl.h> - #include <SkCanvas.h> #include <SkBitmap.h> #include <SkRegion.h> -#include <SkPixelRef.h> -#include "jni.h" -#include "JNIHelp.h" -#include <android_runtime/AndroidRuntime.h> -#include <android_runtime/android_view_Surface.h> -#include <android_runtime/android_view_SurfaceSession.h> -#include <android_runtime/android_graphics_SurfaceTexture.h> #include <utils/misc.h> #include <utils/Log.h> #include <ScopedUtfChars.h> - // ---------------------------------------------------------------------------- namespace android { @@ -62,8 +51,7 @@ static const char* const OutOfResourcesException = static struct { jclass clazz; - jfieldID mNativeSurface; - jfieldID mNativeSurfaceControl; + jfieldID mNativeObject; jfieldID mGenerationId; jfieldID mCanvas; jfieldID mCanvasSaveCount; @@ -82,166 +70,19 @@ static struct { jfieldID mSurfaceFormat; } gCanvasClassInfo; -static struct { - jfieldID width; - jfieldID height; - jfieldID refreshRate; - jfieldID density; - jfieldID xDpi; - jfieldID yDpi; - jfieldID secure; -} gPhysicalDisplayInfoClassInfo; - - -class ScreenshotPixelRef : public SkPixelRef { -public: - ScreenshotPixelRef(SkColorTable* ctable) { - fCTable = ctable; - SkSafeRef(ctable); - setImmutable(); - } - - virtual ~ScreenshotPixelRef() { - SkSafeUnref(fCTable); - } - - status_t update(const sp<IBinder>& display, int width, int height, - int minLayer, int maxLayer, bool allLayers) { - status_t res = (width > 0 && height > 0) - ? (allLayers - ? mScreenshot.update(display, width, height) - : mScreenshot.update(display, width, height, minLayer, maxLayer)) - : mScreenshot.update(display); - if (res != NO_ERROR) { - return res; - } - - return NO_ERROR; - } - - uint32_t getWidth() const { - return mScreenshot.getWidth(); - } - - uint32_t getHeight() const { - return mScreenshot.getHeight(); - } - - uint32_t getStride() const { - return mScreenshot.getStride(); - } - - uint32_t getFormat() const { - return mScreenshot.getFormat(); - } - -protected: - // overrides from SkPixelRef - virtual void* onLockPixels(SkColorTable** ct) { - *ct = fCTable; - return (void*)mScreenshot.getPixels(); - } - - virtual void onUnlockPixels() { - } - -private: - ScreenshotClient mScreenshot; - SkColorTable* fCTable; - - typedef SkPixelRef INHERITED; -}; - - // ---------------------------------------------------------------------------- -static sp<SurfaceControl> getSurfaceControl(JNIEnv* env, jobject surfaceObj) { - return reinterpret_cast<SurfaceControl*>( - env->GetIntField(surfaceObj, gSurfaceClassInfo.mNativeSurfaceControl)); -} - -static void setSurfaceControl(JNIEnv* env, jobject surfaceObj, - const sp<SurfaceControl>& surface) { - SurfaceControl* const p = reinterpret_cast<SurfaceControl*>( - env->GetIntField(surfaceObj, gSurfaceClassInfo.mNativeSurfaceControl)); - if (surface.get()) { - surface->incStrong(surfaceObj); - } - if (p) { - p->decStrong(surfaceObj); - } - env->SetIntField(surfaceObj, gSurfaceClassInfo.mNativeSurfaceControl, - reinterpret_cast<jint>(surface.get())); -} - -static sp<Surface> getSurface(JNIEnv* env, jobject surfaceObj) { - sp<Surface> result(android_view_Surface_getSurface(env, surfaceObj)); - if (result == NULL) { - /* - * if this method is called from the WindowManager's process, it means - * the client is is not remote, and therefore is allowed to have - * a Surface (data), so we create it here. - * If we don't have a SurfaceControl, it means we're in a different - * process. - */ - - SurfaceControl* const control = reinterpret_cast<SurfaceControl*>( - env->GetIntField(surfaceObj, gSurfaceClassInfo.mNativeSurfaceControl)); - if (control) { - result = control->getSurface(); - if (result != NULL) { - result->incStrong(surfaceObj); - env->SetIntField(surfaceObj, gSurfaceClassInfo.mNativeSurface, - reinterpret_cast<jint>(result.get())); - } - } - } - return result; -} - -sp<ANativeWindow> android_view_Surface_getNativeWindow(JNIEnv* env, jobject surfaceObj) { - return getSurface(env, surfaceObj); -} - bool android_view_Surface_isInstanceOf(JNIEnv* env, jobject obj) { return env->IsInstanceOf(obj, gSurfaceClassInfo.clazz); } -sp<Surface> android_view_Surface_getSurface(JNIEnv* env, jobject surfaceObj) { - return reinterpret_cast<Surface*>( - env->GetIntField(surfaceObj, gSurfaceClassInfo.mNativeSurface)); -} - -static void setSurface(JNIEnv* env, jobject surfaceObj, const sp<Surface>& surface) { - Surface* const p = reinterpret_cast<Surface*>( - env->GetIntField(surfaceObj, gSurfaceClassInfo.mNativeSurface)); - if (surface.get()) { - surface->incStrong(surfaceObj); - } - if (p) { - p->decStrong(surfaceObj); - } - env->SetIntField(surfaceObj, gSurfaceClassInfo.mNativeSurface, - reinterpret_cast<jint>(surface.get())); - - // This test is conservative and it would be better to compare the ISurfaces - if (p && p != surface.get()) { - jint generationId = env->GetIntField(surfaceObj, - gSurfaceClassInfo.mGenerationId); - generationId++; - env->SetIntField(surfaceObj, - gSurfaceClassInfo.mGenerationId, generationId); - } +sp<ANativeWindow> android_view_Surface_getNativeWindow(JNIEnv* env, jobject surfaceObj) { + return android_view_Surface_getSurface(env, surfaceObj); } -static sp<IGraphicBufferProducer> getISurfaceTexture(JNIEnv* env, jobject surfaceObj) { - if (surfaceObj) { - sp<Surface> surface(getSurface(env, surfaceObj)); - if (surface != NULL) { - return surface->getSurfaceTexture(); - } - } - return NULL; +sp<Surface> android_view_Surface_getSurface(JNIEnv* env, jobject surfaceObj) { + return reinterpret_cast<Surface *>( + env->GetIntField(surfaceObj, gSurfaceClassInfo.mNativeObject)); } jobject android_view_Surface_createFromISurfaceTexture(JNIEnv* env, @@ -255,7 +96,7 @@ jobject android_view_Surface_createFromISurfaceTexture(JNIEnv* env, return NULL; } - jobject surfaceObj = env->NewObject(gSurfaceClassInfo.clazz, gSurfaceClassInfo.ctor); + jobject surfaceObj = env->NewObject(gSurfaceClassInfo.clazz, gSurfaceClassInfo.ctor, surface.get()); if (surfaceObj == NULL) { if (env->ExceptionCheck()) { ALOGE("Could not create instance of Surface from IGraphicBufferProducer."); @@ -264,82 +105,55 @@ jobject android_view_Surface_createFromISurfaceTexture(JNIEnv* env, } return NULL; } - - setSurface(env, surfaceObj, surface); + surface->incStrong(surfaceObj); return surfaceObj; } - // ---------------------------------------------------------------------------- -static void nativeCreate(JNIEnv* env, jobject surfaceObj, jobject sessionObj, - jstring nameStr, jint w, jint h, jint format, jint flags) { - ScopedUtfChars name(env, nameStr); - sp<SurfaceComposerClient> client(android_view_SurfaceSession_getClient(env, sessionObj)); - - sp<SurfaceControl> surface = client->createSurface( - String8(name.c_str()), w, h, format, flags); - if (surface == NULL) { - jniThrowException(env, OutOfResourcesException, NULL); - return; - } - - setSurfaceControl(env, surfaceObj, surface); -} - -static void nativeCreateFromSurfaceTexture(JNIEnv* env, jobject surfaceObj, +static jint nativeCreateFromSurfaceTexture(JNIEnv* env, jobject surfaceObj, jobject surfaceTextureObj) { sp<GLConsumer> st(SurfaceTexture_getSurfaceTexture(env, surfaceTextureObj)); if (st == NULL) { jniThrowException(env, "java/lang/IllegalArgumentException", "SurfaceTexture has already been released"); - return; + return 0; } sp<IGraphicBufferProducer> bq = st->getBufferQueue(); - sp<Surface> surface(new Surface(bq)); if (surface == NULL) { jniThrowException(env, OutOfResourcesException, NULL); - return; + return 0; } - setSurface(env, surfaceObj, surface); + surface->incStrong(surfaceObj); + return int(surface.get()); } -static void nativeRelease(JNIEnv* env, jobject surfaceObj) { - setSurfaceControl(env, surfaceObj, NULL); - setSurface(env, surfaceObj, NULL); +static void nativeRelease(JNIEnv* env, jobject surfaceObj, jint nativeObject) { + sp<Surface> sur(reinterpret_cast<Surface *>(nativeObject)); + sur->decStrong(surfaceObj); } -static void nativeDestroy(JNIEnv* env, jobject surfaceObj) { - sp<SurfaceControl> surfaceControl(getSurfaceControl(env, surfaceObj)); - if (SurfaceControl::isValid(surfaceControl)) { - surfaceControl->clear(); - } - setSurfaceControl(env, surfaceObj, NULL); - setSurface(env, surfaceObj, NULL); +static void nativeDestroy(JNIEnv* env, jobject surfaceObj, jint nativeObject) { + sp<Surface> sur(reinterpret_cast<Surface *>(nativeObject)); + sur->decStrong(surfaceObj); } -static jboolean nativeIsValid(JNIEnv* env, jobject surfaceObj) { - sp<SurfaceControl> surfaceControl(getSurfaceControl(env, surfaceObj)); - if (surfaceControl != NULL) { - return SurfaceControl::isValid(surfaceControl) ? JNI_TRUE : JNI_FALSE; - } - - sp<Surface> surface(getSurface(env, surfaceObj)); - return Surface::isValid(surface) ? JNI_TRUE : JNI_FALSE; +static jboolean nativeIsValid(JNIEnv* env, jobject surfaceObj, jint nativeObject) { + sp<Surface> sur(reinterpret_cast<Surface *>(nativeObject)); + return Surface::isValid(sur) ? JNI_TRUE : JNI_FALSE; } -static jboolean nativeIsConsumerRunningBehind(JNIEnv* env, jobject surfaceObj) { - sp<Surface> surface(getSurface(env, surfaceObj)); - if (!Surface::isValid(surface)) { +static jboolean nativeIsConsumerRunningBehind(JNIEnv* env, jobject surfaceObj, jint nativeObject) { + sp<Surface> sur(reinterpret_cast<Surface *>(nativeObject)); + if (!Surface::isValid(sur)) { doThrowIAE(env); return JNI_FALSE; } - int value = 0; - ANativeWindow* anw = static_cast<ANativeWindow*>(surface.get()); + ANativeWindow* anw = static_cast<ANativeWindow*>(sur.get()); anw->query(anw, NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND, &value); return value; } @@ -359,8 +173,9 @@ static inline SkBitmap::Config convertPixelFormat(PixelFormat format) { } } -static jobject nativeLockCanvas(JNIEnv* env, jobject surfaceObj, jobject dirtyRectObj) { - sp<Surface> surface(getSurface(env, surfaceObj)); +static jobject nativeLockCanvas(JNIEnv* env, jobject surfaceObj, jint nativeObject, jobject dirtyRectObj) { + sp<Surface> surface(reinterpret_cast<Surface *>(nativeObject)); + if (!Surface::isValid(surface)) { doThrowIAE(env); return NULL; @@ -440,14 +255,14 @@ static jobject nativeLockCanvas(JNIEnv* env, jobject surfaceObj, jobject dirtyRe return canvasObj; } -static void nativeUnlockCanvasAndPost(JNIEnv* env, jobject surfaceObj, jobject canvasObj) { +static void nativeUnlockCanvasAndPost(JNIEnv* env, jobject surfaceObj, jint nativeObject, jobject canvasObj) { jobject ownCanvasObj = env->GetObjectField(surfaceObj, gSurfaceClassInfo.mCanvas); if (!env->IsSameObject(ownCanvasObj, canvasObj)) { doThrowIAE(env); return; } - sp<Surface> surface(getSurface(env, surfaceObj)); + sp<Surface> surface(reinterpret_cast<Surface *>(nativeObject)); if (!Surface::isValid(surface)) { return; } @@ -467,393 +282,81 @@ static void nativeUnlockCanvasAndPost(JNIEnv* env, jobject surfaceObj, jobject c } } -static jobject nativeScreenshot(JNIEnv* env, jclass clazz, jobject displayTokenObj, - jint width, jint height, jint minLayer, jint maxLayer, bool allLayers) { - sp<IBinder> displayToken = ibinderForJavaObject(env, displayTokenObj); - if (displayToken == NULL) { - return NULL; - } - - ScreenshotPixelRef* pixels = new ScreenshotPixelRef(NULL); - if (pixels->update(displayToken, width, height, - minLayer, maxLayer, allLayers) != NO_ERROR) { - delete pixels; - return NULL; - } - - uint32_t w = pixels->getWidth(); - uint32_t h = pixels->getHeight(); - uint32_t s = pixels->getStride(); - uint32_t f = pixels->getFormat(); - ssize_t bpr = s * android::bytesPerPixel(f); - - SkBitmap* bitmap = new SkBitmap(); - bitmap->setConfig(convertPixelFormat(f), w, h, bpr); - if (f == PIXEL_FORMAT_RGBX_8888) { - bitmap->setIsOpaque(true); - } - - if (w > 0 && h > 0) { - bitmap->setPixelRef(pixels)->unref(); - bitmap->lockPixels(); - } else { - // be safe with an empty bitmap. - delete pixels; - bitmap->setPixels(NULL); - } - - return GraphicsJNI::createBitmap(env, bitmap, false, NULL); -} - -static void nativeOpenTransaction(JNIEnv* env, jclass clazz) { - SurfaceComposerClient::openGlobalTransaction(); -} - -static void nativeCloseTransaction(JNIEnv* env, jclass clazz) { - SurfaceComposerClient::closeGlobalTransaction(); -} - -static void nativeSetAnimationTransaction(JNIEnv* env, jclass clazz) { - SurfaceComposerClient::setAnimationTransaction(); -} - -static void nativeSetLayer(JNIEnv* env, jobject surfaceObj, jint zorder) { - sp<SurfaceControl> surface(getSurfaceControl(env, surfaceObj)); - if (surface == NULL) return; - - status_t err = surface->setLayer(zorder); - if (err < 0 && err != NO_INIT) { - doThrowIAE(env); - } -} - -static void nativeSetPosition(JNIEnv* env, jobject surfaceObj, jfloat x, jfloat y) { - sp<SurfaceControl> surface(getSurfaceControl(env, surfaceObj)); - if (surface == NULL) return; - - status_t err = surface->setPosition(x, y); - if (err < 0 && err != NO_INIT) { - doThrowIAE(env); - } -} - -static void nativeSetSize(JNIEnv* env, jobject surfaceObj, jint w, jint h) { - sp<SurfaceControl> surface(getSurfaceControl(env, surfaceObj)); - if (surface == NULL) return; - - status_t err = surface->setSize(w, h); - if (err < 0 && err != NO_INIT) { - doThrowIAE(env); - } -} - -static void nativeSetFlags(JNIEnv* env, jobject surfaceObj, jint flags, jint mask) { - sp<SurfaceControl> surface(getSurfaceControl(env, surfaceObj)); - if (surface == NULL) return; - - status_t err = surface->setFlags(flags, mask); - if (err < 0 && err != NO_INIT) { - doThrowIAE(env); - } -} - -static void nativeSetTransparentRegionHint(JNIEnv* env, jobject surfaceObj, jobject regionObj) { - sp<SurfaceControl> surface(getSurfaceControl(env, surfaceObj)); - if (surface == NULL) return; - - SkRegion* region = android_graphics_Region_getSkRegion(env, regionObj); - if (!region) { - doThrowIAE(env); - return; - } - - const SkIRect& b(region->getBounds()); - Region reg(Rect(b.fLeft, b.fTop, b.fRight, b.fBottom)); - if (region->isComplex()) { - SkRegion::Iterator it(*region); - while (!it.done()) { - const SkIRect& r(it.rect()); - reg.addRectUnchecked(r.fLeft, r.fTop, r.fRight, r.fBottom); - it.next(); - } - } - - status_t err = surface->setTransparentRegionHint(reg); - if (err < 0 && err != NO_INIT) { - doThrowIAE(env); - } -} - -static void nativeSetAlpha(JNIEnv* env, jobject surfaceObj, jfloat alpha) { - sp<SurfaceControl> surface(getSurfaceControl(env, surfaceObj)); - if (surface == NULL) return; - - status_t err = surface->setAlpha(alpha); - if (err < 0 && err != NO_INIT) { - doThrowIAE(env); - } -} - -static void nativeSetMatrix(JNIEnv* env, jobject surfaceObj, - jfloat dsdx, jfloat dtdx, jfloat dsdy, jfloat dtdy) { - sp<SurfaceControl> surface(getSurfaceControl(env, surfaceObj)); - if (surface == NULL) return; - - status_t err = surface->setMatrix(dsdx, dtdx, dsdy, dtdy); - if (err < 0 && err != NO_INIT) { - doThrowIAE(env); - } -} - -static void nativeSetWindowCrop(JNIEnv* env, jobject surfaceObj, jobject cropObj) { - const sp<SurfaceControl>& surface(getSurfaceControl(env, surfaceObj)); - if (surface == NULL) return; - - Rect crop; - if (cropObj) { - crop.left = env->GetIntField(cropObj, gRectClassInfo.left); - crop.top = env->GetIntField(cropObj, gRectClassInfo.top); - crop.right = env->GetIntField(cropObj, gRectClassInfo.right); - crop.bottom = env->GetIntField(cropObj, gRectClassInfo.bottom); - } else { - crop.left = crop.top = crop.right = crop.bottom = 0; - } - - status_t err = surface->setCrop(crop); - if (err < 0 && err != NO_INIT) { - doThrowIAE(env); - } -} - -static void nativeSetLayerStack(JNIEnv* env, jobject surfaceObj, jint layerStack) { - sp<SurfaceControl> surface(getSurfaceControl(env, surfaceObj)); - if (surface == NULL) return; - - status_t err = surface->setLayerStack(layerStack); - if (err < 0 && err != NO_INIT) { - doThrowIAE(env); - } -} - -static jobject nativeGetBuiltInDisplay(JNIEnv* env, jclass clazz, jint id) { - sp<IBinder> token(SurfaceComposerClient::getBuiltInDisplay(id)); - return javaObjectForIBinder(env, token); -} - -static jobject nativeCreateDisplay(JNIEnv* env, jclass clazz, jstring nameObj, - jboolean secure) { - ScopedUtfChars name(env, nameObj); - sp<IBinder> token(SurfaceComposerClient::createDisplay( - String8(name.c_str()), bool(secure))); - return javaObjectForIBinder(env, token); -} - -static void nativeSetDisplaySurface(JNIEnv* env, jclass clazz, - jobject tokenObj, jobject surfaceObj) { - sp<IBinder> token(ibinderForJavaObject(env, tokenObj)); - if (token == NULL) return; - - sp<IGraphicBufferProducer> bufferProducer(getISurfaceTexture(env, surfaceObj)); - SurfaceComposerClient::setDisplaySurface(token, bufferProducer); -} - -static void nativeSetDisplayLayerStack(JNIEnv* env, jclass clazz, - jobject tokenObj, jint layerStack) { - sp<IBinder> token(ibinderForJavaObject(env, tokenObj)); - if (token == NULL) return; - - SurfaceComposerClient::setDisplayLayerStack(token, layerStack); -} - -static void nativeSetDisplayProjection(JNIEnv* env, jclass clazz, - jobject tokenObj, jint orientation, jobject layerStackRectObj, jobject displayRectObj) { - sp<IBinder> token(ibinderForJavaObject(env, tokenObj)); - if (token == NULL) return; - - Rect layerStackRect; - layerStackRect.left = env->GetIntField(layerStackRectObj, gRectClassInfo.left); - layerStackRect.top = env->GetIntField(layerStackRectObj, gRectClassInfo.top); - layerStackRect.right = env->GetIntField(layerStackRectObj, gRectClassInfo.right); - layerStackRect.bottom = env->GetIntField(layerStackRectObj, gRectClassInfo.bottom); - - Rect displayRect; - displayRect.left = env->GetIntField(displayRectObj, gRectClassInfo.left); - displayRect.top = env->GetIntField(displayRectObj, gRectClassInfo.top); - displayRect.right = env->GetIntField(displayRectObj, gRectClassInfo.right); - displayRect.bottom = env->GetIntField(displayRectObj, gRectClassInfo.bottom); - - SurfaceComposerClient::setDisplayProjection(token, orientation, layerStackRect, displayRect); -} - -static jboolean nativeGetDisplayInfo(JNIEnv* env, jclass clazz, - jobject tokenObj, jobject infoObj) { - sp<IBinder> token(ibinderForJavaObject(env, tokenObj)); - if (token == NULL) return JNI_FALSE; - - DisplayInfo info; - if (SurfaceComposerClient::getDisplayInfo(token, &info)) { - return JNI_FALSE; - } - - env->SetIntField(infoObj, gPhysicalDisplayInfoClassInfo.width, info.w); - env->SetIntField(infoObj, gPhysicalDisplayInfoClassInfo.height, info.h); - env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.refreshRate, info.fps); - env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.density, info.density); - env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.xDpi, info.xdpi); - env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.yDpi, info.ydpi); - env->SetBooleanField(infoObj, gPhysicalDisplayInfoClassInfo.secure, info.secure); - return JNI_TRUE; -} - -static void nativeBlankDisplay(JNIEnv* env, jclass clazz, jobject tokenObj) { - sp<IBinder> token(ibinderForJavaObject(env, tokenObj)); - if (token == NULL) return; - - ALOGD_IF_SLOW(100, "Excessive delay in blankDisplay() while turning screen off"); - SurfaceComposerClient::blankDisplay(token); -} - -static void nativeUnblankDisplay(JNIEnv* env, jclass clazz, jobject tokenObj) { - sp<IBinder> token(ibinderForJavaObject(env, tokenObj)); - if (token == NULL) return; - - ALOGD_IF_SLOW(100, "Excessive delay in unblankDisplay() while turning screen on"); - SurfaceComposerClient::unblankDisplay(token); -} - // ---------------------------------------------------------------------------- -static void nativeCopyFrom(JNIEnv* env, jobject surfaceObj, jobject otherObj) { +static jint nativeCopyFrom(JNIEnv* env, jobject surfaceObj, + jint nativeObject, jint surfaceControlNativeObj) { /* * This is used by the WindowManagerService just after constructing * a Surface and is necessary for returning the Surface reference to * the caller. At this point, we should only have a SurfaceControl. */ - sp<SurfaceControl> surface(getSurfaceControl(env, surfaceObj)); - sp<SurfaceControl> other(getSurfaceControl(env, otherObj)); - if (!SurfaceControl::isSameSurface(surface, other)) { - // we reassign the surface only if it's a different one - // otherwise we would loose our client-side state. - setSurfaceControl(env, surfaceObj, other); + sp<SurfaceControl> ctrl(reinterpret_cast<SurfaceControl *>(surfaceControlNativeObj)); + sp<Surface> other(ctrl->getSurface()); + if (other != NULL) { + other->incStrong(surfaceObj); + } + + sp<Surface> sur(reinterpret_cast<Surface *>(nativeObject)); + if (sur != NULL) { + sur->decStrong(surfaceObj); } -} -static void nativeTransferFrom(JNIEnv* env, jobject surfaceObj, jobject otherObj) { - sp<SurfaceControl> control(getSurfaceControl(env, otherObj)); - sp<Surface> surface(android_view_Surface_getSurface(env, otherObj)); - setSurfaceControl(env, surfaceObj, control); - setSurface(env, surfaceObj, surface); - setSurfaceControl(env, otherObj, NULL); - setSurface(env, otherObj, NULL); + return int(other.get()); } -static void nativeReadFromParcel(JNIEnv* env, jobject surfaceObj, jobject parcelObj) { +static jint nativeReadFromParcel(JNIEnv* env, jobject surfaceObj, + jint nativeObject, jobject parcelObj) { Parcel* parcel = parcelForJavaObject(env, parcelObj); if (parcel == NULL) { doThrowNPE(env); - return; + return 0; } - - sp<Surface> surface(Surface::readFromParcel(*parcel)); - setSurfaceControl(env, surfaceObj, NULL); - setSurface(env, surfaceObj, surface); + sp<Surface> self(reinterpret_cast<Surface *>(nativeObject)); + if (self != NULL) { + self->decStrong(surfaceObj); + } + sp<Surface> sur(Surface::readFromParcel(*parcel)); + if (sur != NULL) { + sur->incStrong(surfaceObj); + } + return int(sur.get()); } -static void nativeWriteToParcel(JNIEnv* env, jobject surfaceObj, jobject parcelObj) { +static void nativeWriteToParcel(JNIEnv* env, jobject surfaceObj, + jint nativeObject, jobject parcelObj) { Parcel* parcel = parcelForJavaObject(env, parcelObj); if (parcel == NULL) { doThrowNPE(env); return; } - - // The Java instance may have a SurfaceControl (in the case of the - // WindowManager or a system app). In that case, we defer to the - // SurfaceControl to send its ISurface. Otherwise, if the Surface is - // available we let it parcel itself. Finally, if the Surface is also - // NULL we fall back to using the SurfaceControl path which sends an - // empty surface; this matches legacy behavior. - sp<SurfaceControl> control(getSurfaceControl(env, surfaceObj)); - if (control != NULL) { - SurfaceControl::writeSurfaceToParcel(control, parcel); - } else { - sp<Surface> surface(android_view_Surface_getSurface(env, surfaceObj)); - if (surface != NULL) { - Surface::writeToParcel(surface, parcel); - } else { - SurfaceControl::writeSurfaceToParcel(NULL, parcel); - } - } + sp<Surface> self(reinterpret_cast<Surface *>(nativeObject)); + Surface::writeToParcel(self, parcel); } // ---------------------------------------------------------------------------- static JNINativeMethod gSurfaceMethods[] = { - {"nativeCreate", "(Landroid/view/SurfaceSession;Ljava/lang/String;IIII)V", - (void*)nativeCreate }, - {"nativeCreateFromSurfaceTexture", "(Landroid/graphics/SurfaceTexture;)V", + {"nativeCreateFromSurfaceTexture", "(Landroid/graphics/SurfaceTexture;)I", (void*)nativeCreateFromSurfaceTexture }, - {"nativeRelease", "()V", + {"nativeRelease", "(I)V", (void*)nativeRelease }, - {"nativeDestroy", "()V", + {"nativeDestroy", "(I)V", (void*)nativeDestroy }, - {"nativeIsValid", "()Z", + {"nativeIsValid", "(I)Z", (void*)nativeIsValid }, - {"nativeIsConsumerRunningBehind", "()Z", + {"nativeIsConsumerRunningBehind", "(I)Z", (void*)nativeIsConsumerRunningBehind }, - {"nativeLockCanvas", "(Landroid/graphics/Rect;)Landroid/graphics/Canvas;", + {"nativeLockCanvas", "(ILandroid/graphics/Rect;)Landroid/graphics/Canvas;", (void*)nativeLockCanvas }, - {"nativeUnlockCanvasAndPost", "(Landroid/graphics/Canvas;)V", + {"nativeUnlockCanvasAndPost", "(ILandroid/graphics/Canvas;)V", (void*)nativeUnlockCanvasAndPost }, - {"nativeScreenshot", "(Landroid/os/IBinder;IIIIZ)Landroid/graphics/Bitmap;", - (void*)nativeScreenshot }, - {"nativeOpenTransaction", "()V", - (void*)nativeOpenTransaction }, - {"nativeCloseTransaction", "()V", - (void*)nativeCloseTransaction }, - {"nativeSetAnimationTransaction", "()V", - (void*)nativeSetAnimationTransaction }, - {"nativeSetLayer", "(I)V", - (void*)nativeSetLayer }, - {"nativeSetPosition", "(FF)V", - (void*)nativeSetPosition }, - {"nativeSetSize", "(II)V", - (void*)nativeSetSize }, - {"nativeSetTransparentRegionHint", "(Landroid/graphics/Region;)V", - (void*)nativeSetTransparentRegionHint }, - {"nativeSetAlpha", "(F)V", - (void*)nativeSetAlpha }, - {"nativeSetMatrix", "(FFFF)V", - (void*)nativeSetMatrix }, - {"nativeSetFlags", "(II)V", - (void*)nativeSetFlags }, - {"nativeSetWindowCrop", "(Landroid/graphics/Rect;)V", - (void*)nativeSetWindowCrop }, - {"nativeSetLayerStack", "(I)V", - (void*)nativeSetLayerStack }, - {"nativeGetBuiltInDisplay", "(I)Landroid/os/IBinder;", - (void*)nativeGetBuiltInDisplay }, - {"nativeCreateDisplay", "(Ljava/lang/String;Z)Landroid/os/IBinder;", - (void*)nativeCreateDisplay }, - {"nativeSetDisplaySurface", "(Landroid/os/IBinder;Landroid/view/Surface;)V", - (void*)nativeSetDisplaySurface }, - {"nativeSetDisplayLayerStack", "(Landroid/os/IBinder;I)V", - (void*)nativeSetDisplayLayerStack }, - {"nativeSetDisplayProjection", "(Landroid/os/IBinder;ILandroid/graphics/Rect;Landroid/graphics/Rect;)V", - (void*)nativeSetDisplayProjection }, - {"nativeGetDisplayInfo", "(Landroid/os/IBinder;Landroid/view/Surface$PhysicalDisplayInfo;)Z", - (void*)nativeGetDisplayInfo }, - {"nativeBlankDisplay", "(Landroid/os/IBinder;)V", - (void*)nativeBlankDisplay }, - {"nativeUnblankDisplay", "(Landroid/os/IBinder;)V", - (void*)nativeUnblankDisplay }, - {"nativeCopyFrom", "(Landroid/view/Surface;)V", + {"nativeCopyFrom", "(II)I", (void*)nativeCopyFrom }, - {"nativeTransferFrom", "(Landroid/view/Surface;)V", - (void*)nativeTransferFrom }, - {"nativeReadFromParcel", "(Landroid/os/Parcel;)V", + {"nativeReadFromParcel", "(ILandroid/os/Parcel;)I", (void*)nativeReadFromParcel }, - {"nativeWriteToParcel", "(Landroid/os/Parcel;)V", + {"nativeWriteToParcel", "(ILandroid/os/Parcel;)V", (void*)nativeWriteToParcel }, }; @@ -864,17 +367,15 @@ int register_android_view_Surface(JNIEnv* env) jclass clazz = env->FindClass("android/view/Surface"); gSurfaceClassInfo.clazz = jclass(env->NewGlobalRef(clazz)); - gSurfaceClassInfo.mNativeSurface = - env->GetFieldID(gSurfaceClassInfo.clazz, ANDROID_VIEW_SURFACE_JNI_ID, "I"); - gSurfaceClassInfo.mNativeSurfaceControl = - env->GetFieldID(gSurfaceClassInfo.clazz, "mNativeSurfaceControl", "I"); + gSurfaceClassInfo.mNativeObject = + env->GetFieldID(gSurfaceClassInfo.clazz, "mNativeObject", "I"); gSurfaceClassInfo.mGenerationId = env->GetFieldID(gSurfaceClassInfo.clazz, "mGenerationId", "I"); gSurfaceClassInfo.mCanvas = env->GetFieldID(gSurfaceClassInfo.clazz, "mCanvas", "Landroid/graphics/Canvas;"); gSurfaceClassInfo.mCanvasSaveCount = env->GetFieldID(gSurfaceClassInfo.clazz, "mCanvasSaveCount", "I"); - gSurfaceClassInfo.ctor = env->GetMethodID(gSurfaceClassInfo.clazz, "<init>", "()V"); + gSurfaceClassInfo.ctor = env->GetMethodID(gSurfaceClassInfo.clazz, "<init>", "(I)V"); clazz = env->FindClass("android/graphics/Canvas"); gCanvasClassInfo.mNativeCanvas = env->GetFieldID(clazz, "mNativeCanvas", "I"); @@ -886,14 +387,6 @@ int register_android_view_Surface(JNIEnv* env) gRectClassInfo.right = env->GetFieldID(clazz, "right", "I"); gRectClassInfo.bottom = env->GetFieldID(clazz, "bottom", "I"); - clazz = env->FindClass("android/view/Surface$PhysicalDisplayInfo"); - gPhysicalDisplayInfoClassInfo.width = env->GetFieldID(clazz, "width", "I"); - gPhysicalDisplayInfoClassInfo.height = env->GetFieldID(clazz, "height", "I"); - gPhysicalDisplayInfoClassInfo.refreshRate = env->GetFieldID(clazz, "refreshRate", "F"); - gPhysicalDisplayInfoClassInfo.density = env->GetFieldID(clazz, "density", "F"); - gPhysicalDisplayInfoClassInfo.xDpi = env->GetFieldID(clazz, "xDpi", "F"); - gPhysicalDisplayInfoClassInfo.yDpi = env->GetFieldID(clazz, "yDpi", "F"); - gPhysicalDisplayInfoClassInfo.secure = env->GetFieldID(clazz, "secure", "Z"); return err; } diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp new file mode 100644 index 0000000..7398895 --- /dev/null +++ b/core/jni/android_view_SurfaceControl.cpp @@ -0,0 +1,451 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "SurfaceControl" + +#include <stdio.h> + +#include "jni.h" +#include "JNIHelp.h" + +#include "android_os_Parcel.h" +#include "android_util_Binder.h" +#include "android/graphics/GraphicsJNI.h" +#include "android/graphics/Region.h" + +#include <android_runtime/AndroidRuntime.h> +#include <android_runtime/android_view_SurfaceSession.h> + +#include <gui/Surface.h> +#include <gui/SurfaceComposerClient.h> + +#include <ui/DisplayInfo.h> +#include <ui/Rect.h> +#include <ui/Region.h> + +#include <utils/Log.h> + +#include <ScopedUtfChars.h> + +// ---------------------------------------------------------------------------- + +namespace android { + +static const char* const OutOfResourcesException = + "android/view/Surface$OutOfResourcesException"; + +static struct { + jfieldID width; + jfieldID height; + jfieldID refreshRate; + jfieldID density; + jfieldID xDpi; + jfieldID yDpi; + jfieldID secure; +} gPhysicalDisplayInfoClassInfo; + + +class ScreenshotPixelRef : public SkPixelRef { +public: + ScreenshotPixelRef(SkColorTable* ctable) { + fCTable = ctable; + SkSafeRef(ctable); + setImmutable(); + } + + virtual ~ScreenshotPixelRef() { + SkSafeUnref(fCTable); + } + + status_t update(const sp<IBinder>& display, int width, int height, + int minLayer, int maxLayer, bool allLayers) { + status_t res = (width > 0 && height > 0) + ? (allLayers + ? mScreenshot.update(display, width, height) + : mScreenshot.update(display, width, height, minLayer, maxLayer)) + : mScreenshot.update(display); + if (res != NO_ERROR) { + return res; + } + + return NO_ERROR; + } + + uint32_t getWidth() const { + return mScreenshot.getWidth(); + } + + uint32_t getHeight() const { + return mScreenshot.getHeight(); + } + + uint32_t getStride() const { + return mScreenshot.getStride(); + } + + uint32_t getFormat() const { + return mScreenshot.getFormat(); + } + +protected: + // overrides from SkPixelRef + virtual void* onLockPixels(SkColorTable** ct) { + *ct = fCTable; + return (void*)mScreenshot.getPixels(); + } + + virtual void onUnlockPixels() { + } + +private: + ScreenshotClient mScreenshot; + SkColorTable* fCTable; + + typedef SkPixelRef INHERITED; +}; + + +// ---------------------------------------------------------------------------- + +static jint nativeCreate(JNIEnv* env, jobject surfaceObj, jobject sessionObj, + jstring nameStr, jint w, jint h, jint format, jint flags) { + ScopedUtfChars name(env, nameStr); + sp<SurfaceComposerClient> client(android_view_SurfaceSession_getClient(env, sessionObj)); + sp<SurfaceControl> surface = client->createSurface( + String8(name.c_str()), w, h, format, flags); + if (surface == NULL) { + jniThrowException(env, OutOfResourcesException, NULL); + return 0; + } + surface->incStrong(surfaceObj); + return int(surface.get()); +} + +static void nativeRelease(JNIEnv* env, jobject surfaceObj, jint nativeObject) { + sp<SurfaceControl> ctrl(reinterpret_cast<SurfaceControl *>(nativeObject)); + ctrl->decStrong(surfaceObj); +} + +static void nativeDestroy(JNIEnv* env, jobject surfaceObj, jint nativeObject) { + sp<SurfaceControl> ctrl(reinterpret_cast<SurfaceControl *>(nativeObject)); + ctrl->clear(); + ctrl->decStrong(surfaceObj); +} + +static inline SkBitmap::Config convertPixelFormat(PixelFormat format) { + /* note: if PIXEL_FORMAT_RGBX_8888 means that all alpha bytes are 0xFF, then + we can map to SkBitmap::kARGB_8888_Config, and optionally call + bitmap.setIsOpaque(true) on the resulting SkBitmap (as an accelerator) + */ + switch (format) { + case PIXEL_FORMAT_RGBX_8888: return SkBitmap::kARGB_8888_Config; + case PIXEL_FORMAT_RGBA_8888: return SkBitmap::kARGB_8888_Config; + case PIXEL_FORMAT_RGBA_4444: return SkBitmap::kARGB_4444_Config; + case PIXEL_FORMAT_RGB_565: return SkBitmap::kRGB_565_Config; + case PIXEL_FORMAT_A_8: return SkBitmap::kA8_Config; + default: return SkBitmap::kNo_Config; + } +} + +static jobject nativeScreenshot(JNIEnv* env, jclass clazz, jobject displayTokenObj, + jint width, jint height, jint minLayer, jint maxLayer, bool allLayers) { + sp<IBinder> displayToken = ibinderForJavaObject(env, displayTokenObj); + if (displayToken == NULL) { + return NULL; + } + + ScreenshotPixelRef* pixels = new ScreenshotPixelRef(NULL); + if (pixels->update(displayToken, width, height, + minLayer, maxLayer, allLayers) != NO_ERROR) { + delete pixels; + return NULL; + } + + uint32_t w = pixels->getWidth(); + uint32_t h = pixels->getHeight(); + uint32_t s = pixels->getStride(); + uint32_t f = pixels->getFormat(); + ssize_t bpr = s * android::bytesPerPixel(f); + + SkBitmap* bitmap = new SkBitmap(); + bitmap->setConfig(convertPixelFormat(f), w, h, bpr); + if (f == PIXEL_FORMAT_RGBX_8888) { + bitmap->setIsOpaque(true); + } + + if (w > 0 && h > 0) { + bitmap->setPixelRef(pixels)->unref(); + bitmap->lockPixels(); + } else { + // be safe with an empty bitmap. + delete pixels; + bitmap->setPixels(NULL); + } + + return GraphicsJNI::createBitmap(env, bitmap, false, NULL); +} + +static void nativeOpenTransaction(JNIEnv* env, jclass clazz) { + SurfaceComposerClient::openGlobalTransaction(); +} + +static void nativeCloseTransaction(JNIEnv* env, jclass clazz) { + SurfaceComposerClient::closeGlobalTransaction(); +} + +static void nativeSetAnimationTransaction(JNIEnv* env, jclass clazz) { + SurfaceComposerClient::setAnimationTransaction(); +} + +static void nativeSetLayer(JNIEnv* env, jobject surfaceObj, jint nativeObject, jint zorder) { + SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject); + status_t err = ctrl->setLayer(zorder); + if (err < 0 && err != NO_INIT) { + doThrowIAE(env); + } +} + +static void nativeSetPosition(JNIEnv* env, jobject surfaceObj, jint nativeObject, jfloat x, jfloat y) { + SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject); + status_t err = ctrl->setPosition(x, y); + if (err < 0 && err != NO_INIT) { + doThrowIAE(env); + } +} + +static void nativeSetSize(JNIEnv* env, jobject surfaceObj, jint nativeObject, jint w, jint h) { + SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject); + status_t err = ctrl->setSize(w, h); + if (err < 0 && err != NO_INIT) { + doThrowIAE(env); + } +} + +static void nativeSetFlags(JNIEnv* env, jobject surfaceObj, jint nativeObject, jint flags, jint mask) { + SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject); + status_t err = ctrl->setFlags(flags, mask); + if (err < 0 && err != NO_INIT) { + doThrowIAE(env); + } +} + +static void nativeSetTransparentRegionHint(JNIEnv* env, jobject surfaceObj, jint nativeObject, jobject regionObj) { + SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject); + SkRegion* region = android_graphics_Region_getSkRegion(env, regionObj); + if (!region) { + doThrowIAE(env); + return; + } + + const SkIRect& b(region->getBounds()); + Region reg(Rect(b.fLeft, b.fTop, b.fRight, b.fBottom)); + if (region->isComplex()) { + SkRegion::Iterator it(*region); + while (!it.done()) { + const SkIRect& r(it.rect()); + reg.addRectUnchecked(r.fLeft, r.fTop, r.fRight, r.fBottom); + it.next(); + } + } + + status_t err = ctrl->setTransparentRegionHint(reg); + if (err < 0 && err != NO_INIT) { + doThrowIAE(env); + } +} + +static void nativeSetAlpha(JNIEnv* env, jobject surfaceObj, jint nativeObject, jfloat alpha) { + SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject); + status_t err = ctrl->setAlpha(alpha); + if (err < 0 && err != NO_INIT) { + doThrowIAE(env); + } +} + +static void nativeSetMatrix(JNIEnv* env, jobject surfaceObj, jint nativeObject, + jfloat dsdx, jfloat dtdx, jfloat dsdy, jfloat dtdy) { + SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject); + status_t err = ctrl->setMatrix(dsdx, dtdx, dsdy, dtdy); + if (err < 0 && err != NO_INIT) { + doThrowIAE(env); + } +} + +static void nativeSetWindowCrop(JNIEnv* env, jobject surfaceObj, jint nativeObject, + jint l, jint t, jint r, jint b) { + SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject); + Rect crop(l, t, r, b); + status_t err = ctrl->setCrop(crop); + if (err < 0 && err != NO_INIT) { + doThrowIAE(env); + } +} + +static void nativeSetLayerStack(JNIEnv* env, jobject surfaceObj, jint nativeObject, jint layerStack) { + SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject); + status_t err = ctrl->setLayerStack(layerStack); + if (err < 0 && err != NO_INIT) { + doThrowIAE(env); + } +} + +static jobject nativeGetBuiltInDisplay(JNIEnv* env, jclass clazz, jint id) { + sp<IBinder> token(SurfaceComposerClient::getBuiltInDisplay(id)); + return javaObjectForIBinder(env, token); +} + +static jobject nativeCreateDisplay(JNIEnv* env, jclass clazz, jstring nameObj, + jboolean secure) { + ScopedUtfChars name(env, nameObj); + sp<IBinder> token(SurfaceComposerClient::createDisplay( + String8(name.c_str()), bool(secure))); + return javaObjectForIBinder(env, token); +} + +static void nativeSetDisplaySurface(JNIEnv* env, jclass clazz, + jobject tokenObj, jint nativeSurfaceObject) { + sp<IBinder> token(ibinderForJavaObject(env, tokenObj)); + if (token == NULL) return; + sp<Surface> sur(reinterpret_cast<Surface *>(nativeSurfaceObject)); + sp<IGraphicBufferProducer> bufferProducer(sur->getSurfaceTexture()); + SurfaceComposerClient::setDisplaySurface(token, bufferProducer); +} + +static void nativeSetDisplayLayerStack(JNIEnv* env, jclass clazz, + jobject tokenObj, jint layerStack) { + sp<IBinder> token(ibinderForJavaObject(env, tokenObj)); + if (token == NULL) return; + + SurfaceComposerClient::setDisplayLayerStack(token, layerStack); +} + +static void nativeSetDisplayProjection(JNIEnv* env, jclass clazz, + jobject tokenObj, jint orientation, + jint layerStackRect_left, jint layerStackRect_top, jint layerStackRect_right, jint layerStackRect_bottom, + jint displayRect_left, jint displayRect_top, jint displayRect_right, jint displayRect_bottom) { + sp<IBinder> token(ibinderForJavaObject(env, tokenObj)); + if (token == NULL) return; + Rect layerStackRect(layerStackRect_left, layerStackRect_top, layerStackRect_right, layerStackRect_bottom); + Rect displayRect(displayRect_left, displayRect_top, displayRect_right, displayRect_bottom); + SurfaceComposerClient::setDisplayProjection(token, orientation, layerStackRect, displayRect); +} + +static jboolean nativeGetDisplayInfo(JNIEnv* env, jclass clazz, + jobject tokenObj, jobject infoObj) { + sp<IBinder> token(ibinderForJavaObject(env, tokenObj)); + if (token == NULL) return JNI_FALSE; + + DisplayInfo info; + if (SurfaceComposerClient::getDisplayInfo(token, &info)) { + return JNI_FALSE; + } + + env->SetIntField(infoObj, gPhysicalDisplayInfoClassInfo.width, info.w); + env->SetIntField(infoObj, gPhysicalDisplayInfoClassInfo.height, info.h); + env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.refreshRate, info.fps); + env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.density, info.density); + env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.xDpi, info.xdpi); + env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.yDpi, info.ydpi); + env->SetBooleanField(infoObj, gPhysicalDisplayInfoClassInfo.secure, info.secure); + return JNI_TRUE; +} + +static void nativeBlankDisplay(JNIEnv* env, jclass clazz, jobject tokenObj) { + sp<IBinder> token(ibinderForJavaObject(env, tokenObj)); + if (token == NULL) return; + + ALOGD_IF_SLOW(100, "Excessive delay in blankDisplay() while turning screen off"); + SurfaceComposerClient::blankDisplay(token); +} + +static void nativeUnblankDisplay(JNIEnv* env, jclass clazz, jobject tokenObj) { + sp<IBinder> token(ibinderForJavaObject(env, tokenObj)); + if (token == NULL) return; + + ALOGD_IF_SLOW(100, "Excessive delay in unblankDisplay() while turning screen on"); + SurfaceComposerClient::unblankDisplay(token); +} + +// ---------------------------------------------------------------------------- + +static JNINativeMethod sSurfaceControlMethods[] = { + {"nativeCreate", "(Landroid/view/SurfaceSession;Ljava/lang/String;IIII)I", + (void*)nativeCreate }, + {"nativeRelease", "(I)V", + (void*)nativeRelease }, + {"nativeDestroy", "(I)V", + (void*)nativeDestroy }, + {"nativeScreenshot", "(Landroid/os/IBinder;IIIIZ)Landroid/graphics/Bitmap;", + (void*)nativeScreenshot }, + {"nativeOpenTransaction", "()V", + (void*)nativeOpenTransaction }, + {"nativeCloseTransaction", "()V", + (void*)nativeCloseTransaction }, + {"nativeSetAnimationTransaction", "()V", + (void*)nativeSetAnimationTransaction }, + {"nativeSetLayer", "(II)V", + (void*)nativeSetLayer }, + {"nativeSetPosition", "(IFF)V", + (void*)nativeSetPosition }, + {"nativeSetSize", "(III)V", + (void*)nativeSetSize }, + {"nativeSetTransparentRegionHint", "(ILandroid/graphics/Region;)V", + (void*)nativeSetTransparentRegionHint }, + {"nativeSetAlpha", "(IF)V", + (void*)nativeSetAlpha }, + {"nativeSetMatrix", "(IFFFF)V", + (void*)nativeSetMatrix }, + {"nativeSetFlags", "(III)V", + (void*)nativeSetFlags }, + {"nativeSetWindowCrop", "(IIIII)V", + (void*)nativeSetWindowCrop }, + {"nativeSetLayerStack", "(II)V", + (void*)nativeSetLayerStack }, + {"nativeGetBuiltInDisplay", "(I)Landroid/os/IBinder;", + (void*)nativeGetBuiltInDisplay }, + {"nativeCreateDisplay", "(Ljava/lang/String;Z)Landroid/os/IBinder;", + (void*)nativeCreateDisplay }, + {"nativeSetDisplaySurface", "(Landroid/os/IBinder;I)V", + (void*)nativeSetDisplaySurface }, + {"nativeSetDisplayLayerStack", "(Landroid/os/IBinder;I)V", + (void*)nativeSetDisplayLayerStack }, + {"nativeSetDisplayProjection", "(Landroid/os/IBinder;IIIIIIIII)V", + (void*)nativeSetDisplayProjection }, + {"nativeGetDisplayInfo", "(Landroid/os/IBinder;Landroid/view/SurfaceControl$PhysicalDisplayInfo;)Z", + (void*)nativeGetDisplayInfo }, + {"nativeBlankDisplay", "(Landroid/os/IBinder;)V", + (void*)nativeBlankDisplay }, + {"nativeUnblankDisplay", "(Landroid/os/IBinder;)V", + (void*)nativeUnblankDisplay }, +}; + +int register_android_view_SurfaceControl(JNIEnv* env) +{ + int err = AndroidRuntime::registerNativeMethods(env, "android/view/SurfaceControl", + sSurfaceControlMethods, NELEM(sSurfaceControlMethods)); + + jclass clazz = env->FindClass("android/view/SurfaceControl$PhysicalDisplayInfo"); + gPhysicalDisplayInfoClassInfo.width = env->GetFieldID(clazz, "width", "I"); + gPhysicalDisplayInfoClassInfo.height = env->GetFieldID(clazz, "height", "I"); + gPhysicalDisplayInfoClassInfo.refreshRate = env->GetFieldID(clazz, "refreshRate", "F"); + gPhysicalDisplayInfoClassInfo.density = env->GetFieldID(clazz, "density", "F"); + gPhysicalDisplayInfoClassInfo.xDpi = env->GetFieldID(clazz, "xDpi", "F"); + gPhysicalDisplayInfoClassInfo.yDpi = env->GetFieldID(clazz, "yDpi", "F"); + gPhysicalDisplayInfoClassInfo.secure = env->GetFieldID(clazz, "secure", "Z"); + return err; +} + +}; |