170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin/*
270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin**
370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin** Copyright 2013, The Android Open Source Project
470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin**
570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin** Licensed under the Apache License, Version 2.0 (the "License");
670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin** you may not use this file except in compliance with the License.
770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin** You may obtain a copy of the License at
870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin**
970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin**     http://www.apache.org/licenses/LICENSE-2.0
1070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin**
1170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin** Unless required by applicable law or agreed to in writing, software
1270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin** distributed under the License is distributed on an "AS IS" BASIS,
1370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin** See the License for the specific language governing permissions and
1570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin** limitations under the License.
1670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin*/
1770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
1870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin// #define LOG_NDEBUG 0
1970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin#define LOG_TAG "CameraMetadata-JNI"
2032ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk#include <utils/Errors.h>
2170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin#include <utils/Log.h>
2285c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk#include <utils/RefBase.h>
2332ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk#include <utils/Vector.h>
2432ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk#include <utils/SortedVector.h>
2532ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk#include <utils/KeyedVector.h>
26c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk#include <stdio.h>
2785c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk#include <string.h>
28c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk#include <vector>
2970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
3070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin#include "jni.h"
3170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin#include "JNIHelp.h"
3270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin#include "android_os_Parcel.h"
33ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe#include "core_jni_helpers.h"
34f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk#include "android_runtime/android_hardware_camera2_CameraMetadata.h"
3570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
365d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala#include <android/hardware/ICameraService.h>
3785c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk#include <binder/IServiceManager.h>
3870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin#include <camera/CameraMetadata.h>
39de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev#include <camera_metadata_hidden.h>
4085c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk#include <camera/VendorTagDescriptor.h>
41b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin#include <nativehelper/ScopedUtfChars.h>
42b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin#include <nativehelper/ScopedPrimitiveArray.h>
43b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
44d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin#include <sys/types.h> // for socketpair
45d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin#include <sys/socket.h> // for socketpair
46d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
4770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin// fully-qualified class name
4870c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala#define CAMERA_METADATA_CLASS_NAME "android/hardware/camera2/impl/CameraMetadataNative"
49c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk#define CHARACTERISTICS_KEY_CLASS_NAME "android/hardware/camera2/CameraCharacteristics$Key"
50c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk#define REQUEST_KEY_CLASS_NAME "android/hardware/camera2/CaptureRequest$Key"
51c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk#define RESULT_KEY_CLASS_NAME "android/hardware/camera2/CaptureResult$Key"
5270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
5370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinusing namespace android;
5470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
55c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunkstatic struct metadata_java_key_offsets_t {
56c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    jclass mCharacteristicsKey;
57c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    jclass mResultKey;
58c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    jclass mRequestKey;
59c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    jmethodID mCharacteristicsConstr;
60c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    jmethodID mResultConstr;
61c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    jmethodID mRequestConstr;
62c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    jclass mByteArray;
63c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    jclass mInt32Array;
64c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    jclass mFloatArray;
65c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    jclass mInt64Array;
66c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    jclass mDoubleArray;
67c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    jclass mRationalArray;
68c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    jclass mArrayList;
69c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    jmethodID mArrayListConstr;
70c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    jmethodID mArrayListAdd;
71c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk} gMetadataOffsets;
72c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk
7370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinstruct fields_t {
7470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    jfieldID    metadata_ptr;
7570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin};
7670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
7770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinstatic fields_t fields;
7870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
79f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunknamespace android {
80f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk
81f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunkstatus_t CameraMetadata_getNativeMetadata(JNIEnv* env, jobject thiz,
82f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk        /*out*/CameraMetadata* metadata) {
83f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk    if (!thiz) {
84f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk        ALOGE("%s: Invalid java metadata object.", __FUNCTION__);
85f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk        return BAD_VALUE;
86f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk    }
87f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk
88f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk    if (!metadata) {
89f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk        ALOGE("%s: Invalid output metadata object.", __FUNCTION__);
90f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk        return BAD_VALUE;
91f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk    }
92f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk    CameraMetadata* nativePtr = reinterpret_cast<CameraMetadata*>(env->GetLongField(thiz,
93f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk            fields.metadata_ptr));
94f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk    if (nativePtr == NULL) {
95f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk        ALOGE("%s: Invalid native pointer in java metadata object.", __FUNCTION__);
96f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk        return BAD_VALUE;
97f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk    }
98f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk    *metadata = *nativePtr;
99f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk    return OK;
100f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk}
101f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk
102f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk} /*namespace android*/
103f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk
104b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkinnamespace {
105b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkinstruct Helpers {
106b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    static size_t getTypeSize(uint8_t type) {
107b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        if (type >= NUM_TYPES) {
108b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            ALOGE("%s: Invalid type specified (%ud)", __FUNCTION__, type);
109b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            return static_cast<size_t>(-1);
110b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        }
111b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
112b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        return camera_metadata_type_size[type];
113b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
114b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
115b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    static status_t updateAny(CameraMetadata *metadata,
116b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                          uint32_t tag,
117b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                          uint32_t type,
118b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                          const void *data,
119b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                          size_t dataBytes) {
120b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
121b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        if (type >= NUM_TYPES) {
122b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            ALOGE("%s: Invalid type specified (%ud)", __FUNCTION__, type);
123b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            return INVALID_OPERATION;
124b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        }
125b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
126b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        size_t typeSize = getTypeSize(type);
127b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
128b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        if (dataBytes % typeSize != 0) {
12946d8444631b4b1253a76bfcc78a29d26014d022fDan Albert            ALOGE("%s: Expected dataBytes (%zu) to be divisible by typeSize "
13046d8444631b4b1253a76bfcc78a29d26014d022fDan Albert                  "(%zu)", __FUNCTION__, dataBytes, typeSize);
131b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            return BAD_VALUE;
132b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        }
133b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
134b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        size_t dataCount = dataBytes / typeSize;
135b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
136b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        switch(type) {
137b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin#define METADATA_UPDATE(runtime_type, compile_type)                            \
138b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            case runtime_type: {                                               \
139b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                const compile_type *dataPtr =                                  \
140b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                        static_cast<const compile_type*>(data);                \
141b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                return metadata->update(tag, dataPtr, dataCount);              \
142b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            }                                                                  \
143b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
144b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            METADATA_UPDATE(TYPE_BYTE,     uint8_t);
145b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            METADATA_UPDATE(TYPE_INT32,    int32_t);
146b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            METADATA_UPDATE(TYPE_FLOAT,    float);
147b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            METADATA_UPDATE(TYPE_INT64,    int64_t);
148b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            METADATA_UPDATE(TYPE_DOUBLE,   double);
149b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            METADATA_UPDATE(TYPE_RATIONAL, camera_metadata_rational_t);
150b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
151b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            default: {
152b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                // unreachable
153b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                ALOGE("%s: Unreachable", __FUNCTION__);
154b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                return INVALID_OPERATION;
155b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            }
156b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        }
157b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
158b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin#undef METADATA_UPDATE
159b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
160b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin};
161b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin} // namespace {}
162b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
16370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinextern "C" {
16470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
165c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunkstatic jobject CameraMetadata_getAllVendorKeys(JNIEnv* env, jobject thiz, jclass keyType);
166de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peevstatic jint CameraMetadata_getTagFromKey(JNIEnv *env, jobject thiz, jstring keyName, jlong vendorId);
167de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peevstatic jint CameraMetadata_getTagFromKeyLocal(JNIEnv *env, jobject thiz, jstring keyName);
168de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peevstatic jint CameraMetadata_getTypeFromTag(JNIEnv *env, jobject thiz, jint tag, jlong vendorId);
169de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peevstatic jint CameraMetadata_getTypeFromTagLocal(JNIEnv *env, jobject thiz, jint tag);
17085c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunkstatic jint CameraMetadata_setupGlobalVendorTagDescriptor(JNIEnv *env, jobject thiz);
17170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
17270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin// Less safe access to native pointer. Does NOT throw any Java exceptions if NULL.
17370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinstatic CameraMetadata* CameraMetadata_getPointerNoThrow(JNIEnv *env, jobject thiz) {
17470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
17570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    if (thiz == NULL) {
17670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        return NULL;
17770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    }
17870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
17970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    return reinterpret_cast<CameraMetadata*>(env->GetLongField(thiz, fields.metadata_ptr));
18070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin}
18170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
18270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin// Safe access to native pointer from object. Throws if not possible to access.
18370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinstatic CameraMetadata* CameraMetadata_getPointerThrow(JNIEnv *env, jobject thiz,
18470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin                                                 const char* argName = "this") {
18570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
18670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    if (thiz == NULL) {
18770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        ALOGV("%s: Throwing java.lang.NullPointerException for null reference",
18870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin              __FUNCTION__);
18970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        jniThrowNullPointerException(env, argName);
19070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        return NULL;
19170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    }
19270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
19370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    CameraMetadata* metadata = CameraMetadata_getPointerNoThrow(env, thiz);
19470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    if (metadata == NULL) {
19570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        ALOGV("%s: Throwing java.lang.IllegalStateException for closed object",
19670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin              __FUNCTION__);
19770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        jniThrowException(env, "java/lang/IllegalStateException",
19870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin                            "Metadata object was already closed");
19970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        return NULL;
20070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    }
20170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
20270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    return metadata;
20370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin}
20470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
20570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinstatic jlong CameraMetadata_allocate(JNIEnv *env, jobject thiz) {
20670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    ALOGV("%s", __FUNCTION__);
20770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
20870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    return reinterpret_cast<jlong>(new CameraMetadata());
20970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin}
21070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
21170c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvalastatic jlong CameraMetadata_allocateCopy(JNIEnv *env, jobject thiz,
21270c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala        jobject other) {
21370c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    ALOGV("%s", __FUNCTION__);
21470c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala
21570c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    CameraMetadata* otherMetadata =
21670c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala            CameraMetadata_getPointerThrow(env, other, "other");
21770c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala
21870c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    // In case of exception, return
21970c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    if (otherMetadata == NULL) return NULL;
22070c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala
22170c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    // Clone native metadata and return new pointer
22270c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    return reinterpret_cast<jlong>(new CameraMetadata(*otherMetadata));
22370c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala}
22470c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala
22570c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala
22670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinstatic jboolean CameraMetadata_isEmpty(JNIEnv *env, jobject thiz) {
22770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    ALOGV("%s", __FUNCTION__);
22870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
22970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz);
23070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
23170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    if (metadata == NULL) {
23270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        ALOGW("%s: Returning early due to exception being thrown",
23370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin               __FUNCTION__);
23470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        return JNI_TRUE; // actually throws java exc.
23570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    }
23670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
23770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    jboolean empty = metadata->isEmpty();
23870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
23946d8444631b4b1253a76bfcc78a29d26014d022fDan Albert    ALOGV("%s: Empty returned %d, entry count was %zu",
24070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin          __FUNCTION__, empty, metadata->entryCount());
24170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
24270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    return empty;
24370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin}
24470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
24570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinstatic jint CameraMetadata_getEntryCount(JNIEnv *env, jobject thiz) {
24670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    ALOGV("%s", __FUNCTION__);
24770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
24870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz);
24970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
25070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    if (metadata == NULL) return 0; // actually throws java exc.
25170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
25270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    return metadata->entryCount();
25370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin}
25470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
25570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin// idempotent. calling more than once has no effect.
25670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinstatic void CameraMetadata_close(JNIEnv *env, jobject thiz) {
25770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    ALOGV("%s", __FUNCTION__);
25870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
25970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    CameraMetadata* metadata = CameraMetadata_getPointerNoThrow(env, thiz);
26070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
26170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    if (metadata != NULL) {
26270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        delete metadata;
26370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        env->SetLongField(thiz, fields.metadata_ptr, 0);
26470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    }
26570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
26670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    LOG_ALWAYS_FATAL_IF(CameraMetadata_getPointerNoThrow(env, thiz) != NULL,
26770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin                        "Expected the native ptr to be 0 after #close");
26870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin}
26970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
27070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinstatic void CameraMetadata_swap(JNIEnv *env, jobject thiz, jobject other) {
27170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    ALOGV("%s", __FUNCTION__);
27270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
27370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz);
27470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
27570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    // order is important: we can't call another JNI method
27670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    // if there is an exception pending
27770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    if (metadata == NULL) return;
27870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
27970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    CameraMetadata* otherMetadata = CameraMetadata_getPointerThrow(env, other, "other");
28070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
28170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    if (otherMetadata == NULL) return;
28270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
28370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    metadata->swap(*otherMetadata);
28470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin}
28570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
286b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkinstatic jbyteArray CameraMetadata_readValues(JNIEnv *env, jobject thiz, jint tag) {
287b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    ALOGV("%s (tag = %d)", __FUNCTION__, tag);
288b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
289b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz);
290b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    if (metadata == NULL) return NULL;
291b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
292de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev    const camera_metadata_t *metaBuffer = metadata->getAndLock();
293de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev    int tagType = get_local_camera_metadata_tag_type(tag, metaBuffer);
294de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev    metadata->unlock(metaBuffer);
295b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    if (tagType == -1) {
296b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
297b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                             "Tag (%d) did not have a type", tag);
298b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        return NULL;
299b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
300b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    size_t tagSize = Helpers::getTypeSize(tagType);
301b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
302b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    camera_metadata_entry entry = metadata->find(tag);
303b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    if (entry.count == 0) {
304b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin         if (!metadata->exists(tag)) {
305b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin             ALOGV("%s: Tag %d does not have any entries", __FUNCTION__, tag);
306b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin             return NULL;
307b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin         } else {
308b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin             // OK: we will return a 0-sized array.
309b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin             ALOGV("%s: Tag %d had an entry, but it had 0 data", __FUNCTION__,
310b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                   tag);
311b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin         }
312b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
313b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
314b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    jsize byteCount = entry.count * tagSize;
315b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    jbyteArray byteArray = env->NewByteArray(byteCount);
316b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    if (env->ExceptionCheck()) return NULL;
317b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
318b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    // Copy into java array from native array
319b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    ScopedByteArrayRW arrayWriter(env, byteArray);
320b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    memcpy(arrayWriter.get(), entry.data.u8, byteCount);
321b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
322b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    return byteArray;
323b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin}
324b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
325b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkinstatic void CameraMetadata_writeValues(JNIEnv *env, jobject thiz, jint tag, jbyteArray src) {
326b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    ALOGV("%s (tag = %d)", __FUNCTION__, tag);
327b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
328b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz);
329b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    if (metadata == NULL) return;
330b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
331de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev    const camera_metadata_t *metaBuffer = metadata->getAndLock();
332de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev    int tagType = get_local_camera_metadata_tag_type(tag, metaBuffer);
333de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev    metadata->unlock(metaBuffer);
334b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    if (tagType == -1) {
335b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
336b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                             "Tag (%d) did not have a type", tag);
337b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        return;
338b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
339b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
340b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    status_t res;
341b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
342b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    if (src == NULL) {
343b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        // If array is NULL, delete the entry
3443710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin        if (metadata->exists(tag)) {
3453710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin            res = metadata->erase(tag);
3463710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin            ALOGV("%s: Erase values (res = %d)", __FUNCTION__, res);
3473710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin        } else {
3483710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin            res = OK;
3493710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin            ALOGV("%s: Don't need to erase", __FUNCTION__);
3503710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin        }
351b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    } else {
352b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        // Copy from java array into native array
353b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        ScopedByteArrayRO arrayReader(env, src);
354b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        if (arrayReader.get() == NULL) return;
355b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
356b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        res = Helpers::updateAny(metadata, static_cast<uint32_t>(tag),
357b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                                 tagType, arrayReader.get(), arrayReader.size());
3583710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin
3593710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin        ALOGV("%s: Update values (res = %d)", __FUNCTION__, res);
360b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
361b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
362b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    if (res == OK) {
363b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        return;
364b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    } else if (res == BAD_VALUE) {
365b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
366b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                             "Src byte array was poorly formed");
367b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    } else if (res == INVALID_OPERATION) {
368b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
369b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                             "Internal error while trying to update metadata");
370b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    } else {
371b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
372b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                             "Unknown error (%d) while trying to update "
373b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                            "metadata", res);
374b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
375b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin}
376b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
377d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkinstruct DumpMetadataParams {
378d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    int writeFd;
379d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    const CameraMetadata* metadata;
380d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin};
381d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
382d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkinstatic void* CameraMetadata_writeMetadataThread(void* arg) {
383d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    DumpMetadataParams* p = static_cast<DumpMetadataParams*>(arg);
384d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
385d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    /*
386d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     * Write the dumped data, and close the writing side FD.
387d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     */
388d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    p->metadata->dump(p->writeFd, /*verbosity*/2);
389d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
390d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    if (close(p->writeFd) < 0) {
391d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        ALOGE("%s: Failed to close writeFd (errno = %#x, message = '%s')",
392d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin                __FUNCTION__, errno, strerror(errno));
393d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    }
394d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
395d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    return NULL;
396d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin}
397d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
398d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkinstatic void CameraMetadata_dump(JNIEnv *env, jobject thiz) {
399d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    ALOGV("%s", __FUNCTION__);
400d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz);
401d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    if (metadata == NULL) {
402d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        return;
403d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    }
404d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
405d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    /*
406d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     * Create a socket pair for local streaming read/writes.
407d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     *
408d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     * The metadata will be dumped into the write side,
409d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     * and then read back out (and logged) via the read side.
410d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     */
411d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
412d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    int writeFd, readFd;
413d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    {
414d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
415d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        int sv[2];
416d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        if (socketpair(AF_LOCAL, SOCK_STREAM, /*protocol*/0, &sv[0]) < 0) {
417d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin            jniThrowExceptionFmt(env, "java/io/IOException",
418d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin                    "Failed to create socketpair (errno = %#x, message = '%s')",
419d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin                    errno, strerror(errno));
420d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin            return;
421d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        }
422d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        writeFd = sv[0];
423d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        readFd = sv[1];
424d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    }
425d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
426d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    /*
427d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     * Create a thread for doing the writing.
428d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     *
429d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     * The reading and writing must be concurrent, otherwise
430d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     * the write will block forever once it exhausts the capped
431d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     * buffer size (from getsockopt).
432d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     */
433d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    pthread_t writeThread;
434d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    DumpMetadataParams params = {
435d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        writeFd,
436d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        metadata
437d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    };
438d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
439d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    {
440d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        int threadRet = pthread_create(&writeThread, /*attr*/NULL,
441d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin                CameraMetadata_writeMetadataThread, (void*)&params);
442d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
443d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        if (threadRet != 0) {
444d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin            close(writeFd);
445d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
446d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin            jniThrowExceptionFmt(env, "java/io/IOException",
447d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin                    "Failed to create thread for writing (errno = %#x, message = '%s')",
448d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin                    threadRet, strerror(threadRet));
449d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        }
450d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    }
451d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
452d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    /*
453d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     * Read out a byte until stream is complete. Write completed lines
454d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     * to ALOG.
455d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     */
456d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    {
457d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        char out[] = {'\0', '\0'}; // large enough to append as a string
458d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        String8 logLine;
459d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
460d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        // Read one byte at a time! Very slow but avoids complicated \n scanning.
461d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        ssize_t res;
462d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        while ((res = TEMP_FAILURE_RETRY(read(readFd, &out[0], /*count*/1))) > 0) {
463d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin            if (out[0] == '\n') {
464d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin                ALOGD("%s", logLine.string());
465d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin                logLine.clear();
466d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin            } else {
467d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin                logLine.append(out);
468d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin            }
469d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        }
470d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
471d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        if (res < 0) {
472d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin            jniThrowExceptionFmt(env, "java/io/IOException",
473d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin                    "Failed to read from fd (errno = %#x, message = '%s')",
474d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin                    errno, strerror(errno));
475d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin            //return;
476d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        } else if (!logLine.isEmpty()) {
477d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin            ALOGD("%s", logLine.string());
478d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        }
479d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    }
480d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
481d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    int res;
482d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
483d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    // Join until thread finishes. Ensures params/metadata is valid until then.
484d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    if ((res = pthread_join(writeThread, /*retval*/NULL)) != 0) {
485d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        ALOGE("%s: Failed to join thread (errno = %#x, message = '%s')",
486d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin                __FUNCTION__, res, strerror(res));
487d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    }
488d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin}
489d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
49070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinstatic void CameraMetadata_readFromParcel(JNIEnv *env, jobject thiz, jobject parcel) {
49170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    ALOGV("%s", __FUNCTION__);
49270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz);
49370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    if (metadata == NULL) {
49470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        return;
49570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    }
49670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
49770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    Parcel* parcelNative = parcelForJavaObject(env, parcel);
49870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    if (parcelNative == NULL) {
49970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        jniThrowNullPointerException(env, "parcel");
50070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        return;
50170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    }
50270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
50370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    status_t err;
50470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    if ((err = metadata->readFromParcel(parcelNative)) != OK) {
50570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
50670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin                             "Failed to read from parcel (error code %d)", err);
50770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        return;
50870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    }
50970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin}
51070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
51170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinstatic void CameraMetadata_writeToParcel(JNIEnv *env, jobject thiz, jobject parcel) {
51270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    ALOGV("%s", __FUNCTION__);
51370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz);
51470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    if (metadata == NULL) {
51570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        return;
51670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    }
51770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
51870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    Parcel* parcelNative = parcelForJavaObject(env, parcel);
51970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    if (parcelNative == NULL) {
52070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        jniThrowNullPointerException(env, "parcel");
52170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        return;
52270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    }
52370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
52470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    status_t err;
52570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    if ((err = metadata->writeToParcel(parcelNative)) != OK) {
52670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
52770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin                                  "Failed to write to parcel (error code %d)", err);
52870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        return;
52970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    }
53070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin}
53170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
53270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin} // extern "C"
53370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
53470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin//-------------------------------------------------
53570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
53676f6a86de25e1bf74717e047e55fd44b089673f3Daniel Micaystatic const JNINativeMethod gCameraMetadataMethods[] = {
537b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin// static methods
538b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin  { "nativeGetTagFromKey",
539de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev    "(Ljava/lang/String;J)I",
540b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    (void *)CameraMetadata_getTagFromKey },
541b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin  { "nativeGetTypeFromTag",
542de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev    "(IJ)I",
543b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    (void *)CameraMetadata_getTypeFromTag },
54485c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk  { "nativeSetupGlobalVendorTagDescriptor",
54585c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk    "()I",
54685c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk    (void*)CameraMetadata_setupGlobalVendorTagDescriptor },
547b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin// instance methods
54870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin  { "nativeAllocate",
54970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    "()J",
55070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    (void*)CameraMetadata_allocate },
55170c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala  { "nativeAllocateCopy",
55270c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    "(L" CAMERA_METADATA_CLASS_NAME ";)J",
55370c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    (void *)CameraMetadata_allocateCopy },
55470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin  { "nativeIsEmpty",
55570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    "()Z",
55670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    (void*)CameraMetadata_isEmpty },
55770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin  { "nativeGetEntryCount",
55870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    "()I",
55970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    (void*)CameraMetadata_getEntryCount },
56070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin  { "nativeClose",
56170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    "()V",
56270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    (void*)CameraMetadata_close },
56370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin  { "nativeSwap",
56470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    "(L" CAMERA_METADATA_CLASS_NAME ";)V",
56570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    (void *)CameraMetadata_swap },
566de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev  { "nativeGetTagFromKeyLocal",
567de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev    "(Ljava/lang/String;)I",
568de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev    (void *)CameraMetadata_getTagFromKeyLocal },
569de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev  { "nativeGetTypeFromTagLocal",
570de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev    "(I)I",
571de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev    (void *)CameraMetadata_getTypeFromTagLocal },
572b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin  { "nativeReadValues",
573b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    "(I)[B",
574b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    (void *)CameraMetadata_readValues },
575b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin  { "nativeWriteValues",
576b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    "(I[B)V",
577b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    (void *)CameraMetadata_writeValues },
578d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin  { "nativeDump",
579d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    "()V",
580d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    (void *)CameraMetadata_dump },
581de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev  { "nativeGetAllVendorKeys",
582de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev    "(Ljava/lang/Class;)Ljava/util/ArrayList;",
583de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev    (void *)CameraMetadata_getAllVendorKeys},
584b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin// Parcelable interface
58570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin  { "nativeReadFromParcel",
58670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    "(Landroid/os/Parcel;)V",
58770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    (void *)CameraMetadata_readFromParcel },
58870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin  { "nativeWriteToParcel",
58970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    "(Landroid/os/Parcel;)V",
59070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    (void *)CameraMetadata_writeToParcel },
59170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin};
59270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
59370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin// Get all the required offsets in java class and register native functions
5942f1a2e423e0fbb64467d6fcfa4e82c6384f31210Eino-Ville Talvalaint register_android_hardware_camera2_CameraMetadata(JNIEnv *env)
59570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin{
596c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk
597c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    // Store global references to Key-related classes and methods used natively
598c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    jclass characteristicsKeyClazz = FindClassOrDie(env, CHARACTERISTICS_KEY_CLASS_NAME);
599c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    jclass requestKeyClazz = FindClassOrDie(env, REQUEST_KEY_CLASS_NAME);
600c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    jclass resultKeyClazz = FindClassOrDie(env, RESULT_KEY_CLASS_NAME);
601c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    gMetadataOffsets.mCharacteristicsKey = MakeGlobalRefOrDie(env, characteristicsKeyClazz);
602c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    gMetadataOffsets.mRequestKey = MakeGlobalRefOrDie(env, requestKeyClazz);
603c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    gMetadataOffsets.mResultKey = MakeGlobalRefOrDie(env, resultKeyClazz);
604c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    gMetadataOffsets.mCharacteristicsConstr = GetMethodIDOrDie(env,
605c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk            gMetadataOffsets.mCharacteristicsKey, "<init>",
606de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev            "(Ljava/lang/String;Ljava/lang/Class;J)V");
607c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    gMetadataOffsets.mRequestConstr = GetMethodIDOrDie(env,
608de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev            gMetadataOffsets.mRequestKey, "<init>", "(Ljava/lang/String;Ljava/lang/Class;J)V");
609c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    gMetadataOffsets.mResultConstr = GetMethodIDOrDie(env,
610de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev            gMetadataOffsets.mResultKey, "<init>", "(Ljava/lang/String;Ljava/lang/Class;J)V");
611c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk
612c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    // Store global references for primitive array types used by Keys
613c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    jclass byteClazz = FindClassOrDie(env, "[B");
614c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    jclass int32Clazz = FindClassOrDie(env, "[I");
615c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    jclass floatClazz = FindClassOrDie(env, "[F");
616c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    jclass int64Clazz = FindClassOrDie(env, "[J");
617c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    jclass doubleClazz = FindClassOrDie(env, "[D");
618c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    jclass rationalClazz = FindClassOrDie(env, "[Landroid/util/Rational;");
619c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    gMetadataOffsets.mByteArray = MakeGlobalRefOrDie(env, byteClazz);
620c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    gMetadataOffsets.mInt32Array = MakeGlobalRefOrDie(env, int32Clazz);
621c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    gMetadataOffsets.mFloatArray = MakeGlobalRefOrDie(env, floatClazz);
622c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    gMetadataOffsets.mInt64Array = MakeGlobalRefOrDie(env, int64Clazz);
623c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    gMetadataOffsets.mDoubleArray = MakeGlobalRefOrDie(env, doubleClazz);
624c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    gMetadataOffsets.mRationalArray = MakeGlobalRefOrDie(env, rationalClazz);
625c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk
626c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    // Store global references for ArrayList methods used
627c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    jclass arrayListClazz = FindClassOrDie(env, "java/util/ArrayList");
628c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    gMetadataOffsets.mArrayList = MakeGlobalRefOrDie(env, arrayListClazz);
629c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    gMetadataOffsets.mArrayListConstr = GetMethodIDOrDie(env, gMetadataOffsets.mArrayList,
630c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk            "<init>", "(I)V");
631c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    gMetadataOffsets.mArrayListAdd = GetMethodIDOrDie(env, gMetadataOffsets.mArrayList,
632c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk            "add", "(Ljava/lang/Object;)Z");
633c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk
63408e6c34cf72acbffd560fab21dc6ecf351aaf61bAndreas Gampe    jclass cameraMetadataClazz = FindClassOrDie(env, CAMERA_METADATA_CLASS_NAME);
63508e6c34cf72acbffd560fab21dc6ecf351aaf61bAndreas Gampe    fields.metadata_ptr = GetFieldIDOrDie(env, cameraMetadataClazz, "mMetadataPtr", "J");
63608e6c34cf72acbffd560fab21dc6ecf351aaf61bAndreas Gampe
63770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    // Register native functions
638ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    return RegisterMethodsOrDie(env,
63970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin            CAMERA_METADATA_CLASS_NAME,
64070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin            gCameraMetadataMethods,
64170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin            NELEM(gCameraMetadataMethods));
64270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin}
64370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
64470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinextern "C" {
645c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk
646de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peevstatic jint CameraMetadata_getTypeFromTagLocal(JNIEnv *env, jobject thiz, jint tag) {
647de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev    CameraMetadata* metadata = CameraMetadata_getPointerNoThrow(env, thiz);
648de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev    metadata_vendor_id_t vendorId = CAMERA_METADATA_INVALID_VENDOR_ID;
649de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev    if (metadata) {
650de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev        const camera_metadata_t *metaBuffer = metadata->getAndLock();
651de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev        vendorId = get_camera_metadata_vendor_id(metaBuffer);
652de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev        metadata->unlock(metaBuffer);
653de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev    }
654de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev
655de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev    int tagType = get_local_camera_metadata_tag_type_vendor_id(tag, vendorId);
656de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev    if (tagType == -1) {
657de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev        jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
658de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev                             "Tag (%d) did not have a type", tag);
659de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev        return -1;
660de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev    }
661de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev
662de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev    return tagType;
663de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev}
664de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev
665de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peevstatic jint CameraMetadata_getTagFromKeyLocal(JNIEnv *env, jobject thiz, jstring keyName) {
666de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev    ScopedUtfChars keyScoped(env, keyName);
667de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev    const char *key = keyScoped.c_str();
668de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev    if (key == NULL) {
669de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev        // exception thrown by ScopedUtfChars
670de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev        return 0;
671de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev    }
672de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev    ALOGV("%s (key = '%s')", __FUNCTION__, key);
673de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev
674de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev    uint32_t tag = 0;
675de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev    sp<VendorTagDescriptor> vTags;
676de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev    CameraMetadata* metadata = CameraMetadata_getPointerNoThrow(env, thiz);
677de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev    if (metadata) {
678de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev        sp<VendorTagDescriptorCache> cache = VendorTagDescriptorCache::getGlobalVendorTagCache();
679de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev        if (cache.get()) {
680de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev            const camera_metadata_t *metaBuffer = metadata->getAndLock();
681de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev            metadata_vendor_id_t vendorId = get_camera_metadata_vendor_id(metaBuffer);
682de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev            metadata->unlock(metaBuffer);
683de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev            cache->getVendorTagDescriptor(vendorId, &vTags);
684de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev        }
685de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev    }
686c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk
687de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev    status_t res = CameraMetadata::getTagFromName(key, vTags.get(), &tag);
688de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev    if (res != OK) {
689de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev        jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
690de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev                             "Could not find tag for key '%s')", key);
691de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev    }
692de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev    return tag;
693de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev}
694de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev
695de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peevstatic jobject CameraMetadata_getAllVendorKeys(JNIEnv* env, jobject thiz, jclass keyType) {
696de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev    metadata_vendor_id_t vendorId = CAMERA_METADATA_INVALID_VENDOR_ID;
697c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    // Get all vendor tags
698c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    sp<VendorTagDescriptor> vTags = VendorTagDescriptor::getGlobalVendorTagDescriptor();
699c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    if (vTags.get() == nullptr) {
700de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev        sp<VendorTagDescriptorCache> cache = VendorTagDescriptorCache::getGlobalVendorTagCache();
701de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev        if (cache.get() == nullptr) {
702de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev            // No vendor tags.
703de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev            return nullptr;
704de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev        }
705de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev
706de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev        CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz);
707de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev        if (metadata == NULL) return NULL;
708de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev
709de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev        const camera_metadata_t *metaBuffer = metadata->getAndLock();
710de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev        vendorId = get_camera_metadata_vendor_id(metaBuffer);
711de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev        cache->getVendorTagDescriptor(vendorId, &vTags);
712de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev        metadata->unlock(metaBuffer);
713de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev        if (vTags.get() == nullptr) {
714de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev            return nullptr;
715de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev        }
716c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    }
717c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk
718c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    int count = vTags->getTagCount();
719c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    if (count <= 0) {
720c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk        // No vendor tags.
721c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk        return NULL;
722c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    }
723c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk
724c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    std::vector<uint32_t> tagIds(count, /*initializer value*/0);
725c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    vTags->getTagArray(&tagIds[0]);
726c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk
727c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    // Which key class/constructor should we use?
728c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    jclass keyClazz;
729c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    jmethodID keyConstr;
730c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    if (env->IsSameObject(keyType, gMetadataOffsets.mCharacteristicsKey)) {
731c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk        keyClazz = gMetadataOffsets.mCharacteristicsKey;
732c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk        keyConstr = gMetadataOffsets.mCharacteristicsConstr;
733c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    } else if (env->IsSameObject(keyType, gMetadataOffsets.mResultKey)) {
734c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk        keyClazz = gMetadataOffsets.mResultKey;
735c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk        keyConstr = gMetadataOffsets.mResultConstr;
736c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    } else if (env->IsSameObject(keyType, gMetadataOffsets.mRequestKey)) {
737c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk        keyClazz = gMetadataOffsets.mRequestKey;
738c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk        keyConstr = gMetadataOffsets.mRequestConstr;
739c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    } else {
740c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk        jniThrowException(env, "java/lang/IllegalArgumentException",
741c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk                "Invalid key class given as argument.");
742c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk        return NULL;
743c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    }
744c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk
745c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    // Allocate arrayList to return
746c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    jobject arrayList = env->NewObject(gMetadataOffsets.mArrayList,
747c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk            gMetadataOffsets.mArrayListConstr, static_cast<jint>(count));
748c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    if (env->ExceptionCheck()) {
749c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk        return NULL;
750c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    }
751c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk
752c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    for (uint32_t id : tagIds) {
753c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk        const char* section = vTags->getSectionName(id);
754c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk        const char* tag = vTags->getTagName(id);
755c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk        int type = vTags->getTagType(id);
756c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk
757c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk        size_t totalLen = strlen(section) + strlen(tag) + 2;
758c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk        std::vector<char> fullName(totalLen, 0);
759c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk        snprintf(&fullName[0], totalLen, "%s.%s", section, tag);
760c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk
761c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk        jstring name = env->NewStringUTF(&fullName[0]);
762c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk
763c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk        if (env->ExceptionCheck()) {
764c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk            return NULL;
765c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk        }
766c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk
767c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk        jclass valueClazz;
768c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk        switch (type) {
769c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk            case TYPE_BYTE:
770c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk                valueClazz = gMetadataOffsets.mByteArray;
771c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk                break;
772c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk            case TYPE_INT32:
773c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk                valueClazz = gMetadataOffsets.mInt32Array;
774c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk                break;
775c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk            case TYPE_FLOAT:
776c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk                valueClazz = gMetadataOffsets.mFloatArray;
777c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk                break;
778c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk            case TYPE_INT64:
779c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk                valueClazz = gMetadataOffsets.mInt64Array;
780c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk                break;
781c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk            case TYPE_DOUBLE:
782c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk                valueClazz = gMetadataOffsets.mDoubleArray;
783c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk                break;
784c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk            case TYPE_RATIONAL:
785c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk                valueClazz = gMetadataOffsets.mRationalArray;
786c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk                break;
787c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk            default:
788c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk                jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
789c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk                        "Invalid type %d given for key %s", type, &fullName[0]);
790c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk                return NULL;
791c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk        }
792c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk
793de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev        jobject key = env->NewObject(keyClazz, keyConstr, name, valueClazz, vendorId);
794c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk        if (env->ExceptionCheck()) {
795c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk            return NULL;
796c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk        }
797c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk
798c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk        env->CallBooleanMethod(arrayList, gMetadataOffsets.mArrayListAdd, key);
799c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk        if (env->ExceptionCheck()) {
800c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk            return NULL;
801c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk        }
802c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk
803c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk        env->DeleteLocalRef(name);
804c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk        env->DeleteLocalRef(key);
805c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    }
806c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk
807c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    return arrayList;
808c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk}
809c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk
810de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peevstatic jint CameraMetadata_getTagFromKey(JNIEnv *env, jobject thiz, jstring keyName,
811de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev        jlong vendorId) {
812b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    ScopedUtfChars keyScoped(env, keyName);
813b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    const char *key = keyScoped.c_str();
814b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    if (key == NULL) {
815b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        // exception thrown by ScopedUtfChars
816b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        return 0;
817b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
818b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    ALOGV("%s (key = '%s')", __FUNCTION__, key);
819b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
82032ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk    uint32_t tag = 0;
821376e24a5f899d8238c0c46237d460f092ab6d3a6Eino-Ville Talvala    sp<VendorTagDescriptor> vTags =
822376e24a5f899d8238c0c46237d460f092ab6d3a6Eino-Ville Talvala            VendorTagDescriptor::getGlobalVendorTagDescriptor();
823de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev    if (vTags.get() == nullptr) {
824de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev        sp<VendorTagDescriptorCache> cache = VendorTagDescriptorCache::getGlobalVendorTagCache();
825de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev        if (cache.get() != nullptr) {
826de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev            cache->getVendorTagDescriptor(vendorId, &vTags);
827de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev        }
828de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev    }
829de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev
830376e24a5f899d8238c0c46237d460f092ab6d3a6Eino-Ville Talvala    status_t res = CameraMetadata::getTagFromName(key, vTags.get(), &tag);
831376e24a5f899d8238c0c46237d460f092ab6d3a6Eino-Ville Talvala    if (res != OK) {
832376e24a5f899d8238c0c46237d460f092ab6d3a6Eino-Ville Talvala        jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
833376e24a5f899d8238c0c46237d460f092ab6d3a6Eino-Ville Talvala                             "Could not find tag for key '%s')", key);
834b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
835b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    return tag;
836b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin}
837b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
838de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peevstatic jint CameraMetadata_getTypeFromTag(JNIEnv *env, jobject thiz, jint tag, jlong vendorId) {
839de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev    int tagType = get_local_camera_metadata_tag_type_vendor_id(tag, vendorId);
840b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    if (tagType == -1) {
841b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
842b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                             "Tag (%d) did not have a type", tag);
843b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        return -1;
844b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
845b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
846b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    return tagType;
847b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin}
848b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
84985c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunkstatic jint CameraMetadata_setupGlobalVendorTagDescriptor(JNIEnv *env, jobject thiz) {
85085c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk    const String16 NAME("media.camera");
8515d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala    sp<hardware::ICameraService> cameraService;
85285c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk    status_t err = getService(NAME, /*out*/&cameraService);
85385c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk
85485c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk    if (err != OK) {
85585c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk        ALOGE("%s: Failed to get camera service, received error %s (%d)", __FUNCTION__,
85685c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk                strerror(-err), err);
8575d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala        return hardware::ICameraService::ERROR_DISCONNECTED;
85885c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk    }
85985c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk
8605d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala    sp<VendorTagDescriptor> desc = new VendorTagDescriptor();
8615d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala    binder::Status res = cameraService->getCameraVendorTagDescriptor(/*out*/desc.get());
86285c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk
8635f2f804a19ecf511d069ebbda6cc69a07fa7b13dEino-Ville Talvala    if (res.serviceSpecificErrorCode() == hardware::ICameraService::ERROR_DISCONNECTED) {
8645f2f804a19ecf511d069ebbda6cc69a07fa7b13dEino-Ville Talvala        // No camera module available, not an error on devices with no cameras
8655614cbe64493308dc5330eac5d5ba17202013dc4Igor Murashkin        VendorTagDescriptor::clearGlobalVendorTagDescriptor();
8665614cbe64493308dc5330eac5d5ba17202013dc4Igor Murashkin        return OK;
8675d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala    } else if (!res.isOk()) {
8685f2f804a19ecf511d069ebbda6cc69a07fa7b13dEino-Ville Talvala        VendorTagDescriptor::clearGlobalVendorTagDescriptor();
8695f2f804a19ecf511d069ebbda6cc69a07fa7b13dEino-Ville Talvala        ALOGE("%s: Failed to setup vendor tag descriptors: %s",
8705f2f804a19ecf511d069ebbda6cc69a07fa7b13dEino-Ville Talvala                __FUNCTION__, res.toString8().string());
8715d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala        return res.serviceSpecificErrorCode();
87285c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk    }
873de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev    if (0 < desc->getTagCount()) {
874de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev        err = VendorTagDescriptor::setAsGlobalVendorTagDescriptor(desc);
875de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev    } else {
876de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev        sp<VendorTagDescriptorCache> cache = new VendorTagDescriptorCache();
877de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev        binder::Status res = cameraService->getCameraVendorTagCache(/*out*/cache.get());
878de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev        if (res.serviceSpecificErrorCode() == hardware::ICameraService::ERROR_DISCONNECTED) {
879de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev            // No camera module available, not an error on devices with no cameras
880de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev            VendorTagDescriptorCache::clearGlobalVendorTagCache();
881de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev            return OK;
882de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev        } else if (!res.isOk()) {
883de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev            VendorTagDescriptorCache::clearGlobalVendorTagCache();
884de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev            ALOGE("%s: Failed to setup vendor tag cache: %s",
885de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev                    __FUNCTION__, res.toString8().string());
886de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev            return res.serviceSpecificErrorCode();
887de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev        }
88885c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk
889de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev        err = VendorTagDescriptorCache::setAsGlobalVendorTagCache(cache);
890de62d84eb9dbcd43c4db3100a3cd80209b04cd2fEmilian Peev    }
89185c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk
8925d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala    if (err != OK) {
8935d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala        return hardware::ICameraService::ERROR_INVALID_OPERATION;
8945d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala    }
8955d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala    return OK;
89685c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk}
89785c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk
89870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin} // extern "C"
899