blob: 82e88da77059879d58c9677799afa62a82b383c1 [file] [log] [blame]
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -08001/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Elliott Hughes8e86c9c2014-05-22 01:18:02 -070016
Eino-Ville Talvaladd2dd092016-08-16 15:48:05 -070017#define _GNU_SOURCE // for fdprintf
Mark Salyzyn773e5c82014-03-13 13:24:19 -070018#include <inttypes.h>
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -080019#include <system/camera_metadata.h>
Ruben Brunk9c13e192014-02-14 16:40:56 -080020#include <camera_metadata_hidden.h>
Igor Murashkind1cecc12013-04-30 17:21:54 -070021
22#define LOG_TAG "camera_metadata"
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -080023#include <cutils/log.h>
Alex Ray151389f2013-11-12 18:09:31 -080024#include <assert.h>
Eino-Ville Talvala94c19012012-04-04 15:30:06 -070025#include <stdio.h>
26#include <stdlib.h>
27#include <errno.h>
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -080028
Chien-Yu Chen61af47d2016-08-12 15:40:16 -070029#define OK 0
30#define ERROR 1
31#define NOT_FOUND -ENOENT
32#define SN_EVENT_LOG_ID 0x534e4554
Eino-Ville Talvala31540362012-11-07 16:36:50 -080033
Eino-Ville Talvala31540362012-11-07 16:36:50 -080034#define ALIGN_TO(val, alignment) \
Igor Murashkind1cecc12013-04-30 17:21:54 -070035 (((uintptr_t)(val) + ((alignment) - 1)) & ~((alignment) - 1))
36
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -080037/**
38 * A single metadata entry, storing an array of values of a given type. If the
39 * array is no larger than 4 bytes in size, it is stored in the data.value[]
40 * array; otherwise, it can found in the parent's data array at index
41 * data.offset.
42 */
Narayan Kamath21532652014-05-30 15:25:18 +010043#define ENTRY_ALIGNMENT ((size_t) 4)
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -070044typedef struct camera_metadata_buffer_entry {
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -080045 uint32_t tag;
Narayan Kamath21532652014-05-30 15:25:18 +010046 uint32_t count;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -080047 union {
Narayan Kamath21532652014-05-30 15:25:18 +010048 uint32_t offset;
49 uint8_t value[4];
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -080050 } data;
51 uint8_t type;
52 uint8_t reserved[3];
Eino-Ville Talvala31540362012-11-07 16:36:50 -080053} camera_metadata_buffer_entry_t;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -080054
Narayan Kamath21532652014-05-30 15:25:18 +010055typedef uint32_t metadata_uptrdiff_t;
56typedef uint32_t metadata_size_t;
57
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -080058/**
59 * A packet of metadata. This is a list of entries, each of which may point to
60 * its values stored at an offset in data.
61 *
62 * It is assumed by the utility functions that the memory layout of the packet
63 * is as follows:
64 *
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -070065 * |-----------------------------------------------|
66 * | camera_metadata_t |
67 * | |
68 * |-----------------------------------------------|
69 * | reserved for future expansion |
70 * |-----------------------------------------------|
71 * | camera_metadata_buffer_entry_t #0 |
72 * |-----------------------------------------------|
73 * | .... |
74 * |-----------------------------------------------|
75 * | camera_metadata_buffer_entry_t #entry_count-1 |
76 * |-----------------------------------------------|
77 * | free space for |
78 * | (entry_capacity-entry_count) entries |
79 * |-----------------------------------------------|
80 * | start of camera_metadata.data |
81 * | |
82 * |-----------------------------------------------|
83 * | free space for |
84 * | (data_capacity-data_count) bytes |
85 * |-----------------------------------------------|
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -080086 *
87 * With the total length of the whole packet being camera_metadata.size bytes.
88 *
89 * In short, the entries and data are contiguous in memory after the metadata
90 * header.
91 */
Narayan Kamath21532652014-05-30 15:25:18 +010092#define METADATA_ALIGNMENT ((size_t) 4)
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -080093struct camera_metadata {
Narayan Kamath21532652014-05-30 15:25:18 +010094 metadata_size_t size;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -070095 uint32_t version;
96 uint32_t flags;
Narayan Kamath21532652014-05-30 15:25:18 +010097 metadata_size_t entry_count;
98 metadata_size_t entry_capacity;
99 metadata_uptrdiff_t entries_start; // Offset from camera_metadata
100 metadata_size_t data_count;
101 metadata_size_t data_capacity;
102 metadata_uptrdiff_t data_start; // Offset from camera_metadata
103 uint8_t reserved[];
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800104};
105
Igor Murashkin555aac82012-11-15 10:54:57 -0800106/**
107 * A datum of metadata. This corresponds to camera_metadata_entry_t::data
108 * with the difference that each element is not a pointer. We need to have a
109 * non-pointer type description in order to figure out the largest alignment
110 * requirement for data (DATA_ALIGNMENT).
111 */
Narayan Kamath21532652014-05-30 15:25:18 +0100112#define DATA_ALIGNMENT ((size_t) 8)
Igor Murashkin555aac82012-11-15 10:54:57 -0800113typedef union camera_metadata_data {
114 uint8_t u8;
115 int32_t i32;
116 float f;
117 int64_t i64;
118 double d;
119 camera_metadata_rational_t r;
120} camera_metadata_data_t;
121
Narayan Kamath21532652014-05-30 15:25:18 +0100122/**
123 * The preferred alignment of a packet of camera metadata. In general,
124 * this is the lowest common multiple of the constituents of a metadata
125 * package, i.e, of DATA_ALIGNMENT and ENTRY_ALIGNMENT.
126 */
127#define MAX_ALIGNMENT(A, B) (((A) > (B)) ? (A) : (B))
128#define METADATA_PACKET_ALIGNMENT \
129 MAX_ALIGNMENT(MAX_ALIGNMENT(DATA_ALIGNMENT, METADATA_ALIGNMENT), ENTRY_ALIGNMENT);
130
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700131/** Versioning information */
132#define CURRENT_METADATA_VERSION 1
133
134/** Flag definitions */
135#define FLAG_SORTED 0x00000001
136
137/** Tag information */
138
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800139typedef struct tag_info {
140 const char *tag_name;
141 uint8_t tag_type;
142} tag_info_t;
143
144#include "camera_metadata_tag_info.c"
145
Eino-Ville Talvalafd258822012-06-06 17:22:42 -0700146const size_t camera_metadata_type_size[NUM_TYPES] = {
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800147 [TYPE_BYTE] = sizeof(uint8_t),
148 [TYPE_INT32] = sizeof(int32_t),
149 [TYPE_FLOAT] = sizeof(float),
150 [TYPE_INT64] = sizeof(int64_t),
151 [TYPE_DOUBLE] = sizeof(double),
152 [TYPE_RATIONAL] = sizeof(camera_metadata_rational_t)
153};
154
Eino-Ville Talvalafd258822012-06-06 17:22:42 -0700155const char *camera_metadata_type_names[NUM_TYPES] = {
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800156 [TYPE_BYTE] = "byte",
157 [TYPE_INT32] = "int32",
158 [TYPE_FLOAT] = "float",
159 [TYPE_INT64] = "int64",
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700160 [TYPE_DOUBLE] = "double",
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800161 [TYPE_RATIONAL] = "rational"
162};
163
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800164static camera_metadata_buffer_entry_t *get_entries(
165 const camera_metadata_t *metadata) {
166 return (camera_metadata_buffer_entry_t*)
167 ((uint8_t*)metadata + metadata->entries_start);
168}
169
170static uint8_t *get_data(const camera_metadata_t *metadata) {
171 return (uint8_t*)metadata + metadata->data_start;
172}
173
Zhijun He1450f7f2013-12-05 07:44:56 -0800174size_t get_camera_metadata_alignment() {
Narayan Kamath21532652014-05-30 15:25:18 +0100175 return METADATA_PACKET_ALIGNMENT;
Zhijun He1450f7f2013-12-05 07:44:56 -0800176}
177
Igor Murashkind1cecc12013-04-30 17:21:54 -0700178camera_metadata_t *allocate_copy_camera_metadata_checked(
179 const camera_metadata_t *src,
180 size_t src_size) {
181
182 if (src == NULL) {
183 return NULL;
184 }
185
186 void *buffer = malloc(src_size);
187 memcpy(buffer, src, src_size);
188
189 camera_metadata_t *metadata = (camera_metadata_t*) buffer;
190 if (validate_camera_metadata_structure(metadata, &src_size) != OK) {
191 free(buffer);
192 return NULL;
193 }
194
195 return metadata;
196}
197
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800198camera_metadata_t *allocate_camera_metadata(size_t entry_capacity,
199 size_t data_capacity) {
Eino-Ville Talvala2f4aca62012-08-24 11:42:06 -0700200
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800201 size_t memory_needed = calculate_camera_metadata_size(entry_capacity,
202 data_capacity);
203 void *buffer = malloc(memory_needed);
204 return place_camera_metadata(buffer, memory_needed,
205 entry_capacity,
206 data_capacity);
207}
208
209camera_metadata_t *place_camera_metadata(void *dst,
210 size_t dst_size,
211 size_t entry_capacity,
212 size_t data_capacity) {
213 if (dst == NULL) return NULL;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800214
215 size_t memory_needed = calculate_camera_metadata_size(entry_capacity,
216 data_capacity);
217 if (memory_needed > dst_size) return NULL;
218
219 camera_metadata_t *metadata = (camera_metadata_t*)dst;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700220 metadata->version = CURRENT_METADATA_VERSION;
221 metadata->flags = 0;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800222 metadata->entry_count = 0;
223 metadata->entry_capacity = entry_capacity;
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800224 metadata->entries_start =
225 ALIGN_TO(sizeof(camera_metadata_t), ENTRY_ALIGNMENT);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800226 metadata->data_count = 0;
227 metadata->data_capacity = data_capacity;
228 metadata->size = memory_needed;
Igor Murashkind1cecc12013-04-30 17:21:54 -0700229 size_t data_unaligned = (uint8_t*)(get_entries(metadata) +
230 metadata->entry_capacity) - (uint8_t*)metadata;
231 metadata->data_start = ALIGN_TO(data_unaligned, DATA_ALIGNMENT);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800232
Alex Ray151389f2013-11-12 18:09:31 -0800233 assert(validate_camera_metadata_structure(metadata, NULL) == OK);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800234 return metadata;
235}
236void free_camera_metadata(camera_metadata_t *metadata) {
237 free(metadata);
238}
239
240size_t calculate_camera_metadata_size(size_t entry_count,
241 size_t data_count) {
242 size_t memory_needed = sizeof(camera_metadata_t);
Eino-Ville Talvala31540362012-11-07 16:36:50 -0800243 // Start entry list at aligned boundary
244 memory_needed = ALIGN_TO(memory_needed, ENTRY_ALIGNMENT);
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700245 memory_needed += sizeof(camera_metadata_buffer_entry_t[entry_count]);
Eino-Ville Talvala31540362012-11-07 16:36:50 -0800246 // Start buffer list at aligned boundary
247 memory_needed = ALIGN_TO(memory_needed, DATA_ALIGNMENT);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800248 memory_needed += sizeof(uint8_t[data_count]);
249 return memory_needed;
250}
251
252size_t get_camera_metadata_size(const camera_metadata_t *metadata) {
253 if (metadata == NULL) return ERROR;
254
255 return metadata->size;
256}
257
258size_t get_camera_metadata_compact_size(const camera_metadata_t *metadata) {
259 if (metadata == NULL) return ERROR;
260
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800261 return calculate_camera_metadata_size(metadata->entry_count,
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800262 metadata->data_count);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800263}
264
265size_t get_camera_metadata_entry_count(const camera_metadata_t *metadata) {
266 return metadata->entry_count;
267}
268
269size_t get_camera_metadata_entry_capacity(const camera_metadata_t *metadata) {
270 return metadata->entry_capacity;
271}
272
273size_t get_camera_metadata_data_count(const camera_metadata_t *metadata) {
274 return metadata->data_count;
275}
276
277size_t get_camera_metadata_data_capacity(const camera_metadata_t *metadata) {
278 return metadata->data_capacity;
279}
280
281camera_metadata_t* copy_camera_metadata(void *dst, size_t dst_size,
282 const camera_metadata_t *src) {
283 size_t memory_needed = get_camera_metadata_compact_size(src);
284
285 if (dst == NULL) return NULL;
286 if (dst_size < memory_needed) return NULL;
287
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800288 camera_metadata_t *metadata =
289 place_camera_metadata(dst, dst_size, src->entry_count, src->data_count);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800290
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700291 metadata->flags = src->flags;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800292 metadata->entry_count = src->entry_count;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800293 metadata->data_count = src->data_count;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800294
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800295 memcpy(get_entries(metadata), get_entries(src),
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700296 sizeof(camera_metadata_buffer_entry_t[metadata->entry_count]));
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800297 memcpy(get_data(metadata), get_data(src),
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800298 sizeof(uint8_t[metadata->data_count]));
299
Alex Ray151389f2013-11-12 18:09:31 -0800300 assert(validate_camera_metadata_structure(metadata, NULL) == OK);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800301 return metadata;
302}
303
Chien-Yu Chen61af47d2016-08-12 15:40:16 -0700304// This method should be used when the camera metadata cannot be trusted. For example, when it's
305// read from Parcel.
306static int validate_and_calculate_camera_metadata_entry_data_size(size_t *data_size, uint8_t type,
307 size_t data_count) {
308 if (type >= NUM_TYPES) return ERROR;
309
310 // Check for overflow
311 if (data_count != 0 &&
312 camera_metadata_type_size[type] > (SIZE_MAX - DATA_ALIGNMENT + 1) / data_count) {
313 android_errorWriteLog(SN_EVENT_LOG_ID, "30741779");
314 return ERROR;
315 }
316
317 size_t data_bytes = data_count * camera_metadata_type_size[type];
318
319 if (data_size) {
320 *data_size = data_bytes <= 4 ? 0 : ALIGN_TO(data_bytes, DATA_ALIGNMENT);
321 }
322
323 return OK;
324}
325
326size_t calculate_camera_metadata_entry_data_size(uint8_t type,
327 size_t data_count) {
328 if (type >= NUM_TYPES) return 0;
329
330 size_t data_bytes = data_count *
331 camera_metadata_type_size[type];
332
333 return data_bytes <= 4 ? 0 : ALIGN_TO(data_bytes, DATA_ALIGNMENT);
334}
335
Igor Murashkind1cecc12013-04-30 17:21:54 -0700336int validate_camera_metadata_structure(const camera_metadata_t *metadata,
337 const size_t *expected_size) {
338
339 if (metadata == NULL) {
Zhijun He246a1ad2013-11-26 13:41:18 -0800340 ALOGE("%s: metadata is null!", __FUNCTION__);
Igor Murashkind1cecc12013-04-30 17:21:54 -0700341 return ERROR;
342 }
343
344 // Check that the metadata pointer is well-aligned first.
345 {
Narayan Kamath21532652014-05-30 15:25:18 +0100346 static const struct {
Igor Murashkind1cecc12013-04-30 17:21:54 -0700347 const char *name;
348 size_t alignment;
349 } alignments[] = {
350 {
351 .name = "camera_metadata",
Narayan Kamath21532652014-05-30 15:25:18 +0100352 .alignment = METADATA_ALIGNMENT
Igor Murashkind1cecc12013-04-30 17:21:54 -0700353 },
354 {
355 .name = "camera_metadata_buffer_entry",
Narayan Kamath21532652014-05-30 15:25:18 +0100356 .alignment = ENTRY_ALIGNMENT
Igor Murashkind1cecc12013-04-30 17:21:54 -0700357 },
358 {
359 .name = "camera_metadata_data",
Narayan Kamath21532652014-05-30 15:25:18 +0100360 .alignment = DATA_ALIGNMENT
Igor Murashkind1cecc12013-04-30 17:21:54 -0700361 },
362 };
363
364 for (size_t i = 0; i < sizeof(alignments)/sizeof(alignments[0]); ++i) {
365 uintptr_t aligned_ptr = ALIGN_TO(metadata, alignments[i].alignment);
366
367 if ((uintptr_t)metadata != aligned_ptr) {
368 ALOGE("%s: Metadata pointer is not aligned (actual %p, "
369 "expected %p) to type %s",
370 __FUNCTION__, metadata,
371 (void*)aligned_ptr, alignments[i].name);
372 return ERROR;
373 }
374 }
375 }
376
377 /**
378 * Check that the metadata contents are correct
379 */
380
381 if (expected_size != NULL && metadata->size > *expected_size) {
Narayan Kamath21532652014-05-30 15:25:18 +0100382 ALOGE("%s: Metadata size (%" PRIu32 ") should be <= expected size (%zu)",
Igor Murashkind1cecc12013-04-30 17:21:54 -0700383 __FUNCTION__, metadata->size, *expected_size);
384 return ERROR;
385 }
386
387 if (metadata->entry_count > metadata->entry_capacity) {
Narayan Kamath21532652014-05-30 15:25:18 +0100388 ALOGE("%s: Entry count (%" PRIu32 ") should be <= entry capacity "
389 "(%" PRIu32 ")",
Igor Murashkind1cecc12013-04-30 17:21:54 -0700390 __FUNCTION__, metadata->entry_count, metadata->entry_capacity);
391 return ERROR;
392 }
393
Eino-Ville Talvaladd2dd092016-08-16 15:48:05 -0700394 if (metadata->data_count > metadata->data_capacity) {
395 ALOGE("%s: Data count (%" PRIu32 ") should be <= data capacity "
396 "(%" PRIu32 ")",
397 __FUNCTION__, metadata->data_count, metadata->data_capacity);
398 android_errorWriteLog(SN_EVENT_LOG_ID, "30591838");
399 return ERROR;
400 }
Narayan Kamath21532652014-05-30 15:25:18 +0100401 const metadata_uptrdiff_t entries_end =
402 metadata->entries_start + metadata->entry_capacity;
Eino-Ville Talvaladd2dd092016-08-16 15:48:05 -0700403
404
Igor Murashkind1cecc12013-04-30 17:21:54 -0700405 if (entries_end < metadata->entries_start || // overflow check
406 entries_end > metadata->data_start) {
407
Narayan Kamath21532652014-05-30 15:25:18 +0100408 ALOGE("%s: Entry start + capacity (%" PRIu32 ") should be <= data start "
409 "(%" PRIu32 ")",
Igor Murashkind1cecc12013-04-30 17:21:54 -0700410 __FUNCTION__,
411 (metadata->entries_start + metadata->entry_capacity),
412 metadata->data_start);
413 return ERROR;
414 }
415
Narayan Kamath21532652014-05-30 15:25:18 +0100416 const metadata_uptrdiff_t data_end =
417 metadata->data_start + metadata->data_capacity;
Igor Murashkind1cecc12013-04-30 17:21:54 -0700418 if (data_end < metadata->data_start || // overflow check
419 data_end > metadata->size) {
420
Narayan Kamath21532652014-05-30 15:25:18 +0100421 ALOGE("%s: Data start + capacity (%" PRIu32 ") should be <= total size "
422 "(%" PRIu32 ")",
Igor Murashkind1cecc12013-04-30 17:21:54 -0700423 __FUNCTION__,
424 (metadata->data_start + metadata->data_capacity),
425 metadata->size);
426 return ERROR;
427 }
428
429 // Validate each entry
Narayan Kamath21532652014-05-30 15:25:18 +0100430 const metadata_size_t entry_count = metadata->entry_count;
Igor Murashkind1cecc12013-04-30 17:21:54 -0700431 camera_metadata_buffer_entry_t *entries = get_entries(metadata);
432
433 for (size_t i = 0; i < entry_count; ++i) {
434
435 if ((uintptr_t)&entries[i] != ALIGN_TO(&entries[i], ENTRY_ALIGNMENT)) {
Mark Salyzyn773e5c82014-03-13 13:24:19 -0700436 ALOGE("%s: Entry index %zu had bad alignment (address %p),"
437 " expected alignment %zu",
Igor Murashkind1cecc12013-04-30 17:21:54 -0700438 __FUNCTION__, i, &entries[i], ENTRY_ALIGNMENT);
439 return ERROR;
440 }
441
442 camera_metadata_buffer_entry_t entry = entries[i];
443
444 if (entry.type >= NUM_TYPES) {
Mark Salyzyn773e5c82014-03-13 13:24:19 -0700445 ALOGE("%s: Entry index %zu had a bad type %d",
Igor Murashkind1cecc12013-04-30 17:21:54 -0700446 __FUNCTION__, i, entry.type);
447 return ERROR;
448 }
449
450 // TODO: fix vendor_tag_ops across processes so we don't need to special
451 // case vendor-specific tags
452 uint32_t tag_section = entry.tag >> 16;
453 int tag_type = get_camera_metadata_tag_type(entry.tag);
454 if (tag_type != (int)entry.type && tag_section < VENDOR_SECTION) {
Mark Salyzyn773e5c82014-03-13 13:24:19 -0700455 ALOGE("%s: Entry index %zu had tag type %d, but the type was %d",
Igor Murashkind1cecc12013-04-30 17:21:54 -0700456 __FUNCTION__, i, tag_type, entry.type);
457 return ERROR;
458 }
459
Chien-Yu Chen61af47d2016-08-12 15:40:16 -0700460 size_t data_size;
461 if (validate_and_calculate_camera_metadata_entry_data_size(&data_size, entry.type,
462 entry.count) != OK) {
463 ALOGE("%s: Entry data size is invalid. type: %u count: %u", __FUNCTION__, entry.type,
464 entry.count);
465 return ERROR;
466 }
Igor Murashkind1cecc12013-04-30 17:21:54 -0700467
468 if (data_size != 0) {
469 camera_metadata_data_t *data =
470 (camera_metadata_data_t*) (get_data(metadata) +
471 entry.data.offset);
472
473 if ((uintptr_t)data != ALIGN_TO(data, DATA_ALIGNMENT)) {
Mark Salyzyn773e5c82014-03-13 13:24:19 -0700474 ALOGE("%s: Entry index %zu had bad data alignment (address %p),"
475 " expected align %zu, (tag name %s, data size %zu)",
Igor Murashkind1cecc12013-04-30 17:21:54 -0700476 __FUNCTION__, i, data, DATA_ALIGNMENT,
477 get_camera_metadata_tag_name(entry.tag) ?: "unknown",
478 data_size);
479 return ERROR;
480 }
481
482 size_t data_entry_end = entry.data.offset + data_size;
483 if (data_entry_end < entry.data.offset || // overflow check
484 data_entry_end > metadata->data_capacity) {
485
Mark Salyzyn773e5c82014-03-13 13:24:19 -0700486 ALOGE("%s: Entry index %zu data ends (%zu) beyond the capacity "
Narayan Kamath21532652014-05-30 15:25:18 +0100487 "%" PRIu32, __FUNCTION__, i, data_entry_end,
Igor Murashkind1cecc12013-04-30 17:21:54 -0700488 metadata->data_capacity);
489 return ERROR;
490 }
491
492 } else if (entry.count == 0) {
493 if (entry.data.offset != 0) {
Mark Salyzyn773e5c82014-03-13 13:24:19 -0700494 ALOGE("%s: Entry index %zu had 0 items, but offset was non-0 "
Narayan Kamath21532652014-05-30 15:25:18 +0100495 "(%" PRIu32 "), tag name: %s", __FUNCTION__, i, entry.data.offset,
Zhijun He3064d312013-07-15 13:55:11 -0700496 get_camera_metadata_tag_name(entry.tag) ?: "unknown");
Igor Murashkind1cecc12013-04-30 17:21:54 -0700497 return ERROR;
498 }
499 } // else data stored inline, so we look at value which can be anything.
500 }
501
502 return OK;
503}
504
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800505int append_camera_metadata(camera_metadata_t *dst,
506 const camera_metadata_t *src) {
507 if (dst == NULL || src == NULL ) return ERROR;
508
Eino-Ville Talvaladd2dd092016-08-16 15:48:05 -0700509 // Check for overflow
510 if (src->entry_count + dst->entry_count < src->entry_count) return ERROR;
511 if (src->data_count + dst->data_count < src->data_count) return ERROR;
512 // Check for space
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800513 if (dst->entry_capacity < src->entry_count + dst->entry_count) return ERROR;
514 if (dst->data_capacity < src->data_count + dst->data_count) return ERROR;
515
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800516 memcpy(get_entries(dst) + dst->entry_count, get_entries(src),
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700517 sizeof(camera_metadata_buffer_entry_t[src->entry_count]));
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800518 memcpy(get_data(dst) + dst->data_count, get_data(src),
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800519 sizeof(uint8_t[src->data_count]));
520 if (dst->data_count != 0) {
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800521 camera_metadata_buffer_entry_t *entry = get_entries(dst) + dst->entry_count;
522 for (size_t i = 0; i < src->entry_count; i++, entry++) {
523 if ( calculate_camera_metadata_entry_data_size(entry->type,
524 entry->count) > 0 ) {
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800525 entry->data.offset += dst->data_count;
526 }
527 }
528 }
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700529 if (dst->entry_count == 0) {
530 // Appending onto empty buffer, keep sorted state
531 dst->flags |= src->flags & FLAG_SORTED;
532 } else if (src->entry_count != 0) {
533 // Both src, dst are nonempty, cannot assume sort remains
534 dst->flags &= ~FLAG_SORTED;
535 } else {
536 // Src is empty, keep dst sorted state
537 }
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800538 dst->entry_count += src->entry_count;
539 dst->data_count += src->data_count;
540
Alex Ray151389f2013-11-12 18:09:31 -0800541 assert(validate_camera_metadata_structure(dst, NULL) == OK);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800542 return OK;
543}
544
Eino-Ville Talvala2f4aca62012-08-24 11:42:06 -0700545camera_metadata_t *clone_camera_metadata(const camera_metadata_t *src) {
Eino-Ville Talvalafd258822012-06-06 17:22:42 -0700546 int res;
Eino-Ville Talvala2f4aca62012-08-24 11:42:06 -0700547 if (src == NULL) return NULL;
Eino-Ville Talvalafd258822012-06-06 17:22:42 -0700548 camera_metadata_t *clone = allocate_camera_metadata(
549 get_camera_metadata_entry_count(src),
550 get_camera_metadata_data_count(src));
551 if (clone != NULL) {
552 res = append_camera_metadata(clone, src);
553 if (res != OK) {
554 free_camera_metadata(clone);
555 clone = NULL;
556 }
557 }
Alex Ray151389f2013-11-12 18:09:31 -0800558 assert(validate_camera_metadata_structure(clone, NULL) == OK);
Eino-Ville Talvalafd258822012-06-06 17:22:42 -0700559 return clone;
560}
561
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700562static int add_camera_metadata_entry_raw(camera_metadata_t *dst,
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800563 uint32_t tag,
564 uint8_t type,
565 const void *data,
566 size_t data_count) {
567
568 if (dst == NULL) return ERROR;
569 if (dst->entry_count == dst->entry_capacity) return ERROR;
570 if (data == NULL) return ERROR;
571
572 size_t data_bytes =
573 calculate_camera_metadata_entry_data_size(type, data_count);
Eino-Ville Talvala31540362012-11-07 16:36:50 -0800574 if (data_bytes + dst->data_count > dst->data_capacity) return ERROR;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800575
Eino-Ville Talvala31540362012-11-07 16:36:50 -0800576 size_t data_payload_bytes =
577 data_count * camera_metadata_type_size[type];
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800578 camera_metadata_buffer_entry_t *entry = get_entries(dst) + dst->entry_count;
Zhijun He3064d312013-07-15 13:55:11 -0700579 memset(entry, 0, sizeof(camera_metadata_buffer_entry_t));
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800580 entry->tag = tag;
581 entry->type = type;
582 entry->count = data_count;
583
584 if (data_bytes == 0) {
585 memcpy(entry->data.value, data,
Eino-Ville Talvala31540362012-11-07 16:36:50 -0800586 data_payload_bytes);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800587 } else {
588 entry->data.offset = dst->data_count;
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800589 memcpy(get_data(dst) + entry->data.offset, data,
Eino-Ville Talvala31540362012-11-07 16:36:50 -0800590 data_payload_bytes);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800591 dst->data_count += data_bytes;
592 }
593 dst->entry_count++;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700594 dst->flags &= ~FLAG_SORTED;
Alex Ray151389f2013-11-12 18:09:31 -0800595 assert(validate_camera_metadata_structure(dst, NULL) == OK);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800596 return OK;
597}
598
599int add_camera_metadata_entry(camera_metadata_t *dst,
600 uint32_t tag,
601 const void *data,
602 size_t data_count) {
603
604 int type = get_camera_metadata_tag_type(tag);
605 if (type == -1) {
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700606 ALOGE("%s: Unknown tag %04x.", __FUNCTION__, tag);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800607 return ERROR;
608 }
609
610 return add_camera_metadata_entry_raw(dst,
611 tag,
612 type,
613 data,
614 data_count);
615}
616
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700617static int compare_entry_tags(const void *p1, const void *p2) {
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700618 uint32_t tag1 = ((camera_metadata_buffer_entry_t*)p1)->tag;
619 uint32_t tag2 = ((camera_metadata_buffer_entry_t*)p2)->tag;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700620 return tag1 < tag2 ? -1 :
621 tag1 == tag2 ? 0 :
622 1;
623}
624
625int sort_camera_metadata(camera_metadata_t *dst) {
626 if (dst == NULL) return ERROR;
627 if (dst->flags & FLAG_SORTED) return OK;
628
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800629 qsort(get_entries(dst), dst->entry_count,
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700630 sizeof(camera_metadata_buffer_entry_t),
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700631 compare_entry_tags);
632 dst->flags |= FLAG_SORTED;
633
Alex Ray151389f2013-11-12 18:09:31 -0800634 assert(validate_camera_metadata_structure(dst, NULL) == OK);
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700635 return OK;
636}
637
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800638int get_camera_metadata_entry(camera_metadata_t *src,
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700639 size_t index,
640 camera_metadata_entry_t *entry) {
641 if (src == NULL || entry == NULL) return ERROR;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800642 if (index >= src->entry_count) return ERROR;
643
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800644 camera_metadata_buffer_entry_t *buffer_entry = get_entries(src) + index;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800645
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700646 entry->index = index;
647 entry->tag = buffer_entry->tag;
648 entry->type = buffer_entry->type;
649 entry->count = buffer_entry->count;
650 if (buffer_entry->count *
651 camera_metadata_type_size[buffer_entry->type] > 4) {
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800652 entry->data.u8 = get_data(src) + buffer_entry->data.offset;
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700653 } else {
654 entry->data.u8 = buffer_entry->data.value;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700655 }
656 return OK;
657}
658
Alex Ray71fe0f82013-10-21 12:57:05 -0700659int get_camera_metadata_ro_entry(const camera_metadata_t *src,
660 size_t index,
661 camera_metadata_ro_entry_t *entry) {
662 return get_camera_metadata_entry((camera_metadata_t*)src, index,
663 (camera_metadata_entry_t*)entry);
664}
665
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700666int find_camera_metadata_entry(camera_metadata_t *src,
667 uint32_t tag,
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700668 camera_metadata_entry_t *entry) {
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700669 if (src == NULL) return ERROR;
670
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700671 uint32_t index;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700672 if (src->flags & FLAG_SORTED) {
673 // Sorted entries, do a binary search
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700674 camera_metadata_buffer_entry_t *search_entry = NULL;
675 camera_metadata_buffer_entry_t key;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700676 key.tag = tag;
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700677 search_entry = bsearch(&key,
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800678 get_entries(src),
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700679 src->entry_count,
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700680 sizeof(camera_metadata_buffer_entry_t),
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700681 compare_entry_tags);
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700682 if (search_entry == NULL) return NOT_FOUND;
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800683 index = search_entry - get_entries(src);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800684 } else {
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700685 // Not sorted, linear search
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800686 camera_metadata_buffer_entry_t *search_entry = get_entries(src);
687 for (index = 0; index < src->entry_count; index++, search_entry++) {
688 if (search_entry->tag == tag) {
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700689 break;
690 }
691 }
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700692 if (index == src->entry_count) return NOT_FOUND;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700693 }
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700694
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700695 return get_camera_metadata_entry(src, index,
696 entry);
697}
698
Eino-Ville Talvala2f4aca62012-08-24 11:42:06 -0700699int find_camera_metadata_ro_entry(const camera_metadata_t *src,
700 uint32_t tag,
701 camera_metadata_ro_entry_t *entry) {
702 return find_camera_metadata_entry((camera_metadata_t*)src, tag,
703 (camera_metadata_entry_t*)entry);
704}
705
706
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700707int delete_camera_metadata_entry(camera_metadata_t *dst,
708 size_t index) {
709 if (dst == NULL) return ERROR;
710 if (index >= dst->entry_count) return ERROR;
711
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800712 camera_metadata_buffer_entry_t *entry = get_entries(dst) + index;
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700713 size_t data_bytes = calculate_camera_metadata_entry_data_size(entry->type,
714 entry->count);
715
716 if (data_bytes > 0) {
717 // Shift data buffer to overwrite deleted data
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800718 uint8_t *start = get_data(dst) + entry->data.offset;
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700719 uint8_t *end = start + data_bytes;
720 size_t length = dst->data_count - entry->data.offset - data_bytes;
721 memmove(start, end, length);
722
723 // Update all entry indices to account for shift
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800724 camera_metadata_buffer_entry_t *e = get_entries(dst);
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700725 size_t i;
726 for (i = 0; i < dst->entry_count; i++) {
727 if (calculate_camera_metadata_entry_data_size(
728 e->type, e->count) > 0 &&
729 e->data.offset > entry->data.offset) {
730 e->data.offset -= data_bytes;
731 }
732 ++e;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700733 }
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700734 dst->data_count -= data_bytes;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800735 }
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700736 // Shift entry array
737 memmove(entry, entry + 1,
738 sizeof(camera_metadata_buffer_entry_t) *
739 (dst->entry_count - index - 1) );
740 dst->entry_count -= 1;
741
Alex Ray151389f2013-11-12 18:09:31 -0800742 assert(validate_camera_metadata_structure(dst, NULL) == OK);
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700743 return OK;
744}
745
746int update_camera_metadata_entry(camera_metadata_t *dst,
747 size_t index,
748 const void *data,
749 size_t data_count,
750 camera_metadata_entry_t *updated_entry) {
751 if (dst == NULL) return ERROR;
752 if (index >= dst->entry_count) return ERROR;
753
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800754 camera_metadata_buffer_entry_t *entry = get_entries(dst) + index;
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700755
756 size_t data_bytes =
757 calculate_camera_metadata_entry_data_size(entry->type,
758 data_count);
Eino-Ville Talvala31540362012-11-07 16:36:50 -0800759 size_t data_payload_bytes =
760 data_count * camera_metadata_type_size[entry->type];
761
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700762 size_t entry_bytes =
763 calculate_camera_metadata_entry_data_size(entry->type,
764 entry->count);
765 if (data_bytes != entry_bytes) {
766 // May need to shift/add to data array
767 if (dst->data_capacity < dst->data_count + data_bytes - entry_bytes) {
768 // No room
769 return ERROR;
770 }
771 if (entry_bytes != 0) {
772 // Remove old data
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800773 uint8_t *start = get_data(dst) + entry->data.offset;
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700774 uint8_t *end = start + entry_bytes;
775 size_t length = dst->data_count - entry->data.offset - entry_bytes;
776 memmove(start, end, length);
777 dst->data_count -= entry_bytes;
778
779 // Update all entry indices to account for shift
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800780 camera_metadata_buffer_entry_t *e = get_entries(dst);
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700781 size_t i;
782 for (i = 0; i < dst->entry_count; i++) {
783 if (calculate_camera_metadata_entry_data_size(
784 e->type, e->count) > 0 &&
785 e->data.offset > entry->data.offset) {
786 e->data.offset -= entry_bytes;
787 }
788 ++e;
789 }
790 }
791
792 if (data_bytes != 0) {
793 // Append new data
794 entry->data.offset = dst->data_count;
795
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800796 memcpy(get_data(dst) + entry->data.offset, data, data_payload_bytes);
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700797 dst->data_count += data_bytes;
798 }
799 } else if (data_bytes != 0) {
800 // data size unchanged, reuse same data location
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800801 memcpy(get_data(dst) + entry->data.offset, data, data_payload_bytes);
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700802 }
803
804 if (data_bytes == 0) {
805 // Data fits into entry
806 memcpy(entry->data.value, data,
Eino-Ville Talvala31540362012-11-07 16:36:50 -0800807 data_payload_bytes);
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700808 }
809
810 entry->count = data_count;
811
812 if (updated_entry != NULL) {
813 get_camera_metadata_entry(dst,
814 index,
815 updated_entry);
816 }
817
Alex Ray151389f2013-11-12 18:09:31 -0800818 assert(validate_camera_metadata_structure(dst, NULL) == OK);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800819 return OK;
820}
821
Ruben Brunk9c13e192014-02-14 16:40:56 -0800822static const vendor_tag_ops_t *vendor_tag_ops = NULL;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800823
824const char *get_camera_metadata_section_name(uint32_t tag) {
825 uint32_t tag_section = tag >> 16;
826 if (tag_section >= VENDOR_SECTION && vendor_tag_ops != NULL) {
Ruben Brunk9c13e192014-02-14 16:40:56 -0800827 return vendor_tag_ops->get_section_name(
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700828 vendor_tag_ops,
829 tag);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800830 }
831 if (tag_section >= ANDROID_SECTION_COUNT) {
832 return NULL;
833 }
834 return camera_metadata_section_names[tag_section];
835}
836
837const char *get_camera_metadata_tag_name(uint32_t tag) {
838 uint32_t tag_section = tag >> 16;
839 if (tag_section >= VENDOR_SECTION && vendor_tag_ops != NULL) {
Ruben Brunk9c13e192014-02-14 16:40:56 -0800840 return vendor_tag_ops->get_tag_name(
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700841 vendor_tag_ops,
842 tag);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800843 }
844 if (tag_section >= ANDROID_SECTION_COUNT ||
845 tag >= camera_metadata_section_bounds[tag_section][1] ) {
846 return NULL;
847 }
848 uint32_t tag_index = tag & 0xFFFF;
849 return tag_info[tag_section][tag_index].tag_name;
850}
851
852int get_camera_metadata_tag_type(uint32_t tag) {
853 uint32_t tag_section = tag >> 16;
854 if (tag_section >= VENDOR_SECTION && vendor_tag_ops != NULL) {
Ruben Brunk9c13e192014-02-14 16:40:56 -0800855 return vendor_tag_ops->get_tag_type(
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700856 vendor_tag_ops,
857 tag);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800858 }
859 if (tag_section >= ANDROID_SECTION_COUNT ||
860 tag >= camera_metadata_section_bounds[tag_section][1] ) {
861 return -1;
862 }
863 uint32_t tag_index = tag & 0xFFFF;
864 return tag_info[tag_section][tag_index].tag_type;
865}
866
Ruben Brunk9c13e192014-02-14 16:40:56 -0800867int set_camera_metadata_vendor_tag_ops(const vendor_tag_query_ops_t* ops) {
868 // **DEPRECATED**
869 ALOGE("%s: This function has been deprecated", __FUNCTION__);
870 return ERROR;
871}
872
873// Declared in system/media/private/camera/include/camera_metadata_hidden.h
874int set_camera_metadata_vendor_ops(const vendor_tag_ops_t* ops) {
875 vendor_tag_ops = ops;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800876 return OK;
877}
878
Igor Murashkin375cfd32012-12-03 13:55:33 -0800879static void print_data(int fd, const uint8_t *data_ptr, uint32_t tag, int type,
880 int count,
Eino-Ville Talvala1d27e5b2012-07-30 10:46:22 -0700881 int indentation);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800882
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700883void dump_camera_metadata(const camera_metadata_t *metadata,
884 int fd,
885 int verbosity) {
Eino-Ville Talvala1d27e5b2012-07-30 10:46:22 -0700886 dump_indented_camera_metadata(metadata, fd, verbosity, 0);
887}
888
889void dump_indented_camera_metadata(const camera_metadata_t *metadata,
890 int fd,
891 int verbosity,
892 int indentation) {
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800893 if (metadata == NULL) {
Elliott Hughes8e86c9c2014-05-22 01:18:02 -0700894 dprintf(fd, "%*sDumping camera metadata array: Not allocated\n",
Eino-Ville Talvala2f4aca62012-08-24 11:42:06 -0700895 indentation, "");
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800896 return;
897 }
898 unsigned int i;
Elliott Hughes8e86c9c2014-05-22 01:18:02 -0700899 dprintf(fd,
Narayan Kamath21532652014-05-30 15:25:18 +0100900 "%*sDumping camera metadata array: %" PRIu32 " / %" PRIu32 " entries, "
901 "%" PRIu32 " / %" PRIu32 " bytes of extra data.\n", indentation, "",
Eino-Ville Talvala1d27e5b2012-07-30 10:46:22 -0700902 metadata->entry_count, metadata->entry_capacity,
903 metadata->data_count, metadata->data_capacity);
Elliott Hughes8e86c9c2014-05-22 01:18:02 -0700904 dprintf(fd, "%*sVersion: %d, Flags: %08x\n",
Eino-Ville Talvala1d27e5b2012-07-30 10:46:22 -0700905 indentation + 2, "",
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700906 metadata->version, metadata->flags);
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800907 camera_metadata_buffer_entry_t *entry = get_entries(metadata);
908 for (i=0; i < metadata->entry_count; i++, entry++) {
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800909
910 const char *tag_name, *tag_section;
911 tag_section = get_camera_metadata_section_name(entry->tag);
912 if (tag_section == NULL) {
913 tag_section = "unknownSection";
914 }
915 tag_name = get_camera_metadata_tag_name(entry->tag);
916 if (tag_name == NULL) {
917 tag_name = "unknownTag";
918 }
919 const char *type_name;
920 if (entry->type >= NUM_TYPES) {
921 type_name = "unknown";
922 } else {
923 type_name = camera_metadata_type_names[entry->type];
924 }
Narayan Kamath21532652014-05-30 15:25:18 +0100925 dprintf(fd, "%*s%s.%s (%05x): %s[%" PRIu32 "]\n",
Eino-Ville Talvala1d27e5b2012-07-30 10:46:22 -0700926 indentation + 2, "",
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800927 tag_section,
928 tag_name,
929 entry->tag,
930 type_name,
931 entry->count);
932
933 if (verbosity < 1) continue;
934
935 if (entry->type >= NUM_TYPES) continue;
936
937 size_t type_size = camera_metadata_type_size[entry->type];
938 uint8_t *data_ptr;
939 if ( type_size * entry->count > 4 ) {
940 if (entry->data.offset >= metadata->data_count) {
Narayan Kamath21532652014-05-30 15:25:18 +0100941 ALOGE("%s: Malformed entry data offset: %" PRIu32 " (max %" PRIu32 ")",
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700942 __FUNCTION__,
943 entry->data.offset,
944 metadata->data_count);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800945 continue;
946 }
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800947 data_ptr = get_data(metadata) + entry->data.offset;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800948 } else {
949 data_ptr = entry->data.value;
950 }
951 int count = entry->count;
952 if (verbosity < 2 && count > 16) count = 16;
953
Igor Murashkin375cfd32012-12-03 13:55:33 -0800954 print_data(fd, data_ptr, entry->tag, entry->type, count, indentation);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800955 }
956}
957
Igor Murashkin375cfd32012-12-03 13:55:33 -0800958static void print_data(int fd, const uint8_t *data_ptr, uint32_t tag,
Eino-Ville Talvala1d27e5b2012-07-30 10:46:22 -0700959 int type, int count, int indentation) {
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800960 static int values_per_line[NUM_TYPES] = {
961 [TYPE_BYTE] = 16,
962 [TYPE_INT32] = 4,
963 [TYPE_FLOAT] = 8,
964 [TYPE_INT64] = 2,
965 [TYPE_DOUBLE] = 4,
966 [TYPE_RATIONAL] = 2,
967 };
968 size_t type_size = camera_metadata_type_size[type];
Igor Murashkin375cfd32012-12-03 13:55:33 -0800969 char value_string_tmp[CAMERA_METADATA_ENUM_STRING_MAX_SIZE];
970 uint32_t value;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800971
972 int lines = count / values_per_line[type];
973 if (count % values_per_line[type] != 0) lines++;
974
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800975 int index = 0;
976 int j, k;
977 for (j = 0; j < lines; j++) {
Elliott Hughes8e86c9c2014-05-22 01:18:02 -0700978 dprintf(fd, "%*s[", indentation + 4, "");
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800979 for (k = 0;
980 k < values_per_line[type] && count > 0;
981 k++, count--, index += type_size) {
982
983 switch (type) {
984 case TYPE_BYTE:
Igor Murashkin375cfd32012-12-03 13:55:33 -0800985 value = *(data_ptr + index);
986 if (camera_metadata_enum_snprint(tag,
987 value,
988 value_string_tmp,
989 sizeof(value_string_tmp))
990 == OK) {
Elliott Hughes8e86c9c2014-05-22 01:18:02 -0700991 dprintf(fd, "%s ", value_string_tmp);
Igor Murashkin375cfd32012-12-03 13:55:33 -0800992 } else {
Elliott Hughes8e86c9c2014-05-22 01:18:02 -0700993 dprintf(fd, "%hhu ",
Igor Murashkin375cfd32012-12-03 13:55:33 -0800994 *(data_ptr + index));
995 }
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800996 break;
997 case TYPE_INT32:
Igor Murashkin375cfd32012-12-03 13:55:33 -0800998 value =
999 *(int32_t*)(data_ptr + index);
1000 if (camera_metadata_enum_snprint(tag,
1001 value,
1002 value_string_tmp,
1003 sizeof(value_string_tmp))
1004 == OK) {
Elliott Hughes8e86c9c2014-05-22 01:18:02 -07001005 dprintf(fd, "%s ", value_string_tmp);
Igor Murashkin375cfd32012-12-03 13:55:33 -08001006 } else {
Elliott Hughes8e86c9c2014-05-22 01:18:02 -07001007 dprintf(fd, "%" PRId32 " ",
Igor Murashkin375cfd32012-12-03 13:55:33 -08001008 *(int32_t*)(data_ptr + index));
1009 }
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -08001010 break;
1011 case TYPE_FLOAT:
Elliott Hughesd1c33572014-05-22 10:53:20 -07001012 dprintf(fd, "%0.8f ",
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -08001013 *(float*)(data_ptr + index));
1014 break;
1015 case TYPE_INT64:
Elliott Hughes8e86c9c2014-05-22 01:18:02 -07001016 dprintf(fd, "%" PRId64 " ",
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -08001017 *(int64_t*)(data_ptr + index));
1018 break;
1019 case TYPE_DOUBLE:
Elliott Hughesd1c33572014-05-22 10:53:20 -07001020 dprintf(fd, "%0.8f ",
Eino-Ville Talvala31540362012-11-07 16:36:50 -08001021 *(double*)(data_ptr + index));
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -08001022 break;
1023 case TYPE_RATIONAL: {
1024 int32_t numerator = *(int32_t*)(data_ptr + index);
1025 int32_t denominator = *(int32_t*)(data_ptr + index + 4);
Elliott Hughes8e86c9c2014-05-22 01:18:02 -07001026 dprintf(fd, "(%d / %d) ",
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -08001027 numerator, denominator);
1028 break;
1029 }
1030 default:
Elliott Hughes8e86c9c2014-05-22 01:18:02 -07001031 dprintf(fd, "??? ");
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -08001032 }
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -08001033 }
Elliott Hughes8e86c9c2014-05-22 01:18:02 -07001034 dprintf(fd, "]\n");
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -08001035 }
1036}