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