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