android_view_SurfaceControl.cpp revision b644a3b84521e2155a5af985a4d4ed305474e567
1/* 2 * Copyright (C) 2013 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 "SurfaceControl" 18 19#include <stdio.h> 20 21#include "jni.h" 22#include "JNIHelp.h" 23 24#include "android_os_Parcel.h" 25#include "android_util_Binder.h" 26#include "android/graphics/GraphicsJNI.h" 27#include "android/graphics/Region.h" 28 29#include <android_runtime/AndroidRuntime.h> 30#include <android_runtime/android_view_Surface.h> 31#include <android_runtime/android_view_SurfaceSession.h> 32 33#include <gui/Surface.h> 34#include <gui/SurfaceComposerClient.h> 35 36#include <ui/DisplayInfo.h> 37#include <ui/Rect.h> 38#include <ui/Region.h> 39 40#include <utils/Log.h> 41 42#include <ScopedUtfChars.h> 43 44// ---------------------------------------------------------------------------- 45 46namespace android { 47 48static const char* const OutOfResourcesException = 49 "android/view/Surface$OutOfResourcesException"; 50 51static struct { 52 jfieldID width; 53 jfieldID height; 54 jfieldID refreshRate; 55 jfieldID density; 56 jfieldID xDpi; 57 jfieldID yDpi; 58 jfieldID secure; 59} gPhysicalDisplayInfoClassInfo; 60 61 62class ScreenshotPixelRef : public SkPixelRef { 63public: 64 ScreenshotPixelRef(const SkImageInfo& info, ScreenshotClient* screenshot) : 65 SkPixelRef(info), 66 mScreenshot(screenshot) { 67 setImmutable(); 68 } 69 70 virtual ~ScreenshotPixelRef() { 71 delete mScreenshot; 72 } 73 74protected: 75 // overrides from SkPixelRef 76 virtual void* onLockPixels(SkColorTable** ct) { 77 *ct = NULL; 78 return (void*)mScreenshot->getPixels(); 79 } 80 81 virtual void onUnlockPixels() { 82 } 83 84 SK_DECLARE_UNFLATTENABLE_OBJECT() 85private: 86 ScreenshotClient* mScreenshot; 87 88 typedef SkPixelRef INHERITED; 89}; 90 91 92// ---------------------------------------------------------------------------- 93 94static jlong nativeCreate(JNIEnv* env, jclass clazz, jobject sessionObj, 95 jstring nameStr, jint w, jint h, jint format, jint flags) { 96 ScopedUtfChars name(env, nameStr); 97 sp<SurfaceComposerClient> client(android_view_SurfaceSession_getClient(env, sessionObj)); 98 sp<SurfaceControl> surface = client->createSurface( 99 String8(name.c_str()), w, h, format, flags); 100 if (surface == NULL) { 101 jniThrowException(env, OutOfResourcesException, NULL); 102 return 0; 103 } 104 surface->incStrong((void *)nativeCreate); 105 return reinterpret_cast<jlong>(surface.get()); 106} 107 108static void nativeRelease(JNIEnv* env, jclass clazz, jlong nativeObject) { 109 sp<SurfaceControl> ctrl(reinterpret_cast<SurfaceControl *>(nativeObject)); 110 ctrl->decStrong((void *)nativeCreate); 111} 112 113static void nativeDestroy(JNIEnv* env, jclass clazz, jlong nativeObject) { 114 sp<SurfaceControl> ctrl(reinterpret_cast<SurfaceControl *>(nativeObject)); 115 ctrl->clear(); 116 ctrl->decStrong((void *)nativeCreate); 117} 118 119static jobject nativeScreenshotBitmap(JNIEnv* env, jclass clazz, jobject displayTokenObj, 120 jint width, jint height, jint minLayer, jint maxLayer, bool allLayers, 121 bool useIdentityTransform) { 122 sp<IBinder> displayToken = ibinderForJavaObject(env, displayTokenObj); 123 if (displayToken == NULL) { 124 return NULL; 125 } 126 127 ScreenshotClient* screenshot = new ScreenshotClient(); 128 status_t res; 129 if (width > 0 && height > 0) { 130 if (allLayers) { 131 res = screenshot->update(displayToken, width, height, useIdentityTransform); 132 } else { 133 res = screenshot->update(displayToken, width, height, minLayer, maxLayer, 134 useIdentityTransform); 135 } 136 } else { 137 res = screenshot->update(displayToken, useIdentityTransform); 138 } 139 if (res != NO_ERROR) { 140 delete screenshot; 141 return NULL; 142 } 143 144 SkImageInfo screenshotInfo; 145 screenshotInfo.fWidth = screenshot->getWidth(); 146 screenshotInfo.fHeight = screenshot->getHeight(); 147 148 switch (screenshot->getFormat()) { 149 case PIXEL_FORMAT_RGBX_8888: { 150 screenshotInfo.fColorType = kRGBA_8888_SkColorType; 151 screenshotInfo.fAlphaType = kIgnore_SkAlphaType; 152 break; 153 } 154 case PIXEL_FORMAT_RGBA_8888: { 155 screenshotInfo.fColorType = kRGBA_8888_SkColorType; 156 screenshotInfo.fAlphaType = kPremul_SkAlphaType; 157 break; 158 } 159 case PIXEL_FORMAT_RGB_565: { 160 screenshotInfo.fColorType = kRGB_565_SkColorType; 161 screenshotInfo.fAlphaType = kIgnore_SkAlphaType; 162 break; 163 } 164 default: { 165 delete screenshot; 166 return NULL; 167 } 168 } 169 170 // takes ownership of ScreenshotClient 171 ScreenshotPixelRef* pixels = new ScreenshotPixelRef(screenshotInfo, screenshot); 172 const ssize_t rowBytes = 173 screenshot->getStride() * android::bytesPerPixel(screenshot->getFormat()); 174 175 SkBitmap* bitmap = new SkBitmap(); 176 bitmap->setConfig(screenshotInfo, (size_t)rowBytes); 177 if (screenshotInfo.fWidth > 0 && screenshotInfo.fHeight > 0) { 178 bitmap->setPixelRef(pixels)->unref(); 179 bitmap->lockPixels(); 180 } else { 181 // be safe with an empty bitmap. 182 delete pixels; 183 bitmap->setPixels(NULL); 184 } 185 186 return GraphicsJNI::createBitmap(env, bitmap, 187 GraphicsJNI::kBitmapCreateFlag_Premultiplied, NULL); 188} 189 190static void nativeScreenshot(JNIEnv* env, jclass clazz, 191 jobject displayTokenObj, jobject surfaceObj, 192 jint width, jint height, jint minLayer, jint maxLayer, bool allLayers, 193 bool useIdentityTransform) { 194 sp<IBinder> displayToken = ibinderForJavaObject(env, displayTokenObj); 195 if (displayToken != NULL) { 196 sp<Surface> consumer = android_view_Surface_getSurface(env, surfaceObj); 197 if (consumer != NULL) { 198 if (allLayers) { 199 minLayer = 0; 200 maxLayer = -1; 201 } 202 ScreenshotClient::capture( 203 displayToken, consumer->getIGraphicBufferProducer(), 204 width, height, uint32_t(minLayer), uint32_t(maxLayer), 205 useIdentityTransform); 206 } 207 } 208} 209 210static void nativeOpenTransaction(JNIEnv* env, jclass clazz) { 211 SurfaceComposerClient::openGlobalTransaction(); 212} 213 214static void nativeCloseTransaction(JNIEnv* env, jclass clazz) { 215 SurfaceComposerClient::closeGlobalTransaction(); 216} 217 218static void nativeSetAnimationTransaction(JNIEnv* env, jclass clazz) { 219 SurfaceComposerClient::setAnimationTransaction(); 220} 221 222static void nativeSetLayer(JNIEnv* env, jclass clazz, jlong nativeObject, jint zorder) { 223 SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject); 224 status_t err = ctrl->setLayer(zorder); 225 if (err < 0 && err != NO_INIT) { 226 doThrowIAE(env); 227 } 228} 229 230static void nativeSetPosition(JNIEnv* env, jclass clazz, jlong nativeObject, jfloat x, jfloat y) { 231 SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject); 232 status_t err = ctrl->setPosition(x, y); 233 if (err < 0 && err != NO_INIT) { 234 doThrowIAE(env); 235 } 236} 237 238static void nativeSetSize(JNIEnv* env, jclass clazz, jlong nativeObject, jint w, jint h) { 239 SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject); 240 status_t err = ctrl->setSize(w, h); 241 if (err < 0 && err != NO_INIT) { 242 doThrowIAE(env); 243 } 244} 245 246static void nativeSetFlags(JNIEnv* env, jclass clazz, jlong nativeObject, jint flags, jint mask) { 247 SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject); 248 status_t err = ctrl->setFlags(flags, mask); 249 if (err < 0 && err != NO_INIT) { 250 doThrowIAE(env); 251 } 252} 253 254static void nativeSetTransparentRegionHint(JNIEnv* env, jclass clazz, jlong nativeObject, jobject regionObj) { 255 SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject); 256 SkRegion* region = android_graphics_Region_getSkRegion(env, regionObj); 257 if (!region) { 258 doThrowIAE(env); 259 return; 260 } 261 262 const SkIRect& b(region->getBounds()); 263 Region reg(Rect(b.fLeft, b.fTop, b.fRight, b.fBottom)); 264 if (region->isComplex()) { 265 SkRegion::Iterator it(*region); 266 while (!it.done()) { 267 const SkIRect& r(it.rect()); 268 reg.addRectUnchecked(r.fLeft, r.fTop, r.fRight, r.fBottom); 269 it.next(); 270 } 271 } 272 273 status_t err = ctrl->setTransparentRegionHint(reg); 274 if (err < 0 && err != NO_INIT) { 275 doThrowIAE(env); 276 } 277} 278 279static void nativeSetAlpha(JNIEnv* env, jclass clazz, jlong nativeObject, jfloat alpha) { 280 SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject); 281 status_t err = ctrl->setAlpha(alpha); 282 if (err < 0 && err != NO_INIT) { 283 doThrowIAE(env); 284 } 285} 286 287static void nativeSetMatrix(JNIEnv* env, jclass clazz, jlong nativeObject, 288 jfloat dsdx, jfloat dtdx, jfloat dsdy, jfloat dtdy) { 289 SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject); 290 status_t err = ctrl->setMatrix(dsdx, dtdx, dsdy, dtdy); 291 if (err < 0 && err != NO_INIT) { 292 doThrowIAE(env); 293 } 294} 295 296static void nativeSetWindowCrop(JNIEnv* env, jclass clazz, jlong nativeObject, 297 jint l, jint t, jint r, jint b) { 298 SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject); 299 Rect crop(l, t, r, b); 300 status_t err = ctrl->setCrop(crop); 301 if (err < 0 && err != NO_INIT) { 302 doThrowIAE(env); 303 } 304} 305 306static void nativeSetLayerStack(JNIEnv* env, jclass clazz, jlong nativeObject, jint layerStack) { 307 SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject); 308 status_t err = ctrl->setLayerStack(layerStack); 309 if (err < 0 && err != NO_INIT) { 310 doThrowIAE(env); 311 } 312} 313 314static jobject nativeGetBuiltInDisplay(JNIEnv* env, jclass clazz, jint id) { 315 sp<IBinder> token(SurfaceComposerClient::getBuiltInDisplay(id)); 316 return javaObjectForIBinder(env, token); 317} 318 319static jobject nativeCreateDisplay(JNIEnv* env, jclass clazz, jstring nameObj, 320 jboolean secure) { 321 ScopedUtfChars name(env, nameObj); 322 sp<IBinder> token(SurfaceComposerClient::createDisplay( 323 String8(name.c_str()), bool(secure))); 324 return javaObjectForIBinder(env, token); 325} 326 327static void nativeDestroyDisplay(JNIEnv* env, jclass clazz, jobject tokenObj) { 328 sp<IBinder> token(ibinderForJavaObject(env, tokenObj)); 329 if (token == NULL) return; 330 SurfaceComposerClient::destroyDisplay(token); 331} 332 333static void nativeSetDisplaySurface(JNIEnv* env, jclass clazz, 334 jobject tokenObj, jlong nativeSurfaceObject) { 335 sp<IBinder> token(ibinderForJavaObject(env, tokenObj)); 336 if (token == NULL) return; 337 sp<IGraphicBufferProducer> bufferProducer; 338 sp<Surface> sur(reinterpret_cast<Surface *>(nativeSurfaceObject)); 339 if (sur != NULL) { 340 bufferProducer = sur->getIGraphicBufferProducer(); 341 } 342 SurfaceComposerClient::setDisplaySurface(token, bufferProducer); 343} 344 345static void nativeSetDisplayLayerStack(JNIEnv* env, jclass clazz, 346 jobject tokenObj, jint layerStack) { 347 sp<IBinder> token(ibinderForJavaObject(env, tokenObj)); 348 if (token == NULL) return; 349 350 SurfaceComposerClient::setDisplayLayerStack(token, layerStack); 351} 352 353static void nativeSetDisplayProjection(JNIEnv* env, jclass clazz, 354 jobject tokenObj, jint orientation, 355 jint layerStackRect_left, jint layerStackRect_top, jint layerStackRect_right, jint layerStackRect_bottom, 356 jint displayRect_left, jint displayRect_top, jint displayRect_right, jint displayRect_bottom) { 357 sp<IBinder> token(ibinderForJavaObject(env, tokenObj)); 358 if (token == NULL) return; 359 Rect layerStackRect(layerStackRect_left, layerStackRect_top, layerStackRect_right, layerStackRect_bottom); 360 Rect displayRect(displayRect_left, displayRect_top, displayRect_right, displayRect_bottom); 361 SurfaceComposerClient::setDisplayProjection(token, orientation, layerStackRect, displayRect); 362} 363 364static jboolean nativeGetDisplayInfo(JNIEnv* env, jclass clazz, 365 jobject tokenObj, jobject infoObj) { 366 sp<IBinder> token(ibinderForJavaObject(env, tokenObj)); 367 if (token == NULL) return JNI_FALSE; 368 369 DisplayInfo info; 370 if (SurfaceComposerClient::getDisplayInfo(token, &info)) { 371 return JNI_FALSE; 372 } 373 374 env->SetIntField(infoObj, gPhysicalDisplayInfoClassInfo.width, info.w); 375 env->SetIntField(infoObj, gPhysicalDisplayInfoClassInfo.height, info.h); 376 env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.refreshRate, info.fps); 377 env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.density, info.density); 378 env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.xDpi, info.xdpi); 379 env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.yDpi, info.ydpi); 380 env->SetBooleanField(infoObj, gPhysicalDisplayInfoClassInfo.secure, info.secure); 381 return JNI_TRUE; 382} 383 384static void nativeBlankDisplay(JNIEnv* env, jclass clazz, jobject tokenObj) { 385 sp<IBinder> token(ibinderForJavaObject(env, tokenObj)); 386 if (token == NULL) return; 387 388 ALOGD_IF_SLOW(100, "Excessive delay in blankDisplay() while turning screen off"); 389 SurfaceComposerClient::blankDisplay(token); 390} 391 392static void nativeUnblankDisplay(JNIEnv* env, jclass clazz, jobject tokenObj) { 393 sp<IBinder> token(ibinderForJavaObject(env, tokenObj)); 394 if (token == NULL) return; 395 396 ALOGD_IF_SLOW(100, "Excessive delay in unblankDisplay() while turning screen on"); 397 SurfaceComposerClient::unblankDisplay(token); 398} 399 400// ---------------------------------------------------------------------------- 401 402static JNINativeMethod sSurfaceControlMethods[] = { 403 {"nativeCreate", "(Landroid/view/SurfaceSession;Ljava/lang/String;IIII)J", 404 (void*)nativeCreate }, 405 {"nativeRelease", "(J)V", 406 (void*)nativeRelease }, 407 {"nativeDestroy", "(J)V", 408 (void*)nativeDestroy }, 409 {"nativeScreenshot", "(Landroid/os/IBinder;IIIIZZ)Landroid/graphics/Bitmap;", 410 (void*)nativeScreenshotBitmap }, 411 {"nativeScreenshot", "(Landroid/os/IBinder;Landroid/view/Surface;IIIIZZ)V", 412 (void*)nativeScreenshot }, 413 {"nativeOpenTransaction", "()V", 414 (void*)nativeOpenTransaction }, 415 {"nativeCloseTransaction", "()V", 416 (void*)nativeCloseTransaction }, 417 {"nativeSetAnimationTransaction", "()V", 418 (void*)nativeSetAnimationTransaction }, 419 {"nativeSetLayer", "(JI)V", 420 (void*)nativeSetLayer }, 421 {"nativeSetPosition", "(JFF)V", 422 (void*)nativeSetPosition }, 423 {"nativeSetSize", "(JII)V", 424 (void*)nativeSetSize }, 425 {"nativeSetTransparentRegionHint", "(JLandroid/graphics/Region;)V", 426 (void*)nativeSetTransparentRegionHint }, 427 {"nativeSetAlpha", "(JF)V", 428 (void*)nativeSetAlpha }, 429 {"nativeSetMatrix", "(JFFFF)V", 430 (void*)nativeSetMatrix }, 431 {"nativeSetFlags", "(JII)V", 432 (void*)nativeSetFlags }, 433 {"nativeSetWindowCrop", "(JIIII)V", 434 (void*)nativeSetWindowCrop }, 435 {"nativeSetLayerStack", "(JI)V", 436 (void*)nativeSetLayerStack }, 437 {"nativeGetBuiltInDisplay", "(I)Landroid/os/IBinder;", 438 (void*)nativeGetBuiltInDisplay }, 439 {"nativeCreateDisplay", "(Ljava/lang/String;Z)Landroid/os/IBinder;", 440 (void*)nativeCreateDisplay }, 441 {"nativeDestroyDisplay", "(Landroid/os/IBinder;)V", 442 (void*)nativeDestroyDisplay }, 443 {"nativeSetDisplaySurface", "(Landroid/os/IBinder;J)V", 444 (void*)nativeSetDisplaySurface }, 445 {"nativeSetDisplayLayerStack", "(Landroid/os/IBinder;I)V", 446 (void*)nativeSetDisplayLayerStack }, 447 {"nativeSetDisplayProjection", "(Landroid/os/IBinder;IIIIIIIII)V", 448 (void*)nativeSetDisplayProjection }, 449 {"nativeGetDisplayInfo", "(Landroid/os/IBinder;Landroid/view/SurfaceControl$PhysicalDisplayInfo;)Z", 450 (void*)nativeGetDisplayInfo }, 451 {"nativeBlankDisplay", "(Landroid/os/IBinder;)V", 452 (void*)nativeBlankDisplay }, 453 {"nativeUnblankDisplay", "(Landroid/os/IBinder;)V", 454 (void*)nativeUnblankDisplay }, 455}; 456 457int register_android_view_SurfaceControl(JNIEnv* env) 458{ 459 int err = AndroidRuntime::registerNativeMethods(env, "android/view/SurfaceControl", 460 sSurfaceControlMethods, NELEM(sSurfaceControlMethods)); 461 462 jclass clazz = env->FindClass("android/view/SurfaceControl$PhysicalDisplayInfo"); 463 gPhysicalDisplayInfoClassInfo.width = env->GetFieldID(clazz, "width", "I"); 464 gPhysicalDisplayInfoClassInfo.height = env->GetFieldID(clazz, "height", "I"); 465 gPhysicalDisplayInfoClassInfo.refreshRate = env->GetFieldID(clazz, "refreshRate", "F"); 466 gPhysicalDisplayInfoClassInfo.density = env->GetFieldID(clazz, "density", "F"); 467 gPhysicalDisplayInfoClassInfo.xDpi = env->GetFieldID(clazz, "xDpi", "F"); 468 gPhysicalDisplayInfoClassInfo.yDpi = env->GetFieldID(clazz, "yDpi", "F"); 469 gPhysicalDisplayInfoClassInfo.secure = env->GetFieldID(clazz, "secure", "Z"); 470 return err; 471} 472 473}; 474