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 "JNIHelp.h"
     26 #include "android_runtime/AndroidRuntime.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 <ui/GraphicBuffer.h>
     33 #include <system/window.h>
     34 #include <hardware/camera3.h>
     35 #include <system/camera_metadata.h>
     36 
     37 #include <stdint.h>
     38 #include <inttypes.h>
     39 
     40 using namespace android;
     41 
     42 // fully-qualified class name
     43 #define CAMERA_DEVICE_CLASS_NAME "android/hardware/camera2/legacy/LegacyCameraDevice"
     44 #define CAMERA_DEVICE_BUFFER_SLACK  3
     45 #define DONT_CARE 0
     46 
     47 #define ARRAY_SIZE(a) (sizeof(a)/sizeof(*(a)))
     48 
     49 #define ALIGN(x, mask) ( ((x) + (mask) - 1) & ~((mask) - 1) )
     50 
     51 /**
     52  * Convert from RGB 888 to Y'CbCr using the conversion specified in ITU-R BT.601 for
     53  * digital RGB with K_b = 0.114, and K_r = 0.299.
     54  */
     55 static void rgbToYuv420(uint8_t* rgbBuf, size_t width, size_t height, uint8_t* yPlane,
     56         uint8_t* uPlane, uint8_t* vPlane, size_t chromaStep, size_t yStride, size_t chromaStride) {
     57     uint8_t R, G, B;
     58     size_t index = 0;
     59 
     60     size_t cStrideDiff = chromaStride - width;
     61 
     62     for (size_t j = 0; j < height; j++) {
     63         for (size_t i = 0; i < width; i++) {
     64             R = rgbBuf[index++];
     65             G = rgbBuf[index++];
     66             B = rgbBuf[index++];
     67             *(yPlane + i) = ((66 * R + 129 * G +  25 * B + 128) >> 8) +  16;
     68 
     69             if (j % 2 == 0 && i % 2 == 0){
     70                 *uPlane = (( -38 * R -  74 * G + 112 * B + 128) >> 8) + 128;
     71                 *vPlane = (( 112 * R -  94 * G -  18 * B + 128) >> 8) + 128;
     72                 uPlane += chromaStep;
     73                 vPlane += chromaStep;
     74             }
     75             // Skip alpha
     76             index++;
     77         }
     78         yPlane += yStride;
     79         if (j % 2 == 0) {
     80             uPlane += cStrideDiff;
     81             vPlane += cStrideDiff;
     82         }
     83     }
     84 }
     85 
     86 static void rgbToYuv420(uint8_t* rgbBuf, size_t width, size_t height, android_ycbcr* ycbcr) {
     87     size_t cStep = ycbcr->chroma_step;
     88     size_t cStride = ycbcr->cstride;
     89     size_t yStride = ycbcr->ystride;
     90     rgbToYuv420(rgbBuf, width, height, reinterpret_cast<uint8_t*>(ycbcr->y),
     91             reinterpret_cast<uint8_t*>(ycbcr->cb), reinterpret_cast<uint8_t*>(ycbcr->cr),
     92             cStep, yStride, cStride);
     93 }
     94 
     95 static status_t configureSurface(const sp<ANativeWindow>& anw,
     96                                  int32_t width,
     97                                  int32_t height,
     98                                  int32_t pixelFmt,
     99                                  int32_t maxBufferSlack) {
    100     status_t err = NO_ERROR;
    101     err = native_window_set_buffers_dimensions(anw.get(), width, height);
    102     if (err != NO_ERROR) {
    103         ALOGE("%s: Failed to set native window buffer dimensions, error %s (%d).", __FUNCTION__,
    104                 strerror(-err), err);
    105         return err;
    106     }
    107 
    108     err = native_window_set_buffers_format(anw.get(), pixelFmt);
    109     if (err != NO_ERROR) {
    110         ALOGE("%s: Failed to set native window buffer format, error %s (%d).", __FUNCTION__,
    111                 strerror(-err), err);
    112         return err;
    113     }
    114 
    115     err = native_window_set_usage(anw.get(), GRALLOC_USAGE_SW_WRITE_OFTEN);
    116     if (err != NO_ERROR) {
    117         ALOGE("%s: Failed to set native window usage flag, error %s (%d).", __FUNCTION__,
    118                 strerror(-err), err);
    119         return err;
    120     }
    121 
    122     int minUndequeuedBuffers;
    123     err = anw.get()->query(anw.get(),
    124             NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
    125             &minUndequeuedBuffers);
    126     if (err != NO_ERROR) {
    127         ALOGE("%s: Failed to get native window min undequeued buffers, error %s (%d).",
    128                 __FUNCTION__, strerror(-err), err);
    129         return err;
    130     }
    131 
    132     ALOGV("%s: Setting buffer count to %d, size to (%dx%d), fmt (0x%x)", __FUNCTION__,
    133           maxBufferSlack + 1 + minUndequeuedBuffers,
    134           width, height, pixelFmt);
    135     err = native_window_set_buffer_count(anw.get(), maxBufferSlack + 1 + minUndequeuedBuffers);
    136     if (err != NO_ERROR) {
    137         ALOGE("%s: Failed to set native window buffer count, error %s (%d).", __FUNCTION__,
    138                 strerror(-err), err);
    139         return err;
    140     }
    141     return NO_ERROR;
    142 }
    143 
    144 /**
    145  * Produce a frame in the given surface.
    146  *
    147  * Args:
    148  *    anw - a surface to produce a frame in.
    149  *    pixelBuffer - image buffer to generate a frame from.
    150  *    width - width of the pixelBuffer in pixels.
    151  *    height - height of the pixelBuffer in pixels.
    152  *    pixelFmt - format of the pixelBuffer, one of:
    153  *               HAL_PIXEL_FORMAT_YCrCb_420_SP,
    154  *               HAL_PIXEL_FORMAT_YCbCr_420_888,
    155  *               HAL_PIXEL_FORMAT_BLOB
    156  *    bufSize - the size of the pixelBuffer in bytes.
    157  */
    158 static status_t produceFrame(const sp<ANativeWindow>& anw,
    159                              uint8_t* pixelBuffer,
    160                              int32_t bufWidth, // Width of the pixelBuffer
    161                              int32_t bufHeight, // Height of the pixelBuffer
    162                              int32_t pixelFmt, // Format of the pixelBuffer
    163                              int32_t bufSize) {
    164     ATRACE_CALL();
    165     status_t err = NO_ERROR;
    166     ANativeWindowBuffer* anb;
    167     ALOGV("%s: Dequeue buffer from %p %dx%d (fmt=%x, size=%x)",
    168             __FUNCTION__, anw.get(), bufWidth, bufHeight, pixelFmt, bufSize);
    169 
    170     if (anw == 0) {
    171         ALOGE("%s: anw must not be NULL", __FUNCTION__);
    172         return BAD_VALUE;
    173     } else if (pixelBuffer == NULL) {
    174         ALOGE("%s: pixelBuffer must not be NULL", __FUNCTION__);
    175         return BAD_VALUE;
    176     } else if (bufWidth < 0) {
    177         ALOGE("%s: width must be non-negative", __FUNCTION__);
    178         return BAD_VALUE;
    179     } else if (bufHeight < 0) {
    180         ALOGE("%s: height must be non-negative", __FUNCTION__);
    181         return BAD_VALUE;
    182     } else if (bufSize < 0) {
    183         ALOGE("%s: bufSize must be non-negative", __FUNCTION__);
    184         return BAD_VALUE;
    185     }
    186 
    187     size_t width = static_cast<size_t>(bufWidth);
    188     size_t height = static_cast<size_t>(bufHeight);
    189     size_t bufferLength = static_cast<size_t>(bufSize);
    190 
    191     // TODO: Switch to using Surface::lock and Surface::unlockAndPost
    192     err = native_window_dequeue_buffer_and_wait(anw.get(), &anb);
    193     if (err != NO_ERROR) return err;
    194 
    195     sp<GraphicBuffer> buf(new GraphicBuffer(anb, /*keepOwnership*/false));
    196     uint32_t grallocBufWidth = buf->getWidth();
    197     uint32_t grallocBufHeight = buf->getHeight();
    198     uint32_t grallocBufStride = buf->getStride();
    199     if (grallocBufWidth != width || grallocBufHeight != height) {
    200         ALOGE("%s: Received gralloc buffer with bad dimensions %" PRIu32 "x%" PRIu32
    201                 ", expecting dimensions %zu x %zu",  __FUNCTION__, grallocBufWidth,
    202                 grallocBufHeight, width, height);
    203         return BAD_VALUE;
    204     }
    205 
    206     int32_t bufFmt = 0;
    207     err = anw->query(anw.get(), NATIVE_WINDOW_FORMAT, &bufFmt);
    208     if (err != NO_ERROR) {
    209         ALOGE("%s: Error while querying surface pixel format %s (%d).", __FUNCTION__,
    210                 strerror(-err), err);
    211         return err;
    212     }
    213 
    214     uint64_t tmpSize = (pixelFmt == HAL_PIXEL_FORMAT_BLOB) ? grallocBufWidth :
    215             4 * grallocBufHeight * grallocBufWidth;
    216     if (bufFmt != pixelFmt) {
    217         if (bufFmt == HAL_PIXEL_FORMAT_RGBA_8888 && pixelFmt == HAL_PIXEL_FORMAT_BLOB) {
    218             ALOGV("%s: Using BLOB to RGBA format override.", __FUNCTION__);
    219             tmpSize = 4 * (grallocBufWidth + grallocBufStride * (grallocBufHeight - 1));
    220         } else {
    221             ALOGW("%s: Format mismatch in produceFrame: expecting format %#" PRIx32
    222                     ", but received buffer with format %#" PRIx32, __FUNCTION__, pixelFmt, bufFmt);
    223         }
    224     }
    225 
    226     if (tmpSize > SIZE_MAX) {
    227         ALOGE("%s: Overflow calculating size, buffer with dimens %zu x %zu is absurdly large...",
    228                 __FUNCTION__, width, height);
    229         return BAD_VALUE;
    230     }
    231 
    232     size_t totalSizeBytes = tmpSize;
    233 
    234     switch(pixelFmt) {
    235         case HAL_PIXEL_FORMAT_YCrCb_420_SP: {
    236             if (bufferLength < totalSizeBytes) {
    237                 ALOGE("%s: PixelBuffer size %zu too small for given dimensions",
    238                         __FUNCTION__, bufferLength);
    239                 return BAD_VALUE;
    240             }
    241             uint8_t* img = NULL;
    242             ALOGV("%s: Lock buffer from %p for write", __FUNCTION__, anw.get());
    243             err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
    244             if (err != NO_ERROR) return err;
    245 
    246             uint8_t* yPlane = img;
    247             uint8_t* uPlane = img + height * width;
    248             uint8_t* vPlane = uPlane + 1;
    249             size_t chromaStep = 2;
    250             size_t yStride = width;
    251             size_t chromaStride = width;
    252 
    253             rgbToYuv420(pixelBuffer, width, height, yPlane,
    254                     uPlane, vPlane, chromaStep, yStride, chromaStride);
    255             break;
    256         }
    257         case HAL_PIXEL_FORMAT_YV12: {
    258             if (bufferLength < totalSizeBytes) {
    259                 ALOGE("%s: PixelBuffer size %zu too small for given dimensions",
    260                         __FUNCTION__, bufferLength);
    261                 return BAD_VALUE;
    262             }
    263 
    264             if ((width & 1) || (height & 1)) {
    265                 ALOGE("%s: Dimens %zu x %zu are not divisible by 2.", __FUNCTION__, width, height);
    266                 return BAD_VALUE;
    267             }
    268 
    269             uint8_t* img = NULL;
    270             ALOGV("%s: Lock buffer from %p for write", __FUNCTION__, anw.get());
    271             err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
    272             if (err != NO_ERROR) {
    273                 ALOGE("%s: Error %s (%d) while locking gralloc buffer for write.", __FUNCTION__,
    274                         strerror(-err), err);
    275                 return err;
    276             }
    277 
    278             uint32_t stride = buf->getStride();
    279             LOG_ALWAYS_FATAL_IF(stride % 16, "Stride is not 16 pixel aligned %d", stride);
    280 
    281             uint32_t cStride = ALIGN(stride / 2, 16);
    282             size_t chromaStep = 1;
    283 
    284             uint8_t* yPlane = img;
    285             uint8_t* crPlane = img + static_cast<uint32_t>(height) * stride;
    286             uint8_t* cbPlane = crPlane + cStride * static_cast<uint32_t>(height) / 2;
    287 
    288             rgbToYuv420(pixelBuffer, width, height, yPlane,
    289                     crPlane, cbPlane, chromaStep, stride, cStride);
    290             break;
    291         }
    292         case HAL_PIXEL_FORMAT_YCbCr_420_888: {
    293             // Software writes with YCbCr_420_888 format are unsupported
    294             // by the gralloc module for now
    295             if (bufferLength < totalSizeBytes) {
    296                 ALOGE("%s: PixelBuffer size %zu too small for given dimensions",
    297                         __FUNCTION__, bufferLength);
    298                 return BAD_VALUE;
    299             }
    300             android_ycbcr ycbcr = android_ycbcr();
    301             ALOGV("%s: Lock buffer from %p for write", __FUNCTION__, anw.get());
    302 
    303             err = buf->lockYCbCr(GRALLOC_USAGE_SW_WRITE_OFTEN, &ycbcr);
    304             if (err != NO_ERROR) {
    305                 ALOGE("%s: Failed to lock ycbcr buffer, error %s (%d).", __FUNCTION__,
    306                         strerror(-err), err);
    307                 return err;
    308             }
    309             rgbToYuv420(pixelBuffer, width, height, &ycbcr);
    310             break;
    311         }
    312         case HAL_PIXEL_FORMAT_BLOB: {
    313             int8_t* img = NULL;
    314             struct camera3_jpeg_blob footer = {
    315                 jpeg_blob_id: CAMERA3_JPEG_BLOB_ID,
    316                 jpeg_size: (uint32_t)bufferLength
    317             };
    318 
    319             size_t totalJpegSize = bufferLength + sizeof(footer);
    320             totalJpegSize = (totalJpegSize + 3) & ~0x3; // round up to nearest octonibble
    321 
    322             if (totalJpegSize > totalSizeBytes) {
    323                 ALOGE("%s: Pixel buffer needs size %zu, cannot fit in gralloc buffer of size %zu",
    324                         __FUNCTION__, totalJpegSize, totalSizeBytes);
    325                 return BAD_VALUE;
    326             }
    327 
    328             err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
    329             if (err != NO_ERROR) {
    330                 ALOGE("%s: Failed to lock buffer, error %s (%d).", __FUNCTION__, strerror(-err),
    331                         err);
    332                 return err;
    333             }
    334 
    335             memcpy(img, pixelBuffer, bufferLength);
    336             memcpy(img + totalSizeBytes - sizeof(footer), &footer, sizeof(footer));
    337             break;
    338         }
    339         default: {
    340             ALOGE("%s: Invalid pixel format in produceFrame: %x", __FUNCTION__, pixelFmt);
    341             return BAD_VALUE;
    342         }
    343     }
    344 
    345     ALOGV("%s: Unlock buffer from %p", __FUNCTION__, anw.get());
    346     err = buf->unlock();
    347     if (err != NO_ERROR) {
    348         ALOGE("%s: Failed to unlock buffer, error %s (%d).", __FUNCTION__, strerror(-err), err);
    349         return err;
    350     }
    351 
    352     ALOGV("%s: Queue buffer to %p", __FUNCTION__, anw.get());
    353     err = anw->queueBuffer(anw.get(), buf->getNativeBuffer(), /*fenceFd*/-1);
    354     if (err != NO_ERROR) {
    355         ALOGE("%s: Failed to queue buffer, error %s (%d).", __FUNCTION__, strerror(-err), err);
    356         return err;
    357     }
    358     return NO_ERROR;
    359 }
    360 
    361 static sp<ANativeWindow> getNativeWindow(JNIEnv* env, jobject surface) {
    362     sp<ANativeWindow> anw;
    363     if (surface) {
    364         anw = android_view_Surface_getNativeWindow(env, surface);
    365         if (env->ExceptionCheck()) {
    366             return NULL;
    367         }
    368     } else {
    369         jniThrowNullPointerException(env, "surface");
    370         return NULL;
    371     }
    372     if (anw == NULL) {
    373         jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
    374                 "Surface had no valid native window.");
    375         return NULL;
    376     }
    377     return anw;
    378 }
    379 
    380 static sp<ANativeWindow> getNativeWindowFromTexture(JNIEnv* env, jobject surfaceTexture) {
    381     sp<ANativeWindow> anw;
    382     if (surfaceTexture) {
    383         anw = android_SurfaceTexture_getNativeWindow(env, surfaceTexture);
    384         if (env->ExceptionCheck()) {
    385             return NULL;
    386         }
    387     } else {
    388         jniThrowNullPointerException(env, "surfaceTexture");
    389         return NULL;
    390     }
    391     if (anw == NULL) {
    392         jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
    393                 "SurfaceTexture had no valid native window.");
    394         return NULL;
    395     }
    396     return anw;
    397 }
    398 
    399 static sp<Surface> getSurface(JNIEnv* env, jobject surface) {
    400     sp<Surface> s;
    401     if (surface) {
    402         s = android_view_Surface_getSurface(env, surface);
    403         if (env->ExceptionCheck()) {
    404             return NULL;
    405         }
    406     } else {
    407         jniThrowNullPointerException(env, "surface");
    408         return NULL;
    409     }
    410     if (s == NULL) {
    411         jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
    412                 "Surface had no valid native Surface.");
    413         return NULL;
    414     }
    415     return s;
    416 }
    417 
    418 extern "C" {
    419 
    420 static jint LegacyCameraDevice_nativeDetectSurfaceType(JNIEnv* env, jobject thiz, jobject surface) {
    421     ALOGV("nativeDetectSurfaceType");
    422     sp<ANativeWindow> anw;
    423     if ((anw = getNativeWindow(env, surface)) == NULL) {
    424         ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
    425         return BAD_VALUE;
    426     }
    427     int32_t fmt = 0;
    428     status_t err = anw->query(anw.get(), NATIVE_WINDOW_FORMAT, &fmt);
    429     if(err != NO_ERROR) {
    430         ALOGE("%s: Error while querying surface pixel format %s (%d).", __FUNCTION__, strerror(-err),
    431                 err);
    432         return err;
    433     }
    434     return fmt;
    435 }
    436 
    437 static jint LegacyCameraDevice_nativeDetectSurfaceDimens(JNIEnv* env, jobject thiz,
    438           jobject surface, jintArray dimens) {
    439     ALOGV("nativeGetSurfaceDimens");
    440 
    441     if (dimens == NULL) {
    442         ALOGE("%s: Null dimens argument passed to nativeDetectSurfaceDimens", __FUNCTION__);
    443         return BAD_VALUE;
    444     }
    445 
    446     if (env->GetArrayLength(dimens) < 2) {
    447         ALOGE("%s: Invalid length of dimens argument in nativeDetectSurfaceDimens", __FUNCTION__);
    448         return BAD_VALUE;
    449     }
    450 
    451     sp<ANativeWindow> anw;
    452     if ((anw = getNativeWindow(env, surface)) == NULL) {
    453         ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
    454         return BAD_VALUE;
    455     }
    456     int32_t dimenBuf[2];
    457     status_t err = anw->query(anw.get(), NATIVE_WINDOW_WIDTH, dimenBuf);
    458     if(err != NO_ERROR) {
    459         ALOGE("%s: Error while querying surface width %s (%d).", __FUNCTION__, strerror(-err),
    460                 err);
    461         return err;
    462     }
    463     err = anw->query(anw.get(), NATIVE_WINDOW_HEIGHT, dimenBuf + 1);
    464     if(err != NO_ERROR) {
    465         ALOGE("%s: Error while querying surface height %s (%d).", __FUNCTION__, strerror(-err),
    466                 err);
    467         return err;
    468     }
    469     env->SetIntArrayRegion(dimens, /*start*/0, /*length*/ARRAY_SIZE(dimenBuf), dimenBuf);
    470     return NO_ERROR;
    471 }
    472 
    473 static jint LegacyCameraDevice_nativeDetectTextureDimens(JNIEnv* env, jobject thiz,
    474         jobject surfaceTexture, jintArray dimens) {
    475     ALOGV("nativeDetectTextureDimens");
    476     sp<ANativeWindow> anw;
    477     if ((anw = getNativeWindowFromTexture(env, surfaceTexture)) == NULL) {
    478         ALOGE("%s: Could not retrieve native window from SurfaceTexture.", __FUNCTION__);
    479         return BAD_VALUE;
    480     }
    481 
    482     int32_t dimenBuf[2];
    483     status_t err = anw->query(anw.get(), NATIVE_WINDOW_WIDTH, dimenBuf);
    484     if(err != NO_ERROR) {
    485         ALOGE("%s: Error while querying SurfaceTexture width %s (%d)", __FUNCTION__,
    486                 strerror(-err), err);
    487         return err;
    488     }
    489 
    490     err = anw->query(anw.get(), NATIVE_WINDOW_HEIGHT, dimenBuf + 1);
    491     if(err != NO_ERROR) {
    492         ALOGE("%s: Error while querying SurfaceTexture height %s (%d)", __FUNCTION__,
    493                 strerror(-err), err);
    494         return err;
    495     }
    496 
    497     env->SetIntArrayRegion(dimens, /*start*/0, /*length*/ARRAY_SIZE(dimenBuf), dimenBuf);
    498     if (env->ExceptionCheck()) {
    499         return BAD_VALUE;
    500     }
    501     return NO_ERROR;
    502 }
    503 
    504 static jint LegacyCameraDevice_nativeConfigureSurface(JNIEnv* env, jobject thiz, jobject surface,
    505         jint width, jint height, jint pixelFormat) {
    506     ALOGV("nativeConfigureSurface");
    507     sp<ANativeWindow> anw;
    508     if ((anw = getNativeWindow(env, surface)) == NULL) {
    509         ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
    510         return BAD_VALUE;
    511     }
    512     status_t err = configureSurface(anw, width, height, pixelFormat, CAMERA_DEVICE_BUFFER_SLACK);
    513     if (err != NO_ERROR) {
    514         ALOGE("%s: Error while configuring surface %s (%d).", __FUNCTION__, strerror(-err), err);
    515         return err;
    516     }
    517     return NO_ERROR;
    518 }
    519 
    520 static jint LegacyCameraDevice_nativeProduceFrame(JNIEnv* env, jobject thiz, jobject surface,
    521         jbyteArray pixelBuffer, jint width, jint height, jint pixelFormat) {
    522     ALOGV("nativeProduceFrame");
    523     sp<ANativeWindow> anw;
    524 
    525     if ((anw = getNativeWindow(env, surface)) == NULL) {
    526         ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
    527         return BAD_VALUE;
    528     }
    529 
    530     if (pixelBuffer == NULL) {
    531         jniThrowNullPointerException(env, "pixelBuffer");
    532         return DONT_CARE;
    533     }
    534 
    535     int32_t bufSize = static_cast<int32_t>(env->GetArrayLength(pixelBuffer));
    536     jbyte* pixels = env->GetByteArrayElements(pixelBuffer, /*is_copy*/NULL);
    537 
    538     if (pixels == NULL) {
    539         jniThrowNullPointerException(env, "pixels");
    540         return DONT_CARE;
    541     }
    542 
    543     status_t err = produceFrame(anw, reinterpret_cast<uint8_t*>(pixels), width, height,
    544             pixelFormat, bufSize);
    545     env->ReleaseByteArrayElements(pixelBuffer, pixels, JNI_ABORT);
    546 
    547     if (err != NO_ERROR) {
    548         ALOGE("%s: Error while producing frame %s (%d).", __FUNCTION__, strerror(-err), err);
    549         return err;
    550     }
    551     return NO_ERROR;
    552 }
    553 
    554 static jint LegacyCameraDevice_nativeSetSurfaceFormat(JNIEnv* env, jobject thiz, jobject surface,
    555         jint pixelFormat) {
    556     ALOGV("nativeSetSurfaceType");
    557     sp<ANativeWindow> anw;
    558     if ((anw = getNativeWindow(env, surface)) == NULL) {
    559         ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
    560         return BAD_VALUE;
    561     }
    562     status_t err = native_window_set_buffers_format(anw.get(), pixelFormat);
    563     if (err != NO_ERROR) {
    564         ALOGE("%s: Error while setting surface format %s (%d).", __FUNCTION__, strerror(-err), err);
    565         return err;
    566     }
    567     return NO_ERROR;
    568 }
    569 
    570 static jint LegacyCameraDevice_nativeSetSurfaceDimens(JNIEnv* env, jobject thiz, jobject surface,
    571         jint width, jint height) {
    572     ALOGV("nativeSetSurfaceDimens");
    573     sp<ANativeWindow> anw;
    574     if ((anw = getNativeWindow(env, surface)) == NULL) {
    575         ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
    576         return BAD_VALUE;
    577     }
    578     status_t err = native_window_set_buffers_dimensions(anw.get(), width, height);
    579     if (err != NO_ERROR) {
    580         ALOGE("%s: Error while setting surface dimens %s (%d).", __FUNCTION__, strerror(-err), err);
    581         return err;
    582     }
    583 
    584     // WAR - Set user dimensions also to avoid incorrect scaling after TextureView orientation
    585     // change.
    586     err = native_window_set_buffers_user_dimensions(anw.get(), width, height);
    587     if (err != NO_ERROR) {
    588         ALOGE("%s: Error while setting surface user dimens %s (%d).", __FUNCTION__, strerror(-err),
    589                 err);
    590         return err;
    591     }
    592     return NO_ERROR;
    593 }
    594 
    595 static jlong LegacyCameraDevice_nativeGetSurfaceId(JNIEnv* env, jobject thiz, jobject surface) {
    596     ALOGV("nativeGetSurfaceId");
    597     sp<Surface> s;
    598     if ((s = getSurface(env, surface)) == NULL) {
    599         ALOGE("%s: Could not retrieve native Surface from surface.", __FUNCTION__);
    600         return 0;
    601     }
    602     sp<IGraphicBufferProducer> gbp = s->getIGraphicBufferProducer();
    603     if (gbp == NULL) {
    604         ALOGE("%s: Could not retrieve IGraphicBufferProducer from surface.", __FUNCTION__);
    605         return 0;
    606     }
    607     sp<IBinder> b = gbp->asBinder();
    608     if (b == NULL) {
    609         ALOGE("%s: Could not retrieve IBinder from surface.", __FUNCTION__);
    610         return 0;
    611     }
    612     /*
    613      * FIXME: Use better unique ID for surfaces than native IBinder pointer.  Fix also in the camera
    614      * service (CameraDeviceClient.h).
    615      */
    616     return reinterpret_cast<jlong>(b.get());
    617 }
    618 
    619 static jint LegacyCameraDevice_nativeSetSurfaceOrientation(JNIEnv* env, jobject thiz,
    620         jobject surface, jint facing, jint orientation) {
    621     ALOGV("nativeSetSurfaceOrientation");
    622     sp<ANativeWindow> anw;
    623     if ((anw = getNativeWindow(env, surface)) == NULL) {
    624         ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
    625         return BAD_VALUE;
    626     }
    627 
    628     status_t err = NO_ERROR;
    629     CameraMetadata staticMetadata;
    630 
    631     int32_t orientVal = static_cast<int32_t>(orientation);
    632     uint8_t facingVal = static_cast<uint8_t>(facing);
    633     staticMetadata.update(ANDROID_SENSOR_ORIENTATION, &orientVal, 1);
    634     staticMetadata.update(ANDROID_LENS_FACING, &facingVal, 1);
    635 
    636     int32_t transform = 0;
    637 
    638     if ((err = CameraUtils::getRotationTransform(staticMetadata, /*out*/&transform)) != NO_ERROR) {
    639         ALOGE("%s: Invalid rotation transform %s (%d)", __FUNCTION__, strerror(-err),
    640                 err);
    641         return err;
    642     }
    643 
    644     ALOGV("%s: Setting buffer sticky transform to %d", __FUNCTION__, transform);
    645 
    646     if ((err = native_window_set_buffers_sticky_transform(anw.get(), transform)) != NO_ERROR) {
    647         ALOGE("%s: Unable to configure surface transform, error %s (%d)", __FUNCTION__,
    648                 strerror(-err), err);
    649         return err;
    650     }
    651 
    652     return NO_ERROR;
    653 }
    654 
    655 static jint LegacyCameraDevice_nativeSetNextTimestamp(JNIEnv* env, jobject thiz, jobject surface,
    656         jlong timestamp) {
    657     ALOGV("nativeSetNextTimestamp");
    658     sp<ANativeWindow> anw;
    659     if ((anw = getNativeWindow(env, surface)) == NULL) {
    660         ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
    661         return BAD_VALUE;
    662     }
    663 
    664     status_t err = NO_ERROR;
    665 
    666     if ((err = native_window_set_buffers_timestamp(anw.get(), static_cast<int64_t>(timestamp))) !=
    667             NO_ERROR) {
    668         ALOGE("%s: Unable to set surface timestamp, error %s (%d)", __FUNCTION__, strerror(-err),
    669                 err);
    670         return err;
    671     }
    672     return NO_ERROR;
    673 }
    674 
    675 static jint LegacyCameraDevice_nativeGetJpegFooterSize(JNIEnv* env, jobject thiz) {
    676     ALOGV("nativeGetJpegFooterSize");
    677     return static_cast<jint>(sizeof(struct camera3_jpeg_blob));
    678 }
    679 
    680 } // extern "C"
    681 
    682 static JNINativeMethod gCameraDeviceMethods[] = {
    683     { "nativeDetectSurfaceType",
    684     "(Landroid/view/Surface;)I",
    685     (void *)LegacyCameraDevice_nativeDetectSurfaceType },
    686     { "nativeDetectSurfaceDimens",
    687     "(Landroid/view/Surface;[I)I",
    688     (void *)LegacyCameraDevice_nativeDetectSurfaceDimens },
    689     { "nativeConfigureSurface",
    690     "(Landroid/view/Surface;III)I",
    691     (void *)LegacyCameraDevice_nativeConfigureSurface },
    692     { "nativeProduceFrame",
    693     "(Landroid/view/Surface;[BIII)I",
    694     (void *)LegacyCameraDevice_nativeProduceFrame },
    695     { "nativeSetSurfaceFormat",
    696     "(Landroid/view/Surface;I)I",
    697     (void *)LegacyCameraDevice_nativeSetSurfaceFormat },
    698     { "nativeSetSurfaceDimens",
    699     "(Landroid/view/Surface;II)I",
    700     (void *)LegacyCameraDevice_nativeSetSurfaceDimens },
    701     { "nativeGetSurfaceId",
    702     "(Landroid/view/Surface;)J",
    703     (void *)LegacyCameraDevice_nativeGetSurfaceId },
    704     { "nativeDetectTextureDimens",
    705     "(Landroid/graphics/SurfaceTexture;[I)I",
    706     (void *)LegacyCameraDevice_nativeDetectTextureDimens },
    707     { "nativeSetSurfaceOrientation",
    708     "(Landroid/view/Surface;II)I",
    709     (void *)LegacyCameraDevice_nativeSetSurfaceOrientation },
    710     { "nativeSetNextTimestamp",
    711     "(Landroid/view/Surface;J)I",
    712     (void *)LegacyCameraDevice_nativeSetNextTimestamp },
    713     { "nativeGetJpegFooterSize",
    714     "()I",
    715     (void *)LegacyCameraDevice_nativeGetJpegFooterSize },
    716 };
    717 
    718 // Get all the required offsets in java class and register native functions
    719 int register_android_hardware_camera2_legacy_LegacyCameraDevice(JNIEnv* env)
    720 {
    721     // Register native functions
    722     return AndroidRuntime::registerNativeMethods(env,
    723             CAMERA_DEVICE_CLASS_NAME,
    724             gCameraDeviceMethods,
    725             NELEM(gCameraDeviceMethods));
    726 }
    727 
    728