OSDN Git Service

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