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