1 /*
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 */
16 #define _GNU_SOURCE // for fdprintf
17 #include <system/camera_metadata.h>
18
19 #define LOG_TAG "camera_metadata"
20 #include <cutils/log.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <errno.h>
24
25 #define OK 0
26 #define ERROR 1
27 #define NOT_FOUND -ENOENT
28
29 #define _Alignas(T) \
30 ({struct _AlignasStruct { char c; T field; }; \
31 offsetof(struct _AlignasStruct, field); })
32
33 // Align entry buffers as the compiler would
34 #define ENTRY_ALIGNMENT _Alignas(camera_metadata_buffer_entry_t)
35 // Align data buffer to largest supported data type
36 #define DATA_ALIGNMENT _Alignas(camera_metadata_data_t)
37
38 #define ALIGN_TO(val, alignment) \
39 (((uintptr_t)(val) + ((alignment) - 1)) & ~((alignment) - 1))
40
41 typedef size_t uptrdiff_t;
42
43 /**
44 * A single metadata entry, storing an array of values of a given type. If the
45 * array is no larger than 4 bytes in size, it is stored in the data.value[]
46 * array; otherwise, it can found in the parent's data array at index
47 * data.offset.
48 */
49 typedef struct camera_metadata_buffer_entry {
50 uint32_t tag;
51 size_t count;
52 union {
53 size_t offset;
54 uint8_t value[4];
55 } data;
56 uint8_t type;
57 uint8_t reserved[3];
58 } camera_metadata_buffer_entry_t;
59
60 /**
61 * A packet of metadata. This is a list of entries, each of which may point to
62 * its values stored at an offset in data.
63 *
64 * It is assumed by the utility functions that the memory layout of the packet
65 * is as follows:
66 *
67 * |-----------------------------------------------|
68 * | camera_metadata_t |
69 * | |
70 * |-----------------------------------------------|
71 * | reserved for future expansion |
72 * |-----------------------------------------------|
73 * | camera_metadata_buffer_entry_t #0 |
74 * |-----------------------------------------------|
75 * | .... |
76 * |-----------------------------------------------|
77 * | camera_metadata_buffer_entry_t #entry_count-1 |
78 * |-----------------------------------------------|
79 * | free space for |
80 * | (entry_capacity-entry_count) entries |
81 * |-----------------------------------------------|
82 * | start of camera_metadata.data |
83 * | |
84 * |-----------------------------------------------|
85 * | free space for |
86 * | (data_capacity-data_count) bytes |
87 * |-----------------------------------------------|
88 *
89 * With the total length of the whole packet being camera_metadata.size bytes.
90 *
91 * In short, the entries and data are contiguous in memory after the metadata
92 * header.
93 */
94 struct camera_metadata {
95 size_t size;
96 uint32_t version;
97 uint32_t flags;
98 size_t entry_count;
99 size_t entry_capacity;
100 uptrdiff_t entries_start; // Offset from camera_metadata
101 size_t data_count;
102 size_t data_capacity;
103 uptrdiff_t data_start; // Offset from camera_metadata
104 void *user; // User set pointer, not copied with buffer
105 uint8_t reserved[0];
106 };
107
108 /**
109 * A datum of metadata. This corresponds to camera_metadata_entry_t::data
110 * with the difference that each element is not a pointer. We need to have a
111 * non-pointer type description in order to figure out the largest alignment
112 * requirement for data (DATA_ALIGNMENT).
113 */
114 typedef union camera_metadata_data {
115 uint8_t u8;
116 int32_t i32;
117 float f;
118 int64_t i64;
119 double d;
120 camera_metadata_rational_t r;
121 } camera_metadata_data_t;
122
123 /** Versioning information */
124 #define CURRENT_METADATA_VERSION 1
125
126 /** Flag definitions */
127 #define FLAG_SORTED 0x00000001
128
129 /** Tag information */
130
131 typedef struct tag_info {
132 const char *tag_name;
133 uint8_t tag_type;
134 } tag_info_t;
135
136 #include "camera_metadata_tag_info.c"
137
138 const size_t camera_metadata_type_size[NUM_TYPES] = {
139 [TYPE_BYTE] = sizeof(uint8_t),
140 [TYPE_INT32] = sizeof(int32_t),
141 [TYPE_FLOAT] = sizeof(float),
142 [TYPE_INT64] = sizeof(int64_t),
143 [TYPE_DOUBLE] = sizeof(double),
144 [TYPE_RATIONAL] = sizeof(camera_metadata_rational_t)
145 };
146
147 const char *camera_metadata_type_names[NUM_TYPES] = {
148 [TYPE_BYTE] = "byte",
149 [TYPE_INT32] = "int32",
150 [TYPE_FLOAT] = "float",
151 [TYPE_INT64] = "int64",
152 [TYPE_DOUBLE] = "double",
153 [TYPE_RATIONAL] = "rational"
154 };
155
get_entries(const camera_metadata_t * metadata)156 static camera_metadata_buffer_entry_t *get_entries(
157 const camera_metadata_t *metadata) {
158 return (camera_metadata_buffer_entry_t*)
159 ((uint8_t*)metadata + metadata->entries_start);
160 }
161
get_data(const camera_metadata_t * metadata)162 static uint8_t *get_data(const camera_metadata_t *metadata) {
163 return (uint8_t*)metadata + metadata->data_start;
164 }
165
allocate_copy_camera_metadata_checked(const camera_metadata_t * src,size_t src_size)166 camera_metadata_t *allocate_copy_camera_metadata_checked(
167 const camera_metadata_t *src,
168 size_t src_size) {
169
170 if (src == NULL) {
171 return NULL;
172 }
173
174 void *buffer = malloc(src_size);
175 memcpy(buffer, src, src_size);
176
177 camera_metadata_t *metadata = (camera_metadata_t*) buffer;
178 if (validate_camera_metadata_structure(metadata, &src_size) != OK) {
179 free(buffer);
180 return NULL;
181 }
182
183 return metadata;
184 }
185
allocate_camera_metadata(size_t entry_capacity,size_t data_capacity)186 camera_metadata_t *allocate_camera_metadata(size_t entry_capacity,
187 size_t data_capacity) {
188 if (entry_capacity == 0) return NULL;
189
190 size_t memory_needed = calculate_camera_metadata_size(entry_capacity,
191 data_capacity);
192 void *buffer = malloc(memory_needed);
193 return place_camera_metadata(buffer, memory_needed,
194 entry_capacity,
195 data_capacity);
196 }
197
place_camera_metadata(void * dst,size_t dst_size,size_t entry_capacity,size_t data_capacity)198 camera_metadata_t *place_camera_metadata(void *dst,
199 size_t dst_size,
200 size_t entry_capacity,
201 size_t data_capacity) {
202 if (dst == NULL) return NULL;
203 if (entry_capacity == 0) return NULL;
204
205 size_t memory_needed = calculate_camera_metadata_size(entry_capacity,
206 data_capacity);
207 if (memory_needed > dst_size) return NULL;
208
209 camera_metadata_t *metadata = (camera_metadata_t*)dst;
210 metadata->version = CURRENT_METADATA_VERSION;
211 metadata->flags = 0;
212 metadata->entry_count = 0;
213 metadata->entry_capacity = entry_capacity;
214 metadata->entries_start =
215 ALIGN_TO(sizeof(camera_metadata_t), ENTRY_ALIGNMENT);
216 metadata->data_count = 0;
217 metadata->data_capacity = data_capacity;
218 metadata->size = memory_needed;
219 size_t data_unaligned = (uint8_t*)(get_entries(metadata) +
220 metadata->entry_capacity) - (uint8_t*)metadata;
221 metadata->data_start = ALIGN_TO(data_unaligned, DATA_ALIGNMENT);
222 metadata->user = NULL;
223
224 return metadata;
225 }
free_camera_metadata(camera_metadata_t * metadata)226 void free_camera_metadata(camera_metadata_t *metadata) {
227 free(metadata);
228 }
229
calculate_camera_metadata_size(size_t entry_count,size_t data_count)230 size_t calculate_camera_metadata_size(size_t entry_count,
231 size_t data_count) {
232 size_t memory_needed = sizeof(camera_metadata_t);
233 // Start entry list at aligned boundary
234 memory_needed = ALIGN_TO(memory_needed, ENTRY_ALIGNMENT);
235 memory_needed += sizeof(camera_metadata_buffer_entry_t[entry_count]);
236 // Start buffer list at aligned boundary
237 memory_needed = ALIGN_TO(memory_needed, DATA_ALIGNMENT);
238 memory_needed += sizeof(uint8_t[data_count]);
239 return memory_needed;
240 }
241
get_camera_metadata_size(const camera_metadata_t * metadata)242 size_t get_camera_metadata_size(const camera_metadata_t *metadata) {
243 if (metadata == NULL) return ERROR;
244
245 return metadata->size;
246 }
247
get_camera_metadata_compact_size(const camera_metadata_t * metadata)248 size_t get_camera_metadata_compact_size(const camera_metadata_t *metadata) {
249 if (metadata == NULL) return ERROR;
250
251 return calculate_camera_metadata_size(metadata->entry_count,
252 metadata->data_count);
253 }
254
get_camera_metadata_entry_count(const camera_metadata_t * metadata)255 size_t get_camera_metadata_entry_count(const camera_metadata_t *metadata) {
256 return metadata->entry_count;
257 }
258
get_camera_metadata_entry_capacity(const camera_metadata_t * metadata)259 size_t get_camera_metadata_entry_capacity(const camera_metadata_t *metadata) {
260 return metadata->entry_capacity;
261 }
262
get_camera_metadata_data_count(const camera_metadata_t * metadata)263 size_t get_camera_metadata_data_count(const camera_metadata_t *metadata) {
264 return metadata->data_count;
265 }
266
get_camera_metadata_data_capacity(const camera_metadata_t * metadata)267 size_t get_camera_metadata_data_capacity(const camera_metadata_t *metadata) {
268 return metadata->data_capacity;
269 }
270
copy_camera_metadata(void * dst,size_t dst_size,const camera_metadata_t * src)271 camera_metadata_t* copy_camera_metadata(void *dst, size_t dst_size,
272 const camera_metadata_t *src) {
273 size_t memory_needed = get_camera_metadata_compact_size(src);
274
275 if (dst == NULL) return NULL;
276 if (dst_size < memory_needed) return NULL;
277
278 camera_metadata_t *metadata =
279 place_camera_metadata(dst, dst_size, src->entry_count, src->data_count);
280
281 metadata->flags = src->flags;
282 metadata->entry_count = src->entry_count;
283 metadata->data_count = src->data_count;
284
285 memcpy(get_entries(metadata), get_entries(src),
286 sizeof(camera_metadata_buffer_entry_t[metadata->entry_count]));
287 memcpy(get_data(metadata), get_data(src),
288 sizeof(uint8_t[metadata->data_count]));
289 metadata->user = NULL;
290
291 return metadata;
292 }
293
validate_camera_metadata_structure(const camera_metadata_t * metadata,const size_t * expected_size)294 int validate_camera_metadata_structure(const camera_metadata_t *metadata,
295 const size_t *expected_size) {
296
297 if (metadata == NULL) {
298 return ERROR;
299 }
300
301 // Check that the metadata pointer is well-aligned first.
302 {
303 struct {
304 const char *name;
305 size_t alignment;
306 } alignments[] = {
307 {
308 .name = "camera_metadata",
309 .alignment = _Alignas(struct camera_metadata)
310 },
311 {
312 .name = "camera_metadata_buffer_entry",
313 .alignment = _Alignas(struct camera_metadata_buffer_entry)
314 },
315 {
316 .name = "camera_metadata_data",
317 .alignment = _Alignas(union camera_metadata_data)
318 },
319 };
320
321 for (size_t i = 0; i < sizeof(alignments)/sizeof(alignments[0]); ++i) {
322 uintptr_t aligned_ptr = ALIGN_TO(metadata, alignments[i].alignment);
323
324 if ((uintptr_t)metadata != aligned_ptr) {
325 ALOGE("%s: Metadata pointer is not aligned (actual %p, "
326 "expected %p) to type %s",
327 __FUNCTION__, metadata,
328 (void*)aligned_ptr, alignments[i].name);
329 return ERROR;
330 }
331 }
332 }
333
334 /**
335 * Check that the metadata contents are correct
336 */
337
338 if (expected_size != NULL && metadata->size > *expected_size) {
339 ALOGE("%s: Metadata size (%u) should be <= expected size (%u)",
340 __FUNCTION__, metadata->size, *expected_size);
341 return ERROR;
342 }
343
344 if (metadata->entry_count > metadata->entry_capacity) {
345 ALOGE("%s: Entry count (%u) should be <= entry capacity (%u)",
346 __FUNCTION__, metadata->entry_count, metadata->entry_capacity);
347 return ERROR;
348 }
349
350 uptrdiff_t entries_end = metadata->entries_start + metadata->entry_capacity;
351 if (entries_end < metadata->entries_start || // overflow check
352 entries_end > metadata->data_start) {
353
354 ALOGE("%s: Entry start + capacity (%u) should be <= data start (%u)",
355 __FUNCTION__,
356 (metadata->entries_start + metadata->entry_capacity),
357 metadata->data_start);
358 return ERROR;
359 }
360
361 uptrdiff_t data_end = metadata->data_start + metadata->data_capacity;
362 if (data_end < metadata->data_start || // overflow check
363 data_end > metadata->size) {
364
365 ALOGE("%s: Data start + capacity (%u) should be <= total size (%u)",
366 __FUNCTION__,
367 (metadata->data_start + metadata->data_capacity),
368 metadata->size);
369 return ERROR;
370 }
371
372 // Validate each entry
373 size_t entry_count = metadata->entry_count;
374 camera_metadata_buffer_entry_t *entries = get_entries(metadata);
375
376 for (size_t i = 0; i < entry_count; ++i) {
377
378 if ((uintptr_t)&entries[i] != ALIGN_TO(&entries[i], ENTRY_ALIGNMENT)) {
379 ALOGE("%s: Entry index %u had bad alignment (address %p),"
380 " expected alignment %d",
381 __FUNCTION__, i, &entries[i], ENTRY_ALIGNMENT);
382 return ERROR;
383 }
384
385 camera_metadata_buffer_entry_t entry = entries[i];
386
387 if (entry.type >= NUM_TYPES) {
388 ALOGE("%s: Entry index %u had a bad type %d",
389 __FUNCTION__, i, entry.type);
390 return ERROR;
391 }
392
393 // TODO: fix vendor_tag_ops across processes so we don't need to special
394 // case vendor-specific tags
395 uint32_t tag_section = entry.tag >> 16;
396 int tag_type = get_camera_metadata_tag_type(entry.tag);
397 if (tag_type != (int)entry.type && tag_section < VENDOR_SECTION) {
398 ALOGE("%s: Entry index %u had tag type %d, but the type was %d",
399 __FUNCTION__, i, tag_type, entry.type);
400 return ERROR;
401 }
402
403 size_t data_size =
404 calculate_camera_metadata_entry_data_size(entry.type,
405 entry.count);
406
407 if (data_size != 0) {
408 camera_metadata_data_t *data =
409 (camera_metadata_data_t*) (get_data(metadata) +
410 entry.data.offset);
411
412 if ((uintptr_t)data != ALIGN_TO(data, DATA_ALIGNMENT)) {
413 ALOGE("%s: Entry index %u had bad data alignment (address %p),"
414 " expected align %d, (tag name %s, data size %u)",
415 __FUNCTION__, i, data, DATA_ALIGNMENT,
416 get_camera_metadata_tag_name(entry.tag) ?: "unknown",
417 data_size);
418 return ERROR;
419 }
420
421 size_t data_entry_end = entry.data.offset + data_size;
422 if (data_entry_end < entry.data.offset || // overflow check
423 data_entry_end > metadata->data_capacity) {
424
425 ALOGE("%s: Entry index %u data ends (%u) beyond the capacity "
426 "%u", __FUNCTION__, i, data_entry_end,
427 metadata->data_capacity);
428 return ERROR;
429 }
430
431 } else if (entry.count == 0) {
432 if (entry.data.offset != 0) {
433 ALOGE("%s: Entry index %u had 0 items, but offset was non-0 "
434 "(%u), tag name: %s", __FUNCTION__, i, entry.data.offset,
435 get_camera_metadata_tag_name(entry.tag) ?: "unknown");
436 return ERROR;
437 }
438 } // else data stored inline, so we look at value which can be anything.
439 }
440
441 return OK;
442 }
443
append_camera_metadata(camera_metadata_t * dst,const camera_metadata_t * src)444 int append_camera_metadata(camera_metadata_t *dst,
445 const camera_metadata_t *src) {
446 if (dst == NULL || src == NULL ) return ERROR;
447
448 if (dst->entry_capacity < src->entry_count + dst->entry_count) return ERROR;
449 if (dst->data_capacity < src->data_count + dst->data_count) return ERROR;
450
451 memcpy(get_entries(dst) + dst->entry_count, get_entries(src),
452 sizeof(camera_metadata_buffer_entry_t[src->entry_count]));
453 memcpy(get_data(dst) + dst->data_count, get_data(src),
454 sizeof(uint8_t[src->data_count]));
455 if (dst->data_count != 0) {
456 camera_metadata_buffer_entry_t *entry = get_entries(dst) + dst->entry_count;
457 for (size_t i = 0; i < src->entry_count; i++, entry++) {
458 if ( calculate_camera_metadata_entry_data_size(entry->type,
459 entry->count) > 0 ) {
460 entry->data.offset += dst->data_count;
461 }
462 }
463 }
464 if (dst->entry_count == 0) {
465 // Appending onto empty buffer, keep sorted state
466 dst->flags |= src->flags & FLAG_SORTED;
467 } else if (src->entry_count != 0) {
468 // Both src, dst are nonempty, cannot assume sort remains
469 dst->flags &= ~FLAG_SORTED;
470 } else {
471 // Src is empty, keep dst sorted state
472 }
473 dst->entry_count += src->entry_count;
474 dst->data_count += src->data_count;
475
476 return OK;
477 }
478
clone_camera_metadata(const camera_metadata_t * src)479 camera_metadata_t *clone_camera_metadata(const camera_metadata_t *src) {
480 int res;
481 if (src == NULL) return NULL;
482 camera_metadata_t *clone = allocate_camera_metadata(
483 get_camera_metadata_entry_count(src),
484 get_camera_metadata_data_count(src));
485 if (clone != NULL) {
486 res = append_camera_metadata(clone, src);
487 if (res != OK) {
488 free_camera_metadata(clone);
489 clone = NULL;
490 }
491 }
492 return clone;
493 }
494
calculate_camera_metadata_entry_data_size(uint8_t type,size_t data_count)495 size_t calculate_camera_metadata_entry_data_size(uint8_t type,
496 size_t data_count) {
497 if (type >= NUM_TYPES) return 0;
498 size_t data_bytes = data_count *
499 camera_metadata_type_size[type];
500 return data_bytes <= 4 ? 0 : ALIGN_TO(data_bytes, DATA_ALIGNMENT);
501 }
502
add_camera_metadata_entry_raw(camera_metadata_t * dst,uint32_t tag,uint8_t type,const void * data,size_t data_count)503 static int add_camera_metadata_entry_raw(camera_metadata_t *dst,
504 uint32_t tag,
505 uint8_t type,
506 const void *data,
507 size_t data_count) {
508
509 if (dst == NULL) return ERROR;
510 if (dst->entry_count == dst->entry_capacity) return ERROR;
511 if (data == NULL) return ERROR;
512
513 size_t data_bytes =
514 calculate_camera_metadata_entry_data_size(type, data_count);
515 if (data_bytes + dst->data_count > dst->data_capacity) return ERROR;
516
517 size_t data_payload_bytes =
518 data_count * camera_metadata_type_size[type];
519 camera_metadata_buffer_entry_t *entry = get_entries(dst) + dst->entry_count;
520 memset(entry, 0, sizeof(camera_metadata_buffer_entry_t));
521 entry->tag = tag;
522 entry->type = type;
523 entry->count = data_count;
524
525 if (data_bytes == 0) {
526 memcpy(entry->data.value, data,
527 data_payload_bytes);
528 } else {
529 entry->data.offset = dst->data_count;
530 memcpy(get_data(dst) + entry->data.offset, data,
531 data_payload_bytes);
532 dst->data_count += data_bytes;
533 }
534 dst->entry_count++;
535 dst->flags &= ~FLAG_SORTED;
536 return OK;
537 }
538
add_camera_metadata_entry(camera_metadata_t * dst,uint32_t tag,const void * data,size_t data_count)539 int add_camera_metadata_entry(camera_metadata_t *dst,
540 uint32_t tag,
541 const void *data,
542 size_t data_count) {
543
544 int type = get_camera_metadata_tag_type(tag);
545 if (type == -1) {
546 ALOGE("%s: Unknown tag %04x.", __FUNCTION__, tag);
547 return ERROR;
548 }
549
550 return add_camera_metadata_entry_raw(dst,
551 tag,
552 type,
553 data,
554 data_count);
555 }
556
compare_entry_tags(const void * p1,const void * p2)557 static int compare_entry_tags(const void *p1, const void *p2) {
558 uint32_t tag1 = ((camera_metadata_buffer_entry_t*)p1)->tag;
559 uint32_t tag2 = ((camera_metadata_buffer_entry_t*)p2)->tag;
560 return tag1 < tag2 ? -1 :
561 tag1 == tag2 ? 0 :
562 1;
563 }
564
sort_camera_metadata(camera_metadata_t * dst)565 int sort_camera_metadata(camera_metadata_t *dst) {
566 if (dst == NULL) return ERROR;
567 if (dst->flags & FLAG_SORTED) return OK;
568
569 qsort(get_entries(dst), dst->entry_count,
570 sizeof(camera_metadata_buffer_entry_t),
571 compare_entry_tags);
572 dst->flags |= FLAG_SORTED;
573
574 return OK;
575 }
576
get_camera_metadata_entry(camera_metadata_t * src,size_t index,camera_metadata_entry_t * entry)577 int get_camera_metadata_entry(camera_metadata_t *src,
578 size_t index,
579 camera_metadata_entry_t *entry) {
580 if (src == NULL || entry == NULL) return ERROR;
581 if (index >= src->entry_count) return ERROR;
582
583 camera_metadata_buffer_entry_t *buffer_entry = get_entries(src) + index;
584
585 entry->index = index;
586 entry->tag = buffer_entry->tag;
587 entry->type = buffer_entry->type;
588 entry->count = buffer_entry->count;
589 if (buffer_entry->count *
590 camera_metadata_type_size[buffer_entry->type] > 4) {
591 entry->data.u8 = get_data(src) + buffer_entry->data.offset;
592 } else {
593 entry->data.u8 = buffer_entry->data.value;
594 }
595 return OK;
596 }
597
find_camera_metadata_entry(camera_metadata_t * src,uint32_t tag,camera_metadata_entry_t * entry)598 int find_camera_metadata_entry(camera_metadata_t *src,
599 uint32_t tag,
600 camera_metadata_entry_t *entry) {
601 if (src == NULL) return ERROR;
602
603 uint32_t index;
604 if (src->flags & FLAG_SORTED) {
605 // Sorted entries, do a binary search
606 camera_metadata_buffer_entry_t *search_entry = NULL;
607 camera_metadata_buffer_entry_t key;
608 key.tag = tag;
609 search_entry = bsearch(&key,
610 get_entries(src),
611 src->entry_count,
612 sizeof(camera_metadata_buffer_entry_t),
613 compare_entry_tags);
614 if (search_entry == NULL) return NOT_FOUND;
615 index = search_entry - get_entries(src);
616 } else {
617 // Not sorted, linear search
618 camera_metadata_buffer_entry_t *search_entry = get_entries(src);
619 for (index = 0; index < src->entry_count; index++, search_entry++) {
620 if (search_entry->tag == tag) {
621 break;
622 }
623 }
624 if (index == src->entry_count) return NOT_FOUND;
625 }
626
627 return get_camera_metadata_entry(src, index,
628 entry);
629 }
630
find_camera_metadata_ro_entry(const camera_metadata_t * src,uint32_t tag,camera_metadata_ro_entry_t * entry)631 int find_camera_metadata_ro_entry(const camera_metadata_t *src,
632 uint32_t tag,
633 camera_metadata_ro_entry_t *entry) {
634 return find_camera_metadata_entry((camera_metadata_t*)src, tag,
635 (camera_metadata_entry_t*)entry);
636 }
637
638
delete_camera_metadata_entry(camera_metadata_t * dst,size_t index)639 int delete_camera_metadata_entry(camera_metadata_t *dst,
640 size_t index) {
641 if (dst == NULL) return ERROR;
642 if (index >= dst->entry_count) return ERROR;
643
644 camera_metadata_buffer_entry_t *entry = get_entries(dst) + index;
645 size_t data_bytes = calculate_camera_metadata_entry_data_size(entry->type,
646 entry->count);
647
648 if (data_bytes > 0) {
649 // Shift data buffer to overwrite deleted data
650 uint8_t *start = get_data(dst) + entry->data.offset;
651 uint8_t *end = start + data_bytes;
652 size_t length = dst->data_count - entry->data.offset - data_bytes;
653 memmove(start, end, length);
654
655 // Update all entry indices to account for shift
656 camera_metadata_buffer_entry_t *e = get_entries(dst);
657 size_t i;
658 for (i = 0; i < dst->entry_count; i++) {
659 if (calculate_camera_metadata_entry_data_size(
660 e->type, e->count) > 0 &&
661 e->data.offset > entry->data.offset) {
662 e->data.offset -= data_bytes;
663 }
664 ++e;
665 }
666 dst->data_count -= data_bytes;
667 }
668 // Shift entry array
669 memmove(entry, entry + 1,
670 sizeof(camera_metadata_buffer_entry_t) *
671 (dst->entry_count - index - 1) );
672 dst->entry_count -= 1;
673
674 return OK;
675 }
676
update_camera_metadata_entry(camera_metadata_t * dst,size_t index,const void * data,size_t data_count,camera_metadata_entry_t * updated_entry)677 int update_camera_metadata_entry(camera_metadata_t *dst,
678 size_t index,
679 const void *data,
680 size_t data_count,
681 camera_metadata_entry_t *updated_entry) {
682 if (dst == NULL) return ERROR;
683 if (index >= dst->entry_count) return ERROR;
684
685 camera_metadata_buffer_entry_t *entry = get_entries(dst) + index;
686
687 size_t data_bytes =
688 calculate_camera_metadata_entry_data_size(entry->type,
689 data_count);
690 size_t data_payload_bytes =
691 data_count * camera_metadata_type_size[entry->type];
692
693 size_t entry_bytes =
694 calculate_camera_metadata_entry_data_size(entry->type,
695 entry->count);
696 if (data_bytes != entry_bytes) {
697 // May need to shift/add to data array
698 if (dst->data_capacity < dst->data_count + data_bytes - entry_bytes) {
699 // No room
700 return ERROR;
701 }
702 if (entry_bytes != 0) {
703 // Remove old data
704 uint8_t *start = get_data(dst) + entry->data.offset;
705 uint8_t *end = start + entry_bytes;
706 size_t length = dst->data_count - entry->data.offset - entry_bytes;
707 memmove(start, end, length);
708 dst->data_count -= entry_bytes;
709
710 // Update all entry indices to account for shift
711 camera_metadata_buffer_entry_t *e = get_entries(dst);
712 size_t i;
713 for (i = 0; i < dst->entry_count; i++) {
714 if (calculate_camera_metadata_entry_data_size(
715 e->type, e->count) > 0 &&
716 e->data.offset > entry->data.offset) {
717 e->data.offset -= entry_bytes;
718 }
719 ++e;
720 }
721 }
722
723 if (data_bytes != 0) {
724 // Append new data
725 entry->data.offset = dst->data_count;
726
727 memcpy(get_data(dst) + entry->data.offset, data, data_payload_bytes);
728 dst->data_count += data_bytes;
729 }
730 } else if (data_bytes != 0) {
731 // data size unchanged, reuse same data location
732 memcpy(get_data(dst) + entry->data.offset, data, data_payload_bytes);
733 }
734
735 if (data_bytes == 0) {
736 // Data fits into entry
737 memcpy(entry->data.value, data,
738 data_payload_bytes);
739 }
740
741 entry->count = data_count;
742
743 if (updated_entry != NULL) {
744 get_camera_metadata_entry(dst,
745 index,
746 updated_entry);
747 }
748
749 return OK;
750 }
751
set_camera_metadata_user_pointer(camera_metadata_t * dst,void * user)752 int set_camera_metadata_user_pointer(camera_metadata_t *dst, void* user) {
753 if (dst == NULL) return ERROR;
754 dst->user = user;
755 return OK;
756 }
757
get_camera_metadata_user_pointer(camera_metadata_t * dst,void ** user)758 int get_camera_metadata_user_pointer(camera_metadata_t *dst, void** user) {
759 if (dst == NULL) return ERROR;
760 *user = dst->user;
761 return OK;
762 }
763
764 static const vendor_tag_query_ops_t *vendor_tag_ops = NULL;
765
get_camera_metadata_section_name(uint32_t tag)766 const char *get_camera_metadata_section_name(uint32_t tag) {
767 uint32_t tag_section = tag >> 16;
768 if (tag_section >= VENDOR_SECTION && vendor_tag_ops != NULL) {
769 return vendor_tag_ops->get_camera_vendor_section_name(
770 vendor_tag_ops,
771 tag);
772 }
773 if (tag_section >= ANDROID_SECTION_COUNT) {
774 return NULL;
775 }
776 return camera_metadata_section_names[tag_section];
777 }
778
get_camera_metadata_tag_name(uint32_t tag)779 const char *get_camera_metadata_tag_name(uint32_t tag) {
780 uint32_t tag_section = tag >> 16;
781 if (tag_section >= VENDOR_SECTION && vendor_tag_ops != NULL) {
782 return vendor_tag_ops->get_camera_vendor_tag_name(
783 vendor_tag_ops,
784 tag);
785 }
786 if (tag_section >= ANDROID_SECTION_COUNT ||
787 tag >= camera_metadata_section_bounds[tag_section][1] ) {
788 return NULL;
789 }
790 uint32_t tag_index = tag & 0xFFFF;
791 return tag_info[tag_section][tag_index].tag_name;
792 }
793
get_camera_metadata_tag_type(uint32_t tag)794 int get_camera_metadata_tag_type(uint32_t tag) {
795 uint32_t tag_section = tag >> 16;
796 if (tag_section >= VENDOR_SECTION && vendor_tag_ops != NULL) {
797 return vendor_tag_ops->get_camera_vendor_tag_type(
798 vendor_tag_ops,
799 tag);
800 }
801 if (tag_section >= ANDROID_SECTION_COUNT ||
802 tag >= camera_metadata_section_bounds[tag_section][1] ) {
803 return -1;
804 }
805 uint32_t tag_index = tag & 0xFFFF;
806 return tag_info[tag_section][tag_index].tag_type;
807 }
808
set_camera_metadata_vendor_tag_ops(const vendor_tag_query_ops_t * query_ops)809 int set_camera_metadata_vendor_tag_ops(const vendor_tag_query_ops_t *query_ops) {
810 vendor_tag_ops = query_ops;
811 return OK;
812 }
813
814 static void print_data(int fd, const uint8_t *data_ptr, uint32_t tag, int type,
815 int count,
816 int indentation);
817
dump_camera_metadata(const camera_metadata_t * metadata,int fd,int verbosity)818 void dump_camera_metadata(const camera_metadata_t *metadata,
819 int fd,
820 int verbosity) {
821 dump_indented_camera_metadata(metadata, fd, verbosity, 0);
822 }
823
dump_indented_camera_metadata(const camera_metadata_t * metadata,int fd,int verbosity,int indentation)824 void dump_indented_camera_metadata(const camera_metadata_t *metadata,
825 int fd,
826 int verbosity,
827 int indentation) {
828 if (metadata == NULL) {
829 fdprintf(fd, "%*sDumping camera metadata array: Not allocated\n",
830 indentation, "");
831 return;
832 }
833 unsigned int i;
834 fdprintf(fd,
835 "%*sDumping camera metadata array: %d / %d entries, "
836 "%d / %d bytes of extra data.\n", indentation, "",
837 metadata->entry_count, metadata->entry_capacity,
838 metadata->data_count, metadata->data_capacity);
839 fdprintf(fd, "%*sVersion: %d, Flags: %08x\n",
840 indentation + 2, "",
841 metadata->version, metadata->flags);
842 camera_metadata_buffer_entry_t *entry = get_entries(metadata);
843 for (i=0; i < metadata->entry_count; i++, entry++) {
844
845 const char *tag_name, *tag_section;
846 tag_section = get_camera_metadata_section_name(entry->tag);
847 if (tag_section == NULL) {
848 tag_section = "unknownSection";
849 }
850 tag_name = get_camera_metadata_tag_name(entry->tag);
851 if (tag_name == NULL) {
852 tag_name = "unknownTag";
853 }
854 const char *type_name;
855 if (entry->type >= NUM_TYPES) {
856 type_name = "unknown";
857 } else {
858 type_name = camera_metadata_type_names[entry->type];
859 }
860 fdprintf(fd, "%*s%s.%s (%05x): %s[%d]\n",
861 indentation + 2, "",
862 tag_section,
863 tag_name,
864 entry->tag,
865 type_name,
866 entry->count);
867
868 if (verbosity < 1) continue;
869
870 if (entry->type >= NUM_TYPES) continue;
871
872 size_t type_size = camera_metadata_type_size[entry->type];
873 uint8_t *data_ptr;
874 if ( type_size * entry->count > 4 ) {
875 if (entry->data.offset >= metadata->data_count) {
876 ALOGE("%s: Malformed entry data offset: %d (max %d)",
877 __FUNCTION__,
878 entry->data.offset,
879 metadata->data_count);
880 continue;
881 }
882 data_ptr = get_data(metadata) + entry->data.offset;
883 } else {
884 data_ptr = entry->data.value;
885 }
886 int count = entry->count;
887 if (verbosity < 2 && count > 16) count = 16;
888
889 print_data(fd, data_ptr, entry->tag, entry->type, count, indentation);
890 }
891 }
892
print_data(int fd,const uint8_t * data_ptr,uint32_t tag,int type,int count,int indentation)893 static void print_data(int fd, const uint8_t *data_ptr, uint32_t tag,
894 int type, int count, int indentation) {
895 static int values_per_line[NUM_TYPES] = {
896 [TYPE_BYTE] = 16,
897 [TYPE_INT32] = 4,
898 [TYPE_FLOAT] = 8,
899 [TYPE_INT64] = 2,
900 [TYPE_DOUBLE] = 4,
901 [TYPE_RATIONAL] = 2,
902 };
903 size_t type_size = camera_metadata_type_size[type];
904 char value_string_tmp[CAMERA_METADATA_ENUM_STRING_MAX_SIZE];
905 uint32_t value;
906
907 int lines = count / values_per_line[type];
908 if (count % values_per_line[type] != 0) lines++;
909
910 int index = 0;
911 int j, k;
912 for (j = 0; j < lines; j++) {
913 fdprintf(fd, "%*s[", indentation + 4, "");
914 for (k = 0;
915 k < values_per_line[type] && count > 0;
916 k++, count--, index += type_size) {
917
918 switch (type) {
919 case TYPE_BYTE:
920 value = *(data_ptr + index);
921 if (camera_metadata_enum_snprint(tag,
922 value,
923 value_string_tmp,
924 sizeof(value_string_tmp))
925 == OK) {
926 fdprintf(fd, "%s ", value_string_tmp);
927 } else {
928 fdprintf(fd, "%hhu ",
929 *(data_ptr + index));
930 }
931 break;
932 case TYPE_INT32:
933 value =
934 *(int32_t*)(data_ptr + index);
935 if (camera_metadata_enum_snprint(tag,
936 value,
937 value_string_tmp,
938 sizeof(value_string_tmp))
939 == OK) {
940 fdprintf(fd, "%s ", value_string_tmp);
941 } else {
942 fdprintf(fd, "%d ",
943 *(int32_t*)(data_ptr + index));
944 }
945 break;
946 case TYPE_FLOAT:
947 fdprintf(fd, "%0.2f ",
948 *(float*)(data_ptr + index));
949 break;
950 case TYPE_INT64:
951 fdprintf(fd, "%lld ",
952 *(int64_t*)(data_ptr + index));
953 break;
954 case TYPE_DOUBLE:
955 fdprintf(fd, "%0.2f ",
956 *(double*)(data_ptr + index));
957 break;
958 case TYPE_RATIONAL: {
959 int32_t numerator = *(int32_t*)(data_ptr + index);
960 int32_t denominator = *(int32_t*)(data_ptr + index + 4);
961 fdprintf(fd, "(%d / %d) ",
962 numerator, denominator);
963 break;
964 }
965 default:
966 fdprintf(fd, "??? ");
967 }
968 }
969 fdprintf(fd, "]\n");
970 }
971 }
972