OSDN Git Service

Merge six commits from master-skia to master
[android-x86/frameworks-base.git] / core / jni / android_view_SurfaceControl.cpp
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 "android_os_Parcel.h"
20 #include "android_util_Binder.h"
21 #include "android/graphics/Bitmap.h"
22 #include "android/graphics/GraphicsJNI.h"
23 #include "android/graphics/Region.h"
24 #include "core_jni_helpers.h"
25
26 #include <JNIHelp.h>
27 #include <ScopedUtfChars.h>
28 #include <android_runtime/android_view_Surface.h>
29 #include <android_runtime/android_view_SurfaceSession.h>
30 #include <gui/Surface.h>
31 #include <gui/SurfaceComposerClient.h>
32 #include <jni.h>
33 #include <memory>
34 #include <stdio.h>
35 #include <ui/DisplayInfo.h>
36 #include <ui/FrameStats.h>
37 #include <ui/Rect.h>
38 #include <ui/Region.h>
39 #include <utils/Log.h>
40
41 // ----------------------------------------------------------------------------
42
43 namespace android {
44
45 static const char* const OutOfResourcesException =
46     "android/view/Surface$OutOfResourcesException";
47
48 static struct {
49     jclass clazz;
50     jmethodID ctor;
51     jfieldID width;
52     jfieldID height;
53     jfieldID refreshRate;
54     jfieldID density;
55     jfieldID xDpi;
56     jfieldID yDpi;
57     jfieldID secure;
58     jfieldID appVsyncOffsetNanos;
59     jfieldID presentationDeadlineNanos;
60     jfieldID colorTransform;
61 } gPhysicalDisplayInfoClassInfo;
62
63 static struct {
64     jfieldID bottom;
65     jfieldID left;
66     jfieldID right;
67     jfieldID top;
68 } gRectClassInfo;
69
70 // Implements SkMallocPixelRef::ReleaseProc, to delete the screenshot on unref.
71 void DeleteScreenshot(void* addr, void* context) {
72     SkASSERT(addr == ((ScreenshotClient*) context)->getPixels());
73     delete ((ScreenshotClient*) context);
74 }
75
76 static struct {
77     nsecs_t UNDEFINED_TIME_NANO;
78     jmethodID init;
79 } gWindowContentFrameStatsClassInfo;
80
81 static struct {
82     nsecs_t UNDEFINED_TIME_NANO;
83     jmethodID init;
84 } gWindowAnimationFrameStatsClassInfo;
85
86 // ----------------------------------------------------------------------------
87
88 static jlong nativeCreate(JNIEnv* env, jclass clazz, jobject sessionObj,
89         jstring nameStr, jint w, jint h, jint format, jint flags) {
90     ScopedUtfChars name(env, nameStr);
91     sp<SurfaceComposerClient> client(android_view_SurfaceSession_getClient(env, sessionObj));
92     sp<SurfaceControl> surface = client->createSurface(
93             String8(name.c_str()), w, h, format, flags);
94     if (surface == NULL) {
95         jniThrowException(env, OutOfResourcesException, NULL);
96         return 0;
97     }
98     surface->incStrong((void *)nativeCreate);
99     return reinterpret_cast<jlong>(surface.get());
100 }
101
102 static void nativeRelease(JNIEnv* env, jclass clazz, jlong nativeObject) {
103     sp<SurfaceControl> ctrl(reinterpret_cast<SurfaceControl *>(nativeObject));
104     ctrl->decStrong((void *)nativeCreate);
105 }
106
107 static void nativeDestroy(JNIEnv* env, jclass clazz, jlong nativeObject) {
108     sp<SurfaceControl> ctrl(reinterpret_cast<SurfaceControl *>(nativeObject));
109     ctrl->clear();
110     ctrl->decStrong((void *)nativeCreate);
111 }
112
113 static jobject nativeScreenshotBitmap(JNIEnv* env, jclass clazz,
114         jobject displayTokenObj, jobject sourceCropObj, jint width, jint height,
115         jint minLayer, jint maxLayer, bool allLayers, bool useIdentityTransform,
116         int rotation) {
117     sp<IBinder> displayToken = ibinderForJavaObject(env, displayTokenObj);
118     if (displayToken == NULL) {
119         return NULL;
120     }
121
122     int left = env->GetIntField(sourceCropObj, gRectClassInfo.left);
123     int top = env->GetIntField(sourceCropObj, gRectClassInfo.top);
124     int right = env->GetIntField(sourceCropObj, gRectClassInfo.right);
125     int bottom = env->GetIntField(sourceCropObj, gRectClassInfo.bottom);
126     Rect sourceCrop(left, top, right, bottom);
127
128     std::unique_ptr<ScreenshotClient> screenshot(new ScreenshotClient());
129     status_t res;
130     if (allLayers) {
131         minLayer = 0;
132         maxLayer = -1;
133     }
134
135     res = screenshot->update(displayToken, sourceCrop, width, height,
136         minLayer, maxLayer, useIdentityTransform, static_cast<uint32_t>(rotation));
137     if (res != NO_ERROR) {
138         return NULL;
139     }
140
141     SkColorType ct;
142     SkAlphaType at;
143     switch (screenshot->getFormat()) {
144         case PIXEL_FORMAT_RGBX_8888: {
145             ct = kRGBA_8888_SkColorType;
146             at = kOpaque_SkAlphaType;
147             break;
148         }
149         case PIXEL_FORMAT_RGBA_8888: {
150             ct = kRGBA_8888_SkColorType;
151             at = kPremul_SkAlphaType;
152             break;
153         }
154         case PIXEL_FORMAT_RGB_565: {
155             ct = kRGB_565_SkColorType;
156             at = kOpaque_SkAlphaType;
157             break;
158         }
159         default: {
160             return NULL;
161         }
162     }
163     SkImageInfo screenshotInfo = SkImageInfo::Make(screenshot->getWidth(),
164                                                    screenshot->getHeight(),
165                                                    ct, at);
166
167     const size_t rowBytes =
168             screenshot->getStride() * android::bytesPerPixel(screenshot->getFormat());
169
170     if (!screenshotInfo.width() || !screenshotInfo.height()) {
171         return NULL;
172     }
173
174     Bitmap* bitmap = new Bitmap(
175             (void*) screenshot->getPixels(), (void*) screenshot.get(), DeleteScreenshot,
176             screenshotInfo, rowBytes, nullptr);
177     screenshot.release();
178     bitmap->peekAtPixelRef()->setImmutable();
179
180     return GraphicsJNI::createBitmap(env, bitmap,
181             GraphicsJNI::kBitmapCreateFlag_Premultiplied, NULL);
182 }
183
184 static void nativeScreenshot(JNIEnv* env, jclass clazz, jobject displayTokenObj,
185         jobject surfaceObj, jobject sourceCropObj, jint width, jint height,
186         jint minLayer, jint maxLayer, bool allLayers, bool useIdentityTransform) {
187     sp<IBinder> displayToken = ibinderForJavaObject(env, displayTokenObj);
188     if (displayToken != NULL) {
189         sp<Surface> consumer = android_view_Surface_getSurface(env, surfaceObj);
190         if (consumer != NULL) {
191             int left = env->GetIntField(sourceCropObj, gRectClassInfo.left);
192             int top = env->GetIntField(sourceCropObj, gRectClassInfo.top);
193             int right = env->GetIntField(sourceCropObj, gRectClassInfo.right);
194             int bottom = env->GetIntField(sourceCropObj, gRectClassInfo.bottom);
195             Rect sourceCrop(left, top, right, bottom);
196
197             if (allLayers) {
198                 minLayer = 0;
199                 maxLayer = -1;
200             }
201             ScreenshotClient::capture(displayToken,
202                     consumer->getIGraphicBufferProducer(), sourceCrop,
203                     width, height, uint32_t(minLayer), uint32_t(maxLayer),
204                     useIdentityTransform);
205         }
206     }
207 }
208
209 static void nativeOpenTransaction(JNIEnv* env, jclass clazz) {
210     SurfaceComposerClient::openGlobalTransaction();
211 }
212
213 static void nativeCloseTransaction(JNIEnv* env, jclass clazz) {
214     SurfaceComposerClient::closeGlobalTransaction();
215 }
216
217 static void nativeSetAnimationTransaction(JNIEnv* env, jclass clazz) {
218     SurfaceComposerClient::setAnimationTransaction();
219 }
220
221 static void nativeSetLayer(JNIEnv* env, jclass clazz, jlong nativeObject, jint zorder) {
222     SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
223     status_t err = ctrl->setLayer(zorder);
224     if (err < 0 && err != NO_INIT) {
225         doThrowIAE(env);
226     }
227 }
228
229 static void nativeSetPosition(JNIEnv* env, jclass clazz, jlong nativeObject, jfloat x, jfloat y) {
230     SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
231     status_t err = ctrl->setPosition(x, y);
232     if (err < 0 && err != NO_INIT) {
233         doThrowIAE(env);
234     }
235 }
236
237 static void nativeSetSize(JNIEnv* env, jclass clazz, jlong nativeObject, jint w, jint h) {
238     SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
239     status_t err = ctrl->setSize(w, h);
240     if (err < 0 && err != NO_INIT) {
241         doThrowIAE(env);
242     }
243 }
244
245 static void nativeSetFlags(JNIEnv* env, jclass clazz, jlong nativeObject, jint flags, jint mask) {
246     SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
247     status_t err = ctrl->setFlags(flags, mask);
248     if (err < 0 && err != NO_INIT) {
249         doThrowIAE(env);
250     }
251 }
252
253 static void nativeSetTransparentRegionHint(JNIEnv* env, jclass clazz, jlong nativeObject, jobject regionObj) {
254     SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
255     SkRegion* region = android_graphics_Region_getSkRegion(env, regionObj);
256     if (!region) {
257         doThrowIAE(env);
258         return;
259     }
260
261     const SkIRect& b(region->getBounds());
262     Region reg(Rect(b.fLeft, b.fTop, b.fRight, b.fBottom));
263     if (region->isComplex()) {
264         SkRegion::Iterator it(*region);
265         while (!it.done()) {
266             const SkIRect& r(it.rect());
267             reg.addRectUnchecked(r.fLeft, r.fTop, r.fRight, r.fBottom);
268             it.next();
269         }
270     }
271
272     status_t err = ctrl->setTransparentRegionHint(reg);
273     if (err < 0 && err != NO_INIT) {
274         doThrowIAE(env);
275     }
276 }
277
278 static void nativeSetAlpha(JNIEnv* env, jclass clazz, jlong nativeObject, jfloat alpha) {
279     SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
280     status_t err = ctrl->setAlpha(alpha);
281     if (err < 0 && err != NO_INIT) {
282         doThrowIAE(env);
283     }
284 }
285
286 static void nativeSetMatrix(JNIEnv* env, jclass clazz, jlong nativeObject,
287         jfloat dsdx, jfloat dtdx, jfloat dsdy, jfloat dtdy) {
288     SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
289     status_t err = ctrl->setMatrix(dsdx, dtdx, dsdy, dtdy);
290     if (err < 0 && err != NO_INIT) {
291         doThrowIAE(env);
292     }
293 }
294
295 static void nativeSetWindowCrop(JNIEnv* env, jclass clazz, jlong nativeObject,
296         jint l, jint t, jint r, jint b) {
297     SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
298     Rect crop(l, t, r, b);
299     status_t err = ctrl->setCrop(crop);
300     if (err < 0 && err != NO_INIT) {
301         doThrowIAE(env);
302     }
303 }
304
305 static void nativeSetLayerStack(JNIEnv* env, jclass clazz, jlong nativeObject, jint layerStack) {
306     SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
307     status_t err = ctrl->setLayerStack(layerStack);
308     if (err < 0 && err != NO_INIT) {
309         doThrowIAE(env);
310     }
311 }
312
313 static jobject nativeGetBuiltInDisplay(JNIEnv* env, jclass clazz, jint id) {
314     sp<IBinder> token(SurfaceComposerClient::getBuiltInDisplay(id));
315     return javaObjectForIBinder(env, token);
316 }
317
318 static jobject nativeCreateDisplay(JNIEnv* env, jclass clazz, jstring nameObj,
319         jboolean secure) {
320     ScopedUtfChars name(env, nameObj);
321     sp<IBinder> token(SurfaceComposerClient::createDisplay(
322             String8(name.c_str()), bool(secure)));
323     return javaObjectForIBinder(env, token);
324 }
325
326 static void nativeDestroyDisplay(JNIEnv* env, jclass clazz, jobject tokenObj) {
327     sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
328     if (token == NULL) return;
329     SurfaceComposerClient::destroyDisplay(token);
330 }
331
332 static void nativeSetDisplaySurface(JNIEnv* env, jclass clazz,
333         jobject tokenObj, jlong nativeSurfaceObject) {
334     sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
335     if (token == NULL) return;
336     sp<IGraphicBufferProducer> bufferProducer;
337     sp<Surface> sur(reinterpret_cast<Surface *>(nativeSurfaceObject));
338     if (sur != NULL) {
339         bufferProducer = sur->getIGraphicBufferProducer();
340     }
341     SurfaceComposerClient::setDisplaySurface(token, bufferProducer);
342 }
343
344 static void nativeSetDisplayLayerStack(JNIEnv* env, jclass clazz,
345         jobject tokenObj, jint layerStack) {
346     sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
347     if (token == NULL) return;
348
349     SurfaceComposerClient::setDisplayLayerStack(token, layerStack);
350 }
351
352 static void nativeSetDisplayProjection(JNIEnv* env, jclass clazz,
353         jobject tokenObj, jint orientation,
354         jint layerStackRect_left, jint layerStackRect_top, jint layerStackRect_right, jint layerStackRect_bottom,
355         jint displayRect_left, jint displayRect_top, jint displayRect_right, jint displayRect_bottom) {
356     sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
357     if (token == NULL) return;
358     Rect layerStackRect(layerStackRect_left, layerStackRect_top, layerStackRect_right, layerStackRect_bottom);
359     Rect displayRect(displayRect_left, displayRect_top, displayRect_right, displayRect_bottom);
360     SurfaceComposerClient::setDisplayProjection(token, orientation, layerStackRect, displayRect);
361 }
362
363 static void nativeSetDisplaySize(JNIEnv* env, jclass clazz,
364         jobject tokenObj, jint width, jint height) {
365     sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
366     if (token == NULL) return;
367     SurfaceComposerClient::setDisplaySize(token, width, height);
368 }
369
370 static jobjectArray nativeGetDisplayConfigs(JNIEnv* env, jclass clazz,
371         jobject tokenObj) {
372     sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
373     if (token == NULL) return NULL;
374
375     Vector<DisplayInfo> configs;
376     if (SurfaceComposerClient::getDisplayConfigs(token, &configs) != NO_ERROR ||
377             configs.size() == 0) {
378         return NULL;
379     }
380
381     jobjectArray configArray = env->NewObjectArray(configs.size(),
382             gPhysicalDisplayInfoClassInfo.clazz, NULL);
383
384     for (size_t c = 0; c < configs.size(); ++c) {
385         const DisplayInfo& info = configs[c];
386         jobject infoObj = env->NewObject(gPhysicalDisplayInfoClassInfo.clazz,
387                 gPhysicalDisplayInfoClassInfo.ctor);
388         env->SetIntField(infoObj, gPhysicalDisplayInfoClassInfo.width, info.w);
389         env->SetIntField(infoObj, gPhysicalDisplayInfoClassInfo.height, info.h);
390         env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.refreshRate, info.fps);
391         env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.density, info.density);
392         env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.xDpi, info.xdpi);
393         env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.yDpi, info.ydpi);
394         env->SetBooleanField(infoObj, gPhysicalDisplayInfoClassInfo.secure, info.secure);
395         env->SetLongField(infoObj, gPhysicalDisplayInfoClassInfo.appVsyncOffsetNanos,
396                 info.appVsyncOffset);
397         env->SetLongField(infoObj, gPhysicalDisplayInfoClassInfo.presentationDeadlineNanos,
398                 info.presentationDeadline);
399         env->SetIntField(infoObj, gPhysicalDisplayInfoClassInfo.colorTransform,
400                 info.colorTransform);
401         env->SetObjectArrayElement(configArray, static_cast<jsize>(c), infoObj);
402         env->DeleteLocalRef(infoObj);
403     }
404
405     return configArray;
406 }
407
408 static jint nativeGetActiveConfig(JNIEnv* env, jclass clazz, jobject tokenObj) {
409     sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
410     if (token == NULL) return -1;
411     return static_cast<jint>(SurfaceComposerClient::getActiveConfig(token));
412 }
413
414 static jboolean nativeSetActiveConfig(JNIEnv* env, jclass clazz, jobject tokenObj, jint id) {
415     sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
416     if (token == NULL) return JNI_FALSE;
417     status_t err = SurfaceComposerClient::setActiveConfig(token, static_cast<int>(id));
418     return err == NO_ERROR ? JNI_TRUE : JNI_FALSE;
419 }
420
421 static void nativeSetDisplayPowerMode(JNIEnv* env, jclass clazz, jobject tokenObj, jint mode) {
422     sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
423     if (token == NULL) return;
424
425     ALOGD_IF_SLOW(100, "Excessive delay in setPowerMode()");
426     SurfaceComposerClient::setDisplayPowerMode(token, mode);
427 }
428
429 static jboolean nativeClearContentFrameStats(JNIEnv* env, jclass clazz, jlong nativeObject) {
430     SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
431     status_t err = ctrl->clearLayerFrameStats();
432
433     if (err < 0 && err != NO_INIT) {
434         doThrowIAE(env);
435     }
436
437     // The other end is not ready, just report we failed.
438     if (err == NO_INIT) {
439         return JNI_FALSE;
440     }
441
442     return JNI_TRUE;
443 }
444
445 static jboolean nativeGetContentFrameStats(JNIEnv* env, jclass clazz, jlong nativeObject,
446     jobject outStats) {
447     FrameStats stats;
448
449     SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
450     status_t err = ctrl->getLayerFrameStats(&stats);
451     if (err < 0 && err != NO_INIT) {
452         doThrowIAE(env);
453     }
454
455     // The other end is not ready, fine just return empty stats.
456     if (err == NO_INIT) {
457         return JNI_FALSE;
458     }
459
460     jlong refreshPeriodNano = static_cast<jlong>(stats.refreshPeriodNano);
461     size_t frameCount = stats.desiredPresentTimesNano.size();
462
463     jlongArray postedTimesNanoDst = env->NewLongArray(frameCount);
464     if (postedTimesNanoDst == NULL) {
465         return JNI_FALSE;
466     }
467
468     jlongArray presentedTimesNanoDst = env->NewLongArray(frameCount);
469     if (presentedTimesNanoDst == NULL) {
470         return JNI_FALSE;
471     }
472
473     jlongArray readyTimesNanoDst = env->NewLongArray(frameCount);
474     if (readyTimesNanoDst == NULL) {
475         return JNI_FALSE;
476     }
477
478     nsecs_t postedTimesNanoSrc[frameCount];
479     nsecs_t presentedTimesNanoSrc[frameCount];
480     nsecs_t readyTimesNanoSrc[frameCount];
481
482     for (size_t i = 0; i < frameCount; i++) {
483         nsecs_t postedTimeNano = stats.desiredPresentTimesNano[i];
484         if (postedTimeNano == INT64_MAX) {
485             postedTimeNano = gWindowContentFrameStatsClassInfo.UNDEFINED_TIME_NANO;
486         }
487         postedTimesNanoSrc[i] = postedTimeNano;
488
489         nsecs_t presentedTimeNano = stats.actualPresentTimesNano[i];
490         if (presentedTimeNano == INT64_MAX) {
491             presentedTimeNano = gWindowContentFrameStatsClassInfo.UNDEFINED_TIME_NANO;
492         }
493         presentedTimesNanoSrc[i] = presentedTimeNano;
494
495         nsecs_t readyTimeNano = stats.frameReadyTimesNano[i];
496         if (readyTimeNano == INT64_MAX) {
497             readyTimeNano = gWindowContentFrameStatsClassInfo.UNDEFINED_TIME_NANO;
498         }
499         readyTimesNanoSrc[i] = readyTimeNano;
500     }
501
502     env->SetLongArrayRegion(postedTimesNanoDst, 0, frameCount, postedTimesNanoSrc);
503     env->SetLongArrayRegion(presentedTimesNanoDst, 0, frameCount, presentedTimesNanoSrc);
504     env->SetLongArrayRegion(readyTimesNanoDst, 0, frameCount, readyTimesNanoSrc);
505
506     env->CallVoidMethod(outStats, gWindowContentFrameStatsClassInfo.init, refreshPeriodNano,
507             postedTimesNanoDst, presentedTimesNanoDst, readyTimesNanoDst);
508
509     if (env->ExceptionCheck()) {
510         return JNI_FALSE;
511     }
512
513     return JNI_TRUE;
514 }
515
516 static jboolean nativeClearAnimationFrameStats(JNIEnv* env, jclass clazz) {
517     status_t err = SurfaceComposerClient::clearAnimationFrameStats();
518
519     if (err < 0 && err != NO_INIT) {
520         doThrowIAE(env);
521     }
522
523     // The other end is not ready, just report we failed.
524     if (err == NO_INIT) {
525         return JNI_FALSE;
526     }
527
528     return JNI_TRUE;
529 }
530
531 static jboolean nativeGetAnimationFrameStats(JNIEnv* env, jclass clazz, jobject outStats) {
532     FrameStats stats;
533
534     status_t err = SurfaceComposerClient::getAnimationFrameStats(&stats);
535     if (err < 0 && err != NO_INIT) {
536         doThrowIAE(env);
537     }
538
539     // The other end is not ready, fine just return empty stats.
540     if (err == NO_INIT) {
541         return JNI_FALSE;
542     }
543
544     jlong refreshPeriodNano = static_cast<jlong>(stats.refreshPeriodNano);
545     size_t frameCount = stats.desiredPresentTimesNano.size();
546
547     jlongArray presentedTimesNanoDst = env->NewLongArray(frameCount);
548     if (presentedTimesNanoDst == NULL) {
549         return JNI_FALSE;
550     }
551
552     nsecs_t presentedTimesNanoSrc[frameCount];
553
554     for (size_t i = 0; i < frameCount; i++) {
555         nsecs_t presentedTimeNano = stats.actualPresentTimesNano[i];
556         if (presentedTimeNano == INT64_MAX) {
557             presentedTimeNano = gWindowContentFrameStatsClassInfo.UNDEFINED_TIME_NANO;
558         }
559         presentedTimesNanoSrc[i] = presentedTimeNano;
560     }
561
562     env->SetLongArrayRegion(presentedTimesNanoDst, 0, frameCount, presentedTimesNanoSrc);
563
564     env->CallVoidMethod(outStats, gWindowAnimationFrameStatsClassInfo.init, refreshPeriodNano,
565             presentedTimesNanoDst);
566
567     if (env->ExceptionCheck()) {
568         return JNI_FALSE;
569     }
570
571     return JNI_TRUE;
572 }
573
574 // ----------------------------------------------------------------------------
575
576 static const JNINativeMethod sSurfaceControlMethods[] = {
577     {"nativeCreate", "(Landroid/view/SurfaceSession;Ljava/lang/String;IIII)J",
578             (void*)nativeCreate },
579     {"nativeRelease", "(J)V",
580             (void*)nativeRelease },
581     {"nativeDestroy", "(J)V",
582             (void*)nativeDestroy },
583     {"nativeScreenshot", "(Landroid/os/IBinder;Landroid/graphics/Rect;IIIIZZI)Landroid/graphics/Bitmap;",
584             (void*)nativeScreenshotBitmap },
585     {"nativeScreenshot", "(Landroid/os/IBinder;Landroid/view/Surface;Landroid/graphics/Rect;IIIIZZ)V",
586             (void*)nativeScreenshot },
587     {"nativeOpenTransaction", "()V",
588             (void*)nativeOpenTransaction },
589     {"nativeCloseTransaction", "()V",
590             (void*)nativeCloseTransaction },
591     {"nativeSetAnimationTransaction", "()V",
592             (void*)nativeSetAnimationTransaction },
593     {"nativeSetLayer", "(JI)V",
594             (void*)nativeSetLayer },
595     {"nativeSetPosition", "(JFF)V",
596             (void*)nativeSetPosition },
597     {"nativeSetSize", "(JII)V",
598             (void*)nativeSetSize },
599     {"nativeSetTransparentRegionHint", "(JLandroid/graphics/Region;)V",
600             (void*)nativeSetTransparentRegionHint },
601     {"nativeSetAlpha", "(JF)V",
602             (void*)nativeSetAlpha },
603     {"nativeSetMatrix", "(JFFFF)V",
604             (void*)nativeSetMatrix },
605     {"nativeSetFlags", "(JII)V",
606             (void*)nativeSetFlags },
607     {"nativeSetWindowCrop", "(JIIII)V",
608             (void*)nativeSetWindowCrop },
609     {"nativeSetLayerStack", "(JI)V",
610             (void*)nativeSetLayerStack },
611     {"nativeGetBuiltInDisplay", "(I)Landroid/os/IBinder;",
612             (void*)nativeGetBuiltInDisplay },
613     {"nativeCreateDisplay", "(Ljava/lang/String;Z)Landroid/os/IBinder;",
614             (void*)nativeCreateDisplay },
615     {"nativeDestroyDisplay", "(Landroid/os/IBinder;)V",
616             (void*)nativeDestroyDisplay },
617     {"nativeSetDisplaySurface", "(Landroid/os/IBinder;J)V",
618             (void*)nativeSetDisplaySurface },
619     {"nativeSetDisplayLayerStack", "(Landroid/os/IBinder;I)V",
620             (void*)nativeSetDisplayLayerStack },
621     {"nativeSetDisplayProjection", "(Landroid/os/IBinder;IIIIIIIII)V",
622             (void*)nativeSetDisplayProjection },
623     {"nativeSetDisplaySize", "(Landroid/os/IBinder;II)V",
624             (void*)nativeSetDisplaySize },
625     {"nativeGetDisplayConfigs", "(Landroid/os/IBinder;)[Landroid/view/SurfaceControl$PhysicalDisplayInfo;",
626             (void*)nativeGetDisplayConfigs },
627     {"nativeGetActiveConfig", "(Landroid/os/IBinder;)I",
628             (void*)nativeGetActiveConfig },
629     {"nativeSetActiveConfig", "(Landroid/os/IBinder;I)Z",
630             (void*)nativeSetActiveConfig },
631     {"nativeClearContentFrameStats", "(J)Z",
632             (void*)nativeClearContentFrameStats },
633     {"nativeGetContentFrameStats", "(JLandroid/view/WindowContentFrameStats;)Z",
634             (void*)nativeGetContentFrameStats },
635     {"nativeClearAnimationFrameStats", "()Z",
636             (void*)nativeClearAnimationFrameStats },
637     {"nativeGetAnimationFrameStats", "(Landroid/view/WindowAnimationFrameStats;)Z",
638             (void*)nativeGetAnimationFrameStats },
639     {"nativeSetDisplayPowerMode", "(Landroid/os/IBinder;I)V",
640             (void*)nativeSetDisplayPowerMode },
641 };
642
643 int register_android_view_SurfaceControl(JNIEnv* env)
644 {
645     int err = RegisterMethodsOrDie(env, "android/view/SurfaceControl",
646             sSurfaceControlMethods, NELEM(sSurfaceControlMethods));
647
648     jclass clazz = FindClassOrDie(env, "android/view/SurfaceControl$PhysicalDisplayInfo");
649     gPhysicalDisplayInfoClassInfo.clazz = MakeGlobalRefOrDie(env, clazz);
650     gPhysicalDisplayInfoClassInfo.ctor = GetMethodIDOrDie(env,
651             gPhysicalDisplayInfoClassInfo.clazz, "<init>", "()V");
652     gPhysicalDisplayInfoClassInfo.width =       GetFieldIDOrDie(env, clazz, "width", "I");
653     gPhysicalDisplayInfoClassInfo.height =      GetFieldIDOrDie(env, clazz, "height", "I");
654     gPhysicalDisplayInfoClassInfo.refreshRate = GetFieldIDOrDie(env, clazz, "refreshRate", "F");
655     gPhysicalDisplayInfoClassInfo.density =     GetFieldIDOrDie(env, clazz, "density", "F");
656     gPhysicalDisplayInfoClassInfo.xDpi =        GetFieldIDOrDie(env, clazz, "xDpi", "F");
657     gPhysicalDisplayInfoClassInfo.yDpi =        GetFieldIDOrDie(env, clazz, "yDpi", "F");
658     gPhysicalDisplayInfoClassInfo.secure =      GetFieldIDOrDie(env, clazz, "secure", "Z");
659     gPhysicalDisplayInfoClassInfo.appVsyncOffsetNanos = GetFieldIDOrDie(env,
660             clazz, "appVsyncOffsetNanos", "J");
661     gPhysicalDisplayInfoClassInfo.presentationDeadlineNanos = GetFieldIDOrDie(env,
662             clazz, "presentationDeadlineNanos", "J");
663     gPhysicalDisplayInfoClassInfo.colorTransform = GetFieldIDOrDie(env, clazz,
664             "colorTransform", "I");
665
666     jclass rectClazz = FindClassOrDie(env, "android/graphics/Rect");
667     gRectClassInfo.bottom = GetFieldIDOrDie(env, rectClazz, "bottom", "I");
668     gRectClassInfo.left =   GetFieldIDOrDie(env, rectClazz, "left", "I");
669     gRectClassInfo.right =  GetFieldIDOrDie(env, rectClazz, "right", "I");
670     gRectClassInfo.top =    GetFieldIDOrDie(env, rectClazz, "top", "I");
671
672     jclass frameStatsClazz = FindClassOrDie(env, "android/view/FrameStats");
673     jfieldID undefined_time_nano_field = GetStaticFieldIDOrDie(env,
674             frameStatsClazz, "UNDEFINED_TIME_NANO", "J");
675     nsecs_t undefined_time_nano = env->GetStaticLongField(frameStatsClazz, undefined_time_nano_field);
676
677     jclass contFrameStatsClazz = FindClassOrDie(env, "android/view/WindowContentFrameStats");
678     gWindowContentFrameStatsClassInfo.init = GetMethodIDOrDie(env,
679             contFrameStatsClazz, "init", "(J[J[J[J)V");
680     gWindowContentFrameStatsClassInfo.UNDEFINED_TIME_NANO = undefined_time_nano;
681
682     jclass animFrameStatsClazz = FindClassOrDie(env, "android/view/WindowAnimationFrameStats");
683     gWindowAnimationFrameStatsClassInfo.init =  GetMethodIDOrDie(env,
684             animFrameStatsClazz, "init", "(J[J)V");
685     gWindowAnimationFrameStatsClassInfo.UNDEFINED_TIME_NANO = undefined_time_nano;
686
687     return err;
688 }
689
690 };