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