blob: 8cf1d2cbfaae92bee19cda539deae2d923ad0781 [file] [log] [blame]
Ruben Brunkfeb50af2014-05-09 19:58:49 -07001/*
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"
Igor Murashkin5096def2014-06-24 10:49:11 -070018// #define LOG_NDEBUG 0
Ruben Brunkfeb50af2014-05-09 19:58:49 -070019#include <utils/Log.h>
20#include <utils/Errors.h>
21#include <utils/Trace.h>
Ruben Brunk28c49c92014-06-16 18:43:59 -070022#include <camera/CameraUtils.h>
Ruben Brunkfeb50af2014-05-09 19:58:49 -070023
24#include "jni.h"
Steven Moreland2279b252017-07-19 09:50:45 -070025#include <nativehelper/JNIHelp.h>
Andreas Gampeed6b9df2014-11-20 22:02:20 -080026#include "core_jni_helpers.h"
Ruben Brunkfeb50af2014-05-09 19:58:49 -070027#include "android_runtime/android_view_Surface.h"
Ruben Brunk28c49c92014-06-16 18:43:59 -070028#include "android_runtime/android_graphics_SurfaceTexture.h"
Ruben Brunkfeb50af2014-05-09 19:58:49 -070029
Ruben Brunk3c8fa3b2014-06-30 16:45:05 -070030#include <gui/IGraphicBufferProducer.h>
Chien-Yu Chen29c36302016-03-02 15:34:00 -080031#include <gui/IProducerListener.h>
Stan Iliev5af5d302020-01-13 11:29:18 -050032#include <gui/Surface.h>
Igor Murashkin5096def2014-06-24 10:49:11 -070033#include <hardware/camera3.h>
Stan Iliev5af5d302020-01-13 11:29:18 -050034#include <surfacetexture/SurfaceTexture.h>
Ruben Brunk28c49c92014-06-16 18:43:59 -070035#include <system/camera_metadata.h>
Stan Iliev5af5d302020-01-13 11:29:18 -050036#include <system/window.h>
37#include <ui/GraphicBuffer.h>
Ruben Brunkfeb50af2014-05-09 19:58:49 -070038
Ruben Brunk3c8fa3b2014-06-30 16:45:05 -070039#include <stdint.h>
40#include <inttypes.h>
41
Ruben Brunkfeb50af2014-05-09 19:58:49 -070042using namespace android;
43
44// fully-qualified class name
45#define CAMERA_DEVICE_CLASS_NAME "android/hardware/camera2/legacy/LegacyCameraDevice"
46#define CAMERA_DEVICE_BUFFER_SLACK 3
Ruben Brunkef14da32014-06-24 16:06:54 -070047#define DONT_CARE 0
Ruben Brunkfeb50af2014-05-09 19:58:49 -070048
49#define ARRAY_SIZE(a) (sizeof(a)/sizeof(*(a)))
50
Ruben Brunk91b9aab2014-06-20 00:24:56 -070051#define ALIGN(x, mask) ( ((x) + (mask) - 1) & ~((mask) - 1) )
52
Yin-Chia Yeh36ceaca2018-03-16 11:05:37 -070053// Use BAD_VALUE for surface abandoned error
54#define OVERRIDE_SURFACE_ERROR(err) \
55do { \
56 if (err == -ENODEV) { \
57 err = BAD_VALUE; \
58 } \
59} while (0)
60
61#define UPDATE(md, tag, data, size) \
62do { \
63 if ((md).update((tag), (data), (size))) { \
64 ALOGE("Update " #tag " failed!"); \
65 return BAD_VALUE; \
66 } \
67} while (0)
68
Ruben Brunkfeb50af2014-05-09 19:58:49 -070069/**
Ruben Brunk433e7152014-12-10 19:12:41 -080070 * Convert from RGB 888 to Y'CbCr using the conversion specified in JFIF v1.02
Ruben Brunkfeb50af2014-05-09 19:58:49 -070071 */
Ruben Brunk31798f32014-09-25 19:56:54 -070072static void rgbToYuv420(uint8_t* rgbBuf, size_t width, size_t height, uint8_t* yPlane,
Ruben Brunk89735972014-12-11 12:55:44 -080073 uint8_t* crPlane, uint8_t* cbPlane, size_t chromaStep, size_t yStride, size_t chromaStride) {
Ruben Brunkfeb50af2014-05-09 19:58:49 -070074 uint8_t R, G, B;
75 size_t index = 0;
Ruben Brunk31798f32014-09-25 19:56:54 -070076 for (size_t j = 0; j < height; j++) {
Ruben Brunk89735972014-12-11 12:55:44 -080077 uint8_t* cr = crPlane;
78 uint8_t* cb = cbPlane;
Ruben Brunk433e7152014-12-10 19:12:41 -080079 uint8_t* y = yPlane;
80 bool jEven = (j & 1) == 0;
Ruben Brunk31798f32014-09-25 19:56:54 -070081 for (size_t i = 0; i < width; i++) {
Ruben Brunkfeb50af2014-05-09 19:58:49 -070082 R = rgbBuf[index++];
83 G = rgbBuf[index++];
84 B = rgbBuf[index++];
Ruben Brunk433e7152014-12-10 19:12:41 -080085 *y++ = (77 * R + 150 * G + 29 * B) >> 8;
86 if (jEven && (i & 1) == 0) {
Ruben Brunk89735972014-12-11 12:55:44 -080087 *cb = (( -43 * R - 85 * G + 128 * B) >> 8) + 128;
88 *cr = (( 128 * R - 107 * G - 21 * B) >> 8) + 128;
89 cr += chromaStep;
90 cb += chromaStep;
Ruben Brunkfeb50af2014-05-09 19:58:49 -070091 }
92 // Skip alpha
93 index++;
94 }
95 yPlane += yStride;
Ruben Brunk433e7152014-12-10 19:12:41 -080096 if (jEven) {
Ruben Brunk89735972014-12-11 12:55:44 -080097 crPlane += chromaStride;
98 cbPlane += chromaStride;
Ruben Brunkfeb50af2014-05-09 19:58:49 -070099 }
100 }
101}
102
Ruben Brunk31798f32014-09-25 19:56:54 -0700103static void rgbToYuv420(uint8_t* rgbBuf, size_t width, size_t height, android_ycbcr* ycbcr) {
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700104 size_t cStep = ycbcr->chroma_step;
105 size_t cStride = ycbcr->cstride;
106 size_t yStride = ycbcr->ystride;
Ruben Brunk433e7152014-12-10 19:12:41 -0800107 ALOGV("%s: yStride is: %zu, cStride is: %zu, cStep is: %zu", __FUNCTION__, yStride, cStride,
108 cStep);
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700109 rgbToYuv420(rgbBuf, width, height, reinterpret_cast<uint8_t*>(ycbcr->y),
Ruben Brunk433e7152014-12-10 19:12:41 -0800110 reinterpret_cast<uint8_t*>(ycbcr->cr), reinterpret_cast<uint8_t*>(ycbcr->cb),
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700111 cStep, yStride, cStride);
112}
113
Chien-Yu Chen29c36302016-03-02 15:34:00 -0800114static status_t connectSurface(const sp<Surface>& surface, int32_t maxBufferSlack) {
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700115 status_t err = NO_ERROR;
Chien-Yu Chen29c36302016-03-02 15:34:00 -0800116
117 err = surface->connect(NATIVE_WINDOW_API_CAMERA, /*listener*/NULL);
118 if (err != OK) {
119 ALOGE("%s: Unable to connect to surface, error %s (%d).", __FUNCTION__,
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700120 strerror(-err), err);
121 return err;
122 }
123
Chien-Yu Chen29c36302016-03-02 15:34:00 -0800124 err = native_window_set_usage(surface.get(), GRALLOC_USAGE_SW_WRITE_OFTEN);
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700125 if (err != NO_ERROR) {
126 ALOGE("%s: Failed to set native window usage flag, error %s (%d).", __FUNCTION__,
127 strerror(-err), err);
Yin-Chia Yeh36ceaca2018-03-16 11:05:37 -0700128 OVERRIDE_SURFACE_ERROR(err);
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700129 return err;
130 }
131
132 int minUndequeuedBuffers;
Chien-Yu Chen29c36302016-03-02 15:34:00 -0800133 err = static_cast<ANativeWindow*>(surface.get())->query(surface.get(),
134 NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBuffers);
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700135 if (err != NO_ERROR) {
136 ALOGE("%s: Failed to get native window min undequeued buffers, error %s (%d).",
137 __FUNCTION__, strerror(-err), err);
Yin-Chia Yeh36ceaca2018-03-16 11:05:37 -0700138 OVERRIDE_SURFACE_ERROR(err);
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700139 return err;
140 }
141
Chien-Yu Chen29c36302016-03-02 15:34:00 -0800142 ALOGV("%s: Setting buffer count to %d", __FUNCTION__,
143 maxBufferSlack + 1 + minUndequeuedBuffers);
144 err = native_window_set_buffer_count(surface.get(), maxBufferSlack + 1 + minUndequeuedBuffers);
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700145 if (err != NO_ERROR) {
146 ALOGE("%s: Failed to set native window buffer count, error %s (%d).", __FUNCTION__,
147 strerror(-err), err);
Yin-Chia Yeh36ceaca2018-03-16 11:05:37 -0700148 OVERRIDE_SURFACE_ERROR(err);
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700149 return err;
150 }
151 return NO_ERROR;
152}
153
154/**
155 * Produce a frame in the given surface.
156 *
157 * Args:
158 * anw - a surface to produce a frame in.
159 * pixelBuffer - image buffer to generate a frame from.
160 * width - width of the pixelBuffer in pixels.
161 * height - height of the pixelBuffer in pixels.
162 * pixelFmt - format of the pixelBuffer, one of:
163 * HAL_PIXEL_FORMAT_YCrCb_420_SP,
164 * HAL_PIXEL_FORMAT_YCbCr_420_888,
165 * HAL_PIXEL_FORMAT_BLOB
166 * bufSize - the size of the pixelBuffer in bytes.
167 */
168static status_t produceFrame(const sp<ANativeWindow>& anw,
169 uint8_t* pixelBuffer,
Ruben Brunk31798f32014-09-25 19:56:54 -0700170 int32_t bufWidth, // Width of the pixelBuffer
171 int32_t bufHeight, // Height of the pixelBuffer
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700172 int32_t pixelFmt, // Format of the pixelBuffer
Igor Murashkin5096def2014-06-24 10:49:11 -0700173 int32_t bufSize) {
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700174 ATRACE_CALL();
175 status_t err = NO_ERROR;
176 ANativeWindowBuffer* anb;
Igor Murashkin5096def2014-06-24 10:49:11 -0700177 ALOGV("%s: Dequeue buffer from %p %dx%d (fmt=%x, size=%x)",
Ruben Brunk31798f32014-09-25 19:56:54 -0700178 __FUNCTION__, anw.get(), bufWidth, bufHeight, pixelFmt, bufSize);
Igor Murashkin5096def2014-06-24 10:49:11 -0700179
180 if (anw == 0) {
181 ALOGE("%s: anw must not be NULL", __FUNCTION__);
182 return BAD_VALUE;
183 } else if (pixelBuffer == NULL) {
184 ALOGE("%s: pixelBuffer must not be NULL", __FUNCTION__);
185 return BAD_VALUE;
Ruben Brunk31798f32014-09-25 19:56:54 -0700186 } else if (bufWidth < 0) {
Igor Murashkin5096def2014-06-24 10:49:11 -0700187 ALOGE("%s: width must be non-negative", __FUNCTION__);
188 return BAD_VALUE;
Ruben Brunk31798f32014-09-25 19:56:54 -0700189 } else if (bufHeight < 0) {
Igor Murashkin5096def2014-06-24 10:49:11 -0700190 ALOGE("%s: height must be non-negative", __FUNCTION__);
191 return BAD_VALUE;
192 } else if (bufSize < 0) {
193 ALOGE("%s: bufSize must be non-negative", __FUNCTION__);
194 return BAD_VALUE;
195 }
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700196
Ruben Brunk31798f32014-09-25 19:56:54 -0700197 size_t width = static_cast<size_t>(bufWidth);
198 size_t height = static_cast<size_t>(bufHeight);
199 size_t bufferLength = static_cast<size_t>(bufSize);
Ruben Brunk91b9aab2014-06-20 00:24:56 -0700200
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700201 // TODO: Switch to using Surface::lock and Surface::unlockAndPost
202 err = native_window_dequeue_buffer_and_wait(anw.get(), &anb);
Yin-Chia Yeh36ceaca2018-03-16 11:05:37 -0700203 if (err != NO_ERROR) {
204 ALOGE("%s: Failed to dequeue buffer, error %s (%d).", __FUNCTION__,
205 strerror(-err), err);
206 OVERRIDE_SURFACE_ERROR(err);
207 return err;
208 }
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700209
Mathias Agopian845eef05f2017-04-03 17:51:15 -0700210 sp<GraphicBuffer> buf(GraphicBuffer::from(anb));
Ruben Brunk0c798842014-09-30 03:42:13 -0700211 uint32_t grallocBufWidth = buf->getWidth();
212 uint32_t grallocBufHeight = buf->getHeight();
213 uint32_t grallocBufStride = buf->getStride();
214 if (grallocBufWidth != width || grallocBufHeight != height) {
Ruben Brunk31798f32014-09-25 19:56:54 -0700215 ALOGE("%s: Received gralloc buffer with bad dimensions %" PRIu32 "x%" PRIu32
Ruben Brunk0c798842014-09-30 03:42:13 -0700216 ", expecting dimensions %zu x %zu", __FUNCTION__, grallocBufWidth,
217 grallocBufHeight, width, height);
Ruben Brunk31798f32014-09-25 19:56:54 -0700218 return BAD_VALUE;
219 }
220
221 int32_t bufFmt = 0;
222 err = anw->query(anw.get(), NATIVE_WINDOW_FORMAT, &bufFmt);
223 if (err != NO_ERROR) {
224 ALOGE("%s: Error while querying surface pixel format %s (%d).", __FUNCTION__,
225 strerror(-err), err);
Yin-Chia Yeh36ceaca2018-03-16 11:05:37 -0700226 OVERRIDE_SURFACE_ERROR(err);
Ruben Brunk31798f32014-09-25 19:56:54 -0700227 return err;
228 }
229
Ruben Brunk0c798842014-09-30 03:42:13 -0700230 uint64_t tmpSize = (pixelFmt == HAL_PIXEL_FORMAT_BLOB) ? grallocBufWidth :
231 4 * grallocBufHeight * grallocBufWidth;
Ruben Brunk31798f32014-09-25 19:56:54 -0700232 if (bufFmt != pixelFmt) {
233 if (bufFmt == HAL_PIXEL_FORMAT_RGBA_8888 && pixelFmt == HAL_PIXEL_FORMAT_BLOB) {
234 ALOGV("%s: Using BLOB to RGBA format override.", __FUNCTION__);
Ruben Brunk0c798842014-09-30 03:42:13 -0700235 tmpSize = 4 * (grallocBufWidth + grallocBufStride * (grallocBufHeight - 1));
Ruben Brunk31798f32014-09-25 19:56:54 -0700236 } else {
237 ALOGW("%s: Format mismatch in produceFrame: expecting format %#" PRIx32
238 ", but received buffer with format %#" PRIx32, __FUNCTION__, pixelFmt, bufFmt);
239 }
240 }
241
242 if (tmpSize > SIZE_MAX) {
243 ALOGE("%s: Overflow calculating size, buffer with dimens %zu x %zu is absurdly large...",
244 __FUNCTION__, width, height);
245 return BAD_VALUE;
246 }
247
248 size_t totalSizeBytes = tmpSize;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700249
Ruben Brunk433e7152014-12-10 19:12:41 -0800250 ALOGV("%s: Pixel format chosen: %x", __FUNCTION__, pixelFmt);
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700251 switch(pixelFmt) {
252 case HAL_PIXEL_FORMAT_YCrCb_420_SP: {
Ruben Brunk31798f32014-09-25 19:56:54 -0700253 if (bufferLength < totalSizeBytes) {
254 ALOGE("%s: PixelBuffer size %zu too small for given dimensions",
255 __FUNCTION__, bufferLength);
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700256 return BAD_VALUE;
257 }
258 uint8_t* img = NULL;
259 ALOGV("%s: Lock buffer from %p for write", __FUNCTION__, anw.get());
260 err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
261 if (err != NO_ERROR) return err;
262
263 uint8_t* yPlane = img;
264 uint8_t* uPlane = img + height * width;
265 uint8_t* vPlane = uPlane + 1;
266 size_t chromaStep = 2;
267 size_t yStride = width;
268 size_t chromaStride = width;
269
270 rgbToYuv420(pixelBuffer, width, height, yPlane,
271 uPlane, vPlane, chromaStep, yStride, chromaStride);
272 break;
273 }
Ruben Brunk91b9aab2014-06-20 00:24:56 -0700274 case HAL_PIXEL_FORMAT_YV12: {
Ruben Brunk31798f32014-09-25 19:56:54 -0700275 if (bufferLength < totalSizeBytes) {
276 ALOGE("%s: PixelBuffer size %zu too small for given dimensions",
277 __FUNCTION__, bufferLength);
Ruben Brunk91b9aab2014-06-20 00:24:56 -0700278 return BAD_VALUE;
279 }
280
281 if ((width & 1) || (height & 1)) {
Ruben Brunk31798f32014-09-25 19:56:54 -0700282 ALOGE("%s: Dimens %zu x %zu are not divisible by 2.", __FUNCTION__, width, height);
Ruben Brunk91b9aab2014-06-20 00:24:56 -0700283 return BAD_VALUE;
284 }
285
286 uint8_t* img = NULL;
287 ALOGV("%s: Lock buffer from %p for write", __FUNCTION__, anw.get());
288 err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
289 if (err != NO_ERROR) {
290 ALOGE("%s: Error %s (%d) while locking gralloc buffer for write.", __FUNCTION__,
291 strerror(-err), err);
292 return err;
293 }
294
295 uint32_t stride = buf->getStride();
Ruben Brunk433e7152014-12-10 19:12:41 -0800296 ALOGV("%s: stride is: %" PRIu32, __FUNCTION__, stride);
Ruben Brunk91b9aab2014-06-20 00:24:56 -0700297 LOG_ALWAYS_FATAL_IF(stride % 16, "Stride is not 16 pixel aligned %d", stride);
298
299 uint32_t cStride = ALIGN(stride / 2, 16);
300 size_t chromaStep = 1;
301
302 uint8_t* yPlane = img;
303 uint8_t* crPlane = img + static_cast<uint32_t>(height) * stride;
304 uint8_t* cbPlane = crPlane + cStride * static_cast<uint32_t>(height) / 2;
305
306 rgbToYuv420(pixelBuffer, width, height, yPlane,
307 crPlane, cbPlane, chromaStep, stride, cStride);
308 break;
309 }
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700310 case HAL_PIXEL_FORMAT_YCbCr_420_888: {
311 // Software writes with YCbCr_420_888 format are unsupported
312 // by the gralloc module for now
Ruben Brunk31798f32014-09-25 19:56:54 -0700313 if (bufferLength < totalSizeBytes) {
314 ALOGE("%s: PixelBuffer size %zu too small for given dimensions",
315 __FUNCTION__, bufferLength);
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700316 return BAD_VALUE;
317 }
318 android_ycbcr ycbcr = android_ycbcr();
319 ALOGV("%s: Lock buffer from %p for write", __FUNCTION__, anw.get());
320
321 err = buf->lockYCbCr(GRALLOC_USAGE_SW_WRITE_OFTEN, &ycbcr);
322 if (err != NO_ERROR) {
323 ALOGE("%s: Failed to lock ycbcr buffer, error %s (%d).", __FUNCTION__,
324 strerror(-err), err);
325 return err;
326 }
327 rgbToYuv420(pixelBuffer, width, height, &ycbcr);
328 break;
329 }
330 case HAL_PIXEL_FORMAT_BLOB: {
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700331 int8_t* img = NULL;
Ruben Brunk0fd198a2014-09-23 23:35:43 -0700332 struct camera3_jpeg_blob footer = {
Bernhard Rosenkränzer452efb22014-11-17 23:42:21 +0100333 .jpeg_blob_id = CAMERA3_JPEG_BLOB_ID,
334 .jpeg_size = (uint32_t)bufferLength
Ruben Brunk0fd198a2014-09-23 23:35:43 -0700335 };
336
Ruben Brunk31798f32014-09-25 19:56:54 -0700337 size_t totalJpegSize = bufferLength + sizeof(footer);
338 totalJpegSize = (totalJpegSize + 3) & ~0x3; // round up to nearest octonibble
339
Ruben Brunk31798f32014-09-25 19:56:54 -0700340 if (totalJpegSize > totalSizeBytes) {
341 ALOGE("%s: Pixel buffer needs size %zu, cannot fit in gralloc buffer of size %zu",
342 __FUNCTION__, totalJpegSize, totalSizeBytes);
343 return BAD_VALUE;
344 }
345
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700346 err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
347 if (err != NO_ERROR) {
348 ALOGE("%s: Failed to lock buffer, error %s (%d).", __FUNCTION__, strerror(-err),
349 err);
350 return err;
351 }
Ruben Brunk31798f32014-09-25 19:56:54 -0700352
353 memcpy(img, pixelBuffer, bufferLength);
354 memcpy(img + totalSizeBytes - sizeof(footer), &footer, sizeof(footer));
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700355 break;
356 }
357 default: {
358 ALOGE("%s: Invalid pixel format in produceFrame: %x", __FUNCTION__, pixelFmt);
359 return BAD_VALUE;
360 }
361 }
362
363 ALOGV("%s: Unlock buffer from %p", __FUNCTION__, anw.get());
364 err = buf->unlock();
365 if (err != NO_ERROR) {
366 ALOGE("%s: Failed to unlock buffer, error %s (%d).", __FUNCTION__, strerror(-err), err);
367 return err;
368 }
369
370 ALOGV("%s: Queue buffer to %p", __FUNCTION__, anw.get());
371 err = anw->queueBuffer(anw.get(), buf->getNativeBuffer(), /*fenceFd*/-1);
372 if (err != NO_ERROR) {
373 ALOGE("%s: Failed to queue buffer, error %s (%d).", __FUNCTION__, strerror(-err), err);
Yin-Chia Yeh36ceaca2018-03-16 11:05:37 -0700374 OVERRIDE_SURFACE_ERROR(err);
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700375 return err;
376 }
377 return NO_ERROR;
378}
379
380static sp<ANativeWindow> getNativeWindow(JNIEnv* env, jobject surface) {
381 sp<ANativeWindow> anw;
382 if (surface) {
383 anw = android_view_Surface_getNativeWindow(env, surface);
384 if (env->ExceptionCheck()) {
Ruben Brunk3c8fa3b2014-06-30 16:45:05 -0700385 return NULL;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700386 }
387 } else {
388 jniThrowNullPointerException(env, "surface");
Ruben Brunk3c8fa3b2014-06-30 16:45:05 -0700389 return NULL;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700390 }
391 if (anw == NULL) {
Ruben Brunk443ab2c2015-03-12 20:54:03 -0700392 ALOGE("%s: Surface had no valid native window.", __FUNCTION__);
Ruben Brunk3c8fa3b2014-06-30 16:45:05 -0700393 return NULL;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700394 }
395 return anw;
396}
397
Fedor Kudasov25b18842019-06-24 17:38:38 +0100398static sp<ANativeWindow> getSurfaceTextureNativeWindow(JNIEnv* env, jobject thiz) {
Fedor Kudasov25b18842019-06-24 17:38:38 +0100399 sp<IGraphicBufferProducer> producer(SurfaceTexture_getProducer(env, thiz));
Derek Sollenbergereec1b862019-10-24 09:44:55 -0400400 sp<Surface> surfaceTextureClient(producer != NULL ? new Surface(producer) : NULL);
Fedor Kudasov25b18842019-06-24 17:38:38 +0100401 return surfaceTextureClient;
402}
403
Ruben Brunk28c49c92014-06-16 18:43:59 -0700404static sp<ANativeWindow> getNativeWindowFromTexture(JNIEnv* env, jobject surfaceTexture) {
405 sp<ANativeWindow> anw;
406 if (surfaceTexture) {
Fedor Kudasov25b18842019-06-24 17:38:38 +0100407 anw = getSurfaceTextureNativeWindow(env, surfaceTexture);
Ruben Brunk28c49c92014-06-16 18:43:59 -0700408 if (env->ExceptionCheck()) {
409 return NULL;
410 }
411 } else {
412 jniThrowNullPointerException(env, "surfaceTexture");
413 return NULL;
414 }
415 if (anw == NULL) {
416 jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
417 "SurfaceTexture had no valid native window.");
418 return NULL;
419 }
420 return anw;
421}
422
Ruben Brunk3c8fa3b2014-06-30 16:45:05 -0700423static sp<Surface> getSurface(JNIEnv* env, jobject surface) {
424 sp<Surface> s;
425 if (surface) {
426 s = android_view_Surface_getSurface(env, surface);
427 if (env->ExceptionCheck()) {
428 return NULL;
429 }
430 } else {
431 jniThrowNullPointerException(env, "surface");
432 return NULL;
433 }
434 if (s == NULL) {
435 jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
436 "Surface had no valid native Surface.");
437 return NULL;
438 }
439 return s;
440}
441
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700442extern "C" {
443
444static jint LegacyCameraDevice_nativeDetectSurfaceType(JNIEnv* env, jobject thiz, jobject surface) {
445 ALOGV("nativeDetectSurfaceType");
446 sp<ANativeWindow> anw;
447 if ((anw = getNativeWindow(env, surface)) == NULL) {
448 ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
Ruben Brunkef14da32014-06-24 16:06:54 -0700449 return BAD_VALUE;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700450 }
451 int32_t fmt = 0;
452 status_t err = anw->query(anw.get(), NATIVE_WINDOW_FORMAT, &fmt);
453 if(err != NO_ERROR) {
Ruben Brunkef14da32014-06-24 16:06:54 -0700454 ALOGE("%s: Error while querying surface pixel format %s (%d).", __FUNCTION__, strerror(-err),
455 err);
Yin-Chia Yeh36ceaca2018-03-16 11:05:37 -0700456 OVERRIDE_SURFACE_ERROR(err);
Ruben Brunkef14da32014-06-24 16:06:54 -0700457 return err;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700458 }
459 return fmt;
460}
461
Eino-Ville Talvalae3651202015-06-19 17:29:14 -0700462static jint LegacyCameraDevice_nativeDetectSurfaceDataspace(JNIEnv* env, jobject thiz, jobject surface) {
463 ALOGV("nativeDetectSurfaceDataspace");
464 sp<ANativeWindow> anw;
465 if ((anw = getNativeWindow(env, surface)) == NULL) {
466 ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
467 return BAD_VALUE;
468 }
469 int32_t fmt = 0;
470 status_t err = anw->query(anw.get(), NATIVE_WINDOW_DEFAULT_DATASPACE, &fmt);
471 if(err != NO_ERROR) {
472 ALOGE("%s: Error while querying surface dataspace %s (%d).", __FUNCTION__, strerror(-err),
473 err);
Yin-Chia Yeh36ceaca2018-03-16 11:05:37 -0700474 OVERRIDE_SURFACE_ERROR(err);
Eino-Ville Talvalae3651202015-06-19 17:29:14 -0700475 return err;
476 }
477 return fmt;
478}
479
Ruben Brunkef14da32014-06-24 16:06:54 -0700480static jint LegacyCameraDevice_nativeDetectSurfaceDimens(JNIEnv* env, jobject thiz,
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700481 jobject surface, jintArray dimens) {
482 ALOGV("nativeGetSurfaceDimens");
Ruben Brunk28c49c92014-06-16 18:43:59 -0700483
484 if (dimens == NULL) {
485 ALOGE("%s: Null dimens argument passed to nativeDetectSurfaceDimens", __FUNCTION__);
486 return BAD_VALUE;
487 }
488
489 if (env->GetArrayLength(dimens) < 2) {
490 ALOGE("%s: Invalid length of dimens argument in nativeDetectSurfaceDimens", __FUNCTION__);
491 return BAD_VALUE;
492 }
493
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700494 sp<ANativeWindow> anw;
495 if ((anw = getNativeWindow(env, surface)) == NULL) {
496 ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
Ruben Brunkef14da32014-06-24 16:06:54 -0700497 return BAD_VALUE;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700498 }
499 int32_t dimenBuf[2];
500 status_t err = anw->query(anw.get(), NATIVE_WINDOW_WIDTH, dimenBuf);
501 if(err != NO_ERROR) {
Ruben Brunkef14da32014-06-24 16:06:54 -0700502 ALOGE("%s: Error while querying surface width %s (%d).", __FUNCTION__, strerror(-err),
503 err);
Yin-Chia Yeh36ceaca2018-03-16 11:05:37 -0700504 OVERRIDE_SURFACE_ERROR(err);
Ruben Brunkef14da32014-06-24 16:06:54 -0700505 return err;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700506 }
507 err = anw->query(anw.get(), NATIVE_WINDOW_HEIGHT, dimenBuf + 1);
508 if(err != NO_ERROR) {
Ruben Brunkef14da32014-06-24 16:06:54 -0700509 ALOGE("%s: Error while querying surface height %s (%d).", __FUNCTION__, strerror(-err),
510 err);
Yin-Chia Yeh36ceaca2018-03-16 11:05:37 -0700511 OVERRIDE_SURFACE_ERROR(err);
Ruben Brunkef14da32014-06-24 16:06:54 -0700512 return err;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700513 }
514 env->SetIntArrayRegion(dimens, /*start*/0, /*length*/ARRAY_SIZE(dimenBuf), dimenBuf);
Ruben Brunkef14da32014-06-24 16:06:54 -0700515 return NO_ERROR;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700516}
517
Ruben Brunkf4a637d2014-11-20 18:01:36 -0800518static jint LegacyCameraDevice_nativeDetectSurfaceUsageFlags(JNIEnv* env, jobject thiz,
519 jobject surface) {
520 ALOGV("nativeDetectSurfaceUsageFlags");
521
522 sp<ANativeWindow> anw;
523 if ((anw = getNativeWindow(env, surface)) == NULL) {
Yin-Chia Yeh92843952018-11-27 14:23:40 -0800524 jniThrowException(env, "java/lang/UnsupportedOperationException",
Ruben Brunkf4a637d2014-11-20 18:01:36 -0800525 "Could not retrieve native window from surface.");
526 return BAD_VALUE;
527 }
528 int32_t usage = 0;
529 status_t err = anw->query(anw.get(), NATIVE_WINDOW_CONSUMER_USAGE_BITS, &usage);
530 if(err != NO_ERROR) {
Yin-Chia Yeh92843952018-11-27 14:23:40 -0800531 jniThrowException(env, "java/lang/UnsupportedOperationException",
Ruben Brunkf4a637d2014-11-20 18:01:36 -0800532 "Error while querying surface usage bits");
Yin-Chia Yeh36ceaca2018-03-16 11:05:37 -0700533 OVERRIDE_SURFACE_ERROR(err);
Ruben Brunkf4a637d2014-11-20 18:01:36 -0800534 return err;
535 }
536 return usage;
537}
538
Chien-Yu Chen29c36302016-03-02 15:34:00 -0800539static jint LegacyCameraDevice_nativeDisconnectSurface(JNIEnv* env, jobject thiz,
540 jobject surface) {
541 ALOGV("nativeDisconnectSurface");
542 if (surface == nullptr) return NO_ERROR;
543
544 sp<ANativeWindow> anw;
545 if ((anw = getNativeWindow(env, surface)) == NULL) {
546 ALOGV("Buffer queue has already been abandoned.");
547 return NO_ERROR;
548 }
549
550 status_t err = native_window_api_disconnect(anw.get(), NATIVE_WINDOW_API_CAMERA);
551 if(err != NO_ERROR) {
Yin-Chia Yeh92843952018-11-27 14:23:40 -0800552 jniThrowException(env, "java/lang/UnsupportedOperationException",
Chien-Yu Chen29c36302016-03-02 15:34:00 -0800553 "Error while disconnecting surface");
Yin-Chia Yeh36ceaca2018-03-16 11:05:37 -0700554 OVERRIDE_SURFACE_ERROR(err);
Chien-Yu Chen29c36302016-03-02 15:34:00 -0800555 return err;
556 }
557 return NO_ERROR;
558}
559
Ruben Brunk28c49c92014-06-16 18:43:59 -0700560static jint LegacyCameraDevice_nativeDetectTextureDimens(JNIEnv* env, jobject thiz,
561 jobject surfaceTexture, jintArray dimens) {
562 ALOGV("nativeDetectTextureDimens");
563 sp<ANativeWindow> anw;
564 if ((anw = getNativeWindowFromTexture(env, surfaceTexture)) == NULL) {
565 ALOGE("%s: Could not retrieve native window from SurfaceTexture.", __FUNCTION__);
566 return BAD_VALUE;
567 }
568
569 int32_t dimenBuf[2];
570 status_t err = anw->query(anw.get(), NATIVE_WINDOW_WIDTH, dimenBuf);
571 if(err != NO_ERROR) {
572 ALOGE("%s: Error while querying SurfaceTexture width %s (%d)", __FUNCTION__,
573 strerror(-err), err);
Yin-Chia Yeh36ceaca2018-03-16 11:05:37 -0700574 OVERRIDE_SURFACE_ERROR(err);
Ruben Brunk28c49c92014-06-16 18:43:59 -0700575 return err;
576 }
577
578 err = anw->query(anw.get(), NATIVE_WINDOW_HEIGHT, dimenBuf + 1);
579 if(err != NO_ERROR) {
580 ALOGE("%s: Error while querying SurfaceTexture height %s (%d)", __FUNCTION__,
581 strerror(-err), err);
Yin-Chia Yeh36ceaca2018-03-16 11:05:37 -0700582 OVERRIDE_SURFACE_ERROR(err);
Ruben Brunk28c49c92014-06-16 18:43:59 -0700583 return err;
584 }
585
586 env->SetIntArrayRegion(dimens, /*start*/0, /*length*/ARRAY_SIZE(dimenBuf), dimenBuf);
587 if (env->ExceptionCheck()) {
588 return BAD_VALUE;
589 }
590 return NO_ERROR;
591}
592
Chien-Yu Chen29c36302016-03-02 15:34:00 -0800593static jint LegacyCameraDevice_nativeConnectSurface(JNIEnv* env, jobject thiz, jobject surface) {
594 ALOGV("nativeConnectSurface");
595 sp<Surface> s;
596 if ((s = getSurface(env, surface)) == NULL) {
597 ALOGE("%s: Could not retrieve surface.", __FUNCTION__);
Ruben Brunkef14da32014-06-24 16:06:54 -0700598 return BAD_VALUE;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700599 }
Chien-Yu Chen29c36302016-03-02 15:34:00 -0800600 status_t err = connectSurface(s, CAMERA_DEVICE_BUFFER_SLACK);
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700601 if (err != NO_ERROR) {
Ruben Brunkef14da32014-06-24 16:06:54 -0700602 ALOGE("%s: Error while configuring surface %s (%d).", __FUNCTION__, strerror(-err), err);
Yin-Chia Yeh36ceaca2018-03-16 11:05:37 -0700603 OVERRIDE_SURFACE_ERROR(err);
Ruben Brunkef14da32014-06-24 16:06:54 -0700604 return err;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700605 }
Ruben Brunkef14da32014-06-24 16:06:54 -0700606 return NO_ERROR;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700607}
608
Ruben Brunkef14da32014-06-24 16:06:54 -0700609static jint LegacyCameraDevice_nativeProduceFrame(JNIEnv* env, jobject thiz, jobject surface,
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700610 jbyteArray pixelBuffer, jint width, jint height, jint pixelFormat) {
611 ALOGV("nativeProduceFrame");
612 sp<ANativeWindow> anw;
613
614 if ((anw = getNativeWindow(env, surface)) == NULL) {
615 ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
Ruben Brunkef14da32014-06-24 16:06:54 -0700616 return BAD_VALUE;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700617 }
618
619 if (pixelBuffer == NULL) {
620 jniThrowNullPointerException(env, "pixelBuffer");
Ruben Brunkef14da32014-06-24 16:06:54 -0700621 return DONT_CARE;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700622 }
623
624 int32_t bufSize = static_cast<int32_t>(env->GetArrayLength(pixelBuffer));
625 jbyte* pixels = env->GetByteArrayElements(pixelBuffer, /*is_copy*/NULL);
626
627 if (pixels == NULL) {
628 jniThrowNullPointerException(env, "pixels");
Ruben Brunkef14da32014-06-24 16:06:54 -0700629 return DONT_CARE;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700630 }
631
632 status_t err = produceFrame(anw, reinterpret_cast<uint8_t*>(pixels), width, height,
633 pixelFormat, bufSize);
634 env->ReleaseByteArrayElements(pixelBuffer, pixels, JNI_ABORT);
635
636 if (err != NO_ERROR) {
Ruben Brunkef14da32014-06-24 16:06:54 -0700637 ALOGE("%s: Error while producing frame %s (%d).", __FUNCTION__, strerror(-err), err);
638 return err;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700639 }
Ruben Brunkef14da32014-06-24 16:06:54 -0700640 return NO_ERROR;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700641}
642
Ruben Brunkef14da32014-06-24 16:06:54 -0700643static jint LegacyCameraDevice_nativeSetSurfaceFormat(JNIEnv* env, jobject thiz, jobject surface,
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700644 jint pixelFormat) {
645 ALOGV("nativeSetSurfaceType");
646 sp<ANativeWindow> anw;
647 if ((anw = getNativeWindow(env, surface)) == NULL) {
648 ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
Ruben Brunkef14da32014-06-24 16:06:54 -0700649 return BAD_VALUE;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700650 }
651 status_t err = native_window_set_buffers_format(anw.get(), pixelFormat);
652 if (err != NO_ERROR) {
Ruben Brunkef14da32014-06-24 16:06:54 -0700653 ALOGE("%s: Error while setting surface format %s (%d).", __FUNCTION__, strerror(-err), err);
Yin-Chia Yeh36ceaca2018-03-16 11:05:37 -0700654 OVERRIDE_SURFACE_ERROR(err);
Ruben Brunkef14da32014-06-24 16:06:54 -0700655 return err;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700656 }
Ruben Brunkef14da32014-06-24 16:06:54 -0700657 return NO_ERROR;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700658}
659
Ruben Brunkef14da32014-06-24 16:06:54 -0700660static jint LegacyCameraDevice_nativeSetSurfaceDimens(JNIEnv* env, jobject thiz, jobject surface,
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700661 jint width, jint height) {
662 ALOGV("nativeSetSurfaceDimens");
663 sp<ANativeWindow> anw;
664 if ((anw = getNativeWindow(env, surface)) == NULL) {
665 ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
Ruben Brunkef14da32014-06-24 16:06:54 -0700666 return BAD_VALUE;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700667 }
Ruben Brunka9bc3552014-08-14 15:57:28 -0700668
Eino-Ville Talvalab0acf7f2015-02-11 15:41:12 -0800669 // Set user dimensions only
670 // The producer dimensions are owned by GL
671 status_t err = native_window_set_buffers_user_dimensions(anw.get(), width, height);
Ruben Brunka9bc3552014-08-14 15:57:28 -0700672 if (err != NO_ERROR) {
673 ALOGE("%s: Error while setting surface user dimens %s (%d).", __FUNCTION__, strerror(-err),
674 err);
Yin-Chia Yeh36ceaca2018-03-16 11:05:37 -0700675 OVERRIDE_SURFACE_ERROR(err);
Ruben Brunka9bc3552014-08-14 15:57:28 -0700676 return err;
677 }
Ruben Brunkef14da32014-06-24 16:06:54 -0700678 return NO_ERROR;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700679}
680
Ruben Brunk3c8fa3b2014-06-30 16:45:05 -0700681static jlong LegacyCameraDevice_nativeGetSurfaceId(JNIEnv* env, jobject thiz, jobject surface) {
682 ALOGV("nativeGetSurfaceId");
683 sp<Surface> s;
684 if ((s = getSurface(env, surface)) == NULL) {
685 ALOGE("%s: Could not retrieve native Surface from surface.", __FUNCTION__);
686 return 0;
687 }
688 sp<IGraphicBufferProducer> gbp = s->getIGraphicBufferProducer();
689 if (gbp == NULL) {
690 ALOGE("%s: Could not retrieve IGraphicBufferProducer from surface.", __FUNCTION__);
691 return 0;
692 }
Marco Nelissen97069dd2014-11-14 08:00:42 -0800693 sp<IBinder> b = IInterface::asBinder(gbp);
Ruben Brunk3c8fa3b2014-06-30 16:45:05 -0700694 if (b == NULL) {
695 ALOGE("%s: Could not retrieve IBinder from surface.", __FUNCTION__);
696 return 0;
697 }
698 /*
699 * FIXME: Use better unique ID for surfaces than native IBinder pointer. Fix also in the camera
700 * service (CameraDeviceClient.h).
701 */
702 return reinterpret_cast<jlong>(b.get());
703}
704
Ruben Brunk28c49c92014-06-16 18:43:59 -0700705static jint LegacyCameraDevice_nativeSetSurfaceOrientation(JNIEnv* env, jobject thiz,
706 jobject surface, jint facing, jint orientation) {
707 ALOGV("nativeSetSurfaceOrientation");
708 sp<ANativeWindow> anw;
709 if ((anw = getNativeWindow(env, surface)) == NULL) {
710 ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
711 return BAD_VALUE;
712 }
713
714 status_t err = NO_ERROR;
715 CameraMetadata staticMetadata;
716
717 int32_t orientVal = static_cast<int32_t>(orientation);
718 uint8_t facingVal = static_cast<uint8_t>(facing);
719 staticMetadata.update(ANDROID_SENSOR_ORIENTATION, &orientVal, 1);
720 staticMetadata.update(ANDROID_LENS_FACING, &facingVal, 1);
721
722 int32_t transform = 0;
723
Ruben Brunk91838de2014-07-16 17:24:17 -0700724 if ((err = CameraUtils::getRotationTransform(staticMetadata, /*out*/&transform)) != NO_ERROR) {
Ruben Brunk28c49c92014-06-16 18:43:59 -0700725 ALOGE("%s: Invalid rotation transform %s (%d)", __FUNCTION__, strerror(-err),
726 err);
727 return err;
728 }
729
730 ALOGV("%s: Setting buffer sticky transform to %d", __FUNCTION__, transform);
731
Ruben Brunk91838de2014-07-16 17:24:17 -0700732 if ((err = native_window_set_buffers_sticky_transform(anw.get(), transform)) != NO_ERROR) {
Ruben Brunk28c49c92014-06-16 18:43:59 -0700733 ALOGE("%s: Unable to configure surface transform, error %s (%d)", __FUNCTION__,
734 strerror(-err), err);
735 return err;
736 }
737
738 return NO_ERROR;
739}
740
Ruben Brunk91838de2014-07-16 17:24:17 -0700741static jint LegacyCameraDevice_nativeSetNextTimestamp(JNIEnv* env, jobject thiz, jobject surface,
742 jlong timestamp) {
743 ALOGV("nativeSetNextTimestamp");
744 sp<ANativeWindow> anw;
745 if ((anw = getNativeWindow(env, surface)) == NULL) {
746 ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
747 return BAD_VALUE;
748 }
749
750 status_t err = NO_ERROR;
751
752 if ((err = native_window_set_buffers_timestamp(anw.get(), static_cast<int64_t>(timestamp))) !=
753 NO_ERROR) {
754 ALOGE("%s: Unable to set surface timestamp, error %s (%d)", __FUNCTION__, strerror(-err),
755 err);
756 return err;
757 }
758 return NO_ERROR;
759}
760
Ruben Brunka94c6032015-06-10 16:44:28 -0700761static jint LegacyCameraDevice_nativeSetScalingMode(JNIEnv* env, jobject thiz, jobject surface,
762 jint mode) {
763 ALOGV("nativeSetScalingMode");
764 sp<ANativeWindow> anw;
765 if ((anw = getNativeWindow(env, surface)) == NULL) {
766 ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
767 return BAD_VALUE;
768 }
769 status_t err = NO_ERROR;
770 if ((err = native_window_set_scaling_mode(anw.get(), static_cast<int>(mode))) != NO_ERROR) {
771 ALOGE("%s: Unable to set surface scaling mode, error %s (%d)", __FUNCTION__,
772 strerror(-err), err);
773 return err;
774 }
775 return NO_ERROR;
776}
777
Ruben Brunk1dc13262014-07-31 11:43:27 -0700778static jint LegacyCameraDevice_nativeGetJpegFooterSize(JNIEnv* env, jobject thiz) {
779 ALOGV("nativeGetJpegFooterSize");
780 return static_cast<jint>(sizeof(struct camera3_jpeg_blob));
781}
782
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700783} // extern "C"
784
Daniel Micay76f6a862015-09-19 17:31:01 -0400785static const JNINativeMethod gCameraDeviceMethods[] = {
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700786 { "nativeDetectSurfaceType",
787 "(Landroid/view/Surface;)I",
788 (void *)LegacyCameraDevice_nativeDetectSurfaceType },
Eino-Ville Talvalae3651202015-06-19 17:29:14 -0700789 { "nativeDetectSurfaceDataspace",
790 "(Landroid/view/Surface;)I",
791 (void *)LegacyCameraDevice_nativeDetectSurfaceDataspace },
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700792 { "nativeDetectSurfaceDimens",
Ruben Brunkef14da32014-06-24 16:06:54 -0700793 "(Landroid/view/Surface;[I)I",
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700794 (void *)LegacyCameraDevice_nativeDetectSurfaceDimens },
Chien-Yu Chen29c36302016-03-02 15:34:00 -0800795 { "nativeConnectSurface",
796 "(Landroid/view/Surface;)I",
797 (void *)LegacyCameraDevice_nativeConnectSurface },
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700798 { "nativeProduceFrame",
Ruben Brunkef14da32014-06-24 16:06:54 -0700799 "(Landroid/view/Surface;[BIII)I",
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700800 (void *)LegacyCameraDevice_nativeProduceFrame },
801 { "nativeSetSurfaceFormat",
Ruben Brunkef14da32014-06-24 16:06:54 -0700802 "(Landroid/view/Surface;I)I",
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700803 (void *)LegacyCameraDevice_nativeSetSurfaceFormat },
804 { "nativeSetSurfaceDimens",
Ruben Brunkef14da32014-06-24 16:06:54 -0700805 "(Landroid/view/Surface;II)I",
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700806 (void *)LegacyCameraDevice_nativeSetSurfaceDimens },
Ruben Brunk3c8fa3b2014-06-30 16:45:05 -0700807 { "nativeGetSurfaceId",
808 "(Landroid/view/Surface;)J",
809 (void *)LegacyCameraDevice_nativeGetSurfaceId },
Ruben Brunk28c49c92014-06-16 18:43:59 -0700810 { "nativeDetectTextureDimens",
811 "(Landroid/graphics/SurfaceTexture;[I)I",
812 (void *)LegacyCameraDevice_nativeDetectTextureDimens },
813 { "nativeSetSurfaceOrientation",
814 "(Landroid/view/Surface;II)I",
815 (void *)LegacyCameraDevice_nativeSetSurfaceOrientation },
Ruben Brunk91838de2014-07-16 17:24:17 -0700816 { "nativeSetNextTimestamp",
817 "(Landroid/view/Surface;J)I",
818 (void *)LegacyCameraDevice_nativeSetNextTimestamp },
Ruben Brunk1dc13262014-07-31 11:43:27 -0700819 { "nativeGetJpegFooterSize",
820 "()I",
821 (void *)LegacyCameraDevice_nativeGetJpegFooterSize },
Ruben Brunkf4a637d2014-11-20 18:01:36 -0800822 { "nativeDetectSurfaceUsageFlags",
823 "(Landroid/view/Surface;)I",
824 (void *)LegacyCameraDevice_nativeDetectSurfaceUsageFlags },
Ruben Brunka94c6032015-06-10 16:44:28 -0700825 { "nativeSetScalingMode",
826 "(Landroid/view/Surface;I)I",
827 (void *)LegacyCameraDevice_nativeSetScalingMode },
Chien-Yu Chen29c36302016-03-02 15:34:00 -0800828 { "nativeDisconnectSurface",
829 "(Landroid/view/Surface;)I",
830 (void *)LegacyCameraDevice_nativeDisconnectSurface },
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700831};
832
833// Get all the required offsets in java class and register native functions
834int register_android_hardware_camera2_legacy_LegacyCameraDevice(JNIEnv* env)
835{
836 // Register native functions
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800837 return RegisterMethodsOrDie(env,
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700838 CAMERA_DEVICE_CLASS_NAME,
839 gCameraDeviceMethods,
840 NELEM(gCameraDeviceMethods));
841}