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