OSDN Git Service

Merge \\"Correct the size of example bitmap for xxhdpi.\\" into mnc-io-docs am: 396ed...
[android-x86/frameworks-base.git] / core / jni / android_hardware_camera2_legacy_LegacyCameraDevice.cpp
1 /*
2  * Copyright (C) 2014 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 "Legacy-CameraDevice-JNI"
18 // #define LOG_NDEBUG 0
19 #include <utils/Log.h>
20 #include <utils/Errors.h>
21 #include <utils/Trace.h>
22 #include <camera/CameraUtils.h>
23
24 #include "jni.h"
25 #include "JNIHelp.h"
26 #include "core_jni_helpers.h"
27 #include "android_runtime/android_view_Surface.h"
28 #include "android_runtime/android_graphics_SurfaceTexture.h"
29
30 #include <gui/Surface.h>
31 #include <gui/IGraphicBufferProducer.h>
32 #include <gui/IProducerListener.h>
33 #include <ui/GraphicBuffer.h>
34 #include <system/window.h>
35 #include <hardware/camera3.h>
36 #include <system/camera_metadata.h>
37
38 #include <stdint.h>
39 #include <inttypes.h>
40
41 using namespace android;
42
43 // fully-qualified class name
44 #define CAMERA_DEVICE_CLASS_NAME "android/hardware/camera2/legacy/LegacyCameraDevice"
45 #define CAMERA_DEVICE_BUFFER_SLACK  3
46 #define DONT_CARE 0
47
48 #define ARRAY_SIZE(a) (sizeof(a)/sizeof(*(a)))
49
50 #define ALIGN(x, mask) ( ((x) + (mask) - 1) & ~((mask) - 1) )
51
52 /**
53  * Convert from RGB 888 to Y'CbCr using the conversion specified in JFIF v1.02
54  */
55 static void rgbToYuv420(uint8_t* rgbBuf, size_t width, size_t height, uint8_t* yPlane,
56         uint8_t* crPlane, uint8_t* cbPlane, size_t chromaStep, size_t yStride, size_t chromaStride) {
57     uint8_t R, G, B;
58     size_t index = 0;
59     for (size_t j = 0; j < height; j++) {
60         uint8_t* cr = crPlane;
61         uint8_t* cb = cbPlane;
62         uint8_t* y = yPlane;
63         bool jEven = (j & 1) == 0;
64         for (size_t i = 0; i < width; i++) {
65             R = rgbBuf[index++];
66             G = rgbBuf[index++];
67             B = rgbBuf[index++];
68             *y++ = (77 * R + 150 * G +  29 * B) >> 8;
69             if (jEven && (i & 1) == 0) {
70                 *cb = (( -43 * R - 85 * G + 128 * B) >> 8) + 128;
71                 *cr = (( 128 * R - 107 * G - 21 * B) >> 8) + 128;
72                 cr += chromaStep;
73                 cb += chromaStep;
74             }
75             // Skip alpha
76             index++;
77         }
78         yPlane += yStride;
79         if (jEven) {
80             crPlane += chromaStride;
81             cbPlane += chromaStride;
82         }
83     }
84 }
85
86 static void rgbToYuv420(uint8_t* rgbBuf, size_t width, size_t height, android_ycbcr* ycbcr) {
87     size_t cStep = ycbcr->chroma_step;
88     size_t cStride = ycbcr->cstride;
89     size_t yStride = ycbcr->ystride;
90     ALOGV("%s: yStride is: %zu, cStride is: %zu, cStep is: %zu", __FUNCTION__, yStride, cStride,
91             cStep);
92     rgbToYuv420(rgbBuf, width, height, reinterpret_cast<uint8_t*>(ycbcr->y),
93             reinterpret_cast<uint8_t*>(ycbcr->cr), reinterpret_cast<uint8_t*>(ycbcr->cb),
94             cStep, yStride, cStride);
95 }
96
97 static status_t connectSurface(const sp<Surface>& surface, int32_t maxBufferSlack) {
98     status_t err = NO_ERROR;
99
100     err = surface->connect(NATIVE_WINDOW_API_CAMERA, /*listener*/NULL);
101     if (err != OK) {
102         ALOGE("%s: Unable to connect to surface, error %s (%d).", __FUNCTION__,
103                 strerror(-err), err);
104         return err;
105     }
106
107     err = native_window_set_usage(surface.get(), GRALLOC_USAGE_SW_WRITE_OFTEN);
108     if (err != NO_ERROR) {
109         ALOGE("%s: Failed to set native window usage flag, error %s (%d).", __FUNCTION__,
110                 strerror(-err), err);
111         return err;
112     }
113
114     int minUndequeuedBuffers;
115     err = static_cast<ANativeWindow*>(surface.get())->query(surface.get(),
116             NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBuffers);
117     if (err != NO_ERROR) {
118         ALOGE("%s: Failed to get native window min undequeued buffers, error %s (%d).",
119                 __FUNCTION__, strerror(-err), err);
120         return err;
121     }
122
123     ALOGV("%s: Setting buffer count to %d", __FUNCTION__,
124             maxBufferSlack + 1 + minUndequeuedBuffers);
125     err = native_window_set_buffer_count(surface.get(), maxBufferSlack + 1 + minUndequeuedBuffers);
126     if (err != NO_ERROR) {
127         ALOGE("%s: Failed to set native window buffer count, error %s (%d).", __FUNCTION__,
128                 strerror(-err), err);
129         return err;
130     }
131     return NO_ERROR;
132 }
133
134 /**
135  * Produce a frame in the given surface.
136  *
137  * Args:
138  *    anw - a surface to produce a frame in.
139  *    pixelBuffer - image buffer to generate a frame from.
140  *    width - width of the pixelBuffer in pixels.
141  *    height - height of the pixelBuffer in pixels.
142  *    pixelFmt - format of the pixelBuffer, one of:
143  *               HAL_PIXEL_FORMAT_YCrCb_420_SP,
144  *               HAL_PIXEL_FORMAT_YCbCr_420_888,
145  *               HAL_PIXEL_FORMAT_BLOB
146  *    bufSize - the size of the pixelBuffer in bytes.
147  */
148 static status_t produceFrame(const sp<ANativeWindow>& anw,
149                              uint8_t* pixelBuffer,
150                              int32_t bufWidth, // Width of the pixelBuffer
151                              int32_t bufHeight, // Height of the pixelBuffer
152                              int32_t pixelFmt, // Format of the pixelBuffer
153                              int32_t bufSize) {
154     ATRACE_CALL();
155     status_t err = NO_ERROR;
156     ANativeWindowBuffer* anb;
157     ALOGV("%s: Dequeue buffer from %p %dx%d (fmt=%x, size=%x)",
158             __FUNCTION__, anw.get(), bufWidth, bufHeight, pixelFmt, bufSize);
159
160     if (anw == 0) {
161         ALOGE("%s: anw must not be NULL", __FUNCTION__);
162         return BAD_VALUE;
163     } else if (pixelBuffer == NULL) {
164         ALOGE("%s: pixelBuffer must not be NULL", __FUNCTION__);
165         return BAD_VALUE;
166     } else if (bufWidth < 0) {
167         ALOGE("%s: width must be non-negative", __FUNCTION__);
168         return BAD_VALUE;
169     } else if (bufHeight < 0) {
170         ALOGE("%s: height must be non-negative", __FUNCTION__);
171         return BAD_VALUE;
172     } else if (bufSize < 0) {
173         ALOGE("%s: bufSize must be non-negative", __FUNCTION__);
174         return BAD_VALUE;
175     }
176
177     size_t width = static_cast<size_t>(bufWidth);
178     size_t height = static_cast<size_t>(bufHeight);
179     size_t bufferLength = static_cast<size_t>(bufSize);
180
181     // TODO: Switch to using Surface::lock and Surface::unlockAndPost
182     err = native_window_dequeue_buffer_and_wait(anw.get(), &anb);
183     if (err != NO_ERROR) return err;
184
185     sp<GraphicBuffer> buf(new GraphicBuffer(anb, /*keepOwnership*/false));
186     uint32_t grallocBufWidth = buf->getWidth();
187     uint32_t grallocBufHeight = buf->getHeight();
188     uint32_t grallocBufStride = buf->getStride();
189     if (grallocBufWidth != width || grallocBufHeight != height) {
190         ALOGE("%s: Received gralloc buffer with bad dimensions %" PRIu32 "x%" PRIu32
191                 ", expecting dimensions %zu x %zu",  __FUNCTION__, grallocBufWidth,
192                 grallocBufHeight, width, height);
193         return BAD_VALUE;
194     }
195
196     int32_t bufFmt = 0;
197     err = anw->query(anw.get(), NATIVE_WINDOW_FORMAT, &bufFmt);
198     if (err != NO_ERROR) {
199         ALOGE("%s: Error while querying surface pixel format %s (%d).", __FUNCTION__,
200                 strerror(-err), err);
201         return err;
202     }
203
204     uint64_t tmpSize = (pixelFmt == HAL_PIXEL_FORMAT_BLOB) ? grallocBufWidth :
205             4 * grallocBufHeight * grallocBufWidth;
206     if (bufFmt != pixelFmt) {
207         if (bufFmt == HAL_PIXEL_FORMAT_RGBA_8888 && pixelFmt == HAL_PIXEL_FORMAT_BLOB) {
208             ALOGV("%s: Using BLOB to RGBA format override.", __FUNCTION__);
209             tmpSize = 4 * (grallocBufWidth + grallocBufStride * (grallocBufHeight - 1));
210         } else {
211             ALOGW("%s: Format mismatch in produceFrame: expecting format %#" PRIx32
212                     ", but received buffer with format %#" PRIx32, __FUNCTION__, pixelFmt, bufFmt);
213         }
214     }
215
216     if (tmpSize > SIZE_MAX) {
217         ALOGE("%s: Overflow calculating size, buffer with dimens %zu x %zu is absurdly large...",
218                 __FUNCTION__, width, height);
219         return BAD_VALUE;
220     }
221
222     size_t totalSizeBytes = tmpSize;
223
224     ALOGV("%s: Pixel format chosen: %x", __FUNCTION__, pixelFmt);
225     switch(pixelFmt) {
226         case HAL_PIXEL_FORMAT_YCrCb_420_SP: {
227             if (bufferLength < totalSizeBytes) {
228                 ALOGE("%s: PixelBuffer size %zu too small for given dimensions",
229                         __FUNCTION__, bufferLength);
230                 return BAD_VALUE;
231             }
232             uint8_t* img = NULL;
233             ALOGV("%s: Lock buffer from %p for write", __FUNCTION__, anw.get());
234             err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
235             if (err != NO_ERROR) return err;
236
237             uint8_t* yPlane = img;
238             uint8_t* uPlane = img + height * width;
239             uint8_t* vPlane = uPlane + 1;
240             size_t chromaStep = 2;
241             size_t yStride = width;
242             size_t chromaStride = width;
243
244             rgbToYuv420(pixelBuffer, width, height, yPlane,
245                     uPlane, vPlane, chromaStep, yStride, chromaStride);
246             break;
247         }
248         case HAL_PIXEL_FORMAT_YV12: {
249             if (bufferLength < totalSizeBytes) {
250                 ALOGE("%s: PixelBuffer size %zu too small for given dimensions",
251                         __FUNCTION__, bufferLength);
252                 return BAD_VALUE;
253             }
254
255             if ((width & 1) || (height & 1)) {
256                 ALOGE("%s: Dimens %zu x %zu are not divisible by 2.", __FUNCTION__, width, height);
257                 return BAD_VALUE;
258             }
259
260             uint8_t* img = NULL;
261             ALOGV("%s: Lock buffer from %p for write", __FUNCTION__, anw.get());
262             err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
263             if (err != NO_ERROR) {
264                 ALOGE("%s: Error %s (%d) while locking gralloc buffer for write.", __FUNCTION__,
265                         strerror(-err), err);
266                 return err;
267             }
268
269             uint32_t stride = buf->getStride();
270             ALOGV("%s: stride is: %" PRIu32, __FUNCTION__, stride);
271             LOG_ALWAYS_FATAL_IF(stride % 16, "Stride is not 16 pixel aligned %d", stride);
272
273             uint32_t cStride = ALIGN(stride / 2, 16);
274             size_t chromaStep = 1;
275
276             uint8_t* yPlane = img;
277             uint8_t* crPlane = img + static_cast<uint32_t>(height) * stride;
278             uint8_t* cbPlane = crPlane + cStride * static_cast<uint32_t>(height) / 2;
279
280             rgbToYuv420(pixelBuffer, width, height, yPlane,
281                     crPlane, cbPlane, chromaStep, stride, cStride);
282             break;
283         }
284         case HAL_PIXEL_FORMAT_YCbCr_420_888: {
285             // Software writes with YCbCr_420_888 format are unsupported
286             // by the gralloc module for now
287             if (bufferLength < totalSizeBytes) {
288                 ALOGE("%s: PixelBuffer size %zu too small for given dimensions",
289                         __FUNCTION__, bufferLength);
290                 return BAD_VALUE;
291             }
292             android_ycbcr ycbcr = android_ycbcr();
293             ALOGV("%s: Lock buffer from %p for write", __FUNCTION__, anw.get());
294
295             err = buf->lockYCbCr(GRALLOC_USAGE_SW_WRITE_OFTEN, &ycbcr);
296             if (err != NO_ERROR) {
297                 ALOGE("%s: Failed to lock ycbcr buffer, error %s (%d).", __FUNCTION__,
298                         strerror(-err), err);
299                 return err;
300             }
301             rgbToYuv420(pixelBuffer, width, height, &ycbcr);
302             break;
303         }
304         case HAL_PIXEL_FORMAT_BLOB: {
305             int8_t* img = NULL;
306             struct camera3_jpeg_blob footer = {
307                 .jpeg_blob_id = CAMERA3_JPEG_BLOB_ID,
308                 .jpeg_size = (uint32_t)bufferLength
309             };
310
311             size_t totalJpegSize = bufferLength + sizeof(footer);
312             totalJpegSize = (totalJpegSize + 3) & ~0x3; // round up to nearest octonibble
313
314             if (totalJpegSize > totalSizeBytes) {
315                 ALOGE("%s: Pixel buffer needs size %zu, cannot fit in gralloc buffer of size %zu",
316                         __FUNCTION__, totalJpegSize, totalSizeBytes);
317                 return BAD_VALUE;
318             }
319
320             err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
321             if (err != NO_ERROR) {
322                 ALOGE("%s: Failed to lock buffer, error %s (%d).", __FUNCTION__, strerror(-err),
323                         err);
324                 return err;
325             }
326
327             memcpy(img, pixelBuffer, bufferLength);
328             memcpy(img + totalSizeBytes - sizeof(footer), &footer, sizeof(footer));
329             break;
330         }
331         default: {
332             ALOGE("%s: Invalid pixel format in produceFrame: %x", __FUNCTION__, pixelFmt);
333             return BAD_VALUE;
334         }
335     }
336
337     ALOGV("%s: Unlock buffer from %p", __FUNCTION__, anw.get());
338     err = buf->unlock();
339     if (err != NO_ERROR) {
340         ALOGE("%s: Failed to unlock buffer, error %s (%d).", __FUNCTION__, strerror(-err), err);
341         return err;
342     }
343
344     ALOGV("%s: Queue buffer to %p", __FUNCTION__, anw.get());
345     err = anw->queueBuffer(anw.get(), buf->getNativeBuffer(), /*fenceFd*/-1);
346     if (err != NO_ERROR) {
347         ALOGE("%s: Failed to queue buffer, error %s (%d).", __FUNCTION__, strerror(-err), err);
348         return err;
349     }
350     return NO_ERROR;
351 }
352
353 static sp<ANativeWindow> getNativeWindow(JNIEnv* env, jobject surface) {
354     sp<ANativeWindow> anw;
355     if (surface) {
356         anw = android_view_Surface_getNativeWindow(env, surface);
357         if (env->ExceptionCheck()) {
358             return NULL;
359         }
360     } else {
361         jniThrowNullPointerException(env, "surface");
362         return NULL;
363     }
364     if (anw == NULL) {
365         ALOGE("%s: Surface had no valid native window.", __FUNCTION__);
366         return NULL;
367     }
368     return anw;
369 }
370
371 static sp<ANativeWindow> getNativeWindowFromTexture(JNIEnv* env, jobject surfaceTexture) {
372     sp<ANativeWindow> anw;
373     if (surfaceTexture) {
374         anw = android_SurfaceTexture_getNativeWindow(env, surfaceTexture);
375         if (env->ExceptionCheck()) {
376             return NULL;
377         }
378     } else {
379         jniThrowNullPointerException(env, "surfaceTexture");
380         return NULL;
381     }
382     if (anw == NULL) {
383         jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
384                 "SurfaceTexture had no valid native window.");
385         return NULL;
386     }
387     return anw;
388 }
389
390 static sp<Surface> getSurface(JNIEnv* env, jobject surface) {
391     sp<Surface> s;
392     if (surface) {
393         s = android_view_Surface_getSurface(env, surface);
394         if (env->ExceptionCheck()) {
395             return NULL;
396         }
397     } else {
398         jniThrowNullPointerException(env, "surface");
399         return NULL;
400     }
401     if (s == NULL) {
402         jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
403                 "Surface had no valid native Surface.");
404         return NULL;
405     }
406     return s;
407 }
408
409 extern "C" {
410
411 static jint LegacyCameraDevice_nativeDetectSurfaceType(JNIEnv* env, jobject thiz, jobject surface) {
412     ALOGV("nativeDetectSurfaceType");
413     sp<ANativeWindow> anw;
414     if ((anw = getNativeWindow(env, surface)) == NULL) {
415         ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
416         return BAD_VALUE;
417     }
418     int32_t fmt = 0;
419     status_t err = anw->query(anw.get(), NATIVE_WINDOW_FORMAT, &fmt);
420     if(err != NO_ERROR) {
421         ALOGE("%s: Error while querying surface pixel format %s (%d).", __FUNCTION__, strerror(-err),
422                 err);
423         return err;
424     }
425     return fmt;
426 }
427
428 static jint LegacyCameraDevice_nativeDetectSurfaceDataspace(JNIEnv* env, jobject thiz, jobject surface) {
429     ALOGV("nativeDetectSurfaceDataspace");
430     sp<ANativeWindow> anw;
431     if ((anw = getNativeWindow(env, surface)) == NULL) {
432         ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
433         return BAD_VALUE;
434     }
435     int32_t fmt = 0;
436     status_t err = anw->query(anw.get(), NATIVE_WINDOW_DEFAULT_DATASPACE, &fmt);
437     if(err != NO_ERROR) {
438         ALOGE("%s: Error while querying surface dataspace  %s (%d).", __FUNCTION__, strerror(-err),
439                 err);
440         return err;
441     }
442     return fmt;
443 }
444
445 static jint LegacyCameraDevice_nativeDetectSurfaceDimens(JNIEnv* env, jobject thiz,
446           jobject surface, jintArray dimens) {
447     ALOGV("nativeGetSurfaceDimens");
448
449     if (dimens == NULL) {
450         ALOGE("%s: Null dimens argument passed to nativeDetectSurfaceDimens", __FUNCTION__);
451         return BAD_VALUE;
452     }
453
454     if (env->GetArrayLength(dimens) < 2) {
455         ALOGE("%s: Invalid length of dimens argument in nativeDetectSurfaceDimens", __FUNCTION__);
456         return BAD_VALUE;
457     }
458
459     sp<ANativeWindow> anw;
460     if ((anw = getNativeWindow(env, surface)) == NULL) {
461         ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
462         return BAD_VALUE;
463     }
464     int32_t dimenBuf[2];
465     status_t err = anw->query(anw.get(), NATIVE_WINDOW_WIDTH, dimenBuf);
466     if(err != NO_ERROR) {
467         ALOGE("%s: Error while querying surface width %s (%d).", __FUNCTION__, strerror(-err),
468                 err);
469         return err;
470     }
471     err = anw->query(anw.get(), NATIVE_WINDOW_HEIGHT, dimenBuf + 1);
472     if(err != NO_ERROR) {
473         ALOGE("%s: Error while querying surface height %s (%d).", __FUNCTION__, strerror(-err),
474                 err);
475         return err;
476     }
477     env->SetIntArrayRegion(dimens, /*start*/0, /*length*/ARRAY_SIZE(dimenBuf), dimenBuf);
478     return NO_ERROR;
479 }
480
481 static jint LegacyCameraDevice_nativeDetectSurfaceUsageFlags(JNIEnv* env, jobject thiz,
482           jobject surface) {
483     ALOGV("nativeDetectSurfaceUsageFlags");
484
485     sp<ANativeWindow> anw;
486     if ((anw = getNativeWindow(env, surface)) == NULL) {
487         jniThrowException(env, "Ljava/lang/UnsupportedOperationException;",
488             "Could not retrieve native window from surface.");
489         return BAD_VALUE;
490     }
491     int32_t usage = 0;
492     status_t err = anw->query(anw.get(), NATIVE_WINDOW_CONSUMER_USAGE_BITS, &usage);
493     if(err != NO_ERROR) {
494         jniThrowException(env, "Ljava/lang/UnsupportedOperationException;",
495             "Error while querying surface usage bits");
496         return err;
497     }
498     return usage;
499 }
500
501 static jint LegacyCameraDevice_nativeDisconnectSurface(JNIEnv* env, jobject thiz,
502           jobject surface) {
503     ALOGV("nativeDisconnectSurface");
504     if (surface == nullptr) return NO_ERROR;
505
506     sp<ANativeWindow> anw;
507     if ((anw = getNativeWindow(env, surface)) == NULL) {
508         ALOGV("Buffer queue has already been abandoned.");
509         return NO_ERROR;
510     }
511
512     status_t err = native_window_api_disconnect(anw.get(), NATIVE_WINDOW_API_CAMERA);
513     if(err != NO_ERROR) {
514         jniThrowException(env, "Ljava/lang/UnsupportedOperationException;",
515             "Error while disconnecting surface");
516         return err;
517     }
518     return NO_ERROR;
519 }
520
521 static jint LegacyCameraDevice_nativeDetectTextureDimens(JNIEnv* env, jobject thiz,
522         jobject surfaceTexture, jintArray dimens) {
523     ALOGV("nativeDetectTextureDimens");
524     sp<ANativeWindow> anw;
525     if ((anw = getNativeWindowFromTexture(env, surfaceTexture)) == NULL) {
526         ALOGE("%s: Could not retrieve native window from SurfaceTexture.", __FUNCTION__);
527         return BAD_VALUE;
528     }
529
530     int32_t dimenBuf[2];
531     status_t err = anw->query(anw.get(), NATIVE_WINDOW_WIDTH, dimenBuf);
532     if(err != NO_ERROR) {
533         ALOGE("%s: Error while querying SurfaceTexture width %s (%d)", __FUNCTION__,
534                 strerror(-err), err);
535         return err;
536     }
537
538     err = anw->query(anw.get(), NATIVE_WINDOW_HEIGHT, dimenBuf + 1);
539     if(err != NO_ERROR) {
540         ALOGE("%s: Error while querying SurfaceTexture height %s (%d)", __FUNCTION__,
541                 strerror(-err), err);
542         return err;
543     }
544
545     env->SetIntArrayRegion(dimens, /*start*/0, /*length*/ARRAY_SIZE(dimenBuf), dimenBuf);
546     if (env->ExceptionCheck()) {
547         return BAD_VALUE;
548     }
549     return NO_ERROR;
550 }
551
552 static jint LegacyCameraDevice_nativeConnectSurface(JNIEnv* env, jobject thiz, jobject surface) {
553     ALOGV("nativeConnectSurface");
554     sp<Surface> s;
555     if ((s = getSurface(env, surface)) == NULL) {
556         ALOGE("%s: Could not retrieve surface.", __FUNCTION__);
557         return BAD_VALUE;
558     }
559     status_t err = connectSurface(s, CAMERA_DEVICE_BUFFER_SLACK);
560     if (err != NO_ERROR) {
561         ALOGE("%s: Error while configuring surface %s (%d).", __FUNCTION__, strerror(-err), err);
562         return err;
563     }
564     return NO_ERROR;
565 }
566
567 static jint LegacyCameraDevice_nativeProduceFrame(JNIEnv* env, jobject thiz, jobject surface,
568         jbyteArray pixelBuffer, jint width, jint height, jint pixelFormat) {
569     ALOGV("nativeProduceFrame");
570     sp<ANativeWindow> anw;
571
572     if ((anw = getNativeWindow(env, surface)) == NULL) {
573         ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
574         return BAD_VALUE;
575     }
576
577     if (pixelBuffer == NULL) {
578         jniThrowNullPointerException(env, "pixelBuffer");
579         return DONT_CARE;
580     }
581
582     int32_t bufSize = static_cast<int32_t>(env->GetArrayLength(pixelBuffer));
583     jbyte* pixels = env->GetByteArrayElements(pixelBuffer, /*is_copy*/NULL);
584
585     if (pixels == NULL) {
586         jniThrowNullPointerException(env, "pixels");
587         return DONT_CARE;
588     }
589
590     status_t err = produceFrame(anw, reinterpret_cast<uint8_t*>(pixels), width, height,
591             pixelFormat, bufSize);
592     env->ReleaseByteArrayElements(pixelBuffer, pixels, JNI_ABORT);
593
594     if (err != NO_ERROR) {
595         ALOGE("%s: Error while producing frame %s (%d).", __FUNCTION__, strerror(-err), err);
596         return err;
597     }
598     return NO_ERROR;
599 }
600
601 static jint LegacyCameraDevice_nativeSetSurfaceFormat(JNIEnv* env, jobject thiz, jobject surface,
602         jint pixelFormat) {
603     ALOGV("nativeSetSurfaceType");
604     sp<ANativeWindow> anw;
605     if ((anw = getNativeWindow(env, surface)) == NULL) {
606         ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
607         return BAD_VALUE;
608     }
609     status_t err = native_window_set_buffers_format(anw.get(), pixelFormat);
610     if (err != NO_ERROR) {
611         ALOGE("%s: Error while setting surface format %s (%d).", __FUNCTION__, strerror(-err), err);
612         return err;
613     }
614     return NO_ERROR;
615 }
616
617 static jint LegacyCameraDevice_nativeSetSurfaceDimens(JNIEnv* env, jobject thiz, jobject surface,
618         jint width, jint height) {
619     ALOGV("nativeSetSurfaceDimens");
620     sp<ANativeWindow> anw;
621     if ((anw = getNativeWindow(env, surface)) == NULL) {
622         ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
623         return BAD_VALUE;
624     }
625
626     // Set user dimensions only
627     // The producer dimensions are owned by GL
628     status_t err = native_window_set_buffers_user_dimensions(anw.get(), width, height);
629     if (err != NO_ERROR) {
630         ALOGE("%s: Error while setting surface user dimens %s (%d).", __FUNCTION__, strerror(-err),
631                 err);
632         return err;
633     }
634     return NO_ERROR;
635 }
636
637 static jlong LegacyCameraDevice_nativeGetSurfaceId(JNIEnv* env, jobject thiz, jobject surface) {
638     ALOGV("nativeGetSurfaceId");
639     sp<Surface> s;
640     if ((s = getSurface(env, surface)) == NULL) {
641         ALOGE("%s: Could not retrieve native Surface from surface.", __FUNCTION__);
642         return 0;
643     }
644     sp<IGraphicBufferProducer> gbp = s->getIGraphicBufferProducer();
645     if (gbp == NULL) {
646         ALOGE("%s: Could not retrieve IGraphicBufferProducer from surface.", __FUNCTION__);
647         return 0;
648     }
649     sp<IBinder> b = IInterface::asBinder(gbp);
650     if (b == NULL) {
651         ALOGE("%s: Could not retrieve IBinder from surface.", __FUNCTION__);
652         return 0;
653     }
654     /*
655      * FIXME: Use better unique ID for surfaces than native IBinder pointer.  Fix also in the camera
656      * service (CameraDeviceClient.h).
657      */
658     return reinterpret_cast<jlong>(b.get());
659 }
660
661 static jint LegacyCameraDevice_nativeSetSurfaceOrientation(JNIEnv* env, jobject thiz,
662         jobject surface, jint facing, jint orientation) {
663     ALOGV("nativeSetSurfaceOrientation");
664     sp<ANativeWindow> anw;
665     if ((anw = getNativeWindow(env, surface)) == NULL) {
666         ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
667         return BAD_VALUE;
668     }
669
670     status_t err = NO_ERROR;
671     CameraMetadata staticMetadata;
672
673     int32_t orientVal = static_cast<int32_t>(orientation);
674     uint8_t facingVal = static_cast<uint8_t>(facing);
675     staticMetadata.update(ANDROID_SENSOR_ORIENTATION, &orientVal, 1);
676     staticMetadata.update(ANDROID_LENS_FACING, &facingVal, 1);
677
678     int32_t transform = 0;
679
680     if ((err = CameraUtils::getRotationTransform(staticMetadata, /*out*/&transform)) != NO_ERROR) {
681         ALOGE("%s: Invalid rotation transform %s (%d)", __FUNCTION__, strerror(-err),
682                 err);
683         return err;
684     }
685
686     ALOGV("%s: Setting buffer sticky transform to %d", __FUNCTION__, transform);
687
688     if ((err = native_window_set_buffers_sticky_transform(anw.get(), transform)) != NO_ERROR) {
689         ALOGE("%s: Unable to configure surface transform, error %s (%d)", __FUNCTION__,
690                 strerror(-err), err);
691         return err;
692     }
693
694     return NO_ERROR;
695 }
696
697 static jint LegacyCameraDevice_nativeSetNextTimestamp(JNIEnv* env, jobject thiz, jobject surface,
698         jlong timestamp) {
699     ALOGV("nativeSetNextTimestamp");
700     sp<ANativeWindow> anw;
701     if ((anw = getNativeWindow(env, surface)) == NULL) {
702         ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
703         return BAD_VALUE;
704     }
705
706     status_t err = NO_ERROR;
707
708     if ((err = native_window_set_buffers_timestamp(anw.get(), static_cast<int64_t>(timestamp))) !=
709             NO_ERROR) {
710         ALOGE("%s: Unable to set surface timestamp, error %s (%d)", __FUNCTION__, strerror(-err),
711                 err);
712         return err;
713     }
714     return NO_ERROR;
715 }
716
717 static jint LegacyCameraDevice_nativeSetScalingMode(JNIEnv* env, jobject thiz, jobject surface,
718         jint mode) {
719     ALOGV("nativeSetScalingMode");
720     sp<ANativeWindow> anw;
721     if ((anw = getNativeWindow(env, surface)) == NULL) {
722         ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
723         return BAD_VALUE;
724     }
725     status_t err = NO_ERROR;
726     if ((err = native_window_set_scaling_mode(anw.get(), static_cast<int>(mode))) != NO_ERROR) {
727         ALOGE("%s: Unable to set surface scaling mode, error %s (%d)", __FUNCTION__,
728                 strerror(-err), err);
729         return err;
730     }
731     return NO_ERROR;
732 }
733
734 static jint LegacyCameraDevice_nativeGetJpegFooterSize(JNIEnv* env, jobject thiz) {
735     ALOGV("nativeGetJpegFooterSize");
736     return static_cast<jint>(sizeof(struct camera3_jpeg_blob));
737 }
738
739 } // extern "C"
740
741 static const JNINativeMethod gCameraDeviceMethods[] = {
742     { "nativeDetectSurfaceType",
743     "(Landroid/view/Surface;)I",
744     (void *)LegacyCameraDevice_nativeDetectSurfaceType },
745     { "nativeDetectSurfaceDataspace",
746     "(Landroid/view/Surface;)I",
747     (void *)LegacyCameraDevice_nativeDetectSurfaceDataspace },
748     { "nativeDetectSurfaceDimens",
749     "(Landroid/view/Surface;[I)I",
750     (void *)LegacyCameraDevice_nativeDetectSurfaceDimens },
751     { "nativeConnectSurface",
752     "(Landroid/view/Surface;)I",
753     (void *)LegacyCameraDevice_nativeConnectSurface },
754     { "nativeProduceFrame",
755     "(Landroid/view/Surface;[BIII)I",
756     (void *)LegacyCameraDevice_nativeProduceFrame },
757     { "nativeSetSurfaceFormat",
758     "(Landroid/view/Surface;I)I",
759     (void *)LegacyCameraDevice_nativeSetSurfaceFormat },
760     { "nativeSetSurfaceDimens",
761     "(Landroid/view/Surface;II)I",
762     (void *)LegacyCameraDevice_nativeSetSurfaceDimens },
763     { "nativeGetSurfaceId",
764     "(Landroid/view/Surface;)J",
765     (void *)LegacyCameraDevice_nativeGetSurfaceId },
766     { "nativeDetectTextureDimens",
767     "(Landroid/graphics/SurfaceTexture;[I)I",
768     (void *)LegacyCameraDevice_nativeDetectTextureDimens },
769     { "nativeSetSurfaceOrientation",
770     "(Landroid/view/Surface;II)I",
771     (void *)LegacyCameraDevice_nativeSetSurfaceOrientation },
772     { "nativeSetNextTimestamp",
773     "(Landroid/view/Surface;J)I",
774     (void *)LegacyCameraDevice_nativeSetNextTimestamp },
775     { "nativeGetJpegFooterSize",
776     "()I",
777     (void *)LegacyCameraDevice_nativeGetJpegFooterSize },
778     { "nativeDetectSurfaceUsageFlags",
779     "(Landroid/view/Surface;)I",
780     (void *)LegacyCameraDevice_nativeDetectSurfaceUsageFlags },
781     { "nativeSetScalingMode",
782     "(Landroid/view/Surface;I)I",
783     (void *)LegacyCameraDevice_nativeSetScalingMode },
784     { "nativeDisconnectSurface",
785     "(Landroid/view/Surface;)I",
786     (void *)LegacyCameraDevice_nativeDisconnectSurface },
787 };
788
789 // Get all the required offsets in java class and register native functions
790 int register_android_hardware_camera2_legacy_LegacyCameraDevice(JNIEnv* env)
791 {
792     // Register native functions
793     return RegisterMethodsOrDie(env,
794             CAMERA_DEVICE_CLASS_NAME,
795             gCameraDeviceMethods,
796             NELEM(gCameraDeviceMethods));
797 }