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