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