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