• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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