android_hardware_camera2_CameraMetadata.cpp revision 70c2207c34cf0e6b3b383b1b1500ff5385aa51a6
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
19b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin// #define LOG_NNDEBUG 0
2070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin#define LOG_TAG "CameraMetadata-JNI"
2170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin#include <utils/Log.h>
2270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
2370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin#include "jni.h"
2470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin#include "JNIHelp.h"
2570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin#include "android_os_Parcel.h"
2670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin#include "android_runtime/AndroidRuntime.h"
2770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
2870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin#include <camera/CameraMetadata.h>
29b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin#include <nativehelper/ScopedUtfChars.h>
30b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin#include <nativehelper/ScopedPrimitiveArray.h>
31b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
32b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin#if defined(LOG_NNDEBUG)
33b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin#if !LOG_NNDEBUG
34b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin#define ALOGVV ALOGV
35b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin#endif
36b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin#else
37b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin#define ALOGVV(...)
38b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin#endif
3970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
4070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin// fully-qualified class name
4170c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala#define CAMERA_METADATA_CLASS_NAME "android/hardware/camera2/impl/CameraMetadataNative"
4270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
4370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinusing namespace android;
4470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
4570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinstruct fields_t {
4670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    jfieldID    metadata_ptr;
4770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin};
4870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
4970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinstatic fields_t fields;
5070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
51b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkinnamespace {
52b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkinstruct Helpers {
53b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    static size_t getTypeSize(uint8_t type) {
54b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        if (type >= NUM_TYPES) {
55b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            ALOGE("%s: Invalid type specified (%ud)", __FUNCTION__, type);
56b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            return static_cast<size_t>(-1);
57b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        }
58b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
59b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        return camera_metadata_type_size[type];
60b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
61b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
62b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    static status_t updateAny(CameraMetadata *metadata,
63b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                          uint32_t tag,
64b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                          uint32_t type,
65b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                          const void *data,
66b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                          size_t dataBytes) {
67b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
68b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        if (type >= NUM_TYPES) {
69b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            ALOGE("%s: Invalid type specified (%ud)", __FUNCTION__, type);
70b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            return INVALID_OPERATION;
71b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        }
72b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
73b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        size_t typeSize = getTypeSize(type);
74b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
75b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        if (dataBytes % typeSize != 0) {
76b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            ALOGE("%s: Expected dataBytes (%ud) to be divisible by typeSize "
77b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                  "(%ud)", __FUNCTION__, dataBytes, typeSize);
78b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            return BAD_VALUE;
79b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        }
80b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
81b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        size_t dataCount = dataBytes / typeSize;
82b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
83b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        switch(type) {
84b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin#define METADATA_UPDATE(runtime_type, compile_type)                            \
85b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            case runtime_type: {                                               \
86b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                const compile_type *dataPtr =                                  \
87b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                        static_cast<const compile_type*>(data);                \
88b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                return metadata->update(tag, dataPtr, dataCount);              \
89b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            }                                                                  \
90b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
91b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            METADATA_UPDATE(TYPE_BYTE,     uint8_t);
92b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            METADATA_UPDATE(TYPE_INT32,    int32_t);
93b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            METADATA_UPDATE(TYPE_FLOAT,    float);
94b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            METADATA_UPDATE(TYPE_INT64,    int64_t);
95b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            METADATA_UPDATE(TYPE_DOUBLE,   double);
96b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            METADATA_UPDATE(TYPE_RATIONAL, camera_metadata_rational_t);
97b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
98b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            default: {
99b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                // unreachable
100b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                ALOGE("%s: Unreachable", __FUNCTION__);
101b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                return INVALID_OPERATION;
102b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            }
103b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        }
104b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
105b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin#undef METADATA_UPDATE
106b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
107b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin};
108b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin} // namespace {}
109b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
11070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinextern "C" {
11170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
11270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinstatic void CameraMetadata_classInit(JNIEnv *env, jobject thiz);
113b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkinstatic jint CameraMetadata_getTagFromKey(JNIEnv *env, jobject thiz, jstring keyName);
114b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkinstatic jint CameraMetadata_getTypeFromTag(JNIEnv *env, jobject thiz, jint tag);
11570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
11670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin// Less safe access to native pointer. Does NOT throw any Java exceptions if NULL.
11770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinstatic CameraMetadata* CameraMetadata_getPointerNoThrow(JNIEnv *env, jobject thiz) {
11870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
11970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    if (thiz == NULL) {
12070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        return NULL;
12170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    }
12270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
12370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    return reinterpret_cast<CameraMetadata*>(env->GetLongField(thiz, fields.metadata_ptr));
12470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin}
12570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
12670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin// Safe access to native pointer from object. Throws if not possible to access.
12770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinstatic CameraMetadata* CameraMetadata_getPointerThrow(JNIEnv *env, jobject thiz,
12870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin                                                 const char* argName = "this") {
12970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
13070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    if (thiz == NULL) {
13170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        ALOGV("%s: Throwing java.lang.NullPointerException for null reference",
13270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin              __FUNCTION__);
13370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        jniThrowNullPointerException(env, argName);
13470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        return NULL;
13570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    }
13670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
13770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    CameraMetadata* metadata = CameraMetadata_getPointerNoThrow(env, thiz);
13870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    if (metadata == NULL) {
13970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        ALOGV("%s: Throwing java.lang.IllegalStateException for closed object",
14070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin              __FUNCTION__);
14170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        jniThrowException(env, "java/lang/IllegalStateException",
14270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin                            "Metadata object was already closed");
14370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        return NULL;
14470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    }
14570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
14670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    return metadata;
14770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin}
14870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
14970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinstatic jlong CameraMetadata_allocate(JNIEnv *env, jobject thiz) {
15070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    ALOGV("%s", __FUNCTION__);
15170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
15270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    return reinterpret_cast<jlong>(new CameraMetadata());
15370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin}
15470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
15570c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvalastatic jlong CameraMetadata_allocateCopy(JNIEnv *env, jobject thiz,
15670c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala        jobject other) {
15770c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    ALOGV("%s", __FUNCTION__);
15870c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala
15970c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    CameraMetadata* otherMetadata =
16070c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala            CameraMetadata_getPointerThrow(env, other, "other");
16170c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala
16270c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    // In case of exception, return
16370c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    if (otherMetadata == NULL) return NULL;
16470c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala
16570c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    // Clone native metadata and return new pointer
16670c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    return reinterpret_cast<jlong>(new CameraMetadata(*otherMetadata));
16770c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala}
16870c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala
16970c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala
17070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinstatic jboolean CameraMetadata_isEmpty(JNIEnv *env, jobject thiz) {
17170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    ALOGV("%s", __FUNCTION__);
17270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
17370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz);
17470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
17570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    if (metadata == NULL) {
17670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        ALOGW("%s: Returning early due to exception being thrown",
17770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin               __FUNCTION__);
17870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        return JNI_TRUE; // actually throws java exc.
17970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    }
18070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
18170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    jboolean empty = metadata->isEmpty();
18270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
18370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    ALOGV("%s: Empty returned %d, entry count was %d",
18470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin          __FUNCTION__, empty, metadata->entryCount());
18570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
18670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    return empty;
18770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin}
18870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
18970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinstatic jint CameraMetadata_getEntryCount(JNIEnv *env, jobject thiz) {
19070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    ALOGV("%s", __FUNCTION__);
19170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
19270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz);
19370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
19470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    if (metadata == NULL) return 0; // actually throws java exc.
19570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
19670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    return metadata->entryCount();
19770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin}
19870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
19970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin// idempotent. calling more than once has no effect.
20070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinstatic void CameraMetadata_close(JNIEnv *env, jobject thiz) {
20170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    ALOGV("%s", __FUNCTION__);
20270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
20370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    CameraMetadata* metadata = CameraMetadata_getPointerNoThrow(env, thiz);
20470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
20570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    if (metadata != NULL) {
20670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        delete metadata;
20770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        env->SetLongField(thiz, fields.metadata_ptr, 0);
20870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    }
20970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
21070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    LOG_ALWAYS_FATAL_IF(CameraMetadata_getPointerNoThrow(env, thiz) != NULL,
21170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin                        "Expected the native ptr to be 0 after #close");
21270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin}
21370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
21470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinstatic void CameraMetadata_swap(JNIEnv *env, jobject thiz, jobject other) {
21570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    ALOGV("%s", __FUNCTION__);
21670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
21770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz);
21870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
21970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    // order is important: we can't call another JNI method
22070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    // if there is an exception pending
22170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    if (metadata == NULL) return;
22270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
22370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    CameraMetadata* otherMetadata = CameraMetadata_getPointerThrow(env, other, "other");
22470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
22570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    if (otherMetadata == NULL) return;
22670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
22770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    metadata->swap(*otherMetadata);
22870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin}
22970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
230b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkinstatic jbyteArray CameraMetadata_readValues(JNIEnv *env, jobject thiz, jint tag) {
231b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    ALOGV("%s (tag = %d)", __FUNCTION__, tag);
232b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
233b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz);
234b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    if (metadata == NULL) return NULL;
235b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
236b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    int tagType = get_camera_metadata_tag_type(tag);
237b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    if (tagType == -1) {
238b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
239b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                             "Tag (%d) did not have a type", tag);
240b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        return NULL;
241b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
242b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    size_t tagSize = Helpers::getTypeSize(tagType);
243b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
244b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    camera_metadata_entry entry = metadata->find(tag);
245b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    if (entry.count == 0) {
246b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin         if (!metadata->exists(tag)) {
247b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin             ALOGV("%s: Tag %d does not have any entries", __FUNCTION__, tag);
248b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin             return NULL;
249b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin         } else {
250b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin             // OK: we will return a 0-sized array.
251b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin             ALOGV("%s: Tag %d had an entry, but it had 0 data", __FUNCTION__,
252b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                   tag);
253b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin         }
254b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
255b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
256b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    jsize byteCount = entry.count * tagSize;
257b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    jbyteArray byteArray = env->NewByteArray(byteCount);
258b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    if (env->ExceptionCheck()) return NULL;
259b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
260b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    // Copy into java array from native array
261b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    ScopedByteArrayRW arrayWriter(env, byteArray);
262b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    memcpy(arrayWriter.get(), entry.data.u8, byteCount);
263b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
264b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    return byteArray;
265b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin}
266b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
267b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkinstatic void CameraMetadata_writeValues(JNIEnv *env, jobject thiz, jint tag, jbyteArray src) {
268b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    ALOGV("%s (tag = %d)", __FUNCTION__, tag);
269b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
270b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz);
271b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    if (metadata == NULL) return;
272b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
273b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    int tagType = get_camera_metadata_tag_type(tag);
274b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    if (tagType == -1) {
275b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
276b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                             "Tag (%d) did not have a type", tag);
277b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        return;
278b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
279b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    size_t tagSize = Helpers::getTypeSize(tagType);
280b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
281b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    status_t res;
282b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
283b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    if (src == NULL) {
284b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        // If array is NULL, delete the entry
2853710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin        if (metadata->exists(tag)) {
2863710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin            res = metadata->erase(tag);
2873710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin            ALOGV("%s: Erase values (res = %d)", __FUNCTION__, res);
2883710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin        } else {
2893710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin            res = OK;
2903710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin            ALOGV("%s: Don't need to erase", __FUNCTION__);
2913710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin        }
292b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    } else {
293b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        // Copy from java array into native array
294b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        ScopedByteArrayRO arrayReader(env, src);
295b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        if (arrayReader.get() == NULL) return;
296b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
297b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        res = Helpers::updateAny(metadata, static_cast<uint32_t>(tag),
298b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                                 tagType, arrayReader.get(), arrayReader.size());
2993710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin
3003710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin        ALOGV("%s: Update values (res = %d)", __FUNCTION__, res);
301b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
302b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
303b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    if (res == OK) {
304b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        return;
305b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    } else if (res == BAD_VALUE) {
306b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
307b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                             "Src byte array was poorly formed");
308b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    } else if (res == INVALID_OPERATION) {
309b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
310b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                             "Internal error while trying to update metadata");
311b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    } else {
312b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
313b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                             "Unknown error (%d) while trying to update "
314b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                            "metadata", res);
315b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
316b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin}
317b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
31870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinstatic void CameraMetadata_readFromParcel(JNIEnv *env, jobject thiz, jobject parcel) {
31970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    ALOGV("%s", __FUNCTION__);
32070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz);
32170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    if (metadata == NULL) {
32270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        return;
32370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    }
32470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
32570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    Parcel* parcelNative = parcelForJavaObject(env, parcel);
32670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    if (parcelNative == NULL) {
32770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        jniThrowNullPointerException(env, "parcel");
32870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        return;
32970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    }
33070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
33170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    status_t err;
33270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    if ((err = metadata->readFromParcel(parcelNative)) != OK) {
33370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
33470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin                             "Failed to read from parcel (error code %d)", err);
33570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        return;
33670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    }
33770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin}
33870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
33970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinstatic void CameraMetadata_writeToParcel(JNIEnv *env, jobject thiz, jobject parcel) {
34070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    ALOGV("%s", __FUNCTION__);
34170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz);
34270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    if (metadata == NULL) {
34370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        return;
34470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    }
34570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
34670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    Parcel* parcelNative = parcelForJavaObject(env, parcel);
34770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    if (parcelNative == NULL) {
34870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        jniThrowNullPointerException(env, "parcel");
34970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        return;
35070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    }
35170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
35270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    status_t err;
35370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    if ((err = metadata->writeToParcel(parcelNative)) != OK) {
35470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
35570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin                                  "Failed to write to parcel (error code %d)", err);
35670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        return;
35770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    }
35870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin}
35970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
36070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin} // extern "C"
36170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
36270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin//-------------------------------------------------
36370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
36470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinstatic JNINativeMethod gCameraMetadataMethods[] = {
365b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin// static methods
36670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin  { "nativeClassInit",
36770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    "()V",
36870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    (void *)CameraMetadata_classInit },
369b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin  { "nativeGetTagFromKey",
370b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    "(Ljava/lang/String;)I",
371b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    (void *)CameraMetadata_getTagFromKey },
372b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin  { "nativeGetTypeFromTag",
373b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    "(I)I",
374b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    (void *)CameraMetadata_getTypeFromTag },
375b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin// instance methods
37670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin  { "nativeAllocate",
37770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    "()J",
37870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    (void*)CameraMetadata_allocate },
37970c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala  { "nativeAllocateCopy",
38070c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    "(L" CAMERA_METADATA_CLASS_NAME ";)J",
38170c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    (void *)CameraMetadata_allocateCopy },
38270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin  { "nativeIsEmpty",
38370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    "()Z",
38470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    (void*)CameraMetadata_isEmpty },
38570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin  { "nativeGetEntryCount",
38670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    "()I",
38770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    (void*)CameraMetadata_getEntryCount },
38870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin  { "nativeClose",
38970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    "()V",
39070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    (void*)CameraMetadata_close },
39170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin  { "nativeSwap",
39270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    "(L" CAMERA_METADATA_CLASS_NAME ";)V",
39370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    (void *)CameraMetadata_swap },
394b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin  { "nativeReadValues",
395b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    "(I)[B",
396b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    (void *)CameraMetadata_readValues },
397b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin  { "nativeWriteValues",
398b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    "(I[B)V",
399b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    (void *)CameraMetadata_writeValues },
400b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin// Parcelable interface
40170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin  { "nativeReadFromParcel",
40270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    "(Landroid/os/Parcel;)V",
40370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    (void *)CameraMetadata_readFromParcel },
40470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin  { "nativeWriteToParcel",
40570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    "(Landroid/os/Parcel;)V",
40670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    (void *)CameraMetadata_writeToParcel },
40770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin};
40870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
40970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinstruct field {
41070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    const char *class_name;
41170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    const char *field_name;
41270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    const char *field_type;
41370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    jfieldID   *jfield;
41470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin};
41570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
41670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinstatic int find_fields(JNIEnv *env, field *fields, int count)
41770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin{
41870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    for (int i = 0; i < count; i++) {
41970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        field *f = &fields[i];
42070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        jclass clazz = env->FindClass(f->class_name);
42170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        if (clazz == NULL) {
42270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin            ALOGE("Can't find %s", f->class_name);
42370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin            return -1;
42470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        }
42570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
42670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        jfieldID field = env->GetFieldID(clazz, f->field_name, f->field_type);
42770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        if (field == NULL) {
42870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin            ALOGE("Can't find %s.%s", f->class_name, f->field_name);
42970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin            return -1;
43070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        }
43170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
43270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        *(f->jfield) = field;
43370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    }
43470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
43570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    return 0;
43670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin}
43770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
43870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin// Get all the required offsets in java class and register native functions
4392f1a2e423e0fbb64467d6fcfa4e82c6384f31210Eino-Ville Talvalaint register_android_hardware_camera2_CameraMetadata(JNIEnv *env)
44070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin{
44170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    // Register native functions
44270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    return AndroidRuntime::registerNativeMethods(env,
44370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin            CAMERA_METADATA_CLASS_NAME,
44470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin            gCameraMetadataMethods,
44570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin            NELEM(gCameraMetadataMethods));
44670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin}
44770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
44870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinextern "C" {
44970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinstatic void CameraMetadata_classInit(JNIEnv *env, jobject thiz) {
45070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    // XX: Why do this separately instead of doing it in the register function?
45170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    ALOGV("%s", __FUNCTION__);
45270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
45370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    field fields_to_find[] = {
45470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        { CAMERA_METADATA_CLASS_NAME, "mMetadataPtr", "J", &fields.metadata_ptr },
45570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    };
45670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
45770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    // Do this here instead of in register_native_methods,
45870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    // since otherwise it will fail to find the fields.
45970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    if (find_fields(env, fields_to_find, NELEM(fields_to_find)) < 0)
46070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        return;
46170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
46270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    jclass clazz = env->FindClass(CAMERA_METADATA_CLASS_NAME);
46370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin}
464b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
465b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkinstatic jint CameraMetadata_getTagFromKey(JNIEnv *env, jobject thiz, jstring keyName) {
466b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
467b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    ScopedUtfChars keyScoped(env, keyName);
468b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    const char *key = keyScoped.c_str();
469b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    if (key == NULL) {
470b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        // exception thrown by ScopedUtfChars
471b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        return 0;
472b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
473b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    size_t keyLength = strlen(key);
474b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
475b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    ALOGV("%s (key = '%s')", __FUNCTION__, key);
476b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
477b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    // First, find the section by the longest string match
478b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    const char *section = NULL;
479b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    size_t sectionIndex = 0;
480b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    size_t sectionLength = 0;
481b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    for (size_t i = 0; i < ANDROID_SECTION_COUNT; ++i) {
482b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        const char *str = camera_metadata_section_names[i];
483b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        ALOGVV("%s: Trying to match against section '%s'",
484b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin               __FUNCTION__, str);
485b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        if (strstr(key, str) == key) { // key begins with the section name
486b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            size_t strLength = strlen(str);
487b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
488b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            ALOGVV("%s: Key begins with section name", __FUNCTION__);
489b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
490b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            // section name is the longest we've found so far
491b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            if (section == NULL || sectionLength < strLength) {
492b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                section = str;
493b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                sectionIndex = i;
494b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                sectionLength = strLength;
495b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
496b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                ALOGVV("%s: Found new best section (idx %d)", __FUNCTION__, sectionIndex);
497b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            }
498b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        }
499b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
500b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
501b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    // TODO: vendor ext
502b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    // TODO: Make above get_camera_metadata_section_from_name ?
503b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
504b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    if (section == NULL) {
505b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
506b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                             "Could not find section name for key '%s')", key);
507b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        return 0;
508b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    } else {
509b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        ALOGV("%s: Found matched section '%s' (%d)",
510b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin              __FUNCTION__, section, sectionIndex);
511b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
512b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
513b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    // Get the tag name component of the key
514b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    const char *keyTagName = key + sectionLength + 1; // x.y.z -> z
515b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    if (sectionLength + 1 >= keyLength) {
516b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
517b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                             "Key length too short for key '%s')", key);
518b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
519b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
520b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    // Match rest of name against the tag names in that section only
521b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    uint32_t tagBegin, tagEnd; // [tagBegin, tagEnd)
522b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    tagBegin = camera_metadata_section_bounds[sectionIndex][0];
523b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    tagEnd = camera_metadata_section_bounds[sectionIndex][1];
524b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
525b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    uint32_t tag;
526b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    for (tag = tagBegin; tag < tagEnd; ++tag) {
527b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        const char *tagName = get_camera_metadata_tag_name(tag);
528b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
529b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        if (strcmp(keyTagName, tagName) == 0) {
530b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            ALOGV("%s: Found matched tag '%s' (%d)",
531b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                  __FUNCTION__, tagName, tag);
532b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            break;
533b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        }
534b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
535b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
536b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    // TODO: vendor ext
537b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    // TODO: Make above get_camera_metadata_tag_from_name ?
538b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
539b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    if (tag == tagEnd) {
540b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
541b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                             "Could not find tag name for key '%s')", key);
542b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        return 0;
543b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
544b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
545b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    return tag;
546b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin}
547b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
548b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkinstatic jint CameraMetadata_getTypeFromTag(JNIEnv *env, jobject thiz, jint tag) {
549b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    int tagType = get_camera_metadata_tag_type(tag);
550b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    if (tagType == -1) {
551b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
552b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                             "Tag (%d) did not have a type", tag);
553b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        return -1;
554b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
555b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
556b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    return tagType;
557b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin}
558b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
55970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin} // extern "C"
560