android_view_SurfaceControl.cpp revision 550780745fa28ae9a87d02331841ca5ce4f9c763
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
43namespace android {
44
45static const char* const OutOfResourcesException =
46    "android/view/Surface$OutOfResourcesException";
47
48static 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
63static 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.
71void DeleteScreenshot(void* addr, void* context) {
72    SkASSERT(addr == ((ScreenshotClient*) context)->getPixels());
73    delete ((ScreenshotClient*) context);
74}
75
76static struct {
77    nsecs_t UNDEFINED_TIME_NANO;
78    jmethodID init;
79} gWindowContentFrameStatsClassInfo;
80
81static struct {
82    nsecs_t UNDEFINED_TIME_NANO;
83    jmethodID init;
84} gWindowAnimationFrameStatsClassInfo;
85
86// ----------------------------------------------------------------------------
87
88static 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
102static void nativeRelease(JNIEnv* env, jclass clazz, jlong nativeObject) {
103    sp<SurfaceControl> ctrl(reinterpret_cast<SurfaceControl *>(nativeObject));
104    ctrl->decStrong((void *)nativeCreate);
105}
106
107static 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
113static 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
184static 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
209static void nativeOpenTransaction(JNIEnv* env, jclass clazz) {
210    SurfaceComposerClient::openGlobalTransaction();
211}
212
213static void nativeCloseTransaction(JNIEnv* env, jclass clazz) {
214    SurfaceComposerClient::closeGlobalTransaction();
215}
216
217static void nativeSetAnimationTransaction(JNIEnv* env, jclass clazz) {
218    SurfaceComposerClient::setAnimationTransaction();
219}
220
221static 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
229static 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
237static 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
245static 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
253static 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
278static 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
286static 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
295static 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
305static 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
313static jobject nativeGetBuiltInDisplay(JNIEnv* env, jclass clazz, jint id) {
314    sp<IBinder> token(SurfaceComposerClient::getBuiltInDisplay(id));
315    return javaObjectForIBinder(env, token);
316}
317
318static 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
326static 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
332static 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
344static 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
352static 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
363static 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
370static 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
408static 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
414static 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
421static 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
429static 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
445static 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
516static 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
531static 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
576static 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
643int 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};
691