• 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 <camera/CameraMetadata.h>
24 #include <binder/Parcel.h>
25 
26 namespace android {
27 
28 typedef Parcel::WritableBlob WritableBlob;
29 typedef Parcel::ReadableBlob ReadableBlob;
30 
CameraMetadata()31 CameraMetadata::CameraMetadata() :
32         mBuffer(NULL), mLocked(false) {
33 }
34 
CameraMetadata(size_t entryCapacity,size_t dataCapacity)35 CameraMetadata::CameraMetadata(size_t entryCapacity, size_t dataCapacity) :
36         mLocked(false)
37 {
38     mBuffer = allocate_camera_metadata(entryCapacity, dataCapacity);
39 }
40 
CameraMetadata(const CameraMetadata & other)41 CameraMetadata::CameraMetadata(const CameraMetadata &other) :
42         mLocked(false) {
43     mBuffer = clone_camera_metadata(other.mBuffer);
44 }
45 
CameraMetadata(camera_metadata_t * buffer)46 CameraMetadata::CameraMetadata(camera_metadata_t *buffer) :
47         mBuffer(NULL), mLocked(false) {
48     acquire(buffer);
49 }
50 
operator =(const CameraMetadata & other)51 CameraMetadata &CameraMetadata::operator=(const CameraMetadata &other) {
52     return operator=(other.mBuffer);
53 }
54 
operator =(const camera_metadata_t * buffer)55 CameraMetadata &CameraMetadata::operator=(const camera_metadata_t *buffer) {
56     if (mLocked) {
57         ALOGE("%s: Assignment to a locked CameraMetadata!", __FUNCTION__);
58         return *this;
59     }
60 
61     if (CC_LIKELY(buffer != mBuffer)) {
62         camera_metadata_t *newBuffer = clone_camera_metadata(buffer);
63         clear();
64         mBuffer = newBuffer;
65     }
66     return *this;
67 }
68 
~CameraMetadata()69 CameraMetadata::~CameraMetadata() {
70     mLocked = false;
71     clear();
72 }
73 
getAndLock()74 const camera_metadata_t* CameraMetadata::getAndLock() {
75     mLocked = true;
76     return mBuffer;
77 }
78 
unlock(const camera_metadata_t * buffer)79 status_t CameraMetadata::unlock(const camera_metadata_t *buffer) {
80     if (!mLocked) {
81         ALOGE("%s: Can't unlock a non-locked CameraMetadata!", __FUNCTION__);
82         return INVALID_OPERATION;
83     }
84     if (buffer != mBuffer) {
85         ALOGE("%s: Can't unlock CameraMetadata with wrong pointer!",
86                 __FUNCTION__);
87         return BAD_VALUE;
88     }
89     mLocked = false;
90     return OK;
91 }
92 
release()93 camera_metadata_t* CameraMetadata::release() {
94     if (mLocked) {
95         ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
96         return NULL;
97     }
98     camera_metadata_t *released = mBuffer;
99     mBuffer = NULL;
100     return released;
101 }
102 
clear()103 void CameraMetadata::clear() {
104     if (mLocked) {
105         ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
106         return;
107     }
108     if (mBuffer) {
109         free_camera_metadata(mBuffer);
110         mBuffer = NULL;
111     }
112 }
113 
acquire(camera_metadata_t * buffer)114 void CameraMetadata::acquire(camera_metadata_t *buffer) {
115     if (mLocked) {
116         ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
117         return;
118     }
119     clear();
120     mBuffer = buffer;
121 
122     ALOGE_IF(validate_camera_metadata_structure(mBuffer, /*size*/NULL) != OK,
123              "%s: Failed to validate metadata structure %p",
124              __FUNCTION__, buffer);
125 }
126 
acquire(CameraMetadata & other)127 void CameraMetadata::acquire(CameraMetadata &other) {
128     if (mLocked) {
129         ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
130         return;
131     }
132     acquire(other.release());
133 }
134 
append(const CameraMetadata & other)135 status_t CameraMetadata::append(const CameraMetadata &other) {
136     return append(other.mBuffer);
137 }
138 
append(const camera_metadata_t * other)139 status_t CameraMetadata::append(const camera_metadata_t* other) {
140     if (mLocked) {
141         ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
142         return INVALID_OPERATION;
143     }
144     size_t extraEntries = get_camera_metadata_entry_count(other);
145     size_t extraData = get_camera_metadata_data_count(other);
146     resizeIfNeeded(extraEntries, extraData);
147 
148     return append_camera_metadata(mBuffer, other);
149 }
150 
entryCount() const151 size_t CameraMetadata::entryCount() const {
152     return (mBuffer == NULL) ? 0 :
153             get_camera_metadata_entry_count(mBuffer);
154 }
155 
isEmpty() const156 bool CameraMetadata::isEmpty() const {
157     return entryCount() == 0;
158 }
159 
sort()160 status_t CameraMetadata::sort() {
161     if (mLocked) {
162         ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
163         return INVALID_OPERATION;
164     }
165     return sort_camera_metadata(mBuffer);
166 }
167 
checkType(uint32_t tag,uint8_t expectedType)168 status_t CameraMetadata::checkType(uint32_t tag, uint8_t expectedType) {
169     int tagType = get_camera_metadata_tag_type(tag);
170     if ( CC_UNLIKELY(tagType == -1)) {
171         ALOGE("Update metadata entry: Unknown tag %d", tag);
172         return INVALID_OPERATION;
173     }
174     if ( CC_UNLIKELY(tagType != expectedType) ) {
175         ALOGE("Mismatched tag type when updating entry %s (%d) of type %s; "
176                 "got type %s data instead ",
177                 get_camera_metadata_tag_name(tag), tag,
178                 camera_metadata_type_names[tagType],
179                 camera_metadata_type_names[expectedType]);
180         return INVALID_OPERATION;
181     }
182     return OK;
183 }
184 
update(uint32_t tag,const int32_t * data,size_t data_count)185 status_t CameraMetadata::update(uint32_t tag,
186         const int32_t *data, size_t data_count) {
187     status_t res;
188     if (mLocked) {
189         ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
190         return INVALID_OPERATION;
191     }
192     if ( (res = checkType(tag, TYPE_INT32)) != OK) {
193         return res;
194     }
195     return updateImpl(tag, (const void*)data, data_count);
196 }
197 
update(uint32_t tag,const uint8_t * data,size_t data_count)198 status_t CameraMetadata::update(uint32_t tag,
199         const uint8_t *data, size_t data_count) {
200     status_t res;
201     if (mLocked) {
202         ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
203         return INVALID_OPERATION;
204     }
205     if ( (res = checkType(tag, TYPE_BYTE)) != OK) {
206         return res;
207     }
208     return updateImpl(tag, (const void*)data, data_count);
209 }
210 
update(uint32_t tag,const float * data,size_t data_count)211 status_t CameraMetadata::update(uint32_t tag,
212         const float *data, size_t data_count) {
213     status_t res;
214     if (mLocked) {
215         ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
216         return INVALID_OPERATION;
217     }
218     if ( (res = checkType(tag, TYPE_FLOAT)) != OK) {
219         return res;
220     }
221     return updateImpl(tag, (const void*)data, data_count);
222 }
223 
update(uint32_t tag,const int64_t * data,size_t data_count)224 status_t CameraMetadata::update(uint32_t tag,
225         const int64_t *data, size_t data_count) {
226     status_t res;
227     if (mLocked) {
228         ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
229         return INVALID_OPERATION;
230     }
231     if ( (res = checkType(tag, TYPE_INT64)) != OK) {
232         return res;
233     }
234     return updateImpl(tag, (const void*)data, data_count);
235 }
236 
update(uint32_t tag,const double * data,size_t data_count)237 status_t CameraMetadata::update(uint32_t tag,
238         const double *data, size_t data_count) {
239     status_t res;
240     if (mLocked) {
241         ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
242         return INVALID_OPERATION;
243     }
244     if ( (res = checkType(tag, TYPE_DOUBLE)) != OK) {
245         return res;
246     }
247     return updateImpl(tag, (const void*)data, data_count);
248 }
249 
update(uint32_t tag,const camera_metadata_rational_t * data,size_t data_count)250 status_t CameraMetadata::update(uint32_t tag,
251         const camera_metadata_rational_t *data, size_t data_count) {
252     status_t res;
253     if (mLocked) {
254         ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
255         return INVALID_OPERATION;
256     }
257     if ( (res = checkType(tag, TYPE_RATIONAL)) != OK) {
258         return res;
259     }
260     return updateImpl(tag, (const void*)data, data_count);
261 }
262 
update(uint32_t tag,const String8 & string)263 status_t CameraMetadata::update(uint32_t tag,
264         const String8 &string) {
265     status_t res;
266     if (mLocked) {
267         ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
268         return INVALID_OPERATION;
269     }
270     if ( (res = checkType(tag, TYPE_BYTE)) != OK) {
271         return res;
272     }
273     return updateImpl(tag, (const void*)string.string(), string.size());
274 }
275 
updateImpl(uint32_t tag,const void * data,size_t data_count)276 status_t CameraMetadata::updateImpl(uint32_t tag, const void *data,
277         size_t data_count) {
278     status_t res;
279     if (mLocked) {
280         ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
281         return INVALID_OPERATION;
282     }
283     int type = get_camera_metadata_tag_type(tag);
284     if (type == -1) {
285         ALOGE("%s: Tag %d not found", __FUNCTION__, tag);
286         return BAD_VALUE;
287     }
288     size_t data_size = calculate_camera_metadata_entry_data_size(type,
289             data_count);
290 
291     res = resizeIfNeeded(1, data_size);
292 
293     if (res == OK) {
294         camera_metadata_entry_t entry;
295         res = find_camera_metadata_entry(mBuffer, tag, &entry);
296         if (res == NAME_NOT_FOUND) {
297             res = add_camera_metadata_entry(mBuffer,
298                     tag, data, data_count);
299         } else if (res == OK) {
300             res = update_camera_metadata_entry(mBuffer,
301                     entry.index, data, data_count, NULL);
302         }
303     }
304 
305     if (res != OK) {
306         ALOGE("%s: Unable to update metadata entry %s.%s (%x): %s (%d)",
307                 __FUNCTION__, get_camera_metadata_section_name(tag),
308                 get_camera_metadata_tag_name(tag), tag, strerror(-res), res);
309     }
310 
311     IF_ALOGV() {
312         ALOGE_IF(validate_camera_metadata_structure(mBuffer, /*size*/NULL) !=
313                  OK,
314 
315                  "%s: Failed to validate metadata structure after update %p",
316                  __FUNCTION__, mBuffer);
317     }
318 
319     return res;
320 }
321 
exists(uint32_t tag) const322 bool CameraMetadata::exists(uint32_t tag) const {
323     camera_metadata_ro_entry entry;
324     return find_camera_metadata_ro_entry(mBuffer, tag, &entry) == 0;
325 }
326 
find(uint32_t tag)327 camera_metadata_entry_t CameraMetadata::find(uint32_t tag) {
328     status_t res;
329     camera_metadata_entry entry;
330     if (mLocked) {
331         ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
332         entry.count = 0;
333         return entry;
334     }
335     res = find_camera_metadata_entry(mBuffer, tag, &entry);
336     if (CC_UNLIKELY( res != OK )) {
337         entry.count = 0;
338         entry.data.u8 = NULL;
339     }
340     return entry;
341 }
342 
find(uint32_t tag) const343 camera_metadata_ro_entry_t CameraMetadata::find(uint32_t tag) const {
344     status_t res;
345     camera_metadata_ro_entry entry;
346     res = find_camera_metadata_ro_entry(mBuffer, tag, &entry);
347     if (CC_UNLIKELY( res != OK )) {
348         entry.count = 0;
349         entry.data.u8 = NULL;
350     }
351     return entry;
352 }
353 
erase(uint32_t tag)354 status_t CameraMetadata::erase(uint32_t tag) {
355     camera_metadata_entry_t entry;
356     status_t res;
357     if (mLocked) {
358         ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
359         return INVALID_OPERATION;
360     }
361     res = find_camera_metadata_entry(mBuffer, tag, &entry);
362     if (res == NAME_NOT_FOUND) {
363         return OK;
364     } else if (res != OK) {
365         ALOGE("%s: Error looking for entry %s.%s (%x): %s %d",
366                 __FUNCTION__,
367                 get_camera_metadata_section_name(tag),
368                 get_camera_metadata_tag_name(tag), tag, strerror(-res), res);
369         return res;
370     }
371     res = delete_camera_metadata_entry(mBuffer, entry.index);
372     if (res != OK) {
373         ALOGE("%s: Error deleting entry %s.%s (%x): %s %d",
374                 __FUNCTION__,
375                 get_camera_metadata_section_name(tag),
376                 get_camera_metadata_tag_name(tag), tag, strerror(-res), res);
377     }
378     return res;
379 }
380 
dump(int fd,int verbosity,int indentation) const381 void CameraMetadata::dump(int fd, int verbosity, int indentation) const {
382     dump_indented_camera_metadata(mBuffer, fd, verbosity, indentation);
383 }
384 
resizeIfNeeded(size_t extraEntries,size_t extraData)385 status_t CameraMetadata::resizeIfNeeded(size_t extraEntries, size_t extraData) {
386     if (mBuffer == NULL) {
387         mBuffer = allocate_camera_metadata(extraEntries * 2, extraData * 2);
388         if (mBuffer == NULL) {
389             ALOGE("%s: Can't allocate larger metadata buffer", __FUNCTION__);
390             return NO_MEMORY;
391         }
392     } else {
393         size_t currentEntryCount = get_camera_metadata_entry_count(mBuffer);
394         size_t currentEntryCap = get_camera_metadata_entry_capacity(mBuffer);
395         size_t newEntryCount = currentEntryCount +
396                 extraEntries;
397         newEntryCount = (newEntryCount > currentEntryCap) ?
398                 newEntryCount * 2 : currentEntryCap;
399 
400         size_t currentDataCount = get_camera_metadata_data_count(mBuffer);
401         size_t currentDataCap = get_camera_metadata_data_capacity(mBuffer);
402         size_t newDataCount = currentDataCount +
403                 extraData;
404         newDataCount = (newDataCount > currentDataCap) ?
405                 newDataCount * 2 : currentDataCap;
406 
407         if (newEntryCount > currentEntryCap ||
408                 newDataCount > currentDataCap) {
409             camera_metadata_t *oldBuffer = mBuffer;
410             mBuffer = allocate_camera_metadata(newEntryCount,
411                     newDataCount);
412             if (mBuffer == NULL) {
413                 ALOGE("%s: Can't allocate larger metadata buffer", __FUNCTION__);
414                 return NO_MEMORY;
415             }
416             append_camera_metadata(mBuffer, oldBuffer);
417             free_camera_metadata(oldBuffer);
418         }
419     }
420     return OK;
421 }
422 
readFromParcel(const Parcel & data,camera_metadata_t ** out)423 status_t CameraMetadata::readFromParcel(const Parcel& data,
424                                         camera_metadata_t** out) {
425 
426     status_t err = OK;
427 
428     camera_metadata_t* metadata = NULL;
429 
430     if (out) {
431         *out = NULL;
432     }
433 
434     // arg0 = metadataSize (int32)
435     int32_t metadataSizeTmp = -1;
436     if ((err = data.readInt32(&metadataSizeTmp)) != OK) {
437         ALOGE("%s: Failed to read metadata size (error %d %s)",
438               __FUNCTION__, err, strerror(-err));
439         return err;
440     }
441     const size_t metadataSize = static_cast<size_t>(metadataSizeTmp);
442 
443     if (metadataSize == 0) {
444         ALOGV("%s: Read 0-sized metadata", __FUNCTION__);
445         return OK;
446     }
447 
448     // NOTE: this doesn't make sense to me. shouldnt the blob
449     // know how big it is? why do we have to specify the size
450     // to Parcel::readBlob ?
451 
452     ReadableBlob blob;
453     // arg1 = metadata (blob)
454     do {
455         if ((err = data.readBlob(metadataSize, &blob)) != OK) {
456             ALOGE("%s: Failed to read metadata blob (sized %d). Possible "
457                   " serialization bug. Error %d %s",
458                   __FUNCTION__, metadataSize, err, strerror(-err));
459             break;
460         }
461         const camera_metadata_t* tmp =
462                        reinterpret_cast<const camera_metadata_t*>(blob.data());
463 
464         metadata = allocate_copy_camera_metadata_checked(tmp, metadataSize);
465         if (metadata == NULL) {
466             // We consider that allocation only fails if the validation
467             // also failed, therefore the readFromParcel was a failure.
468             err = BAD_VALUE;
469         }
470     } while(0);
471     blob.release();
472 
473     if (out) {
474         ALOGV("%s: Set out metadata to %p", __FUNCTION__, metadata);
475         *out = metadata;
476     } else if (metadata != NULL) {
477         ALOGV("%s: Freed camera metadata at %p", __FUNCTION__, metadata);
478         free_camera_metadata(metadata);
479     }
480 
481     return err;
482 }
483 
writeToParcel(Parcel & data,const camera_metadata_t * metadata)484 status_t CameraMetadata::writeToParcel(Parcel& data,
485                                        const camera_metadata_t* metadata) {
486     status_t res = OK;
487 
488     // arg0 = metadataSize (int32)
489 
490     if (metadata == NULL) {
491         return data.writeInt32(0);
492     }
493 
494     const size_t metadataSize = get_camera_metadata_compact_size(metadata);
495     res = data.writeInt32(static_cast<int32_t>(metadataSize));
496     if (res != OK) {
497         return res;
498     }
499 
500     // arg1 = metadata (blob)
501     WritableBlob blob;
502     do {
503         res = data.writeBlob(metadataSize, &blob);
504         if (res != OK) {
505             break;
506         }
507         copy_camera_metadata(blob.data(), metadataSize, metadata);
508 
509         IF_ALOGV() {
510             if (validate_camera_metadata_structure(
511                         (const camera_metadata_t*)blob.data(),
512                         &metadataSize) != OK) {
513                 ALOGV("%s: Failed to validate metadata %p after writing blob",
514                        __FUNCTION__, blob.data());
515             } else {
516                 ALOGV("%s: Metadata written to blob. Validation success",
517                         __FUNCTION__);
518             }
519         }
520 
521         // Not too big of a problem since receiving side does hard validation
522         // Don't check the size since the compact size could be larger
523         if (validate_camera_metadata_structure(metadata, /*size*/NULL) != OK) {
524             ALOGW("%s: Failed to validate metadata %p before writing blob",
525                    __FUNCTION__, metadata);
526         }
527 
528     } while(false);
529     blob.release();
530 
531     return res;
532 }
533 
readFromParcel(Parcel * parcel)534 status_t CameraMetadata::readFromParcel(Parcel *parcel) {
535 
536     ALOGV("%s: parcel = %p", __FUNCTION__, parcel);
537 
538     status_t res = OK;
539 
540     if (parcel == NULL) {
541         ALOGE("%s: parcel is null", __FUNCTION__);
542         return BAD_VALUE;
543     }
544 
545     if (mLocked) {
546         ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
547         return INVALID_OPERATION;
548     }
549 
550     camera_metadata *buffer = NULL;
551     // TODO: reading should return a status code, in case validation fails
552     res = CameraMetadata::readFromParcel(*parcel, &buffer);
553 
554     if (res != NO_ERROR) {
555         ALOGE("%s: Failed to read from parcel. Metadata is unchanged.",
556               __FUNCTION__);
557         return res;
558     }
559 
560     clear();
561     mBuffer = buffer;
562 
563     return OK;
564 }
565 
writeToParcel(Parcel * parcel) const566 status_t CameraMetadata::writeToParcel(Parcel *parcel) const {
567 
568     ALOGV("%s: parcel = %p", __FUNCTION__, parcel);
569 
570     if (parcel == NULL) {
571         ALOGE("%s: parcel is null", __FUNCTION__);
572         return BAD_VALUE;
573     }
574 
575     return CameraMetadata::writeToParcel(*parcel, mBuffer);
576 }
577 
swap(CameraMetadata & other)578 void CameraMetadata::swap(CameraMetadata& other) {
579     if (mLocked) {
580         ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
581         return;
582     } else if (other.mLocked) {
583         ALOGE("%s: Other CameraMetadata is locked", __FUNCTION__);
584         return;
585     }
586 
587     camera_metadata* thisBuf = mBuffer;
588     camera_metadata* otherBuf = other.mBuffer;
589 
590     other.mBuffer = thisBuf;
591     mBuffer = otherBuf;
592 }
593 
594 }; // namespace android
595