• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 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 "Surface"
18 
19 #include <stdio.h>
20 
21 #include "jni.h"
22 #include <nativehelper/JNIHelp.h>
23 #include "core_jni_helpers.h"
24 
25 #include <android/graphics/canvas.h>
26 #include <android_runtime/android_hardware_HardwareBuffer.h>
27 #include <android_runtime/android_graphics_SurfaceTexture.h>
28 #include <android_runtime/android_view_Surface.h>
29 #include <android_runtime/Log.h>
30 #include <private/android/AHardwareBufferHelpers.h>
31 
32 #include "android_os_Parcel.h"
33 #include <binder/Parcel.h>
34 
35 #include <gui/BLASTBufferQueue.h>
36 #include <gui/Surface.h>
37 #include <gui/SurfaceControl.h>
38 #include <gui/view/Surface.h>
39 
40 #include <ui/GraphicBuffer.h>
41 #include <ui/Rect.h>
42 #include <ui/Region.h>
43 
44 #include <utils/misc.h>
45 #include <utils/Log.h>
46 
47 #include <nativehelper/ScopedUtfChars.h>
48 
49 // ----------------------------------------------------------------------------
50 
51 namespace android {
52 
53 static const char* const IllegalArgumentException = "java/lang/IllegalArgumentException";
54 static const char* const OutOfResourcesException = "android/view/Surface$OutOfResourcesException";
55 
56 static struct {
57     jclass clazz;
58     jfieldID mNativeObject;
59     jfieldID mLock;
60     jmethodID ctor;
61 } gSurfaceClassInfo;
62 
63 static struct {
64     jfieldID left;
65     jfieldID top;
66     jfieldID right;
67     jfieldID bottom;
68 } gRectClassInfo;
69 
70 class JNamedColorSpace {
71 public:
72     // ColorSpace.Named.SRGB.ordinal() = 0;
73     static constexpr jint SRGB = 0;
74 
75     // ColorSpace.Named.DISPLAY_P3.ordinal() = 7;
76     static constexpr jint DISPLAY_P3 = 7;
77 };
78 
fromNamedColorSpaceValueToDataspace(const jint colorSpace)79 constexpr ui::Dataspace fromNamedColorSpaceValueToDataspace(const jint colorSpace) {
80     switch (colorSpace) {
81         case JNamedColorSpace::DISPLAY_P3:
82             return ui::Dataspace::DISPLAY_P3;
83         default:
84             return ui::Dataspace::V0_SRGB;
85     }
86 }
87 
88 // ----------------------------------------------------------------------------
89 
90 // this is just a pointer we use to pass to inc/decStrong
91 static const void *sRefBaseOwner;
92 
android_view_Surface_isInstanceOf(JNIEnv * env,jobject obj)93 bool android_view_Surface_isInstanceOf(JNIEnv* env, jobject obj) {
94     return env->IsInstanceOf(obj, gSurfaceClassInfo.clazz);
95 }
96 
android_view_Surface_getNativeWindow(JNIEnv * env,jobject surfaceObj)97 sp<ANativeWindow> android_view_Surface_getNativeWindow(JNIEnv* env, jobject surfaceObj) {
98     return android_view_Surface_getSurface(env, surfaceObj);
99 }
100 
android_view_Surface_getSurface(JNIEnv * env,jobject surfaceObj)101 sp<Surface> android_view_Surface_getSurface(JNIEnv* env, jobject surfaceObj) {
102     sp<Surface> sur;
103     jobject lock = env->GetObjectField(surfaceObj,
104             gSurfaceClassInfo.mLock);
105     if (env->MonitorEnter(lock) == JNI_OK) {
106         sur = reinterpret_cast<Surface *>(
107                 env->GetLongField(surfaceObj, gSurfaceClassInfo.mNativeObject));
108         env->MonitorExit(lock);
109     }
110     env->DeleteLocalRef(lock);
111     return sur;
112 }
113 
android_view_Surface_createFromSurface(JNIEnv * env,const sp<Surface> & surface)114 jobject android_view_Surface_createFromSurface(JNIEnv* env, const sp<Surface>& surface) {
115     jobject surfaceObj = env->NewObject(gSurfaceClassInfo.clazz,
116             gSurfaceClassInfo.ctor, (jlong)surface.get());
117     if (surfaceObj == NULL) {
118         if (env->ExceptionCheck()) {
119             ALOGE("Could not create instance of Surface from IGraphicBufferProducer.");
120             LOGE_EX(env);
121             env->ExceptionClear();
122         }
123         return NULL;
124     }
125     surface->incStrong(&sRefBaseOwner);
126     return surfaceObj;
127 }
128 
android_view_Surface_createFromIGraphicBufferProducer(JNIEnv * env,const sp<IGraphicBufferProducer> & bufferProducer)129 jobject android_view_Surface_createFromIGraphicBufferProducer(JNIEnv* env,
130         const sp<IGraphicBufferProducer>& bufferProducer) {
131     if (bufferProducer == NULL) {
132         return NULL;
133     }
134 
135     sp<Surface> surface(new Surface(bufferProducer, true));
136     return android_view_Surface_createFromSurface(env, surface);
137 }
138 
139 // ----------------------------------------------------------------------------
140 
isSurfaceValid(const sp<Surface> & sur)141 static inline bool isSurfaceValid(const sp<Surface>& sur) {
142     return Surface::isValid(sur);
143 }
144 
145 // ----------------------------------------------------------------------------
146 
nativeCreateFromSurfaceTexture(JNIEnv * env,jclass clazz,jobject surfaceTextureObj)147 static jlong nativeCreateFromSurfaceTexture(JNIEnv* env, jclass clazz,
148         jobject surfaceTextureObj) {
149     sp<IGraphicBufferProducer> producer(SurfaceTexture_getProducer(env, surfaceTextureObj));
150     if (producer == NULL) {
151         jniThrowException(env, IllegalArgumentException,
152                 "SurfaceTexture has already been released");
153         return 0;
154     }
155 
156     sp<Surface> surface(new Surface(producer, true));
157     if (surface == NULL) {
158         jniThrowException(env, OutOfResourcesException, NULL);
159         return 0;
160     }
161 
162     surface->incStrong(&sRefBaseOwner);
163     return jlong(surface.get());
164 }
165 
nativeRelease(JNIEnv * env,jclass clazz,jlong nativeObject)166 static void nativeRelease(JNIEnv* env, jclass clazz, jlong nativeObject) {
167     sp<Surface> sur(reinterpret_cast<Surface *>(nativeObject));
168     sur->decStrong(&sRefBaseOwner);
169 }
170 
nativeIsValid(JNIEnv * env,jclass clazz,jlong nativeObject)171 static jboolean nativeIsValid(JNIEnv* env, jclass clazz, jlong nativeObject) {
172     sp<Surface> sur(reinterpret_cast<Surface *>(nativeObject));
173     return isSurfaceValid(sur) ? JNI_TRUE : JNI_FALSE;
174 }
175 
nativeIsConsumerRunningBehind(JNIEnv * env,jclass clazz,jlong nativeObject)176 static jboolean nativeIsConsumerRunningBehind(JNIEnv* env, jclass clazz, jlong nativeObject) {
177     sp<Surface> sur(reinterpret_cast<Surface *>(nativeObject));
178     if (!isSurfaceValid(sur)) {
179         jniThrowException(env, IllegalArgumentException, NULL);
180         return JNI_FALSE;
181     }
182     int value = 0;
183     ANativeWindow* anw = static_cast<ANativeWindow*>(sur.get());
184     anw->query(anw, NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND, &value);
185     return value;
186 }
187 
nativeLockCanvas(JNIEnv * env,jclass clazz,jlong nativeObject,jobject canvasObj,jobject dirtyRectObj)188 static jlong nativeLockCanvas(JNIEnv* env, jclass clazz,
189         jlong nativeObject, jobject canvasObj, jobject dirtyRectObj) {
190     sp<Surface> surface(reinterpret_cast<Surface *>(nativeObject));
191 
192     if (!isSurfaceValid(surface)) {
193         jniThrowException(env, IllegalArgumentException, NULL);
194         return 0;
195     }
196 
197     if (!ACanvas_isSupportedPixelFormat(ANativeWindow_getFormat(surface.get()))) {
198         native_window_set_buffers_format(surface.get(), PIXEL_FORMAT_RGBA_8888);
199     }
200 
201     Rect dirtyRect(Rect::EMPTY_RECT);
202     Rect* dirtyRectPtr = NULL;
203 
204     if (dirtyRectObj) {
205         dirtyRect.left   = env->GetIntField(dirtyRectObj, gRectClassInfo.left);
206         dirtyRect.top    = env->GetIntField(dirtyRectObj, gRectClassInfo.top);
207         dirtyRect.right  = env->GetIntField(dirtyRectObj, gRectClassInfo.right);
208         dirtyRect.bottom = env->GetIntField(dirtyRectObj, gRectClassInfo.bottom);
209         dirtyRectPtr = &dirtyRect;
210     }
211 
212     ANativeWindow_Buffer buffer;
213     status_t err = surface->lock(&buffer, dirtyRectPtr);
214     if (err < 0) {
215         const char* const exception = (err == NO_MEMORY) ?
216                 OutOfResourcesException : IllegalArgumentException;
217         jniThrowException(env, exception, NULL);
218         return 0;
219     }
220 
221     graphics::Canvas canvas(env, canvasObj);
222     canvas.setBuffer(&buffer, static_cast<int32_t>(surface->getBuffersDataSpace()));
223 
224     if (dirtyRectPtr) {
225         canvas.clipRect({dirtyRect.left, dirtyRect.top, dirtyRect.right, dirtyRect.bottom});
226     }
227 
228     if (dirtyRectObj) {
229         env->SetIntField(dirtyRectObj, gRectClassInfo.left,   dirtyRect.left);
230         env->SetIntField(dirtyRectObj, gRectClassInfo.top,    dirtyRect.top);
231         env->SetIntField(dirtyRectObj, gRectClassInfo.right,  dirtyRect.right);
232         env->SetIntField(dirtyRectObj, gRectClassInfo.bottom, dirtyRect.bottom);
233     }
234 
235     // Create another reference to the surface and return it.  This reference
236     // should be passed to nativeUnlockCanvasAndPost in place of mNativeObject,
237     // because the latter could be replaced while the surface is locked.
238     sp<Surface> lockedSurface(surface);
239     lockedSurface->incStrong(&sRefBaseOwner);
240     return (jlong) lockedSurface.get();
241 }
242 
nativeUnlockCanvasAndPost(JNIEnv * env,jclass clazz,jlong nativeObject,jobject canvasObj)243 static void nativeUnlockCanvasAndPost(JNIEnv* env, jclass clazz,
244         jlong nativeObject, jobject canvasObj) {
245     sp<Surface> surface(reinterpret_cast<Surface *>(nativeObject));
246     if (!isSurfaceValid(surface)) {
247         return;
248     }
249 
250     // detach the canvas from the surface
251     graphics::Canvas canvas(env, canvasObj);
252     canvas.setBuffer(nullptr, ADATASPACE_UNKNOWN);
253 
254     // unlock surface
255     status_t err = surface->unlockAndPost();
256     if (err < 0) {
257         jniThrowException(env, IllegalArgumentException, NULL);
258     }
259 }
260 
nativeAllocateBuffers(JNIEnv *,jclass,jlong nativeObject)261 static void nativeAllocateBuffers(JNIEnv* /* env */ , jclass /* clazz */,
262         jlong nativeObject) {
263     sp<Surface> surface(reinterpret_cast<Surface *>(nativeObject));
264     if (!isSurfaceValid(surface)) {
265         return;
266     }
267 
268     surface->allocateBuffers();
269 }
270 
271 // ----------------------------------------------------------------------------
272 
nativeCreateFromSurfaceControl(JNIEnv * env,jclass clazz,jlong surfaceControlNativeObj)273 static jlong nativeCreateFromSurfaceControl(JNIEnv* env, jclass clazz,
274         jlong surfaceControlNativeObj) {
275     sp<SurfaceControl> ctrl(reinterpret_cast<SurfaceControl *>(surfaceControlNativeObj));
276     sp<Surface> surface(ctrl->createSurface());
277     if (surface != NULL) {
278         surface->incStrong(&sRefBaseOwner);
279     }
280     return reinterpret_cast<jlong>(surface.get());
281 }
282 
nativeGetFromSurfaceControl(JNIEnv * env,jclass clazz,jlong nativeObject,jlong surfaceControlNativeObj)283 static jlong nativeGetFromSurfaceControl(JNIEnv* env, jclass clazz,
284         jlong nativeObject,
285         jlong surfaceControlNativeObj) {
286     Surface* self(reinterpret_cast<Surface *>(nativeObject));
287     sp<SurfaceControl> ctrl(reinterpret_cast<SurfaceControl *>(surfaceControlNativeObj));
288 
289     // If the underlying IGBP's are the same, we don't need to do anything.
290     if (self != nullptr &&
291             IInterface::asBinder(self->getIGraphicBufferProducer()) ==
292             IInterface::asBinder(ctrl->getIGraphicBufferProducer())) {
293         return nativeObject;
294     }
295 
296     sp<Surface> surface(ctrl->getSurface());
297     if (surface != NULL) {
298         surface->incStrong(&sRefBaseOwner);
299     }
300 
301     return reinterpret_cast<jlong>(surface.get());
302 }
303 
nativeGetFromBlastBufferQueue(JNIEnv * env,jclass clazz,jlong nativeObject,jlong blastBufferQueueNativeObj)304 static jlong nativeGetFromBlastBufferQueue(JNIEnv* env, jclass clazz, jlong nativeObject,
305                                            jlong blastBufferQueueNativeObj) {
306     Surface* self(reinterpret_cast<Surface*>(nativeObject));
307     sp<BLASTBufferQueue> queue = reinterpret_cast<BLASTBufferQueue*>(blastBufferQueueNativeObj);
308     const sp<IGraphicBufferProducer>& bufferProducer = queue->getIGraphicBufferProducer();
309     // If the underlying IGBP's are the same, we don't need to do anything.
310     if (self != nullptr &&
311         IInterface::asBinder(self->getIGraphicBufferProducer()) ==
312                 IInterface::asBinder(bufferProducer)) {
313         return nativeObject;
314     }
315 
316     sp<Surface> surface = queue->getSurface(true /* includeSurfaceControlHandle */);
317     if (surface != NULL) {
318         surface->incStrong(&sRefBaseOwner);
319     }
320 
321     return reinterpret_cast<jlong>(surface.get());
322 }
323 
nativeReadFromParcel(JNIEnv * env,jclass clazz,jlong nativeObject,jobject parcelObj)324 static jlong nativeReadFromParcel(JNIEnv* env, jclass clazz,
325         jlong nativeObject, jobject parcelObj) {
326     Parcel* parcel = parcelForJavaObject(env, parcelObj);
327     if (parcel == NULL) {
328         jniThrowNullPointerException(env, NULL);
329         return 0;
330     }
331 
332     android::view::Surface surfaceShim;
333 
334     // Calling code in Surface.java has already read the name of the Surface
335     // from the Parcel
336     surfaceShim.readFromParcel(parcel, /*nameAlreadyRead*/true);
337 
338     sp<Surface> self(reinterpret_cast<Surface *>(nativeObject));
339 
340     // update the Surface only if the underlying IGraphicBufferProducer
341     // has changed.
342     if (self != nullptr
343             && (IInterface::asBinder(self->getIGraphicBufferProducer()) ==
344                     IInterface::asBinder(surfaceShim.graphicBufferProducer))) {
345         // same IGraphicBufferProducer, return ourselves
346         return jlong(self.get());
347     }
348 
349     sp<Surface> sur;
350     if (surfaceShim.graphicBufferProducer != nullptr) {
351         // we have a new IGraphicBufferProducer, create a new Surface for it
352         sur = new Surface(surfaceShim.graphicBufferProducer, true,
353                           surfaceShim.surfaceControlHandle);
354         // and keep a reference before passing to java
355         sur->incStrong(&sRefBaseOwner);
356     }
357 
358     if (self != NULL) {
359         // and loose the java reference to ourselves
360         self->decStrong(&sRefBaseOwner);
361     }
362 
363     return jlong(sur.get());
364 }
365 
nativeWriteToParcel(JNIEnv * env,jclass clazz,jlong nativeObject,jobject parcelObj)366 static void nativeWriteToParcel(JNIEnv* env, jclass clazz,
367         jlong nativeObject, jobject parcelObj) {
368     Parcel* parcel = parcelForJavaObject(env, parcelObj);
369     if (parcel == NULL) {
370         jniThrowNullPointerException(env, NULL);
371         return;
372     }
373     sp<Surface> self(reinterpret_cast<Surface *>(nativeObject));
374     android::view::Surface surfaceShim;
375     if (self != nullptr) {
376         surfaceShim.graphicBufferProducer = self->getIGraphicBufferProducer();
377         surfaceShim.surfaceControlHandle = self->getSurfaceControlHandle();
378     }
379     // Calling code in Surface.java has already written the name of the Surface
380     // to the Parcel
381     surfaceShim.writeToParcel(parcel, /*nameAlreadyWritten*/true);
382 }
383 
nativeGetWidth(JNIEnv * env,jclass clazz,jlong nativeObject)384 static jint nativeGetWidth(JNIEnv* env, jclass clazz, jlong nativeObject) {
385     Surface* surface = reinterpret_cast<Surface*>(nativeObject);
386     ANativeWindow* anw = static_cast<ANativeWindow*>(surface);
387     int value = 0;
388     anw->query(anw, NATIVE_WINDOW_WIDTH, &value);
389     return value;
390 }
391 
nativeGetHeight(JNIEnv * env,jclass clazz,jlong nativeObject)392 static jint nativeGetHeight(JNIEnv* env, jclass clazz, jlong nativeObject) {
393     Surface* surface = reinterpret_cast<Surface*>(nativeObject);
394     ANativeWindow* anw = static_cast<ANativeWindow*>(surface);
395     int value = 0;
396     anw->query(anw, NATIVE_WINDOW_HEIGHT, &value);
397     return value;
398 }
399 
nativeGetNextFrameNumber(JNIEnv * env,jclass clazz,jlong nativeObject)400 static jlong nativeGetNextFrameNumber(JNIEnv *env, jclass clazz, jlong nativeObject) {
401     Surface* surface = reinterpret_cast<Surface*>(nativeObject);
402     return surface->getNextFrameNumber();
403 }
404 
nativeSetScalingMode(JNIEnv * env,jclass clazz,jlong nativeObject,jint scalingMode)405 static jint nativeSetScalingMode(JNIEnv *env, jclass clazz, jlong nativeObject, jint scalingMode) {
406     Surface* surface = reinterpret_cast<Surface*>(nativeObject);
407     return surface->setScalingMode(scalingMode);
408 }
409 
nativeForceScopedDisconnect(JNIEnv * env,jclass clazz,jlong nativeObject)410 static jint nativeForceScopedDisconnect(JNIEnv *env, jclass clazz, jlong nativeObject) {
411     Surface* surface = reinterpret_cast<Surface*>(nativeObject);
412     return surface->disconnect(-1, IGraphicBufferProducer::DisconnectMode::AllLocal);
413 }
414 
nativeAttachAndQueueBufferWithColorSpace(JNIEnv * env,jclass clazz,jlong nativeObject,jobject hardwareBuffer,jint colorSpaceId)415 static jint nativeAttachAndQueueBufferWithColorSpace(JNIEnv* env, jclass clazz, jlong nativeObject,
416                                                      jobject hardwareBuffer, jint colorSpaceId) {
417     Surface* surface = reinterpret_cast<Surface*>(nativeObject);
418     AHardwareBuffer* ahb =
419             android_hardware_HardwareBuffer_getNativeHardwareBuffer(env, hardwareBuffer);
420     GraphicBuffer* gb = AHardwareBuffer_to_GraphicBuffer(ahb);
421     int err = Surface::attachAndQueueBufferWithDataspace(surface, gb,
422             fromNamedColorSpaceValueToDataspace(colorSpaceId));
423     return err;
424 }
425 
nativeSetSharedBufferModeEnabled(JNIEnv * env,jclass clazz,jlong nativeObject,jboolean enabled)426 static jint nativeSetSharedBufferModeEnabled(JNIEnv* env, jclass clazz, jlong nativeObject,
427         jboolean enabled) {
428     Surface* surface = reinterpret_cast<Surface*>(nativeObject);
429     ANativeWindow* anw = static_cast<ANativeWindow*>(surface);
430     return anw->perform(surface, NATIVE_WINDOW_SET_SHARED_BUFFER_MODE, int(enabled));
431 }
432 
nativeSetAutoRefreshEnabled(JNIEnv * env,jclass clazz,jlong nativeObject,jboolean enabled)433 static jint nativeSetAutoRefreshEnabled(JNIEnv* env, jclass clazz, jlong nativeObject,
434         jboolean enabled) {
435     Surface* surface = reinterpret_cast<Surface*>(nativeObject);
436     ANativeWindow* anw = static_cast<ANativeWindow*>(surface);
437     return anw->perform(surface, NATIVE_WINDOW_SET_AUTO_REFRESH, int(enabled));
438 }
439 
nativeSetFrameRate(JNIEnv * env,jclass clazz,jlong nativeObject,jfloat frameRate,jint compatibility,jint changeFrameRateStrategy)440 static jint nativeSetFrameRate(JNIEnv* env, jclass clazz, jlong nativeObject, jfloat frameRate,
441                                jint compatibility, jint changeFrameRateStrategy) {
442     Surface* surface = reinterpret_cast<Surface*>(nativeObject);
443     ANativeWindow* anw = static_cast<ANativeWindow*>(surface);
444     // Our compatibility is a Surface.FRAME_RATE_COMPATIBILITY_* value, and
445     // NATIVE_WINDOW_SET_FRAME_RATE takes an
446     // ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_* value. The values are identical
447     // though, so no need to explicitly convert.
448     return anw->perform(surface, NATIVE_WINDOW_SET_FRAME_RATE, double(frameRate), compatibility,
449                         int(changeFrameRateStrategy));
450 }
451 
nativeDestroy(JNIEnv * env,jclass clazz,jlong nativeObject)452 static void nativeDestroy(JNIEnv* env, jclass clazz, jlong nativeObject) {
453     sp<Surface> surface(reinterpret_cast<Surface*>(nativeObject));
454     surface->destroy();
455 }
456 
457 // ----------------------------------------------------------------------------
458 
459 static const JNINativeMethod gSurfaceMethods[] = {
460         {"nativeCreateFromSurfaceTexture", "(Landroid/graphics/SurfaceTexture;)J",
461          (void*)nativeCreateFromSurfaceTexture},
462         {"nativeRelease", "(J)V", (void*)nativeRelease},
463         {"nativeIsValid", "(J)Z", (void*)nativeIsValid},
464         {"nativeIsConsumerRunningBehind", "(J)Z", (void*)nativeIsConsumerRunningBehind},
465         {"nativeLockCanvas", "(JLandroid/graphics/Canvas;Landroid/graphics/Rect;)J",
466          (void*)nativeLockCanvas},
467         {"nativeUnlockCanvasAndPost", "(JLandroid/graphics/Canvas;)V",
468          (void*)nativeUnlockCanvasAndPost},
469         {"nativeAllocateBuffers", "(J)V", (void*)nativeAllocateBuffers},
470         {"nativeCreateFromSurfaceControl", "(J)J", (void*)nativeCreateFromSurfaceControl},
471         {"nativeGetFromSurfaceControl", "(JJ)J", (void*)nativeGetFromSurfaceControl},
472         {"nativeReadFromParcel", "(JLandroid/os/Parcel;)J", (void*)nativeReadFromParcel},
473         {"nativeWriteToParcel", "(JLandroid/os/Parcel;)V", (void*)nativeWriteToParcel},
474         {"nativeGetWidth", "(J)I", (void*)nativeGetWidth},
475         {"nativeGetHeight", "(J)I", (void*)nativeGetHeight},
476         {"nativeGetNextFrameNumber", "(J)J", (void*)nativeGetNextFrameNumber},
477         {"nativeSetScalingMode", "(JI)I", (void*)nativeSetScalingMode},
478         {"nativeForceScopedDisconnect", "(J)I", (void*)nativeForceScopedDisconnect},
479         {"nativeAttachAndQueueBufferWithColorSpace", "(JLandroid/hardware/HardwareBuffer;I)I",
480          (void*)nativeAttachAndQueueBufferWithColorSpace},
481         {"nativeSetSharedBufferModeEnabled", "(JZ)I", (void*)nativeSetSharedBufferModeEnabled},
482         {"nativeSetAutoRefreshEnabled", "(JZ)I", (void*)nativeSetAutoRefreshEnabled},
483         {"nativeSetFrameRate", "(JFII)I", (void*)nativeSetFrameRate},
484         {"nativeGetFromBlastBufferQueue", "(JJ)J", (void*)nativeGetFromBlastBufferQueue},
485         {"nativeDestroy", "(J)V", (void*)nativeDestroy},
486 };
487 
register_android_view_Surface(JNIEnv * env)488 int register_android_view_Surface(JNIEnv* env)
489 {
490     int err = RegisterMethodsOrDie(env, "android/view/Surface",
491             gSurfaceMethods, NELEM(gSurfaceMethods));
492 
493     jclass clazz = FindClassOrDie(env, "android/view/Surface");
494     gSurfaceClassInfo.clazz = MakeGlobalRefOrDie(env, clazz);
495     gSurfaceClassInfo.mNativeObject = GetFieldIDOrDie(env,
496             gSurfaceClassInfo.clazz, "mNativeObject", "J");
497     gSurfaceClassInfo.mLock = GetFieldIDOrDie(env,
498             gSurfaceClassInfo.clazz, "mLock", "Ljava/lang/Object;");
499     gSurfaceClassInfo.ctor = GetMethodIDOrDie(env, gSurfaceClassInfo.clazz, "<init>", "(J)V");
500 
501     clazz = FindClassOrDie(env, "android/graphics/Rect");
502     gRectClassInfo.left = GetFieldIDOrDie(env, clazz, "left", "I");
503     gRectClassInfo.top = GetFieldIDOrDie(env, clazz, "top", "I");
504     gRectClassInfo.right = GetFieldIDOrDie(env, clazz, "right", "I");
505     gRectClassInfo.bottom = GetFieldIDOrDie(env, clazz, "bottom", "I");
506 
507     return err;
508 }
509 
510 };
511