1212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He/*
2212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He * Copyright 2013 The Android Open Source Project
3212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He *
4212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He * Licensed under the Apache License, Version 2.0 (the "License");
5212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He * you may not use this file except in compliance with the License.
6212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He * You may obtain a copy of the License at
7212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He *
8212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He *      http://www.apache.org/licenses/LICENSE-2.0
9212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He *
10212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He * Unless required by applicable law or agreed to in writing, software
11212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He * distributed under the License is distributed on an "AS IS" BASIS,
12212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He * See the License for the specific language governing permissions and
14212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He * limitations under the License.
15212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He */
16212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He
17212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He//#define LOG_NDEBUG 0
18212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He#define LOG_TAG "ImageReader_JNI"
190ab416269a866c8afa8f65d9351afa2407abee4cZhijun He#include "android_media_Utils.h"
20df7707cb4f34138b423dde493fccfa4e7fb50c20Mathias Agopian#include <cutils/atomic.h>
21212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He#include <utils/Log.h>
22212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He#include <utils/misc.h>
23212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He#include <utils/List.h>
24ef961215599b1c154130d4e64e46a401d6bfef67Jeff Brown#include <utils/String8.h>
25212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He
26212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He#include <cstdio>
27212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He
28ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He#include <gui/BufferItemConsumer.h>
29212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He#include <gui/Surface.h>
30534046d2b12fd13776ad782b982649cb0bea9b79Zhijun He#include <camera3.h>
31212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He
32212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He#include <android_runtime/AndroidRuntime.h>
33212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He#include <android_runtime/android_view_Surface.h>
34916d8ac650865cd05808d48bad68b69bebbc95abZhijun He#include <android_runtime/android_hardware_HardwareBuffer.h>
35916d8ac650865cd05808d48bad68b69bebbc95abZhijun He#include <grallocusage/GrallocUsageConversion.h>
36212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He
37212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He#include <jni.h>
38212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He#include <JNIHelp.h>
39212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He
405096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin#include <stdint.h>
415096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin#include <inttypes.h>
425096defdaa4716ce81047a855d6e5ce3f8263600Igor Murashkin
43212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He#define ANDROID_MEDIA_IMAGEREADER_CTX_JNI_ID       "mNativeContext"
44ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He#define ANDROID_MEDIA_SURFACEIMAGE_BUFFER_JNI_ID   "mNativeBuffer"
45212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He#define ANDROID_MEDIA_SURFACEIMAGE_TS_JNI_ID       "mTimestamp"
46212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He
47916d8ac650865cd05808d48bad68b69bebbc95abZhijun He#define CONSUMER_BUFFER_USAGE_UNKNOWN              0;
48212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He// ----------------------------------------------------------------------------
49212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He
50212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun Heusing namespace android;
51212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He
52212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He
53e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkinenum {
54e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin    ACQUIRE_SUCCESS = 0,
55e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin    ACQUIRE_NO_BUFFERS = 1,
56e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin    ACQUIRE_MAX_IMAGES = 2,
57e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin};
58e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin
59ef961215599b1c154130d4e64e46a401d6bfef67Jeff Brownstatic struct {
60ef961215599b1c154130d4e64e46a401d6bfef67Jeff Brown    jfieldID mNativeContext;
61ef961215599b1c154130d4e64e46a401d6bfef67Jeff Brown    jmethodID postEventFromNative;
62ef961215599b1c154130d4e64e46a401d6bfef67Jeff Brown} gImageReaderClassInfo;
63ef961215599b1c154130d4e64e46a401d6bfef67Jeff Brown
64ef961215599b1c154130d4e64e46a401d6bfef67Jeff Brownstatic struct {
65ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He    jfieldID mNativeBuffer;
66ef961215599b1c154130d4e64e46a401d6bfef67Jeff Brown    jfieldID mTimestamp;
670ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    jfieldID mPlanes;
68ef961215599b1c154130d4e64e46a401d6bfef67Jeff Brown} gSurfaceImageClassInfo;
69212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He
70ef961215599b1c154130d4e64e46a401d6bfef67Jeff Brownstatic struct {
71212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    jclass clazz;
72212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    jmethodID ctor;
73ef961215599b1c154130d4e64e46a401d6bfef67Jeff Brown} gSurfacePlaneClassInfo;
74212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He
75ef9db7d81b0ce1093944b9e3d5efb6ab756f5cbcEino-Ville Talvala// Get an ID that's unique within this process.
76ef9db7d81b0ce1093944b9e3d5efb6ab756f5cbcEino-Ville Talvalastatic int32_t createProcessUniqueId() {
77ef9db7d81b0ce1093944b9e3d5efb6ab756f5cbcEino-Ville Talvala    static volatile int32_t globalCounter = 0;
78ef9db7d81b0ce1093944b9e3d5efb6ab756f5cbcEino-Ville Talvala    return android_atomic_inc(&globalCounter);
79ef9db7d81b0ce1093944b9e3d5efb6ab756f5cbcEino-Ville Talvala}
80ef9db7d81b0ce1093944b9e3d5efb6ab756f5cbcEino-Ville Talvala
81212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He// ----------------------------------------------------------------------------
82212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He
83ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun Heclass JNIImageReaderContext : public ConsumerBase::FrameAvailableListener
84212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He{
85212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun Hepublic:
86212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    JNIImageReaderContext(JNIEnv* env, jobject weakThiz, jclass clazz, int maxImages);
87212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He
88212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    virtual ~JNIImageReaderContext();
89212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He
902c34b5e8136eac0332dac294cb06a6a98eac1c14Dan Stoza    virtual void onFrameAvailable(const BufferItem& item);
91212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He
920ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    BufferItem* getBufferItem();
930ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    void returnBufferItem(BufferItem* buffer);
94ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He
95212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He
960ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    void setBufferConsumer(const sp<BufferItemConsumer>& consumer) { mConsumer = consumer; }
970ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    BufferItemConsumer* getBufferConsumer() { return mConsumer.get(); }
98ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He
995b3c7c1e575a7fe1bc765e5d14690e1bfd971ffbDan Stoza    void setProducer(const sp<IGraphicBufferProducer>& producer) { mProducer = producer; }
1005b3c7c1e575a7fe1bc765e5d14690e1bfd971ffbDan Stoza    IGraphicBufferProducer* getProducer() { return mProducer.get(); }
101212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He
102212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    void setBufferFormat(int format) { mFormat = format; }
103212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    int getBufferFormat() { return mFormat; }
104212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He
105805f3c9428f9ebd5080aec48d3d9d77dbf4b41a9Eino-Ville Talvala    void setBufferDataspace(android_dataspace dataSpace) { mDataSpace = dataSpace; }
106805f3c9428f9ebd5080aec48d3d9d77dbf4b41a9Eino-Ville Talvala    android_dataspace getBufferDataspace() { return mDataSpace; }
107805f3c9428f9ebd5080aec48d3d9d77dbf4b41a9Eino-Ville Talvala
108212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    void setBufferWidth(int width) { mWidth = width; }
109212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    int getBufferWidth() { return mWidth; }
110212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He
111212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    void setBufferHeight(int height) { mHeight = height; }
112212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    int getBufferHeight() { return mHeight; }
113212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He
114212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun Heprivate:
115212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    static JNIEnv* getJNIEnv(bool* needsDetach);
116212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    static void detachJNI();
117212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He
1180ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    List<BufferItem*> mBuffers;
1190ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    sp<BufferItemConsumer> mConsumer;
1205b3c7c1e575a7fe1bc765e5d14690e1bfd971ffbDan Stoza    sp<IGraphicBufferProducer> mProducer;
121212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    jobject mWeakThiz;
122212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    jclass mClazz;
123212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    int mFormat;
124805f3c9428f9ebd5080aec48d3d9d77dbf4b41a9Eino-Ville Talvala    android_dataspace mDataSpace;
125212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    int mWidth;
126212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    int mHeight;
127212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He};
128212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He
129212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun HeJNIImageReaderContext::JNIImageReaderContext(JNIEnv* env,
130212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He        jobject weakThiz, jclass clazz, int maxImages) :
131212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    mWeakThiz(env->NewGlobalRef(weakThiz)),
1320ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    mClazz((jclass)env->NewGlobalRef(clazz)),
1330ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    mFormat(0),
1340ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    mDataSpace(HAL_DATASPACE_UNKNOWN),
1350ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    mWidth(-1),
1360ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    mHeight(-1) {
137212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    for (int i = 0; i < maxImages; i++) {
1380ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        BufferItem* buffer = new BufferItem;
139212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He        mBuffers.push_back(buffer);
140212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    }
141212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He}
142212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He
143212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun HeJNIEnv* JNIImageReaderContext::getJNIEnv(bool* needsDetach) {
144212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    LOG_ALWAYS_FATAL_IF(needsDetach == NULL, "needsDetach is null!!!");
145212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    *needsDetach = false;
146212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    JNIEnv* env = AndroidRuntime::getJNIEnv();
147212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    if (env == NULL) {
148212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He        JavaVMAttachArgs args = {JNI_VERSION_1_4, NULL, NULL};
149212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He        JavaVM* vm = AndroidRuntime::getJavaVM();
150212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He        int result = vm->AttachCurrentThread(&env, (void*) &args);
151212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He        if (result != JNI_OK) {
152212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He            ALOGE("thread attach failed: %#x", result);
153212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He            return NULL;
154212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He        }
155212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He        *needsDetach = true;
156212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    }
157212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    return env;
158212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He}
159212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He
160212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun Hevoid JNIImageReaderContext::detachJNI() {
161212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    JavaVM* vm = AndroidRuntime::getJavaVM();
162212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    int result = vm->DetachCurrentThread();
163212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    if (result != JNI_OK) {
164212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He        ALOGE("thread detach failed: %#x", result);
165212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    }
166212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He}
167212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He
1680ab416269a866c8afa8f65d9351afa2407abee4cZhijun HeBufferItem* JNIImageReaderContext::getBufferItem() {
169212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    if (mBuffers.empty()) {
170212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He        return NULL;
171212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    }
1720ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    // Return a BufferItem pointer and remove it from the list
1730ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    List<BufferItem*>::iterator it = mBuffers.begin();
1740ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    BufferItem* buffer = *it;
175212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    mBuffers.erase(it);
176212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    return buffer;
177212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He}
178212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He
1790ab416269a866c8afa8f65d9351afa2407abee4cZhijun Hevoid JNIImageReaderContext::returnBufferItem(BufferItem* buffer) {
1805dacbef0448c20718725376d6d3d30d6a1983d3fEino-Ville Talvala    buffer->mGraphicBuffer = nullptr;
181212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    mBuffers.push_back(buffer);
182212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He}
183212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He
184212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun HeJNIImageReaderContext::~JNIImageReaderContext() {
185212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    bool needsDetach = false;
186212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    JNIEnv* env = getJNIEnv(&needsDetach);
187212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    if (env != NULL) {
188212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He        env->DeleteGlobalRef(mWeakThiz);
189212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He        env->DeleteGlobalRef(mClazz);
190212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    } else {
191212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He        ALOGW("leaking JNI object references");
192212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    }
193212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    if (needsDetach) {
194212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He        detachJNI();
195212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    }
196212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He
1970ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    // Delete buffer items.
1980ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    for (List<BufferItem *>::iterator it = mBuffers.begin();
199212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He            it != mBuffers.end(); it++) {
200212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He        delete *it;
201212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    }
202ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He
203ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He    if (mConsumer != 0) {
204ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He        mConsumer.clear();
205ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He    }
206212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He}
207212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He
2082c34b5e8136eac0332dac294cb06a6a98eac1c14Dan Stozavoid JNIImageReaderContext::onFrameAvailable(const BufferItem& /*item*/)
209212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He{
210212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    ALOGV("%s: frame available", __FUNCTION__);
211212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    bool needsDetach = false;
212212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    JNIEnv* env = getJNIEnv(&needsDetach);
213212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    if (env != NULL) {
214ef961215599b1c154130d4e64e46a401d6bfef67Jeff Brown        env->CallStaticVoidMethod(mClazz, gImageReaderClassInfo.postEventFromNative, mWeakThiz);
215212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    } else {
216212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He        ALOGW("onFrameAvailable event will not posted");
217212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    }
218212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    if (needsDetach) {
219212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He        detachJNI();
220212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    }
221212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He}
222212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He
223212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He// ----------------------------------------------------------------------------
224212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He
225212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun Heextern "C" {
226212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He
227212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun Hestatic JNIImageReaderContext* ImageReader_getContext(JNIEnv* env, jobject thiz)
228212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He{
229212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    JNIImageReaderContext *ctx;
230212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    ctx = reinterpret_cast<JNIImageReaderContext *>
231ef961215599b1c154130d4e64e46a401d6bfef67Jeff Brown              (env->GetLongField(thiz, gImageReaderClassInfo.mNativeContext));
232212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    return ctx;
233212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He}
234212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He
2355b3c7c1e575a7fe1bc765e5d14690e1bfd971ffbDan Stozastatic IGraphicBufferProducer* ImageReader_getProducer(JNIEnv* env, jobject thiz)
23652a9a10b6b8c7b7a9f97777541841b94d4fd9754Mathias Agopian{
23752a9a10b6b8c7b7a9f97777541841b94d4fd9754Mathias Agopian    ALOGV("%s:", __FUNCTION__);
23852a9a10b6b8c7b7a9f97777541841b94d4fd9754Mathias Agopian    JNIImageReaderContext* const ctx = ImageReader_getContext(env, thiz);
23952a9a10b6b8c7b7a9f97777541841b94d4fd9754Mathias Agopian    if (ctx == NULL) {
24052a9a10b6b8c7b7a9f97777541841b94d4fd9754Mathias Agopian        jniThrowRuntimeException(env, "ImageReaderContext is not initialized");
24152a9a10b6b8c7b7a9f97777541841b94d4fd9754Mathias Agopian        return NULL;
24252a9a10b6b8c7b7a9f97777541841b94d4fd9754Mathias Agopian    }
243ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He
2445b3c7c1e575a7fe1bc765e5d14690e1bfd971ffbDan Stoza    return ctx->getProducer();
24552a9a10b6b8c7b7a9f97777541841b94d4fd9754Mathias Agopian}
24652a9a10b6b8c7b7a9f97777541841b94d4fd9754Mathias Agopian
247212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun Hestatic void ImageReader_setNativeContext(JNIEnv* env,
248212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He        jobject thiz, sp<JNIImageReaderContext> ctx)
249212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He{
250212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    ALOGV("%s:", __FUNCTION__);
251212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    JNIImageReaderContext* const p = ImageReader_getContext(env, thiz);
252212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    if (ctx != 0) {
253212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He        ctx->incStrong((void*)ImageReader_setNativeContext);
254212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    }
255212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    if (p) {
256212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He        p->decStrong((void*)ImageReader_setNativeContext);
257212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    }
258ef961215599b1c154130d4e64e46a401d6bfef67Jeff Brown    env->SetLongField(thiz, gImageReaderClassInfo.mNativeContext,
259ef961215599b1c154130d4e64e46a401d6bfef67Jeff Brown            reinterpret_cast<jlong>(ctx.get()));
260212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He}
261212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He
2620ab416269a866c8afa8f65d9351afa2407abee4cZhijun Hestatic BufferItemConsumer* ImageReader_getBufferConsumer(JNIEnv* env, jobject thiz)
263ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He{
264ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He    ALOGV("%s:", __FUNCTION__);
265ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He    JNIImageReaderContext* const ctx = ImageReader_getContext(env, thiz);
266ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He    if (ctx == NULL) {
267ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He        jniThrowRuntimeException(env, "ImageReaderContext is not initialized");
268ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He        return NULL;
269ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He    }
270ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He
2710ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    return ctx->getBufferConsumer();
2720ab416269a866c8afa8f65d9351afa2407abee4cZhijun He}
273ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He
2740ab416269a866c8afa8f65d9351afa2407abee4cZhijun Hestatic void Image_setBufferItem(JNIEnv* env, jobject thiz,
2750ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        const BufferItem* buffer)
2760ab416269a866c8afa8f65d9351afa2407abee4cZhijun He{
2770ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    env->SetLongField(thiz, gSurfaceImageClassInfo.mNativeBuffer, reinterpret_cast<jlong>(buffer));
278ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He}
279ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He
2800ab416269a866c8afa8f65d9351afa2407abee4cZhijun Hestatic BufferItem* Image_getBufferItem(JNIEnv* env, jobject image)
281ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He{
282ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He    return reinterpret_cast<BufferItem*>(
283ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He            env->GetLongField(image, gSurfaceImageClassInfo.mNativeBuffer));
284ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He}
285ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He
286ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He
287212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He// ----------------------------------------------------------------------------
288212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He
289212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun Hestatic void ImageReader_classInit(JNIEnv* env, jclass clazz)
290212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He{
291212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    ALOGV("%s:", __FUNCTION__);
292212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He
293212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    jclass imageClazz = env->FindClass("android/media/ImageReader$SurfaceImage");
294212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    LOG_ALWAYS_FATAL_IF(imageClazz == NULL,
295212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He                        "can't find android/graphics/ImageReader$SurfaceImage");
296ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He    gSurfaceImageClassInfo.mNativeBuffer = env->GetFieldID(
297ef961215599b1c154130d4e64e46a401d6bfef67Jeff Brown            imageClazz, ANDROID_MEDIA_SURFACEIMAGE_BUFFER_JNI_ID, "J");
298ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He    LOG_ALWAYS_FATAL_IF(gSurfaceImageClassInfo.mNativeBuffer == NULL,
299212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He                        "can't find android/graphics/ImageReader.%s",
300212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He                        ANDROID_MEDIA_SURFACEIMAGE_BUFFER_JNI_ID);
301212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He
302ef961215599b1c154130d4e64e46a401d6bfef67Jeff Brown    gSurfaceImageClassInfo.mTimestamp = env->GetFieldID(
303ef961215599b1c154130d4e64e46a401d6bfef67Jeff Brown            imageClazz, ANDROID_MEDIA_SURFACEIMAGE_TS_JNI_ID, "J");
304ef961215599b1c154130d4e64e46a401d6bfef67Jeff Brown    LOG_ALWAYS_FATAL_IF(gSurfaceImageClassInfo.mTimestamp == NULL,
305212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He                        "can't find android/graphics/ImageReader.%s",
306212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He                        ANDROID_MEDIA_SURFACEIMAGE_TS_JNI_ID);
307212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He
3080ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    gSurfaceImageClassInfo.mPlanes = env->GetFieldID(
3090ab416269a866c8afa8f65d9351afa2407abee4cZhijun He            imageClazz, "mPlanes", "[Landroid/media/ImageReader$SurfaceImage$SurfacePlane;");
3100ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    LOG_ALWAYS_FATAL_IF(gSurfaceImageClassInfo.mPlanes == NULL,
3110ab416269a866c8afa8f65d9351afa2407abee4cZhijun He            "can't find android/media/ImageReader$ReaderSurfaceImage.mPlanes");
3120ab416269a866c8afa8f65d9351afa2407abee4cZhijun He
313ef961215599b1c154130d4e64e46a401d6bfef67Jeff Brown    gImageReaderClassInfo.mNativeContext = env->GetFieldID(
314ef961215599b1c154130d4e64e46a401d6bfef67Jeff Brown            clazz, ANDROID_MEDIA_IMAGEREADER_CTX_JNI_ID, "J");
315ef961215599b1c154130d4e64e46a401d6bfef67Jeff Brown    LOG_ALWAYS_FATAL_IF(gImageReaderClassInfo.mNativeContext == NULL,
316212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He                        "can't find android/graphics/ImageReader.%s",
317212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He                          ANDROID_MEDIA_IMAGEREADER_CTX_JNI_ID);
318212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He
319ef961215599b1c154130d4e64e46a401d6bfef67Jeff Brown    gImageReaderClassInfo.postEventFromNative = env->GetStaticMethodID(
320ef961215599b1c154130d4e64e46a401d6bfef67Jeff Brown            clazz, "postEventFromNative", "(Ljava/lang/Object;)V");
321ef961215599b1c154130d4e64e46a401d6bfef67Jeff Brown    LOG_ALWAYS_FATAL_IF(gImageReaderClassInfo.postEventFromNative == NULL,
322212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He                        "can't find android/graphics/ImageReader.postEventFromNative");
323212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He
324212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    jclass planeClazz = env->FindClass("android/media/ImageReader$SurfaceImage$SurfacePlane");
325212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    LOG_ALWAYS_FATAL_IF(planeClazz == NULL, "Can not find SurfacePlane class");
326212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    // FindClass only gives a local reference of jclass object.
327ef961215599b1c154130d4e64e46a401d6bfef67Jeff Brown    gSurfacePlaneClassInfo.clazz = (jclass) env->NewGlobalRef(planeClazz);
328ef961215599b1c154130d4e64e46a401d6bfef67Jeff Brown    gSurfacePlaneClassInfo.ctor = env->GetMethodID(gSurfacePlaneClassInfo.clazz, "<init>",
3290ab416269a866c8afa8f65d9351afa2407abee4cZhijun He            "(Landroid/media/ImageReader$SurfaceImage;IILjava/nio/ByteBuffer;)V");
330ef961215599b1c154130d4e64e46a401d6bfef67Jeff Brown    LOG_ALWAYS_FATAL_IF(gSurfacePlaneClassInfo.ctor == NULL,
331ef961215599b1c154130d4e64e46a401d6bfef67Jeff Brown            "Can not find SurfacePlane constructor");
332212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He}
333212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He
334916d8ac650865cd05808d48bad68b69bebbc95abZhijun Hestatic void ImageReader_init(JNIEnv* env, jobject thiz, jobject weakThiz, jint width, jint height,
335916d8ac650865cd05808d48bad68b69bebbc95abZhijun He                             jint format, jint maxImages, jlong ndkUsage)
336212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He{
337212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    status_t res;
338212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    int nativeFormat;
339805f3c9428f9ebd5080aec48d3d9d77dbf4b41a9Eino-Ville Talvala    android_dataspace nativeDataspace;
340212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He
341212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    ALOGV("%s: width:%d, height: %d, format: 0x%x, maxImages:%d",
342212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He          __FUNCTION__, width, height, format, maxImages);
343212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He
344805f3c9428f9ebd5080aec48d3d9d77dbf4b41a9Eino-Ville Talvala    PublicFormat publicFormat = static_cast<PublicFormat>(format);
345805f3c9428f9ebd5080aec48d3d9d77dbf4b41a9Eino-Ville Talvala    nativeFormat = android_view_Surface_mapPublicFormatToHalFormat(
346805f3c9428f9ebd5080aec48d3d9d77dbf4b41a9Eino-Ville Talvala        publicFormat);
347805f3c9428f9ebd5080aec48d3d9d77dbf4b41a9Eino-Ville Talvala    nativeDataspace = android_view_Surface_mapPublicFormatToHalDataspace(
348805f3c9428f9ebd5080aec48d3d9d77dbf4b41a9Eino-Ville Talvala        publicFormat);
349212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He
350212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    jclass clazz = env->GetObjectClass(thiz);
351212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    if (clazz == NULL) {
352212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He        jniThrowRuntimeException(env, "Can't find android/graphics/ImageReader");
353212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He        return;
354212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    }
355212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    sp<JNIImageReaderContext> ctx(new JNIImageReaderContext(env, weakThiz, clazz, maxImages));
356ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He
357ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He    sp<IGraphicBufferProducer> gbProducer;
358ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He    sp<IGraphicBufferConsumer> gbConsumer;
359ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He    BufferQueue::createBufferQueue(&gbProducer, &gbConsumer);
3600ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    sp<BufferItemConsumer> bufferConsumer;
361ef9db7d81b0ce1093944b9e3d5efb6ab756f5cbcEino-Ville Talvala    String8 consumerName = String8::format("ImageReader-%dx%df%xm%d-%d-%d",
362ef9db7d81b0ce1093944b9e3d5efb6ab756f5cbcEino-Ville Talvala            width, height, format, maxImages, getpid(),
363ef9db7d81b0ce1093944b9e3d5efb6ab756f5cbcEino-Ville Talvala            createProcessUniqueId());
3640ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    uint32_t consumerUsage = GRALLOC_USAGE_SW_READ_OFTEN;
365916d8ac650865cd05808d48bad68b69bebbc95abZhijun He    bool needUsageOverride = ndkUsage != CONSUMER_BUFFER_USAGE_UNKNOWN;
366916d8ac650865cd05808d48bad68b69bebbc95abZhijun He    uint64_t outProducerUsage = 0;
367916d8ac650865cd05808d48bad68b69bebbc95abZhijun He    uint64_t outConsumerUsage = 0;
368916d8ac650865cd05808d48bad68b69bebbc95abZhijun He    android_hardware_HardwareBuffer_convertToGrallocUsageBits(&outProducerUsage, &outConsumerUsage,
369916d8ac650865cd05808d48bad68b69bebbc95abZhijun He            ndkUsage, 0);
3700ab416269a866c8afa8f65d9351afa2407abee4cZhijun He
371ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He    if (isFormatOpaque(nativeFormat)) {
372ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He        // Use the SW_READ_NEVER usage to tell producer that this format is not for preview or video
373ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He        // encoding. The only possibility will be ZSL output.
3740ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        consumerUsage = GRALLOC_USAGE_SW_READ_NEVER;
375916d8ac650865cd05808d48bad68b69bebbc95abZhijun He        if (needUsageOverride) {
376916d8ac650865cd05808d48bad68b69bebbc95abZhijun He            consumerUsage = android_convertGralloc1To0Usage(0, outConsumerUsage);
377916d8ac650865cd05808d48bad68b69bebbc95abZhijun He        }
378916d8ac650865cd05808d48bad68b69bebbc95abZhijun He    } else if (needUsageOverride) {
379916d8ac650865cd05808d48bad68b69bebbc95abZhijun He        ALOGW("Consumer usage override for non-opaque format is not implemented yet, "
380916d8ac650865cd05808d48bad68b69bebbc95abZhijun He                "ignore the provided usage from the application");
381ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He    }
3820ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    bufferConsumer = new BufferItemConsumer(gbConsumer, consumerUsage, maxImages,
3830ab416269a866c8afa8f65d9351afa2407abee4cZhijun He            /*controlledByApp*/true);
3840ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    if (bufferConsumer == nullptr) {
3850ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        jniThrowExceptionFmt(env, "java/lang/RuntimeException",
386916d8ac650865cd05808d48bad68b69bebbc95abZhijun He                "Failed to allocate native buffer consumer for format 0x%x and usage 0x%x",
387916d8ac650865cd05808d48bad68b69bebbc95abZhijun He                nativeFormat, consumerUsage);
3880ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        return;
3890ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    }
3900ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    ctx->setBufferConsumer(bufferConsumer);
3910ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    bufferConsumer->setName(consumerName);
392ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He
3935b3c7c1e575a7fe1bc765e5d14690e1bfd971ffbDan Stoza    ctx->setProducer(gbProducer);
3940ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    bufferConsumer->setFrameAvailableListener(ctx);
395212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    ImageReader_setNativeContext(env, thiz, ctx);
396212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    ctx->setBufferFormat(nativeFormat);
397805f3c9428f9ebd5080aec48d3d9d77dbf4b41a9Eino-Ville Talvala    ctx->setBufferDataspace(nativeDataspace);
398212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    ctx->setBufferWidth(width);
399212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    ctx->setBufferHeight(height);
400212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He
4010ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    // Set the width/height/format/dataspace to the bufferConsumer.
4020ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    res = bufferConsumer->setDefaultBufferSize(width, height);
4030ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    if (res != OK) {
4040ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
4050ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                          "Failed to set buffer consumer default size (%dx%d) for format 0x%x",
4060ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                          width, height, nativeFormat);
4070ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        return;
4080ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    }
4090ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    res = bufferConsumer->setDefaultBufferFormat(nativeFormat);
4100ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    if (res != OK) {
4110ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
4120ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                          "Failed to set buffer consumer default format 0x%x", nativeFormat);
4130ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    }
4140ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    res = bufferConsumer->setDefaultBufferDataSpace(nativeDataspace);
4150ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    if (res != OK) {
4160ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
4170ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                          "Failed to set buffer consumer default dataSpace 0x%x", nativeDataspace);
418805f3c9428f9ebd5080aec48d3d9d77dbf4b41a9Eino-Ville Talvala    }
419212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He}
420212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He
421212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun Hestatic void ImageReader_close(JNIEnv* env, jobject thiz)
422212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He{
423212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    ALOGV("%s:", __FUNCTION__);
424212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He
425212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    JNIImageReaderContext* const ctx = ImageReader_getContext(env, thiz);
426212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    if (ctx == NULL) {
427212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He        // ImageReader is already closed.
428212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He        return;
429212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    }
430212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He
4310ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    BufferItemConsumer* consumer = NULL;
4320ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    consumer = ImageReader_getBufferConsumer(env, thiz);
433ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He
434212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    if (consumer != NULL) {
435212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He        consumer->abandon();
436212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He        consumer->setFrameAvailableListener(NULL);
437212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    }
438212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    ImageReader_setNativeContext(env, thiz, NULL);
439212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He}
440212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He
4410ab416269a866c8afa8f65d9351afa2407abee4cZhijun Hestatic sp<Fence> Image_unlockIfLocked(JNIEnv* env, jobject image) {
4420ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    ALOGV("%s", __FUNCTION__);
4430ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    BufferItem* buffer = Image_getBufferItem(env, image);
4440ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    if (buffer == NULL) {
4450ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        jniThrowException(env, "java/lang/IllegalStateException",
4460ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                "Image is not initialized");
4470ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        return Fence::NO_FENCE;
4480ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    }
4490ab416269a866c8afa8f65d9351afa2407abee4cZhijun He
4500ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    // Is locked?
4510ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    bool wasBufferLocked = false;
4520ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    jobject planes = NULL;
4530ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    if (!isFormatOpaque(buffer->mGraphicBuffer->getPixelFormat())) {
4540ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        planes = env->GetObjectField(image, gSurfaceImageClassInfo.mPlanes);
4550ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    }
4560ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    wasBufferLocked = (planes != NULL);
4570ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    if (wasBufferLocked) {
4580ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        status_t res = OK;
4590ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        int fenceFd = -1;
4600ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        if (wasBufferLocked) {
4610ab416269a866c8afa8f65d9351afa2407abee4cZhijun He            res = buffer->mGraphicBuffer->unlockAsync(&fenceFd);
4620ab416269a866c8afa8f65d9351afa2407abee4cZhijun He            if (res != OK) {
4630ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                jniThrowRuntimeException(env, "unlock buffer failed");
4640ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                return Fence::NO_FENCE;
4650ab416269a866c8afa8f65d9351afa2407abee4cZhijun He            }
4660ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        }
4670ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        sp<Fence> releaseFence = new Fence(fenceFd);
4680ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        return releaseFence;
4690ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        ALOGV("Successfully unlocked the image");
4700ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    }
4710ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    return Fence::NO_FENCE;
4720ab416269a866c8afa8f65d9351afa2407abee4cZhijun He}
4730ab416269a866c8afa8f65d9351afa2407abee4cZhijun He
474212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun Hestatic void ImageReader_imageRelease(JNIEnv* env, jobject thiz, jobject image)
475212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He{
476212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    ALOGV("%s:", __FUNCTION__);
477212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    JNIImageReaderContext* ctx = ImageReader_getContext(env, thiz);
478212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    if (ctx == NULL) {
479212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He        ALOGW("ImageReader#close called before Image#close, consider calling Image#close first");
480212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He        return;
481212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    }
482212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He
4830ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    BufferItemConsumer* bufferConsumer = ctx->getBufferConsumer();
4840ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    BufferItem* buffer = Image_getBufferItem(env, image);
4850ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    if (buffer == nullptr) {
4860ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        // Release an already closed image is harmless.
4870ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        return;
488212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    }
4890ab416269a866c8afa8f65d9351afa2407abee4cZhijun He
4900ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    sp<Fence> releaseFence = Image_unlockIfLocked(env, image);
4910ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    bufferConsumer->releaseBuffer(*buffer, releaseFence);
4920ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    Image_setBufferItem(env, image, NULL);
4930ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    ctx->returnBufferItem(buffer);
4940ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    ALOGV("%s: Image (format: 0x%x) has been released", __FUNCTION__, ctx->getBufferFormat());
495212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He}
496212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He
4970ab416269a866c8afa8f65d9351afa2407abee4cZhijun Hestatic jint ImageReader_imageSetup(JNIEnv* env, jobject thiz, jobject image) {
498212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    ALOGV("%s:", __FUNCTION__);
4990ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    JNIImageReaderContext* ctx = ImageReader_getContext(env, thiz);
5000ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    if (ctx == NULL) {
5010ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        jniThrowException(env, "java/lang/IllegalStateException",
5020ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                "ImageReader is not initialized or was already closed");
503e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin        return -1;
504212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    }
505212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He
5060ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    BufferItemConsumer* bufferConsumer = ctx->getBufferConsumer();
5070ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    BufferItem* buffer = ctx->getBufferItem();
508ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He    if (buffer == NULL) {
509ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He        ALOGW("Unable to acquire a buffer item, very likely client tried to acquire more than"
510ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He            " maxImages buffers");
511ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He        return ACQUIRE_MAX_IMAGES;
512ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He    }
513ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He
5140ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    status_t res = bufferConsumer->acquireBuffer(buffer, 0);
515ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He    if (res != OK) {
5160ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        ctx->returnBufferItem(buffer);
5170ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        if (res != BufferQueue::NO_BUFFER_AVAILABLE) {
5180ab416269a866c8afa8f65d9351afa2407abee4cZhijun He            if (res == INVALID_OPERATION) {
5190ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                // Max number of images were already acquired.
5200ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                ALOGE("%s: Max number of buffers allowed are already acquired : %s (%d)",
5210ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                        __FUNCTION__, strerror(-res), res);
522e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin                return ACQUIRE_MAX_IMAGES;
523dd0643202de80cc4ced37d1844e722c8a5e89154Igor Murashkin            } else {
5240ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                ALOGE("%s: Acquire image failed with some unknown error: %s (%d)",
5250ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                        __FUNCTION__, strerror(-res), res);
5260ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
5270ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                        "Unknown error (%d) when we tried to acquire an image.",
5280ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                                          res);
5290ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                return ACQUIRE_NO_BUFFERS;
530dd0643202de80cc4ced37d1844e722c8a5e89154Igor Murashkin            }
531f724c277d3362dbc8099fcbf8674609a424cd2eeJeff Brown        }
5320ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        // This isn't really an error case, as the application may acquire buffer at any time.
533e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin        return ACQUIRE_NO_BUFFERS;
534212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    }
535212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He
5360ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    // Add some extra checks for non-opaque formats.
5370ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    if (!isFormatOpaque(ctx->getBufferFormat())) {
5380ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        // Check if the left-top corner of the crop rect is origin, we currently assume this point is
5390ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        // zero, will revisit this once this assumption turns out problematic.
5400ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        Point lt = buffer->mCrop.leftTop();
5410ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        if (lt.x != 0 || lt.y != 0) {
5420ab416269a866c8afa8f65d9351afa2407abee4cZhijun He            jniThrowExceptionFmt(env, "java/lang/UnsupportedOperationException",
5430ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                    "crop left top corner [%d, %d] need to be at origin", lt.x, lt.y);
5440ab416269a866c8afa8f65d9351afa2407abee4cZhijun He            return -1;
5450ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        }
5464eda9f5359347c11914e47f477535c9533674d32Zhijun He
5470ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        // Check if the producer buffer configurations match what ImageReader configured.
5480ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        int outputWidth = getBufferWidth(buffer);
5490ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        int outputHeight = getBufferHeight(buffer);
5500ab416269a866c8afa8f65d9351afa2407abee4cZhijun He
5510ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        int imgReaderFmt = ctx->getBufferFormat();
5520ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        int imageReaderWidth = ctx->getBufferWidth();
5530ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        int imageReaderHeight = ctx->getBufferHeight();
5540ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        int bufferFormat = buffer->mGraphicBuffer->getPixelFormat();
5550ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        if ((bufferFormat != HAL_PIXEL_FORMAT_BLOB) && (imgReaderFmt != HAL_PIXEL_FORMAT_BLOB) &&
5560ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                (imageReaderWidth != outputWidth || imageReaderHeight != outputHeight)) {
5570ab416269a866c8afa8f65d9351afa2407abee4cZhijun He            ALOGV("%s: Producer buffer size: %dx%d, doesn't match ImageReader configured size: %dx%d",
5580ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                    __FUNCTION__, outputWidth, outputHeight, imageReaderWidth, imageReaderHeight);
5590ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        }
5600ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        if (imgReaderFmt != bufferFormat) {
5610ab416269a866c8afa8f65d9351afa2407abee4cZhijun He            if (imgReaderFmt == HAL_PIXEL_FORMAT_YCbCr_420_888 &&
5620ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                    isPossiblyYUV(bufferFormat)) {
5630ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                // Treat formats that are compatible with flexible YUV
5640ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                // (HAL_PIXEL_FORMAT_YCbCr_420_888) as HAL_PIXEL_FORMAT_YCbCr_420_888.
5650ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                ALOGV("%s: Treat buffer format to 0x%x as HAL_PIXEL_FORMAT_YCbCr_420_888",
5660ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                        __FUNCTION__, bufferFormat);
5670ab416269a866c8afa8f65d9351afa2407abee4cZhijun He            } else if (imgReaderFmt == HAL_PIXEL_FORMAT_BLOB &&
5680ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                    bufferFormat == HAL_PIXEL_FORMAT_RGBA_8888) {
5690ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                // Using HAL_PIXEL_FORMAT_RGBA_8888 Gralloc buffers containing JPEGs to get around
5700ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                // SW write limitations for (b/17379185).
5710ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                ALOGV("%s: Receiving JPEG in HAL_PIXEL_FORMAT_RGBA_8888 buffer.", __FUNCTION__);
5720ab416269a866c8afa8f65d9351afa2407abee4cZhijun He            } else {
5730ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                // Return the buffer to the queue. No need to provide fence, as this buffer wasn't
5740ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                // used anywhere yet.
5750ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                bufferConsumer->releaseBuffer(*buffer);
5760ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                ctx->returnBufferItem(buffer);
5770ab416269a866c8afa8f65d9351afa2407abee4cZhijun He
5780ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                // Throw exception
5790ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                ALOGE("Producer output buffer format: 0x%x, ImageReader configured format: 0x%x",
5800ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                        bufferFormat, ctx->getBufferFormat());
5810ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                String8 msg;
5820ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                msg.appendFormat("The producer output buffer format 0x%x doesn't "
5830ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                        "match the ImageReader's configured buffer format 0x%x.",
5840ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                        bufferFormat, ctx->getBufferFormat());
5850ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                jniThrowException(env, "java/lang/UnsupportedOperationException",
5860ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                        msg.string());
5870ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                return -1;
5880ab416269a866c8afa8f65d9351afa2407abee4cZhijun He            }
5890ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        }
590212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He
591212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    }
592212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He
593212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    // Set SurfaceImage instance member variables
5940ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    Image_setBufferItem(env, image, buffer);
595ef961215599b1c154130d4e64e46a401d6bfef67Jeff Brown    env->SetLongField(image, gSurfaceImageClassInfo.mTimestamp,
5960ab416269a866c8afa8f65d9351afa2407abee4cZhijun He            static_cast<jlong>(buffer->mTimestamp));
597212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He
598e3351f1942bfe86682389b278e7ff128a72ea671Igor Murashkin    return ACQUIRE_SUCCESS;
599212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He}
600212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He
601ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun Hestatic jint ImageReader_detachImage(JNIEnv* env, jobject thiz, jobject image) {
602f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He    ALOGV("%s:", __FUNCTION__);
603f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He    JNIImageReaderContext* ctx = ImageReader_getContext(env, thiz);
604f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He    if (ctx == NULL) {
605f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He        jniThrowException(env, "java/lang/IllegalStateException", "ImageReader was already closed");
606ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He        return -1;
607f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He    }
608f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He
6090ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    BufferItemConsumer* bufferConsumer = ctx->getBufferConsumer();
6100ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    BufferItem* buffer = Image_getBufferItem(env, image);
6110ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    if (!buffer) {
612ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He        ALOGE(
6130ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                "Image already released and can not be detached from ImageReader!!!");
614ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He        jniThrowException(env, "java/lang/IllegalStateException",
6150ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                "Image detach from ImageReader failed: buffer was already released");
616ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He        return -1;
617ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He    }
618ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He
6190ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    status_t res = OK;
6200ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    Image_unlockIfLocked(env, image);
6210ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    res = bufferConsumer->detachBuffer(buffer->mSlot);
622ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He    if (res != OK) {
6230ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        ALOGE("Image detach failed: %s (%d)!!!", strerror(-res), res);
624ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He        jniThrowRuntimeException(env,
6250ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                "nativeDetachImage failed for image!!!");
626ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He        return res;
627ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He    }
628ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He    return OK;
629f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He}
630f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He
6312e2aaf6e0497302bc03c218949d29b01f469316eEino-Ville Talvalastatic void ImageReader_discardFreeBuffers(JNIEnv* env, jobject thiz) {
6322e2aaf6e0497302bc03c218949d29b01f469316eEino-Ville Talvala    ALOGV("%s:", __FUNCTION__);
6332e2aaf6e0497302bc03c218949d29b01f469316eEino-Ville Talvala    JNIImageReaderContext* ctx = ImageReader_getContext(env, thiz);
6342e2aaf6e0497302bc03c218949d29b01f469316eEino-Ville Talvala    if (ctx == NULL) {
6352e2aaf6e0497302bc03c218949d29b01f469316eEino-Ville Talvala        jniThrowException(env, "java/lang/IllegalStateException", "ImageReader was already closed");
6362e2aaf6e0497302bc03c218949d29b01f469316eEino-Ville Talvala        return;
6372e2aaf6e0497302bc03c218949d29b01f469316eEino-Ville Talvala    }
6382e2aaf6e0497302bc03c218949d29b01f469316eEino-Ville Talvala
6392e2aaf6e0497302bc03c218949d29b01f469316eEino-Ville Talvala    BufferItemConsumer* bufferConsumer = ctx->getBufferConsumer();
6402e2aaf6e0497302bc03c218949d29b01f469316eEino-Ville Talvala    status_t res = bufferConsumer->discardFreeBuffers();
6412e2aaf6e0497302bc03c218949d29b01f469316eEino-Ville Talvala    if (res != OK) {
6422e2aaf6e0497302bc03c218949d29b01f469316eEino-Ville Talvala        ALOGE("Buffer discard failed: %s (%d)", strerror(-res), res);
6432e2aaf6e0497302bc03c218949d29b01f469316eEino-Ville Talvala        jniThrowRuntimeException(env,
6442e2aaf6e0497302bc03c218949d29b01f469316eEino-Ville Talvala                "nativeDicardFreebuffers failed");
6452e2aaf6e0497302bc03c218949d29b01f469316eEino-Ville Talvala    }
6462e2aaf6e0497302bc03c218949d29b01f469316eEino-Ville Talvala}
6472e2aaf6e0497302bc03c218949d29b01f469316eEino-Ville Talvala
648212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun Hestatic jobject ImageReader_getSurface(JNIEnv* env, jobject thiz)
649212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He{
650212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    ALOGV("%s: ", __FUNCTION__);
651212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He
6525b3c7c1e575a7fe1bc765e5d14690e1bfd971ffbDan Stoza    IGraphicBufferProducer* gbp = ImageReader_getProducer(env, thiz);
6535b3c7c1e575a7fe1bc765e5d14690e1bfd971ffbDan Stoza    if (gbp == NULL) {
6540ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        jniThrowRuntimeException(env, "Buffer consumer is uninitialized");
655212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He        return NULL;
656212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    }
657212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He
658212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    // Wrap the IGBP in a Java-language Surface.
6595b3c7c1e575a7fe1bc765e5d14690e1bfd971ffbDan Stoza    return android_view_Surface_createFromIGraphicBufferProducer(env, gbp);
660212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He}
661212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He
6620ab416269a866c8afa8f65d9351afa2407abee4cZhijun Hestatic void Image_getLockedImage(JNIEnv* env, jobject thiz, LockedImage *image) {
6630ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    ALOGV("%s", __FUNCTION__);
6640ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    BufferItem* buffer = Image_getBufferItem(env, thiz);
6650ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    if (buffer == NULL) {
666ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He        jniThrowException(env, "java/lang/IllegalStateException",
6670ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                "Image is not initialized");
6680ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        return;
669ce9d6f9c75e2254f3704996e232e57e0c8f686d8Zhijun He    }
670212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He
6710ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    status_t res = lockImageFromBuffer(buffer,
6720ab416269a866c8afa8f65d9351afa2407abee4cZhijun He            GRALLOC_USAGE_SW_READ_OFTEN, buffer->mFence->dup(), image);
6730ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    if (res != OK) {
6740ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        jniThrowExceptionFmt(env, "java/lang/RuntimeException",
6750ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                "lock buffer failed for format 0x%x",
6760ab416269a866c8afa8f65d9351afa2407abee4cZhijun He                buffer->mGraphicBuffer->getPixelFormat());
6770ab416269a866c8afa8f65d9351afa2407abee4cZhijun He        return;
678212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He    }
6790fd198ad89ec9c600bb1761b10d938146c28bb98Ruben Brunk
6800ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    // Carry over some fields from BufferItem.
6810ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    image->crop        = buffer->mCrop;
6820ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    image->transform   = buffer->mTransform;
6830ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    image->scalingMode = buffer->mScalingMode;
6840ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    image->timestamp   = buffer->mTimestamp;
6850ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    image->dataSpace   = buffer->mDataSpace;
6860ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    image->frameNumber = buffer->mFrameNumber;
6870ab416269a866c8afa8f65d9351afa2407abee4cZhijun He
6880ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    ALOGV("%s: Successfully locked the image", __FUNCTION__);
6890ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    // crop, transform, scalingMode, timestamp, and frameNumber should be set by producer,
6900ab416269a866c8afa8f65d9351afa2407abee4cZhijun He    // and we don't set them here.
6910ab416269a866c8afa8f65d9351afa2407abee4cZhijun He}
692212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He
6930ab416269a866c8afa8f65d9351afa2407abee4cZhijun Hestatic void Image_getLockedImageInfo(JNIEnv* env, LockedImage* buffer, int idx,
694