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