1*b9df5ad1SAndroid Build Coastguard Worker /*
2*b9df5ad1SAndroid Build Coastguard Worker * Copyright (C) 2012 The Android Open Source Project
3*b9df5ad1SAndroid Build Coastguard Worker *
4*b9df5ad1SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*b9df5ad1SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*b9df5ad1SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*b9df5ad1SAndroid Build Coastguard Worker *
8*b9df5ad1SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*b9df5ad1SAndroid Build Coastguard Worker *
10*b9df5ad1SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*b9df5ad1SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*b9df5ad1SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*b9df5ad1SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*b9df5ad1SAndroid Build Coastguard Worker * limitations under the License.
15*b9df5ad1SAndroid Build Coastguard Worker */
16*b9df5ad1SAndroid Build Coastguard Worker
17*b9df5ad1SAndroid Build Coastguard Worker #define LOG_TAG "camera_metadata"
18*b9df5ad1SAndroid Build Coastguard Worker
19*b9df5ad1SAndroid Build Coastguard Worker #include <system/camera_metadata.h>
20*b9df5ad1SAndroid Build Coastguard Worker #include <camera_metadata_hidden.h>
21*b9df5ad1SAndroid Build Coastguard Worker
22*b9df5ad1SAndroid Build Coastguard Worker #include <assert.h>
23*b9df5ad1SAndroid Build Coastguard Worker #include <errno.h>
24*b9df5ad1SAndroid Build Coastguard Worker #include <inttypes.h>
25*b9df5ad1SAndroid Build Coastguard Worker #include <stdio.h>
26*b9df5ad1SAndroid Build Coastguard Worker #include <stdlib.h>
27*b9df5ad1SAndroid Build Coastguard Worker
28*b9df5ad1SAndroid Build Coastguard Worker #include <log/log.h>
29*b9df5ad1SAndroid Build Coastguard Worker
30*b9df5ad1SAndroid Build Coastguard Worker #define OK 0
31*b9df5ad1SAndroid Build Coastguard Worker #define ERROR 1
32*b9df5ad1SAndroid Build Coastguard Worker #define NOT_FOUND (-ENOENT)
33*b9df5ad1SAndroid Build Coastguard Worker #define SN_EVENT_LOG_ID 0x534e4554
34*b9df5ad1SAndroid Build Coastguard Worker
35*b9df5ad1SAndroid Build Coastguard Worker #define ALIGN_TO(val, alignment) \
36*b9df5ad1SAndroid Build Coastguard Worker (((uintptr_t)(val) + ((alignment) - 1)) & ~((alignment) - 1))
37*b9df5ad1SAndroid Build Coastguard Worker
38*b9df5ad1SAndroid Build Coastguard Worker /**
39*b9df5ad1SAndroid Build Coastguard Worker * A single metadata entry, storing an array of values of a given type. If the
40*b9df5ad1SAndroid Build Coastguard Worker * array is no larger than 4 bytes in size, it is stored in the data.value[]
41*b9df5ad1SAndroid Build Coastguard Worker * array; otherwise, it can found in the parent's data array at index
42*b9df5ad1SAndroid Build Coastguard Worker * data.offset.
43*b9df5ad1SAndroid Build Coastguard Worker */
44*b9df5ad1SAndroid Build Coastguard Worker #define ENTRY_ALIGNMENT ((size_t) 4)
45*b9df5ad1SAndroid Build Coastguard Worker typedef struct camera_metadata_buffer_entry {
46*b9df5ad1SAndroid Build Coastguard Worker uint32_t tag;
47*b9df5ad1SAndroid Build Coastguard Worker uint32_t count;
48*b9df5ad1SAndroid Build Coastguard Worker union {
49*b9df5ad1SAndroid Build Coastguard Worker uint32_t offset;
50*b9df5ad1SAndroid Build Coastguard Worker uint8_t value[4];
51*b9df5ad1SAndroid Build Coastguard Worker } data;
52*b9df5ad1SAndroid Build Coastguard Worker uint8_t type;
53*b9df5ad1SAndroid Build Coastguard Worker uint8_t reserved[3];
54*b9df5ad1SAndroid Build Coastguard Worker } camera_metadata_buffer_entry_t;
55*b9df5ad1SAndroid Build Coastguard Worker
56*b9df5ad1SAndroid Build Coastguard Worker typedef uint32_t metadata_uptrdiff_t;
57*b9df5ad1SAndroid Build Coastguard Worker typedef uint32_t metadata_size_t;
58*b9df5ad1SAndroid Build Coastguard Worker
59*b9df5ad1SAndroid Build Coastguard Worker /**
60*b9df5ad1SAndroid Build Coastguard Worker * A packet of metadata. This is a list of entries, each of which may point to
61*b9df5ad1SAndroid Build Coastguard Worker * its values stored at an offset in data.
62*b9df5ad1SAndroid Build Coastguard Worker *
63*b9df5ad1SAndroid Build Coastguard Worker * It is assumed by the utility functions that the memory layout of the packet
64*b9df5ad1SAndroid Build Coastguard Worker * is as follows:
65*b9df5ad1SAndroid Build Coastguard Worker *
66*b9df5ad1SAndroid Build Coastguard Worker * |-----------------------------------------------|
67*b9df5ad1SAndroid Build Coastguard Worker * | camera_metadata_t |
68*b9df5ad1SAndroid Build Coastguard Worker * | |
69*b9df5ad1SAndroid Build Coastguard Worker * |-----------------------------------------------|
70*b9df5ad1SAndroid Build Coastguard Worker * | reserved for future expansion |
71*b9df5ad1SAndroid Build Coastguard Worker * |-----------------------------------------------|
72*b9df5ad1SAndroid Build Coastguard Worker * | camera_metadata_buffer_entry_t #0 |
73*b9df5ad1SAndroid Build Coastguard Worker * |-----------------------------------------------|
74*b9df5ad1SAndroid Build Coastguard Worker * | .... |
75*b9df5ad1SAndroid Build Coastguard Worker * |-----------------------------------------------|
76*b9df5ad1SAndroid Build Coastguard Worker * | camera_metadata_buffer_entry_t #entry_count-1 |
77*b9df5ad1SAndroid Build Coastguard Worker * |-----------------------------------------------|
78*b9df5ad1SAndroid Build Coastguard Worker * | free space for |
79*b9df5ad1SAndroid Build Coastguard Worker * | (entry_capacity-entry_count) entries |
80*b9df5ad1SAndroid Build Coastguard Worker * |-----------------------------------------------|
81*b9df5ad1SAndroid Build Coastguard Worker * | start of camera_metadata.data |
82*b9df5ad1SAndroid Build Coastguard Worker * | |
83*b9df5ad1SAndroid Build Coastguard Worker * |-----------------------------------------------|
84*b9df5ad1SAndroid Build Coastguard Worker * | free space for |
85*b9df5ad1SAndroid Build Coastguard Worker * | (data_capacity-data_count) bytes |
86*b9df5ad1SAndroid Build Coastguard Worker * |-----------------------------------------------|
87*b9df5ad1SAndroid Build Coastguard Worker *
88*b9df5ad1SAndroid Build Coastguard Worker * With the total length of the whole packet being camera_metadata.size bytes.
89*b9df5ad1SAndroid Build Coastguard Worker *
90*b9df5ad1SAndroid Build Coastguard Worker * In short, the entries and data are contiguous in memory after the metadata
91*b9df5ad1SAndroid Build Coastguard Worker * header.
92*b9df5ad1SAndroid Build Coastguard Worker */
93*b9df5ad1SAndroid Build Coastguard Worker #define METADATA_ALIGNMENT ((size_t) 4)
94*b9df5ad1SAndroid Build Coastguard Worker struct camera_metadata {
95*b9df5ad1SAndroid Build Coastguard Worker metadata_size_t size;
96*b9df5ad1SAndroid Build Coastguard Worker uint32_t version;
97*b9df5ad1SAndroid Build Coastguard Worker uint32_t flags;
98*b9df5ad1SAndroid Build Coastguard Worker metadata_size_t entry_count;
99*b9df5ad1SAndroid Build Coastguard Worker metadata_size_t entry_capacity;
100*b9df5ad1SAndroid Build Coastguard Worker metadata_uptrdiff_t entries_start; // Offset from camera_metadata
101*b9df5ad1SAndroid Build Coastguard Worker metadata_size_t data_count;
102*b9df5ad1SAndroid Build Coastguard Worker metadata_size_t data_capacity;
103*b9df5ad1SAndroid Build Coastguard Worker metadata_uptrdiff_t data_start; // Offset from camera_metadata
104*b9df5ad1SAndroid Build Coastguard Worker uint32_t padding; // padding to 8 bytes boundary
105*b9df5ad1SAndroid Build Coastguard Worker metadata_vendor_id_t vendor_id;
106*b9df5ad1SAndroid Build Coastguard Worker };
107*b9df5ad1SAndroid Build Coastguard Worker
108*b9df5ad1SAndroid Build Coastguard Worker /**
109*b9df5ad1SAndroid Build Coastguard Worker * A datum of metadata. This corresponds to camera_metadata_entry_t::data
110*b9df5ad1SAndroid Build Coastguard Worker * with the difference that each element is not a pointer. We need to have a
111*b9df5ad1SAndroid Build Coastguard Worker * non-pointer type description in order to figure out the largest alignment
112*b9df5ad1SAndroid Build Coastguard Worker * requirement for data (DATA_ALIGNMENT).
113*b9df5ad1SAndroid Build Coastguard Worker */
114*b9df5ad1SAndroid Build Coastguard Worker #define DATA_ALIGNMENT ((size_t) 8)
115*b9df5ad1SAndroid Build Coastguard Worker typedef union camera_metadata_data {
116*b9df5ad1SAndroid Build Coastguard Worker uint8_t u8;
117*b9df5ad1SAndroid Build Coastguard Worker int32_t i32;
118*b9df5ad1SAndroid Build Coastguard Worker float f;
119*b9df5ad1SAndroid Build Coastguard Worker int64_t i64;
120*b9df5ad1SAndroid Build Coastguard Worker double d;
121*b9df5ad1SAndroid Build Coastguard Worker camera_metadata_rational_t r;
122*b9df5ad1SAndroid Build Coastguard Worker } camera_metadata_data_t;
123*b9df5ad1SAndroid Build Coastguard Worker
124*b9df5ad1SAndroid Build Coastguard Worker _Static_assert(sizeof(metadata_size_t) == 4,
125*b9df5ad1SAndroid Build Coastguard Worker "Size of metadata_size_t must be 4");
126*b9df5ad1SAndroid Build Coastguard Worker _Static_assert(sizeof(metadata_uptrdiff_t) == 4,
127*b9df5ad1SAndroid Build Coastguard Worker "Size of metadata_uptrdiff_t must be 4");
128*b9df5ad1SAndroid Build Coastguard Worker _Static_assert(sizeof(metadata_vendor_id_t) == 8,
129*b9df5ad1SAndroid Build Coastguard Worker "Size of metadata_vendor_id_t must be 8");
130*b9df5ad1SAndroid Build Coastguard Worker _Static_assert(sizeof(camera_metadata_data_t) == 8,
131*b9df5ad1SAndroid Build Coastguard Worker "Size of camera_metadata_data_t must be 8");
132*b9df5ad1SAndroid Build Coastguard Worker
133*b9df5ad1SAndroid Build Coastguard Worker _Static_assert(offsetof(camera_metadata_buffer_entry_t, tag) == 0,
134*b9df5ad1SAndroid Build Coastguard Worker "Offset of tag must be 0");
135*b9df5ad1SAndroid Build Coastguard Worker _Static_assert(offsetof(camera_metadata_buffer_entry_t, count) == 4,
136*b9df5ad1SAndroid Build Coastguard Worker "Offset of count must be 4");
137*b9df5ad1SAndroid Build Coastguard Worker _Static_assert(offsetof(camera_metadata_buffer_entry_t, data) == 8,
138*b9df5ad1SAndroid Build Coastguard Worker "Offset of data must be 8");
139*b9df5ad1SAndroid Build Coastguard Worker _Static_assert(offsetof(camera_metadata_buffer_entry_t, type) == 12,
140*b9df5ad1SAndroid Build Coastguard Worker "Offset of type must be 12");
141*b9df5ad1SAndroid Build Coastguard Worker _Static_assert(sizeof(camera_metadata_buffer_entry_t) == 16,
142*b9df5ad1SAndroid Build Coastguard Worker "Size of camera_metadata_buffer_entry_t must be 16");
143*b9df5ad1SAndroid Build Coastguard Worker
144*b9df5ad1SAndroid Build Coastguard Worker _Static_assert(offsetof(camera_metadata_t, size) == 0,
145*b9df5ad1SAndroid Build Coastguard Worker "Offset of size must be 0");
146*b9df5ad1SAndroid Build Coastguard Worker _Static_assert(offsetof(camera_metadata_t, version) == 4,
147*b9df5ad1SAndroid Build Coastguard Worker "Offset of version must be 4");
148*b9df5ad1SAndroid Build Coastguard Worker _Static_assert(offsetof(camera_metadata_t, flags) == 8,
149*b9df5ad1SAndroid Build Coastguard Worker "Offset of flags must be 8");
150*b9df5ad1SAndroid Build Coastguard Worker _Static_assert(offsetof(camera_metadata_t, entry_count) == 12,
151*b9df5ad1SAndroid Build Coastguard Worker "Offset of entry_count must be 12");
152*b9df5ad1SAndroid Build Coastguard Worker _Static_assert(offsetof(camera_metadata_t, entry_capacity) == 16,
153*b9df5ad1SAndroid Build Coastguard Worker "Offset of entry_capacity must be 16");
154*b9df5ad1SAndroid Build Coastguard Worker _Static_assert(offsetof(camera_metadata_t, entries_start) == 20,
155*b9df5ad1SAndroid Build Coastguard Worker "Offset of entries_start must be 20");
156*b9df5ad1SAndroid Build Coastguard Worker _Static_assert(offsetof(camera_metadata_t, data_count) == 24,
157*b9df5ad1SAndroid Build Coastguard Worker "Offset of data_count must be 24");
158*b9df5ad1SAndroid Build Coastguard Worker _Static_assert(offsetof(camera_metadata_t, data_capacity) == 28,
159*b9df5ad1SAndroid Build Coastguard Worker "Offset of data_capacity must be 28");
160*b9df5ad1SAndroid Build Coastguard Worker _Static_assert(offsetof(camera_metadata_t, data_start) == 32,
161*b9df5ad1SAndroid Build Coastguard Worker "Offset of data_start must be 32");
162*b9df5ad1SAndroid Build Coastguard Worker _Static_assert(offsetof(camera_metadata_t, vendor_id) == 40,
163*b9df5ad1SAndroid Build Coastguard Worker "Offset of vendor_id must be 40");
164*b9df5ad1SAndroid Build Coastguard Worker _Static_assert(sizeof(camera_metadata_t) == 48,
165*b9df5ad1SAndroid Build Coastguard Worker "Size of camera_metadata_t must be 48");
166*b9df5ad1SAndroid Build Coastguard Worker
167*b9df5ad1SAndroid Build Coastguard Worker /**
168*b9df5ad1SAndroid Build Coastguard Worker * The preferred alignment of a packet of camera metadata. In general,
169*b9df5ad1SAndroid Build Coastguard Worker * this is the lowest common multiple of the constituents of a metadata
170*b9df5ad1SAndroid Build Coastguard Worker * package, i.e, of DATA_ALIGNMENT and ENTRY_ALIGNMENT.
171*b9df5ad1SAndroid Build Coastguard Worker */
172*b9df5ad1SAndroid Build Coastguard Worker #define MAX_ALIGNMENT(A, B) (((A) > (B)) ? (A) : (B))
173*b9df5ad1SAndroid Build Coastguard Worker #define METADATA_PACKET_ALIGNMENT \
174*b9df5ad1SAndroid Build Coastguard Worker MAX_ALIGNMENT(MAX_ALIGNMENT(DATA_ALIGNMENT, METADATA_ALIGNMENT), ENTRY_ALIGNMENT)
175*b9df5ad1SAndroid Build Coastguard Worker
176*b9df5ad1SAndroid Build Coastguard Worker /** Versioning information */
177*b9df5ad1SAndroid Build Coastguard Worker #define CURRENT_METADATA_VERSION 1
178*b9df5ad1SAndroid Build Coastguard Worker
179*b9df5ad1SAndroid Build Coastguard Worker /** Flag definitions */
180*b9df5ad1SAndroid Build Coastguard Worker #define FLAG_SORTED 0x00000001
181*b9df5ad1SAndroid Build Coastguard Worker
182*b9df5ad1SAndroid Build Coastguard Worker /** Tag information */
183*b9df5ad1SAndroid Build Coastguard Worker
184*b9df5ad1SAndroid Build Coastguard Worker typedef struct tag_info {
185*b9df5ad1SAndroid Build Coastguard Worker const char *tag_name;
186*b9df5ad1SAndroid Build Coastguard Worker uint8_t tag_type;
187*b9df5ad1SAndroid Build Coastguard Worker } tag_info_t;
188*b9df5ad1SAndroid Build Coastguard Worker
189*b9df5ad1SAndroid Build Coastguard Worker #include "camera_metadata_tag_info.c"
190*b9df5ad1SAndroid Build Coastguard Worker
191*b9df5ad1SAndroid Build Coastguard Worker const size_t camera_metadata_type_size[NUM_TYPES] = {
192*b9df5ad1SAndroid Build Coastguard Worker [TYPE_BYTE] = sizeof(uint8_t),
193*b9df5ad1SAndroid Build Coastguard Worker [TYPE_INT32] = sizeof(int32_t),
194*b9df5ad1SAndroid Build Coastguard Worker [TYPE_FLOAT] = sizeof(float),
195*b9df5ad1SAndroid Build Coastguard Worker [TYPE_INT64] = sizeof(int64_t),
196*b9df5ad1SAndroid Build Coastguard Worker [TYPE_DOUBLE] = sizeof(double),
197*b9df5ad1SAndroid Build Coastguard Worker [TYPE_RATIONAL] = sizeof(camera_metadata_rational_t)
198*b9df5ad1SAndroid Build Coastguard Worker };
199*b9df5ad1SAndroid Build Coastguard Worker
200*b9df5ad1SAndroid Build Coastguard Worker const char *camera_metadata_type_names[NUM_TYPES] = {
201*b9df5ad1SAndroid Build Coastguard Worker [TYPE_BYTE] = "byte",
202*b9df5ad1SAndroid Build Coastguard Worker [TYPE_INT32] = "int32",
203*b9df5ad1SAndroid Build Coastguard Worker [TYPE_FLOAT] = "float",
204*b9df5ad1SAndroid Build Coastguard Worker [TYPE_INT64] = "int64",
205*b9df5ad1SAndroid Build Coastguard Worker [TYPE_DOUBLE] = "double",
206*b9df5ad1SAndroid Build Coastguard Worker [TYPE_RATIONAL] = "rational"
207*b9df5ad1SAndroid Build Coastguard Worker };
208*b9df5ad1SAndroid Build Coastguard Worker
get_entries(const camera_metadata_t * metadata)209*b9df5ad1SAndroid Build Coastguard Worker static camera_metadata_buffer_entry_t *get_entries(
210*b9df5ad1SAndroid Build Coastguard Worker const camera_metadata_t *metadata) {
211*b9df5ad1SAndroid Build Coastguard Worker return (camera_metadata_buffer_entry_t*)
212*b9df5ad1SAndroid Build Coastguard Worker ((uint8_t*)metadata + metadata->entries_start);
213*b9df5ad1SAndroid Build Coastguard Worker }
214*b9df5ad1SAndroid Build Coastguard Worker
get_data(const camera_metadata_t * metadata)215*b9df5ad1SAndroid Build Coastguard Worker static uint8_t *get_data(const camera_metadata_t *metadata) {
216*b9df5ad1SAndroid Build Coastguard Worker return (uint8_t*)metadata + metadata->data_start;
217*b9df5ad1SAndroid Build Coastguard Worker }
218*b9df5ad1SAndroid Build Coastguard Worker
get_camera_metadata_alignment()219*b9df5ad1SAndroid Build Coastguard Worker size_t get_camera_metadata_alignment() {
220*b9df5ad1SAndroid Build Coastguard Worker return METADATA_PACKET_ALIGNMENT;
221*b9df5ad1SAndroid Build Coastguard Worker }
222*b9df5ad1SAndroid Build Coastguard Worker
allocate_copy_camera_metadata_checked(const camera_metadata_t * src,size_t src_size)223*b9df5ad1SAndroid Build Coastguard Worker camera_metadata_t *allocate_copy_camera_metadata_checked(
224*b9df5ad1SAndroid Build Coastguard Worker const camera_metadata_t *src,
225*b9df5ad1SAndroid Build Coastguard Worker size_t src_size) {
226*b9df5ad1SAndroid Build Coastguard Worker
227*b9df5ad1SAndroid Build Coastguard Worker if (src == NULL) {
228*b9df5ad1SAndroid Build Coastguard Worker return NULL;
229*b9df5ad1SAndroid Build Coastguard Worker }
230*b9df5ad1SAndroid Build Coastguard Worker
231*b9df5ad1SAndroid Build Coastguard Worker if (src_size < sizeof(camera_metadata_t)) {
232*b9df5ad1SAndroid Build Coastguard Worker ALOGE("%s: Source size too small!", __FUNCTION__);
233*b9df5ad1SAndroid Build Coastguard Worker android_errorWriteLog(0x534e4554, "67782345");
234*b9df5ad1SAndroid Build Coastguard Worker return NULL;
235*b9df5ad1SAndroid Build Coastguard Worker }
236*b9df5ad1SAndroid Build Coastguard Worker
237*b9df5ad1SAndroid Build Coastguard Worker void *buffer = calloc(1, src_size);
238*b9df5ad1SAndroid Build Coastguard Worker memcpy(buffer, src, src_size);
239*b9df5ad1SAndroid Build Coastguard Worker
240*b9df5ad1SAndroid Build Coastguard Worker camera_metadata_t *metadata = (camera_metadata_t*) buffer;
241*b9df5ad1SAndroid Build Coastguard Worker if (validate_camera_metadata_structure(metadata, &src_size) != OK) {
242*b9df5ad1SAndroid Build Coastguard Worker free(buffer);
243*b9df5ad1SAndroid Build Coastguard Worker return NULL;
244*b9df5ad1SAndroid Build Coastguard Worker }
245*b9df5ad1SAndroid Build Coastguard Worker
246*b9df5ad1SAndroid Build Coastguard Worker return metadata;
247*b9df5ad1SAndroid Build Coastguard Worker }
248*b9df5ad1SAndroid Build Coastguard Worker
allocate_camera_metadata(size_t entry_capacity,size_t data_capacity)249*b9df5ad1SAndroid Build Coastguard Worker camera_metadata_t *allocate_camera_metadata(size_t entry_capacity,
250*b9df5ad1SAndroid Build Coastguard Worker size_t data_capacity) {
251*b9df5ad1SAndroid Build Coastguard Worker
252*b9df5ad1SAndroid Build Coastguard Worker size_t memory_needed = calculate_camera_metadata_size(entry_capacity,
253*b9df5ad1SAndroid Build Coastguard Worker data_capacity);
254*b9df5ad1SAndroid Build Coastguard Worker void *buffer = calloc(1, memory_needed);
255*b9df5ad1SAndroid Build Coastguard Worker camera_metadata_t *metadata = place_camera_metadata(
256*b9df5ad1SAndroid Build Coastguard Worker buffer, memory_needed, entry_capacity, data_capacity);
257*b9df5ad1SAndroid Build Coastguard Worker if (!metadata) {
258*b9df5ad1SAndroid Build Coastguard Worker /* This should not happen when memory_needed is the same
259*b9df5ad1SAndroid Build Coastguard Worker * calculated in this function and in place_camera_metadata.
260*b9df5ad1SAndroid Build Coastguard Worker */
261*b9df5ad1SAndroid Build Coastguard Worker free(buffer);
262*b9df5ad1SAndroid Build Coastguard Worker }
263*b9df5ad1SAndroid Build Coastguard Worker return metadata;
264*b9df5ad1SAndroid Build Coastguard Worker }
265*b9df5ad1SAndroid Build Coastguard Worker
place_camera_metadata(void * dst,size_t dst_size,size_t entry_capacity,size_t data_capacity)266*b9df5ad1SAndroid Build Coastguard Worker camera_metadata_t *place_camera_metadata(void *dst,
267*b9df5ad1SAndroid Build Coastguard Worker size_t dst_size,
268*b9df5ad1SAndroid Build Coastguard Worker size_t entry_capacity,
269*b9df5ad1SAndroid Build Coastguard Worker size_t data_capacity) {
270*b9df5ad1SAndroid Build Coastguard Worker if (dst == NULL) return NULL;
271*b9df5ad1SAndroid Build Coastguard Worker
272*b9df5ad1SAndroid Build Coastguard Worker size_t memory_needed = calculate_camera_metadata_size(entry_capacity,
273*b9df5ad1SAndroid Build Coastguard Worker data_capacity);
274*b9df5ad1SAndroid Build Coastguard Worker if (memory_needed > dst_size) {
275*b9df5ad1SAndroid Build Coastguard Worker ALOGE("%s: Memory needed to place camera metadata (%zu) > dst size (%zu)", __FUNCTION__,
276*b9df5ad1SAndroid Build Coastguard Worker memory_needed, dst_size);
277*b9df5ad1SAndroid Build Coastguard Worker return NULL;
278*b9df5ad1SAndroid Build Coastguard Worker }
279*b9df5ad1SAndroid Build Coastguard Worker
280*b9df5ad1SAndroid Build Coastguard Worker camera_metadata_t *metadata = (camera_metadata_t*)dst;
281*b9df5ad1SAndroid Build Coastguard Worker metadata->version = CURRENT_METADATA_VERSION;
282*b9df5ad1SAndroid Build Coastguard Worker metadata->flags = 0;
283*b9df5ad1SAndroid Build Coastguard Worker metadata->entry_count = 0;
284*b9df5ad1SAndroid Build Coastguard Worker metadata->entry_capacity = entry_capacity;
285*b9df5ad1SAndroid Build Coastguard Worker metadata->entries_start =
286*b9df5ad1SAndroid Build Coastguard Worker ALIGN_TO(sizeof(camera_metadata_t), ENTRY_ALIGNMENT);
287*b9df5ad1SAndroid Build Coastguard Worker metadata->data_count = 0;
288*b9df5ad1SAndroid Build Coastguard Worker metadata->data_capacity = data_capacity;
289*b9df5ad1SAndroid Build Coastguard Worker metadata->size = memory_needed;
290*b9df5ad1SAndroid Build Coastguard Worker size_t data_unaligned = (uint8_t*)(get_entries(metadata) +
291*b9df5ad1SAndroid Build Coastguard Worker metadata->entry_capacity) - (uint8_t*)metadata;
292*b9df5ad1SAndroid Build Coastguard Worker metadata->data_start = ALIGN_TO(data_unaligned, DATA_ALIGNMENT);
293*b9df5ad1SAndroid Build Coastguard Worker metadata->vendor_id = CAMERA_METADATA_INVALID_VENDOR_ID;
294*b9df5ad1SAndroid Build Coastguard Worker
295*b9df5ad1SAndroid Build Coastguard Worker assert(validate_camera_metadata_structure(metadata, NULL) == OK);
296*b9df5ad1SAndroid Build Coastguard Worker return metadata;
297*b9df5ad1SAndroid Build Coastguard Worker }
free_camera_metadata(camera_metadata_t * metadata)298*b9df5ad1SAndroid Build Coastguard Worker void free_camera_metadata(camera_metadata_t *metadata) {
299*b9df5ad1SAndroid Build Coastguard Worker free(metadata);
300*b9df5ad1SAndroid Build Coastguard Worker }
301*b9df5ad1SAndroid Build Coastguard Worker
calculate_camera_metadata_size(size_t entry_count,size_t data_count)302*b9df5ad1SAndroid Build Coastguard Worker size_t calculate_camera_metadata_size(size_t entry_count,
303*b9df5ad1SAndroid Build Coastguard Worker size_t data_count) {
304*b9df5ad1SAndroid Build Coastguard Worker size_t memory_needed = sizeof(camera_metadata_t);
305*b9df5ad1SAndroid Build Coastguard Worker // Start entry list at aligned boundary
306*b9df5ad1SAndroid Build Coastguard Worker memory_needed = ALIGN_TO(memory_needed, ENTRY_ALIGNMENT);
307*b9df5ad1SAndroid Build Coastguard Worker memory_needed += sizeof(camera_metadata_buffer_entry_t[entry_count]);
308*b9df5ad1SAndroid Build Coastguard Worker // Start buffer list at aligned boundary
309*b9df5ad1SAndroid Build Coastguard Worker memory_needed = ALIGN_TO(memory_needed, DATA_ALIGNMENT);
310*b9df5ad1SAndroid Build Coastguard Worker memory_needed += sizeof(uint8_t[data_count]);
311*b9df5ad1SAndroid Build Coastguard Worker // Make sure camera metadata can be stacked in continuous memory
312*b9df5ad1SAndroid Build Coastguard Worker memory_needed = ALIGN_TO(memory_needed, METADATA_PACKET_ALIGNMENT);
313*b9df5ad1SAndroid Build Coastguard Worker return memory_needed;
314*b9df5ad1SAndroid Build Coastguard Worker }
315*b9df5ad1SAndroid Build Coastguard Worker
get_camera_metadata_size(const camera_metadata_t * metadata)316*b9df5ad1SAndroid Build Coastguard Worker size_t get_camera_metadata_size(const camera_metadata_t *metadata) {
317*b9df5ad1SAndroid Build Coastguard Worker if (metadata == NULL) return ERROR;
318*b9df5ad1SAndroid Build Coastguard Worker
319*b9df5ad1SAndroid Build Coastguard Worker return metadata->size;
320*b9df5ad1SAndroid Build Coastguard Worker }
321*b9df5ad1SAndroid Build Coastguard Worker
get_camera_metadata_compact_size(const camera_metadata_t * metadata)322*b9df5ad1SAndroid Build Coastguard Worker size_t get_camera_metadata_compact_size(const camera_metadata_t *metadata) {
323*b9df5ad1SAndroid Build Coastguard Worker if (metadata == NULL) return ERROR;
324*b9df5ad1SAndroid Build Coastguard Worker
325*b9df5ad1SAndroid Build Coastguard Worker return calculate_camera_metadata_size(metadata->entry_count,
326*b9df5ad1SAndroid Build Coastguard Worker metadata->data_count);
327*b9df5ad1SAndroid Build Coastguard Worker }
328*b9df5ad1SAndroid Build Coastguard Worker
get_camera_metadata_entry_count(const camera_metadata_t * metadata)329*b9df5ad1SAndroid Build Coastguard Worker size_t get_camera_metadata_entry_count(const camera_metadata_t *metadata) {
330*b9df5ad1SAndroid Build Coastguard Worker return metadata->entry_count;
331*b9df5ad1SAndroid Build Coastguard Worker }
332*b9df5ad1SAndroid Build Coastguard Worker
get_camera_metadata_entry_capacity(const camera_metadata_t * metadata)333*b9df5ad1SAndroid Build Coastguard Worker size_t get_camera_metadata_entry_capacity(const camera_metadata_t *metadata) {
334*b9df5ad1SAndroid Build Coastguard Worker return metadata->entry_capacity;
335*b9df5ad1SAndroid Build Coastguard Worker }
336*b9df5ad1SAndroid Build Coastguard Worker
get_camera_metadata_data_count(const camera_metadata_t * metadata)337*b9df5ad1SAndroid Build Coastguard Worker size_t get_camera_metadata_data_count(const camera_metadata_t *metadata) {
338*b9df5ad1SAndroid Build Coastguard Worker return metadata->data_count;
339*b9df5ad1SAndroid Build Coastguard Worker }
340*b9df5ad1SAndroid Build Coastguard Worker
get_camera_metadata_data_capacity(const camera_metadata_t * metadata)341*b9df5ad1SAndroid Build Coastguard Worker size_t get_camera_metadata_data_capacity(const camera_metadata_t *metadata) {
342*b9df5ad1SAndroid Build Coastguard Worker return metadata->data_capacity;
343*b9df5ad1SAndroid Build Coastguard Worker }
344*b9df5ad1SAndroid Build Coastguard Worker
copy_camera_metadata(void * dst,size_t dst_size,const camera_metadata_t * src)345*b9df5ad1SAndroid Build Coastguard Worker camera_metadata_t* copy_camera_metadata(void *dst, size_t dst_size,
346*b9df5ad1SAndroid Build Coastguard Worker const camera_metadata_t *src) {
347*b9df5ad1SAndroid Build Coastguard Worker size_t memory_needed = get_camera_metadata_compact_size(src);
348*b9df5ad1SAndroid Build Coastguard Worker
349*b9df5ad1SAndroid Build Coastguard Worker if (dst == NULL) return NULL;
350*b9df5ad1SAndroid Build Coastguard Worker if (dst_size < memory_needed) {
351*b9df5ad1SAndroid Build Coastguard Worker ALOGE("%s: Memory needed to place camera metadata (%zu) > dst size (%zu)", __FUNCTION__,
352*b9df5ad1SAndroid Build Coastguard Worker memory_needed, dst_size);
353*b9df5ad1SAndroid Build Coastguard Worker return NULL;
354*b9df5ad1SAndroid Build Coastguard Worker }
355*b9df5ad1SAndroid Build Coastguard Worker
356*b9df5ad1SAndroid Build Coastguard Worker camera_metadata_t *metadata =
357*b9df5ad1SAndroid Build Coastguard Worker place_camera_metadata(dst, dst_size, src->entry_count, src->data_count);
358*b9df5ad1SAndroid Build Coastguard Worker
359*b9df5ad1SAndroid Build Coastguard Worker metadata->flags = src->flags;
360*b9df5ad1SAndroid Build Coastguard Worker metadata->entry_count = src->entry_count;
361*b9df5ad1SAndroid Build Coastguard Worker metadata->data_count = src->data_count;
362*b9df5ad1SAndroid Build Coastguard Worker metadata->vendor_id = src->vendor_id;
363*b9df5ad1SAndroid Build Coastguard Worker
364*b9df5ad1SAndroid Build Coastguard Worker memcpy(get_entries(metadata), get_entries(src),
365*b9df5ad1SAndroid Build Coastguard Worker sizeof(camera_metadata_buffer_entry_t[metadata->entry_count]));
366*b9df5ad1SAndroid Build Coastguard Worker memcpy(get_data(metadata), get_data(src),
367*b9df5ad1SAndroid Build Coastguard Worker sizeof(uint8_t[metadata->data_count]));
368*b9df5ad1SAndroid Build Coastguard Worker
369*b9df5ad1SAndroid Build Coastguard Worker assert(validate_camera_metadata_structure(metadata, NULL) == OK);
370*b9df5ad1SAndroid Build Coastguard Worker return metadata;
371*b9df5ad1SAndroid Build Coastguard Worker }
372*b9df5ad1SAndroid Build Coastguard Worker
373*b9df5ad1SAndroid Build Coastguard Worker // This method should be used when the camera metadata cannot be trusted. For example, when it's
374*b9df5ad1SAndroid Build Coastguard Worker // read from Parcel.
validate_and_calculate_camera_metadata_entry_data_size(size_t * data_size,uint8_t type,size_t data_count)375*b9df5ad1SAndroid Build Coastguard Worker static int validate_and_calculate_camera_metadata_entry_data_size(size_t *data_size, uint8_t type,
376*b9df5ad1SAndroid Build Coastguard Worker size_t data_count) {
377*b9df5ad1SAndroid Build Coastguard Worker if (type >= NUM_TYPES) return ERROR;
378*b9df5ad1SAndroid Build Coastguard Worker
379*b9df5ad1SAndroid Build Coastguard Worker // Check for overflow
380*b9df5ad1SAndroid Build Coastguard Worker if (data_count != 0 &&
381*b9df5ad1SAndroid Build Coastguard Worker camera_metadata_type_size[type] > (SIZE_MAX - DATA_ALIGNMENT + 1) / data_count) {
382*b9df5ad1SAndroid Build Coastguard Worker android_errorWriteLog(SN_EVENT_LOG_ID, "30741779");
383*b9df5ad1SAndroid Build Coastguard Worker return ERROR;
384*b9df5ad1SAndroid Build Coastguard Worker }
385*b9df5ad1SAndroid Build Coastguard Worker
386*b9df5ad1SAndroid Build Coastguard Worker size_t data_bytes = data_count * camera_metadata_type_size[type];
387*b9df5ad1SAndroid Build Coastguard Worker
388*b9df5ad1SAndroid Build Coastguard Worker if (data_size) {
389*b9df5ad1SAndroid Build Coastguard Worker *data_size = data_bytes <= 4 ? 0 : ALIGN_TO(data_bytes, DATA_ALIGNMENT);
390*b9df5ad1SAndroid Build Coastguard Worker }
391*b9df5ad1SAndroid Build Coastguard Worker
392*b9df5ad1SAndroid Build Coastguard Worker return OK;
393*b9df5ad1SAndroid Build Coastguard Worker }
394*b9df5ad1SAndroid Build Coastguard Worker
calculate_camera_metadata_entry_data_size(uint8_t type,size_t data_count)395*b9df5ad1SAndroid Build Coastguard Worker size_t calculate_camera_metadata_entry_data_size(uint8_t type,
396*b9df5ad1SAndroid Build Coastguard Worker size_t data_count) {
397*b9df5ad1SAndroid Build Coastguard Worker if (type >= NUM_TYPES) return 0;
398*b9df5ad1SAndroid Build Coastguard Worker
399*b9df5ad1SAndroid Build Coastguard Worker size_t data_bytes = data_count *
400*b9df5ad1SAndroid Build Coastguard Worker camera_metadata_type_size[type];
401*b9df5ad1SAndroid Build Coastguard Worker
402*b9df5ad1SAndroid Build Coastguard Worker return data_bytes <= 4 ? 0 : ALIGN_TO(data_bytes, DATA_ALIGNMENT);
403*b9df5ad1SAndroid Build Coastguard Worker }
404*b9df5ad1SAndroid Build Coastguard Worker
validate_camera_metadata_structure(const camera_metadata_t * metadata,const size_t * expected_size)405*b9df5ad1SAndroid Build Coastguard Worker int validate_camera_metadata_structure(const camera_metadata_t *metadata,
406*b9df5ad1SAndroid Build Coastguard Worker const size_t *expected_size) {
407*b9df5ad1SAndroid Build Coastguard Worker
408*b9df5ad1SAndroid Build Coastguard Worker if (metadata == NULL) {
409*b9df5ad1SAndroid Build Coastguard Worker ALOGE("%s: metadata is null!", __FUNCTION__);
410*b9df5ad1SAndroid Build Coastguard Worker return CAMERA_METADATA_VALIDATION_ERROR;
411*b9df5ad1SAndroid Build Coastguard Worker }
412*b9df5ad1SAndroid Build Coastguard Worker
413*b9df5ad1SAndroid Build Coastguard Worker uintptr_t aligned_ptr = ALIGN_TO(metadata, METADATA_PACKET_ALIGNMENT);
414*b9df5ad1SAndroid Build Coastguard Worker const uintptr_t alignmentOffset = aligned_ptr - (uintptr_t) metadata;
415*b9df5ad1SAndroid Build Coastguard Worker
416*b9df5ad1SAndroid Build Coastguard Worker // Check that the metadata pointer is well-aligned first.
417*b9df5ad1SAndroid Build Coastguard Worker {
418*b9df5ad1SAndroid Build Coastguard Worker static const struct {
419*b9df5ad1SAndroid Build Coastguard Worker const char *name;
420*b9df5ad1SAndroid Build Coastguard Worker size_t alignment;
421*b9df5ad1SAndroid Build Coastguard Worker } alignments[] = {
422*b9df5ad1SAndroid Build Coastguard Worker {
423*b9df5ad1SAndroid Build Coastguard Worker .name = "camera_metadata",
424*b9df5ad1SAndroid Build Coastguard Worker .alignment = METADATA_ALIGNMENT
425*b9df5ad1SAndroid Build Coastguard Worker },
426*b9df5ad1SAndroid Build Coastguard Worker {
427*b9df5ad1SAndroid Build Coastguard Worker .name = "camera_metadata_buffer_entry",
428*b9df5ad1SAndroid Build Coastguard Worker .alignment = ENTRY_ALIGNMENT
429*b9df5ad1SAndroid Build Coastguard Worker },
430*b9df5ad1SAndroid Build Coastguard Worker {
431*b9df5ad1SAndroid Build Coastguard Worker .name = "camera_metadata_data",
432*b9df5ad1SAndroid Build Coastguard Worker .alignment = DATA_ALIGNMENT
433*b9df5ad1SAndroid Build Coastguard Worker },
434*b9df5ad1SAndroid Build Coastguard Worker };
435*b9df5ad1SAndroid Build Coastguard Worker
436*b9df5ad1SAndroid Build Coastguard Worker for (size_t i = 0; i < sizeof(alignments)/sizeof(alignments[0]); ++i) {
437*b9df5ad1SAndroid Build Coastguard Worker uintptr_t aligned_ptr_section = ALIGN_TO((uintptr_t) metadata + alignmentOffset,
438*b9df5ad1SAndroid Build Coastguard Worker alignments[i].alignment);
439*b9df5ad1SAndroid Build Coastguard Worker
440*b9df5ad1SAndroid Build Coastguard Worker if ((uintptr_t)metadata + alignmentOffset != aligned_ptr_section) {
441*b9df5ad1SAndroid Build Coastguard Worker ALOGE("%s: Metadata pointer is not aligned (actual %p, "
442*b9df5ad1SAndroid Build Coastguard Worker "expected %p, offset %" PRIuPTR ") to type %s",
443*b9df5ad1SAndroid Build Coastguard Worker __FUNCTION__, metadata,
444*b9df5ad1SAndroid Build Coastguard Worker (void*)aligned_ptr_section, alignmentOffset, alignments[i].name);
445*b9df5ad1SAndroid Build Coastguard Worker return CAMERA_METADATA_VALIDATION_ERROR;
446*b9df5ad1SAndroid Build Coastguard Worker }
447*b9df5ad1SAndroid Build Coastguard Worker }
448*b9df5ad1SAndroid Build Coastguard Worker }
449*b9df5ad1SAndroid Build Coastguard Worker
450*b9df5ad1SAndroid Build Coastguard Worker /**
451*b9df5ad1SAndroid Build Coastguard Worker * Check that the metadata contents are correct
452*b9df5ad1SAndroid Build Coastguard Worker */
453*b9df5ad1SAndroid Build Coastguard Worker if (expected_size != NULL && sizeof(camera_metadata_t) > *expected_size) {
454*b9df5ad1SAndroid Build Coastguard Worker ALOGE("%s: Metadata size (%zu) should be <= expected size (%zu)",
455*b9df5ad1SAndroid Build Coastguard Worker __FUNCTION__, sizeof(camera_metadata_t), *expected_size);
456*b9df5ad1SAndroid Build Coastguard Worker return CAMERA_METADATA_VALIDATION_ERROR;
457*b9df5ad1SAndroid Build Coastguard Worker }
458*b9df5ad1SAndroid Build Coastguard Worker
459*b9df5ad1SAndroid Build Coastguard Worker // Create an aligned header
460*b9df5ad1SAndroid Build Coastguard Worker camera_metadata_t headerCopy;
461*b9df5ad1SAndroid Build Coastguard Worker const camera_metadata_t *header;
462*b9df5ad1SAndroid Build Coastguard Worker if (alignmentOffset != 0) {
463*b9df5ad1SAndroid Build Coastguard Worker memcpy(&headerCopy, metadata, sizeof(camera_metadata_t));
464*b9df5ad1SAndroid Build Coastguard Worker header = &headerCopy;
465*b9df5ad1SAndroid Build Coastguard Worker } else {
466*b9df5ad1SAndroid Build Coastguard Worker header = metadata;
467*b9df5ad1SAndroid Build Coastguard Worker }
468*b9df5ad1SAndroid Build Coastguard Worker
469*b9df5ad1SAndroid Build Coastguard Worker if (expected_size != NULL && header->size > *expected_size) {
470*b9df5ad1SAndroid Build Coastguard Worker ALOGE("%s: Metadata size (%" PRIu32 ") should be <= expected size (%zu)",
471*b9df5ad1SAndroid Build Coastguard Worker __FUNCTION__, header->size, *expected_size);
472*b9df5ad1SAndroid Build Coastguard Worker return CAMERA_METADATA_VALIDATION_ERROR;
473*b9df5ad1SAndroid Build Coastguard Worker }
474*b9df5ad1SAndroid Build Coastguard Worker
475*b9df5ad1SAndroid Build Coastguard Worker if (header->entry_count > header->entry_capacity) {
476*b9df5ad1SAndroid Build Coastguard Worker ALOGE("%s: Entry count (%" PRIu32 ") should be <= entry capacity "
477*b9df5ad1SAndroid Build Coastguard Worker "(%" PRIu32 ")",
478*b9df5ad1SAndroid Build Coastguard Worker __FUNCTION__, header->entry_count, header->entry_capacity);
479*b9df5ad1SAndroid Build Coastguard Worker return CAMERA_METADATA_VALIDATION_ERROR;
480*b9df5ad1SAndroid Build Coastguard Worker }
481*b9df5ad1SAndroid Build Coastguard Worker
482*b9df5ad1SAndroid Build Coastguard Worker if (header->data_count > header->data_capacity) {
483*b9df5ad1SAndroid Build Coastguard Worker ALOGE("%s: Data count (%" PRIu32 ") should be <= data capacity "
484*b9df5ad1SAndroid Build Coastguard Worker "(%" PRIu32 ")",
485*b9df5ad1SAndroid Build Coastguard Worker __FUNCTION__, header->data_count, header->data_capacity);
486*b9df5ad1SAndroid Build Coastguard Worker android_errorWriteLog(SN_EVENT_LOG_ID, "30591838");
487*b9df5ad1SAndroid Build Coastguard Worker return CAMERA_METADATA_VALIDATION_ERROR;
488*b9df5ad1SAndroid Build Coastguard Worker }
489*b9df5ad1SAndroid Build Coastguard Worker
490*b9df5ad1SAndroid Build Coastguard Worker const metadata_uptrdiff_t entries_end =
491*b9df5ad1SAndroid Build Coastguard Worker header->entries_start + header->entry_capacity;
492*b9df5ad1SAndroid Build Coastguard Worker if (entries_end < header->entries_start || // overflow check
493*b9df5ad1SAndroid Build Coastguard Worker entries_end > header->data_start) {
494*b9df5ad1SAndroid Build Coastguard Worker
495*b9df5ad1SAndroid Build Coastguard Worker ALOGE("%s: Entry start + capacity (%" PRIu32 ") should be <= data start "
496*b9df5ad1SAndroid Build Coastguard Worker "(%" PRIu32 ")",
497*b9df5ad1SAndroid Build Coastguard Worker __FUNCTION__,
498*b9df5ad1SAndroid Build Coastguard Worker (header->entries_start + header->entry_capacity),
499*b9df5ad1SAndroid Build Coastguard Worker header->data_start);
500*b9df5ad1SAndroid Build Coastguard Worker return CAMERA_METADATA_VALIDATION_ERROR;
501*b9df5ad1SAndroid Build Coastguard Worker }
502*b9df5ad1SAndroid Build Coastguard Worker
503*b9df5ad1SAndroid Build Coastguard Worker const metadata_uptrdiff_t data_end =
504*b9df5ad1SAndroid Build Coastguard Worker header->data_start + header->data_capacity;
505*b9df5ad1SAndroid Build Coastguard Worker if (data_end < header->data_start || // overflow check
506*b9df5ad1SAndroid Build Coastguard Worker data_end > header->size) {
507*b9df5ad1SAndroid Build Coastguard Worker
508*b9df5ad1SAndroid Build Coastguard Worker ALOGE("%s: Data start + capacity (%" PRIu32 ") should be <= total size "
509*b9df5ad1SAndroid Build Coastguard Worker "(%" PRIu32 ")",
510*b9df5ad1SAndroid Build Coastguard Worker __FUNCTION__,
511*b9df5ad1SAndroid Build Coastguard Worker (header->data_start + header->data_capacity),
512*b9df5ad1SAndroid Build Coastguard Worker header->size);
513*b9df5ad1SAndroid Build Coastguard Worker return CAMERA_METADATA_VALIDATION_ERROR;
514*b9df5ad1SAndroid Build Coastguard Worker }
515*b9df5ad1SAndroid Build Coastguard Worker
516*b9df5ad1SAndroid Build Coastguard Worker // Validate each entry
517*b9df5ad1SAndroid Build Coastguard Worker const metadata_size_t entry_count = header->entry_count;
518*b9df5ad1SAndroid Build Coastguard Worker camera_metadata_buffer_entry_t *entries = get_entries(metadata);
519*b9df5ad1SAndroid Build Coastguard Worker
520*b9df5ad1SAndroid Build Coastguard Worker for (size_t i = 0; i < entry_count; ++i) {
521*b9df5ad1SAndroid Build Coastguard Worker
522*b9df5ad1SAndroid Build Coastguard Worker if ((uintptr_t)&entries[i] + alignmentOffset !=
523*b9df5ad1SAndroid Build Coastguard Worker ALIGN_TO((uintptr_t)&entries[i] + alignmentOffset, ENTRY_ALIGNMENT)) {
524*b9df5ad1SAndroid Build Coastguard Worker ALOGE("%s: Entry index %zu had bad alignment (address %p),"
525*b9df5ad1SAndroid Build Coastguard Worker " expected alignment %zu",
526*b9df5ad1SAndroid Build Coastguard Worker __FUNCTION__, i, &entries[i], ENTRY_ALIGNMENT);
527*b9df5ad1SAndroid Build Coastguard Worker return CAMERA_METADATA_VALIDATION_ERROR;
528*b9df5ad1SAndroid Build Coastguard Worker }
529*b9df5ad1SAndroid Build Coastguard Worker
530*b9df5ad1SAndroid Build Coastguard Worker camera_metadata_buffer_entry_t entry;
531*b9df5ad1SAndroid Build Coastguard Worker if (alignmentOffset != 0) {
532*b9df5ad1SAndroid Build Coastguard Worker memcpy(&entry, entries + i, sizeof(camera_metadata_buffer_entry_t));
533*b9df5ad1SAndroid Build Coastguard Worker } else {
534*b9df5ad1SAndroid Build Coastguard Worker entry = entries[i];
535*b9df5ad1SAndroid Build Coastguard Worker }
536*b9df5ad1SAndroid Build Coastguard Worker
537*b9df5ad1SAndroid Build Coastguard Worker if (entry.type >= NUM_TYPES) {
538*b9df5ad1SAndroid Build Coastguard Worker ALOGE("%s: Entry index %zu had a bad type %d",
539*b9df5ad1SAndroid Build Coastguard Worker __FUNCTION__, i, entry.type);
540*b9df5ad1SAndroid Build Coastguard Worker return CAMERA_METADATA_VALIDATION_ERROR;
541*b9df5ad1SAndroid Build Coastguard Worker }
542*b9df5ad1SAndroid Build Coastguard Worker
543*b9df5ad1SAndroid Build Coastguard Worker // TODO: fix vendor_tag_ops across processes so we don't need to special
544*b9df5ad1SAndroid Build Coastguard Worker // case vendor-specific tags
545*b9df5ad1SAndroid Build Coastguard Worker uint32_t tag_section = entry.tag >> 16;
546*b9df5ad1SAndroid Build Coastguard Worker int tag_type = get_local_camera_metadata_tag_type(entry.tag, header);
547*b9df5ad1SAndroid Build Coastguard Worker if (tag_type != (int)entry.type && tag_section < VENDOR_SECTION) {
548*b9df5ad1SAndroid Build Coastguard Worker ALOGE("%s: Entry index %zu (0x%x) had tag type %d, but the type was %d",
549*b9df5ad1SAndroid Build Coastguard Worker __FUNCTION__, i, entry.tag, tag_type, entry.type);
550*b9df5ad1SAndroid Build Coastguard Worker return CAMERA_METADATA_VALIDATION_ERROR;
551*b9df5ad1SAndroid Build Coastguard Worker }
552*b9df5ad1SAndroid Build Coastguard Worker
553*b9df5ad1SAndroid Build Coastguard Worker size_t data_size;
554*b9df5ad1SAndroid Build Coastguard Worker if (validate_and_calculate_camera_metadata_entry_data_size(&data_size, entry.type,
555*b9df5ad1SAndroid Build Coastguard Worker entry.count) != OK) {
556*b9df5ad1SAndroid Build Coastguard Worker ALOGE("%s: Entry data size is invalid. type: %u count: %u", __FUNCTION__, entry.type,
557*b9df5ad1SAndroid Build Coastguard Worker entry.count);
558*b9df5ad1SAndroid Build Coastguard Worker return CAMERA_METADATA_VALIDATION_ERROR;
559*b9df5ad1SAndroid Build Coastguard Worker }
560*b9df5ad1SAndroid Build Coastguard Worker
561*b9df5ad1SAndroid Build Coastguard Worker if (data_size != 0) {
562*b9df5ad1SAndroid Build Coastguard Worker camera_metadata_data_t *data =
563*b9df5ad1SAndroid Build Coastguard Worker (camera_metadata_data_t*) (get_data(metadata) +
564*b9df5ad1SAndroid Build Coastguard Worker entry.data.offset);
565*b9df5ad1SAndroid Build Coastguard Worker
566*b9df5ad1SAndroid Build Coastguard Worker if ((uintptr_t)data + alignmentOffset !=
567*b9df5ad1SAndroid Build Coastguard Worker ALIGN_TO((uintptr_t)data + alignmentOffset, DATA_ALIGNMENT)) {
568*b9df5ad1SAndroid Build Coastguard Worker ALOGE("%s: Entry index %zu had bad data alignment (address %p),"
569*b9df5ad1SAndroid Build Coastguard Worker " expected align %zu, (tag name %s, data size %zu)",
570*b9df5ad1SAndroid Build Coastguard Worker __FUNCTION__, i, data, DATA_ALIGNMENT,
571*b9df5ad1SAndroid Build Coastguard Worker get_local_camera_metadata_tag_name(entry.tag, metadata) ?
572*b9df5ad1SAndroid Build Coastguard Worker : "unknown", data_size);
573*b9df5ad1SAndroid Build Coastguard Worker return CAMERA_METADATA_VALIDATION_ERROR;
574*b9df5ad1SAndroid Build Coastguard Worker }
575*b9df5ad1SAndroid Build Coastguard Worker
576*b9df5ad1SAndroid Build Coastguard Worker size_t data_entry_end = entry.data.offset + data_size;
577*b9df5ad1SAndroid Build Coastguard Worker if (data_entry_end < entry.data.offset || // overflow check
578*b9df5ad1SAndroid Build Coastguard Worker data_entry_end > metadata->data_capacity) {
579*b9df5ad1SAndroid Build Coastguard Worker
580*b9df5ad1SAndroid Build Coastguard Worker ALOGE("%s: Entry index %zu data ends (%zu) beyond the capacity "
581*b9df5ad1SAndroid Build Coastguard Worker "%" PRIu32, __FUNCTION__, i, data_entry_end,
582*b9df5ad1SAndroid Build Coastguard Worker metadata->data_capacity);
583*b9df5ad1SAndroid Build Coastguard Worker return CAMERA_METADATA_VALIDATION_ERROR;
584*b9df5ad1SAndroid Build Coastguard Worker }
585*b9df5ad1SAndroid Build Coastguard Worker
586*b9df5ad1SAndroid Build Coastguard Worker } else if (entry.count == 0) {
587*b9df5ad1SAndroid Build Coastguard Worker if (entry.data.offset != 0) {
588*b9df5ad1SAndroid Build Coastguard Worker ALOGE("%s: Entry index %zu had 0 items, but offset was non-0 "
589*b9df5ad1SAndroid Build Coastguard Worker "(%" PRIu32 "), tag name: %s", __FUNCTION__, i, entry.data.offset,
590*b9df5ad1SAndroid Build Coastguard Worker get_local_camera_metadata_tag_name(entry.tag, metadata) ? : "unknown");
591*b9df5ad1SAndroid Build Coastguard Worker return CAMERA_METADATA_VALIDATION_ERROR;
592*b9df5ad1SAndroid Build Coastguard Worker }
593*b9df5ad1SAndroid Build Coastguard Worker } // else data stored inline, so we look at value which can be anything.
594*b9df5ad1SAndroid Build Coastguard Worker }
595*b9df5ad1SAndroid Build Coastguard Worker
596*b9df5ad1SAndroid Build Coastguard Worker if (alignmentOffset == 0) {
597*b9df5ad1SAndroid Build Coastguard Worker return OK;
598*b9df5ad1SAndroid Build Coastguard Worker }
599*b9df5ad1SAndroid Build Coastguard Worker return CAMERA_METADATA_VALIDATION_SHIFTED;
600*b9df5ad1SAndroid Build Coastguard Worker }
601*b9df5ad1SAndroid Build Coastguard Worker
append_camera_metadata(camera_metadata_t * dst,const camera_metadata_t * src)602*b9df5ad1SAndroid Build Coastguard Worker int append_camera_metadata(camera_metadata_t *dst,
603*b9df5ad1SAndroid Build Coastguard Worker const camera_metadata_t *src) {
604*b9df5ad1SAndroid Build Coastguard Worker if (dst == NULL || src == NULL ) return ERROR;
605*b9df5ad1SAndroid Build Coastguard Worker
606*b9df5ad1SAndroid Build Coastguard Worker // Check for overflow
607*b9df5ad1SAndroid Build Coastguard Worker if (src->entry_count + dst->entry_count < src->entry_count) return ERROR;
608*b9df5ad1SAndroid Build Coastguard Worker if (src->data_count + dst->data_count < src->data_count) return ERROR;
609*b9df5ad1SAndroid Build Coastguard Worker // Check for space
610*b9df5ad1SAndroid Build Coastguard Worker if (dst->entry_capacity < src->entry_count + dst->entry_count) return ERROR;
611*b9df5ad1SAndroid Build Coastguard Worker if (dst->data_capacity < src->data_count + dst->data_count) return ERROR;
612*b9df5ad1SAndroid Build Coastguard Worker
613*b9df5ad1SAndroid Build Coastguard Worker if ((dst->vendor_id != CAMERA_METADATA_INVALID_VENDOR_ID) &&
614*b9df5ad1SAndroid Build Coastguard Worker (src->vendor_id != CAMERA_METADATA_INVALID_VENDOR_ID)) {
615*b9df5ad1SAndroid Build Coastguard Worker if (dst->vendor_id != src->vendor_id) {
616*b9df5ad1SAndroid Build Coastguard Worker ALOGE("%s: Append for metadata from different vendors is"
617*b9df5ad1SAndroid Build Coastguard Worker "not supported!", __func__);
618*b9df5ad1SAndroid Build Coastguard Worker return ERROR;
619*b9df5ad1SAndroid Build Coastguard Worker }
620*b9df5ad1SAndroid Build Coastguard Worker }
621*b9df5ad1SAndroid Build Coastguard Worker
622*b9df5ad1SAndroid Build Coastguard Worker memcpy(get_entries(dst) + dst->entry_count, get_entries(src),
623*b9df5ad1SAndroid Build Coastguard Worker sizeof(camera_metadata_buffer_entry_t[src->entry_count]));
624*b9df5ad1SAndroid Build Coastguard Worker memcpy(get_data(dst) + dst->data_count, get_data(src),
625*b9df5ad1SAndroid Build Coastguard Worker sizeof(uint8_t[src->data_count]));
626*b9df5ad1SAndroid Build Coastguard Worker if (dst->data_count != 0) {
627*b9df5ad1SAndroid Build Coastguard Worker camera_metadata_buffer_entry_t *entry = get_entries(dst) + dst->entry_count;
628*b9df5ad1SAndroid Build Coastguard Worker for (size_t i = 0; i < src->entry_count; i++, entry++) {
629*b9df5ad1SAndroid Build Coastguard Worker if ( calculate_camera_metadata_entry_data_size(entry->type,
630*b9df5ad1SAndroid Build Coastguard Worker entry->count) > 0 ) {
631*b9df5ad1SAndroid Build Coastguard Worker entry->data.offset += dst->data_count;
632*b9df5ad1SAndroid Build Coastguard Worker }
633*b9df5ad1SAndroid Build Coastguard Worker }
634*b9df5ad1SAndroid Build Coastguard Worker }
635*b9df5ad1SAndroid Build Coastguard Worker if (dst->entry_count == 0) {
636*b9df5ad1SAndroid Build Coastguard Worker // Appending onto empty buffer, keep sorted state
637*b9df5ad1SAndroid Build Coastguard Worker dst->flags |= src->flags & FLAG_SORTED;
638*b9df5ad1SAndroid Build Coastguard Worker } else if (src->entry_count != 0) {
639*b9df5ad1SAndroid Build Coastguard Worker // Both src, dst are nonempty, cannot assume sort remains
640*b9df5ad1SAndroid Build Coastguard Worker dst->flags &= ~FLAG_SORTED;
641*b9df5ad1SAndroid Build Coastguard Worker } else {
642*b9df5ad1SAndroid Build Coastguard Worker // Src is empty, keep dst sorted state
643*b9df5ad1SAndroid Build Coastguard Worker }
644*b9df5ad1SAndroid Build Coastguard Worker dst->entry_count += src->entry_count;
645*b9df5ad1SAndroid Build Coastguard Worker dst->data_count += src->data_count;
646*b9df5ad1SAndroid Build Coastguard Worker
647*b9df5ad1SAndroid Build Coastguard Worker if (dst->vendor_id == CAMERA_METADATA_INVALID_VENDOR_ID) {
648*b9df5ad1SAndroid Build Coastguard Worker dst->vendor_id = src->vendor_id;
649*b9df5ad1SAndroid Build Coastguard Worker }
650*b9df5ad1SAndroid Build Coastguard Worker
651*b9df5ad1SAndroid Build Coastguard Worker assert(validate_camera_metadata_structure(dst, NULL) == OK);
652*b9df5ad1SAndroid Build Coastguard Worker return OK;
653*b9df5ad1SAndroid Build Coastguard Worker }
654*b9df5ad1SAndroid Build Coastguard Worker
clone_camera_metadata(const camera_metadata_t * src)655*b9df5ad1SAndroid Build Coastguard Worker camera_metadata_t *clone_camera_metadata(const camera_metadata_t *src) {
656*b9df5ad1SAndroid Build Coastguard Worker int res;
657*b9df5ad1SAndroid Build Coastguard Worker if (src == NULL) return NULL;
658*b9df5ad1SAndroid Build Coastguard Worker camera_metadata_t *clone = allocate_camera_metadata(
659*b9df5ad1SAndroid Build Coastguard Worker get_camera_metadata_entry_count(src),
660*b9df5ad1SAndroid Build Coastguard Worker get_camera_metadata_data_count(src));
661*b9df5ad1SAndroid Build Coastguard Worker if (clone != NULL) {
662*b9df5ad1SAndroid Build Coastguard Worker res = append_camera_metadata(clone, src);
663*b9df5ad1SAndroid Build Coastguard Worker if (res != OK) {
664*b9df5ad1SAndroid Build Coastguard Worker free_camera_metadata(clone);
665*b9df5ad1SAndroid Build Coastguard Worker clone = NULL;
666*b9df5ad1SAndroid Build Coastguard Worker }
667*b9df5ad1SAndroid Build Coastguard Worker }
668*b9df5ad1SAndroid Build Coastguard Worker assert(validate_camera_metadata_structure(clone, NULL) == OK);
669*b9df5ad1SAndroid Build Coastguard Worker return clone;
670*b9df5ad1SAndroid Build Coastguard Worker }
671*b9df5ad1SAndroid Build Coastguard Worker
add_camera_metadata_entry_raw(camera_metadata_t * dst,uint32_t tag,uint8_t type,const void * data,size_t data_count)672*b9df5ad1SAndroid Build Coastguard Worker static int add_camera_metadata_entry_raw(camera_metadata_t *dst,
673*b9df5ad1SAndroid Build Coastguard Worker uint32_t tag,
674*b9df5ad1SAndroid Build Coastguard Worker uint8_t type,
675*b9df5ad1SAndroid Build Coastguard Worker const void *data,
676*b9df5ad1SAndroid Build Coastguard Worker size_t data_count) {
677*b9df5ad1SAndroid Build Coastguard Worker
678*b9df5ad1SAndroid Build Coastguard Worker if (dst == NULL) return ERROR;
679*b9df5ad1SAndroid Build Coastguard Worker if (dst->entry_count == dst->entry_capacity) return ERROR;
680*b9df5ad1SAndroid Build Coastguard Worker if (data_count && data == NULL) return ERROR;
681*b9df5ad1SAndroid Build Coastguard Worker
682*b9df5ad1SAndroid Build Coastguard Worker size_t data_bytes =
683*b9df5ad1SAndroid Build Coastguard Worker calculate_camera_metadata_entry_data_size(type, data_count);
684*b9df5ad1SAndroid Build Coastguard Worker if (data_bytes + dst->data_count > dst->data_capacity) return ERROR;
685*b9df5ad1SAndroid Build Coastguard Worker
686*b9df5ad1SAndroid Build Coastguard Worker size_t data_payload_bytes =
687*b9df5ad1SAndroid Build Coastguard Worker data_count * camera_metadata_type_size[type];
688*b9df5ad1SAndroid Build Coastguard Worker camera_metadata_buffer_entry_t *entry = get_entries(dst) + dst->entry_count;
689*b9df5ad1SAndroid Build Coastguard Worker memset(entry, 0, sizeof(camera_metadata_buffer_entry_t));
690*b9df5ad1SAndroid Build Coastguard Worker entry->tag = tag;
691*b9df5ad1SAndroid Build Coastguard Worker entry->type = type;
692*b9df5ad1SAndroid Build Coastguard Worker entry->count = data_count;
693*b9df5ad1SAndroid Build Coastguard Worker
694*b9df5ad1SAndroid Build Coastguard Worker if (data_bytes == 0) {
695*b9df5ad1SAndroid Build Coastguard Worker memcpy(entry->data.value, data,
696*b9df5ad1SAndroid Build Coastguard Worker data_payload_bytes);
697*b9df5ad1SAndroid Build Coastguard Worker } else {
698*b9df5ad1SAndroid Build Coastguard Worker entry->data.offset = dst->data_count;
699*b9df5ad1SAndroid Build Coastguard Worker memcpy(get_data(dst) + entry->data.offset, data,
700*b9df5ad1SAndroid Build Coastguard Worker data_payload_bytes);
701*b9df5ad1SAndroid Build Coastguard Worker dst->data_count += data_bytes;
702*b9df5ad1SAndroid Build Coastguard Worker }
703*b9df5ad1SAndroid Build Coastguard Worker dst->entry_count++;
704*b9df5ad1SAndroid Build Coastguard Worker dst->flags &= ~FLAG_SORTED;
705*b9df5ad1SAndroid Build Coastguard Worker assert(validate_camera_metadata_structure(dst, NULL) == OK);
706*b9df5ad1SAndroid Build Coastguard Worker return OK;
707*b9df5ad1SAndroid Build Coastguard Worker }
708*b9df5ad1SAndroid Build Coastguard Worker
add_camera_metadata_entry(camera_metadata_t * dst,uint32_t tag,const void * data,size_t data_count)709*b9df5ad1SAndroid Build Coastguard Worker int add_camera_metadata_entry(camera_metadata_t *dst,
710*b9df5ad1SAndroid Build Coastguard Worker uint32_t tag,
711*b9df5ad1SAndroid Build Coastguard Worker const void *data,
712*b9df5ad1SAndroid Build Coastguard Worker size_t data_count) {
713*b9df5ad1SAndroid Build Coastguard Worker
714*b9df5ad1SAndroid Build Coastguard Worker int type = get_local_camera_metadata_tag_type(tag, dst);
715*b9df5ad1SAndroid Build Coastguard Worker if (type == -1) {
716*b9df5ad1SAndroid Build Coastguard Worker ALOGE("%s: Unknown tag %04x.", __FUNCTION__, tag);
717*b9df5ad1SAndroid Build Coastguard Worker return ERROR;
718*b9df5ad1SAndroid Build Coastguard Worker }
719*b9df5ad1SAndroid Build Coastguard Worker
720*b9df5ad1SAndroid Build Coastguard Worker return add_camera_metadata_entry_raw(dst,
721*b9df5ad1SAndroid Build Coastguard Worker tag,
722*b9df5ad1SAndroid Build Coastguard Worker type,
723*b9df5ad1SAndroid Build Coastguard Worker data,
724*b9df5ad1SAndroid Build Coastguard Worker data_count);
725*b9df5ad1SAndroid Build Coastguard Worker }
726*b9df5ad1SAndroid Build Coastguard Worker
compare_entry_tags(const void * p1,const void * p2)727*b9df5ad1SAndroid Build Coastguard Worker static int compare_entry_tags(const void *p1, const void *p2) {
728*b9df5ad1SAndroid Build Coastguard Worker uint32_t tag1 = ((camera_metadata_buffer_entry_t*)p1)->tag;
729*b9df5ad1SAndroid Build Coastguard Worker uint32_t tag2 = ((camera_metadata_buffer_entry_t*)p2)->tag;
730*b9df5ad1SAndroid Build Coastguard Worker return tag1 < tag2 ? -1 :
731*b9df5ad1SAndroid Build Coastguard Worker tag1 == tag2 ? 0 :
732*b9df5ad1SAndroid Build Coastguard Worker 1;
733*b9df5ad1SAndroid Build Coastguard Worker }
734*b9df5ad1SAndroid Build Coastguard Worker
sort_camera_metadata(camera_metadata_t * dst)735*b9df5ad1SAndroid Build Coastguard Worker int sort_camera_metadata(camera_metadata_t *dst) {
736*b9df5ad1SAndroid Build Coastguard Worker if (dst == NULL) return ERROR;
737*b9df5ad1SAndroid Build Coastguard Worker if (dst->flags & FLAG_SORTED) return OK;
738*b9df5ad1SAndroid Build Coastguard Worker
739*b9df5ad1SAndroid Build Coastguard Worker qsort(get_entries(dst), dst->entry_count,
740*b9df5ad1SAndroid Build Coastguard Worker sizeof(camera_metadata_buffer_entry_t),
741*b9df5ad1SAndroid Build Coastguard Worker compare_entry_tags);
742*b9df5ad1SAndroid Build Coastguard Worker dst->flags |= FLAG_SORTED;
743*b9df5ad1SAndroid Build Coastguard Worker
744*b9df5ad1SAndroid Build Coastguard Worker assert(validate_camera_metadata_structure(dst, NULL) == OK);
745*b9df5ad1SAndroid Build Coastguard Worker return OK;
746*b9df5ad1SAndroid Build Coastguard Worker }
747*b9df5ad1SAndroid Build Coastguard Worker
get_camera_metadata_entry(camera_metadata_t * src,size_t index,camera_metadata_entry_t * entry)748*b9df5ad1SAndroid Build Coastguard Worker int get_camera_metadata_entry(camera_metadata_t *src,
749*b9df5ad1SAndroid Build Coastguard Worker size_t index,
750*b9df5ad1SAndroid Build Coastguard Worker camera_metadata_entry_t *entry) {
751*b9df5ad1SAndroid Build Coastguard Worker if (src == NULL || entry == NULL) return ERROR;
752*b9df5ad1SAndroid Build Coastguard Worker if (index >= src->entry_count) return ERROR;
753*b9df5ad1SAndroid Build Coastguard Worker
754*b9df5ad1SAndroid Build Coastguard Worker camera_metadata_buffer_entry_t *buffer_entry = get_entries(src) + index;
755*b9df5ad1SAndroid Build Coastguard Worker
756*b9df5ad1SAndroid Build Coastguard Worker entry->index = index;
757*b9df5ad1SAndroid Build Coastguard Worker entry->tag = buffer_entry->tag;
758*b9df5ad1SAndroid Build Coastguard Worker entry->type = buffer_entry->type;
759*b9df5ad1SAndroid Build Coastguard Worker entry->count = buffer_entry->count;
760*b9df5ad1SAndroid Build Coastguard Worker if (buffer_entry->count *
761*b9df5ad1SAndroid Build Coastguard Worker camera_metadata_type_size[buffer_entry->type] > 4) {
762*b9df5ad1SAndroid Build Coastguard Worker entry->data.u8 = get_data(src) + buffer_entry->data.offset;
763*b9df5ad1SAndroid Build Coastguard Worker } else {
764*b9df5ad1SAndroid Build Coastguard Worker entry->data.u8 = buffer_entry->data.value;
765*b9df5ad1SAndroid Build Coastguard Worker }
766*b9df5ad1SAndroid Build Coastguard Worker return OK;
767*b9df5ad1SAndroid Build Coastguard Worker }
768*b9df5ad1SAndroid Build Coastguard Worker
get_camera_metadata_ro_entry(const camera_metadata_t * src,size_t index,camera_metadata_ro_entry_t * entry)769*b9df5ad1SAndroid Build Coastguard Worker int get_camera_metadata_ro_entry(const camera_metadata_t *src,
770*b9df5ad1SAndroid Build Coastguard Worker size_t index,
771*b9df5ad1SAndroid Build Coastguard Worker camera_metadata_ro_entry_t *entry) {
772*b9df5ad1SAndroid Build Coastguard Worker return get_camera_metadata_entry((camera_metadata_t*)src, index,
773*b9df5ad1SAndroid Build Coastguard Worker (camera_metadata_entry_t*)entry);
774*b9df5ad1SAndroid Build Coastguard Worker }
775*b9df5ad1SAndroid Build Coastguard Worker
find_camera_metadata_entry(camera_metadata_t * src,uint32_t tag,camera_metadata_entry_t * entry)776*b9df5ad1SAndroid Build Coastguard Worker int find_camera_metadata_entry(camera_metadata_t *src,
777*b9df5ad1SAndroid Build Coastguard Worker uint32_t tag,
778*b9df5ad1SAndroid Build Coastguard Worker camera_metadata_entry_t *entry) {
779*b9df5ad1SAndroid Build Coastguard Worker if (src == NULL) return ERROR;
780*b9df5ad1SAndroid Build Coastguard Worker
781*b9df5ad1SAndroid Build Coastguard Worker uint32_t index;
782*b9df5ad1SAndroid Build Coastguard Worker if (src->flags & FLAG_SORTED) {
783*b9df5ad1SAndroid Build Coastguard Worker // Sorted entries, do a binary search
784*b9df5ad1SAndroid Build Coastguard Worker camera_metadata_buffer_entry_t *search_entry = NULL;
785*b9df5ad1SAndroid Build Coastguard Worker camera_metadata_buffer_entry_t key;
786*b9df5ad1SAndroid Build Coastguard Worker key.tag = tag;
787*b9df5ad1SAndroid Build Coastguard Worker search_entry = bsearch(&key,
788*b9df5ad1SAndroid Build Coastguard Worker get_entries(src),
789*b9df5ad1SAndroid Build Coastguard Worker src->entry_count,
790*b9df5ad1SAndroid Build Coastguard Worker sizeof(camera_metadata_buffer_entry_t),
791*b9df5ad1SAndroid Build Coastguard Worker compare_entry_tags);
792*b9df5ad1SAndroid Build Coastguard Worker if (search_entry == NULL) return NOT_FOUND;
793*b9df5ad1SAndroid Build Coastguard Worker index = search_entry - get_entries(src);
794*b9df5ad1SAndroid Build Coastguard Worker } else {
795*b9df5ad1SAndroid Build Coastguard Worker // Not sorted, linear search
796*b9df5ad1SAndroid Build Coastguard Worker camera_metadata_buffer_entry_t *search_entry = get_entries(src);
797*b9df5ad1SAndroid Build Coastguard Worker for (index = 0; index < src->entry_count; index++, search_entry++) {
798*b9df5ad1SAndroid Build Coastguard Worker if (search_entry->tag == tag) {
799*b9df5ad1SAndroid Build Coastguard Worker break;
800*b9df5ad1SAndroid Build Coastguard Worker }
801*b9df5ad1SAndroid Build Coastguard Worker }
802*b9df5ad1SAndroid Build Coastguard Worker if (index == src->entry_count) return NOT_FOUND;
803*b9df5ad1SAndroid Build Coastguard Worker }
804*b9df5ad1SAndroid Build Coastguard Worker
805*b9df5ad1SAndroid Build Coastguard Worker return get_camera_metadata_entry(src, index,
806*b9df5ad1SAndroid Build Coastguard Worker entry);
807*b9df5ad1SAndroid Build Coastguard Worker }
808*b9df5ad1SAndroid Build Coastguard Worker
find_camera_metadata_ro_entry(const camera_metadata_t * src,uint32_t tag,camera_metadata_ro_entry_t * entry)809*b9df5ad1SAndroid Build Coastguard Worker int find_camera_metadata_ro_entry(const camera_metadata_t *src,
810*b9df5ad1SAndroid Build Coastguard Worker uint32_t tag,
811*b9df5ad1SAndroid Build Coastguard Worker camera_metadata_ro_entry_t *entry) {
812*b9df5ad1SAndroid Build Coastguard Worker return find_camera_metadata_entry((camera_metadata_t*)src, tag,
813*b9df5ad1SAndroid Build Coastguard Worker (camera_metadata_entry_t*)entry);
814*b9df5ad1SAndroid Build Coastguard Worker }
815*b9df5ad1SAndroid Build Coastguard Worker
816*b9df5ad1SAndroid Build Coastguard Worker
delete_camera_metadata_entry(camera_metadata_t * dst,size_t index)817*b9df5ad1SAndroid Build Coastguard Worker int delete_camera_metadata_entry(camera_metadata_t *dst,
818*b9df5ad1SAndroid Build Coastguard Worker size_t index) {
819*b9df5ad1SAndroid Build Coastguard Worker if (dst == NULL) return ERROR;
820*b9df5ad1SAndroid Build Coastguard Worker if (index >= dst->entry_count) return ERROR;
821*b9df5ad1SAndroid Build Coastguard Worker
822*b9df5ad1SAndroid Build Coastguard Worker camera_metadata_buffer_entry_t *entry = get_entries(dst) + index;
823*b9df5ad1SAndroid Build Coastguard Worker size_t data_bytes = calculate_camera_metadata_entry_data_size(entry->type,
824*b9df5ad1SAndroid Build Coastguard Worker entry->count);
825*b9df5ad1SAndroid Build Coastguard Worker
826*b9df5ad1SAndroid Build Coastguard Worker if (data_bytes > 0) {
827*b9df5ad1SAndroid Build Coastguard Worker // Shift data buffer to overwrite deleted data
828*b9df5ad1SAndroid Build Coastguard Worker uint8_t *start = get_data(dst) + entry->data.offset;
829*b9df5ad1SAndroid Build Coastguard Worker uint8_t *end = start + data_bytes;
830*b9df5ad1SAndroid Build Coastguard Worker size_t length = dst->data_count - entry->data.offset - data_bytes;
831*b9df5ad1SAndroid Build Coastguard Worker memmove(start, end, length);
832*b9df5ad1SAndroid Build Coastguard Worker
833*b9df5ad1SAndroid Build Coastguard Worker // Update all entry indices to account for shift
834*b9df5ad1SAndroid Build Coastguard Worker camera_metadata_buffer_entry_t *e = get_entries(dst);
835*b9df5ad1SAndroid Build Coastguard Worker size_t i;
836*b9df5ad1SAndroid Build Coastguard Worker for (i = 0; i < dst->entry_count; i++) {
837*b9df5ad1SAndroid Build Coastguard Worker if (calculate_camera_metadata_entry_data_size(
838*b9df5ad1SAndroid Build Coastguard Worker e->type, e->count) > 0 &&
839*b9df5ad1SAndroid Build Coastguard Worker e->data.offset > entry->data.offset) {
840*b9df5ad1SAndroid Build Coastguard Worker e->data.offset -= data_bytes;
841*b9df5ad1SAndroid Build Coastguard Worker }
842*b9df5ad1SAndroid Build Coastguard Worker ++e;
843*b9df5ad1SAndroid Build Coastguard Worker }
844*b9df5ad1SAndroid Build Coastguard Worker dst->data_count -= data_bytes;
845*b9df5ad1SAndroid Build Coastguard Worker }
846*b9df5ad1SAndroid Build Coastguard Worker // Shift entry array
847*b9df5ad1SAndroid Build Coastguard Worker memmove(entry, entry + 1,
848*b9df5ad1SAndroid Build Coastguard Worker sizeof(camera_metadata_buffer_entry_t) *
849*b9df5ad1SAndroid Build Coastguard Worker (dst->entry_count - index - 1) );
850*b9df5ad1SAndroid Build Coastguard Worker dst->entry_count -= 1;
851*b9df5ad1SAndroid Build Coastguard Worker
852*b9df5ad1SAndroid Build Coastguard Worker assert(validate_camera_metadata_structure(dst, NULL) == OK);
853*b9df5ad1SAndroid Build Coastguard Worker return OK;
854*b9df5ad1SAndroid Build Coastguard Worker }
855*b9df5ad1SAndroid Build Coastguard Worker
update_camera_metadata_entry(camera_metadata_t * dst,size_t index,const void * data,size_t data_count,camera_metadata_entry_t * updated_entry)856*b9df5ad1SAndroid Build Coastguard Worker int update_camera_metadata_entry(camera_metadata_t *dst,
857*b9df5ad1SAndroid Build Coastguard Worker size_t index,
858*b9df5ad1SAndroid Build Coastguard Worker const void *data,
859*b9df5ad1SAndroid Build Coastguard Worker size_t data_count,
860*b9df5ad1SAndroid Build Coastguard Worker camera_metadata_entry_t *updated_entry) {
861*b9df5ad1SAndroid Build Coastguard Worker if (dst == NULL) return ERROR;
862*b9df5ad1SAndroid Build Coastguard Worker if (index >= dst->entry_count) return ERROR;
863*b9df5ad1SAndroid Build Coastguard Worker
864*b9df5ad1SAndroid Build Coastguard Worker camera_metadata_buffer_entry_t *entry = get_entries(dst) + index;
865*b9df5ad1SAndroid Build Coastguard Worker
866*b9df5ad1SAndroid Build Coastguard Worker size_t data_bytes =
867*b9df5ad1SAndroid Build Coastguard Worker calculate_camera_metadata_entry_data_size(entry->type,
868*b9df5ad1SAndroid Build Coastguard Worker data_count);
869*b9df5ad1SAndroid Build Coastguard Worker size_t data_payload_bytes =
870*b9df5ad1SAndroid Build Coastguard Worker data_count * camera_metadata_type_size[entry->type];
871*b9df5ad1SAndroid Build Coastguard Worker
872*b9df5ad1SAndroid Build Coastguard Worker size_t entry_bytes =
873*b9df5ad1SAndroid Build Coastguard Worker calculate_camera_metadata_entry_data_size(entry->type,
874*b9df5ad1SAndroid Build Coastguard Worker entry->count);
875*b9df5ad1SAndroid Build Coastguard Worker if (data_bytes != entry_bytes) {
876*b9df5ad1SAndroid Build Coastguard Worker // May need to shift/add to data array
877*b9df5ad1SAndroid Build Coastguard Worker if (dst->data_capacity < dst->data_count + data_bytes - entry_bytes) {
878*b9df5ad1SAndroid Build Coastguard Worker // No room
879*b9df5ad1SAndroid Build Coastguard Worker return ERROR;
880*b9df5ad1SAndroid Build Coastguard Worker }
881*b9df5ad1SAndroid Build Coastguard Worker if (entry_bytes != 0) {
882*b9df5ad1SAndroid Build Coastguard Worker // Remove old data
883*b9df5ad1SAndroid Build Coastguard Worker uint8_t *start = get_data(dst) + entry->data.offset;
884*b9df5ad1SAndroid Build Coastguard Worker uint8_t *end = start + entry_bytes;
885*b9df5ad1SAndroid Build Coastguard Worker size_t length = dst->data_count - entry->data.offset - entry_bytes;
886*b9df5ad1SAndroid Build Coastguard Worker memmove(start, end, length);
887*b9df5ad1SAndroid Build Coastguard Worker dst->data_count -= entry_bytes;
888*b9df5ad1SAndroid Build Coastguard Worker
889*b9df5ad1SAndroid Build Coastguard Worker // Update all entry indices to account for shift
890*b9df5ad1SAndroid Build Coastguard Worker camera_metadata_buffer_entry_t *e = get_entries(dst);
891*b9df5ad1SAndroid Build Coastguard Worker size_t i;
892*b9df5ad1SAndroid Build Coastguard Worker for (i = 0; i < dst->entry_count; i++) {
893*b9df5ad1SAndroid Build Coastguard Worker if (calculate_camera_metadata_entry_data_size(
894*b9df5ad1SAndroid Build Coastguard Worker e->type, e->count) > 0 &&
895*b9df5ad1SAndroid Build Coastguard Worker e->data.offset > entry->data.offset) {
896*b9df5ad1SAndroid Build Coastguard Worker e->data.offset -= entry_bytes;
897*b9df5ad1SAndroid Build Coastguard Worker }
898*b9df5ad1SAndroid Build Coastguard Worker ++e;
899*b9df5ad1SAndroid Build Coastguard Worker }
900*b9df5ad1SAndroid Build Coastguard Worker }
901*b9df5ad1SAndroid Build Coastguard Worker
902*b9df5ad1SAndroid Build Coastguard Worker if (data_bytes != 0) {
903*b9df5ad1SAndroid Build Coastguard Worker // Append new data
904*b9df5ad1SAndroid Build Coastguard Worker entry->data.offset = dst->data_count;
905*b9df5ad1SAndroid Build Coastguard Worker
906*b9df5ad1SAndroid Build Coastguard Worker memcpy(get_data(dst) + entry->data.offset, data, data_payload_bytes);
907*b9df5ad1SAndroid Build Coastguard Worker dst->data_count += data_bytes;
908*b9df5ad1SAndroid Build Coastguard Worker }
909*b9df5ad1SAndroid Build Coastguard Worker } else if (data_bytes != 0) {
910*b9df5ad1SAndroid Build Coastguard Worker // data size unchanged, reuse same data location
911*b9df5ad1SAndroid Build Coastguard Worker memcpy(get_data(dst) + entry->data.offset, data, data_payload_bytes);
912*b9df5ad1SAndroid Build Coastguard Worker }
913*b9df5ad1SAndroid Build Coastguard Worker
914*b9df5ad1SAndroid Build Coastguard Worker if (data_bytes == 0) {
915*b9df5ad1SAndroid Build Coastguard Worker // Data fits into entry
916*b9df5ad1SAndroid Build Coastguard Worker memcpy(entry->data.value, data,
917*b9df5ad1SAndroid Build Coastguard Worker data_payload_bytes);
918*b9df5ad1SAndroid Build Coastguard Worker }
919*b9df5ad1SAndroid Build Coastguard Worker
920*b9df5ad1SAndroid Build Coastguard Worker entry->count = data_count;
921*b9df5ad1SAndroid Build Coastguard Worker
922*b9df5ad1SAndroid Build Coastguard Worker if (updated_entry != NULL) {
923*b9df5ad1SAndroid Build Coastguard Worker get_camera_metadata_entry(dst,
924*b9df5ad1SAndroid Build Coastguard Worker index,
925*b9df5ad1SAndroid Build Coastguard Worker updated_entry);
926*b9df5ad1SAndroid Build Coastguard Worker }
927*b9df5ad1SAndroid Build Coastguard Worker
928*b9df5ad1SAndroid Build Coastguard Worker assert(validate_camera_metadata_structure(dst, NULL) == OK);
929*b9df5ad1SAndroid Build Coastguard Worker return OK;
930*b9df5ad1SAndroid Build Coastguard Worker }
931*b9df5ad1SAndroid Build Coastguard Worker
932*b9df5ad1SAndroid Build Coastguard Worker static const vendor_tag_ops_t *vendor_tag_ops = NULL;
933*b9df5ad1SAndroid Build Coastguard Worker static const struct vendor_tag_cache_ops *vendor_cache_ops = NULL;
934*b9df5ad1SAndroid Build Coastguard Worker
935*b9df5ad1SAndroid Build Coastguard Worker // Declared in system/media/private/camera/include/camera_metadata_hidden.h
get_local_camera_metadata_section_name_vendor_id(uint32_t tag,metadata_vendor_id_t id)936*b9df5ad1SAndroid Build Coastguard Worker const char *get_local_camera_metadata_section_name_vendor_id(uint32_t tag,
937*b9df5ad1SAndroid Build Coastguard Worker metadata_vendor_id_t id) {
938*b9df5ad1SAndroid Build Coastguard Worker uint32_t tag_section = tag >> 16;
939*b9df5ad1SAndroid Build Coastguard Worker if (tag_section >= VENDOR_SECTION && vendor_cache_ops != NULL &&
940*b9df5ad1SAndroid Build Coastguard Worker id != CAMERA_METADATA_INVALID_VENDOR_ID) {
941*b9df5ad1SAndroid Build Coastguard Worker return vendor_cache_ops->get_section_name(tag, id);
942*b9df5ad1SAndroid Build Coastguard Worker } else if (tag_section >= VENDOR_SECTION && vendor_tag_ops != NULL) {
943*b9df5ad1SAndroid Build Coastguard Worker return vendor_tag_ops->get_section_name(
944*b9df5ad1SAndroid Build Coastguard Worker vendor_tag_ops,
945*b9df5ad1SAndroid Build Coastguard Worker tag);
946*b9df5ad1SAndroid Build Coastguard Worker }
947*b9df5ad1SAndroid Build Coastguard Worker if (tag_section >= ANDROID_SECTION_COUNT) {
948*b9df5ad1SAndroid Build Coastguard Worker return NULL;
949*b9df5ad1SAndroid Build Coastguard Worker }
950*b9df5ad1SAndroid Build Coastguard Worker return camera_metadata_section_names[tag_section];
951*b9df5ad1SAndroid Build Coastguard Worker }
952*b9df5ad1SAndroid Build Coastguard Worker
953*b9df5ad1SAndroid Build Coastguard Worker // Declared in system/media/private/camera/include/camera_metadata_hidden.h
get_local_camera_metadata_tag_name_vendor_id(uint32_t tag,metadata_vendor_id_t id)954*b9df5ad1SAndroid Build Coastguard Worker const char *get_local_camera_metadata_tag_name_vendor_id(uint32_t tag,
955*b9df5ad1SAndroid Build Coastguard Worker metadata_vendor_id_t id) {
956*b9df5ad1SAndroid Build Coastguard Worker uint32_t tag_section = tag >> 16;
957*b9df5ad1SAndroid Build Coastguard Worker if (tag_section >= VENDOR_SECTION && vendor_cache_ops != NULL &&
958*b9df5ad1SAndroid Build Coastguard Worker id != CAMERA_METADATA_INVALID_VENDOR_ID) {
959*b9df5ad1SAndroid Build Coastguard Worker return vendor_cache_ops->get_tag_name(tag, id);
960*b9df5ad1SAndroid Build Coastguard Worker } else if (tag_section >= VENDOR_SECTION && vendor_tag_ops != NULL) {
961*b9df5ad1SAndroid Build Coastguard Worker return vendor_tag_ops->get_tag_name(
962*b9df5ad1SAndroid Build Coastguard Worker vendor_tag_ops,
963*b9df5ad1SAndroid Build Coastguard Worker tag);
964*b9df5ad1SAndroid Build Coastguard Worker }
965*b9df5ad1SAndroid Build Coastguard Worker if (tag_section >= ANDROID_SECTION_COUNT ||
966*b9df5ad1SAndroid Build Coastguard Worker tag >= camera_metadata_section_bounds[tag_section][1] ) {
967*b9df5ad1SAndroid Build Coastguard Worker return NULL;
968*b9df5ad1SAndroid Build Coastguard Worker }
969*b9df5ad1SAndroid Build Coastguard Worker uint32_t tag_index = tag & 0xFFFF;
970*b9df5ad1SAndroid Build Coastguard Worker return tag_info[tag_section][tag_index].tag_name;
971*b9df5ad1SAndroid Build Coastguard Worker }
972*b9df5ad1SAndroid Build Coastguard Worker
973*b9df5ad1SAndroid Build Coastguard Worker // Declared in system/media/private/camera/include/camera_metadata_hidden.h
get_local_camera_metadata_tag_type_vendor_id(uint32_t tag,metadata_vendor_id_t id)974*b9df5ad1SAndroid Build Coastguard Worker int get_local_camera_metadata_tag_type_vendor_id(uint32_t tag,
975*b9df5ad1SAndroid Build Coastguard Worker metadata_vendor_id_t id) {
976*b9df5ad1SAndroid Build Coastguard Worker uint32_t tag_section = tag >> 16;
977*b9df5ad1SAndroid Build Coastguard Worker if (tag_section >= VENDOR_SECTION && vendor_cache_ops != NULL &&
978*b9df5ad1SAndroid Build Coastguard Worker id != CAMERA_METADATA_INVALID_VENDOR_ID) {
979*b9df5ad1SAndroid Build Coastguard Worker return vendor_cache_ops->get_tag_type(tag, id);
980*b9df5ad1SAndroid Build Coastguard Worker } else if (tag_section >= VENDOR_SECTION && vendor_tag_ops != NULL) {
981*b9df5ad1SAndroid Build Coastguard Worker return vendor_tag_ops->get_tag_type(
982*b9df5ad1SAndroid Build Coastguard Worker vendor_tag_ops,
983*b9df5ad1SAndroid Build Coastguard Worker tag);
984*b9df5ad1SAndroid Build Coastguard Worker }
985*b9df5ad1SAndroid Build Coastguard Worker if (tag_section >= ANDROID_SECTION_COUNT ||
986*b9df5ad1SAndroid Build Coastguard Worker tag >= camera_metadata_section_bounds[tag_section][1] ) {
987*b9df5ad1SAndroid Build Coastguard Worker return -1;
988*b9df5ad1SAndroid Build Coastguard Worker }
989*b9df5ad1SAndroid Build Coastguard Worker uint32_t tag_index = tag & 0xFFFF;
990*b9df5ad1SAndroid Build Coastguard Worker return tag_info[tag_section][tag_index].tag_type;
991*b9df5ad1SAndroid Build Coastguard Worker }
992*b9df5ad1SAndroid Build Coastguard Worker
get_camera_metadata_section_name(uint32_t tag)993*b9df5ad1SAndroid Build Coastguard Worker const char *get_camera_metadata_section_name(uint32_t tag) {
994*b9df5ad1SAndroid Build Coastguard Worker return get_local_camera_metadata_section_name(tag, NULL);
995*b9df5ad1SAndroid Build Coastguard Worker }
996*b9df5ad1SAndroid Build Coastguard Worker
get_camera_metadata_tag_name(uint32_t tag)997*b9df5ad1SAndroid Build Coastguard Worker const char *get_camera_metadata_tag_name(uint32_t tag) {
998*b9df5ad1SAndroid Build Coastguard Worker return get_local_camera_metadata_tag_name(tag, NULL);
999*b9df5ad1SAndroid Build Coastguard Worker }
1000*b9df5ad1SAndroid Build Coastguard Worker
get_camera_metadata_tag_type(uint32_t tag)1001*b9df5ad1SAndroid Build Coastguard Worker int get_camera_metadata_tag_type(uint32_t tag) {
1002*b9df5ad1SAndroid Build Coastguard Worker return get_local_camera_metadata_tag_type(tag, NULL);
1003*b9df5ad1SAndroid Build Coastguard Worker }
1004*b9df5ad1SAndroid Build Coastguard Worker
get_local_camera_metadata_section_name(uint32_t tag,const camera_metadata_t * meta)1005*b9df5ad1SAndroid Build Coastguard Worker const char *get_local_camera_metadata_section_name(uint32_t tag,
1006*b9df5ad1SAndroid Build Coastguard Worker const camera_metadata_t *meta) {
1007*b9df5ad1SAndroid Build Coastguard Worker metadata_vendor_id_t id = (NULL == meta) ? CAMERA_METADATA_INVALID_VENDOR_ID :
1008*b9df5ad1SAndroid Build Coastguard Worker meta->vendor_id;
1009*b9df5ad1SAndroid Build Coastguard Worker
1010*b9df5ad1SAndroid Build Coastguard Worker return get_local_camera_metadata_section_name_vendor_id(tag, id);
1011*b9df5ad1SAndroid Build Coastguard Worker }
1012*b9df5ad1SAndroid Build Coastguard Worker
get_local_camera_metadata_tag_name(uint32_t tag,const camera_metadata_t * meta)1013*b9df5ad1SAndroid Build Coastguard Worker const char *get_local_camera_metadata_tag_name(uint32_t tag,
1014*b9df5ad1SAndroid Build Coastguard Worker const camera_metadata_t *meta) {
1015*b9df5ad1SAndroid Build Coastguard Worker metadata_vendor_id_t id = (NULL == meta) ? CAMERA_METADATA_INVALID_VENDOR_ID :
1016*b9df5ad1SAndroid Build Coastguard Worker meta->vendor_id;
1017*b9df5ad1SAndroid Build Coastguard Worker
1018*b9df5ad1SAndroid Build Coastguard Worker return get_local_camera_metadata_tag_name_vendor_id(tag, id);
1019*b9df5ad1SAndroid Build Coastguard Worker }
1020*b9df5ad1SAndroid Build Coastguard Worker
get_local_camera_metadata_tag_type(uint32_t tag,const camera_metadata_t * meta)1021*b9df5ad1SAndroid Build Coastguard Worker int get_local_camera_metadata_tag_type(uint32_t tag,
1022*b9df5ad1SAndroid Build Coastguard Worker const camera_metadata_t *meta) {
1023*b9df5ad1SAndroid Build Coastguard Worker metadata_vendor_id_t id = (NULL == meta) ? CAMERA_METADATA_INVALID_VENDOR_ID :
1024*b9df5ad1SAndroid Build Coastguard Worker meta->vendor_id;
1025*b9df5ad1SAndroid Build Coastguard Worker
1026*b9df5ad1SAndroid Build Coastguard Worker return get_local_camera_metadata_tag_type_vendor_id(tag, id);
1027*b9df5ad1SAndroid Build Coastguard Worker }
1028*b9df5ad1SAndroid Build Coastguard Worker
get_camera_metadata_permission_needed(uint32_t * tag_count)1029*b9df5ad1SAndroid Build Coastguard Worker const int32_t *get_camera_metadata_permission_needed(uint32_t *tag_count) {
1030*b9df5ad1SAndroid Build Coastguard Worker if (NULL == tag_count) {
1031*b9df5ad1SAndroid Build Coastguard Worker return NULL;
1032*b9df5ad1SAndroid Build Coastguard Worker }
1033*b9df5ad1SAndroid Build Coastguard Worker
1034*b9df5ad1SAndroid Build Coastguard Worker *tag_count = sizeof(tag_permission_needed) / sizeof(tag_permission_needed[0]);
1035*b9df5ad1SAndroid Build Coastguard Worker return tag_permission_needed;
1036*b9df5ad1SAndroid Build Coastguard Worker }
1037*b9df5ad1SAndroid Build Coastguard Worker
set_camera_metadata_vendor_tag_ops(const vendor_tag_query_ops_t * ops)1038*b9df5ad1SAndroid Build Coastguard Worker int set_camera_metadata_vendor_tag_ops(const vendor_tag_query_ops_t* ops) {
1039*b9df5ad1SAndroid Build Coastguard Worker // **DEPRECATED**
1040*b9df5ad1SAndroid Build Coastguard Worker (void) ops;
1041*b9df5ad1SAndroid Build Coastguard Worker ALOGE("%s: This function has been deprecated", __FUNCTION__);
1042*b9df5ad1SAndroid Build Coastguard Worker return ERROR;
1043*b9df5ad1SAndroid Build Coastguard Worker }
1044*b9df5ad1SAndroid Build Coastguard Worker
1045*b9df5ad1SAndroid Build Coastguard Worker // Declared in system/media/private/camera/include/camera_metadata_hidden.h
set_camera_metadata_vendor_ops(const vendor_tag_ops_t * ops)1046*b9df5ad1SAndroid Build Coastguard Worker int set_camera_metadata_vendor_ops(const vendor_tag_ops_t* ops) {
1047*b9df5ad1SAndroid Build Coastguard Worker vendor_tag_ops = ops;
1048*b9df5ad1SAndroid Build Coastguard Worker return OK;
1049*b9df5ad1SAndroid Build Coastguard Worker }
1050*b9df5ad1SAndroid Build Coastguard Worker
1051*b9df5ad1SAndroid Build Coastguard Worker // Declared in system/media/private/camera/include/camera_metadata_hidden.h
set_camera_metadata_vendor_cache_ops(const struct vendor_tag_cache_ops * query_cache_ops)1052*b9df5ad1SAndroid Build Coastguard Worker int set_camera_metadata_vendor_cache_ops(
1053*b9df5ad1SAndroid Build Coastguard Worker const struct vendor_tag_cache_ops *query_cache_ops) {
1054*b9df5ad1SAndroid Build Coastguard Worker vendor_cache_ops = query_cache_ops;
1055*b9df5ad1SAndroid Build Coastguard Worker return OK;
1056*b9df5ad1SAndroid Build Coastguard Worker }
1057*b9df5ad1SAndroid Build Coastguard Worker
1058*b9df5ad1SAndroid Build Coastguard Worker // Declared in system/media/private/camera/include/camera_metadata_hidden.h
set_camera_metadata_vendor_id(camera_metadata_t * meta,metadata_vendor_id_t id)1059*b9df5ad1SAndroid Build Coastguard Worker void set_camera_metadata_vendor_id(camera_metadata_t *meta,
1060*b9df5ad1SAndroid Build Coastguard Worker metadata_vendor_id_t id) {
1061*b9df5ad1SAndroid Build Coastguard Worker if (NULL != meta) {
1062*b9df5ad1SAndroid Build Coastguard Worker meta->vendor_id = id;
1063*b9df5ad1SAndroid Build Coastguard Worker }
1064*b9df5ad1SAndroid Build Coastguard Worker }
1065*b9df5ad1SAndroid Build Coastguard Worker
1066*b9df5ad1SAndroid Build Coastguard Worker // Declared in system/media/private/camera/include/camera_metadata_hidden.h
get_camera_metadata_vendor_id(const camera_metadata_t * meta)1067*b9df5ad1SAndroid Build Coastguard Worker metadata_vendor_id_t get_camera_metadata_vendor_id(
1068*b9df5ad1SAndroid Build Coastguard Worker const camera_metadata_t *meta) {
1069*b9df5ad1SAndroid Build Coastguard Worker metadata_vendor_id_t ret = CAMERA_METADATA_INVALID_VENDOR_ID;
1070*b9df5ad1SAndroid Build Coastguard Worker
1071*b9df5ad1SAndroid Build Coastguard Worker if (NULL != meta) {
1072*b9df5ad1SAndroid Build Coastguard Worker ret = meta->vendor_id;
1073*b9df5ad1SAndroid Build Coastguard Worker }
1074*b9df5ad1SAndroid Build Coastguard Worker
1075*b9df5ad1SAndroid Build Coastguard Worker return ret;
1076*b9df5ad1SAndroid Build Coastguard Worker }
1077*b9df5ad1SAndroid Build Coastguard Worker
1078*b9df5ad1SAndroid Build Coastguard Worker static void print_data(int fd, const uint8_t *data_ptr, uint32_t tag, int type,
1079*b9df5ad1SAndroid Build Coastguard Worker metadata_vendor_id_t vendor_id, int count, int indentation);
1080*b9df5ad1SAndroid Build Coastguard Worker
dump_camera_metadata(const camera_metadata_t * metadata,int fd,int verbosity)1081*b9df5ad1SAndroid Build Coastguard Worker void dump_camera_metadata(const camera_metadata_t *metadata,
1082*b9df5ad1SAndroid Build Coastguard Worker int fd,
1083*b9df5ad1SAndroid Build Coastguard Worker int verbosity) {
1084*b9df5ad1SAndroid Build Coastguard Worker dump_indented_camera_metadata(metadata, fd, verbosity, 0);
1085*b9df5ad1SAndroid Build Coastguard Worker }
1086*b9df5ad1SAndroid Build Coastguard Worker
dump_indented_camera_metadata(const camera_metadata_t * metadata,int fd,int verbosity,int indentation)1087*b9df5ad1SAndroid Build Coastguard Worker void dump_indented_camera_metadata(const camera_metadata_t *metadata,
1088*b9df5ad1SAndroid Build Coastguard Worker int fd,
1089*b9df5ad1SAndroid Build Coastguard Worker int verbosity,
1090*b9df5ad1SAndroid Build Coastguard Worker int indentation) {
1091*b9df5ad1SAndroid Build Coastguard Worker if (metadata == NULL) {
1092*b9df5ad1SAndroid Build Coastguard Worker dprintf(fd, "%*sDumping camera metadata array: Not allocated\n",
1093*b9df5ad1SAndroid Build Coastguard Worker indentation, "");
1094*b9df5ad1SAndroid Build Coastguard Worker return;
1095*b9df5ad1SAndroid Build Coastguard Worker }
1096*b9df5ad1SAndroid Build Coastguard Worker unsigned int i;
1097*b9df5ad1SAndroid Build Coastguard Worker dprintf(fd,
1098*b9df5ad1SAndroid Build Coastguard Worker "%*sDumping camera metadata array: %" PRIu32 " / %" PRIu32 " entries, "
1099*b9df5ad1SAndroid Build Coastguard Worker "%" PRIu32 " / %" PRIu32 " bytes of extra data.\n", indentation, "",
1100*b9df5ad1SAndroid Build Coastguard Worker metadata->entry_count, metadata->entry_capacity,
1101*b9df5ad1SAndroid Build Coastguard Worker metadata->data_count, metadata->data_capacity);
1102*b9df5ad1SAndroid Build Coastguard Worker dprintf(fd, "%*sVersion: %d, Flags: %08x\n",
1103*b9df5ad1SAndroid Build Coastguard Worker indentation + 2, "",
1104*b9df5ad1SAndroid Build Coastguard Worker metadata->version, metadata->flags);
1105*b9df5ad1SAndroid Build Coastguard Worker camera_metadata_buffer_entry_t *entry = get_entries(metadata);
1106*b9df5ad1SAndroid Build Coastguard Worker for (i=0; i < metadata->entry_count; i++, entry++) {
1107*b9df5ad1SAndroid Build Coastguard Worker
1108*b9df5ad1SAndroid Build Coastguard Worker const char *tag_name, *tag_section;
1109*b9df5ad1SAndroid Build Coastguard Worker tag_section = get_local_camera_metadata_section_name(entry->tag, metadata);
1110*b9df5ad1SAndroid Build Coastguard Worker if (tag_section == NULL) {
1111*b9df5ad1SAndroid Build Coastguard Worker tag_section = "unknownSection";
1112*b9df5ad1SAndroid Build Coastguard Worker }
1113*b9df5ad1SAndroid Build Coastguard Worker tag_name = get_local_camera_metadata_tag_name(entry->tag, metadata);
1114*b9df5ad1SAndroid Build Coastguard Worker if (tag_name == NULL) {
1115*b9df5ad1SAndroid Build Coastguard Worker tag_name = "unknownTag";
1116*b9df5ad1SAndroid Build Coastguard Worker }
1117*b9df5ad1SAndroid Build Coastguard Worker const char *type_name;
1118*b9df5ad1SAndroid Build Coastguard Worker if (entry->type >= NUM_TYPES) {
1119*b9df5ad1SAndroid Build Coastguard Worker type_name = "unknown";
1120*b9df5ad1SAndroid Build Coastguard Worker } else {
1121*b9df5ad1SAndroid Build Coastguard Worker type_name = camera_metadata_type_names[entry->type];
1122*b9df5ad1SAndroid Build Coastguard Worker }
1123*b9df5ad1SAndroid Build Coastguard Worker dprintf(fd, "%*s%s.%s (%05x): %s[%" PRIu32 "]\n",
1124*b9df5ad1SAndroid Build Coastguard Worker indentation + 2, "",
1125*b9df5ad1SAndroid Build Coastguard Worker tag_section,
1126*b9df5ad1SAndroid Build Coastguard Worker tag_name,
1127*b9df5ad1SAndroid Build Coastguard Worker entry->tag,
1128*b9df5ad1SAndroid Build Coastguard Worker type_name,
1129*b9df5ad1SAndroid Build Coastguard Worker entry->count);
1130*b9df5ad1SAndroid Build Coastguard Worker
1131*b9df5ad1SAndroid Build Coastguard Worker if (verbosity < 1) continue;
1132*b9df5ad1SAndroid Build Coastguard Worker
1133*b9df5ad1SAndroid Build Coastguard Worker if (entry->type >= NUM_TYPES) continue;
1134*b9df5ad1SAndroid Build Coastguard Worker
1135*b9df5ad1SAndroid Build Coastguard Worker size_t type_size = camera_metadata_type_size[entry->type];
1136*b9df5ad1SAndroid Build Coastguard Worker uint8_t *data_ptr;
1137*b9df5ad1SAndroid Build Coastguard Worker if ( type_size * entry->count > 4 ) {
1138*b9df5ad1SAndroid Build Coastguard Worker if (entry->data.offset >= metadata->data_count) {
1139*b9df5ad1SAndroid Build Coastguard Worker ALOGE("%s: Malformed entry data offset: %" PRIu32 " (max %" PRIu32 ")",
1140*b9df5ad1SAndroid Build Coastguard Worker __FUNCTION__,
1141*b9df5ad1SAndroid Build Coastguard Worker entry->data.offset,
1142*b9df5ad1SAndroid Build Coastguard Worker metadata->data_count);
1143*b9df5ad1SAndroid Build Coastguard Worker continue;
1144*b9df5ad1SAndroid Build Coastguard Worker }
1145*b9df5ad1SAndroid Build Coastguard Worker data_ptr = get_data(metadata) + entry->data.offset;
1146*b9df5ad1SAndroid Build Coastguard Worker } else {
1147*b9df5ad1SAndroid Build Coastguard Worker data_ptr = entry->data.value;
1148*b9df5ad1SAndroid Build Coastguard Worker }
1149*b9df5ad1SAndroid Build Coastguard Worker int count = entry->count;
1150*b9df5ad1SAndroid Build Coastguard Worker if (verbosity < 2 && count > 16) count = 16;
1151*b9df5ad1SAndroid Build Coastguard Worker
1152*b9df5ad1SAndroid Build Coastguard Worker print_data(fd, data_ptr, entry->tag, entry->type, get_camera_metadata_vendor_id(metadata),
1153*b9df5ad1SAndroid Build Coastguard Worker count, indentation);
1154*b9df5ad1SAndroid Build Coastguard Worker }
1155*b9df5ad1SAndroid Build Coastguard Worker }
1156*b9df5ad1SAndroid Build Coastguard Worker
print_data(int fd,const uint8_t * data_ptr,uint32_t tag,int type,metadata_vendor_id_t vendor_id,int count,int indentation)1157*b9df5ad1SAndroid Build Coastguard Worker static void print_data(int fd, const uint8_t *data_ptr, uint32_t tag, int type,
1158*b9df5ad1SAndroid Build Coastguard Worker metadata_vendor_id_t vendor_id, int count, int indentation) {
1159*b9df5ad1SAndroid Build Coastguard Worker static int values_per_line[NUM_TYPES] = {
1160*b9df5ad1SAndroid Build Coastguard Worker [TYPE_BYTE] = 16,
1161*b9df5ad1SAndroid Build Coastguard Worker [TYPE_INT32] = 4,
1162*b9df5ad1SAndroid Build Coastguard Worker [TYPE_FLOAT] = 8,
1163*b9df5ad1SAndroid Build Coastguard Worker [TYPE_INT64] = 2,
1164*b9df5ad1SAndroid Build Coastguard Worker [TYPE_DOUBLE] = 4,
1165*b9df5ad1SAndroid Build Coastguard Worker [TYPE_RATIONAL] = 2,
1166*b9df5ad1SAndroid Build Coastguard Worker };
1167*b9df5ad1SAndroid Build Coastguard Worker size_t type_size = camera_metadata_type_size[type];
1168*b9df5ad1SAndroid Build Coastguard Worker char value_string_tmp[CAMERA_METADATA_ENUM_STRING_MAX_SIZE];
1169*b9df5ad1SAndroid Build Coastguard Worker uint32_t value;
1170*b9df5ad1SAndroid Build Coastguard Worker size_t value_offset;
1171*b9df5ad1SAndroid Build Coastguard Worker size_t entry_size;
1172*b9df5ad1SAndroid Build Coastguard Worker // It is possible that the tag value is only found at specific
1173*b9df5ad1SAndroid Build Coastguard Worker // offset. The rest of the data must not be enumerated.
1174*b9df5ad1SAndroid Build Coastguard Worker switch (tag) {
1175*b9df5ad1SAndroid Build Coastguard Worker case ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS:
1176*b9df5ad1SAndroid Build Coastguard Worker case ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION:
1177*b9df5ad1SAndroid Build Coastguard Worker case ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS:
1178*b9df5ad1SAndroid Build Coastguard Worker case ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION:
1179*b9df5ad1SAndroid Build Coastguard Worker case ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS:
1180*b9df5ad1SAndroid Build Coastguard Worker case ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION:
1181*b9df5ad1SAndroid Build Coastguard Worker case ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS:
1182*b9df5ad1SAndroid Build Coastguard Worker case ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION:
1183*b9df5ad1SAndroid Build Coastguard Worker case ANDROID_JPEGR_AVAILABLE_JPEG_R_STREAM_CONFIGURATIONS:
1184*b9df5ad1SAndroid Build Coastguard Worker case ANDROID_JPEGR_AVAILABLE_JPEG_R_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION:
1185*b9df5ad1SAndroid Build Coastguard Worker case ANDROID_SCALER_PHYSICAL_CAMERA_MULTI_RESOLUTION_STREAM_CONFIGURATIONS:
1186*b9df5ad1SAndroid Build Coastguard Worker value_offset = 3 * type_size;
1187*b9df5ad1SAndroid Build Coastguard Worker entry_size = 4 * type_size;
1188*b9df5ad1SAndroid Build Coastguard Worker break;
1189*b9df5ad1SAndroid Build Coastguard Worker default:
1190*b9df5ad1SAndroid Build Coastguard Worker value_offset = 0;
1191*b9df5ad1SAndroid Build Coastguard Worker entry_size = 0;
1192*b9df5ad1SAndroid Build Coastguard Worker }
1193*b9df5ad1SAndroid Build Coastguard Worker
1194*b9df5ad1SAndroid Build Coastguard Worker int lines = count / values_per_line[type];
1195*b9df5ad1SAndroid Build Coastguard Worker if (count % values_per_line[type] != 0) lines++;
1196*b9df5ad1SAndroid Build Coastguard Worker
1197*b9df5ad1SAndroid Build Coastguard Worker int index = 0;
1198*b9df5ad1SAndroid Build Coastguard Worker int j, k;
1199*b9df5ad1SAndroid Build Coastguard Worker for (j = 0; j < lines; j++) {
1200*b9df5ad1SAndroid Build Coastguard Worker dprintf(fd, "%*s[", indentation + 4, "");
1201*b9df5ad1SAndroid Build Coastguard Worker for (k = 0;
1202*b9df5ad1SAndroid Build Coastguard Worker k < values_per_line[type] && count > 0;
1203*b9df5ad1SAndroid Build Coastguard Worker k++, count--, index += type_size) {
1204*b9df5ad1SAndroid Build Coastguard Worker
1205*b9df5ad1SAndroid Build Coastguard Worker switch (type) {
1206*b9df5ad1SAndroid Build Coastguard Worker case TYPE_BYTE:
1207*b9df5ad1SAndroid Build Coastguard Worker value = *(data_ptr + index);
1208*b9df5ad1SAndroid Build Coastguard Worker if (camera_metadata_enum_snprint(tag,
1209*b9df5ad1SAndroid Build Coastguard Worker value,
1210*b9df5ad1SAndroid Build Coastguard Worker value_string_tmp,
1211*b9df5ad1SAndroid Build Coastguard Worker sizeof(value_string_tmp))
1212*b9df5ad1SAndroid Build Coastguard Worker == OK) {
1213*b9df5ad1SAndroid Build Coastguard Worker dprintf(fd, "%s ", value_string_tmp);
1214*b9df5ad1SAndroid Build Coastguard Worker } else if (tag == ANDROID_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS) {
1215*b9df5ad1SAndroid Build Coastguard Worker if (value != 0) {
1216*b9df5ad1SAndroid Build Coastguard Worker dprintf(fd, "%c ",
1217*b9df5ad1SAndroid Build Coastguard Worker *(data_ptr + index));
1218*b9df5ad1SAndroid Build Coastguard Worker }
1219*b9df5ad1SAndroid Build Coastguard Worker } else {
1220*b9df5ad1SAndroid Build Coastguard Worker dprintf(fd, "%hhu ",
1221*b9df5ad1SAndroid Build Coastguard Worker *(data_ptr + index));
1222*b9df5ad1SAndroid Build Coastguard Worker }
1223*b9df5ad1SAndroid Build Coastguard Worker break;
1224*b9df5ad1SAndroid Build Coastguard Worker case TYPE_INT32:
1225*b9df5ad1SAndroid Build Coastguard Worker value = *(int32_t*)(data_ptr + index);
1226*b9df5ad1SAndroid Build Coastguard Worker
1227*b9df5ad1SAndroid Build Coastguard Worker if ((entry_size > 0) && ((index % entry_size ) != value_offset)) {
1228*b9df5ad1SAndroid Build Coastguard Worker dprintf(fd, "%" PRId32 " ", value);
1229*b9df5ad1SAndroid Build Coastguard Worker break;
1230*b9df5ad1SAndroid Build Coastguard Worker }
1231*b9df5ad1SAndroid Build Coastguard Worker
1232*b9df5ad1SAndroid Build Coastguard Worker if (camera_metadata_enum_snprint(tag,
1233*b9df5ad1SAndroid Build Coastguard Worker value,
1234*b9df5ad1SAndroid Build Coastguard Worker value_string_tmp,
1235*b9df5ad1SAndroid Build Coastguard Worker sizeof(value_string_tmp))
1236*b9df5ad1SAndroid Build Coastguard Worker == OK) {
1237*b9df5ad1SAndroid Build Coastguard Worker dprintf(fd, "%s ", value_string_tmp);
1238*b9df5ad1SAndroid Build Coastguard Worker } else {
1239*b9df5ad1SAndroid Build Coastguard Worker dprintf(fd, "%" PRId32 " ", value);
1240*b9df5ad1SAndroid Build Coastguard Worker if (tag == ANDROID_REQUEST_AVAILABLE_REQUEST_KEYS ||
1241*b9df5ad1SAndroid Build Coastguard Worker tag == ANDROID_REQUEST_AVAILABLE_RESULT_KEYS ||
1242*b9df5ad1SAndroid Build Coastguard Worker tag == ANDROID_REQUEST_AVAILABLE_SESSION_KEYS ||
1243*b9df5ad1SAndroid Build Coastguard Worker tag == ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS ||
1244*b9df5ad1SAndroid Build Coastguard Worker tag == ANDROID_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS) {
1245*b9df5ad1SAndroid Build Coastguard Worker const char *camera_metadata_tag_name =
1246*b9df5ad1SAndroid Build Coastguard Worker get_camera_metadata_tag_name(value);
1247*b9df5ad1SAndroid Build Coastguard Worker if (camera_metadata_tag_name != NULL) {
1248*b9df5ad1SAndroid Build Coastguard Worker dprintf(fd, "(%s) ", camera_metadata_tag_name);
1249*b9df5ad1SAndroid Build Coastguard Worker } else {
1250*b9df5ad1SAndroid Build Coastguard Worker const char *camera_metadata_tag_vendor_id =
1251*b9df5ad1SAndroid Build Coastguard Worker get_local_camera_metadata_tag_name_vendor_id(value, vendor_id);
1252*b9df5ad1SAndroid Build Coastguard Worker if (camera_metadata_tag_vendor_id != NULL) {
1253*b9df5ad1SAndroid Build Coastguard Worker dprintf(fd, "(%s) ", camera_metadata_tag_vendor_id);
1254*b9df5ad1SAndroid Build Coastguard Worker }
1255*b9df5ad1SAndroid Build Coastguard Worker }
1256*b9df5ad1SAndroid Build Coastguard Worker }
1257*b9df5ad1SAndroid Build Coastguard Worker }
1258*b9df5ad1SAndroid Build Coastguard Worker break;
1259*b9df5ad1SAndroid Build Coastguard Worker case TYPE_FLOAT:
1260*b9df5ad1SAndroid Build Coastguard Worker dprintf(fd, "%0.8f ",
1261*b9df5ad1SAndroid Build Coastguard Worker *(float*)(data_ptr + index));
1262*b9df5ad1SAndroid Build Coastguard Worker break;
1263*b9df5ad1SAndroid Build Coastguard Worker case TYPE_INT64:
1264*b9df5ad1SAndroid Build Coastguard Worker dprintf(fd, "%" PRId64 " ",
1265*b9df5ad1SAndroid Build Coastguard Worker *(int64_t*)(data_ptr + index));
1266*b9df5ad1SAndroid Build Coastguard Worker break;
1267*b9df5ad1SAndroid Build Coastguard Worker case TYPE_DOUBLE:
1268*b9df5ad1SAndroid Build Coastguard Worker dprintf(fd, "%0.8f ",
1269*b9df5ad1SAndroid Build Coastguard Worker *(double*)(data_ptr + index));
1270*b9df5ad1SAndroid Build Coastguard Worker break;
1271*b9df5ad1SAndroid Build Coastguard Worker case TYPE_RATIONAL: {
1272*b9df5ad1SAndroid Build Coastguard Worker int32_t numerator = *(int32_t*)(data_ptr + index);
1273*b9df5ad1SAndroid Build Coastguard Worker int32_t denominator = *(int32_t*)(data_ptr + index + 4);
1274*b9df5ad1SAndroid Build Coastguard Worker dprintf(fd, "(%d / %d) ",
1275*b9df5ad1SAndroid Build Coastguard Worker numerator, denominator);
1276*b9df5ad1SAndroid Build Coastguard Worker break;
1277*b9df5ad1SAndroid Build Coastguard Worker }
1278*b9df5ad1SAndroid Build Coastguard Worker default:
1279*b9df5ad1SAndroid Build Coastguard Worker dprintf(fd, "??? ");
1280*b9df5ad1SAndroid Build Coastguard Worker }
1281*b9df5ad1SAndroid Build Coastguard Worker }
1282*b9df5ad1SAndroid Build Coastguard Worker dprintf(fd, "]\n");
1283*b9df5ad1SAndroid Build Coastguard Worker }
1284*b9df5ad1SAndroid Build Coastguard Worker }
1285