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