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