android_hardware_camera2_legacy_LegacyCameraDevice.cpp revision 0c79884076405bc36c0fb4f1bce27f883b97d64c
1feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk/*
2feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Copyright (C) 2014 The Android Open Source Project
3feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *
4feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Licensed under the Apache License, Version 2.0 (the "License");
5feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * you may not use this file except in compliance with the License.
6feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * You may obtain a copy of the License at
7feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *
8feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *      http://www.apache.org/licenses/LICENSE-2.0
9feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *
10feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Unless required by applicable law or agreed to in writing, software
11feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * distributed under the License is distributed on an "AS IS" BASIS,
12feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * See the License for the specific language governing permissions and
14feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * limitations under the License.
15feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */
16feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
17feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk#define LOG_TAG "Legacy-CameraDevice-JNI"
185096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin// #define LOG_NDEBUG 0
19feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk#include <utils/Log.h>
20feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk#include <utils/Errors.h>
21feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk#include <utils/Trace.h>
2228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk#include <camera/CameraUtils.h>
23feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
24feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk#include "jni.h"
25feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk#include "JNIHelp.h"
26feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk#include "android_runtime/AndroidRuntime.h"
27feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk#include "android_runtime/android_view_Surface.h"
2828c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk#include "android_runtime/android_graphics_SurfaceTexture.h"
29feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
303c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk#include <gui/Surface.h>
313c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk#include <gui/IGraphicBufferProducer.h>
32feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk#include <ui/GraphicBuffer.h>
33feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk#include <system/window.h>
345096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin#include <hardware/camera3.h>
3528c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk#include <system/camera_metadata.h>
36feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
373c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk#include <stdint.h>
383c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk#include <inttypes.h>
393c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk
40feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkusing namespace android;
41feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
42feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk// fully-qualified class name
43feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk#define CAMERA_DEVICE_CLASS_NAME "android/hardware/camera2/legacy/LegacyCameraDevice"
44feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk#define CAMERA_DEVICE_BUFFER_SLACK  3
45ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk#define DONT_CARE 0
46feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
47feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk#define ARRAY_SIZE(a) (sizeof(a)/sizeof(*(a)))
48feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
4991b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk#define ALIGN(x, mask) ( ((x) + (mask) - 1) & ~((mask) - 1) )
5091b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk
51feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk/**
52feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Convert from RGB 888 to Y'CbCr using the conversion specified in ITU-R BT.601 for
53feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * digital RGB with K_b = 0.114, and K_r = 0.299.
54feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */
5531798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunkstatic void rgbToYuv420(uint8_t* rgbBuf, size_t width, size_t height, uint8_t* yPlane,
56feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        uint8_t* uPlane, uint8_t* vPlane, size_t chromaStep, size_t yStride, size_t chromaStride) {
57feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    uint8_t R, G, B;
58feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    size_t index = 0;
59feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
6031798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    size_t cStrideDiff = chromaStride - width;
61feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
6231798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    for (size_t j = 0; j < height; j++) {
6331798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk        for (size_t i = 0; i < width; i++) {
64feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            R = rgbBuf[index++];
65feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            G = rgbBuf[index++];
66feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            B = rgbBuf[index++];
67feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            *(yPlane + i) = ((66 * R + 129 * G +  25 * B + 128) >> 8) +  16;
68feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
69feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            if (j % 2 == 0 && i % 2 == 0){
70feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                *uPlane = (( -38 * R -  74 * G + 112 * B + 128) >> 8) + 128;
71feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                *vPlane = (( 112 * R -  94 * G -  18 * B + 128) >> 8) + 128;
72feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                uPlane += chromaStep;
73feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                vPlane += chromaStep;
74feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
75feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            // Skip alpha
76feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            index++;
77feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
78feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        yPlane += yStride;
79feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        if (j % 2 == 0) {
80feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            uPlane += cStrideDiff;
81feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            vPlane += cStrideDiff;
82feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
83feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
84feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk}
85feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
8631798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunkstatic void rgbToYuv420(uint8_t* rgbBuf, size_t width, size_t height, android_ycbcr* ycbcr) {
87feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    size_t cStep = ycbcr->chroma_step;
88feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    size_t cStride = ycbcr->cstride;
89feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    size_t yStride = ycbcr->ystride;
90feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    rgbToYuv420(rgbBuf, width, height, reinterpret_cast<uint8_t*>(ycbcr->y),
91feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            reinterpret_cast<uint8_t*>(ycbcr->cb), reinterpret_cast<uint8_t*>(ycbcr->cr),
92feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            cStep, yStride, cStride);
93feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk}
94feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
95feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkstatic status_t configureSurface(const sp<ANativeWindow>& anw,
96feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                                 int32_t width,
97feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                                 int32_t height,
98feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                                 int32_t pixelFmt,
99feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                                 int32_t maxBufferSlack) {
100feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    status_t err = NO_ERROR;
101feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    err = native_window_set_buffers_dimensions(anw.get(), width, height);
102feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (err != NO_ERROR) {
103feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        ALOGE("%s: Failed to set native window buffer dimensions, error %s (%d).", __FUNCTION__,
104feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                strerror(-err), err);
105feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        return err;
106feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
107feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
108feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    err = native_window_set_buffers_format(anw.get(), pixelFmt);
109feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (err != NO_ERROR) {
110feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        ALOGE("%s: Failed to set native window buffer format, error %s (%d).", __FUNCTION__,
111feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                strerror(-err), err);
112feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        return err;
113feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
114feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
115feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    err = native_window_set_usage(anw.get(), GRALLOC_USAGE_SW_WRITE_OFTEN);
116feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (err != NO_ERROR) {
117feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        ALOGE("%s: Failed to set native window usage flag, error %s (%d).", __FUNCTION__,
118feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                strerror(-err), err);
119feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        return err;
120feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
121feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
122feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    int minUndequeuedBuffers;
123feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    err = anw.get()->query(anw.get(),
124feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
125feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            &minUndequeuedBuffers);
126feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (err != NO_ERROR) {
127feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        ALOGE("%s: Failed to get native window min undequeued buffers, error %s (%d).",
128feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                __FUNCTION__, strerror(-err), err);
129feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        return err;
130feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
131feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
1325096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin    ALOGV("%s: Setting buffer count to %d, size to (%dx%d), fmt (0x%x)", __FUNCTION__,
1335096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin          maxBufferSlack + 1 + minUndequeuedBuffers,
1345096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin          width, height, pixelFmt);
135feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    err = native_window_set_buffer_count(anw.get(), maxBufferSlack + 1 + minUndequeuedBuffers);
136feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (err != NO_ERROR) {
137feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        ALOGE("%s: Failed to set native window buffer count, error %s (%d).", __FUNCTION__,
138feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                strerror(-err), err);
139feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        return err;
140feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
141feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    return NO_ERROR;
142feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk}
143feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
144feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk/**
145feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Produce a frame in the given surface.
146feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *
147feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Args:
148feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *    anw - a surface to produce a frame in.
149feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *    pixelBuffer - image buffer to generate a frame from.
150feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *    width - width of the pixelBuffer in pixels.
151feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *    height - height of the pixelBuffer in pixels.
152feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *    pixelFmt - format of the pixelBuffer, one of:
153feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *               HAL_PIXEL_FORMAT_YCrCb_420_SP,
154feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *               HAL_PIXEL_FORMAT_YCbCr_420_888,
155feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *               HAL_PIXEL_FORMAT_BLOB
156feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *    bufSize - the size of the pixelBuffer in bytes.
157feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */
158feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkstatic status_t produceFrame(const sp<ANativeWindow>& anw,
159feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                             uint8_t* pixelBuffer,
16031798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk                             int32_t bufWidth, // Width of the pixelBuffer
16131798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk                             int32_t bufHeight, // Height of the pixelBuffer
162feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                             int32_t pixelFmt, // Format of the pixelBuffer
1635096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin                             int32_t bufSize) {
164feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    ATRACE_CALL();
165feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    status_t err = NO_ERROR;
166feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    ANativeWindowBuffer* anb;
1675096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin    ALOGV("%s: Dequeue buffer from %p %dx%d (fmt=%x, size=%x)",
16831798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk            __FUNCTION__, anw.get(), bufWidth, bufHeight, pixelFmt, bufSize);
1695096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin
1705096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin    if (anw == 0) {
1715096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin        ALOGE("%s: anw must not be NULL", __FUNCTION__);
1725096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin        return BAD_VALUE;
1735096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin    } else if (pixelBuffer == NULL) {
1745096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin        ALOGE("%s: pixelBuffer must not be NULL", __FUNCTION__);
1755096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin        return BAD_VALUE;
17631798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    } else if (bufWidth < 0) {
1775096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin        ALOGE("%s: width must be non-negative", __FUNCTION__);
1785096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin        return BAD_VALUE;
17931798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    } else if (bufHeight < 0) {
1805096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin        ALOGE("%s: height must be non-negative", __FUNCTION__);
1815096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin        return BAD_VALUE;
1825096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin    } else if (bufSize < 0) {
1835096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin        ALOGE("%s: bufSize must be non-negative", __FUNCTION__);
1845096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin        return BAD_VALUE;
1855096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin    }
186feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
18731798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    size_t width = static_cast<size_t>(bufWidth);
18831798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    size_t height = static_cast<size_t>(bufHeight);
18931798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    size_t bufferLength = static_cast<size_t>(bufSize);
19091b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk
191feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    // TODO: Switch to using Surface::lock and Surface::unlockAndPost
192feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    err = native_window_dequeue_buffer_and_wait(anw.get(), &anb);
193feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (err != NO_ERROR) return err;
194feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
195feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    sp<GraphicBuffer> buf(new GraphicBuffer(anb, /*keepOwnership*/false));
1960c79884076405bc36c0fb4f1bce27f883b97d64cRuben Brunk    uint32_t grallocBufWidth = buf->getWidth();
1970c79884076405bc36c0fb4f1bce27f883b97d64cRuben Brunk    uint32_t grallocBufHeight = buf->getHeight();
1980c79884076405bc36c0fb4f1bce27f883b97d64cRuben Brunk    uint32_t grallocBufStride = buf->getStride();
1990c79884076405bc36c0fb4f1bce27f883b97d64cRuben Brunk    if (grallocBufWidth != width || grallocBufHeight != height) {
20031798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk        ALOGE("%s: Received gralloc buffer with bad dimensions %" PRIu32 "x%" PRIu32
2010c79884076405bc36c0fb4f1bce27f883b97d64cRuben Brunk                ", expecting dimensions %zu x %zu",  __FUNCTION__, grallocBufWidth,
2020c79884076405bc36c0fb4f1bce27f883b97d64cRuben Brunk                grallocBufHeight, width, height);
20331798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk        return BAD_VALUE;
20431798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    }
20531798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk
20631798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    int32_t bufFmt = 0;
20731798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    err = anw->query(anw.get(), NATIVE_WINDOW_FORMAT, &bufFmt);
20831798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    if (err != NO_ERROR) {
20931798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk        ALOGE("%s: Error while querying surface pixel format %s (%d).", __FUNCTION__,
21031798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk                strerror(-err), err);
21131798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk        return err;
21231798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    }
21331798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk
2140c79884076405bc36c0fb4f1bce27f883b97d64cRuben Brunk    uint64_t tmpSize = (pixelFmt == HAL_PIXEL_FORMAT_BLOB) ? grallocBufWidth :
2150c79884076405bc36c0fb4f1bce27f883b97d64cRuben Brunk            4 * grallocBufHeight * grallocBufWidth;
21631798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    if (bufFmt != pixelFmt) {
21731798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk        if (bufFmt == HAL_PIXEL_FORMAT_RGBA_8888 && pixelFmt == HAL_PIXEL_FORMAT_BLOB) {
21831798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk            ALOGV("%s: Using BLOB to RGBA format override.", __FUNCTION__);
2190c79884076405bc36c0fb4f1bce27f883b97d64cRuben Brunk            tmpSize = 4 * (grallocBufWidth + grallocBufStride * (grallocBufHeight - 1));
22031798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk        } else {
22131798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk            ALOGW("%s: Format mismatch in produceFrame: expecting format %#" PRIx32
22231798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk                    ", but received buffer with format %#" PRIx32, __FUNCTION__, pixelFmt, bufFmt);
22331798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk        }
22431798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    }
22531798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk
22631798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    if (tmpSize > SIZE_MAX) {
22731798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk        ALOGE("%s: Overflow calculating size, buffer with dimens %zu x %zu is absurdly large...",
22831798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk                __FUNCTION__, width, height);
22931798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk        return BAD_VALUE;
23031798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    }
23131798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk
23231798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk    size_t totalSizeBytes = tmpSize;
233feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
234feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    switch(pixelFmt) {
235feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        case HAL_PIXEL_FORMAT_YCrCb_420_SP: {
23631798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk            if (bufferLength < totalSizeBytes) {
23731798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk                ALOGE("%s: PixelBuffer size %zu too small for given dimensions",
23831798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk                        __FUNCTION__, bufferLength);
239feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                return BAD_VALUE;
240feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
241feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            uint8_t* img = NULL;
242feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            ALOGV("%s: Lock buffer from %p for write", __FUNCTION__, anw.get());
243feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
244feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            if (err != NO_ERROR) return err;
245feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
246feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            uint8_t* yPlane = img;
247feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            uint8_t* uPlane = img + height * width;
248feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            uint8_t* vPlane = uPlane + 1;
249feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            size_t chromaStep = 2;
250feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            size_t yStride = width;
251feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            size_t chromaStride = width;
252feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
253feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            rgbToYuv420(pixelBuffer, width, height, yPlane,
254feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                    uPlane, vPlane, chromaStep, yStride, chromaStride);
255feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            break;
256feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
25791b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk        case HAL_PIXEL_FORMAT_YV12: {
25831798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk            if (bufferLength < totalSizeBytes) {
25931798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk                ALOGE("%s: PixelBuffer size %zu too small for given dimensions",
26031798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk                        __FUNCTION__, bufferLength);
26191b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk                return BAD_VALUE;
26291b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            }
26391b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk
26491b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            if ((width & 1) || (height & 1)) {
26531798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk                ALOGE("%s: Dimens %zu x %zu are not divisible by 2.", __FUNCTION__, width, height);
26691b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk                return BAD_VALUE;
26791b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            }
26891b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk
26991b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            uint8_t* img = NULL;
27091b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            ALOGV("%s: Lock buffer from %p for write", __FUNCTION__, anw.get());
27191b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
27291b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            if (err != NO_ERROR) {
27391b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk                ALOGE("%s: Error %s (%d) while locking gralloc buffer for write.", __FUNCTION__,
27491b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk                        strerror(-err), err);
27591b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk                return err;
27691b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            }
27791b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk
27891b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            uint32_t stride = buf->getStride();
27991b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            LOG_ALWAYS_FATAL_IF(stride % 16, "Stride is not 16 pixel aligned %d", stride);
28091b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk
28191b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            uint32_t cStride = ALIGN(stride / 2, 16);
28291b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            size_t chromaStep = 1;
28391b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk
28491b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            uint8_t* yPlane = img;
28591b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            uint8_t* crPlane = img + static_cast<uint32_t>(height) * stride;
28691b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            uint8_t* cbPlane = crPlane + cStride * static_cast<uint32_t>(height) / 2;
28791b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk
28891b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            rgbToYuv420(pixelBuffer, width, height, yPlane,
28991b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk                    crPlane, cbPlane, chromaStep, stride, cStride);
29091b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk            break;
29191b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk        }
292feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        case HAL_PIXEL_FORMAT_YCbCr_420_888: {
293feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            // Software writes with YCbCr_420_888 format are unsupported
294feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            // by the gralloc module for now
29531798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk            if (bufferLength < totalSizeBytes) {
29631798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk                ALOGE("%s: PixelBuffer size %zu too small for given dimensions",
29731798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk                        __FUNCTION__, bufferLength);
298feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                return BAD_VALUE;
299feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
300feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            android_ycbcr ycbcr = android_ycbcr();
301feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            ALOGV("%s: Lock buffer from %p for write", __FUNCTION__, anw.get());
302feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
303feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            err = buf->lockYCbCr(GRALLOC_USAGE_SW_WRITE_OFTEN, &ycbcr);
304feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            if (err != NO_ERROR) {
305feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                ALOGE("%s: Failed to lock ycbcr buffer, error %s (%d).", __FUNCTION__,
306feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                        strerror(-err), err);
307feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                return err;
308feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
309feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            rgbToYuv420(pixelBuffer, width, height, &ycbcr);
310feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            break;
311feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
312feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        case HAL_PIXEL_FORMAT_BLOB: {
313feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            int8_t* img = NULL;
3140fd198ad89ec9c600bb1761b10d938146c28bb98Ruben Brunk            struct camera3_jpeg_blob footer = {
3150fd198ad89ec9c600bb1761b10d938146c28bb98Ruben Brunk                jpeg_blob_id: CAMERA3_JPEG_BLOB_ID,
3160c79884076405bc36c0fb4f1bce27f883b97d64cRuben Brunk                jpeg_size: (uint32_t)bufferLength
3170fd198ad89ec9c600bb1761b10d938146c28bb98Ruben Brunk            };
3180fd198ad89ec9c600bb1761b10d938146c28bb98Ruben Brunk
31931798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk            size_t totalJpegSize = bufferLength + sizeof(footer);
32031798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk            totalJpegSize = (totalJpegSize + 3) & ~0x3; // round up to nearest octonibble
32131798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk
32231798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk            if (totalJpegSize > totalSizeBytes) {
32331798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk                ALOGE("%s: Pixel buffer needs size %zu, cannot fit in gralloc buffer of size %zu",
32431798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk                        __FUNCTION__, totalJpegSize, totalSizeBytes);
3250fd198ad89ec9c600bb1761b10d938146c28bb98Ruben Brunk                return BAD_VALUE;
3260fd198ad89ec9c600bb1761b10d938146c28bb98Ruben Brunk            }
327feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
328feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
329feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            if (err != NO_ERROR) {
330feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                ALOGE("%s: Failed to lock buffer, error %s (%d).", __FUNCTION__, strerror(-err),
331feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                        err);
332feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                return err;
333feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
33431798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk
33531798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk            memcpy(img, pixelBuffer, bufferLength);
33631798f33184fd59dd3d3cc55e6373d9f91d220b6Ruben Brunk            memcpy(img + totalSizeBytes - sizeof(footer), &footer, sizeof(footer));
337feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            break;
338feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
339feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        default: {
340feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            ALOGE("%s: Invalid pixel format in produceFrame: %x", __FUNCTION__, pixelFmt);
341feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            return BAD_VALUE;
342feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
343feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
344feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
345feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    ALOGV("%s: Unlock buffer from %p", __FUNCTION__, anw.get());
346feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    err = buf->unlock();
347feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (err != NO_ERROR) {
348feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        ALOGE("%s: Failed to unlock buffer, error %s (%d).", __FUNCTION__, strerror(-err), err);
349feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        return err;
350feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
351feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
352feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    ALOGV("%s: Queue buffer to %p", __FUNCTION__, anw.get());
353feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    err = anw->queueBuffer(anw.get(), buf->getNativeBuffer(), /*fenceFd*/-1);
354feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (err != NO_ERROR) {
355feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        ALOGE("%s: Failed to queue buffer, error %s (%d).", __FUNCTION__, strerror(-err), err);
356feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        return err;
357feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
358feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    return NO_ERROR;
359feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk}
360feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
361feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkstatic sp<ANativeWindow> getNativeWindow(JNIEnv* env, jobject surface) {
362feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    sp<ANativeWindow> anw;
363feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (surface) {
364feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        anw = android_view_Surface_getNativeWindow(env, surface);
365feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        if (env->ExceptionCheck()) {
3663c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk            return NULL;
367feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
368feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    } else {
369feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        jniThrowNullPointerException(env, "surface");
3703c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        return NULL;
371feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
372feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (anw == NULL) {
373feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
374feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                "Surface had no valid native window.");
3753c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        return NULL;
376feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
377feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    return anw;
378feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk}
379feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
38028c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunkstatic sp<ANativeWindow> getNativeWindowFromTexture(JNIEnv* env, jobject surfaceTexture) {
38128c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    sp<ANativeWindow> anw;
38228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    if (surfaceTexture) {
38328c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        anw = android_SurfaceTexture_getNativeWindow(env, surfaceTexture);
38428c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        if (env->ExceptionCheck()) {
38528c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk            return NULL;
38628c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        }
38728c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    } else {
38828c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        jniThrowNullPointerException(env, "surfaceTexture");
38928c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        return NULL;
39028c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    }
39128c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    if (anw == NULL) {
39228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
39328c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk                "SurfaceTexture had no valid native window.");
39428c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        return NULL;
39528c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    }
39628c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    return anw;
39728c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk}
39828c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
3993c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunkstatic sp<Surface> getSurface(JNIEnv* env, jobject surface) {
4003c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    sp<Surface> s;
4013c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    if (surface) {
4023c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        s = android_view_Surface_getSurface(env, surface);
4033c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        if (env->ExceptionCheck()) {
4043c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk            return NULL;
4053c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        }
4063c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    } else {
4073c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        jniThrowNullPointerException(env, "surface");
4083c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        return NULL;
4093c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    }
4103c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    if (s == NULL) {
4113c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
4123c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk                "Surface had no valid native Surface.");
4133c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        return NULL;
4143c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    }
4153c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    return s;
4163c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk}
4173c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk
418feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkextern "C" {
419feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
420feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkstatic jint LegacyCameraDevice_nativeDetectSurfaceType(JNIEnv* env, jobject thiz, jobject surface) {
421feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    ALOGV("nativeDetectSurfaceType");
422feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    sp<ANativeWindow> anw;
423feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if ((anw = getNativeWindow(env, surface)) == NULL) {
424feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
425ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return BAD_VALUE;
426feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
427feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    int32_t fmt = 0;
428feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    status_t err = anw->query(anw.get(), NATIVE_WINDOW_FORMAT, &fmt);
429feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if(err != NO_ERROR) {
430ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        ALOGE("%s: Error while querying surface pixel format %s (%d).", __FUNCTION__, strerror(-err),
431ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk                err);
432ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return err;
433feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
434feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    return fmt;
435feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk}
436feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
437ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunkstatic jint LegacyCameraDevice_nativeDetectSurfaceDimens(JNIEnv* env, jobject thiz,
438feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk          jobject surface, jintArray dimens) {
439feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    ALOGV("nativeGetSurfaceDimens");
44028c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
44128c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    if (dimens == NULL) {
44228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        ALOGE("%s: Null dimens argument passed to nativeDetectSurfaceDimens", __FUNCTION__);
44328c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        return BAD_VALUE;
44428c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    }
44528c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
44628c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    if (env->GetArrayLength(dimens) < 2) {
44728c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        ALOGE("%s: Invalid length of dimens argument in nativeDetectSurfaceDimens", __FUNCTION__);
44828c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        return BAD_VALUE;
44928c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    }
45028c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
451feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    sp<ANativeWindow> anw;
452feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if ((anw = getNativeWindow(env, surface)) == NULL) {
453feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
454ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return BAD_VALUE;
455feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
456feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    int32_t dimenBuf[2];
457feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    status_t err = anw->query(anw.get(), NATIVE_WINDOW_WIDTH, dimenBuf);
458feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if(err != NO_ERROR) {
459ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        ALOGE("%s: Error while querying surface width %s (%d).", __FUNCTION__, strerror(-err),
460ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk                err);
461ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return err;
462feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
463feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    err = anw->query(anw.get(), NATIVE_WINDOW_HEIGHT, dimenBuf + 1);
464feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if(err != NO_ERROR) {
465ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        ALOGE("%s: Error while querying surface height %s (%d).", __FUNCTION__, strerror(-err),
466ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk                err);
467ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return err;
468feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
469feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    env->SetIntArrayRegion(dimens, /*start*/0, /*length*/ARRAY_SIZE(dimenBuf), dimenBuf);
470ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk    return NO_ERROR;
471feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk}
472feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
47328c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunkstatic jint LegacyCameraDevice_nativeDetectTextureDimens(JNIEnv* env, jobject thiz,
47428c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        jobject surfaceTexture, jintArray dimens) {
47528c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    ALOGV("nativeDetectTextureDimens");
47628c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    sp<ANativeWindow> anw;
47728c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    if ((anw = getNativeWindowFromTexture(env, surfaceTexture)) == NULL) {
47828c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        ALOGE("%s: Could not retrieve native window from SurfaceTexture.", __FUNCTION__);
47928c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        return BAD_VALUE;
48028c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    }
48128c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
48228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    int32_t dimenBuf[2];
48328c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    status_t err = anw->query(anw.get(), NATIVE_WINDOW_WIDTH, dimenBuf);
48428c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    if(err != NO_ERROR) {
48528c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        ALOGE("%s: Error while querying SurfaceTexture width %s (%d)", __FUNCTION__,
48628c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk                strerror(-err), err);
48728c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        return err;
48828c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    }
48928c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
49028c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    err = anw->query(anw.get(), NATIVE_WINDOW_HEIGHT, dimenBuf + 1);
49128c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    if(err != NO_ERROR) {
49228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        ALOGE("%s: Error while querying SurfaceTexture height %s (%d)", __FUNCTION__,
49328c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk                strerror(-err), err);
49428c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        return err;
49528c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    }
49628c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
49728c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    env->SetIntArrayRegion(dimens, /*start*/0, /*length*/ARRAY_SIZE(dimenBuf), dimenBuf);
49828c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    if (env->ExceptionCheck()) {
49928c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        return BAD_VALUE;
50028c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    }
50128c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    return NO_ERROR;
50228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk}
50328c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
504ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunkstatic jint LegacyCameraDevice_nativeConfigureSurface(JNIEnv* env, jobject thiz, jobject surface,
505feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        jint width, jint height, jint pixelFormat) {
506feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    ALOGV("nativeConfigureSurface");
507feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    sp<ANativeWindow> anw;
508feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if ((anw = getNativeWindow(env, surface)) == NULL) {
509feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
510ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return BAD_VALUE;
511feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
512feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    status_t err = configureSurface(anw, width, height, pixelFormat, CAMERA_DEVICE_BUFFER_SLACK);
513feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (err != NO_ERROR) {
514ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        ALOGE("%s: Error while configuring surface %s (%d).", __FUNCTION__, strerror(-err), err);
515ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return err;
516feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
517ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk    return NO_ERROR;
518feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk}
519feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
520ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunkstatic jint LegacyCameraDevice_nativeProduceFrame(JNIEnv* env, jobject thiz, jobject surface,
521feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        jbyteArray pixelBuffer, jint width, jint height, jint pixelFormat) {
522feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    ALOGV("nativeProduceFrame");
523feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    sp<ANativeWindow> anw;
524feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
525feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if ((anw = getNativeWindow(env, surface)) == NULL) {
526feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
527ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return BAD_VALUE;
528feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
529feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
530feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (pixelBuffer == NULL) {
531feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        jniThrowNullPointerException(env, "pixelBuffer");
532ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return DONT_CARE;
533feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
534feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
535feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    int32_t bufSize = static_cast<int32_t>(env->GetArrayLength(pixelBuffer));
536feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    jbyte* pixels = env->GetByteArrayElements(pixelBuffer, /*is_copy*/NULL);
537feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
538feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (pixels == NULL) {
539feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        jniThrowNullPointerException(env, "pixels");
540ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return DONT_CARE;
541feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
542feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
543feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    status_t err = produceFrame(anw, reinterpret_cast<uint8_t*>(pixels), width, height,
544feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            pixelFormat, bufSize);
545feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    env->ReleaseByteArrayElements(pixelBuffer, pixels, JNI_ABORT);
546feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
547feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (err != NO_ERROR) {
548ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        ALOGE("%s: Error while producing frame %s (%d).", __FUNCTION__, strerror(-err), err);
549ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return err;
550feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
551ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk    return NO_ERROR;
552feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk}
553feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
554ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunkstatic jint LegacyCameraDevice_nativeSetSurfaceFormat(JNIEnv* env, jobject thiz, jobject surface,
555feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        jint pixelFormat) {
556feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    ALOGV("nativeSetSurfaceType");
557feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    sp<ANativeWindow> anw;
558feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if ((anw = getNativeWindow(env, surface)) == NULL) {
559feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
560ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return BAD_VALUE;
561feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
562feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    status_t err = native_window_set_buffers_format(anw.get(), pixelFormat);
563feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (err != NO_ERROR) {
564ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        ALOGE("%s: Error while setting surface format %s (%d).", __FUNCTION__, strerror(-err), err);
565ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return err;
566feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
567ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk    return NO_ERROR;
568feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk}
569feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
570ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunkstatic jint LegacyCameraDevice_nativeSetSurfaceDimens(JNIEnv* env, jobject thiz, jobject surface,
571feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        jint width, jint height) {
572feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    ALOGV("nativeSetSurfaceDimens");
573feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    sp<ANativeWindow> anw;
574feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if ((anw = getNativeWindow(env, surface)) == NULL) {
575feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
576ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return BAD_VALUE;
577feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
578feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    status_t err = native_window_set_buffers_dimensions(anw.get(), width, height);
579feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (err != NO_ERROR) {
580ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        ALOGE("%s: Error while setting surface dimens %s (%d).", __FUNCTION__, strerror(-err), err);
581ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk        return err;
582feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
583a9bc3559109836efe7479a3279713bd58810b153Ruben Brunk
584a9bc3559109836efe7479a3279713bd58810b153Ruben Brunk    // WAR - Set user dimensions also to avoid incorrect scaling after TextureView orientation
585a9bc3559109836efe7479a3279713bd58810b153Ruben Brunk    // change.
586a9bc3559109836efe7479a3279713bd58810b153Ruben Brunk    err = native_window_set_buffers_user_dimensions(anw.get(), width, height);
587a9bc3559109836efe7479a3279713bd58810b153Ruben Brunk    if (err != NO_ERROR) {
588a9bc3559109836efe7479a3279713bd58810b153Ruben Brunk        ALOGE("%s: Error while setting surface user dimens %s (%d).", __FUNCTION__, strerror(-err),
589a9bc3559109836efe7479a3279713bd58810b153Ruben Brunk                err);
590a9bc3559109836efe7479a3279713bd58810b153Ruben Brunk        return err;
591a9bc3559109836efe7479a3279713bd58810b153Ruben Brunk    }
592ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk    return NO_ERROR;
593feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk}
594feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
5953c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunkstatic jlong LegacyCameraDevice_nativeGetSurfaceId(JNIEnv* env, jobject thiz, jobject surface) {
5963c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    ALOGV("nativeGetSurfaceId");
5973c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    sp<Surface> s;
5983c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    if ((s = getSurface(env, surface)) == NULL) {
5993c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        ALOGE("%s: Could not retrieve native Surface from surface.", __FUNCTION__);
6003c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        return 0;
6013c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    }
6023c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    sp<IGraphicBufferProducer> gbp = s->getIGraphicBufferProducer();
6033c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    if (gbp == NULL) {
6043c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        ALOGE("%s: Could not retrieve IGraphicBufferProducer from surface.", __FUNCTION__);
6053c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        return 0;
6063c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    }
6073c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    sp<IBinder> b = gbp->asBinder();
6083c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    if (b == NULL) {
6093c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        ALOGE("%s: Could not retrieve IBinder from surface.", __FUNCTION__);
6103c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk        return 0;
6113c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    }
6123c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    /*
6133c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk     * FIXME: Use better unique ID for surfaces than native IBinder pointer.  Fix also in the camera
6143c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk     * service (CameraDeviceClient.h).
6153c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk     */
6163c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    return reinterpret_cast<jlong>(b.get());
6173c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk}
6183c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk
61928c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunkstatic jint LegacyCameraDevice_nativeSetSurfaceOrientation(JNIEnv* env, jobject thiz,
62028c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        jobject surface, jint facing, jint orientation) {
62128c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    ALOGV("nativeSetSurfaceOrientation");
62228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    sp<ANativeWindow> anw;
62328c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    if ((anw = getNativeWindow(env, surface)) == NULL) {
62428c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
62528c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        return BAD_VALUE;
62628c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    }
62728c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
62828c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    status_t err = NO_ERROR;
62928c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    CameraMetadata staticMetadata;
63028c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
63128c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    int32_t orientVal = static_cast<int32_t>(orientation);
63228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    uint8_t facingVal = static_cast<uint8_t>(facing);
63328c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    staticMetadata.update(ANDROID_SENSOR_ORIENTATION, &orientVal, 1);
63428c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    staticMetadata.update(ANDROID_LENS_FACING, &facingVal, 1);
63528c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
63628c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    int32_t transform = 0;
63728c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
63891838ded36131525312739c0929913b215519c2aRuben Brunk    if ((err = CameraUtils::getRotationTransform(staticMetadata, /*out*/&transform)) != NO_ERROR) {
63928c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        ALOGE("%s: Invalid rotation transform %s (%d)", __FUNCTION__, strerror(-err),
64028c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk                err);
64128c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        return err;
64228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    }
64328c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
64428c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    ALOGV("%s: Setting buffer sticky transform to %d", __FUNCTION__, transform);
64528c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
64691838ded36131525312739c0929913b215519c2aRuben Brunk    if ((err = native_window_set_buffers_sticky_transform(anw.get(), transform)) != NO_ERROR) {
64728c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        ALOGE("%s: Unable to configure surface transform, error %s (%d)", __FUNCTION__,
64828c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk                strerror(-err), err);
64928c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk        return err;
65028c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    }
65128c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
65228c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    return NO_ERROR;
65328c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk}
65428c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk
65591838ded36131525312739c0929913b215519c2aRuben Brunkstatic jint LegacyCameraDevice_nativeSetNextTimestamp(JNIEnv* env, jobject thiz, jobject surface,
65691838ded36131525312739c0929913b215519c2aRuben Brunk        jlong timestamp) {
65791838ded36131525312739c0929913b215519c2aRuben Brunk    ALOGV("nativeSetNextTimestamp");
65891838ded36131525312739c0929913b215519c2aRuben Brunk    sp<ANativeWindow> anw;
65991838ded36131525312739c0929913b215519c2aRuben Brunk    if ((anw = getNativeWindow(env, surface)) == NULL) {
66091838ded36131525312739c0929913b215519c2aRuben Brunk        ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
66191838ded36131525312739c0929913b215519c2aRuben Brunk        return BAD_VALUE;
66291838ded36131525312739c0929913b215519c2aRuben Brunk    }
66391838ded36131525312739c0929913b215519c2aRuben Brunk
66491838ded36131525312739c0929913b215519c2aRuben Brunk    status_t err = NO_ERROR;
66591838ded36131525312739c0929913b215519c2aRuben Brunk
66691838ded36131525312739c0929913b215519c2aRuben Brunk    if ((err = native_window_set_buffers_timestamp(anw.get(), static_cast<int64_t>(timestamp))) !=
66791838ded36131525312739c0929913b215519c2aRuben Brunk            NO_ERROR) {
66891838ded36131525312739c0929913b215519c2aRuben Brunk        ALOGE("%s: Unable to set surface timestamp, error %s (%d)", __FUNCTION__, strerror(-err),
66991838ded36131525312739c0929913b215519c2aRuben Brunk                err);
67091838ded36131525312739c0929913b215519c2aRuben Brunk        return err;
67191838ded36131525312739c0929913b215519c2aRuben Brunk    }
67291838ded36131525312739c0929913b215519c2aRuben Brunk    return NO_ERROR;
67391838ded36131525312739c0929913b215519c2aRuben Brunk}
67491838ded36131525312739c0929913b215519c2aRuben Brunk
6751dc1326eaedd11ffd8f85927b8f0195f4f7598d3Ruben Brunkstatic jint LegacyCameraDevice_nativeGetJpegFooterSize(JNIEnv* env, jobject thiz) {
6761dc1326eaedd11ffd8f85927b8f0195f4f7598d3Ruben Brunk    ALOGV("nativeGetJpegFooterSize");
6771dc1326eaedd11ffd8f85927b8f0195f4f7598d3Ruben Brunk    return static_cast<jint>(sizeof(struct camera3_jpeg_blob));
6781dc1326eaedd11ffd8f85927b8f0195f4f7598d3Ruben Brunk}
6791dc1326eaedd11ffd8f85927b8f0195f4f7598d3Ruben Brunk
680feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk} // extern "C"
681feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
682feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkstatic JNINativeMethod gCameraDeviceMethods[] = {
683feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    { "nativeDetectSurfaceType",
684feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    "(Landroid/view/Surface;)I",
685feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    (void *)LegacyCameraDevice_nativeDetectSurfaceType },
686feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    { "nativeDetectSurfaceDimens",
687ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk    "(Landroid/view/Surface;[I)I",
688feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    (void *)LegacyCameraDevice_nativeDetectSurfaceDimens },
689feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    { "nativeConfigureSurface",
690ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk    "(Landroid/view/Surface;III)I",
691feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    (void *)LegacyCameraDevice_nativeConfigureSurface },
692feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    { "nativeProduceFrame",
693ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk    "(Landroid/view/Surface;[BIII)I",
694feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    (void *)LegacyCameraDevice_nativeProduceFrame },
695feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    { "nativeSetSurfaceFormat",
696ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk    "(Landroid/view/Surface;I)I",
697feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    (void *)LegacyCameraDevice_nativeSetSurfaceFormat },
698feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    { "nativeSetSurfaceDimens",
699ef14da32804b06bac872c9e0e14ce0e52120a0bdRuben Brunk    "(Landroid/view/Surface;II)I",
700feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    (void *)LegacyCameraDevice_nativeSetSurfaceDimens },
7013c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    { "nativeGetSurfaceId",
7023c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    "(Landroid/view/Surface;)J",
7033c8fa3b356fa8f24b55d3dc42d4313297542e9f2Ruben Brunk    (void *)LegacyCameraDevice_nativeGetSurfaceId },
70428c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    { "nativeDetectTextureDimens",
70528c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    "(Landroid/graphics/SurfaceTexture;[I)I",
70628c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    (void *)LegacyCameraDevice_nativeDetectTextureDimens },
70728c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    { "nativeSetSurfaceOrientation",
70828c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    "(Landroid/view/Surface;II)I",
70928c49c9d202a9f4675c1c1e5d4562492d2107b79Ruben Brunk    (void *)LegacyCameraDevice_nativeSetSurfaceOrientation },
71091838ded36131525312739c0929913b215519c2aRuben Brunk    { "nativeSetNextTimestamp",
71191838ded36131525312739c0929913b215519c2aRuben Brunk    "(Landroid/view/Surface;J)I",
71291838ded36131525312739c0929913b215519c2aRuben Brunk    (void *)LegacyCameraDevice_nativeSetNextTimestamp },
7131dc1326eaedd11ffd8f85927b8f0195f4f7598d3Ruben Brunk    { "nativeGetJpegFooterSize",
7141dc1326eaedd11ffd8f85927b8f0195f4f7598d3Ruben Brunk    "()I",
7151dc1326eaedd11ffd8f85927b8f0195f4f7598d3Ruben Brunk    (void *)LegacyCameraDevice_nativeGetJpegFooterSize },
716feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk};
717feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
718feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk// Get all the required offsets in java class and register native functions
719feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkint register_android_hardware_camera2_legacy_LegacyCameraDevice(JNIEnv* env)
720feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk{
721feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    // Register native functions
722feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    return AndroidRuntime::registerNativeMethods(env,
723feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            CAMERA_DEVICE_CLASS_NAME,
724feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            gCameraDeviceMethods,
725feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            NELEM(gCameraDeviceMethods));
726feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk}
727feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
728