blob: 8141a00c5a35e8dd075eff58ea4dcdd843ed1352 [file] [log] [blame]
Mathias Agopian3866f0d2013-02-11 22:08:48 -08001/*
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>
Mathias Agopian0449a402013-03-01 23:01:51 -080030#include <android_runtime/android_view_Surface.h>
Mathias Agopian3866f0d2013-02-11 22:08:48 -080031#include <android_runtime/android_view_SurfaceSession.h>
32
33#include <gui/Surface.h>
34#include <gui/SurfaceComposerClient.h>
35
36#include <ui/DisplayInfo.h>
Svetoslav1376d602014-03-13 11:17:26 -070037#include <ui/FrameStats.h>
Mathias Agopian3866f0d2013-02-11 22:08:48 -080038#include <ui/Rect.h>
39#include <ui/Region.h>
40
41#include <utils/Log.h>
42
43#include <ScopedUtfChars.h>
44
45// ----------------------------------------------------------------------------
46
47namespace android {
48
49static const char* const OutOfResourcesException =
50 "android/view/Surface$OutOfResourcesException";
51
52static struct {
53 jfieldID width;
54 jfieldID height;
55 jfieldID refreshRate;
56 jfieldID density;
57 jfieldID xDpi;
58 jfieldID yDpi;
59 jfieldID secure;
60} gPhysicalDisplayInfoClassInfo;
61
Leon Scroggins46cb9bd2014-03-06 15:36:39 -050062// Implements SkMallocPixelRef::ReleaseProc, to delete the screenshot on unref.
63void DeleteScreenshot(void* addr, void* context) {
64 SkASSERT(addr == ((ScreenshotClient*) context)->getPixels());
65 delete ((ScreenshotClient*) context);
66}
Mathias Agopian3866f0d2013-02-11 22:08:48 -080067
Svetoslav1376d602014-03-13 11:17:26 -070068static struct {
69 nsecs_t UNDEFINED_TIME_NANO;
70 jmethodID init;
71} gWindowContentFrameStatsClassInfo;
72
73static struct {
74 nsecs_t UNDEFINED_TIME_NANO;
75 jmethodID init;
76} gWindowAnimationFrameStatsClassInfo;
77
Mathias Agopian3866f0d2013-02-11 22:08:48 -080078// ----------------------------------------------------------------------------
79
Ashok Bhat36bef0b2014-01-20 20:08:01 +000080static jlong nativeCreate(JNIEnv* env, jclass clazz, jobject sessionObj,
Mathias Agopian3866f0d2013-02-11 22:08:48 -080081 jstring nameStr, jint w, jint h, jint format, jint flags) {
82 ScopedUtfChars name(env, nameStr);
83 sp<SurfaceComposerClient> client(android_view_SurfaceSession_getClient(env, sessionObj));
84 sp<SurfaceControl> surface = client->createSurface(
85 String8(name.c_str()), w, h, format, flags);
86 if (surface == NULL) {
87 jniThrowException(env, OutOfResourcesException, NULL);
88 return 0;
89 }
Mathias Agopianb1d90c82013-03-06 17:45:42 -080090 surface->incStrong((void *)nativeCreate);
Ashok Bhat36bef0b2014-01-20 20:08:01 +000091 return reinterpret_cast<jlong>(surface.get());
Mathias Agopian3866f0d2013-02-11 22:08:48 -080092}
93
Ashok Bhat36bef0b2014-01-20 20:08:01 +000094static void nativeRelease(JNIEnv* env, jclass clazz, jlong nativeObject) {
Mathias Agopian3866f0d2013-02-11 22:08:48 -080095 sp<SurfaceControl> ctrl(reinterpret_cast<SurfaceControl *>(nativeObject));
Mathias Agopianb1d90c82013-03-06 17:45:42 -080096 ctrl->decStrong((void *)nativeCreate);
Mathias Agopian3866f0d2013-02-11 22:08:48 -080097}
98
Ashok Bhat36bef0b2014-01-20 20:08:01 +000099static void nativeDestroy(JNIEnv* env, jclass clazz, jlong nativeObject) {
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800100 sp<SurfaceControl> ctrl(reinterpret_cast<SurfaceControl *>(nativeObject));
101 ctrl->clear();
Mathias Agopianb1d90c82013-03-06 17:45:42 -0800102 ctrl->decStrong((void *)nativeCreate);
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800103}
104
Mathias Agopian0449a402013-03-01 23:01:51 -0800105static jobject nativeScreenshotBitmap(JNIEnv* env, jclass clazz, jobject displayTokenObj,
Dan Stoza16ec12a2014-02-14 15:06:55 -0800106 jint width, jint height, jint minLayer, jint maxLayer, bool allLayers,
107 bool useIdentityTransform) {
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800108 sp<IBinder> displayToken = ibinderForJavaObject(env, displayTokenObj);
109 if (displayToken == NULL) {
110 return NULL;
111 }
112
Derek Sollenbergerb644a3b2014-01-17 15:45:10 -0500113 ScreenshotClient* screenshot = new ScreenshotClient();
114 status_t res;
115 if (width > 0 && height > 0) {
116 if (allLayers) {
117 res = screenshot->update(displayToken, width, height, useIdentityTransform);
118 } else {
119 res = screenshot->update(displayToken, width, height, minLayer, maxLayer,
120 useIdentityTransform);
121 }
122 } else {
123 res = screenshot->update(displayToken, useIdentityTransform);
124 }
125 if (res != NO_ERROR) {
126 delete screenshot;
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800127 return NULL;
128 }
129
Derek Sollenbergerb644a3b2014-01-17 15:45:10 -0500130 SkImageInfo screenshotInfo;
131 screenshotInfo.fWidth = screenshot->getWidth();
132 screenshotInfo.fHeight = screenshot->getHeight();
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800133
Derek Sollenbergerb644a3b2014-01-17 15:45:10 -0500134 switch (screenshot->getFormat()) {
135 case PIXEL_FORMAT_RGBX_8888: {
136 screenshotInfo.fColorType = kRGBA_8888_SkColorType;
137 screenshotInfo.fAlphaType = kIgnore_SkAlphaType;
138 break;
139 }
140 case PIXEL_FORMAT_RGBA_8888: {
141 screenshotInfo.fColorType = kRGBA_8888_SkColorType;
142 screenshotInfo.fAlphaType = kPremul_SkAlphaType;
143 break;
144 }
145 case PIXEL_FORMAT_RGB_565: {
146 screenshotInfo.fColorType = kRGB_565_SkColorType;
147 screenshotInfo.fAlphaType = kIgnore_SkAlphaType;
148 break;
149 }
150 default: {
151 delete screenshot;
152 return NULL;
153 }
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800154 }
155
Derek Sollenbergerb644a3b2014-01-17 15:45:10 -0500156 const ssize_t rowBytes =
157 screenshot->getStride() * android::bytesPerPixel(screenshot->getFormat());
158
159 SkBitmap* bitmap = new SkBitmap();
160 bitmap->setConfig(screenshotInfo, (size_t)rowBytes);
161 if (screenshotInfo.fWidth > 0 && screenshotInfo.fHeight > 0) {
Leon Scroggins46cb9bd2014-03-06 15:36:39 -0500162 // takes ownership of ScreenshotClient
163 SkMallocPixelRef* pixels = SkMallocPixelRef::NewWithProc(screenshotInfo,
164 (size_t) rowBytes, NULL, (void*) screenshot->getPixels(), &DeleteScreenshot,
165 (void*) screenshot);
166 pixels->setImmutable();
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800167 bitmap->setPixelRef(pixels)->unref();
168 bitmap->lockPixels();
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800169 }
170
Chris Craik1abf5d62013-08-16 12:47:03 -0700171 return GraphicsJNI::createBitmap(env, bitmap,
172 GraphicsJNI::kBitmapCreateFlag_Premultiplied, NULL);
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800173}
174
Mathias Agopian0449a402013-03-01 23:01:51 -0800175static void nativeScreenshot(JNIEnv* env, jclass clazz,
176 jobject displayTokenObj, jobject surfaceObj,
Dan Stoza16ec12a2014-02-14 15:06:55 -0800177 jint width, jint height, jint minLayer, jint maxLayer, bool allLayers,
178 bool useIdentityTransform) {
Mathias Agopian0449a402013-03-01 23:01:51 -0800179 sp<IBinder> displayToken = ibinderForJavaObject(env, displayTokenObj);
180 if (displayToken != NULL) {
181 sp<Surface> consumer = android_view_Surface_getSurface(env, surfaceObj);
182 if (consumer != NULL) {
183 if (allLayers) {
184 minLayer = 0;
185 maxLayer = -1;
186 }
187 ScreenshotClient::capture(
188 displayToken, consumer->getIGraphicBufferProducer(),
Dan Stoza16ec12a2014-02-14 15:06:55 -0800189 width, height, uint32_t(minLayer), uint32_t(maxLayer),
190 useIdentityTransform);
Mathias Agopian0449a402013-03-01 23:01:51 -0800191 }
192 }
193}
194
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800195static void nativeOpenTransaction(JNIEnv* env, jclass clazz) {
196 SurfaceComposerClient::openGlobalTransaction();
197}
198
199static void nativeCloseTransaction(JNIEnv* env, jclass clazz) {
200 SurfaceComposerClient::closeGlobalTransaction();
201}
202
203static void nativeSetAnimationTransaction(JNIEnv* env, jclass clazz) {
204 SurfaceComposerClient::setAnimationTransaction();
205}
206
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000207static void nativeSetLayer(JNIEnv* env, jclass clazz, jlong nativeObject, jint zorder) {
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800208 SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
209 status_t err = ctrl->setLayer(zorder);
210 if (err < 0 && err != NO_INIT) {
211 doThrowIAE(env);
212 }
213}
214
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000215static void nativeSetPosition(JNIEnv* env, jclass clazz, jlong nativeObject, jfloat x, jfloat y) {
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800216 SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
217 status_t err = ctrl->setPosition(x, y);
218 if (err < 0 && err != NO_INIT) {
219 doThrowIAE(env);
220 }
221}
222
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000223static void nativeSetSize(JNIEnv* env, jclass clazz, jlong nativeObject, jint w, jint h) {
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800224 SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
225 status_t err = ctrl->setSize(w, h);
226 if (err < 0 && err != NO_INIT) {
227 doThrowIAE(env);
228 }
229}
230
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000231static void nativeSetFlags(JNIEnv* env, jclass clazz, jlong nativeObject, jint flags, jint mask) {
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800232 SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
233 status_t err = ctrl->setFlags(flags, mask);
234 if (err < 0 && err != NO_INIT) {
235 doThrowIAE(env);
236 }
237}
238
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000239static void nativeSetTransparentRegionHint(JNIEnv* env, jclass clazz, jlong nativeObject, jobject regionObj) {
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800240 SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
241 SkRegion* region = android_graphics_Region_getSkRegion(env, regionObj);
242 if (!region) {
243 doThrowIAE(env);
244 return;
245 }
246
247 const SkIRect& b(region->getBounds());
248 Region reg(Rect(b.fLeft, b.fTop, b.fRight, b.fBottom));
249 if (region->isComplex()) {
250 SkRegion::Iterator it(*region);
251 while (!it.done()) {
252 const SkIRect& r(it.rect());
253 reg.addRectUnchecked(r.fLeft, r.fTop, r.fRight, r.fBottom);
254 it.next();
255 }
256 }
257
258 status_t err = ctrl->setTransparentRegionHint(reg);
259 if (err < 0 && err != NO_INIT) {
260 doThrowIAE(env);
261 }
262}
263
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000264static void nativeSetAlpha(JNIEnv* env, jclass clazz, jlong nativeObject, jfloat alpha) {
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800265 SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
266 status_t err = ctrl->setAlpha(alpha);
267 if (err < 0 && err != NO_INIT) {
268 doThrowIAE(env);
269 }
270}
271
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000272static void nativeSetMatrix(JNIEnv* env, jclass clazz, jlong nativeObject,
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800273 jfloat dsdx, jfloat dtdx, jfloat dsdy, jfloat dtdy) {
274 SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
275 status_t err = ctrl->setMatrix(dsdx, dtdx, dsdy, dtdy);
276 if (err < 0 && err != NO_INIT) {
277 doThrowIAE(env);
278 }
279}
280
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000281static void nativeSetWindowCrop(JNIEnv* env, jclass clazz, jlong nativeObject,
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800282 jint l, jint t, jint r, jint b) {
283 SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
284 Rect crop(l, t, r, b);
285 status_t err = ctrl->setCrop(crop);
286 if (err < 0 && err != NO_INIT) {
287 doThrowIAE(env);
288 }
289}
290
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000291static void nativeSetLayerStack(JNIEnv* env, jclass clazz, jlong nativeObject, jint layerStack) {
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800292 SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
293 status_t err = ctrl->setLayerStack(layerStack);
294 if (err < 0 && err != NO_INIT) {
295 doThrowIAE(env);
296 }
297}
298
299static jobject nativeGetBuiltInDisplay(JNIEnv* env, jclass clazz, jint id) {
300 sp<IBinder> token(SurfaceComposerClient::getBuiltInDisplay(id));
301 return javaObjectForIBinder(env, token);
302}
303
304static jobject nativeCreateDisplay(JNIEnv* env, jclass clazz, jstring nameObj,
305 jboolean secure) {
306 ScopedUtfChars name(env, nameObj);
307 sp<IBinder> token(SurfaceComposerClient::createDisplay(
308 String8(name.c_str()), bool(secure)));
309 return javaObjectForIBinder(env, token);
310}
311
Jesse Hall6a6bc212013-08-08 12:15:03 -0700312static void nativeDestroyDisplay(JNIEnv* env, jclass clazz, jobject tokenObj) {
313 sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
314 if (token == NULL) return;
315 SurfaceComposerClient::destroyDisplay(token);
316}
317
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800318static void nativeSetDisplaySurface(JNIEnv* env, jclass clazz,
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000319 jobject tokenObj, jlong nativeSurfaceObject) {
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800320 sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
321 if (token == NULL) return;
Mathias Agopianffddc9b2013-02-25 15:56:31 -0800322 sp<IGraphicBufferProducer> bufferProducer;
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800323 sp<Surface> sur(reinterpret_cast<Surface *>(nativeSurfaceObject));
Mathias Agopianffddc9b2013-02-25 15:56:31 -0800324 if (sur != NULL) {
325 bufferProducer = sur->getIGraphicBufferProducer();
326 }
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800327 SurfaceComposerClient::setDisplaySurface(token, bufferProducer);
328}
329
330static void nativeSetDisplayLayerStack(JNIEnv* env, jclass clazz,
331 jobject tokenObj, jint layerStack) {
332 sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
333 if (token == NULL) return;
334
335 SurfaceComposerClient::setDisplayLayerStack(token, layerStack);
336}
337
338static void nativeSetDisplayProjection(JNIEnv* env, jclass clazz,
339 jobject tokenObj, jint orientation,
340 jint layerStackRect_left, jint layerStackRect_top, jint layerStackRect_right, jint layerStackRect_bottom,
341 jint displayRect_left, jint displayRect_top, jint displayRect_right, jint displayRect_bottom) {
342 sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
343 if (token == NULL) return;
344 Rect layerStackRect(layerStackRect_left, layerStackRect_top, layerStackRect_right, layerStackRect_bottom);
345 Rect displayRect(displayRect_left, displayRect_top, displayRect_right, displayRect_bottom);
346 SurfaceComposerClient::setDisplayProjection(token, orientation, layerStackRect, displayRect);
347}
348
349static jboolean nativeGetDisplayInfo(JNIEnv* env, jclass clazz,
350 jobject tokenObj, jobject infoObj) {
351 sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
352 if (token == NULL) return JNI_FALSE;
353
354 DisplayInfo info;
355 if (SurfaceComposerClient::getDisplayInfo(token, &info)) {
356 return JNI_FALSE;
357 }
358
359 env->SetIntField(infoObj, gPhysicalDisplayInfoClassInfo.width, info.w);
360 env->SetIntField(infoObj, gPhysicalDisplayInfoClassInfo.height, info.h);
361 env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.refreshRate, info.fps);
362 env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.density, info.density);
363 env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.xDpi, info.xdpi);
364 env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.yDpi, info.ydpi);
365 env->SetBooleanField(infoObj, gPhysicalDisplayInfoClassInfo.secure, info.secure);
366 return JNI_TRUE;
367}
368
369static void nativeBlankDisplay(JNIEnv* env, jclass clazz, jobject tokenObj) {
370 sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
371 if (token == NULL) return;
372
373 ALOGD_IF_SLOW(100, "Excessive delay in blankDisplay() while turning screen off");
374 SurfaceComposerClient::blankDisplay(token);
375}
376
377static void nativeUnblankDisplay(JNIEnv* env, jclass clazz, jobject tokenObj) {
378 sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
379 if (token == NULL) return;
380
381 ALOGD_IF_SLOW(100, "Excessive delay in unblankDisplay() while turning screen on");
382 SurfaceComposerClient::unblankDisplay(token);
383}
384
Svetoslav1376d602014-03-13 11:17:26 -0700385static jboolean nativeClearContentFrameStats(JNIEnv* env, jclass clazz, jlong nativeObject) {
386 SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
387 status_t err = ctrl->clearLayerFrameStats();
388
389 if (err < 0 && err != NO_INIT) {
390 doThrowIAE(env);
391 }
392
393 // The other end is not ready, just report we failed.
394 if (err == NO_INIT) {
395 return JNI_FALSE;
396 }
397
398 return JNI_TRUE;
399}
400
401static jboolean nativeGetContentFrameStats(JNIEnv* env, jclass clazz, jlong nativeObject,
402 jobject outStats) {
403 FrameStats stats;
404
405 SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
406 status_t err = ctrl->getLayerFrameStats(&stats);
407 if (err < 0 && err != NO_INIT) {
408 doThrowIAE(env);
409 }
410
411 // The other end is not ready, fine just return empty stats.
412 if (err == NO_INIT) {
413 return JNI_FALSE;
414 }
415
416 jlong refreshPeriodNano = static_cast<jlong>(stats.refreshPeriodNano);
417 size_t frameCount = stats.desiredPresentTimesNano.size();
418
419 jlongArray postedTimesNanoDst = env->NewLongArray(frameCount);
420 if (postedTimesNanoDst == NULL) {
421 return JNI_FALSE;
422 }
423
424 jlongArray presentedTimesNanoDst = env->NewLongArray(frameCount);
425 if (presentedTimesNanoDst == NULL) {
426 return JNI_FALSE;
427 }
428
429 jlongArray readyTimesNanoDst = env->NewLongArray(frameCount);
430 if (readyTimesNanoDst == NULL) {
431 return JNI_FALSE;
432 }
433
434 nsecs_t postedTimesNanoSrc[frameCount];
435 nsecs_t presentedTimesNanoSrc[frameCount];
436 nsecs_t readyTimesNanoSrc[frameCount];
437
438 for (size_t i = 0; i < frameCount; i++) {
439 nsecs_t postedTimeNano = stats.desiredPresentTimesNano[i];
440 if (postedTimeNano == INT64_MAX) {
441 postedTimeNano = gWindowContentFrameStatsClassInfo.UNDEFINED_TIME_NANO;
442 }
443 postedTimesNanoSrc[i] = postedTimeNano;
444
445 nsecs_t presentedTimeNano = stats.actualPresentTimesNano[i];
446 if (presentedTimeNano == INT64_MAX) {
447 presentedTimeNano = gWindowContentFrameStatsClassInfo.UNDEFINED_TIME_NANO;
448 }
449 presentedTimesNanoSrc[i] = presentedTimeNano;
450
451 nsecs_t readyTimeNano = stats.frameReadyTimesNano[i];
452 if (readyTimeNano == INT64_MAX) {
453 readyTimeNano = gWindowContentFrameStatsClassInfo.UNDEFINED_TIME_NANO;
454 }
455 readyTimesNanoSrc[i] = readyTimeNano;
456 }
457
458 env->SetLongArrayRegion(postedTimesNanoDst, 0, frameCount, postedTimesNanoSrc);
459 env->SetLongArrayRegion(presentedTimesNanoDst, 0, frameCount, presentedTimesNanoSrc);
460 env->SetLongArrayRegion(readyTimesNanoDst, 0, frameCount, readyTimesNanoSrc);
461
462 env->CallVoidMethod(outStats, gWindowContentFrameStatsClassInfo.init, refreshPeriodNano,
463 postedTimesNanoDst, presentedTimesNanoDst, readyTimesNanoDst);
464
465 if (env->ExceptionCheck()) {
466 return JNI_FALSE;
467 }
468
469 return JNI_TRUE;
470}
471
472static jboolean nativeClearAnimationFrameStats(JNIEnv* env, jclass clazz) {
473 status_t err = SurfaceComposerClient::clearAnimationFrameStats();
474
475 if (err < 0 && err != NO_INIT) {
476 doThrowIAE(env);
477 }
478
479 // The other end is not ready, just report we failed.
480 if (err == NO_INIT) {
481 return JNI_FALSE;
482 }
483
484 return JNI_TRUE;
485}
486
487static jboolean nativeGetAnimationFrameStats(JNIEnv* env, jclass clazz, jobject outStats) {
488 FrameStats stats;
489
490 status_t err = SurfaceComposerClient::getAnimationFrameStats(&stats);
491 if (err < 0 && err != NO_INIT) {
492 doThrowIAE(env);
493 }
494
495 // The other end is not ready, fine just return empty stats.
496 if (err == NO_INIT) {
497 return JNI_FALSE;
498 }
499
500 jlong refreshPeriodNano = static_cast<jlong>(stats.refreshPeriodNano);
501 size_t frameCount = stats.desiredPresentTimesNano.size();
502
503 jlongArray presentedTimesNanoDst = env->NewLongArray(frameCount);
504 if (presentedTimesNanoDst == NULL) {
505 return JNI_FALSE;
506 }
507
508 nsecs_t presentedTimesNanoSrc[frameCount];
509
510 for (size_t i = 0; i < frameCount; i++) {
511 nsecs_t presentedTimeNano = stats.desiredPresentTimesNano[i];
512 if (presentedTimeNano == INT64_MAX) {
513 presentedTimeNano = gWindowContentFrameStatsClassInfo.UNDEFINED_TIME_NANO;
514 }
515 presentedTimesNanoSrc[i] = presentedTimeNano;
516 }
517
518 env->SetLongArrayRegion(presentedTimesNanoDst, 0, frameCount, presentedTimesNanoSrc);
519
520 env->CallVoidMethod(outStats, gWindowAnimationFrameStatsClassInfo.init, refreshPeriodNano,
521 presentedTimesNanoDst);
522
523 if (env->ExceptionCheck()) {
524 return JNI_FALSE;
525 }
526
527 return JNI_TRUE;
528}
529
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800530// ----------------------------------------------------------------------------
531
532static JNINativeMethod sSurfaceControlMethods[] = {
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000533 {"nativeCreate", "(Landroid/view/SurfaceSession;Ljava/lang/String;IIII)J",
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800534 (void*)nativeCreate },
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000535 {"nativeRelease", "(J)V",
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800536 (void*)nativeRelease },
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000537 {"nativeDestroy", "(J)V",
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800538 (void*)nativeDestroy },
Dan Stoza16ec12a2014-02-14 15:06:55 -0800539 {"nativeScreenshot", "(Landroid/os/IBinder;IIIIZZ)Landroid/graphics/Bitmap;",
Mathias Agopian0449a402013-03-01 23:01:51 -0800540 (void*)nativeScreenshotBitmap },
Dan Stoza16ec12a2014-02-14 15:06:55 -0800541 {"nativeScreenshot", "(Landroid/os/IBinder;Landroid/view/Surface;IIIIZZ)V",
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800542 (void*)nativeScreenshot },
543 {"nativeOpenTransaction", "()V",
544 (void*)nativeOpenTransaction },
545 {"nativeCloseTransaction", "()V",
546 (void*)nativeCloseTransaction },
547 {"nativeSetAnimationTransaction", "()V",
548 (void*)nativeSetAnimationTransaction },
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000549 {"nativeSetLayer", "(JI)V",
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800550 (void*)nativeSetLayer },
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000551 {"nativeSetPosition", "(JFF)V",
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800552 (void*)nativeSetPosition },
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000553 {"nativeSetSize", "(JII)V",
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800554 (void*)nativeSetSize },
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000555 {"nativeSetTransparentRegionHint", "(JLandroid/graphics/Region;)V",
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800556 (void*)nativeSetTransparentRegionHint },
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000557 {"nativeSetAlpha", "(JF)V",
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800558 (void*)nativeSetAlpha },
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000559 {"nativeSetMatrix", "(JFFFF)V",
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800560 (void*)nativeSetMatrix },
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000561 {"nativeSetFlags", "(JII)V",
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800562 (void*)nativeSetFlags },
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000563 {"nativeSetWindowCrop", "(JIIII)V",
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800564 (void*)nativeSetWindowCrop },
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000565 {"nativeSetLayerStack", "(JI)V",
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800566 (void*)nativeSetLayerStack },
567 {"nativeGetBuiltInDisplay", "(I)Landroid/os/IBinder;",
568 (void*)nativeGetBuiltInDisplay },
569 {"nativeCreateDisplay", "(Ljava/lang/String;Z)Landroid/os/IBinder;",
570 (void*)nativeCreateDisplay },
Jesse Hall6a6bc212013-08-08 12:15:03 -0700571 {"nativeDestroyDisplay", "(Landroid/os/IBinder;)V",
572 (void*)nativeDestroyDisplay },
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000573 {"nativeSetDisplaySurface", "(Landroid/os/IBinder;J)V",
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800574 (void*)nativeSetDisplaySurface },
575 {"nativeSetDisplayLayerStack", "(Landroid/os/IBinder;I)V",
576 (void*)nativeSetDisplayLayerStack },
577 {"nativeSetDisplayProjection", "(Landroid/os/IBinder;IIIIIIIII)V",
578 (void*)nativeSetDisplayProjection },
579 {"nativeGetDisplayInfo", "(Landroid/os/IBinder;Landroid/view/SurfaceControl$PhysicalDisplayInfo;)Z",
580 (void*)nativeGetDisplayInfo },
581 {"nativeBlankDisplay", "(Landroid/os/IBinder;)V",
582 (void*)nativeBlankDisplay },
583 {"nativeUnblankDisplay", "(Landroid/os/IBinder;)V",
584 (void*)nativeUnblankDisplay },
Svetoslav1376d602014-03-13 11:17:26 -0700585 {"nativeClearContentFrameStats", "(J)Z",
586 (void*)nativeClearContentFrameStats },
587 {"nativeGetContentFrameStats", "(JLandroid/view/WindowContentFrameStats;)Z",
588 (void*)nativeGetContentFrameStats },
589 {"nativeClearAnimationFrameStats", "()Z",
590 (void*)nativeClearAnimationFrameStats },
591 {"nativeGetAnimationFrameStats", "(Landroid/view/WindowAnimationFrameStats;)Z",
592 (void*)nativeGetAnimationFrameStats },
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800593};
594
595int register_android_view_SurfaceControl(JNIEnv* env)
596{
597 int err = AndroidRuntime::registerNativeMethods(env, "android/view/SurfaceControl",
598 sSurfaceControlMethods, NELEM(sSurfaceControlMethods));
599
600 jclass clazz = env->FindClass("android/view/SurfaceControl$PhysicalDisplayInfo");
601 gPhysicalDisplayInfoClassInfo.width = env->GetFieldID(clazz, "width", "I");
602 gPhysicalDisplayInfoClassInfo.height = env->GetFieldID(clazz, "height", "I");
603 gPhysicalDisplayInfoClassInfo.refreshRate = env->GetFieldID(clazz, "refreshRate", "F");
604 gPhysicalDisplayInfoClassInfo.density = env->GetFieldID(clazz, "density", "F");
605 gPhysicalDisplayInfoClassInfo.xDpi = env->GetFieldID(clazz, "xDpi", "F");
606 gPhysicalDisplayInfoClassInfo.yDpi = env->GetFieldID(clazz, "yDpi", "F");
607 gPhysicalDisplayInfoClassInfo.secure = env->GetFieldID(clazz, "secure", "Z");
Svetoslav1376d602014-03-13 11:17:26 -0700608
609 jclass frameStatsClazz = env->FindClass("android/view/FrameStats");
610 jfieldID undefined_time_nano_field = env->GetStaticFieldID(frameStatsClazz, "UNDEFINED_TIME_NANO", "J");
611 nsecs_t undefined_time_nano = env->GetStaticLongField(frameStatsClazz, undefined_time_nano_field);
612
613 jclass contFrameStatsClazz = env->FindClass("android/view/WindowContentFrameStats");
614 gWindowContentFrameStatsClassInfo.init = env->GetMethodID(contFrameStatsClazz, "init", "(J[J[J[J)V");
615 gWindowContentFrameStatsClassInfo.UNDEFINED_TIME_NANO = undefined_time_nano;
616
617 jclass animFrameStatsClazz = env->FindClass("android/view/WindowAnimationFrameStats");
618 gWindowAnimationFrameStatsClassInfo.init = env->GetMethodID(animFrameStatsClazz, "init", "(J[J)V");
619 gWindowAnimationFrameStatsClassInfo.UNDEFINED_TIME_NANO = undefined_time_nano;
620
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800621 return err;
622}
623
624};