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