blob: 8f78be77b9425312eb0942fd41ba7bf096b16c08 [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
Mark Salyzyn773e5c82014-03-13 13:24:19 -070017#include <inttypes.h>
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -080018#include <system/camera_metadata.h>
Ruben Brunk9c13e192014-02-14 16:40:56 -080019#include <camera_metadata_hidden.h>
Igor Murashkind1cecc12013-04-30 17:21:54 -070020
21#define LOG_TAG "camera_metadata"
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -080022#include <cutils/log.h>
Alex Ray151389f2013-11-12 18:09:31 -080023#include <assert.h>
Eino-Ville Talvala94c19012012-04-04 15:30:06 -070024#include <stdio.h>
25#include <stdlib.h>
26#include <errno.h>
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -080027
Eino-Ville Talvala94c19012012-04-04 15:30:06 -070028#define OK 0
29#define ERROR 1
30#define NOT_FOUND -ENOENT
Eino-Ville Talvala31540362012-11-07 16:36:50 -080031
32#define _Alignas(T) \
33 ({struct _AlignasStruct { char c; T field; }; \
34 offsetof(struct _AlignasStruct, field); })
35
36// Align entry buffers as the compiler would
37#define ENTRY_ALIGNMENT _Alignas(camera_metadata_buffer_entry_t)
38// Align data buffer to largest supported data type
Igor Murashkin555aac82012-11-15 10:54:57 -080039#define DATA_ALIGNMENT _Alignas(camera_metadata_data_t)
Eino-Ville Talvala31540362012-11-07 16:36:50 -080040
41#define ALIGN_TO(val, alignment) \
Igor Murashkind1cecc12013-04-30 17:21:54 -070042 (((uintptr_t)(val) + ((alignment) - 1)) & ~((alignment) - 1))
43
44typedef size_t uptrdiff_t;
Eino-Ville Talvala31540362012-11-07 16:36:50 -080045
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -080046/**
47 * A single metadata entry, storing an array of values of a given type. If the
48 * array is no larger than 4 bytes in size, it is stored in the data.value[]
49 * array; otherwise, it can found in the parent's data array at index
50 * data.offset.
51 */
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -070052typedef struct camera_metadata_buffer_entry {
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -080053 uint32_t tag;
54 size_t count;
55 union {
56 size_t offset;
57 uint8_t value[4];
58 } data;
59 uint8_t type;
60 uint8_t reserved[3];
Eino-Ville Talvala31540362012-11-07 16:36:50 -080061} camera_metadata_buffer_entry_t;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -080062
63/**
64 * A packet of metadata. This is a list of entries, each of which may point to
65 * its values stored at an offset in data.
66 *
67 * It is assumed by the utility functions that the memory layout of the packet
68 * is as follows:
69 *
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -070070 * |-----------------------------------------------|
71 * | camera_metadata_t |
72 * | |
73 * |-----------------------------------------------|
74 * | reserved for future expansion |
75 * |-----------------------------------------------|
76 * | camera_metadata_buffer_entry_t #0 |
77 * |-----------------------------------------------|
78 * | .... |
79 * |-----------------------------------------------|
80 * | camera_metadata_buffer_entry_t #entry_count-1 |
81 * |-----------------------------------------------|
82 * | free space for |
83 * | (entry_capacity-entry_count) entries |
84 * |-----------------------------------------------|
85 * | start of camera_metadata.data |
86 * | |
87 * |-----------------------------------------------|
88 * | free space for |
89 * | (data_capacity-data_count) bytes |
90 * |-----------------------------------------------|
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -080091 *
92 * With the total length of the whole packet being camera_metadata.size bytes.
93 *
94 * In short, the entries and data are contiguous in memory after the metadata
95 * header.
96 */
97struct camera_metadata {
98 size_t size;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -070099 uint32_t version;
100 uint32_t flags;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800101 size_t entry_count;
102 size_t entry_capacity;
Igor Murashkind1cecc12013-04-30 17:21:54 -0700103 uptrdiff_t entries_start; // Offset from camera_metadata
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800104 size_t data_count;
105 size_t data_capacity;
Igor Murashkind1cecc12013-04-30 17:21:54 -0700106 uptrdiff_t data_start; // Offset from camera_metadata
Eino-Ville Talvala98d02fd2012-05-21 14:46:49 -0700107 void *user; // User set pointer, not copied with buffer
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800108 uint8_t reserved[0];
109};
110
Igor Murashkin555aac82012-11-15 10:54:57 -0800111/**
112 * A datum of metadata. This corresponds to camera_metadata_entry_t::data
113 * with the difference that each element is not a pointer. We need to have a
114 * non-pointer type description in order to figure out the largest alignment
115 * requirement for data (DATA_ALIGNMENT).
116 */
117typedef union camera_metadata_data {
118 uint8_t u8;
119 int32_t i32;
120 float f;
121 int64_t i64;
122 double d;
123 camera_metadata_rational_t r;
124} camera_metadata_data_t;
125
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700126/** Versioning information */
127#define CURRENT_METADATA_VERSION 1
128
129/** Flag definitions */
130#define FLAG_SORTED 0x00000001
131
132/** Tag information */
133
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800134typedef struct tag_info {
135 const char *tag_name;
136 uint8_t tag_type;
137} tag_info_t;
138
139#include "camera_metadata_tag_info.c"
140
Eino-Ville Talvalafd258822012-06-06 17:22:42 -0700141const size_t camera_metadata_type_size[NUM_TYPES] = {
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800142 [TYPE_BYTE] = sizeof(uint8_t),
143 [TYPE_INT32] = sizeof(int32_t),
144 [TYPE_FLOAT] = sizeof(float),
145 [TYPE_INT64] = sizeof(int64_t),
146 [TYPE_DOUBLE] = sizeof(double),
147 [TYPE_RATIONAL] = sizeof(camera_metadata_rational_t)
148};
149
Eino-Ville Talvalafd258822012-06-06 17:22:42 -0700150const char *camera_metadata_type_names[NUM_TYPES] = {
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800151 [TYPE_BYTE] = "byte",
152 [TYPE_INT32] = "int32",
153 [TYPE_FLOAT] = "float",
154 [TYPE_INT64] = "int64",
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700155 [TYPE_DOUBLE] = "double",
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800156 [TYPE_RATIONAL] = "rational"
157};
158
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800159static camera_metadata_buffer_entry_t *get_entries(
160 const camera_metadata_t *metadata) {
161 return (camera_metadata_buffer_entry_t*)
162 ((uint8_t*)metadata + metadata->entries_start);
163}
164
165static uint8_t *get_data(const camera_metadata_t *metadata) {
166 return (uint8_t*)metadata + metadata->data_start;
167}
168
Zhijun He1450f7f2013-12-05 07:44:56 -0800169size_t get_camera_metadata_alignment() {
170 size_t alignments[] = {
171 _Alignas(struct camera_metadata),
172 _Alignas(struct camera_metadata_buffer_entry),
173 _Alignas(union camera_metadata_data)
174 };
175 size_t max_alignment = alignments[0];
176
177 for (size_t i = 1; i < sizeof(alignments)/sizeof(alignments[0]); ++i) {
178 if (max_alignment < alignments[i]) {
179 max_alignment = alignments[i];
180 }
181 }
182
183 return max_alignment;
184}
185
Igor Murashkind1cecc12013-04-30 17:21:54 -0700186camera_metadata_t *allocate_copy_camera_metadata_checked(
187 const camera_metadata_t *src,
188 size_t src_size) {
189
190 if (src == NULL) {
191 return NULL;
192 }
193
194 void *buffer = malloc(src_size);
195 memcpy(buffer, src, src_size);
196
197 camera_metadata_t *metadata = (camera_metadata_t*) buffer;
198 if (validate_camera_metadata_structure(metadata, &src_size) != OK) {
199 free(buffer);
200 return NULL;
201 }
202
203 return metadata;
204}
205
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800206camera_metadata_t *allocate_camera_metadata(size_t entry_capacity,
207 size_t data_capacity) {
Eino-Ville Talvala2f4aca62012-08-24 11:42:06 -0700208
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800209 size_t memory_needed = calculate_camera_metadata_size(entry_capacity,
210 data_capacity);
211 void *buffer = malloc(memory_needed);
212 return place_camera_metadata(buffer, memory_needed,
213 entry_capacity,
214 data_capacity);
215}
216
217camera_metadata_t *place_camera_metadata(void *dst,
218 size_t dst_size,
219 size_t entry_capacity,
220 size_t data_capacity) {
221 if (dst == NULL) return NULL;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800222
223 size_t memory_needed = calculate_camera_metadata_size(entry_capacity,
224 data_capacity);
225 if (memory_needed > dst_size) return NULL;
226
227 camera_metadata_t *metadata = (camera_metadata_t*)dst;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700228 metadata->version = CURRENT_METADATA_VERSION;
229 metadata->flags = 0;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800230 metadata->entry_count = 0;
231 metadata->entry_capacity = entry_capacity;
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800232 metadata->entries_start =
233 ALIGN_TO(sizeof(camera_metadata_t), ENTRY_ALIGNMENT);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800234 metadata->data_count = 0;
235 metadata->data_capacity = data_capacity;
236 metadata->size = memory_needed;
Igor Murashkind1cecc12013-04-30 17:21:54 -0700237 size_t data_unaligned = (uint8_t*)(get_entries(metadata) +
238 metadata->entry_capacity) - (uint8_t*)metadata;
239 metadata->data_start = ALIGN_TO(data_unaligned, DATA_ALIGNMENT);
Eino-Ville Talvala98d02fd2012-05-21 14:46:49 -0700240 metadata->user = NULL;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800241
Alex Ray151389f2013-11-12 18:09:31 -0800242 assert(validate_camera_metadata_structure(metadata, NULL) == OK);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800243 return metadata;
244}
245void free_camera_metadata(camera_metadata_t *metadata) {
246 free(metadata);
247}
248
249size_t calculate_camera_metadata_size(size_t entry_count,
250 size_t data_count) {
251 size_t memory_needed = sizeof(camera_metadata_t);
Eino-Ville Talvala31540362012-11-07 16:36:50 -0800252 // Start entry list at aligned boundary
253 memory_needed = ALIGN_TO(memory_needed, ENTRY_ALIGNMENT);
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700254 memory_needed += sizeof(camera_metadata_buffer_entry_t[entry_count]);
Eino-Ville Talvala31540362012-11-07 16:36:50 -0800255 // Start buffer list at aligned boundary
256 memory_needed = ALIGN_TO(memory_needed, DATA_ALIGNMENT);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800257 memory_needed += sizeof(uint8_t[data_count]);
258 return memory_needed;
259}
260
261size_t get_camera_metadata_size(const camera_metadata_t *metadata) {
262 if (metadata == NULL) return ERROR;
263
264 return metadata->size;
265}
266
267size_t get_camera_metadata_compact_size(const camera_metadata_t *metadata) {
268 if (metadata == NULL) return ERROR;
269
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800270 return calculate_camera_metadata_size(metadata->entry_count,
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800271 metadata->data_count);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800272}
273
274size_t get_camera_metadata_entry_count(const camera_metadata_t *metadata) {
275 return metadata->entry_count;
276}
277
278size_t get_camera_metadata_entry_capacity(const camera_metadata_t *metadata) {
279 return metadata->entry_capacity;
280}
281
282size_t get_camera_metadata_data_count(const camera_metadata_t *metadata) {
283 return metadata->data_count;
284}
285
286size_t get_camera_metadata_data_capacity(const camera_metadata_t *metadata) {
287 return metadata->data_capacity;
288}
289
290camera_metadata_t* copy_camera_metadata(void *dst, size_t dst_size,
291 const camera_metadata_t *src) {
292 size_t memory_needed = get_camera_metadata_compact_size(src);
293
294 if (dst == NULL) return NULL;
295 if (dst_size < memory_needed) return NULL;
296
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800297 camera_metadata_t *metadata =
298 place_camera_metadata(dst, dst_size, src->entry_count, src->data_count);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800299
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700300 metadata->flags = src->flags;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800301 metadata->entry_count = src->entry_count;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800302 metadata->data_count = src->data_count;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800303
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800304 memcpy(get_entries(metadata), get_entries(src),
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700305 sizeof(camera_metadata_buffer_entry_t[metadata->entry_count]));
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800306 memcpy(get_data(metadata), get_data(src),
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800307 sizeof(uint8_t[metadata->data_count]));
Eino-Ville Talvala98d02fd2012-05-21 14:46:49 -0700308 metadata->user = NULL;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800309
Alex Ray151389f2013-11-12 18:09:31 -0800310 assert(validate_camera_metadata_structure(metadata, NULL) == OK);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800311 return metadata;
312}
313
Igor Murashkind1cecc12013-04-30 17:21:54 -0700314int validate_camera_metadata_structure(const camera_metadata_t *metadata,
315 const size_t *expected_size) {
316
317 if (metadata == NULL) {
Zhijun He246a1ad2013-11-26 13:41:18 -0800318 ALOGE("%s: metadata is null!", __FUNCTION__);
Igor Murashkind1cecc12013-04-30 17:21:54 -0700319 return ERROR;
320 }
321
322 // Check that the metadata pointer is well-aligned first.
323 {
324 struct {
325 const char *name;
326 size_t alignment;
327 } alignments[] = {
328 {
329 .name = "camera_metadata",
330 .alignment = _Alignas(struct camera_metadata)
331 },
332 {
333 .name = "camera_metadata_buffer_entry",
334 .alignment = _Alignas(struct camera_metadata_buffer_entry)
335 },
336 {
337 .name = "camera_metadata_data",
338 .alignment = _Alignas(union camera_metadata_data)
339 },
340 };
341
342 for (size_t i = 0; i < sizeof(alignments)/sizeof(alignments[0]); ++i) {
343 uintptr_t aligned_ptr = ALIGN_TO(metadata, alignments[i].alignment);
344
345 if ((uintptr_t)metadata != aligned_ptr) {
346 ALOGE("%s: Metadata pointer is not aligned (actual %p, "
347 "expected %p) to type %s",
348 __FUNCTION__, metadata,
349 (void*)aligned_ptr, alignments[i].name);
350 return ERROR;
351 }
352 }
353 }
354
355 /**
356 * Check that the metadata contents are correct
357 */
358
359 if (expected_size != NULL && metadata->size > *expected_size) {
Mark Salyzyn773e5c82014-03-13 13:24:19 -0700360 ALOGE("%s: Metadata size (%zu) should be <= expected size (%zu)",
Igor Murashkind1cecc12013-04-30 17:21:54 -0700361 __FUNCTION__, metadata->size, *expected_size);
362 return ERROR;
363 }
364
365 if (metadata->entry_count > metadata->entry_capacity) {
Mark Salyzyn773e5c82014-03-13 13:24:19 -0700366 ALOGE("%s: Entry count (%zu) should be <= entry capacity (%zu)",
Igor Murashkind1cecc12013-04-30 17:21:54 -0700367 __FUNCTION__, metadata->entry_count, metadata->entry_capacity);
368 return ERROR;
369 }
370
371 uptrdiff_t entries_end = metadata->entries_start + metadata->entry_capacity;
372 if (entries_end < metadata->entries_start || // overflow check
373 entries_end > metadata->data_start) {
374
Mark Salyzyn773e5c82014-03-13 13:24:19 -0700375 ALOGE("%s: Entry start + capacity (%zu) should be <= data start (%zu)",
Igor Murashkind1cecc12013-04-30 17:21:54 -0700376 __FUNCTION__,
377 (metadata->entries_start + metadata->entry_capacity),
378 metadata->data_start);
379 return ERROR;
380 }
381
382 uptrdiff_t data_end = metadata->data_start + metadata->data_capacity;
383 if (data_end < metadata->data_start || // overflow check
384 data_end > metadata->size) {
385
Mark Salyzyn773e5c82014-03-13 13:24:19 -0700386 ALOGE("%s: Data start + capacity (%zu) should be <= total size (%zu)",
Igor Murashkind1cecc12013-04-30 17:21:54 -0700387 __FUNCTION__,
388 (metadata->data_start + metadata->data_capacity),
389 metadata->size);
390 return ERROR;
391 }
392
393 // Validate each entry
394 size_t entry_count = metadata->entry_count;
395 camera_metadata_buffer_entry_t *entries = get_entries(metadata);
396
397 for (size_t i = 0; i < entry_count; ++i) {
398
399 if ((uintptr_t)&entries[i] != ALIGN_TO(&entries[i], ENTRY_ALIGNMENT)) {
Mark Salyzyn773e5c82014-03-13 13:24:19 -0700400 ALOGE("%s: Entry index %zu had bad alignment (address %p),"
401 " expected alignment %zu",
Igor Murashkind1cecc12013-04-30 17:21:54 -0700402 __FUNCTION__, i, &entries[i], ENTRY_ALIGNMENT);
403 return ERROR;
404 }
405
406 camera_metadata_buffer_entry_t entry = entries[i];
407
408 if (entry.type >= NUM_TYPES) {
Mark Salyzyn773e5c82014-03-13 13:24:19 -0700409 ALOGE("%s: Entry index %zu had a bad type %d",
Igor Murashkind1cecc12013-04-30 17:21:54 -0700410 __FUNCTION__, i, entry.type);
411 return ERROR;
412 }
413
414 // TODO: fix vendor_tag_ops across processes so we don't need to special
415 // case vendor-specific tags
416 uint32_t tag_section = entry.tag >> 16;
417 int tag_type = get_camera_metadata_tag_type(entry.tag);
418 if (tag_type != (int)entry.type && tag_section < VENDOR_SECTION) {
Mark Salyzyn773e5c82014-03-13 13:24:19 -0700419 ALOGE("%s: Entry index %zu had tag type %d, but the type was %d",
Igor Murashkind1cecc12013-04-30 17:21:54 -0700420 __FUNCTION__, i, tag_type, entry.type);
421 return ERROR;
422 }
423
424 size_t data_size =
425 calculate_camera_metadata_entry_data_size(entry.type,
426 entry.count);
427
428 if (data_size != 0) {
429 camera_metadata_data_t *data =
430 (camera_metadata_data_t*) (get_data(metadata) +
431 entry.data.offset);
432
433 if ((uintptr_t)data != ALIGN_TO(data, DATA_ALIGNMENT)) {
Mark Salyzyn773e5c82014-03-13 13:24:19 -0700434 ALOGE("%s: Entry index %zu had bad data alignment (address %p),"
435 " expected align %zu, (tag name %s, data size %zu)",
Igor Murashkind1cecc12013-04-30 17:21:54 -0700436 __FUNCTION__, i, data, DATA_ALIGNMENT,
437 get_camera_metadata_tag_name(entry.tag) ?: "unknown",
438 data_size);
439 return ERROR;
440 }
441
442 size_t data_entry_end = entry.data.offset + data_size;
443 if (data_entry_end < entry.data.offset || // overflow check
444 data_entry_end > metadata->data_capacity) {
445
Mark Salyzyn773e5c82014-03-13 13:24:19 -0700446 ALOGE("%s: Entry index %zu data ends (%zu) beyond the capacity "
447 "%zu", __FUNCTION__, i, data_entry_end,
Igor Murashkind1cecc12013-04-30 17:21:54 -0700448 metadata->data_capacity);
449 return ERROR;
450 }
451
452 } else if (entry.count == 0) {
453 if (entry.data.offset != 0) {
Mark Salyzyn773e5c82014-03-13 13:24:19 -0700454 ALOGE("%s: Entry index %zu had 0 items, but offset was non-0 "
455 "(%zu), tag name: %s", __FUNCTION__, i, entry.data.offset,
Zhijun He3064d312013-07-15 13:55:11 -0700456 get_camera_metadata_tag_name(entry.tag) ?: "unknown");
Igor Murashkind1cecc12013-04-30 17:21:54 -0700457 return ERROR;
458 }
459 } // else data stored inline, so we look at value which can be anything.
460 }
461
462 return OK;
463}
464
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800465int append_camera_metadata(camera_metadata_t *dst,
466 const camera_metadata_t *src) {
467 if (dst == NULL || src == NULL ) return ERROR;
468
469 if (dst->entry_capacity < src->entry_count + dst->entry_count) return ERROR;
470 if (dst->data_capacity < src->data_count + dst->data_count) return ERROR;
471
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800472 memcpy(get_entries(dst) + dst->entry_count, get_entries(src),
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700473 sizeof(camera_metadata_buffer_entry_t[src->entry_count]));
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800474 memcpy(get_data(dst) + dst->data_count, get_data(src),
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800475 sizeof(uint8_t[src->data_count]));
476 if (dst->data_count != 0) {
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800477 camera_metadata_buffer_entry_t *entry = get_entries(dst) + dst->entry_count;
478 for (size_t i = 0; i < src->entry_count; i++, entry++) {
479 if ( calculate_camera_metadata_entry_data_size(entry->type,
480 entry->count) > 0 ) {
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800481 entry->data.offset += dst->data_count;
482 }
483 }
484 }
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700485 if (dst->entry_count == 0) {
486 // Appending onto empty buffer, keep sorted state
487 dst->flags |= src->flags & FLAG_SORTED;
488 } else if (src->entry_count != 0) {
489 // Both src, dst are nonempty, cannot assume sort remains
490 dst->flags &= ~FLAG_SORTED;
491 } else {
492 // Src is empty, keep dst sorted state
493 }
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800494 dst->entry_count += src->entry_count;
495 dst->data_count += src->data_count;
496
Alex Ray151389f2013-11-12 18:09:31 -0800497 assert(validate_camera_metadata_structure(dst, NULL) == OK);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800498 return OK;
499}
500
Eino-Ville Talvala2f4aca62012-08-24 11:42:06 -0700501camera_metadata_t *clone_camera_metadata(const camera_metadata_t *src) {
Eino-Ville Talvalafd258822012-06-06 17:22:42 -0700502 int res;
Eino-Ville Talvala2f4aca62012-08-24 11:42:06 -0700503 if (src == NULL) return NULL;
Eino-Ville Talvalafd258822012-06-06 17:22:42 -0700504 camera_metadata_t *clone = allocate_camera_metadata(
505 get_camera_metadata_entry_count(src),
506 get_camera_metadata_data_count(src));
507 if (clone != NULL) {
508 res = append_camera_metadata(clone, src);
509 if (res != OK) {
510 free_camera_metadata(clone);
511 clone = NULL;
512 }
513 }
Alex Ray151389f2013-11-12 18:09:31 -0800514 assert(validate_camera_metadata_structure(clone, NULL) == OK);
Eino-Ville Talvalafd258822012-06-06 17:22:42 -0700515 return clone;
516}
517
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800518size_t calculate_camera_metadata_entry_data_size(uint8_t type,
519 size_t data_count) {
520 if (type >= NUM_TYPES) return 0;
521 size_t data_bytes = data_count *
522 camera_metadata_type_size[type];
Eino-Ville Talvala31540362012-11-07 16:36:50 -0800523 return data_bytes <= 4 ? 0 : ALIGN_TO(data_bytes, DATA_ALIGNMENT);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800524}
525
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700526static int add_camera_metadata_entry_raw(camera_metadata_t *dst,
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800527 uint32_t tag,
528 uint8_t type,
529 const void *data,
530 size_t data_count) {
531
532 if (dst == NULL) return ERROR;
533 if (dst->entry_count == dst->entry_capacity) return ERROR;
534 if (data == NULL) return ERROR;
535
536 size_t data_bytes =
537 calculate_camera_metadata_entry_data_size(type, data_count);
Eino-Ville Talvala31540362012-11-07 16:36:50 -0800538 if (data_bytes + dst->data_count > dst->data_capacity) return ERROR;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800539
Eino-Ville Talvala31540362012-11-07 16:36:50 -0800540 size_t data_payload_bytes =
541 data_count * camera_metadata_type_size[type];
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800542 camera_metadata_buffer_entry_t *entry = get_entries(dst) + dst->entry_count;
Zhijun He3064d312013-07-15 13:55:11 -0700543 memset(entry, 0, sizeof(camera_metadata_buffer_entry_t));
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800544 entry->tag = tag;
545 entry->type = type;
546 entry->count = data_count;
547
548 if (data_bytes == 0) {
549 memcpy(entry->data.value, data,
Eino-Ville Talvala31540362012-11-07 16:36:50 -0800550 data_payload_bytes);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800551 } else {
552 entry->data.offset = dst->data_count;
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800553 memcpy(get_data(dst) + entry->data.offset, data,
Eino-Ville Talvala31540362012-11-07 16:36:50 -0800554 data_payload_bytes);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800555 dst->data_count += data_bytes;
556 }
557 dst->entry_count++;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700558 dst->flags &= ~FLAG_SORTED;
Alex Ray151389f2013-11-12 18:09:31 -0800559 assert(validate_camera_metadata_structure(dst, NULL) == OK);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800560 return OK;
561}
562
563int add_camera_metadata_entry(camera_metadata_t *dst,
564 uint32_t tag,
565 const void *data,
566 size_t data_count) {
567
568 int type = get_camera_metadata_tag_type(tag);
569 if (type == -1) {
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700570 ALOGE("%s: Unknown tag %04x.", __FUNCTION__, tag);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800571 return ERROR;
572 }
573
574 return add_camera_metadata_entry_raw(dst,
575 tag,
576 type,
577 data,
578 data_count);
579}
580
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700581static int compare_entry_tags(const void *p1, const void *p2) {
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700582 uint32_t tag1 = ((camera_metadata_buffer_entry_t*)p1)->tag;
583 uint32_t tag2 = ((camera_metadata_buffer_entry_t*)p2)->tag;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700584 return tag1 < tag2 ? -1 :
585 tag1 == tag2 ? 0 :
586 1;
587}
588
589int sort_camera_metadata(camera_metadata_t *dst) {
590 if (dst == NULL) return ERROR;
591 if (dst->flags & FLAG_SORTED) return OK;
592
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800593 qsort(get_entries(dst), dst->entry_count,
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700594 sizeof(camera_metadata_buffer_entry_t),
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700595 compare_entry_tags);
596 dst->flags |= FLAG_SORTED;
597
Alex Ray151389f2013-11-12 18:09:31 -0800598 assert(validate_camera_metadata_structure(dst, NULL) == OK);
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700599 return OK;
600}
601
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800602int get_camera_metadata_entry(camera_metadata_t *src,
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700603 size_t index,
604 camera_metadata_entry_t *entry) {
605 if (src == NULL || entry == NULL) return ERROR;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800606 if (index >= src->entry_count) return ERROR;
607
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800608 camera_metadata_buffer_entry_t *buffer_entry = get_entries(src) + index;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800609
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700610 entry->index = index;
611 entry->tag = buffer_entry->tag;
612 entry->type = buffer_entry->type;
613 entry->count = buffer_entry->count;
614 if (buffer_entry->count *
615 camera_metadata_type_size[buffer_entry->type] > 4) {
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800616 entry->data.u8 = get_data(src) + buffer_entry->data.offset;
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700617 } else {
618 entry->data.u8 = buffer_entry->data.value;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700619 }
620 return OK;
621}
622
Alex Ray71fe0f82013-10-21 12:57:05 -0700623int get_camera_metadata_ro_entry(const camera_metadata_t *src,
624 size_t index,
625 camera_metadata_ro_entry_t *entry) {
626 return get_camera_metadata_entry((camera_metadata_t*)src, index,
627 (camera_metadata_entry_t*)entry);
628}
629
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700630int find_camera_metadata_entry(camera_metadata_t *src,
631 uint32_t tag,
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700632 camera_metadata_entry_t *entry) {
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700633 if (src == NULL) return ERROR;
634
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700635 uint32_t index;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700636 if (src->flags & FLAG_SORTED) {
637 // Sorted entries, do a binary search
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700638 camera_metadata_buffer_entry_t *search_entry = NULL;
639 camera_metadata_buffer_entry_t key;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700640 key.tag = tag;
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700641 search_entry = bsearch(&key,
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800642 get_entries(src),
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700643 src->entry_count,
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700644 sizeof(camera_metadata_buffer_entry_t),
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700645 compare_entry_tags);
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700646 if (search_entry == NULL) return NOT_FOUND;
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800647 index = search_entry - get_entries(src);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800648 } else {
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700649 // Not sorted, linear search
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800650 camera_metadata_buffer_entry_t *search_entry = get_entries(src);
651 for (index = 0; index < src->entry_count; index++, search_entry++) {
652 if (search_entry->tag == tag) {
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700653 break;
654 }
655 }
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700656 if (index == src->entry_count) return NOT_FOUND;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700657 }
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700658
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700659 return get_camera_metadata_entry(src, index,
660 entry);
661}
662
Eino-Ville Talvala2f4aca62012-08-24 11:42:06 -0700663int find_camera_metadata_ro_entry(const camera_metadata_t *src,
664 uint32_t tag,
665 camera_metadata_ro_entry_t *entry) {
666 return find_camera_metadata_entry((camera_metadata_t*)src, tag,
667 (camera_metadata_entry_t*)entry);
668}
669
670
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700671int delete_camera_metadata_entry(camera_metadata_t *dst,
672 size_t index) {
673 if (dst == NULL) return ERROR;
674 if (index >= dst->entry_count) return ERROR;
675
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800676 camera_metadata_buffer_entry_t *entry = get_entries(dst) + index;
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700677 size_t data_bytes = calculate_camera_metadata_entry_data_size(entry->type,
678 entry->count);
679
680 if (data_bytes > 0) {
681 // Shift data buffer to overwrite deleted data
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800682 uint8_t *start = get_data(dst) + entry->data.offset;
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700683 uint8_t *end = start + data_bytes;
684 size_t length = dst->data_count - entry->data.offset - data_bytes;
685 memmove(start, end, length);
686
687 // Update all entry indices to account for shift
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800688 camera_metadata_buffer_entry_t *e = get_entries(dst);
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700689 size_t i;
690 for (i = 0; i < dst->entry_count; i++) {
691 if (calculate_camera_metadata_entry_data_size(
692 e->type, e->count) > 0 &&
693 e->data.offset > entry->data.offset) {
694 e->data.offset -= data_bytes;
695 }
696 ++e;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700697 }
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700698 dst->data_count -= data_bytes;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800699 }
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700700 // Shift entry array
701 memmove(entry, entry + 1,
702 sizeof(camera_metadata_buffer_entry_t) *
703 (dst->entry_count - index - 1) );
704 dst->entry_count -= 1;
705
Alex Ray151389f2013-11-12 18:09:31 -0800706 assert(validate_camera_metadata_structure(dst, NULL) == OK);
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700707 return OK;
708}
709
710int update_camera_metadata_entry(camera_metadata_t *dst,
711 size_t index,
712 const void *data,
713 size_t data_count,
714 camera_metadata_entry_t *updated_entry) {
715 if (dst == NULL) return ERROR;
716 if (index >= dst->entry_count) return ERROR;
717
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800718 camera_metadata_buffer_entry_t *entry = get_entries(dst) + index;
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700719
720 size_t data_bytes =
721 calculate_camera_metadata_entry_data_size(entry->type,
722 data_count);
Eino-Ville Talvala31540362012-11-07 16:36:50 -0800723 size_t data_payload_bytes =
724 data_count * camera_metadata_type_size[entry->type];
725
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700726 size_t entry_bytes =
727 calculate_camera_metadata_entry_data_size(entry->type,
728 entry->count);
729 if (data_bytes != entry_bytes) {
730 // May need to shift/add to data array
731 if (dst->data_capacity < dst->data_count + data_bytes - entry_bytes) {
732 // No room
733 return ERROR;
734 }
735 if (entry_bytes != 0) {
736 // Remove old data
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800737 uint8_t *start = get_data(dst) + entry->data.offset;
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700738 uint8_t *end = start + entry_bytes;
739 size_t length = dst->data_count - entry->data.offset - entry_bytes;
740 memmove(start, end, length);
741 dst->data_count -= entry_bytes;
742
743 // Update all entry indices to account for shift
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800744 camera_metadata_buffer_entry_t *e = get_entries(dst);
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700745 size_t i;
746 for (i = 0; i < dst->entry_count; i++) {
747 if (calculate_camera_metadata_entry_data_size(
748 e->type, e->count) > 0 &&
749 e->data.offset > entry->data.offset) {
750 e->data.offset -= entry_bytes;
751 }
752 ++e;
753 }
754 }
755
756 if (data_bytes != 0) {
757 // Append new data
758 entry->data.offset = dst->data_count;
759
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800760 memcpy(get_data(dst) + entry->data.offset, data, data_payload_bytes);
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700761 dst->data_count += data_bytes;
762 }
763 } else if (data_bytes != 0) {
764 // data size unchanged, reuse same data location
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800765 memcpy(get_data(dst) + entry->data.offset, data, data_payload_bytes);
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700766 }
767
768 if (data_bytes == 0) {
769 // Data fits into entry
770 memcpy(entry->data.value, data,
Eino-Ville Talvala31540362012-11-07 16:36:50 -0800771 data_payload_bytes);
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700772 }
773
774 entry->count = data_count;
775
776 if (updated_entry != NULL) {
777 get_camera_metadata_entry(dst,
778 index,
779 updated_entry);
780 }
781
Alex Ray151389f2013-11-12 18:09:31 -0800782 assert(validate_camera_metadata_structure(dst, NULL) == OK);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800783 return OK;
784}
785
Eino-Ville Talvala98d02fd2012-05-21 14:46:49 -0700786int set_camera_metadata_user_pointer(camera_metadata_t *dst, void* user) {
787 if (dst == NULL) return ERROR;
788 dst->user = user;
789 return OK;
790}
791
792int get_camera_metadata_user_pointer(camera_metadata_t *dst, void** user) {
793 if (dst == NULL) return ERROR;
794 *user = dst->user;
795 return OK;
796}
797
Ruben Brunk9c13e192014-02-14 16:40:56 -0800798static const vendor_tag_ops_t *vendor_tag_ops = NULL;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800799
800const char *get_camera_metadata_section_name(uint32_t tag) {
801 uint32_t tag_section = tag >> 16;
802 if (tag_section >= VENDOR_SECTION && vendor_tag_ops != NULL) {
Ruben Brunk9c13e192014-02-14 16:40:56 -0800803 return vendor_tag_ops->get_section_name(
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700804 vendor_tag_ops,
805 tag);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800806 }
807 if (tag_section >= ANDROID_SECTION_COUNT) {
808 return NULL;
809 }
810 return camera_metadata_section_names[tag_section];
811}
812
813const char *get_camera_metadata_tag_name(uint32_t tag) {
814 uint32_t tag_section = tag >> 16;
815 if (tag_section >= VENDOR_SECTION && vendor_tag_ops != NULL) {
Ruben Brunk9c13e192014-02-14 16:40:56 -0800816 return vendor_tag_ops->get_tag_name(
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700817 vendor_tag_ops,
818 tag);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800819 }
820 if (tag_section >= ANDROID_SECTION_COUNT ||
821 tag >= camera_metadata_section_bounds[tag_section][1] ) {
822 return NULL;
823 }
824 uint32_t tag_index = tag & 0xFFFF;
825 return tag_info[tag_section][tag_index].tag_name;
826}
827
828int get_camera_metadata_tag_type(uint32_t tag) {
829 uint32_t tag_section = tag >> 16;
830 if (tag_section >= VENDOR_SECTION && vendor_tag_ops != NULL) {
Ruben Brunk9c13e192014-02-14 16:40:56 -0800831 return vendor_tag_ops->get_tag_type(
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700832 vendor_tag_ops,
833 tag);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800834 }
835 if (tag_section >= ANDROID_SECTION_COUNT ||
836 tag >= camera_metadata_section_bounds[tag_section][1] ) {
837 return -1;
838 }
839 uint32_t tag_index = tag & 0xFFFF;
840 return tag_info[tag_section][tag_index].tag_type;
841}
842
Ruben Brunk9c13e192014-02-14 16:40:56 -0800843int set_camera_metadata_vendor_tag_ops(const vendor_tag_query_ops_t* ops) {
844 // **DEPRECATED**
845 ALOGE("%s: This function has been deprecated", __FUNCTION__);
846 return ERROR;
847}
848
849// Declared in system/media/private/camera/include/camera_metadata_hidden.h
850int set_camera_metadata_vendor_ops(const vendor_tag_ops_t* ops) {
851 vendor_tag_ops = ops;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800852 return OK;
853}
854
Igor Murashkin375cfd32012-12-03 13:55:33 -0800855static void print_data(int fd, const uint8_t *data_ptr, uint32_t tag, int type,
856 int count,
Eino-Ville Talvala1d27e5b2012-07-30 10:46:22 -0700857 int indentation);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800858
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700859void dump_camera_metadata(const camera_metadata_t *metadata,
860 int fd,
861 int verbosity) {
Eino-Ville Talvala1d27e5b2012-07-30 10:46:22 -0700862 dump_indented_camera_metadata(metadata, fd, verbosity, 0);
863}
864
865void dump_indented_camera_metadata(const camera_metadata_t *metadata,
866 int fd,
867 int verbosity,
868 int indentation) {
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800869 if (metadata == NULL) {
Elliott Hughes8e86c9c2014-05-22 01:18:02 -0700870 dprintf(fd, "%*sDumping camera metadata array: Not allocated\n",
Eino-Ville Talvala2f4aca62012-08-24 11:42:06 -0700871 indentation, "");
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800872 return;
873 }
874 unsigned int i;
Elliott Hughes8e86c9c2014-05-22 01:18:02 -0700875 dprintf(fd,
Mark Salyzyn773e5c82014-03-13 13:24:19 -0700876 "%*sDumping camera metadata array: %zu / %zu entries, "
877 "%zu / %zu bytes of extra data.\n", indentation, "",
Eino-Ville Talvala1d27e5b2012-07-30 10:46:22 -0700878 metadata->entry_count, metadata->entry_capacity,
879 metadata->data_count, metadata->data_capacity);
Elliott Hughes8e86c9c2014-05-22 01:18:02 -0700880 dprintf(fd, "%*sVersion: %d, Flags: %08x\n",
Eino-Ville Talvala1d27e5b2012-07-30 10:46:22 -0700881 indentation + 2, "",
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700882 metadata->version, metadata->flags);
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800883 camera_metadata_buffer_entry_t *entry = get_entries(metadata);
884 for (i=0; i < metadata->entry_count; i++, entry++) {
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800885
886 const char *tag_name, *tag_section;
887 tag_section = get_camera_metadata_section_name(entry->tag);
888 if (tag_section == NULL) {
889 tag_section = "unknownSection";
890 }
891 tag_name = get_camera_metadata_tag_name(entry->tag);
892 if (tag_name == NULL) {
893 tag_name = "unknownTag";
894 }
895 const char *type_name;
896 if (entry->type >= NUM_TYPES) {
897 type_name = "unknown";
898 } else {
899 type_name = camera_metadata_type_names[entry->type];
900 }
Elliott Hughes8e86c9c2014-05-22 01:18:02 -0700901 dprintf(fd, "%*s%s.%s (%05x): %s[%zu]\n",
Eino-Ville Talvala1d27e5b2012-07-30 10:46:22 -0700902 indentation + 2, "",
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800903 tag_section,
904 tag_name,
905 entry->tag,
906 type_name,
907 entry->count);
908
909 if (verbosity < 1) continue;
910
911 if (entry->type >= NUM_TYPES) continue;
912
913 size_t type_size = camera_metadata_type_size[entry->type];
914 uint8_t *data_ptr;
915 if ( type_size * entry->count > 4 ) {
916 if (entry->data.offset >= metadata->data_count) {
Mark Salyzyn773e5c82014-03-13 13:24:19 -0700917 ALOGE("%s: Malformed entry data offset: %zu (max %zu)",
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700918 __FUNCTION__,
919 entry->data.offset,
920 metadata->data_count);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800921 continue;
922 }
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800923 data_ptr = get_data(metadata) + entry->data.offset;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800924 } else {
925 data_ptr = entry->data.value;
926 }
927 int count = entry->count;
928 if (verbosity < 2 && count > 16) count = 16;
929
Igor Murashkin375cfd32012-12-03 13:55:33 -0800930 print_data(fd, data_ptr, entry->tag, entry->type, count, indentation);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800931 }
932}
933
Igor Murashkin375cfd32012-12-03 13:55:33 -0800934static void print_data(int fd, const uint8_t *data_ptr, uint32_t tag,
Eino-Ville Talvala1d27e5b2012-07-30 10:46:22 -0700935 int type, int count, int indentation) {
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800936 static int values_per_line[NUM_TYPES] = {
937 [TYPE_BYTE] = 16,
938 [TYPE_INT32] = 4,
939 [TYPE_FLOAT] = 8,
940 [TYPE_INT64] = 2,
941 [TYPE_DOUBLE] = 4,
942 [TYPE_RATIONAL] = 2,
943 };
944 size_t type_size = camera_metadata_type_size[type];
Igor Murashkin375cfd32012-12-03 13:55:33 -0800945 char value_string_tmp[CAMERA_METADATA_ENUM_STRING_MAX_SIZE];
946 uint32_t value;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800947
948 int lines = count / values_per_line[type];
949 if (count % values_per_line[type] != 0) lines++;
950
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800951 int index = 0;
952 int j, k;
953 for (j = 0; j < lines; j++) {
Elliott Hughes8e86c9c2014-05-22 01:18:02 -0700954 dprintf(fd, "%*s[", indentation + 4, "");
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800955 for (k = 0;
956 k < values_per_line[type] && count > 0;
957 k++, count--, index += type_size) {
958
959 switch (type) {
960 case TYPE_BYTE:
Igor Murashkin375cfd32012-12-03 13:55:33 -0800961 value = *(data_ptr + index);
962 if (camera_metadata_enum_snprint(tag,
963 value,
964 value_string_tmp,
965 sizeof(value_string_tmp))
966 == OK) {
Elliott Hughes8e86c9c2014-05-22 01:18:02 -0700967 dprintf(fd, "%s ", value_string_tmp);
Igor Murashkin375cfd32012-12-03 13:55:33 -0800968 } else {
Elliott Hughes8e86c9c2014-05-22 01:18:02 -0700969 dprintf(fd, "%hhu ",
Igor Murashkin375cfd32012-12-03 13:55:33 -0800970 *(data_ptr + index));
971 }
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800972 break;
973 case TYPE_INT32:
Igor Murashkin375cfd32012-12-03 13:55:33 -0800974 value =
975 *(int32_t*)(data_ptr + index);
976 if (camera_metadata_enum_snprint(tag,
977 value,
978 value_string_tmp,
979 sizeof(value_string_tmp))
980 == OK) {
Elliott Hughes8e86c9c2014-05-22 01:18:02 -0700981 dprintf(fd, "%s ", value_string_tmp);
Igor Murashkin375cfd32012-12-03 13:55:33 -0800982 } else {
Elliott Hughes8e86c9c2014-05-22 01:18:02 -0700983 dprintf(fd, "%" PRId32 " ",
Igor Murashkin375cfd32012-12-03 13:55:33 -0800984 *(int32_t*)(data_ptr + index));
985 }
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800986 break;
987 case TYPE_FLOAT:
Elliott Hughesd1c33572014-05-22 10:53:20 -0700988 dprintf(fd, "%0.8f ",
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800989 *(float*)(data_ptr + index));
990 break;
991 case TYPE_INT64:
Elliott Hughes8e86c9c2014-05-22 01:18:02 -0700992 dprintf(fd, "%" PRId64 " ",
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800993 *(int64_t*)(data_ptr + index));
994 break;
995 case TYPE_DOUBLE:
Elliott Hughesd1c33572014-05-22 10:53:20 -0700996 dprintf(fd, "%0.8f ",
Eino-Ville Talvala31540362012-11-07 16:36:50 -0800997 *(double*)(data_ptr + index));
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800998 break;
999 case TYPE_RATIONAL: {
1000 int32_t numerator = *(int32_t*)(data_ptr + index);
1001 int32_t denominator = *(int32_t*)(data_ptr + index + 4);
Elliott Hughes8e86c9c2014-05-22 01:18:02 -07001002 dprintf(fd, "(%d / %d) ",
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -08001003 numerator, denominator);
1004 break;
1005 }
1006 default:
Elliott Hughes8e86c9c2014-05-22 01:18:02 -07001007 dprintf(fd, "??? ");
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -08001008 }
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -08001009 }
Elliott Hughes8e86c9c2014-05-22 01:18:02 -07001010 dprintf(fd, "]\n");
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -08001011 }
1012}