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>
3985c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk#include <camera/VendorTagDescriptor.h>
40b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin#include <nativehelper/ScopedUtfChars.h>
41b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin#include <nativehelper/ScopedPrimitiveArray.h>
42b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
43d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin#include <sys/types.h> // for socketpair
44d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin#include <sys/socket.h> // for socketpair
45d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
46ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampestatic const bool kIsDebug = false;
4770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
4870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin// fully-qualified class name
4970c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala#define CAMERA_METADATA_CLASS_NAME "android/hardware/camera2/impl/CameraMetadataNative"
50c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk#define CHARACTERISTICS_KEY_CLASS_NAME "android/hardware/camera2/CameraCharacteristics$Key"
51c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk#define REQUEST_KEY_CLASS_NAME "android/hardware/camera2/CaptureRequest$Key"
52c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk#define RESULT_KEY_CLASS_NAME "android/hardware/camera2/CaptureResult$Key"
5370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
5470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinusing namespace android;
5570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
56c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunkstatic struct metadata_java_key_offsets_t {
57c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    jclass mCharacteristicsKey;
58c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    jclass mResultKey;
59c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    jclass mRequestKey;
60c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    jmethodID mCharacteristicsConstr;
61c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    jmethodID mResultConstr;
62c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    jmethodID mRequestConstr;
63c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    jclass mByteArray;
64c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    jclass mInt32Array;
65c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    jclass mFloatArray;
66c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    jclass mInt64Array;
67c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    jclass mDoubleArray;
68c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    jclass mRationalArray;
69c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    jclass mArrayList;
70c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    jmethodID mArrayListConstr;
71c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    jmethodID mArrayListAdd;
72c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk} gMetadataOffsets;
73c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk
7470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinstruct fields_t {
7570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    jfieldID    metadata_ptr;
7670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin};
7770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
7870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinstatic fields_t fields;
7970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
80f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunknamespace android {
81f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk
82f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunkstatus_t CameraMetadata_getNativeMetadata(JNIEnv* env, jobject thiz,
83f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk        /*out*/CameraMetadata* metadata) {
84f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk    if (!thiz) {
85f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk        ALOGE("%s: Invalid java metadata object.", __FUNCTION__);
86f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk        return BAD_VALUE;
87f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk    }
88f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk
89f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk    if (!metadata) {
90f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk        ALOGE("%s: Invalid output metadata object.", __FUNCTION__);
91f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk        return BAD_VALUE;
92f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk    }
93f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk    CameraMetadata* nativePtr = reinterpret_cast<CameraMetadata*>(env->GetLongField(thiz,
94f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk            fields.metadata_ptr));
95f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk    if (nativePtr == NULL) {
96f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk        ALOGE("%s: Invalid native pointer in java metadata object.", __FUNCTION__);
97f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk        return BAD_VALUE;
98f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk    }
99f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk    *metadata = *nativePtr;
100f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk    return OK;
101f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk}
102f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk
103f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk} /*namespace android*/
104f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk
105b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkinnamespace {
106b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkinstruct Helpers {
107b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    static size_t getTypeSize(uint8_t type) {
108b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        if (type >= NUM_TYPES) {
109b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            ALOGE("%s: Invalid type specified (%ud)", __FUNCTION__, type);
110b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            return static_cast<size_t>(-1);
111b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        }
112b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
113b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        return camera_metadata_type_size[type];
114b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
115b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
116b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    static status_t updateAny(CameraMetadata *metadata,
117b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                          uint32_t tag,
118b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                          uint32_t type,
119b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                          const void *data,
120b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                          size_t dataBytes) {
121b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
122b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        if (type >= NUM_TYPES) {
123b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            ALOGE("%s: Invalid type specified (%ud)", __FUNCTION__, type);
124b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            return INVALID_OPERATION;
125b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        }
126b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
127b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        size_t typeSize = getTypeSize(type);
128b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
129b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        if (dataBytes % typeSize != 0) {
13046d8444631b4b1253a76bfcc78a29d26014d022fDan Albert            ALOGE("%s: Expected dataBytes (%zu) to be divisible by typeSize "
13146d8444631b4b1253a76bfcc78a29d26014d022fDan Albert                  "(%zu)", __FUNCTION__, dataBytes, typeSize);
132b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            return BAD_VALUE;
133b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        }
134b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
135b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        size_t dataCount = dataBytes / typeSize;
136b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
137b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        switch(type) {
138b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin#define METADATA_UPDATE(runtime_type, compile_type)                            \
139b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            case runtime_type: {                                               \
140b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                const compile_type *dataPtr =                                  \
141b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                        static_cast<const compile_type*>(data);                \
142b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                return metadata->update(tag, dataPtr, dataCount);              \
143b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            }                                                                  \
144b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
145b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            METADATA_UPDATE(TYPE_BYTE,     uint8_t);
146b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            METADATA_UPDATE(TYPE_INT32,    int32_t);
147b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            METADATA_UPDATE(TYPE_FLOAT,    float);
148b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            METADATA_UPDATE(TYPE_INT64,    int64_t);
149b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            METADATA_UPDATE(TYPE_DOUBLE,   double);
150b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            METADATA_UPDATE(TYPE_RATIONAL, camera_metadata_rational_t);
151b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
152b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            default: {
153b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                // unreachable
154b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                ALOGE("%s: Unreachable", __FUNCTION__);
155b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                return INVALID_OPERATION;
156b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            }
157b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        }
158b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
159b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin#undef METADATA_UPDATE
160b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
161b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin};
162b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin} // namespace {}
163b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
16470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinextern "C" {
16570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
16670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinstatic void CameraMetadata_classInit(JNIEnv *env, jobject thiz);
167c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunkstatic jobject CameraMetadata_getAllVendorKeys(JNIEnv* env, jobject thiz, jclass keyType);
168b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkinstatic jint CameraMetadata_getTagFromKey(JNIEnv *env, jobject thiz, jstring keyName);
169b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkinstatic jint CameraMetadata_getTypeFromTag(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
292b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    int tagType = get_camera_metadata_tag_type(tag);
293b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    if (tagType == -1) {
294b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
295b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                             "Tag (%d) did not have a type", tag);
296b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        return NULL;
297b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
298b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    size_t tagSize = Helpers::getTypeSize(tagType);
299b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
300b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    camera_metadata_entry entry = metadata->find(tag);
301b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    if (entry.count == 0) {
302b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin         if (!metadata->exists(tag)) {
303b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin             ALOGV("%s: Tag %d does not have any entries", __FUNCTION__, tag);
304b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin             return NULL;
305b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin         } else {
306b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin             // OK: we will return a 0-sized array.
307b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin             ALOGV("%s: Tag %d had an entry, but it had 0 data", __FUNCTION__,
308b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                   tag);
309b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin         }
310b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
311b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
312b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    jsize byteCount = entry.count * tagSize;
313b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    jbyteArray byteArray = env->NewByteArray(byteCount);
314b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    if (env->ExceptionCheck()) return NULL;
315b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
316b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    // Copy into java array from native array
317b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    ScopedByteArrayRW arrayWriter(env, byteArray);
318b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    memcpy(arrayWriter.get(), entry.data.u8, byteCount);
319b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
320b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    return byteArray;
321b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin}
322b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
323b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkinstatic void CameraMetadata_writeValues(JNIEnv *env, jobject thiz, jint tag, jbyteArray src) {
324b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    ALOGV("%s (tag = %d)", __FUNCTION__, tag);
325b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
326b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz);
327b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    if (metadata == NULL) return;
328b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
329b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    int tagType = get_camera_metadata_tag_type(tag);
330b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    if (tagType == -1) {
331b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
332b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                             "Tag (%d) did not have a type", tag);
333b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        return;
334b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
335b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
336b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    status_t res;
337b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
338b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    if (src == NULL) {
339b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        // If array is NULL, delete the entry
3403710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin        if (metadata->exists(tag)) {
3413710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin            res = metadata->erase(tag);
3423710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin            ALOGV("%s: Erase values (res = %d)", __FUNCTION__, res);
3433710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin        } else {
3443710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin            res = OK;
3453710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin            ALOGV("%s: Don't need to erase", __FUNCTION__);
3463710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin        }
347b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    } else {
348b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        // Copy from java array into native array
349b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        ScopedByteArrayRO arrayReader(env, src);
350b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        if (arrayReader.get() == NULL) return;
351b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
352b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        res = Helpers::updateAny(metadata, static_cast<uint32_t>(tag),
353b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                                 tagType, arrayReader.get(), arrayReader.size());
3543710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin
3553710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin        ALOGV("%s: Update values (res = %d)", __FUNCTION__, res);
356b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
357b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
358b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    if (res == OK) {
359b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        return;
360b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    } else if (res == BAD_VALUE) {
361b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
362b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                             "Src byte array was poorly formed");
363b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    } else if (res == INVALID_OPERATION) {
364b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
365b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                             "Internal error while trying to update metadata");
366b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    } else {
367b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
368b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                             "Unknown error (%d) while trying to update "
369b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                            "metadata", res);
370b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
371b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin}
372b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
373d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkinstruct DumpMetadataParams {
374d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    int writeFd;
375d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    const CameraMetadata* metadata;
376d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin};
377d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
378d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkinstatic void* CameraMetadata_writeMetadataThread(void* arg) {
379d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    DumpMetadataParams* p = static_cast<DumpMetadataParams*>(arg);
380d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
381d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    /*
382d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     * Write the dumped data, and close the writing side FD.
383d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     */
384d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    p->metadata->dump(p->writeFd, /*verbosity*/2);
385d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
386d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    if (close(p->writeFd) < 0) {
387d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        ALOGE("%s: Failed to close writeFd (errno = %#x, message = '%s')",
388d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin                __FUNCTION__, errno, strerror(errno));
389d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    }
390d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
391d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    return NULL;
392d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin}
393d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
394d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkinstatic void CameraMetadata_dump(JNIEnv *env, jobject thiz) {
395d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    ALOGV("%s", __FUNCTION__);
396d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz);
397d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    if (metadata == NULL) {
398d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        return;
399d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    }
400d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
401d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    /*
402d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     * Create a socket pair for local streaming read/writes.
403d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     *
404d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     * The metadata will be dumped into the write side,
405d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     * and then read back out (and logged) via the read side.
406d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     */
407d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
408d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    int writeFd, readFd;
409d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    {
410d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
411d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        int sv[2];
412d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        if (socketpair(AF_LOCAL, SOCK_STREAM, /*protocol*/0, &sv[0]) < 0) {
413d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin            jniThrowExceptionFmt(env, "java/io/IOException",
414d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin                    "Failed to create socketpair (errno = %#x, message = '%s')",
415d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin                    errno, strerror(errno));
416d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin            return;
417d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        }
418d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        writeFd = sv[0];
419d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        readFd = sv[1];
420d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    }
421d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
422d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    /*
423d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     * Create a thread for doing the writing.
424d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     *
425d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     * The reading and writing must be concurrent, otherwise
426d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     * the write will block forever once it exhausts the capped
427d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     * buffer size (from getsockopt).
428d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     */
429d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    pthread_t writeThread;
430d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    DumpMetadataParams params = {
431d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        writeFd,
432d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        metadata
433d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    };
434d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
435d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    {
436d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        int threadRet = pthread_create(&writeThread, /*attr*/NULL,
437d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin                CameraMetadata_writeMetadataThread, (void*)&params);
438d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
439d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        if (threadRet != 0) {
440d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin            close(writeFd);
441d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
442d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin            jniThrowExceptionFmt(env, "java/io/IOException",
443d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin                    "Failed to create thread for writing (errno = %#x, message = '%s')",
444d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin                    threadRet, strerror(threadRet));
445d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        }
446d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    }
447d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
448d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    /*
449d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     * Read out a byte until stream is complete. Write completed lines
450d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     * to ALOG.
451d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     */
452d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    {
453d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        char out[] = {'\0', '\0'}; // large enough to append as a string
454d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        String8 logLine;
455d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
456d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        // Read one byte at a time! Very slow but avoids complicated \n scanning.
457d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        ssize_t res;
458d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        while ((res = TEMP_FAILURE_RETRY(read(readFd, &out[0], /*count*/1))) > 0) {
459d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin            if (out[0] == '\n') {
460d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin                ALOGD("%s", logLine.string());
461d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin                logLine.clear();
462d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin            } else {
463d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin                logLine.append(out);
464d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin            }
465d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        }
466d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
467d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        if (res < 0) {
468d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin            jniThrowExceptionFmt(env, "java/io/IOException",
469d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin                    "Failed to read from fd (errno = %#x, message = '%s')",
470d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin                    errno, strerror(errno));
471d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin            //return;
472d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        } else if (!logLine.isEmpty()) {
473d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin            ALOGD("%s", logLine.string());
474d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        }
475d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    }
476d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
477d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    int res;
478d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
479d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    // Join until thread finishes. Ensures params/metadata is valid until then.
480d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    if ((res = pthread_join(writeThread, /*retval*/NULL)) != 0) {
481d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        ALOGE("%s: Failed to join thread (errno = %#x, message = '%s')",
482d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin                __FUNCTION__, res, strerror(res));
483d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    }
484d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin}
485d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
48670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinstatic void CameraMetadata_readFromParcel(JNIEnv *env, jobject thiz, jobject parcel) {
48770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    ALOGV("%s", __FUNCTION__);
48870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz);
48970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    if (metadata == NULL) {
49070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        return;
49170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    }
49270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
49370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    Parcel* parcelNative = parcelForJavaObject(env, parcel);
49470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    if (parcelNative == NULL) {
49570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        jniThrowNullPointerException(env, "parcel");
49670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        return;
49770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    }
49870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
49970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    status_t err;
50070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    if ((err = metadata->readFromParcel(parcelNative)) != OK) {
50170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
50270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin                             "Failed to read from parcel (error code %d)", err);
50370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        return;
50470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    }
50570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin}
50670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
50770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinstatic void CameraMetadata_writeToParcel(JNIEnv *env, jobject thiz, jobject parcel) {
50870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    ALOGV("%s", __FUNCTION__);
50970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz);
51070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    if (metadata == NULL) {
51170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        return;
51270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    }
51370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
51470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    Parcel* parcelNative = parcelForJavaObject(env, parcel);
51570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    if (parcelNative == NULL) {
51670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        jniThrowNullPointerException(env, "parcel");
51770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        return;
51870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    }
51970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
52070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    status_t err;
52170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    if ((err = metadata->writeToParcel(parcelNative)) != OK) {
52270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
52370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin                                  "Failed to write to parcel (error code %d)", err);
52470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        return;
52570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    }
52670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin}
52770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
52870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin} // extern "C"
52970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
53070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin//-------------------------------------------------
53170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
53276f6a86de25e1bf74717e047e55fd44b089673f3Daniel Micaystatic const JNINativeMethod gCameraMetadataMethods[] = {
533b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin// static methods
53470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin  { "nativeClassInit",
53570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    "()V",
53670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    (void *)CameraMetadata_classInit },
537c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk  { "nativeGetAllVendorKeys",
538c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    "(Ljava/lang/Class;)Ljava/util/ArrayList;",
539c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    (void *)CameraMetadata_getAllVendorKeys},
540b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin  { "nativeGetTagFromKey",
541b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    "(Ljava/lang/String;)I",
542b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    (void *)CameraMetadata_getTagFromKey },
543b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin  { "nativeGetTypeFromTag",
544b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    "(I)I",
545b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    (void *)CameraMetadata_getTypeFromTag },
54685c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk  { "nativeSetupGlobalVendorTagDescriptor",
54785c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk    "()I",
54885c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk    (void*)CameraMetadata_setupGlobalVendorTagDescriptor },
549b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin// instance methods
55070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin  { "nativeAllocate",
55170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    "()J",
55270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    (void*)CameraMetadata_allocate },
55370c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala  { "nativeAllocateCopy",
55470c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    "(L" CAMERA_METADATA_CLASS_NAME ";)J",
55570c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    (void *)CameraMetadata_allocateCopy },
55670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin  { "nativeIsEmpty",
55770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    "()Z",
55870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    (void*)CameraMetadata_isEmpty },
55970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin  { "nativeGetEntryCount",
56070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    "()I",
56170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    (void*)CameraMetadata_getEntryCount },
56270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin  { "nativeClose",
56370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    "()V",
56470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    (void*)CameraMetadata_close },
56570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin  { "nativeSwap",
56670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    "(L" CAMERA_METADATA_CLASS_NAME ";)V",
56770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    (void *)CameraMetadata_swap },
568b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin  { "nativeReadValues",
569b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    "(I)[B",
570b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    (void *)CameraMetadata_readValues },
571b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin  { "nativeWriteValues",
572b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    "(I[B)V",
573b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    (void *)CameraMetadata_writeValues },
574d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin  { "nativeDump",
575d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    "()V",
576d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    (void *)CameraMetadata_dump },
577b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin// Parcelable interface
57870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin  { "nativeReadFromParcel",
57970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    "(Landroid/os/Parcel;)V",
58070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    (void *)CameraMetadata_readFromParcel },
58170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin  { "nativeWriteToParcel",
58270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    "(Landroid/os/Parcel;)V",
58370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    (void *)CameraMetadata_writeToParcel },
58470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin};
58570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
58670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinstruct field {
58770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    const char *class_name;
58870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    const char *field_name;
58970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    const char *field_type;
59070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    jfieldID   *jfield;
59170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin};
59270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
59370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinstatic int find_fields(JNIEnv *env, field *fields, int count)
59470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin{
59570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    for (int i = 0; i < count; i++) {
59670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        field *f = &fields[i];
59770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        jclass clazz = env->FindClass(f->class_name);
59870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        if (clazz == NULL) {
59970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin            ALOGE("Can't find %s", f->class_name);
60070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin            return -1;
60170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        }
60270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
60370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        jfieldID field = env->GetFieldID(clazz, f->field_name, f->field_type);
60470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        if (field == NULL) {
60570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin            ALOGE("Can't find %s.%s", f->class_name, f->field_name);
60670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin            return -1;
60770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        }
60870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
60970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        *(f->jfield) = field;
61070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    }
61170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
61270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    return 0;
61370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin}
61470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
61570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin// Get all the required offsets in java class and register native functions
6162f1a2e423e0fbb64467d6fcfa4e82c6384f31210Eino-Ville Talvalaint register_android_hardware_camera2_CameraMetadata(JNIEnv *env)
61770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin{
618c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk
619c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    // Store global references to Key-related classes and methods used natively
620c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    jclass characteristicsKeyClazz = FindClassOrDie(env, CHARACTERISTICS_KEY_CLASS_NAME);
621c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    jclass requestKeyClazz = FindClassOrDie(env, REQUEST_KEY_CLASS_NAME);
622c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    jclass resultKeyClazz = FindClassOrDie(env, RESULT_KEY_CLASS_NAME);
623c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    gMetadataOffsets.mCharacteristicsKey = MakeGlobalRefOrDie(env, characteristicsKeyClazz);
624c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    gMetadataOffsets.mRequestKey = MakeGlobalRefOrDie(env, requestKeyClazz);
625c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    gMetadataOffsets.mResultKey = MakeGlobalRefOrDie(env, resultKeyClazz);
626c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    gMetadataOffsets.mCharacteristicsConstr = GetMethodIDOrDie(env,
627c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk            gMetadataOffsets.mCharacteristicsKey, "<init>",
628c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk            "(Ljava/lang/String;Ljava/lang/Class;)V");
629c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    gMetadataOffsets.mRequestConstr = GetMethodIDOrDie(env,
630c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk            gMetadataOffsets.mRequestKey, "<init>", "(Ljava/lang/String;Ljava/lang/Class;)V");
631c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    gMetadataOffsets.mResultConstr = GetMethodIDOrDie(env,
632c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk            gMetadataOffsets.mResultKey, "<init>", "(Ljava/lang/String;Ljava/lang/Class;)V");
633c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk
634c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    // Store global references for primitive array types used by Keys
635c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    jclass byteClazz = FindClassOrDie(env, "[B");
636c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    jclass int32Clazz = FindClassOrDie(env, "[I");
637c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    jclass floatClazz = FindClassOrDie(env, "[F");
638c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    jclass int64Clazz = FindClassOrDie(env, "[J");
639c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    jclass doubleClazz = FindClassOrDie(env, "[D");
640c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    jclass rationalClazz = FindClassOrDie(env, "[Landroid/util/Rational;");
641c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    gMetadataOffsets.mByteArray = MakeGlobalRefOrDie(env, byteClazz);
642c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    gMetadataOffsets.mInt32Array = MakeGlobalRefOrDie(env, int32Clazz);
643c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    gMetadataOffsets.mFloatArray = MakeGlobalRefOrDie(env, floatClazz);
644c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    gMetadataOffsets.mInt64Array = MakeGlobalRefOrDie(env, int64Clazz);
645c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    gMetadataOffsets.mDoubleArray = MakeGlobalRefOrDie(env, doubleClazz);
646c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    gMetadataOffsets.mRationalArray = MakeGlobalRefOrDie(env, rationalClazz);
647c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk
648c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    // Store global references for ArrayList methods used
649c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    jclass arrayListClazz = FindClassOrDie(env, "java/util/ArrayList");
650c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    gMetadataOffsets.mArrayList = MakeGlobalRefOrDie(env, arrayListClazz);
651c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    gMetadataOffsets.mArrayListConstr = GetMethodIDOrDie(env, gMetadataOffsets.mArrayList,
652c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk            "<init>", "(I)V");
653c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    gMetadataOffsets.mArrayListAdd = GetMethodIDOrDie(env, gMetadataOffsets.mArrayList,
654c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk            "add", "(Ljava/lang/Object;)Z");
655c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk
65670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    // Register native functions
657ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    return RegisterMethodsOrDie(env,
65870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin            CAMERA_METADATA_CLASS_NAME,
65970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin            gCameraMetadataMethods,
66070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin            NELEM(gCameraMetadataMethods));
66170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin}
66270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
66370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinextern "C" {
664c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk
66570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinstatic void CameraMetadata_classInit(JNIEnv *env, jobject thiz) {
66670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    // XX: Why do this separately instead of doing it in the register function?
66770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    ALOGV("%s", __FUNCTION__);
66870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
66970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    field fields_to_find[] = {
67070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        { CAMERA_METADATA_CLASS_NAME, "mMetadataPtr", "J", &fields.metadata_ptr },
67170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    };
67270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
67370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    // Do this here instead of in register_native_methods,
67470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    // since otherwise it will fail to find the fields.
67570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    if (find_fields(env, fields_to_find, NELEM(fields_to_find)) < 0)
67670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        return;
67770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
6780f0b4919667f418b249c497f5ad3e83fdf4437e5Andreas Gampe    env->FindClass(CAMERA_METADATA_CLASS_NAME);
67970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin}
680b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
681c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunkstatic jobject CameraMetadata_getAllVendorKeys(JNIEnv* env, jobject thiz, jclass keyType) {
682c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk
683c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    // Get all vendor tags
684c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    sp<VendorTagDescriptor> vTags = VendorTagDescriptor::getGlobalVendorTagDescriptor();
685c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    if (vTags.get() == nullptr) {
686c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk        // No vendor tags.
687c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk        return NULL;
688c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    }
689c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk
690c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    int count = vTags->getTagCount();
691c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    if (count <= 0) {
692c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk        // No vendor tags.
693c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk        return NULL;
694c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    }
695c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk
696c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    std::vector<uint32_t> tagIds(count, /*initializer value*/0);
697c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    vTags->getTagArray(&tagIds[0]);
698c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk
699c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    // Which key class/constructor should we use?
700c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    jclass keyClazz;
701c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    jmethodID keyConstr;
702c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    if (env->IsSameObject(keyType, gMetadataOffsets.mCharacteristicsKey)) {
703c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk        keyClazz = gMetadataOffsets.mCharacteristicsKey;
704c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk        keyConstr = gMetadataOffsets.mCharacteristicsConstr;
705c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    } else if (env->IsSameObject(keyType, gMetadataOffsets.mResultKey)) {
706c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk        keyClazz = gMetadataOffsets.mResultKey;
707c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk        keyConstr = gMetadataOffsets.mResultConstr;
708c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    } else if (env->IsSameObject(keyType, gMetadataOffsets.mRequestKey)) {
709c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk        keyClazz = gMetadataOffsets.mRequestKey;
710c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk        keyConstr = gMetadataOffsets.mRequestConstr;
711c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    } else {
712c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk        jniThrowException(env, "java/lang/IllegalArgumentException",
713c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk                "Invalid key class given as argument.");
714c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk        return NULL;
715c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    }
716c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk
717c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    // Allocate arrayList to return
718c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    jobject arrayList = env->NewObject(gMetadataOffsets.mArrayList,
719c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk            gMetadataOffsets.mArrayListConstr, static_cast<jint>(count));
720c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    if (env->ExceptionCheck()) {
721c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk        return NULL;
722c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    }
723c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk
724c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    for (uint32_t id : tagIds) {
725c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk        const char* section = vTags->getSectionName(id);
726c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk        const char* tag = vTags->getTagName(id);
727c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk        int type = vTags->getTagType(id);
728c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk
729c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk        size_t totalLen = strlen(section) + strlen(tag) + 2;
730c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk        std::vector<char> fullName(totalLen, 0);
731c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk        snprintf(&fullName[0], totalLen, "%s.%s", section, tag);
732c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk
733c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk        jstring name = env->NewStringUTF(&fullName[0]);
734c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk
735c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk        if (env->ExceptionCheck()) {
736c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk            return NULL;
737c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk        }
738c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk
739c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk        jclass valueClazz;
740c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk        switch (type) {
741c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk            case TYPE_BYTE:
742c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk                valueClazz = gMetadataOffsets.mByteArray;
743c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk                break;
744c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk            case TYPE_INT32:
745c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk                valueClazz = gMetadataOffsets.mInt32Array;
746c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk                break;
747c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk            case TYPE_FLOAT:
748c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk                valueClazz = gMetadataOffsets.mFloatArray;
749c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk                break;
750c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk            case TYPE_INT64:
751c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk                valueClazz = gMetadataOffsets.mInt64Array;
752c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk                break;
753c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk            case TYPE_DOUBLE:
754c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk                valueClazz = gMetadataOffsets.mDoubleArray;
755c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk                break;
756c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk            case TYPE_RATIONAL:
757c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk                valueClazz = gMetadataOffsets.mRationalArray;
758c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk                break;
759c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk            default:
760c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk                jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
761c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk                        "Invalid type %d given for key %s", type, &fullName[0]);
762c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk                return NULL;
763c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk        }
764c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk
765c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk        jobject key = env->NewObject(keyClazz, keyConstr, name, valueClazz);
766c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk        if (env->ExceptionCheck()) {
767c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk            return NULL;
768c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk        }
769c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk
770c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk        env->CallBooleanMethod(arrayList, gMetadataOffsets.mArrayListAdd, key);
771c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk        if (env->ExceptionCheck()) {
772c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk            return NULL;
773c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk        }
774c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk
775c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk        env->DeleteLocalRef(name);
776c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk        env->DeleteLocalRef(key);
777c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    }
778c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk
779c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk    return arrayList;
780c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk}
781c620eb7e864e5505f5a6f867223fa8e525669d0bRuben Brunk
782b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkinstatic jint CameraMetadata_getTagFromKey(JNIEnv *env, jobject thiz, jstring keyName) {
783b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
784b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    ScopedUtfChars keyScoped(env, keyName);
785b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    const char *key = keyScoped.c_str();
786b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    if (key == NULL) {
787b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        // exception thrown by ScopedUtfChars
788b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        return 0;
789b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
790b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    size_t keyLength = strlen(key);
791b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
792b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    ALOGV("%s (key = '%s')", __FUNCTION__, key);
793b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
79432ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk    sp<VendorTagDescriptor> vTags = VendorTagDescriptor::getGlobalVendorTagDescriptor();
79532ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk
7963c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    SortedVector<String8> vendorSections;
7973c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    size_t vendorSectionCount = 0;
7983c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
799feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (vTags != NULL) {
8003c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        vendorSections = vTags->getAllSectionNames();
8013c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        vendorSectionCount = vendorSections.size();
8023c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    }
80332ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk
804b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    // First, find the section by the longest string match
805b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    const char *section = NULL;
806b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    size_t sectionIndex = 0;
807b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    size_t sectionLength = 0;
80832ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk    size_t totalSectionCount = ANDROID_SECTION_COUNT + vendorSectionCount;
80932ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk    for (size_t i = 0; i < totalSectionCount; ++i) {
81032ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk
81132ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk        const char *str = (i < ANDROID_SECTION_COUNT) ? camera_metadata_section_names[i] :
81232ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk                vendorSections[i - ANDROID_SECTION_COUNT].string();
813ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe        if (kIsDebug) {
814ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe            ALOGV("%s: Trying to match against section '%s'", __FUNCTION__, str);
815ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe        }
816b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        if (strstr(key, str) == key) { // key begins with the section name
817b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            size_t strLength = strlen(str);
818b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
819ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe            if (kIsDebug) {
820ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe                ALOGV("%s: Key begins with section name", __FUNCTION__);
821ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe            }
822b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
823b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            // section name is the longest we've found so far
824b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            if (section == NULL || sectionLength < strLength) {
825b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                section = str;
826b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                sectionIndex = i;
827b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                sectionLength = strLength;
828b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
829ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe                if (kIsDebug) {
830ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe                    ALOGV("%s: Found new best section (%s)", __FUNCTION__, section);
831ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe                }
832b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            }
833b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        }
834b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
835b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
836b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    // TODO: Make above get_camera_metadata_section_from_name ?
837b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
838b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    if (section == NULL) {
839b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
840b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                             "Could not find section name for key '%s')", key);
841b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        return 0;
842b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    } else {
84346d8444631b4b1253a76bfcc78a29d26014d022fDan Albert        ALOGV("%s: Found matched section '%s' (%zu)",
844b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin              __FUNCTION__, section, sectionIndex);
845b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
846b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
847b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    // Get the tag name component of the key
848b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    const char *keyTagName = key + sectionLength + 1; // x.y.z -> z
849b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    if (sectionLength + 1 >= keyLength) {
850b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
851b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                             "Key length too short for key '%s')", key);
85232ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk        return 0;
853b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
854b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
855b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    // Match rest of name against the tag names in that section only
85632ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk    uint32_t tag = 0;
85732ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk    if (sectionIndex < ANDROID_SECTION_COUNT) {
85832ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk        // Match built-in tags (typically android.*)
85932ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk        uint32_t tagBegin, tagEnd; // [tagBegin, tagEnd)
86032ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk        tagBegin = camera_metadata_section_bounds[sectionIndex][0];
86132ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk        tagEnd = camera_metadata_section_bounds[sectionIndex][1];
86232ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk
86332ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk        for (tag = tagBegin; tag < tagEnd; ++tag) {
86432ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk            const char *tagName = get_camera_metadata_tag_name(tag);
86532ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk
86632ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk            if (strcmp(keyTagName, tagName) == 0) {
86732ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk                ALOGV("%s: Found matched tag '%s' (%d)",
86832ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk                      __FUNCTION__, tagName, tag);
86932ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk                break;
87032ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk            }
87132ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk        }
87232ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk
87332ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk        if (tag == tagEnd) {
87432ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk            jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
87532ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk                                 "Could not find tag name for key '%s')", key);
87632ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk            return 0;
87732ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk        }
878feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    } else if (vTags != NULL) {
87932ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk        // Match vendor tags (typically com.*)
88032ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk        const String8 sectionName(section);
88132ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk        const String8 tagName(keyTagName);
88232ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk
88332ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk        status_t res = OK;
88432ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk        if ((res = vTags->lookupTag(tagName, sectionName, &tag)) != OK) {
88532ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk            jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
88632ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk                    "%s: No vendor tag matches key '%s'", __FUNCTION__, key);
88732ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk            return 0;
888b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        }
889b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
890b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
891b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    // TODO: Make above get_camera_metadata_tag_from_name ?
892b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
893b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    return tag;
894b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin}
895b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
896b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkinstatic jint CameraMetadata_getTypeFromTag(JNIEnv *env, jobject thiz, jint tag) {
897b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    int tagType = get_camera_metadata_tag_type(tag);
898b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    if (tagType == -1) {
899b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
900b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                             "Tag (%d) did not have a type", tag);
901b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        return -1;
902b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
903b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
904b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    return tagType;
905b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin}
906b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
90785c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunkstatic jint CameraMetadata_setupGlobalVendorTagDescriptor(JNIEnv *env, jobject thiz) {
90885c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk    const String16 NAME("media.camera");
9095d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala    sp<hardware::ICameraService> cameraService;
91085c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk    status_t err = getService(NAME, /*out*/&cameraService);
91185c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk
91285c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk    if (err != OK) {
91385c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk        ALOGE("%s: Failed to get camera service, received error %s (%d)", __FUNCTION__,
91485c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk                strerror(-err), err);
9155d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala        return hardware::ICameraService::ERROR_DISCONNECTED;
91685c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk    }
91785c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk
9185d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala    sp<VendorTagDescriptor> desc = new VendorTagDescriptor();
9195d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala    binder::Status res = cameraService->getCameraVendorTagDescriptor(/*out*/desc.get());
92085c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk
9215f2f804a19ecf511d069ebbda6cc69a07fa7b13dEino-Ville Talvala    if (res.serviceSpecificErrorCode() == hardware::ICameraService::ERROR_DISCONNECTED) {
9225f2f804a19ecf511d069ebbda6cc69a07fa7b13dEino-Ville Talvala        // No camera module available, not an error on devices with no cameras
9235614cbe64493308dc5330eac5d5ba17202013dc4Igor Murashkin        VendorTagDescriptor::clearGlobalVendorTagDescriptor();
9245614cbe64493308dc5330eac5d5ba17202013dc4Igor Murashkin        return OK;
9255d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala    } else if (!res.isOk()) {
9265f2f804a19ecf511d069ebbda6cc69a07fa7b13dEino-Ville Talvala        VendorTagDescriptor::clearGlobalVendorTagDescriptor();
9275f2f804a19ecf511d069ebbda6cc69a07fa7b13dEino-Ville Talvala        ALOGE("%s: Failed to setup vendor tag descriptors: %s",
9285f2f804a19ecf511d069ebbda6cc69a07fa7b13dEino-Ville Talvala                __FUNCTION__, res.toString8().string());
9295d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala        return res.serviceSpecificErrorCode();
93085c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk    }
93185c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk
93285c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk    err = VendorTagDescriptor::setAsGlobalVendorTagDescriptor(desc);
93385c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk
9345d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala    if (err != OK) {
9355d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala        return hardware::ICameraService::ERROR_INVALID_OPERATION;
9365d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala    }
9375d2d7788f1759b0f3d2c057af0b3ea61b0354feeEino-Ville Talvala    return OK;
93885c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk}
93985c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk
94070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin} // extern "C"
941