android_hardware_camera2_CameraMetadata.cpp revision 46d8444631b4b1253a76bfcc78a29d26014d022f
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"
2132ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk#include <utils/Errors.h>
2270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin#include <utils/Log.h>
2385c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk#include <utils/RefBase.h>
2432ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk#include <utils/Vector.h>
2532ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk#include <utils/SortedVector.h>
2632ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk#include <utils/KeyedVector.h>
2785c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk#include <string.h>
2870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
2970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin#include "jni.h"
3070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin#include "JNIHelp.h"
3170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin#include "android_os_Parcel.h"
3270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin#include "android_runtime/AndroidRuntime.h"
33f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk#include "android_runtime/android_hardware_camera2_CameraMetadata.h"
3470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
3585c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk#include <binder/IServiceManager.h>
3670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin#include <camera/CameraMetadata.h>
3785c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk#include <camera/ICameraService.h>
3885c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk#include <camera/VendorTagDescriptor.h>
39b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin#include <nativehelper/ScopedUtfChars.h>
40b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin#include <nativehelper/ScopedPrimitiveArray.h>
41b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
42d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin#include <sys/types.h> // for socketpair
43d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin#include <sys/socket.h> // for socketpair
44d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
45b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin#if defined(LOG_NNDEBUG)
46b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin#if !LOG_NNDEBUG
47b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin#define ALOGVV ALOGV
48b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin#endif
49b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin#else
50b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin#define ALOGVV(...)
51b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin#endif
5270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
5370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin// fully-qualified class name
5470c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala#define CAMERA_METADATA_CLASS_NAME "android/hardware/camera2/impl/CameraMetadataNative"
5570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
5670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinusing namespace android;
5770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
5870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinstruct fields_t {
5970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    jfieldID    metadata_ptr;
6070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin};
6170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
6270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinstatic fields_t fields;
6370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
64f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunknamespace android {
65f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk
66f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunkstatus_t CameraMetadata_getNativeMetadata(JNIEnv* env, jobject thiz,
67f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk        /*out*/CameraMetadata* metadata) {
68f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk    if (!thiz) {
69f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk        ALOGE("%s: Invalid java metadata object.", __FUNCTION__);
70f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk        return BAD_VALUE;
71f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk    }
72f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk
73f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk    if (!metadata) {
74f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk        ALOGE("%s: Invalid output metadata object.", __FUNCTION__);
75f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk        return BAD_VALUE;
76f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk    }
77f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk    CameraMetadata* nativePtr = reinterpret_cast<CameraMetadata*>(env->GetLongField(thiz,
78f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk            fields.metadata_ptr));
79f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk    if (nativePtr == NULL) {
80f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk        ALOGE("%s: Invalid native pointer in java metadata object.", __FUNCTION__);
81f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk        return BAD_VALUE;
82f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk    }
83f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk    *metadata = *nativePtr;
84f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk    return OK;
85f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk}
86f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk
87f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk} /*namespace android*/
88f967a5486a78db244624fde4c105aa5e6fa914b9Ruben Brunk
89b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkinnamespace {
90b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkinstruct Helpers {
91b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    static size_t getTypeSize(uint8_t type) {
92b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        if (type >= NUM_TYPES) {
93b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            ALOGE("%s: Invalid type specified (%ud)", __FUNCTION__, type);
94b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            return static_cast<size_t>(-1);
95b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        }
96b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
97b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        return camera_metadata_type_size[type];
98b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
99b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
100b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    static status_t updateAny(CameraMetadata *metadata,
101b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                          uint32_t tag,
102b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                          uint32_t type,
103b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                          const void *data,
104b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                          size_t dataBytes) {
105b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
106b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        if (type >= NUM_TYPES) {
107b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            ALOGE("%s: Invalid type specified (%ud)", __FUNCTION__, type);
108b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            return INVALID_OPERATION;
109b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        }
110b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
111b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        size_t typeSize = getTypeSize(type);
112b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
113b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        if (dataBytes % typeSize != 0) {
11446d8444631b4b1253a76bfcc78a29d26014d022fDan Albert            ALOGE("%s: Expected dataBytes (%zu) to be divisible by typeSize "
11546d8444631b4b1253a76bfcc78a29d26014d022fDan Albert                  "(%zu)", __FUNCTION__, dataBytes, typeSize);
116b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            return BAD_VALUE;
117b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        }
118b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
119b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        size_t dataCount = dataBytes / typeSize;
120b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
121b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        switch(type) {
122b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin#define METADATA_UPDATE(runtime_type, compile_type)                            \
123b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            case runtime_type: {                                               \
124b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                const compile_type *dataPtr =                                  \
125b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                        static_cast<const compile_type*>(data);                \
126b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                return metadata->update(tag, dataPtr, dataCount);              \
127b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            }                                                                  \
128b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
129b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            METADATA_UPDATE(TYPE_BYTE,     uint8_t);
130b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            METADATA_UPDATE(TYPE_INT32,    int32_t);
131b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            METADATA_UPDATE(TYPE_FLOAT,    float);
132b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            METADATA_UPDATE(TYPE_INT64,    int64_t);
133b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            METADATA_UPDATE(TYPE_DOUBLE,   double);
134b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            METADATA_UPDATE(TYPE_RATIONAL, camera_metadata_rational_t);
135b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
136b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            default: {
137b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                // unreachable
138b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                ALOGE("%s: Unreachable", __FUNCTION__);
139b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                return INVALID_OPERATION;
140b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            }
141b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        }
142b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
143b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin#undef METADATA_UPDATE
144b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
145b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin};
146b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin} // namespace {}
147b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
14870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinextern "C" {
14970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
15070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinstatic void CameraMetadata_classInit(JNIEnv *env, jobject thiz);
151b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkinstatic jint CameraMetadata_getTagFromKey(JNIEnv *env, jobject thiz, jstring keyName);
152b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkinstatic jint CameraMetadata_getTypeFromTag(JNIEnv *env, jobject thiz, jint tag);
15385c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunkstatic jint CameraMetadata_setupGlobalVendorTagDescriptor(JNIEnv *env, jobject thiz);
15470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
15570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin// Less safe access to native pointer. Does NOT throw any Java exceptions if NULL.
15670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinstatic CameraMetadata* CameraMetadata_getPointerNoThrow(JNIEnv *env, jobject thiz) {
15770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
15870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    if (thiz == NULL) {
15970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        return NULL;
16070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    }
16170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
16270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    return reinterpret_cast<CameraMetadata*>(env->GetLongField(thiz, fields.metadata_ptr));
16370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin}
16470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
16570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin// Safe access to native pointer from object. Throws if not possible to access.
16670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinstatic CameraMetadata* CameraMetadata_getPointerThrow(JNIEnv *env, jobject thiz,
16770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin                                                 const char* argName = "this") {
16870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
16970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    if (thiz == NULL) {
17070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        ALOGV("%s: Throwing java.lang.NullPointerException for null reference",
17170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin              __FUNCTION__);
17270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        jniThrowNullPointerException(env, argName);
17370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        return NULL;
17470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    }
17570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
17670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    CameraMetadata* metadata = CameraMetadata_getPointerNoThrow(env, thiz);
17770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    if (metadata == NULL) {
17870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        ALOGV("%s: Throwing java.lang.IllegalStateException for closed object",
17970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin              __FUNCTION__);
18070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        jniThrowException(env, "java/lang/IllegalStateException",
18170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin                            "Metadata object was already closed");
18270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        return NULL;
18370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    }
18470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
18570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    return metadata;
18670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin}
18770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
18870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinstatic jlong CameraMetadata_allocate(JNIEnv *env, jobject thiz) {
18970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    ALOGV("%s", __FUNCTION__);
19070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
19170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    return reinterpret_cast<jlong>(new CameraMetadata());
19270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin}
19370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
19470c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvalastatic jlong CameraMetadata_allocateCopy(JNIEnv *env, jobject thiz,
19570c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala        jobject other) {
19670c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    ALOGV("%s", __FUNCTION__);
19770c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala
19870c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    CameraMetadata* otherMetadata =
19970c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala            CameraMetadata_getPointerThrow(env, other, "other");
20070c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala
20170c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    // In case of exception, return
20270c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    if (otherMetadata == NULL) return NULL;
20370c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala
20470c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    // Clone native metadata and return new pointer
20570c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    return reinterpret_cast<jlong>(new CameraMetadata(*otherMetadata));
20670c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala}
20770c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala
20870c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala
20970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinstatic jboolean CameraMetadata_isEmpty(JNIEnv *env, jobject thiz) {
21070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    ALOGV("%s", __FUNCTION__);
21170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
21270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz);
21370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
21470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    if (metadata == NULL) {
21570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        ALOGW("%s: Returning early due to exception being thrown",
21670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin               __FUNCTION__);
21770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        return JNI_TRUE; // actually throws java exc.
21870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    }
21970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
22070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    jboolean empty = metadata->isEmpty();
22170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
22246d8444631b4b1253a76bfcc78a29d26014d022fDan Albert    ALOGV("%s: Empty returned %d, entry count was %zu",
22370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin          __FUNCTION__, empty, metadata->entryCount());
22470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
22570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    return empty;
22670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin}
22770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
22870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinstatic jint CameraMetadata_getEntryCount(JNIEnv *env, jobject thiz) {
22970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    ALOGV("%s", __FUNCTION__);
23070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
23170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz);
23270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
23370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    if (metadata == NULL) return 0; // actually throws java exc.
23470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
23570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    return metadata->entryCount();
23670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin}
23770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
23870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin// idempotent. calling more than once has no effect.
23970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinstatic void CameraMetadata_close(JNIEnv *env, jobject thiz) {
24070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    ALOGV("%s", __FUNCTION__);
24170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
24270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    CameraMetadata* metadata = CameraMetadata_getPointerNoThrow(env, thiz);
24370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
24470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    if (metadata != NULL) {
24570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        delete metadata;
24670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        env->SetLongField(thiz, fields.metadata_ptr, 0);
24770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    }
24870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
24970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    LOG_ALWAYS_FATAL_IF(CameraMetadata_getPointerNoThrow(env, thiz) != NULL,
25070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin                        "Expected the native ptr to be 0 after #close");
25170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin}
25270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
25370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinstatic void CameraMetadata_swap(JNIEnv *env, jobject thiz, jobject other) {
25470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    ALOGV("%s", __FUNCTION__);
25570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
25670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz);
25770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
25870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    // order is important: we can't call another JNI method
25970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    // if there is an exception pending
26070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    if (metadata == NULL) return;
26170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
26270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    CameraMetadata* otherMetadata = CameraMetadata_getPointerThrow(env, other, "other");
26370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
26470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    if (otherMetadata == NULL) return;
26570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
26670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    metadata->swap(*otherMetadata);
26770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin}
26870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
269b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkinstatic jbyteArray CameraMetadata_readValues(JNIEnv *env, jobject thiz, jint tag) {
270b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    ALOGV("%s (tag = %d)", __FUNCTION__, tag);
271b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
272b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz);
273b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    if (metadata == NULL) return NULL;
274b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
275b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    int tagType = get_camera_metadata_tag_type(tag);
276b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    if (tagType == -1) {
277b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
278b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                             "Tag (%d) did not have a type", tag);
279b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        return NULL;
280b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
281b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    size_t tagSize = Helpers::getTypeSize(tagType);
282b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
283b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    camera_metadata_entry entry = metadata->find(tag);
284b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    if (entry.count == 0) {
285b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin         if (!metadata->exists(tag)) {
286b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin             ALOGV("%s: Tag %d does not have any entries", __FUNCTION__, tag);
287b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin             return NULL;
288b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin         } else {
289b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin             // OK: we will return a 0-sized array.
290b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin             ALOGV("%s: Tag %d had an entry, but it had 0 data", __FUNCTION__,
291b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                   tag);
292b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin         }
293b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
294b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
295b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    jsize byteCount = entry.count * tagSize;
296b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    jbyteArray byteArray = env->NewByteArray(byteCount);
297b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    if (env->ExceptionCheck()) return NULL;
298b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
299b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    // Copy into java array from native array
300b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    ScopedByteArrayRW arrayWriter(env, byteArray);
301b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    memcpy(arrayWriter.get(), entry.data.u8, byteCount);
302b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
303b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    return byteArray;
304b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin}
305b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
306b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkinstatic void CameraMetadata_writeValues(JNIEnv *env, jobject thiz, jint tag, jbyteArray src) {
307b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    ALOGV("%s (tag = %d)", __FUNCTION__, tag);
308b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
309b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz);
310b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    if (metadata == NULL) return;
311b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
312b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    int tagType = get_camera_metadata_tag_type(tag);
313b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    if (tagType == -1) {
314b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
315b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                             "Tag (%d) did not have a type", tag);
316b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        return;
317b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
318b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
319b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    status_t res;
320b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
321b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    if (src == NULL) {
322b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        // If array is NULL, delete the entry
3233710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin        if (metadata->exists(tag)) {
3243710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin            res = metadata->erase(tag);
3253710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin            ALOGV("%s: Erase values (res = %d)", __FUNCTION__, res);
3263710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin        } else {
3273710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin            res = OK;
3283710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin            ALOGV("%s: Don't need to erase", __FUNCTION__);
3293710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin        }
330b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    } else {
331b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        // Copy from java array into native array
332b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        ScopedByteArrayRO arrayReader(env, src);
333b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        if (arrayReader.get() == NULL) return;
334b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
335b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        res = Helpers::updateAny(metadata, static_cast<uint32_t>(tag),
336b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                                 tagType, arrayReader.get(), arrayReader.size());
3373710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin
3383710db80d4b9e573d775790e4c9a2ab6e062201eIgor Murashkin        ALOGV("%s: Update values (res = %d)", __FUNCTION__, res);
339b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
340b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
341b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    if (res == OK) {
342b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        return;
343b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    } else if (res == BAD_VALUE) {
344b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
345b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                             "Src byte array was poorly formed");
346b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    } else if (res == INVALID_OPERATION) {
347b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
348b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                             "Internal error while trying to update metadata");
349b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    } else {
350b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
351b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                             "Unknown error (%d) while trying to update "
352b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                            "metadata", res);
353b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
354b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin}
355b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
356d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkinstruct DumpMetadataParams {
357d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    int writeFd;
358d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    const CameraMetadata* metadata;
359d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin};
360d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
361d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkinstatic void* CameraMetadata_writeMetadataThread(void* arg) {
362d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    DumpMetadataParams* p = static_cast<DumpMetadataParams*>(arg);
363d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
364d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    /*
365d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     * Write the dumped data, and close the writing side FD.
366d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     */
367d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    p->metadata->dump(p->writeFd, /*verbosity*/2);
368d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
369d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    if (close(p->writeFd) < 0) {
370d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        ALOGE("%s: Failed to close writeFd (errno = %#x, message = '%s')",
371d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin                __FUNCTION__, errno, strerror(errno));
372d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    }
373d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
374d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    return NULL;
375d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin}
376d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
377d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkinstatic void CameraMetadata_dump(JNIEnv *env, jobject thiz) {
378d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    ALOGV("%s", __FUNCTION__);
379d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz);
380d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    if (metadata == NULL) {
381d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        return;
382d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    }
383d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
384d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    /*
385d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     * Create a socket pair for local streaming read/writes.
386d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     *
387d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     * The metadata will be dumped into the write side,
388d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     * and then read back out (and logged) via the read side.
389d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     */
390d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
391d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    int writeFd, readFd;
392d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    {
393d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
394d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        int sv[2];
395d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        if (socketpair(AF_LOCAL, SOCK_STREAM, /*protocol*/0, &sv[0]) < 0) {
396d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin            jniThrowExceptionFmt(env, "java/io/IOException",
397d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin                    "Failed to create socketpair (errno = %#x, message = '%s')",
398d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin                    errno, strerror(errno));
399d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin            return;
400d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        }
401d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        writeFd = sv[0];
402d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        readFd = sv[1];
403d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    }
404d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
405d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    /*
406d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     * Create a thread for doing the writing.
407d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     *
408d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     * The reading and writing must be concurrent, otherwise
409d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     * the write will block forever once it exhausts the capped
410d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     * buffer size (from getsockopt).
411d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     */
412d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    pthread_t writeThread;
413d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    DumpMetadataParams params = {
414d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        writeFd,
415d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        metadata
416d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    };
417d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
418d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    {
419d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        int threadRet = pthread_create(&writeThread, /*attr*/NULL,
420d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin                CameraMetadata_writeMetadataThread, (void*)&params);
421d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
422d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        if (threadRet != 0) {
423d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin            close(writeFd);
424d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
425d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin            jniThrowExceptionFmt(env, "java/io/IOException",
426d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin                    "Failed to create thread for writing (errno = %#x, message = '%s')",
427d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin                    threadRet, strerror(threadRet));
428d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        }
429d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    }
430d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
431d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    /*
432d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     * Read out a byte until stream is complete. Write completed lines
433d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     * to ALOG.
434d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin     */
435d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    {
436d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        char out[] = {'\0', '\0'}; // large enough to append as a string
437d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        String8 logLine;
438d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
439d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        // Read one byte at a time! Very slow but avoids complicated \n scanning.
440d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        ssize_t res;
441d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        while ((res = TEMP_FAILURE_RETRY(read(readFd, &out[0], /*count*/1))) > 0) {
442d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin            if (out[0] == '\n') {
443d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin                ALOGD("%s", logLine.string());
444d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin                logLine.clear();
445d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin            } else {
446d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin                logLine.append(out);
447d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin            }
448d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        }
449d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
450d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        if (res < 0) {
451d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin            jniThrowExceptionFmt(env, "java/io/IOException",
452d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin                    "Failed to read from fd (errno = %#x, message = '%s')",
453d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin                    errno, strerror(errno));
454d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin            //return;
455d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        } else if (!logLine.isEmpty()) {
456d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin            ALOGD("%s", logLine.string());
457d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        }
458d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    }
459d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
460d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    int res;
461d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
462d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    // Join until thread finishes. Ensures params/metadata is valid until then.
463d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    if ((res = pthread_join(writeThread, /*retval*/NULL)) != 0) {
464d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin        ALOGE("%s: Failed to join thread (errno = %#x, message = '%s')",
465d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin                __FUNCTION__, res, strerror(res));
466d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    }
467d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin}
468d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin
46970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinstatic void CameraMetadata_readFromParcel(JNIEnv *env, jobject thiz, jobject parcel) {
47070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    ALOGV("%s", __FUNCTION__);
47170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz);
47270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    if (metadata == NULL) {
47370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        return;
47470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    }
47570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
47670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    Parcel* parcelNative = parcelForJavaObject(env, parcel);
47770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    if (parcelNative == NULL) {
47870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        jniThrowNullPointerException(env, "parcel");
47970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        return;
48070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    }
48170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
48270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    status_t err;
48370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    if ((err = metadata->readFromParcel(parcelNative)) != OK) {
48470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
48570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin                             "Failed to read from parcel (error code %d)", err);
48670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        return;
48770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    }
48870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin}
48970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
49070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinstatic void CameraMetadata_writeToParcel(JNIEnv *env, jobject thiz, jobject parcel) {
49170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    ALOGV("%s", __FUNCTION__);
49270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz);
49370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    if (metadata == NULL) {
49470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        return;
49570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    }
49670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
49770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    Parcel* parcelNative = parcelForJavaObject(env, parcel);
49870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    if (parcelNative == NULL) {
49970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        jniThrowNullPointerException(env, "parcel");
50070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        return;
50170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    }
50270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
50370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    status_t err;
50470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    if ((err = metadata->writeToParcel(parcelNative)) != OK) {
50570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
50670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin                                  "Failed to write to parcel (error code %d)", err);
50770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        return;
50870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    }
50970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin}
51070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
51170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin} // extern "C"
51270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
51370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin//-------------------------------------------------
51470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
51570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinstatic JNINativeMethod gCameraMetadataMethods[] = {
516b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin// static methods
51770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin  { "nativeClassInit",
51870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    "()V",
51970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    (void *)CameraMetadata_classInit },
520b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin  { "nativeGetTagFromKey",
521b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    "(Ljava/lang/String;)I",
522b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    (void *)CameraMetadata_getTagFromKey },
523b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin  { "nativeGetTypeFromTag",
524b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    "(I)I",
525b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    (void *)CameraMetadata_getTypeFromTag },
52685c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk  { "nativeSetupGlobalVendorTagDescriptor",
52785c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk    "()I",
52885c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk    (void*)CameraMetadata_setupGlobalVendorTagDescriptor },
529b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin// instance methods
53070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin  { "nativeAllocate",
53170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    "()J",
53270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    (void*)CameraMetadata_allocate },
53370c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala  { "nativeAllocateCopy",
53470c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    "(L" CAMERA_METADATA_CLASS_NAME ";)J",
53570c2207c34cf0e6b3b383b1b1500ff5385aa51a6Eino-Ville Talvala    (void *)CameraMetadata_allocateCopy },
53670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin  { "nativeIsEmpty",
53770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    "()Z",
53870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    (void*)CameraMetadata_isEmpty },
53970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin  { "nativeGetEntryCount",
54070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    "()I",
54170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    (void*)CameraMetadata_getEntryCount },
54270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin  { "nativeClose",
54370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    "()V",
54470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    (void*)CameraMetadata_close },
54570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin  { "nativeSwap",
54670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    "(L" CAMERA_METADATA_CLASS_NAME ";)V",
54770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    (void *)CameraMetadata_swap },
548b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin  { "nativeReadValues",
549b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    "(I)[B",
550b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    (void *)CameraMetadata_readValues },
551b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin  { "nativeWriteValues",
552b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    "(I[B)V",
553b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    (void *)CameraMetadata_writeValues },
554d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin  { "nativeDump",
555d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    "()V",
556d6d65154e55612b489aae95b60f3145f3b81f3b4Igor Murashkin    (void *)CameraMetadata_dump },
557b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin// Parcelable interface
55870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin  { "nativeReadFromParcel",
55970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    "(Landroid/os/Parcel;)V",
56070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    (void *)CameraMetadata_readFromParcel },
56170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin  { "nativeWriteToParcel",
56270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    "(Landroid/os/Parcel;)V",
56370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    (void *)CameraMetadata_writeToParcel },
56470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin};
56570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
56670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinstruct field {
56770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    const char *class_name;
56870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    const char *field_name;
56970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    const char *field_type;
57070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    jfieldID   *jfield;
57170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin};
57270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
57370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinstatic int find_fields(JNIEnv *env, field *fields, int count)
57470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin{
57570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    for (int i = 0; i < count; i++) {
57670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        field *f = &fields[i];
57770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        jclass clazz = env->FindClass(f->class_name);
57870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        if (clazz == NULL) {
57970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin            ALOGE("Can't find %s", f->class_name);
58070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin            return -1;
58170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        }
58270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
58370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        jfieldID field = env->GetFieldID(clazz, f->field_name, f->field_type);
58470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        if (field == NULL) {
58570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin            ALOGE("Can't find %s.%s", f->class_name, f->field_name);
58670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin            return -1;
58770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        }
58870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
58970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        *(f->jfield) = field;
59070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    }
59170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
59270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    return 0;
59370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin}
59470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
59570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin// Get all the required offsets in java class and register native functions
5962f1a2e423e0fbb64467d6fcfa4e82c6384f31210Eino-Ville Talvalaint register_android_hardware_camera2_CameraMetadata(JNIEnv *env)
59770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin{
59870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    // Register native functions
59970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    return AndroidRuntime::registerNativeMethods(env,
60070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin            CAMERA_METADATA_CLASS_NAME,
60170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin            gCameraMetadataMethods,
60270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin            NELEM(gCameraMetadataMethods));
60370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin}
60470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
60570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinextern "C" {
60670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkinstatic void CameraMetadata_classInit(JNIEnv *env, jobject thiz) {
60770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    // XX: Why do this separately instead of doing it in the register function?
60870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    ALOGV("%s", __FUNCTION__);
60970725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
61070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    field fields_to_find[] = {
61170725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        { CAMERA_METADATA_CLASS_NAME, "mMetadataPtr", "J", &fields.metadata_ptr },
61270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    };
61370725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
61470725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    // Do this here instead of in register_native_methods,
61570725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    // since otherwise it will fail to find the fields.
61670725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin    if (find_fields(env, fields_to_find, NELEM(fields_to_find)) < 0)
61770725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin        return;
61870725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin
6190f0b4919667f418b249c497f5ad3e83fdf4437e5Andreas Gampe    env->FindClass(CAMERA_METADATA_CLASS_NAME);
62070725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin}
621b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
622b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkinstatic jint CameraMetadata_getTagFromKey(JNIEnv *env, jobject thiz, jstring keyName) {
623b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
624b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    ScopedUtfChars keyScoped(env, keyName);
625b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    const char *key = keyScoped.c_str();
626b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    if (key == NULL) {
627b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        // exception thrown by ScopedUtfChars
628b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        return 0;
629b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
630b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    size_t keyLength = strlen(key);
631b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
632b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    ALOGV("%s (key = '%s')", __FUNCTION__, key);
633b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
63432ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk    sp<VendorTagDescriptor> vTags = VendorTagDescriptor::getGlobalVendorTagDescriptor();
63532ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk
6363c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    SortedVector<String8> vendorSections;
6373c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    size_t vendorSectionCount = 0;
6383c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin
639feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    if (vTags != NULL) {
6403c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        vendorSections = vTags->getAllSectionNames();
6413c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        vendorSectionCount = vendorSections.size();
6423c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin    }
64332ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk
644b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    // First, find the section by the longest string match
645b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    const char *section = NULL;
646b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    size_t sectionIndex = 0;
647b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    size_t sectionLength = 0;
64832ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk    size_t totalSectionCount = ANDROID_SECTION_COUNT + vendorSectionCount;
64932ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk    for (size_t i = 0; i < totalSectionCount; ++i) {
65032ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk
65132ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk        const char *str = (i < ANDROID_SECTION_COUNT) ? camera_metadata_section_names[i] :
65232ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk                vendorSections[i - ANDROID_SECTION_COUNT].string();
653b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        ALOGVV("%s: Trying to match against section '%s'",
654b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin               __FUNCTION__, str);
655b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        if (strstr(key, str) == key) { // key begins with the section name
656b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            size_t strLength = strlen(str);
657b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
658b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            ALOGVV("%s: Key begins with section name", __FUNCTION__);
659b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
660b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            // section name is the longest we've found so far
661b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            if (section == NULL || sectionLength < strLength) {
662b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                section = str;
663b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                sectionIndex = i;
664b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                sectionLength = strLength;
665b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
66632ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk                ALOGVV("%s: Found new best section (%s)", __FUNCTION__, section);
667b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin            }
668b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        }
669b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
670b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
671b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    // TODO: Make above get_camera_metadata_section_from_name ?
672b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
673b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    if (section == NULL) {
674b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
675b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                             "Could not find section name for key '%s')", key);
676b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        return 0;
677b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    } else {
67846d8444631b4b1253a76bfcc78a29d26014d022fDan Albert        ALOGV("%s: Found matched section '%s' (%zu)",
679b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin              __FUNCTION__, section, sectionIndex);
680b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
681b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
682b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    // Get the tag name component of the key
683b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    const char *keyTagName = key + sectionLength + 1; // x.y.z -> z
684b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    if (sectionLength + 1 >= keyLength) {
685b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
686b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                             "Key length too short for key '%s')", key);
68732ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk        return 0;
688b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
689b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
690b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    // Match rest of name against the tag names in that section only
69132ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk    uint32_t tag = 0;
69232ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk    if (sectionIndex < ANDROID_SECTION_COUNT) {
69332ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk        // Match built-in tags (typically android.*)
69432ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk        uint32_t tagBegin, tagEnd; // [tagBegin, tagEnd)
69532ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk        tagBegin = camera_metadata_section_bounds[sectionIndex][0];
69632ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk        tagEnd = camera_metadata_section_bounds[sectionIndex][1];
69732ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk
69832ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk        for (tag = tagBegin; tag < tagEnd; ++tag) {
69932ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk            const char *tagName = get_camera_metadata_tag_name(tag);
70032ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk
70132ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk            if (strcmp(keyTagName, tagName) == 0) {
70232ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk                ALOGV("%s: Found matched tag '%s' (%d)",
70332ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk                      __FUNCTION__, tagName, tag);
70432ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk                break;
70532ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk            }
70632ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk        }
70732ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk
70832ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk        if (tag == tagEnd) {
70932ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk            jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
71032ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk                                 "Could not find tag name for key '%s')", key);
71132ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk            return 0;
71232ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk        }
713feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    } else if (vTags != NULL) {
71432ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk        // Match vendor tags (typically com.*)
71532ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk        const String8 sectionName(section);
71632ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk        const String8 tagName(keyTagName);
71732ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk
71832ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk        status_t res = OK;
71932ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk        if ((res = vTags->lookupTag(tagName, sectionName, &tag)) != OK) {
72032ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk            jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
72132ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk                    "%s: No vendor tag matches key '%s'", __FUNCTION__, key);
72232ef3ae085288597fb86ab97e42ced1da9691362Ruben Brunk            return 0;
723b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        }
724b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
725b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
726b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    // TODO: Make above get_camera_metadata_tag_from_name ?
727b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
728b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    return tag;
729b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin}
730b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
731b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkinstatic jint CameraMetadata_getTypeFromTag(JNIEnv *env, jobject thiz, jint tag) {
732b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    int tagType = get_camera_metadata_tag_type(tag);
733b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    if (tagType == -1) {
734b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
735b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin                             "Tag (%d) did not have a type", tag);
736b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin        return -1;
737b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    }
738b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
739b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin    return tagType;
740b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin}
741b519cc52ecba8f44da31173c9fc90a7b66d52b79Igor Murashkin
74285c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunkstatic jint CameraMetadata_setupGlobalVendorTagDescriptor(JNIEnv *env, jobject thiz) {
74385c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk    const String16 NAME("media.camera");
74485c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk    sp<ICameraService> cameraService;
74585c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk    status_t err = getService(NAME, /*out*/&cameraService);
74685c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk
74785c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk    if (err != OK) {
74885c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk        ALOGE("%s: Failed to get camera service, received error %s (%d)", __FUNCTION__,
74985c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk                strerror(-err), err);
75085c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk        return err;
75185c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk    }
75285c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk
75385c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk    sp<VendorTagDescriptor> desc;
75485c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk    err = cameraService->getCameraVendorTagDescriptor(/*out*/desc);
75585c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk
7565614cbe64493308dc5330eac5d5ba17202013dc4Igor Murashkin    if (err == -EOPNOTSUPP) {
7575614cbe64493308dc5330eac5d5ba17202013dc4Igor Murashkin        ALOGW("%s: Camera HAL too old; does not support vendor tags", __FUNCTION__);
7585614cbe64493308dc5330eac5d5ba17202013dc4Igor Murashkin        VendorTagDescriptor::clearGlobalVendorTagDescriptor();
7595614cbe64493308dc5330eac5d5ba17202013dc4Igor Murashkin
7605614cbe64493308dc5330eac5d5ba17202013dc4Igor Murashkin        return OK;
7615614cbe64493308dc5330eac5d5ba17202013dc4Igor Murashkin    } else if (err != OK) {
7625614cbe64493308dc5330eac5d5ba17202013dc4Igor Murashkin        ALOGE("%s: Failed to setup vendor tag descriptors, received error %s (%d)",
7635614cbe64493308dc5330eac5d5ba17202013dc4Igor Murashkin                __FUNCTION__, strerror(-err), err);
76485c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk        return err;
76585c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk    }
76685c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk
76785c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk    err = VendorTagDescriptor::setAsGlobalVendorTagDescriptor(desc);
76885c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk
76985c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk    return err;
77085c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk}
77185c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk
77270725500dcf3b666b43d50563d64705aab58d2d3Igor Murashkin} // extern "C"
773