xref: /aosp_15_r20/frameworks/av/camera/CameraMetadata.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
1*ec779b8eSAndroid Build Coastguard Worker /*
2*ec779b8eSAndroid Build Coastguard Worker  * Copyright (C) 2012 The Android Open Source Project
3*ec779b8eSAndroid Build Coastguard Worker  *
4*ec779b8eSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*ec779b8eSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*ec779b8eSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*ec779b8eSAndroid Build Coastguard Worker  *
8*ec779b8eSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*ec779b8eSAndroid Build Coastguard Worker  *
10*ec779b8eSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*ec779b8eSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*ec779b8eSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*ec779b8eSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*ec779b8eSAndroid Build Coastguard Worker  * limitations under the License.
15*ec779b8eSAndroid Build Coastguard Worker  */
16*ec779b8eSAndroid Build Coastguard Worker 
17*ec779b8eSAndroid Build Coastguard Worker // #define LOG_NDEBUG 0
18*ec779b8eSAndroid Build Coastguard Worker 
19*ec779b8eSAndroid Build Coastguard Worker #define LOG_TAG "Camera2-Metadata"
20*ec779b8eSAndroid Build Coastguard Worker #include <utils/Log.h>
21*ec779b8eSAndroid Build Coastguard Worker #include <utils/Errors.h>
22*ec779b8eSAndroid Build Coastguard Worker 
23*ec779b8eSAndroid Build Coastguard Worker #include <binder/Parcel.h>
24*ec779b8eSAndroid Build Coastguard Worker #include <camera/CameraMetadata.h>
25*ec779b8eSAndroid Build Coastguard Worker #include <camera_metadata_hidden.h>
26*ec779b8eSAndroid Build Coastguard Worker 
27*ec779b8eSAndroid Build Coastguard Worker namespace android {
28*ec779b8eSAndroid Build Coastguard Worker 
29*ec779b8eSAndroid Build Coastguard Worker #define ALIGN_TO(val, alignment) \
30*ec779b8eSAndroid Build Coastguard Worker     (((uintptr_t)(val) + ((alignment) - 1)) & ~((alignment) - 1))
31*ec779b8eSAndroid Build Coastguard Worker 
32*ec779b8eSAndroid Build Coastguard Worker typedef Parcel::WritableBlob WritableBlob;
33*ec779b8eSAndroid Build Coastguard Worker typedef Parcel::ReadableBlob ReadableBlob;
34*ec779b8eSAndroid Build Coastguard Worker 
CameraMetadata()35*ec779b8eSAndroid Build Coastguard Worker CameraMetadata::CameraMetadata() :
36*ec779b8eSAndroid Build Coastguard Worker         mBuffer(NULL), mLocked(false) {
37*ec779b8eSAndroid Build Coastguard Worker }
38*ec779b8eSAndroid Build Coastguard Worker 
CameraMetadata(size_t entryCapacity,size_t dataCapacity)39*ec779b8eSAndroid Build Coastguard Worker CameraMetadata::CameraMetadata(size_t entryCapacity, size_t dataCapacity) :
40*ec779b8eSAndroid Build Coastguard Worker         mLocked(false)
41*ec779b8eSAndroid Build Coastguard Worker {
42*ec779b8eSAndroid Build Coastguard Worker     mBuffer = allocate_camera_metadata(entryCapacity, dataCapacity);
43*ec779b8eSAndroid Build Coastguard Worker }
44*ec779b8eSAndroid Build Coastguard Worker 
CameraMetadata(const CameraMetadata & other)45*ec779b8eSAndroid Build Coastguard Worker CameraMetadata::CameraMetadata(const CameraMetadata &other) :
46*ec779b8eSAndroid Build Coastguard Worker         mLocked(false) {
47*ec779b8eSAndroid Build Coastguard Worker     mBuffer = clone_camera_metadata(other.mBuffer);
48*ec779b8eSAndroid Build Coastguard Worker }
49*ec779b8eSAndroid Build Coastguard Worker 
CameraMetadata(CameraMetadata && other)50*ec779b8eSAndroid Build Coastguard Worker CameraMetadata::CameraMetadata(CameraMetadata &&other) :mBuffer(NULL),  mLocked(false) {
51*ec779b8eSAndroid Build Coastguard Worker     acquire(other);
52*ec779b8eSAndroid Build Coastguard Worker }
53*ec779b8eSAndroid Build Coastguard Worker 
operator =(CameraMetadata && other)54*ec779b8eSAndroid Build Coastguard Worker CameraMetadata &CameraMetadata::operator=(CameraMetadata &&other) {
55*ec779b8eSAndroid Build Coastguard Worker     acquire(other);
56*ec779b8eSAndroid Build Coastguard Worker     return *this;
57*ec779b8eSAndroid Build Coastguard Worker }
58*ec779b8eSAndroid Build Coastguard Worker 
CameraMetadata(camera_metadata_t * buffer)59*ec779b8eSAndroid Build Coastguard Worker CameraMetadata::CameraMetadata(camera_metadata_t *buffer) :
60*ec779b8eSAndroid Build Coastguard Worker         mBuffer(NULL), mLocked(false) {
61*ec779b8eSAndroid Build Coastguard Worker     acquire(buffer);
62*ec779b8eSAndroid Build Coastguard Worker }
63*ec779b8eSAndroid Build Coastguard Worker 
operator =(const CameraMetadata & other)64*ec779b8eSAndroid Build Coastguard Worker CameraMetadata &CameraMetadata::operator=(const CameraMetadata &other) {
65*ec779b8eSAndroid Build Coastguard Worker     return operator=(other.mBuffer);
66*ec779b8eSAndroid Build Coastguard Worker }
67*ec779b8eSAndroid Build Coastguard Worker 
operator =(const camera_metadata_t * buffer)68*ec779b8eSAndroid Build Coastguard Worker CameraMetadata &CameraMetadata::operator=(const camera_metadata_t *buffer) {
69*ec779b8eSAndroid Build Coastguard Worker     if (mLocked) {
70*ec779b8eSAndroid Build Coastguard Worker         ALOGE("%s: Assignment to a locked CameraMetadata!", __FUNCTION__);
71*ec779b8eSAndroid Build Coastguard Worker         return *this;
72*ec779b8eSAndroid Build Coastguard Worker     }
73*ec779b8eSAndroid Build Coastguard Worker 
74*ec779b8eSAndroid Build Coastguard Worker     if (CC_LIKELY(buffer != mBuffer)) {
75*ec779b8eSAndroid Build Coastguard Worker         camera_metadata_t *newBuffer = clone_camera_metadata(buffer);
76*ec779b8eSAndroid Build Coastguard Worker         clear();
77*ec779b8eSAndroid Build Coastguard Worker         mBuffer = newBuffer;
78*ec779b8eSAndroid Build Coastguard Worker     }
79*ec779b8eSAndroid Build Coastguard Worker     return *this;
80*ec779b8eSAndroid Build Coastguard Worker }
81*ec779b8eSAndroid Build Coastguard Worker 
~CameraMetadata()82*ec779b8eSAndroid Build Coastguard Worker CameraMetadata::~CameraMetadata() {
83*ec779b8eSAndroid Build Coastguard Worker     mLocked = false;
84*ec779b8eSAndroid Build Coastguard Worker     clear();
85*ec779b8eSAndroid Build Coastguard Worker }
86*ec779b8eSAndroid Build Coastguard Worker 
getAndLock() const87*ec779b8eSAndroid Build Coastguard Worker const camera_metadata_t* CameraMetadata::getAndLock() const {
88*ec779b8eSAndroid Build Coastguard Worker     mLocked = true;
89*ec779b8eSAndroid Build Coastguard Worker     return mBuffer;
90*ec779b8eSAndroid Build Coastguard Worker }
91*ec779b8eSAndroid Build Coastguard Worker 
unlock(const camera_metadata_t * buffer) const92*ec779b8eSAndroid Build Coastguard Worker status_t CameraMetadata::unlock(const camera_metadata_t *buffer) const {
93*ec779b8eSAndroid Build Coastguard Worker     if (!mLocked) {
94*ec779b8eSAndroid Build Coastguard Worker         ALOGE("%s: Can't unlock a non-locked CameraMetadata!", __FUNCTION__);
95*ec779b8eSAndroid Build Coastguard Worker         return INVALID_OPERATION;
96*ec779b8eSAndroid Build Coastguard Worker     }
97*ec779b8eSAndroid Build Coastguard Worker     if (buffer != mBuffer) {
98*ec779b8eSAndroid Build Coastguard Worker         ALOGE("%s: Can't unlock CameraMetadata with wrong pointer!",
99*ec779b8eSAndroid Build Coastguard Worker                 __FUNCTION__);
100*ec779b8eSAndroid Build Coastguard Worker         return BAD_VALUE;
101*ec779b8eSAndroid Build Coastguard Worker     }
102*ec779b8eSAndroid Build Coastguard Worker     mLocked = false;
103*ec779b8eSAndroid Build Coastguard Worker     return OK;
104*ec779b8eSAndroid Build Coastguard Worker }
105*ec779b8eSAndroid Build Coastguard Worker 
release()106*ec779b8eSAndroid Build Coastguard Worker camera_metadata_t* CameraMetadata::release() {
107*ec779b8eSAndroid Build Coastguard Worker     if (mLocked) {
108*ec779b8eSAndroid Build Coastguard Worker         ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
109*ec779b8eSAndroid Build Coastguard Worker         return NULL;
110*ec779b8eSAndroid Build Coastguard Worker     }
111*ec779b8eSAndroid Build Coastguard Worker     camera_metadata_t *released = mBuffer;
112*ec779b8eSAndroid Build Coastguard Worker     mBuffer = NULL;
113*ec779b8eSAndroid Build Coastguard Worker     return released;
114*ec779b8eSAndroid Build Coastguard Worker }
115*ec779b8eSAndroid Build Coastguard Worker 
clear()116*ec779b8eSAndroid Build Coastguard Worker void CameraMetadata::clear() {
117*ec779b8eSAndroid Build Coastguard Worker     if (mLocked) {
118*ec779b8eSAndroid Build Coastguard Worker         ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
119*ec779b8eSAndroid Build Coastguard Worker         return;
120*ec779b8eSAndroid Build Coastguard Worker     }
121*ec779b8eSAndroid Build Coastguard Worker     if (mBuffer) {
122*ec779b8eSAndroid Build Coastguard Worker         free_camera_metadata(mBuffer);
123*ec779b8eSAndroid Build Coastguard Worker         mBuffer = NULL;
124*ec779b8eSAndroid Build Coastguard Worker     }
125*ec779b8eSAndroid Build Coastguard Worker }
126*ec779b8eSAndroid Build Coastguard Worker 
acquire(camera_metadata_t * buffer)127*ec779b8eSAndroid Build Coastguard Worker void CameraMetadata::acquire(camera_metadata_t *buffer) {
128*ec779b8eSAndroid Build Coastguard Worker     if (mLocked) {
129*ec779b8eSAndroid Build Coastguard Worker         ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
130*ec779b8eSAndroid Build Coastguard Worker         return;
131*ec779b8eSAndroid Build Coastguard Worker     }
132*ec779b8eSAndroid Build Coastguard Worker     clear();
133*ec779b8eSAndroid Build Coastguard Worker     mBuffer = buffer;
134*ec779b8eSAndroid Build Coastguard Worker 
135*ec779b8eSAndroid Build Coastguard Worker     ALOGE_IF(validate_camera_metadata_structure(mBuffer, /*size*/NULL) != OK,
136*ec779b8eSAndroid Build Coastguard Worker              "%s: Failed to validate metadata structure %p",
137*ec779b8eSAndroid Build Coastguard Worker              __FUNCTION__, buffer);
138*ec779b8eSAndroid Build Coastguard Worker }
139*ec779b8eSAndroid Build Coastguard Worker 
acquire(CameraMetadata & other)140*ec779b8eSAndroid Build Coastguard Worker void CameraMetadata::acquire(CameraMetadata &other) {
141*ec779b8eSAndroid Build Coastguard Worker     if (mLocked) {
142*ec779b8eSAndroid Build Coastguard Worker         ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
143*ec779b8eSAndroid Build Coastguard Worker         return;
144*ec779b8eSAndroid Build Coastguard Worker     }
145*ec779b8eSAndroid Build Coastguard Worker     acquire(other.release());
146*ec779b8eSAndroid Build Coastguard Worker }
147*ec779b8eSAndroid Build Coastguard Worker 
append(const CameraMetadata & other)148*ec779b8eSAndroid Build Coastguard Worker status_t CameraMetadata::append(const CameraMetadata &other) {
149*ec779b8eSAndroid Build Coastguard Worker     return append(other.mBuffer);
150*ec779b8eSAndroid Build Coastguard Worker }
151*ec779b8eSAndroid Build Coastguard Worker 
append(const camera_metadata_t * other)152*ec779b8eSAndroid Build Coastguard Worker status_t CameraMetadata::append(const camera_metadata_t* other) {
153*ec779b8eSAndroid Build Coastguard Worker     if (mLocked) {
154*ec779b8eSAndroid Build Coastguard Worker         ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
155*ec779b8eSAndroid Build Coastguard Worker         return INVALID_OPERATION;
156*ec779b8eSAndroid Build Coastguard Worker     }
157*ec779b8eSAndroid Build Coastguard Worker     size_t extraEntries = get_camera_metadata_entry_count(other);
158*ec779b8eSAndroid Build Coastguard Worker     size_t extraData = get_camera_metadata_data_count(other);
159*ec779b8eSAndroid Build Coastguard Worker     resizeIfNeeded(extraEntries, extraData);
160*ec779b8eSAndroid Build Coastguard Worker 
161*ec779b8eSAndroid Build Coastguard Worker     return append_camera_metadata(mBuffer, other);
162*ec779b8eSAndroid Build Coastguard Worker }
163*ec779b8eSAndroid Build Coastguard Worker 
entryCount() const164*ec779b8eSAndroid Build Coastguard Worker size_t CameraMetadata::entryCount() const {
165*ec779b8eSAndroid Build Coastguard Worker     return (mBuffer == NULL) ? 0 :
166*ec779b8eSAndroid Build Coastguard Worker             get_camera_metadata_entry_count(mBuffer);
167*ec779b8eSAndroid Build Coastguard Worker }
168*ec779b8eSAndroid Build Coastguard Worker 
isEmpty() const169*ec779b8eSAndroid Build Coastguard Worker bool CameraMetadata::isEmpty() const {
170*ec779b8eSAndroid Build Coastguard Worker     return entryCount() == 0;
171*ec779b8eSAndroid Build Coastguard Worker }
172*ec779b8eSAndroid Build Coastguard Worker 
bufferSize() const173*ec779b8eSAndroid Build Coastguard Worker size_t CameraMetadata::bufferSize() const {
174*ec779b8eSAndroid Build Coastguard Worker     return (mBuffer == NULL) ? 0 :
175*ec779b8eSAndroid Build Coastguard Worker             get_camera_metadata_size(mBuffer);
176*ec779b8eSAndroid Build Coastguard Worker }
177*ec779b8eSAndroid Build Coastguard Worker 
sort()178*ec779b8eSAndroid Build Coastguard Worker status_t CameraMetadata::sort() {
179*ec779b8eSAndroid Build Coastguard Worker     if (mLocked) {
180*ec779b8eSAndroid Build Coastguard Worker         ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
181*ec779b8eSAndroid Build Coastguard Worker         return INVALID_OPERATION;
182*ec779b8eSAndroid Build Coastguard Worker     }
183*ec779b8eSAndroid Build Coastguard Worker     return sort_camera_metadata(mBuffer);
184*ec779b8eSAndroid Build Coastguard Worker }
185*ec779b8eSAndroid Build Coastguard Worker 
checkType(uint32_t tag,uint8_t expectedType)186*ec779b8eSAndroid Build Coastguard Worker status_t CameraMetadata::checkType(uint32_t tag, uint8_t expectedType) {
187*ec779b8eSAndroid Build Coastguard Worker     int tagType = get_local_camera_metadata_tag_type(tag, mBuffer);
188*ec779b8eSAndroid Build Coastguard Worker     if ( CC_UNLIKELY(tagType == -1)) {
189*ec779b8eSAndroid Build Coastguard Worker         ALOGE("Update metadata entry: Unknown tag %d", tag);
190*ec779b8eSAndroid Build Coastguard Worker         return INVALID_OPERATION;
191*ec779b8eSAndroid Build Coastguard Worker     }
192*ec779b8eSAndroid Build Coastguard Worker     if ( CC_UNLIKELY(tagType != expectedType) ) {
193*ec779b8eSAndroid Build Coastguard Worker         ALOGE("Mismatched tag type when updating entry %s (%d) of type %s; "
194*ec779b8eSAndroid Build Coastguard Worker                 "got type %s data instead ",
195*ec779b8eSAndroid Build Coastguard Worker                 get_local_camera_metadata_tag_name(tag, mBuffer), tag,
196*ec779b8eSAndroid Build Coastguard Worker                 camera_metadata_type_names[tagType],
197*ec779b8eSAndroid Build Coastguard Worker                 camera_metadata_type_names[expectedType]);
198*ec779b8eSAndroid Build Coastguard Worker         return INVALID_OPERATION;
199*ec779b8eSAndroid Build Coastguard Worker     }
200*ec779b8eSAndroid Build Coastguard Worker     return OK;
201*ec779b8eSAndroid Build Coastguard Worker }
202*ec779b8eSAndroid Build Coastguard Worker 
update(uint32_t tag,const int32_t * data,size_t data_count)203*ec779b8eSAndroid Build Coastguard Worker status_t CameraMetadata::update(uint32_t tag,
204*ec779b8eSAndroid Build Coastguard Worker         const int32_t *data, size_t data_count) {
205*ec779b8eSAndroid Build Coastguard Worker     status_t res;
206*ec779b8eSAndroid Build Coastguard Worker     if (mLocked) {
207*ec779b8eSAndroid Build Coastguard Worker         ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
208*ec779b8eSAndroid Build Coastguard Worker         return INVALID_OPERATION;
209*ec779b8eSAndroid Build Coastguard Worker     }
210*ec779b8eSAndroid Build Coastguard Worker     if ( (res = checkType(tag, TYPE_INT32)) != OK) {
211*ec779b8eSAndroid Build Coastguard Worker         return res;
212*ec779b8eSAndroid Build Coastguard Worker     }
213*ec779b8eSAndroid Build Coastguard Worker     return updateImpl(tag, (const void*)data, data_count);
214*ec779b8eSAndroid Build Coastguard Worker }
215*ec779b8eSAndroid Build Coastguard Worker 
update(uint32_t tag,const uint8_t * data,size_t data_count)216*ec779b8eSAndroid Build Coastguard Worker status_t CameraMetadata::update(uint32_t tag,
217*ec779b8eSAndroid Build Coastguard Worker         const uint8_t *data, size_t data_count) {
218*ec779b8eSAndroid Build Coastguard Worker     status_t res;
219*ec779b8eSAndroid Build Coastguard Worker     if (mLocked) {
220*ec779b8eSAndroid Build Coastguard Worker         ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
221*ec779b8eSAndroid Build Coastguard Worker         return INVALID_OPERATION;
222*ec779b8eSAndroid Build Coastguard Worker     }
223*ec779b8eSAndroid Build Coastguard Worker     if ( (res = checkType(tag, TYPE_BYTE)) != OK) {
224*ec779b8eSAndroid Build Coastguard Worker         return res;
225*ec779b8eSAndroid Build Coastguard Worker     }
226*ec779b8eSAndroid Build Coastguard Worker     return updateImpl(tag, (const void*)data, data_count);
227*ec779b8eSAndroid Build Coastguard Worker }
228*ec779b8eSAndroid Build Coastguard Worker 
update(uint32_t tag,const float * data,size_t data_count)229*ec779b8eSAndroid Build Coastguard Worker status_t CameraMetadata::update(uint32_t tag,
230*ec779b8eSAndroid Build Coastguard Worker         const float *data, size_t data_count) {
231*ec779b8eSAndroid Build Coastguard Worker     status_t res;
232*ec779b8eSAndroid Build Coastguard Worker     if (mLocked) {
233*ec779b8eSAndroid Build Coastguard Worker         ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
234*ec779b8eSAndroid Build Coastguard Worker         return INVALID_OPERATION;
235*ec779b8eSAndroid Build Coastguard Worker     }
236*ec779b8eSAndroid Build Coastguard Worker     if ( (res = checkType(tag, TYPE_FLOAT)) != OK) {
237*ec779b8eSAndroid Build Coastguard Worker         return res;
238*ec779b8eSAndroid Build Coastguard Worker     }
239*ec779b8eSAndroid Build Coastguard Worker     return updateImpl(tag, (const void*)data, data_count);
240*ec779b8eSAndroid Build Coastguard Worker }
241*ec779b8eSAndroid Build Coastguard Worker 
update(uint32_t tag,const int64_t * data,size_t data_count)242*ec779b8eSAndroid Build Coastguard Worker status_t CameraMetadata::update(uint32_t tag,
243*ec779b8eSAndroid Build Coastguard Worker         const int64_t *data, size_t data_count) {
244*ec779b8eSAndroid Build Coastguard Worker     status_t res;
245*ec779b8eSAndroid Build Coastguard Worker     if (mLocked) {
246*ec779b8eSAndroid Build Coastguard Worker         ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
247*ec779b8eSAndroid Build Coastguard Worker         return INVALID_OPERATION;
248*ec779b8eSAndroid Build Coastguard Worker     }
249*ec779b8eSAndroid Build Coastguard Worker     if ( (res = checkType(tag, TYPE_INT64)) != OK) {
250*ec779b8eSAndroid Build Coastguard Worker         return res;
251*ec779b8eSAndroid Build Coastguard Worker     }
252*ec779b8eSAndroid Build Coastguard Worker     return updateImpl(tag, (const void*)data, data_count);
253*ec779b8eSAndroid Build Coastguard Worker }
254*ec779b8eSAndroid Build Coastguard Worker 
update(uint32_t tag,const double * data,size_t data_count)255*ec779b8eSAndroid Build Coastguard Worker status_t CameraMetadata::update(uint32_t tag,
256*ec779b8eSAndroid Build Coastguard Worker         const double *data, size_t data_count) {
257*ec779b8eSAndroid Build Coastguard Worker     status_t res;
258*ec779b8eSAndroid Build Coastguard Worker     if (mLocked) {
259*ec779b8eSAndroid Build Coastguard Worker         ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
260*ec779b8eSAndroid Build Coastguard Worker         return INVALID_OPERATION;
261*ec779b8eSAndroid Build Coastguard Worker     }
262*ec779b8eSAndroid Build Coastguard Worker     if ( (res = checkType(tag, TYPE_DOUBLE)) != OK) {
263*ec779b8eSAndroid Build Coastguard Worker         return res;
264*ec779b8eSAndroid Build Coastguard Worker     }
265*ec779b8eSAndroid Build Coastguard Worker     return updateImpl(tag, (const void*)data, data_count);
266*ec779b8eSAndroid Build Coastguard Worker }
267*ec779b8eSAndroid Build Coastguard Worker 
update(uint32_t tag,const camera_metadata_rational_t * data,size_t data_count)268*ec779b8eSAndroid Build Coastguard Worker status_t CameraMetadata::update(uint32_t tag,
269*ec779b8eSAndroid Build Coastguard Worker         const camera_metadata_rational_t *data, size_t data_count) {
270*ec779b8eSAndroid Build Coastguard Worker     status_t res;
271*ec779b8eSAndroid Build Coastguard Worker     if (mLocked) {
272*ec779b8eSAndroid Build Coastguard Worker         ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
273*ec779b8eSAndroid Build Coastguard Worker         return INVALID_OPERATION;
274*ec779b8eSAndroid Build Coastguard Worker     }
275*ec779b8eSAndroid Build Coastguard Worker     if ( (res = checkType(tag, TYPE_RATIONAL)) != OK) {
276*ec779b8eSAndroid Build Coastguard Worker         return res;
277*ec779b8eSAndroid Build Coastguard Worker     }
278*ec779b8eSAndroid Build Coastguard Worker     return updateImpl(tag, (const void*)data, data_count);
279*ec779b8eSAndroid Build Coastguard Worker }
280*ec779b8eSAndroid Build Coastguard Worker 
update(uint32_t tag,const String8 & string)281*ec779b8eSAndroid Build Coastguard Worker status_t CameraMetadata::update(uint32_t tag,
282*ec779b8eSAndroid Build Coastguard Worker         const String8 &string) {
283*ec779b8eSAndroid Build Coastguard Worker     status_t res;
284*ec779b8eSAndroid Build Coastguard Worker     if (mLocked) {
285*ec779b8eSAndroid Build Coastguard Worker         ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
286*ec779b8eSAndroid Build Coastguard Worker         return INVALID_OPERATION;
287*ec779b8eSAndroid Build Coastguard Worker     }
288*ec779b8eSAndroid Build Coastguard Worker     if ( (res = checkType(tag, TYPE_BYTE)) != OK) {
289*ec779b8eSAndroid Build Coastguard Worker         return res;
290*ec779b8eSAndroid Build Coastguard Worker     }
291*ec779b8eSAndroid Build Coastguard Worker     // string.size() doesn't count the null termination character.
292*ec779b8eSAndroid Build Coastguard Worker     return updateImpl(tag, (const void*)string.c_str(), string.size() + 1);
293*ec779b8eSAndroid Build Coastguard Worker }
294*ec779b8eSAndroid Build Coastguard Worker 
update(const camera_metadata_ro_entry & entry)295*ec779b8eSAndroid Build Coastguard Worker status_t CameraMetadata::update(const camera_metadata_ro_entry &entry) {
296*ec779b8eSAndroid Build Coastguard Worker     status_t res;
297*ec779b8eSAndroid Build Coastguard Worker     if (mLocked) {
298*ec779b8eSAndroid Build Coastguard Worker         ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
299*ec779b8eSAndroid Build Coastguard Worker         return INVALID_OPERATION;
300*ec779b8eSAndroid Build Coastguard Worker     }
301*ec779b8eSAndroid Build Coastguard Worker     if ( (res = checkType(entry.tag, entry.type)) != OK) {
302*ec779b8eSAndroid Build Coastguard Worker         return res;
303*ec779b8eSAndroid Build Coastguard Worker     }
304*ec779b8eSAndroid Build Coastguard Worker     return updateImpl(entry.tag, (const void*)entry.data.u8, entry.count);
305*ec779b8eSAndroid Build Coastguard Worker }
306*ec779b8eSAndroid Build Coastguard Worker 
updateImpl(uint32_t tag,const void * data,size_t data_count)307*ec779b8eSAndroid Build Coastguard Worker status_t CameraMetadata::updateImpl(uint32_t tag, const void *data,
308*ec779b8eSAndroid Build Coastguard Worker         size_t data_count) {
309*ec779b8eSAndroid Build Coastguard Worker     status_t res;
310*ec779b8eSAndroid Build Coastguard Worker     if (mLocked) {
311*ec779b8eSAndroid Build Coastguard Worker         ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
312*ec779b8eSAndroid Build Coastguard Worker         return INVALID_OPERATION;
313*ec779b8eSAndroid Build Coastguard Worker     }
314*ec779b8eSAndroid Build Coastguard Worker     int type = get_local_camera_metadata_tag_type(tag, mBuffer);
315*ec779b8eSAndroid Build Coastguard Worker     if (type == -1) {
316*ec779b8eSAndroid Build Coastguard Worker         ALOGE("%s: Tag %d not found", __FUNCTION__, tag);
317*ec779b8eSAndroid Build Coastguard Worker         return BAD_VALUE;
318*ec779b8eSAndroid Build Coastguard Worker     }
319*ec779b8eSAndroid Build Coastguard Worker     // Safety check - ensure that data isn't pointing to this metadata, since
320*ec779b8eSAndroid Build Coastguard Worker     // that would get invalidated if a resize is needed
321*ec779b8eSAndroid Build Coastguard Worker     size_t bufferSize = get_camera_metadata_size(mBuffer);
322*ec779b8eSAndroid Build Coastguard Worker     uintptr_t bufAddr = reinterpret_cast<uintptr_t>(mBuffer);
323*ec779b8eSAndroid Build Coastguard Worker     uintptr_t dataAddr = reinterpret_cast<uintptr_t>(data);
324*ec779b8eSAndroid Build Coastguard Worker     if (dataAddr > bufAddr && dataAddr < (bufAddr + bufferSize)) {
325*ec779b8eSAndroid Build Coastguard Worker         ALOGE("%s: Update attempted with data from the same metadata buffer!",
326*ec779b8eSAndroid Build Coastguard Worker                 __FUNCTION__);
327*ec779b8eSAndroid Build Coastguard Worker         return INVALID_OPERATION;
328*ec779b8eSAndroid Build Coastguard Worker     }
329*ec779b8eSAndroid Build Coastguard Worker 
330*ec779b8eSAndroid Build Coastguard Worker     size_t data_size = calculate_camera_metadata_entry_data_size(type,
331*ec779b8eSAndroid Build Coastguard Worker             data_count);
332*ec779b8eSAndroid Build Coastguard Worker 
333*ec779b8eSAndroid Build Coastguard Worker     res = resizeIfNeeded(1, data_size);
334*ec779b8eSAndroid Build Coastguard Worker 
335*ec779b8eSAndroid Build Coastguard Worker     if (res == OK) {
336*ec779b8eSAndroid Build Coastguard Worker         camera_metadata_entry_t entry;
337*ec779b8eSAndroid Build Coastguard Worker         res = find_camera_metadata_entry(mBuffer, tag, &entry);
338*ec779b8eSAndroid Build Coastguard Worker         if (res == NAME_NOT_FOUND) {
339*ec779b8eSAndroid Build Coastguard Worker             res = add_camera_metadata_entry(mBuffer,
340*ec779b8eSAndroid Build Coastguard Worker                     tag, data, data_count);
341*ec779b8eSAndroid Build Coastguard Worker         } else if (res == OK) {
342*ec779b8eSAndroid Build Coastguard Worker             res = update_camera_metadata_entry(mBuffer,
343*ec779b8eSAndroid Build Coastguard Worker                     entry.index, data, data_count, NULL);
344*ec779b8eSAndroid Build Coastguard Worker         }
345*ec779b8eSAndroid Build Coastguard Worker     }
346*ec779b8eSAndroid Build Coastguard Worker 
347*ec779b8eSAndroid Build Coastguard Worker     if (res != OK) {
348*ec779b8eSAndroid Build Coastguard Worker         ALOGE("%s: Unable to update metadata entry %s.%s (%x): %s (%d)",
349*ec779b8eSAndroid Build Coastguard Worker                 __FUNCTION__, get_local_camera_metadata_section_name(tag, mBuffer),
350*ec779b8eSAndroid Build Coastguard Worker                 get_local_camera_metadata_tag_name(tag, mBuffer), tag,
351*ec779b8eSAndroid Build Coastguard Worker                 strerror(-res), res);
352*ec779b8eSAndroid Build Coastguard Worker     }
353*ec779b8eSAndroid Build Coastguard Worker 
354*ec779b8eSAndroid Build Coastguard Worker     IF_ALOGV() {
355*ec779b8eSAndroid Build Coastguard Worker         ALOGE_IF(validate_camera_metadata_structure(mBuffer, /*size*/NULL) !=
356*ec779b8eSAndroid Build Coastguard Worker                  OK,
357*ec779b8eSAndroid Build Coastguard Worker 
358*ec779b8eSAndroid Build Coastguard Worker                  "%s: Failed to validate metadata structure after update %p",
359*ec779b8eSAndroid Build Coastguard Worker                  __FUNCTION__, mBuffer);
360*ec779b8eSAndroid Build Coastguard Worker     }
361*ec779b8eSAndroid Build Coastguard Worker 
362*ec779b8eSAndroid Build Coastguard Worker     return res;
363*ec779b8eSAndroid Build Coastguard Worker }
364*ec779b8eSAndroid Build Coastguard Worker 
exists(uint32_t tag) const365*ec779b8eSAndroid Build Coastguard Worker bool CameraMetadata::exists(uint32_t tag) const {
366*ec779b8eSAndroid Build Coastguard Worker     camera_metadata_ro_entry entry;
367*ec779b8eSAndroid Build Coastguard Worker     return find_camera_metadata_ro_entry(mBuffer, tag, &entry) == 0;
368*ec779b8eSAndroid Build Coastguard Worker }
369*ec779b8eSAndroid Build Coastguard Worker 
find(uint32_t tag)370*ec779b8eSAndroid Build Coastguard Worker camera_metadata_entry_t CameraMetadata::find(uint32_t tag) {
371*ec779b8eSAndroid Build Coastguard Worker     status_t res;
372*ec779b8eSAndroid Build Coastguard Worker     camera_metadata_entry entry;
373*ec779b8eSAndroid Build Coastguard Worker     if (mLocked) {
374*ec779b8eSAndroid Build Coastguard Worker         ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
375*ec779b8eSAndroid Build Coastguard Worker         entry.count = 0;
376*ec779b8eSAndroid Build Coastguard Worker         return entry;
377*ec779b8eSAndroid Build Coastguard Worker     }
378*ec779b8eSAndroid Build Coastguard Worker     res = find_camera_metadata_entry(mBuffer, tag, &entry);
379*ec779b8eSAndroid Build Coastguard Worker     if (CC_UNLIKELY( res != OK )) {
380*ec779b8eSAndroid Build Coastguard Worker         entry.count = 0;
381*ec779b8eSAndroid Build Coastguard Worker         entry.data.u8 = NULL;
382*ec779b8eSAndroid Build Coastguard Worker     }
383*ec779b8eSAndroid Build Coastguard Worker     return entry;
384*ec779b8eSAndroid Build Coastguard Worker }
385*ec779b8eSAndroid Build Coastguard Worker 
find(uint32_t tag) const386*ec779b8eSAndroid Build Coastguard Worker camera_metadata_ro_entry_t CameraMetadata::find(uint32_t tag) const {
387*ec779b8eSAndroid Build Coastguard Worker     status_t res;
388*ec779b8eSAndroid Build Coastguard Worker     camera_metadata_ro_entry entry;
389*ec779b8eSAndroid Build Coastguard Worker     res = find_camera_metadata_ro_entry(mBuffer, tag, &entry);
390*ec779b8eSAndroid Build Coastguard Worker     if (CC_UNLIKELY( res != OK )) {
391*ec779b8eSAndroid Build Coastguard Worker         entry.count = 0;
392*ec779b8eSAndroid Build Coastguard Worker         entry.data.u8 = NULL;
393*ec779b8eSAndroid Build Coastguard Worker     }
394*ec779b8eSAndroid Build Coastguard Worker     return entry;
395*ec779b8eSAndroid Build Coastguard Worker }
396*ec779b8eSAndroid Build Coastguard Worker 
erase(uint32_t tag)397*ec779b8eSAndroid Build Coastguard Worker status_t CameraMetadata::erase(uint32_t tag) {
398*ec779b8eSAndroid Build Coastguard Worker     camera_metadata_entry_t entry;
399*ec779b8eSAndroid Build Coastguard Worker     status_t res;
400*ec779b8eSAndroid Build Coastguard Worker     if (mLocked) {
401*ec779b8eSAndroid Build Coastguard Worker         ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
402*ec779b8eSAndroid Build Coastguard Worker         return INVALID_OPERATION;
403*ec779b8eSAndroid Build Coastguard Worker     }
404*ec779b8eSAndroid Build Coastguard Worker     res = find_camera_metadata_entry(mBuffer, tag, &entry);
405*ec779b8eSAndroid Build Coastguard Worker     if (res == NAME_NOT_FOUND) {
406*ec779b8eSAndroid Build Coastguard Worker         return OK;
407*ec779b8eSAndroid Build Coastguard Worker     } else if (res != OK) {
408*ec779b8eSAndroid Build Coastguard Worker         ALOGE("%s: Error looking for entry %s.%s (%x): %s %d",
409*ec779b8eSAndroid Build Coastguard Worker                 __FUNCTION__,
410*ec779b8eSAndroid Build Coastguard Worker                 get_local_camera_metadata_section_name(tag, mBuffer),
411*ec779b8eSAndroid Build Coastguard Worker                 get_local_camera_metadata_tag_name(tag, mBuffer),
412*ec779b8eSAndroid Build Coastguard Worker                 tag, strerror(-res), res);
413*ec779b8eSAndroid Build Coastguard Worker         return res;
414*ec779b8eSAndroid Build Coastguard Worker     }
415*ec779b8eSAndroid Build Coastguard Worker     res = delete_camera_metadata_entry(mBuffer, entry.index);
416*ec779b8eSAndroid Build Coastguard Worker     if (res != OK) {
417*ec779b8eSAndroid Build Coastguard Worker         ALOGE("%s: Error deleting entry %s.%s (%x): %s %d",
418*ec779b8eSAndroid Build Coastguard Worker                 __FUNCTION__,
419*ec779b8eSAndroid Build Coastguard Worker                 get_local_camera_metadata_section_name(tag, mBuffer),
420*ec779b8eSAndroid Build Coastguard Worker                 get_local_camera_metadata_tag_name(tag, mBuffer),
421*ec779b8eSAndroid Build Coastguard Worker                 tag, strerror(-res), res);
422*ec779b8eSAndroid Build Coastguard Worker     }
423*ec779b8eSAndroid Build Coastguard Worker     return res;
424*ec779b8eSAndroid Build Coastguard Worker }
425*ec779b8eSAndroid Build Coastguard Worker 
removePermissionEntries(metadata_vendor_id_t vendorId,std::vector<int32_t> * tagsRemoved)426*ec779b8eSAndroid Build Coastguard Worker status_t CameraMetadata::removePermissionEntries(metadata_vendor_id_t vendorId,
427*ec779b8eSAndroid Build Coastguard Worker         std::vector<int32_t> *tagsRemoved) {
428*ec779b8eSAndroid Build Coastguard Worker     uint32_t tagCount = 0;
429*ec779b8eSAndroid Build Coastguard Worker     std::vector<uint32_t> tagsToRemove;
430*ec779b8eSAndroid Build Coastguard Worker 
431*ec779b8eSAndroid Build Coastguard Worker     if (tagsRemoved == nullptr) {
432*ec779b8eSAndroid Build Coastguard Worker         return BAD_VALUE;
433*ec779b8eSAndroid Build Coastguard Worker     }
434*ec779b8eSAndroid Build Coastguard Worker 
435*ec779b8eSAndroid Build Coastguard Worker     sp<VendorTagDescriptor> vTags = VendorTagDescriptor::getGlobalVendorTagDescriptor();
436*ec779b8eSAndroid Build Coastguard Worker     if ((nullptr == vTags.get()) || (0 >= vTags->getTagCount())) {
437*ec779b8eSAndroid Build Coastguard Worker         sp<VendorTagDescriptorCache> cache =
438*ec779b8eSAndroid Build Coastguard Worker             VendorTagDescriptorCache::getGlobalVendorTagCache();
439*ec779b8eSAndroid Build Coastguard Worker         if (cache.get()) {
440*ec779b8eSAndroid Build Coastguard Worker             cache->getVendorTagDescriptor(vendorId, &vTags);
441*ec779b8eSAndroid Build Coastguard Worker         }
442*ec779b8eSAndroid Build Coastguard Worker     }
443*ec779b8eSAndroid Build Coastguard Worker 
444*ec779b8eSAndroid Build Coastguard Worker     if ((nullptr != vTags.get()) && (vTags->getTagCount() > 0)) {
445*ec779b8eSAndroid Build Coastguard Worker         tagCount = vTags->getTagCount();
446*ec779b8eSAndroid Build Coastguard Worker         uint32_t *vendorTags = new uint32_t[tagCount];
447*ec779b8eSAndroid Build Coastguard Worker         if (nullptr == vendorTags) {
448*ec779b8eSAndroid Build Coastguard Worker             return NO_MEMORY;
449*ec779b8eSAndroid Build Coastguard Worker         }
450*ec779b8eSAndroid Build Coastguard Worker         vTags->getTagArray(vendorTags);
451*ec779b8eSAndroid Build Coastguard Worker 
452*ec779b8eSAndroid Build Coastguard Worker         tagsToRemove.reserve(tagCount);
453*ec779b8eSAndroid Build Coastguard Worker         tagsToRemove.insert(tagsToRemove.begin(), vendorTags, vendorTags + tagCount);
454*ec779b8eSAndroid Build Coastguard Worker 
455*ec779b8eSAndroid Build Coastguard Worker         delete [] vendorTags;
456*ec779b8eSAndroid Build Coastguard Worker         tagCount = 0;
457*ec779b8eSAndroid Build Coastguard Worker     }
458*ec779b8eSAndroid Build Coastguard Worker 
459*ec779b8eSAndroid Build Coastguard Worker     auto tagsNeedingPermission = get_camera_metadata_permission_needed(&tagCount);
460*ec779b8eSAndroid Build Coastguard Worker     if (tagCount > 0) {
461*ec779b8eSAndroid Build Coastguard Worker         tagsToRemove.reserve(tagsToRemove.capacity() + tagCount);
462*ec779b8eSAndroid Build Coastguard Worker         tagsToRemove.insert(tagsToRemove.end(), tagsNeedingPermission,
463*ec779b8eSAndroid Build Coastguard Worker                 tagsNeedingPermission + tagCount);
464*ec779b8eSAndroid Build Coastguard Worker     }
465*ec779b8eSAndroid Build Coastguard Worker 
466*ec779b8eSAndroid Build Coastguard Worker     tagsRemoved->reserve(tagsToRemove.size());
467*ec779b8eSAndroid Build Coastguard Worker     for (const auto &it : tagsToRemove) {
468*ec779b8eSAndroid Build Coastguard Worker         if (exists(it)) {
469*ec779b8eSAndroid Build Coastguard Worker             auto rc = erase(it);
470*ec779b8eSAndroid Build Coastguard Worker             if (NO_ERROR != rc) {
471*ec779b8eSAndroid Build Coastguard Worker                 ALOGE("%s: Failed to erase tag: %x", __func__, it);
472*ec779b8eSAndroid Build Coastguard Worker                 return rc;
473*ec779b8eSAndroid Build Coastguard Worker             }
474*ec779b8eSAndroid Build Coastguard Worker             tagsRemoved->push_back(it);
475*ec779b8eSAndroid Build Coastguard Worker         }
476*ec779b8eSAndroid Build Coastguard Worker     }
477*ec779b8eSAndroid Build Coastguard Worker 
478*ec779b8eSAndroid Build Coastguard Worker     // Update the available characterstics accordingly
479*ec779b8eSAndroid Build Coastguard Worker     if (exists(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS)) {
480*ec779b8eSAndroid Build Coastguard Worker         std::vector<uint32_t> currentKeys;
481*ec779b8eSAndroid Build Coastguard Worker 
482*ec779b8eSAndroid Build Coastguard Worker         std::sort(tagsRemoved->begin(), tagsRemoved->end());
483*ec779b8eSAndroid Build Coastguard Worker         auto keys = find(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS);
484*ec779b8eSAndroid Build Coastguard Worker         currentKeys.reserve(keys.count);
485*ec779b8eSAndroid Build Coastguard Worker         currentKeys.insert(currentKeys.end(), keys.data.i32, keys.data.i32 + keys.count);
486*ec779b8eSAndroid Build Coastguard Worker         std::sort(currentKeys.begin(), currentKeys.end());
487*ec779b8eSAndroid Build Coastguard Worker 
488*ec779b8eSAndroid Build Coastguard Worker         std::vector<int32_t> newKeys(keys.count);
489*ec779b8eSAndroid Build Coastguard Worker         auto end = std::set_difference(currentKeys.begin(), currentKeys.end(), tagsRemoved->begin(),
490*ec779b8eSAndroid Build Coastguard Worker                 tagsRemoved->end(), newKeys.begin());
491*ec779b8eSAndroid Build Coastguard Worker         newKeys.resize(end - newKeys.begin());
492*ec779b8eSAndroid Build Coastguard Worker 
493*ec779b8eSAndroid Build Coastguard Worker         update(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS, newKeys.data(), newKeys.size());
494*ec779b8eSAndroid Build Coastguard Worker     }
495*ec779b8eSAndroid Build Coastguard Worker 
496*ec779b8eSAndroid Build Coastguard Worker     return NO_ERROR;
497*ec779b8eSAndroid Build Coastguard Worker }
498*ec779b8eSAndroid Build Coastguard Worker 
dump(int fd,int verbosity,int indentation) const499*ec779b8eSAndroid Build Coastguard Worker void CameraMetadata::dump(int fd, int verbosity, int indentation) const {
500*ec779b8eSAndroid Build Coastguard Worker     dump_indented_camera_metadata(mBuffer, fd, verbosity, indentation);
501*ec779b8eSAndroid Build Coastguard Worker }
502*ec779b8eSAndroid Build Coastguard Worker 
resizeIfNeeded(size_t extraEntries,size_t extraData)503*ec779b8eSAndroid Build Coastguard Worker status_t CameraMetadata::resizeIfNeeded(size_t extraEntries, size_t extraData) {
504*ec779b8eSAndroid Build Coastguard Worker     if (mBuffer == NULL) {
505*ec779b8eSAndroid Build Coastguard Worker         mBuffer = allocate_camera_metadata(extraEntries * 2, extraData * 2);
506*ec779b8eSAndroid Build Coastguard Worker         if (mBuffer == NULL) {
507*ec779b8eSAndroid Build Coastguard Worker             ALOGE("%s: Can't allocate larger metadata buffer", __FUNCTION__);
508*ec779b8eSAndroid Build Coastguard Worker             return NO_MEMORY;
509*ec779b8eSAndroid Build Coastguard Worker         }
510*ec779b8eSAndroid Build Coastguard Worker     } else {
511*ec779b8eSAndroid Build Coastguard Worker         size_t currentEntryCount = get_camera_metadata_entry_count(mBuffer);
512*ec779b8eSAndroid Build Coastguard Worker         size_t currentEntryCap = get_camera_metadata_entry_capacity(mBuffer);
513*ec779b8eSAndroid Build Coastguard Worker         size_t newEntryCount = currentEntryCount +
514*ec779b8eSAndroid Build Coastguard Worker                 extraEntries;
515*ec779b8eSAndroid Build Coastguard Worker         newEntryCount = (newEntryCount > currentEntryCap) ?
516*ec779b8eSAndroid Build Coastguard Worker                 newEntryCount * 2 : currentEntryCap;
517*ec779b8eSAndroid Build Coastguard Worker 
518*ec779b8eSAndroid Build Coastguard Worker         size_t currentDataCount = get_camera_metadata_data_count(mBuffer);
519*ec779b8eSAndroid Build Coastguard Worker         size_t currentDataCap = get_camera_metadata_data_capacity(mBuffer);
520*ec779b8eSAndroid Build Coastguard Worker         size_t newDataCount = currentDataCount +
521*ec779b8eSAndroid Build Coastguard Worker                 extraData;
522*ec779b8eSAndroid Build Coastguard Worker         newDataCount = (newDataCount > currentDataCap) ?
523*ec779b8eSAndroid Build Coastguard Worker                 newDataCount * 2 : currentDataCap;
524*ec779b8eSAndroid Build Coastguard Worker 
525*ec779b8eSAndroid Build Coastguard Worker         if (newEntryCount > currentEntryCap ||
526*ec779b8eSAndroid Build Coastguard Worker                 newDataCount > currentDataCap) {
527*ec779b8eSAndroid Build Coastguard Worker             camera_metadata_t *oldBuffer = mBuffer;
528*ec779b8eSAndroid Build Coastguard Worker             mBuffer = allocate_camera_metadata(newEntryCount,
529*ec779b8eSAndroid Build Coastguard Worker                     newDataCount);
530*ec779b8eSAndroid Build Coastguard Worker             if (mBuffer == NULL) {
531*ec779b8eSAndroid Build Coastguard Worker                 // Maintain old buffer to avoid potential memory leak.
532*ec779b8eSAndroid Build Coastguard Worker                 mBuffer = oldBuffer;
533*ec779b8eSAndroid Build Coastguard Worker                 ALOGE("%s: Can't allocate larger metadata buffer", __FUNCTION__);
534*ec779b8eSAndroid Build Coastguard Worker                 return NO_MEMORY;
535*ec779b8eSAndroid Build Coastguard Worker             }
536*ec779b8eSAndroid Build Coastguard Worker             append_camera_metadata(mBuffer, oldBuffer);
537*ec779b8eSAndroid Build Coastguard Worker             free_camera_metadata(oldBuffer);
538*ec779b8eSAndroid Build Coastguard Worker         }
539*ec779b8eSAndroid Build Coastguard Worker     }
540*ec779b8eSAndroid Build Coastguard Worker     return OK;
541*ec779b8eSAndroid Build Coastguard Worker }
542*ec779b8eSAndroid Build Coastguard Worker 
readFromParcel(const Parcel & data,camera_metadata_t ** out)543*ec779b8eSAndroid Build Coastguard Worker status_t CameraMetadata::readFromParcel(const Parcel& data,
544*ec779b8eSAndroid Build Coastguard Worker                                         camera_metadata_t** out) {
545*ec779b8eSAndroid Build Coastguard Worker 
546*ec779b8eSAndroid Build Coastguard Worker     status_t err = OK;
547*ec779b8eSAndroid Build Coastguard Worker 
548*ec779b8eSAndroid Build Coastguard Worker     camera_metadata_t* metadata = NULL;
549*ec779b8eSAndroid Build Coastguard Worker 
550*ec779b8eSAndroid Build Coastguard Worker     if (out) {
551*ec779b8eSAndroid Build Coastguard Worker         *out = NULL;
552*ec779b8eSAndroid Build Coastguard Worker     }
553*ec779b8eSAndroid Build Coastguard Worker 
554*ec779b8eSAndroid Build Coastguard Worker     // See CameraMetadata::writeToParcel for parcel data layout diagram and explanation.
555*ec779b8eSAndroid Build Coastguard Worker     // arg0 = blobSize (int32)
556*ec779b8eSAndroid Build Coastguard Worker     int32_t blobSizeTmp = -1;
557*ec779b8eSAndroid Build Coastguard Worker     if ((err = data.readInt32(&blobSizeTmp)) != OK) {
558*ec779b8eSAndroid Build Coastguard Worker         ALOGE("%s: Failed to read metadata size (error %d %s)",
559*ec779b8eSAndroid Build Coastguard Worker               __FUNCTION__, err, strerror(-err));
560*ec779b8eSAndroid Build Coastguard Worker         return err;
561*ec779b8eSAndroid Build Coastguard Worker     }
562*ec779b8eSAndroid Build Coastguard Worker     const size_t blobSize = static_cast<size_t>(blobSizeTmp);
563*ec779b8eSAndroid Build Coastguard Worker     const size_t alignment = get_camera_metadata_alignment();
564*ec779b8eSAndroid Build Coastguard Worker 
565*ec779b8eSAndroid Build Coastguard Worker     // Special case: zero blob size means zero sized (NULL) metadata.
566*ec779b8eSAndroid Build Coastguard Worker     if (blobSize == 0) {
567*ec779b8eSAndroid Build Coastguard Worker         ALOGV("%s: Read 0-sized metadata", __FUNCTION__);
568*ec779b8eSAndroid Build Coastguard Worker         return OK;
569*ec779b8eSAndroid Build Coastguard Worker     }
570*ec779b8eSAndroid Build Coastguard Worker 
571*ec779b8eSAndroid Build Coastguard Worker     if (blobSize <= alignment) {
572*ec779b8eSAndroid Build Coastguard Worker         ALOGE("%s: metadata blob is malformed, blobSize(%zu) should be larger than alignment(%zu)",
573*ec779b8eSAndroid Build Coastguard Worker                 __FUNCTION__, blobSize, alignment);
574*ec779b8eSAndroid Build Coastguard Worker         return BAD_VALUE;
575*ec779b8eSAndroid Build Coastguard Worker     }
576*ec779b8eSAndroid Build Coastguard Worker 
577*ec779b8eSAndroid Build Coastguard Worker     const size_t metadataSize = blobSize - alignment;
578*ec779b8eSAndroid Build Coastguard Worker 
579*ec779b8eSAndroid Build Coastguard Worker     // NOTE: this doesn't make sense to me. shouldn't the blob
580*ec779b8eSAndroid Build Coastguard Worker     // know how big it is? why do we have to specify the size
581*ec779b8eSAndroid Build Coastguard Worker     // to Parcel::readBlob ?
582*ec779b8eSAndroid Build Coastguard Worker     ReadableBlob blob;
583*ec779b8eSAndroid Build Coastguard Worker     // arg1 = metadata (blob)
584*ec779b8eSAndroid Build Coastguard Worker     do {
585*ec779b8eSAndroid Build Coastguard Worker         if ((err = data.readBlob(blobSize, &blob)) != OK) {
586*ec779b8eSAndroid Build Coastguard Worker             ALOGE("%s: Failed to read metadata blob (sized %zu). Possible "
587*ec779b8eSAndroid Build Coastguard Worker                   " serialization bug. Error %d %s",
588*ec779b8eSAndroid Build Coastguard Worker                   __FUNCTION__, blobSize, err, strerror(-err));
589*ec779b8eSAndroid Build Coastguard Worker             break;
590*ec779b8eSAndroid Build Coastguard Worker         }
591*ec779b8eSAndroid Build Coastguard Worker 
592*ec779b8eSAndroid Build Coastguard Worker         // arg2 = offset (blob)
593*ec779b8eSAndroid Build Coastguard Worker         // Must be after blob since we don't know offset until after writeBlob.
594*ec779b8eSAndroid Build Coastguard Worker         int32_t offsetTmp;
595*ec779b8eSAndroid Build Coastguard Worker         if ((err = data.readInt32(&offsetTmp)) != OK) {
596*ec779b8eSAndroid Build Coastguard Worker             ALOGE("%s: Failed to read metadata offsetTmp (error %d %s)",
597*ec779b8eSAndroid Build Coastguard Worker                   __FUNCTION__, err, strerror(-err));
598*ec779b8eSAndroid Build Coastguard Worker             break;
599*ec779b8eSAndroid Build Coastguard Worker         }
600*ec779b8eSAndroid Build Coastguard Worker         const size_t offset = static_cast<size_t>(offsetTmp);
601*ec779b8eSAndroid Build Coastguard Worker         if (offset >= alignment) {
602*ec779b8eSAndroid Build Coastguard Worker             ALOGE("%s: metadata offset(%zu) should be less than alignment(%zu)",
603*ec779b8eSAndroid Build Coastguard Worker                     __FUNCTION__, blobSize, alignment);
604*ec779b8eSAndroid Build Coastguard Worker             err = BAD_VALUE;
605*ec779b8eSAndroid Build Coastguard Worker             break;
606*ec779b8eSAndroid Build Coastguard Worker         }
607*ec779b8eSAndroid Build Coastguard Worker 
608*ec779b8eSAndroid Build Coastguard Worker         const uintptr_t metadataStart = reinterpret_cast<uintptr_t>(blob.data()) + offset;
609*ec779b8eSAndroid Build Coastguard Worker         const camera_metadata_t* tmp =
610*ec779b8eSAndroid Build Coastguard Worker                        reinterpret_cast<const camera_metadata_t*>(metadataStart);
611*ec779b8eSAndroid Build Coastguard Worker         ALOGV("%s: alignment is: %zu, metadata start: %p, offset: %zu",
612*ec779b8eSAndroid Build Coastguard Worker                 __FUNCTION__, alignment, tmp, offset);
613*ec779b8eSAndroid Build Coastguard Worker         metadata = allocate_copy_camera_metadata_checked(tmp, metadataSize);
614*ec779b8eSAndroid Build Coastguard Worker         if (metadata == NULL) {
615*ec779b8eSAndroid Build Coastguard Worker             // We consider that allocation only fails if the validation
616*ec779b8eSAndroid Build Coastguard Worker             // also failed, therefore the readFromParcel was a failure.
617*ec779b8eSAndroid Build Coastguard Worker             ALOGE("%s: metadata allocation and copy failed", __FUNCTION__);
618*ec779b8eSAndroid Build Coastguard Worker             err = BAD_VALUE;
619*ec779b8eSAndroid Build Coastguard Worker         }
620*ec779b8eSAndroid Build Coastguard Worker     } while(0);
621*ec779b8eSAndroid Build Coastguard Worker     blob.release();
622*ec779b8eSAndroid Build Coastguard Worker 
623*ec779b8eSAndroid Build Coastguard Worker     if (out) {
624*ec779b8eSAndroid Build Coastguard Worker         ALOGV("%s: Set out metadata to %p", __FUNCTION__, metadata);
625*ec779b8eSAndroid Build Coastguard Worker         *out = metadata;
626*ec779b8eSAndroid Build Coastguard Worker     } else if (metadata != NULL) {
627*ec779b8eSAndroid Build Coastguard Worker         ALOGV("%s: Freed camera metadata at %p", __FUNCTION__, metadata);
628*ec779b8eSAndroid Build Coastguard Worker         free_camera_metadata(metadata);
629*ec779b8eSAndroid Build Coastguard Worker     }
630*ec779b8eSAndroid Build Coastguard Worker 
631*ec779b8eSAndroid Build Coastguard Worker     return err;
632*ec779b8eSAndroid Build Coastguard Worker }
633*ec779b8eSAndroid Build Coastguard Worker 
writeToParcel(Parcel & data,const camera_metadata_t * metadata)634*ec779b8eSAndroid Build Coastguard Worker status_t CameraMetadata::writeToParcel(Parcel& data,
635*ec779b8eSAndroid Build Coastguard Worker                                        const camera_metadata_t* metadata) {
636*ec779b8eSAndroid Build Coastguard Worker     status_t res = OK;
637*ec779b8eSAndroid Build Coastguard Worker 
638*ec779b8eSAndroid Build Coastguard Worker     /**
639*ec779b8eSAndroid Build Coastguard Worker      * Below is the camera metadata parcel layout:
640*ec779b8eSAndroid Build Coastguard Worker      *
641*ec779b8eSAndroid Build Coastguard Worker      * |--------------------------------------------|
642*ec779b8eSAndroid Build Coastguard Worker      * |             arg0: blobSize                 |
643*ec779b8eSAndroid Build Coastguard Worker      * |              (length = 4)                  |
644*ec779b8eSAndroid Build Coastguard Worker      * |--------------------------------------------|<--Skip the rest if blobSize == 0.
645*ec779b8eSAndroid Build Coastguard Worker      * |                                            |
646*ec779b8eSAndroid Build Coastguard Worker      * |                                            |
647*ec779b8eSAndroid Build Coastguard Worker      * |              arg1: blob                    |
648*ec779b8eSAndroid Build Coastguard Worker      * | (length = variable, see arg1 layout below) |
649*ec779b8eSAndroid Build Coastguard Worker      * |                                            |
650*ec779b8eSAndroid Build Coastguard Worker      * |                                            |
651*ec779b8eSAndroid Build Coastguard Worker      * |--------------------------------------------|
652*ec779b8eSAndroid Build Coastguard Worker      * |              arg2: offset                  |
653*ec779b8eSAndroid Build Coastguard Worker      * |              (length = 4)                  |
654*ec779b8eSAndroid Build Coastguard Worker      * |--------------------------------------------|
655*ec779b8eSAndroid Build Coastguard Worker      */
656*ec779b8eSAndroid Build Coastguard Worker 
657*ec779b8eSAndroid Build Coastguard Worker     // arg0 = blobSize (int32)
658*ec779b8eSAndroid Build Coastguard Worker     if (metadata == NULL) {
659*ec779b8eSAndroid Build Coastguard Worker         // Write zero blobSize for null metadata.
660*ec779b8eSAndroid Build Coastguard Worker         return data.writeInt32(0);
661*ec779b8eSAndroid Build Coastguard Worker     }
662*ec779b8eSAndroid Build Coastguard Worker 
663*ec779b8eSAndroid Build Coastguard Worker     /**
664*ec779b8eSAndroid Build Coastguard Worker      * Always make the blob size sufficiently larger, as we need put alignment
665*ec779b8eSAndroid Build Coastguard Worker      * padding and metadata into the blob. Since we don't know the alignment
666*ec779b8eSAndroid Build Coastguard Worker      * offset before writeBlob. Then write the metadata to aligned offset.
667*ec779b8eSAndroid Build Coastguard Worker      */
668*ec779b8eSAndroid Build Coastguard Worker     const size_t metadataSize = get_camera_metadata_compact_size(metadata);
669*ec779b8eSAndroid Build Coastguard Worker     const size_t alignment = get_camera_metadata_alignment();
670*ec779b8eSAndroid Build Coastguard Worker     const size_t blobSize = metadataSize + alignment;
671*ec779b8eSAndroid Build Coastguard Worker     res = data.writeInt32(static_cast<int32_t>(blobSize));
672*ec779b8eSAndroid Build Coastguard Worker     if (res != OK) {
673*ec779b8eSAndroid Build Coastguard Worker         return res;
674*ec779b8eSAndroid Build Coastguard Worker     }
675*ec779b8eSAndroid Build Coastguard Worker 
676*ec779b8eSAndroid Build Coastguard Worker     size_t offset = 0;
677*ec779b8eSAndroid Build Coastguard Worker     /**
678*ec779b8eSAndroid Build Coastguard Worker      * arg1 = metadata (blob).
679*ec779b8eSAndroid Build Coastguard Worker      *
680*ec779b8eSAndroid Build Coastguard Worker      * The blob size is the sum of front padding size, metadata size and back padding
681*ec779b8eSAndroid Build Coastguard Worker      * size, which is equal to metadataSize + alignment.
682*ec779b8eSAndroid Build Coastguard Worker      *
683*ec779b8eSAndroid Build Coastguard Worker      * The blob layout is:
684*ec779b8eSAndroid Build Coastguard Worker      * |------------------------------------|<----Start address of the blob (unaligned).
685*ec779b8eSAndroid Build Coastguard Worker      * |           front padding            |
686*ec779b8eSAndroid Build Coastguard Worker      * |          (size = offset)           |
687*ec779b8eSAndroid Build Coastguard Worker      * |------------------------------------|<----Aligned start address of metadata.
688*ec779b8eSAndroid Build Coastguard Worker      * |                                    |
689*ec779b8eSAndroid Build Coastguard Worker      * |                                    |
690*ec779b8eSAndroid Build Coastguard Worker      * |            metadata                |
691*ec779b8eSAndroid Build Coastguard Worker      * |       (size = metadataSize)        |
692*ec779b8eSAndroid Build Coastguard Worker      * |                                    |
693*ec779b8eSAndroid Build Coastguard Worker      * |                                    |
694*ec779b8eSAndroid Build Coastguard Worker      * |------------------------------------|
695*ec779b8eSAndroid Build Coastguard Worker      * |           back padding             |
696*ec779b8eSAndroid Build Coastguard Worker      * |     (size = alignment - offset)    |
697*ec779b8eSAndroid Build Coastguard Worker      * |------------------------------------|<----End address of blob.
698*ec779b8eSAndroid Build Coastguard Worker      *                                            (Blob start address + blob size).
699*ec779b8eSAndroid Build Coastguard Worker      */
700*ec779b8eSAndroid Build Coastguard Worker     WritableBlob blob;
701*ec779b8eSAndroid Build Coastguard Worker     do {
702*ec779b8eSAndroid Build Coastguard Worker         res = data.writeBlob(blobSize, false, &blob);
703*ec779b8eSAndroid Build Coastguard Worker         if (res != OK) {
704*ec779b8eSAndroid Build Coastguard Worker             break;
705*ec779b8eSAndroid Build Coastguard Worker         }
706*ec779b8eSAndroid Build Coastguard Worker         const uintptr_t metadataStart = ALIGN_TO(blob.data(), alignment);
707*ec779b8eSAndroid Build Coastguard Worker         offset = metadataStart - reinterpret_cast<uintptr_t>(blob.data());
708*ec779b8eSAndroid Build Coastguard Worker         ALOGV("%s: alignment is: %zu, metadata start: %p, offset: %zu",
709*ec779b8eSAndroid Build Coastguard Worker                 __FUNCTION__, alignment,
710*ec779b8eSAndroid Build Coastguard Worker                 reinterpret_cast<const void *>(metadataStart), offset);
711*ec779b8eSAndroid Build Coastguard Worker         copy_camera_metadata(reinterpret_cast<void*>(metadataStart), metadataSize, metadata);
712*ec779b8eSAndroid Build Coastguard Worker 
713*ec779b8eSAndroid Build Coastguard Worker         // Not too big of a problem since receiving side does hard validation
714*ec779b8eSAndroid Build Coastguard Worker         // Don't check the size since the compact size could be larger
715*ec779b8eSAndroid Build Coastguard Worker         if (validate_camera_metadata_structure(metadata, /*size*/NULL) != OK) {
716*ec779b8eSAndroid Build Coastguard Worker             ALOGW("%s: Failed to validate metadata %p before writing blob",
717*ec779b8eSAndroid Build Coastguard Worker                    __FUNCTION__, metadata);
718*ec779b8eSAndroid Build Coastguard Worker         }
719*ec779b8eSAndroid Build Coastguard Worker 
720*ec779b8eSAndroid Build Coastguard Worker     } while(false);
721*ec779b8eSAndroid Build Coastguard Worker     blob.release();
722*ec779b8eSAndroid Build Coastguard Worker 
723*ec779b8eSAndroid Build Coastguard Worker     // arg2 = offset (int32)
724*ec779b8eSAndroid Build Coastguard Worker     res = data.writeInt32(static_cast<int32_t>(offset));
725*ec779b8eSAndroid Build Coastguard Worker 
726*ec779b8eSAndroid Build Coastguard Worker     return res;
727*ec779b8eSAndroid Build Coastguard Worker }
728*ec779b8eSAndroid Build Coastguard Worker 
readFromParcel(const Parcel * parcel)729*ec779b8eSAndroid Build Coastguard Worker status_t CameraMetadata::readFromParcel(const Parcel *parcel) {
730*ec779b8eSAndroid Build Coastguard Worker 
731*ec779b8eSAndroid Build Coastguard Worker     ALOGV("%s: parcel = %p", __FUNCTION__, parcel);
732*ec779b8eSAndroid Build Coastguard Worker 
733*ec779b8eSAndroid Build Coastguard Worker     status_t res = OK;
734*ec779b8eSAndroid Build Coastguard Worker 
735*ec779b8eSAndroid Build Coastguard Worker     if (parcel == NULL) {
736*ec779b8eSAndroid Build Coastguard Worker         ALOGE("%s: parcel is null", __FUNCTION__);
737*ec779b8eSAndroid Build Coastguard Worker         return BAD_VALUE;
738*ec779b8eSAndroid Build Coastguard Worker     }
739*ec779b8eSAndroid Build Coastguard Worker 
740*ec779b8eSAndroid Build Coastguard Worker     if (mLocked) {
741*ec779b8eSAndroid Build Coastguard Worker         ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
742*ec779b8eSAndroid Build Coastguard Worker         return INVALID_OPERATION;
743*ec779b8eSAndroid Build Coastguard Worker     }
744*ec779b8eSAndroid Build Coastguard Worker 
745*ec779b8eSAndroid Build Coastguard Worker     camera_metadata *buffer = NULL;
746*ec779b8eSAndroid Build Coastguard Worker     // TODO: reading should return a status code, in case validation fails
747*ec779b8eSAndroid Build Coastguard Worker     res = CameraMetadata::readFromParcel(*parcel, &buffer);
748*ec779b8eSAndroid Build Coastguard Worker 
749*ec779b8eSAndroid Build Coastguard Worker     if (res != NO_ERROR) {
750*ec779b8eSAndroid Build Coastguard Worker         ALOGE("%s: Failed to read from parcel. Metadata is unchanged.",
751*ec779b8eSAndroid Build Coastguard Worker               __FUNCTION__);
752*ec779b8eSAndroid Build Coastguard Worker         return res;
753*ec779b8eSAndroid Build Coastguard Worker     }
754*ec779b8eSAndroid Build Coastguard Worker 
755*ec779b8eSAndroid Build Coastguard Worker     clear();
756*ec779b8eSAndroid Build Coastguard Worker     mBuffer = buffer;
757*ec779b8eSAndroid Build Coastguard Worker 
758*ec779b8eSAndroid Build Coastguard Worker     return OK;
759*ec779b8eSAndroid Build Coastguard Worker }
760*ec779b8eSAndroid Build Coastguard Worker 
writeToParcel(Parcel * parcel) const761*ec779b8eSAndroid Build Coastguard Worker status_t CameraMetadata::writeToParcel(Parcel *parcel) const {
762*ec779b8eSAndroid Build Coastguard Worker 
763*ec779b8eSAndroid Build Coastguard Worker     ALOGV("%s: parcel = %p", __FUNCTION__, parcel);
764*ec779b8eSAndroid Build Coastguard Worker 
765*ec779b8eSAndroid Build Coastguard Worker     if (parcel == NULL) {
766*ec779b8eSAndroid Build Coastguard Worker         ALOGE("%s: parcel is null", __FUNCTION__);
767*ec779b8eSAndroid Build Coastguard Worker         return BAD_VALUE;
768*ec779b8eSAndroid Build Coastguard Worker     }
769*ec779b8eSAndroid Build Coastguard Worker 
770*ec779b8eSAndroid Build Coastguard Worker     return CameraMetadata::writeToParcel(*parcel, mBuffer);
771*ec779b8eSAndroid Build Coastguard Worker }
772*ec779b8eSAndroid Build Coastguard Worker 
swap(CameraMetadata & other)773*ec779b8eSAndroid Build Coastguard Worker void CameraMetadata::swap(CameraMetadata& other) {
774*ec779b8eSAndroid Build Coastguard Worker     if (mLocked) {
775*ec779b8eSAndroid Build Coastguard Worker         ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
776*ec779b8eSAndroid Build Coastguard Worker         return;
777*ec779b8eSAndroid Build Coastguard Worker     } else if (other.mLocked) {
778*ec779b8eSAndroid Build Coastguard Worker         ALOGE("%s: Other CameraMetadata is locked", __FUNCTION__);
779*ec779b8eSAndroid Build Coastguard Worker         return;
780*ec779b8eSAndroid Build Coastguard Worker     }
781*ec779b8eSAndroid Build Coastguard Worker 
782*ec779b8eSAndroid Build Coastguard Worker     camera_metadata* thisBuf = mBuffer;
783*ec779b8eSAndroid Build Coastguard Worker     camera_metadata* otherBuf = other.mBuffer;
784*ec779b8eSAndroid Build Coastguard Worker 
785*ec779b8eSAndroid Build Coastguard Worker     other.mBuffer = thisBuf;
786*ec779b8eSAndroid Build Coastguard Worker     mBuffer = otherBuf;
787*ec779b8eSAndroid Build Coastguard Worker }
788*ec779b8eSAndroid Build Coastguard Worker 
getTagFromName(const char * name,const VendorTagDescriptor * vTags,uint32_t * tag)789*ec779b8eSAndroid Build Coastguard Worker status_t CameraMetadata::getTagFromName(const char *name,
790*ec779b8eSAndroid Build Coastguard Worker         const VendorTagDescriptor* vTags, uint32_t *tag) {
791*ec779b8eSAndroid Build Coastguard Worker 
792*ec779b8eSAndroid Build Coastguard Worker     if (name == nullptr || tag == nullptr) return BAD_VALUE;
793*ec779b8eSAndroid Build Coastguard Worker 
794*ec779b8eSAndroid Build Coastguard Worker     size_t nameLength = strlen(name);
795*ec779b8eSAndroid Build Coastguard Worker 
796*ec779b8eSAndroid Build Coastguard Worker     const SortedVector<String8> *vendorSections;
797*ec779b8eSAndroid Build Coastguard Worker     size_t vendorSectionCount = 0;
798*ec779b8eSAndroid Build Coastguard Worker 
799*ec779b8eSAndroid Build Coastguard Worker     if (vTags != NULL) {
800*ec779b8eSAndroid Build Coastguard Worker         vendorSections = vTags->getAllSectionNames();
801*ec779b8eSAndroid Build Coastguard Worker         vendorSectionCount = vendorSections->size();
802*ec779b8eSAndroid Build Coastguard Worker     }
803*ec779b8eSAndroid Build Coastguard Worker 
804*ec779b8eSAndroid Build Coastguard Worker     // First, find the section by the longest string match
805*ec779b8eSAndroid Build Coastguard Worker     const char *section = NULL;
806*ec779b8eSAndroid Build Coastguard Worker     size_t sectionIndex = 0;
807*ec779b8eSAndroid Build Coastguard Worker     size_t sectionLength = 0;
808*ec779b8eSAndroid Build Coastguard Worker     size_t totalSectionCount = ANDROID_SECTION_COUNT + vendorSectionCount;
809*ec779b8eSAndroid Build Coastguard Worker     for (size_t i = 0; i < totalSectionCount; ++i) {
810*ec779b8eSAndroid Build Coastguard Worker 
811*ec779b8eSAndroid Build Coastguard Worker         const char *str = (i < ANDROID_SECTION_COUNT) ? camera_metadata_section_names[i] :
812*ec779b8eSAndroid Build Coastguard Worker                 (*vendorSections)[i - ANDROID_SECTION_COUNT].c_str();
813*ec779b8eSAndroid Build Coastguard Worker 
814*ec779b8eSAndroid Build Coastguard Worker         ALOGV("%s: Trying to match against section '%s'", __FUNCTION__, str);
815*ec779b8eSAndroid Build Coastguard Worker 
816*ec779b8eSAndroid Build Coastguard Worker         if (strstr(name, str) == name) { // name begins with the section name
817*ec779b8eSAndroid Build Coastguard Worker             size_t strLength = strlen(str);
818*ec779b8eSAndroid Build Coastguard Worker 
819*ec779b8eSAndroid Build Coastguard Worker             ALOGV("%s: Name begins with section name", __FUNCTION__);
820*ec779b8eSAndroid Build Coastguard Worker 
821*ec779b8eSAndroid Build Coastguard Worker             // section name is the longest we've found so far
822*ec779b8eSAndroid Build Coastguard Worker             if (section == NULL || sectionLength < strLength) {
823*ec779b8eSAndroid Build Coastguard Worker                 section = str;
824*ec779b8eSAndroid Build Coastguard Worker                 sectionIndex = i;
825*ec779b8eSAndroid Build Coastguard Worker                 sectionLength = strLength;
826*ec779b8eSAndroid Build Coastguard Worker 
827*ec779b8eSAndroid Build Coastguard Worker                 ALOGV("%s: Found new best section (%s)", __FUNCTION__, section);
828*ec779b8eSAndroid Build Coastguard Worker             }
829*ec779b8eSAndroid Build Coastguard Worker         }
830*ec779b8eSAndroid Build Coastguard Worker     }
831*ec779b8eSAndroid Build Coastguard Worker 
832*ec779b8eSAndroid Build Coastguard Worker     // TODO: Make above get_camera_metadata_section_from_name ?
833*ec779b8eSAndroid Build Coastguard Worker 
834*ec779b8eSAndroid Build Coastguard Worker     if (section == NULL) {
835*ec779b8eSAndroid Build Coastguard Worker         return NAME_NOT_FOUND;
836*ec779b8eSAndroid Build Coastguard Worker     } else {
837*ec779b8eSAndroid Build Coastguard Worker         ALOGV("%s: Found matched section '%s' (%zu)",
838*ec779b8eSAndroid Build Coastguard Worker               __FUNCTION__, section, sectionIndex);
839*ec779b8eSAndroid Build Coastguard Worker     }
840*ec779b8eSAndroid Build Coastguard Worker 
841*ec779b8eSAndroid Build Coastguard Worker     // Get the tag name component of the name
842*ec779b8eSAndroid Build Coastguard Worker     const char *nameTagName = name + sectionLength + 1; // x.y.z -> z
843*ec779b8eSAndroid Build Coastguard Worker     if (sectionLength + 1 >= nameLength) {
844*ec779b8eSAndroid Build Coastguard Worker         return BAD_VALUE;
845*ec779b8eSAndroid Build Coastguard Worker     }
846*ec779b8eSAndroid Build Coastguard Worker 
847*ec779b8eSAndroid Build Coastguard Worker     // Match rest of name against the tag names in that section only
848*ec779b8eSAndroid Build Coastguard Worker     uint32_t candidateTag = 0;
849*ec779b8eSAndroid Build Coastguard Worker     if (sectionIndex < ANDROID_SECTION_COUNT) {
850*ec779b8eSAndroid Build Coastguard Worker         // Match built-in tags (typically android.*)
851*ec779b8eSAndroid Build Coastguard Worker         uint32_t tagBegin, tagEnd; // [tagBegin, tagEnd)
852*ec779b8eSAndroid Build Coastguard Worker         tagBegin = camera_metadata_section_bounds[sectionIndex][0];
853*ec779b8eSAndroid Build Coastguard Worker         tagEnd = camera_metadata_section_bounds[sectionIndex][1];
854*ec779b8eSAndroid Build Coastguard Worker 
855*ec779b8eSAndroid Build Coastguard Worker         for (candidateTag = tagBegin; candidateTag < tagEnd; ++candidateTag) {
856*ec779b8eSAndroid Build Coastguard Worker             const char *tagName = get_camera_metadata_tag_name(candidateTag);
857*ec779b8eSAndroid Build Coastguard Worker 
858*ec779b8eSAndroid Build Coastguard Worker             if (strcmp(nameTagName, tagName) == 0) {
859*ec779b8eSAndroid Build Coastguard Worker                 ALOGV("%s: Found matched tag '%s' (%d)",
860*ec779b8eSAndroid Build Coastguard Worker                       __FUNCTION__, tagName, candidateTag);
861*ec779b8eSAndroid Build Coastguard Worker                 break;
862*ec779b8eSAndroid Build Coastguard Worker             }
863*ec779b8eSAndroid Build Coastguard Worker         }
864*ec779b8eSAndroid Build Coastguard Worker 
865*ec779b8eSAndroid Build Coastguard Worker         if (candidateTag == tagEnd) {
866*ec779b8eSAndroid Build Coastguard Worker             return NAME_NOT_FOUND;
867*ec779b8eSAndroid Build Coastguard Worker         }
868*ec779b8eSAndroid Build Coastguard Worker     } else if (vTags != NULL) {
869*ec779b8eSAndroid Build Coastguard Worker         // Match vendor tags (typically com.*)
870*ec779b8eSAndroid Build Coastguard Worker         const String8 sectionName(section);
871*ec779b8eSAndroid Build Coastguard Worker         const String8 tagName(nameTagName);
872*ec779b8eSAndroid Build Coastguard Worker 
873*ec779b8eSAndroid Build Coastguard Worker         status_t res = OK;
874*ec779b8eSAndroid Build Coastguard Worker         if ((res = vTags->lookupTag(tagName, sectionName, &candidateTag)) != OK) {
875*ec779b8eSAndroid Build Coastguard Worker             return NAME_NOT_FOUND;
876*ec779b8eSAndroid Build Coastguard Worker         }
877*ec779b8eSAndroid Build Coastguard Worker     }
878*ec779b8eSAndroid Build Coastguard Worker 
879*ec779b8eSAndroid Build Coastguard Worker     *tag = candidateTag;
880*ec779b8eSAndroid Build Coastguard Worker     return OK;
881*ec779b8eSAndroid Build Coastguard Worker }
882*ec779b8eSAndroid Build Coastguard Worker 
getVendorId() const883*ec779b8eSAndroid Build Coastguard Worker metadata_vendor_id_t CameraMetadata::getVendorId() const {
884*ec779b8eSAndroid Build Coastguard Worker     return get_camera_metadata_vendor_id(mBuffer);
885*ec779b8eSAndroid Build Coastguard Worker }
886*ec779b8eSAndroid Build Coastguard Worker 
887*ec779b8eSAndroid Build Coastguard Worker }; // namespace android
888