blob: 719cf74a451de0a28cd3a6566055e37a4a7efa5e [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/Surface.h>
31#include <gui/IGraphicBufferProducer.h>
Chien-Yu Chen29c36302016-03-02 15:34:00 -080032#include <gui/IProducerListener.h>
Ruben Brunkfeb50af2014-05-09 19:58:49 -070033#include <ui/GraphicBuffer.h>
34#include <system/window.h>
Igor Murashkin5096def2014-06-24 10:49:11 -070035#include <hardware/camera3.h>
Ruben Brunk28c49c92014-06-16 18:43:59 -070036#include <system/camera_metadata.h>
Ruben Brunkfeb50af2014-05-09 19:58:49 -070037
Ruben Brunk3c8fa3b2014-06-30 16:45:05 -070038#include <stdint.h>
39#include <inttypes.h>
40
Ruben Brunkfeb50af2014-05-09 19:58:49 -070041using 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
Ruben Brunkef14da32014-06-24 16:06:54 -070046#define DONT_CARE 0
Ruben Brunkfeb50af2014-05-09 19:58:49 -070047
48#define ARRAY_SIZE(a) (sizeof(a)/sizeof(*(a)))
49
Ruben Brunk91b9aab2014-06-20 00:24:56 -070050#define ALIGN(x, mask) ( ((x) + (mask) - 1) & ~((mask) - 1) )
51
Yin-Chia Yeh36ceaca2018-03-16 11:05:37 -070052// Use BAD_VALUE for surface abandoned error
53#define OVERRIDE_SURFACE_ERROR(err) \
54do { \
55 if (err == -ENODEV) { \
56 err = BAD_VALUE; \
57 } \
58} while (0)
59
60#define UPDATE(md, tag, data, size) \
61do { \
62 if ((md).update((tag), (data), (size))) { \
63 ALOGE("Update " #tag " failed!"); \
64 return BAD_VALUE; \
65 } \
66} while (0)
67
Ruben Brunkfeb50af2014-05-09 19:58:49 -070068/**
Ruben Brunk433e7152014-12-10 19:12:41 -080069 * Convert from RGB 888 to Y'CbCr using the conversion specified in JFIF v1.02
Ruben Brunkfeb50af2014-05-09 19:58:49 -070070 */
Ruben Brunk31798f32014-09-25 19:56:54 -070071static void rgbToYuv420(uint8_t* rgbBuf, size_t width, size_t height, uint8_t* yPlane,
Ruben Brunk89735972014-12-11 12:55:44 -080072 uint8_t* crPlane, uint8_t* cbPlane, size_t chromaStep, size_t yStride, size_t chromaStride) {
Ruben Brunkfeb50af2014-05-09 19:58:49 -070073 uint8_t R, G, B;
74 size_t index = 0;
Ruben Brunk31798f32014-09-25 19:56:54 -070075 for (size_t j = 0; j < height; j++) {
Ruben Brunk89735972014-12-11 12:55:44 -080076 uint8_t* cr = crPlane;
77 uint8_t* cb = cbPlane;
Ruben Brunk433e7152014-12-10 19:12:41 -080078 uint8_t* y = yPlane;
79 bool jEven = (j & 1) == 0;
Ruben Brunk31798f32014-09-25 19:56:54 -070080 for (size_t i = 0; i < width; i++) {
Ruben Brunkfeb50af2014-05-09 19:58:49 -070081 R = rgbBuf[index++];
82 G = rgbBuf[index++];
83 B = rgbBuf[index++];
Ruben Brunk433e7152014-12-10 19:12:41 -080084 *y++ = (77 * R + 150 * G + 29 * B) >> 8;
85 if (jEven && (i & 1) == 0) {
Ruben Brunk89735972014-12-11 12:55:44 -080086 *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;
Ruben Brunkfeb50af2014-05-09 19:58:49 -070090 }
91 // Skip alpha
92 index++;
93 }
94 yPlane += yStride;
Ruben Brunk433e7152014-12-10 19:12:41 -080095 if (jEven) {
Ruben Brunk89735972014-12-11 12:55:44 -080096 crPlane += chromaStride;
97 cbPlane += chromaStride;
Ruben Brunkfeb50af2014-05-09 19:58:49 -070098 }
99 }
100}
101
Ruben Brunk31798f32014-09-25 19:56:54 -0700102static void rgbToYuv420(uint8_t* rgbBuf, size_t width, size_t height, android_ycbcr* ycbcr) {
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700103 size_t cStep = ycbcr->chroma_step;
104 size_t cStride = ycbcr->cstride;
105 size_t yStride = ycbcr->ystride;
Ruben Brunk433e7152014-12-10 19:12:41 -0800106 ALOGV("%s: yStride is: %zu, cStride is: %zu, cStep is: %zu", __FUNCTION__, yStride, cStride,
107 cStep);
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700108 rgbToYuv420(rgbBuf, width, height, reinterpret_cast<uint8_t*>(ycbcr->y),
Ruben Brunk433e7152014-12-10 19:12:41 -0800109 reinterpret_cast<uint8_t*>(ycbcr->cr), reinterpret_cast<uint8_t*>(ycbcr->cb),
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700110 cStep, yStride, cStride);
111}
112
Chien-Yu Chen29c36302016-03-02 15:34:00 -0800113static status_t connectSurface(const sp<Surface>& surface, int32_t maxBufferSlack) {
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700114 status_t err = NO_ERROR;
Chien-Yu Chen29c36302016-03-02 15:34:00 -0800115
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__,
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700119 strerror(-err), err);
120 return err;
121 }
122
Chien-Yu Chen29c36302016-03-02 15:34:00 -0800123 err = native_window_set_usage(surface.get(), GRALLOC_USAGE_SW_WRITE_OFTEN);
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700124 if (err != NO_ERROR) {
125 ALOGE("%s: Failed to set native window usage flag, error %s (%d).", __FUNCTION__,
126 strerror(-err), err);
Yin-Chia Yeh36ceaca2018-03-16 11:05:37 -0700127 OVERRIDE_SURFACE_ERROR(err);
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700128 return err;
129 }
130
131 int minUndequeuedBuffers;
Chien-Yu Chen29c36302016-03-02 15:34:00 -0800132 err = static_cast<ANativeWindow*>(surface.get())->query(surface.get(),
133 NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBuffers);
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700134 if (err != NO_ERROR) {
135 ALOGE("%s: Failed to get native window min undequeued buffers, error %s (%d).",
136 __FUNCTION__, strerror(-err), err);
Yin-Chia Yeh36ceaca2018-03-16 11:05:37 -0700137 OVERRIDE_SURFACE_ERROR(err);
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700138 return err;
139 }
140
Chien-Yu Chen29c36302016-03-02 15:34:00 -0800141 ALOGV("%s: Setting buffer count to %d", __FUNCTION__,
142 maxBufferSlack + 1 + minUndequeuedBuffers);
143 err = native_window_set_buffer_count(surface.get(), maxBufferSlack + 1 + minUndequeuedBuffers);
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700144 if (err != NO_ERROR) {
145 ALOGE("%s: Failed to set native window buffer count, error %s (%d).", __FUNCTION__,
146 strerror(-err), err);
Yin-Chia Yeh36ceaca2018-03-16 11:05:37 -0700147 OVERRIDE_SURFACE_ERROR(err);
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700148 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 */
167static status_t produceFrame(const sp<ANativeWindow>& anw,
168 uint8_t* pixelBuffer,
Ruben Brunk31798f32014-09-25 19:56:54 -0700169 int32_t bufWidth, // Width of the pixelBuffer
170 int32_t bufHeight, // Height of the pixelBuffer
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700171 int32_t pixelFmt, // Format of the pixelBuffer
Igor Murashkin5096def2014-06-24 10:49:11 -0700172 int32_t bufSize) {
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700173 ATRACE_CALL();
174 status_t err = NO_ERROR;
175 ANativeWindowBuffer* anb;
Igor Murashkin5096def2014-06-24 10:49:11 -0700176 ALOGV("%s: Dequeue buffer from %p %dx%d (fmt=%x, size=%x)",
Ruben Brunk31798f32014-09-25 19:56:54 -0700177 __FUNCTION__, anw.get(), bufWidth, bufHeight, pixelFmt, bufSize);
Igor Murashkin5096def2014-06-24 10:49:11 -0700178
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;
Ruben Brunk31798f32014-09-25 19:56:54 -0700185 } else if (bufWidth < 0) {
Igor Murashkin5096def2014-06-24 10:49:11 -0700186 ALOGE("%s: width must be non-negative", __FUNCTION__);
187 return BAD_VALUE;
Ruben Brunk31798f32014-09-25 19:56:54 -0700188 } else if (bufHeight < 0) {
Igor Murashkin5096def2014-06-24 10:49:11 -0700189 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 }
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700195
Ruben Brunk31798f32014-09-25 19:56:54 -0700196 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);
Ruben Brunk91b9aab2014-06-20 00:24:56 -0700199
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700200 // TODO: Switch to using Surface::lock and Surface::unlockAndPost
201 err = native_window_dequeue_buffer_and_wait(anw.get(), &anb);
Yin-Chia Yeh36ceaca2018-03-16 11:05:37 -0700202 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 }
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700208
Mathias Agopian845eef05f2017-04-03 17:51:15 -0700209 sp<GraphicBuffer> buf(GraphicBuffer::from(anb));
Ruben Brunk0c798842014-09-30 03:42:13 -0700210 uint32_t grallocBufWidth = buf->getWidth();
211 uint32_t grallocBufHeight = buf->getHeight();
212 uint32_t grallocBufStride = buf->getStride();
213 if (grallocBufWidth != width || grallocBufHeight != height) {
Ruben Brunk31798f32014-09-25 19:56:54 -0700214 ALOGE("%s: Received gralloc buffer with bad dimensions %" PRIu32 "x%" PRIu32
Ruben Brunk0c798842014-09-30 03:42:13 -0700215 ", expecting dimensions %zu x %zu", __FUNCTION__, grallocBufWidth,
216 grallocBufHeight, width, height);
Ruben Brunk31798f32014-09-25 19:56:54 -0700217 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);
Yin-Chia Yeh36ceaca2018-03-16 11:05:37 -0700225 OVERRIDE_SURFACE_ERROR(err);
Ruben Brunk31798f32014-09-25 19:56:54 -0700226 return err;
227 }
228
Ruben Brunk0c798842014-09-30 03:42:13 -0700229 uint64_t tmpSize = (pixelFmt == HAL_PIXEL_FORMAT_BLOB) ? grallocBufWidth :
230 4 * grallocBufHeight * grallocBufWidth;
Ruben Brunk31798f32014-09-25 19:56:54 -0700231 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__);
Ruben Brunk0c798842014-09-30 03:42:13 -0700234 tmpSize = 4 * (grallocBufWidth + grallocBufStride * (grallocBufHeight - 1));
Ruben Brunk31798f32014-09-25 19:56:54 -0700235 } 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;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700248
Ruben Brunk433e7152014-12-10 19:12:41 -0800249 ALOGV("%s: Pixel format chosen: %x", __FUNCTION__, pixelFmt);
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700250 switch(pixelFmt) {
251 case HAL_PIXEL_FORMAT_YCrCb_420_SP: {
Ruben Brunk31798f32014-09-25 19:56:54 -0700252 if (bufferLength < totalSizeBytes) {
253 ALOGE("%s: PixelBuffer size %zu too small for given dimensions",
254 __FUNCTION__, bufferLength);
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700255 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 }
Ruben Brunk91b9aab2014-06-20 00:24:56 -0700273 case HAL_PIXEL_FORMAT_YV12: {
Ruben Brunk31798f32014-09-25 19:56:54 -0700274 if (bufferLength < totalSizeBytes) {
275 ALOGE("%s: PixelBuffer size %zu too small for given dimensions",
276 __FUNCTION__, bufferLength);
Ruben Brunk91b9aab2014-06-20 00:24:56 -0700277 return BAD_VALUE;
278 }
279
280 if ((width & 1) || (height & 1)) {
Ruben Brunk31798f32014-09-25 19:56:54 -0700281 ALOGE("%s: Dimens %zu x %zu are not divisible by 2.", __FUNCTION__, width, height);
Ruben Brunk91b9aab2014-06-20 00:24:56 -0700282 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();
Ruben Brunk433e7152014-12-10 19:12:41 -0800295 ALOGV("%s: stride is: %" PRIu32, __FUNCTION__, stride);
Ruben Brunk91b9aab2014-06-20 00:24:56 -0700296 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 }
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700309 case HAL_PIXEL_FORMAT_YCbCr_420_888: {
310 // Software writes with YCbCr_420_888 format are unsupported
311 // by the gralloc module for now
Ruben Brunk31798f32014-09-25 19:56:54 -0700312 if (bufferLength < totalSizeBytes) {
313 ALOGE("%s: PixelBuffer size %zu too small for given dimensions",
314 __FUNCTION__, bufferLength);
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700315 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: {
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700330 int8_t* img = NULL;
Ruben Brunk0fd198a2014-09-23 23:35:43 -0700331 struct camera3_jpeg_blob footer = {
Bernhard Rosenkränzer452efb22014-11-17 23:42:21 +0100332 .jpeg_blob_id = CAMERA3_JPEG_BLOB_ID,
333 .jpeg_size = (uint32_t)bufferLength
Ruben Brunk0fd198a2014-09-23 23:35:43 -0700334 };
335
Ruben Brunk31798f32014-09-25 19:56:54 -0700336 size_t totalJpegSize = bufferLength + sizeof(footer);
337 totalJpegSize = (totalJpegSize + 3) & ~0x3; // round up to nearest octonibble
338
Ruben Brunk31798f32014-09-25 19:56:54 -0700339 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
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700345 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 }
Ruben Brunk31798f32014-09-25 19:56:54 -0700351
352 memcpy(img, pixelBuffer, bufferLength);
353 memcpy(img + totalSizeBytes - sizeof(footer), &footer, sizeof(footer));
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700354 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);
Yin-Chia Yeh36ceaca2018-03-16 11:05:37 -0700373 OVERRIDE_SURFACE_ERROR(err);
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700374 return err;
375 }
376 return NO_ERROR;
377}
378
379static 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()) {
Ruben Brunk3c8fa3b2014-06-30 16:45:05 -0700384 return NULL;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700385 }
386 } else {
387 jniThrowNullPointerException(env, "surface");
Ruben Brunk3c8fa3b2014-06-30 16:45:05 -0700388 return NULL;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700389 }
390 if (anw == NULL) {
Ruben Brunk443ab2c2015-03-12 20:54:03 -0700391 ALOGE("%s: Surface had no valid native window.", __FUNCTION__);
Ruben Brunk3c8fa3b2014-06-30 16:45:05 -0700392 return NULL;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700393 }
394 return anw;
395}
396
Ruben Brunk28c49c92014-06-16 18:43:59 -0700397static 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
Ruben Brunk3c8fa3b2014-06-30 16:45:05 -0700416static 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
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700435extern "C" {
436
437static 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__);
Ruben Brunkef14da32014-06-24 16:06:54 -0700442 return BAD_VALUE;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700443 }
444 int32_t fmt = 0;
445 status_t err = anw->query(anw.get(), NATIVE_WINDOW_FORMAT, &fmt);
446 if(err != NO_ERROR) {
Ruben Brunkef14da32014-06-24 16:06:54 -0700447 ALOGE("%s: Error while querying surface pixel format %s (%d).", __FUNCTION__, strerror(-err),
448 err);
Yin-Chia Yeh36ceaca2018-03-16 11:05:37 -0700449 OVERRIDE_SURFACE_ERROR(err);
Ruben Brunkef14da32014-06-24 16:06:54 -0700450 return err;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700451 }
452 return fmt;
453}
454
Eino-Ville Talvalae3651202015-06-19 17:29:14 -0700455static 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);
Yin-Chia Yeh36ceaca2018-03-16 11:05:37 -0700467 OVERRIDE_SURFACE_ERROR(err);
Eino-Ville Talvalae3651202015-06-19 17:29:14 -0700468 return err;
469 }
470 return fmt;
471}
472
Ruben Brunkef14da32014-06-24 16:06:54 -0700473static jint LegacyCameraDevice_nativeDetectSurfaceDimens(JNIEnv* env, jobject thiz,
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700474 jobject surface, jintArray dimens) {
475 ALOGV("nativeGetSurfaceDimens");
Ruben Brunk28c49c92014-06-16 18:43:59 -0700476
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
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700487 sp<ANativeWindow> anw;
488 if ((anw = getNativeWindow(env, surface)) == NULL) {
489 ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
Ruben Brunkef14da32014-06-24 16:06:54 -0700490 return BAD_VALUE;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700491 }
492 int32_t dimenBuf[2];
493 status_t err = anw->query(anw.get(), NATIVE_WINDOW_WIDTH, dimenBuf);
494 if(err != NO_ERROR) {
Ruben Brunkef14da32014-06-24 16:06:54 -0700495 ALOGE("%s: Error while querying surface width %s (%d).", __FUNCTION__, strerror(-err),
496 err);
Yin-Chia Yeh36ceaca2018-03-16 11:05:37 -0700497 OVERRIDE_SURFACE_ERROR(err);
Ruben Brunkef14da32014-06-24 16:06:54 -0700498 return err;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700499 }
500 err = anw->query(anw.get(), NATIVE_WINDOW_HEIGHT, dimenBuf + 1);
501 if(err != NO_ERROR) {
Ruben Brunkef14da32014-06-24 16:06:54 -0700502 ALOGE("%s: Error while querying surface height %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 env->SetIntArrayRegion(dimens, /*start*/0, /*length*/ARRAY_SIZE(dimenBuf), dimenBuf);
Ruben Brunkef14da32014-06-24 16:06:54 -0700508 return NO_ERROR;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700509}
510
Ruben Brunkf4a637d2014-11-20 18:01:36 -0800511static 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) {
Yin-Chia Yeh92843952018-11-27 14:23:40 -0800517 jniThrowException(env, "java/lang/UnsupportedOperationException",
Ruben Brunkf4a637d2014-11-20 18:01:36 -0800518 "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) {
Yin-Chia Yeh92843952018-11-27 14:23:40 -0800524 jniThrowException(env, "java/lang/UnsupportedOperationException",
Ruben Brunkf4a637d2014-11-20 18:01:36 -0800525 "Error while querying surface usage bits");
Yin-Chia Yeh36ceaca2018-03-16 11:05:37 -0700526 OVERRIDE_SURFACE_ERROR(err);
Ruben Brunkf4a637d2014-11-20 18:01:36 -0800527 return err;
528 }
529 return usage;
530}
531
Chien-Yu Chen29c36302016-03-02 15:34:00 -0800532static 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) {
Yin-Chia Yeh92843952018-11-27 14:23:40 -0800545 jniThrowException(env, "java/lang/UnsupportedOperationException",
Chien-Yu Chen29c36302016-03-02 15:34:00 -0800546 "Error while disconnecting surface");
Yin-Chia Yeh36ceaca2018-03-16 11:05:37 -0700547 OVERRIDE_SURFACE_ERROR(err);
Chien-Yu Chen29c36302016-03-02 15:34:00 -0800548 return err;
549 }
550 return NO_ERROR;
551}
552
Ruben Brunk28c49c92014-06-16 18:43:59 -0700553static 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);
Yin-Chia Yeh36ceaca2018-03-16 11:05:37 -0700567 OVERRIDE_SURFACE_ERROR(err);
Ruben Brunk28c49c92014-06-16 18:43:59 -0700568 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);
Yin-Chia Yeh36ceaca2018-03-16 11:05:37 -0700575 OVERRIDE_SURFACE_ERROR(err);
Ruben Brunk28c49c92014-06-16 18:43:59 -0700576 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
Chien-Yu Chen29c36302016-03-02 15:34:00 -0800586static 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__);
Ruben Brunkef14da32014-06-24 16:06:54 -0700591 return BAD_VALUE;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700592 }
Chien-Yu Chen29c36302016-03-02 15:34:00 -0800593 status_t err = connectSurface(s, CAMERA_DEVICE_BUFFER_SLACK);
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700594 if (err != NO_ERROR) {
Ruben Brunkef14da32014-06-24 16:06:54 -0700595 ALOGE("%s: Error while configuring surface %s (%d).", __FUNCTION__, strerror(-err), err);
Yin-Chia Yeh36ceaca2018-03-16 11:05:37 -0700596 OVERRIDE_SURFACE_ERROR(err);
Ruben Brunkef14da32014-06-24 16:06:54 -0700597 return err;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700598 }
Ruben Brunkef14da32014-06-24 16:06:54 -0700599 return NO_ERROR;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700600}
601
Ruben Brunkef14da32014-06-24 16:06:54 -0700602static jint LegacyCameraDevice_nativeProduceFrame(JNIEnv* env, jobject thiz, jobject surface,
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700603 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__);
Ruben Brunkef14da32014-06-24 16:06:54 -0700609 return BAD_VALUE;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700610 }
611
612 if (pixelBuffer == NULL) {
613 jniThrowNullPointerException(env, "pixelBuffer");
Ruben Brunkef14da32014-06-24 16:06:54 -0700614 return DONT_CARE;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700615 }
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");
Ruben Brunkef14da32014-06-24 16:06:54 -0700622 return DONT_CARE;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700623 }
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) {
Ruben Brunkef14da32014-06-24 16:06:54 -0700630 ALOGE("%s: Error while producing frame %s (%d).", __FUNCTION__, strerror(-err), err);
631 return err;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700632 }
Ruben Brunkef14da32014-06-24 16:06:54 -0700633 return NO_ERROR;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700634}
635
Ruben Brunkef14da32014-06-24 16:06:54 -0700636static jint LegacyCameraDevice_nativeSetSurfaceFormat(JNIEnv* env, jobject thiz, jobject surface,
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700637 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__);
Ruben Brunkef14da32014-06-24 16:06:54 -0700642 return BAD_VALUE;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700643 }
644 status_t err = native_window_set_buffers_format(anw.get(), pixelFormat);
645 if (err != NO_ERROR) {
Ruben Brunkef14da32014-06-24 16:06:54 -0700646 ALOGE("%s: Error while setting surface format %s (%d).", __FUNCTION__, strerror(-err), err);
Yin-Chia Yeh36ceaca2018-03-16 11:05:37 -0700647 OVERRIDE_SURFACE_ERROR(err);
Ruben Brunkef14da32014-06-24 16:06:54 -0700648 return err;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700649 }
Ruben Brunkef14da32014-06-24 16:06:54 -0700650 return NO_ERROR;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700651}
652
Ruben Brunkef14da32014-06-24 16:06:54 -0700653static jint LegacyCameraDevice_nativeSetSurfaceDimens(JNIEnv* env, jobject thiz, jobject surface,
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700654 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__);
Ruben Brunkef14da32014-06-24 16:06:54 -0700659 return BAD_VALUE;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700660 }
Ruben Brunka9bc3552014-08-14 15:57:28 -0700661
Eino-Ville Talvalab0acf7f2015-02-11 15:41:12 -0800662 // 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);
Ruben Brunka9bc3552014-08-14 15:57:28 -0700665 if (err != NO_ERROR) {
666 ALOGE("%s: Error while setting surface user dimens %s (%d).", __FUNCTION__, strerror(-err),
667 err);
Yin-Chia Yeh36ceaca2018-03-16 11:05:37 -0700668 OVERRIDE_SURFACE_ERROR(err);
Ruben Brunka9bc3552014-08-14 15:57:28 -0700669 return err;
670 }
Ruben Brunkef14da32014-06-24 16:06:54 -0700671 return NO_ERROR;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700672}
673
Ruben Brunk3c8fa3b2014-06-30 16:45:05 -0700674static 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 }
Marco Nelissen97069dd2014-11-14 08:00:42 -0800686 sp<IBinder> b = IInterface::asBinder(gbp);
Ruben Brunk3c8fa3b2014-06-30 16:45:05 -0700687 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
Ruben Brunk28c49c92014-06-16 18:43:59 -0700698static 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
Ruben Brunk91838de2014-07-16 17:24:17 -0700717 if ((err = CameraUtils::getRotationTransform(staticMetadata, /*out*/&transform)) != NO_ERROR) {
Ruben Brunk28c49c92014-06-16 18:43:59 -0700718 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
Ruben Brunk91838de2014-07-16 17:24:17 -0700725 if ((err = native_window_set_buffers_sticky_transform(anw.get(), transform)) != NO_ERROR) {
Ruben Brunk28c49c92014-06-16 18:43:59 -0700726 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
Ruben Brunk91838de2014-07-16 17:24:17 -0700734static 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
Ruben Brunka94c6032015-06-10 16:44:28 -0700754static 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
Ruben Brunk1dc13262014-07-31 11:43:27 -0700771static jint LegacyCameraDevice_nativeGetJpegFooterSize(JNIEnv* env, jobject thiz) {
772 ALOGV("nativeGetJpegFooterSize");
773 return static_cast<jint>(sizeof(struct camera3_jpeg_blob));
774}
775
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700776} // extern "C"
777
Daniel Micay76f6a862015-09-19 17:31:01 -0400778static const JNINativeMethod gCameraDeviceMethods[] = {
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700779 { "nativeDetectSurfaceType",
780 "(Landroid/view/Surface;)I",
781 (void *)LegacyCameraDevice_nativeDetectSurfaceType },
Eino-Ville Talvalae3651202015-06-19 17:29:14 -0700782 { "nativeDetectSurfaceDataspace",
783 "(Landroid/view/Surface;)I",
784 (void *)LegacyCameraDevice_nativeDetectSurfaceDataspace },
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700785 { "nativeDetectSurfaceDimens",
Ruben Brunkef14da32014-06-24 16:06:54 -0700786 "(Landroid/view/Surface;[I)I",
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700787 (void *)LegacyCameraDevice_nativeDetectSurfaceDimens },
Chien-Yu Chen29c36302016-03-02 15:34:00 -0800788 { "nativeConnectSurface",
789 "(Landroid/view/Surface;)I",
790 (void *)LegacyCameraDevice_nativeConnectSurface },
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700791 { "nativeProduceFrame",
Ruben Brunkef14da32014-06-24 16:06:54 -0700792 "(Landroid/view/Surface;[BIII)I",
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700793 (void *)LegacyCameraDevice_nativeProduceFrame },
794 { "nativeSetSurfaceFormat",
Ruben Brunkef14da32014-06-24 16:06:54 -0700795 "(Landroid/view/Surface;I)I",
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700796 (void *)LegacyCameraDevice_nativeSetSurfaceFormat },
797 { "nativeSetSurfaceDimens",
Ruben Brunkef14da32014-06-24 16:06:54 -0700798 "(Landroid/view/Surface;II)I",
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700799 (void *)LegacyCameraDevice_nativeSetSurfaceDimens },
Ruben Brunk3c8fa3b2014-06-30 16:45:05 -0700800 { "nativeGetSurfaceId",
801 "(Landroid/view/Surface;)J",
802 (void *)LegacyCameraDevice_nativeGetSurfaceId },
Ruben Brunk28c49c92014-06-16 18:43:59 -0700803 { "nativeDetectTextureDimens",
804 "(Landroid/graphics/SurfaceTexture;[I)I",
805 (void *)LegacyCameraDevice_nativeDetectTextureDimens },
806 { "nativeSetSurfaceOrientation",
807 "(Landroid/view/Surface;II)I",
808 (void *)LegacyCameraDevice_nativeSetSurfaceOrientation },
Ruben Brunk91838de2014-07-16 17:24:17 -0700809 { "nativeSetNextTimestamp",
810 "(Landroid/view/Surface;J)I",
811 (void *)LegacyCameraDevice_nativeSetNextTimestamp },
Ruben Brunk1dc13262014-07-31 11:43:27 -0700812 { "nativeGetJpegFooterSize",
813 "()I",
814 (void *)LegacyCameraDevice_nativeGetJpegFooterSize },
Ruben Brunkf4a637d2014-11-20 18:01:36 -0800815 { "nativeDetectSurfaceUsageFlags",
816 "(Landroid/view/Surface;)I",
817 (void *)LegacyCameraDevice_nativeDetectSurfaceUsageFlags },
Ruben Brunka94c6032015-06-10 16:44:28 -0700818 { "nativeSetScalingMode",
819 "(Landroid/view/Surface;I)I",
820 (void *)LegacyCameraDevice_nativeSetScalingMode },
Chien-Yu Chen29c36302016-03-02 15:34:00 -0800821 { "nativeDisconnectSurface",
822 "(Landroid/view/Surface;)I",
823 (void *)LegacyCameraDevice_nativeDisconnectSurface },
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700824};
825
826// Get all the required offsets in java class and register native functions
827int register_android_hardware_camera2_legacy_LegacyCameraDevice(JNIEnv* env)
828{
829 // Register native functions
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800830 return RegisterMethodsOrDie(env,
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700831 CAMERA_DEVICE_CLASS_NAME,
832 gCameraDeviceMethods,
833 NELEM(gCameraDeviceMethods));
834}