2 * Copyright (C) 2012 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 // #define LOG_NDEBUG 0
19 #define LOG_TAG "Camera2-Metadata"
20 #include <utils/Log.h>
21 #include <utils/Errors.h>
23 #include <camera/CameraMetadata.h>
24 #include <binder/Parcel.h>
28 #define ALIGN_TO(val, alignment) \
29 (((uintptr_t)(val) + ((alignment) - 1)) & ~((alignment) - 1))
31 typedef Parcel::WritableBlob WritableBlob;
32 typedef Parcel::ReadableBlob ReadableBlob;
34 CameraMetadata::CameraMetadata() :
35 mBuffer(NULL), mLocked(false) {
38 CameraMetadata::CameraMetadata(size_t entryCapacity, size_t dataCapacity) :
41 mBuffer = allocate_camera_metadata(entryCapacity, dataCapacity);
44 CameraMetadata::CameraMetadata(const CameraMetadata &other) :
46 mBuffer = clone_camera_metadata(other.mBuffer);
49 CameraMetadata::CameraMetadata(camera_metadata_t *buffer) :
50 mBuffer(NULL), mLocked(false) {
54 CameraMetadata &CameraMetadata::operator=(const CameraMetadata &other) {
55 return operator=(other.mBuffer);
58 CameraMetadata &CameraMetadata::operator=(const camera_metadata_t *buffer) {
60 ALOGE("%s: Assignment to a locked CameraMetadata!", __FUNCTION__);
64 if (CC_LIKELY(buffer != mBuffer)) {
65 camera_metadata_t *newBuffer = clone_camera_metadata(buffer);
72 CameraMetadata::~CameraMetadata() {
77 const camera_metadata_t* CameraMetadata::getAndLock() const {
82 status_t CameraMetadata::unlock(const camera_metadata_t *buffer) {
84 ALOGE("%s: Can't unlock a non-locked CameraMetadata!", __FUNCTION__);
85 return INVALID_OPERATION;
87 if (buffer != mBuffer) {
88 ALOGE("%s: Can't unlock CameraMetadata with wrong pointer!",
96 camera_metadata_t* CameraMetadata::release() {
98 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
101 camera_metadata_t *released = mBuffer;
106 void CameraMetadata::clear() {
108 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
112 free_camera_metadata(mBuffer);
117 void CameraMetadata::acquire(camera_metadata_t *buffer) {
119 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
125 ALOGE_IF(validate_camera_metadata_structure(mBuffer, /*size*/NULL) != OK,
126 "%s: Failed to validate metadata structure %p",
127 __FUNCTION__, buffer);
130 void CameraMetadata::acquire(CameraMetadata &other) {
132 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
135 acquire(other.release());
138 status_t CameraMetadata::append(const CameraMetadata &other) {
139 return append(other.mBuffer);
142 status_t CameraMetadata::append(const camera_metadata_t* other) {
144 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
145 return INVALID_OPERATION;
147 size_t extraEntries = get_camera_metadata_entry_count(other);
148 size_t extraData = get_camera_metadata_data_count(other);
149 resizeIfNeeded(extraEntries, extraData);
151 return append_camera_metadata(mBuffer, other);
154 size_t CameraMetadata::entryCount() const {
155 return (mBuffer == NULL) ? 0 :
156 get_camera_metadata_entry_count(mBuffer);
159 bool CameraMetadata::isEmpty() const {
160 return entryCount() == 0;
163 status_t CameraMetadata::sort() {
165 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
166 return INVALID_OPERATION;
168 return sort_camera_metadata(mBuffer);
171 status_t CameraMetadata::checkType(uint32_t tag, uint8_t expectedType) {
172 int tagType = get_camera_metadata_tag_type(tag);
173 if ( CC_UNLIKELY(tagType == -1)) {
174 ALOGE("Update metadata entry: Unknown tag %d", tag);
175 return INVALID_OPERATION;
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_camera_metadata_tag_name(tag), tag,
181 camera_metadata_type_names[tagType],
182 camera_metadata_type_names[expectedType]);
183 return INVALID_OPERATION;
188 status_t CameraMetadata::update(uint32_t tag,
189 const int32_t *data, size_t data_count) {
192 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
193 return INVALID_OPERATION;
195 if ( (res = checkType(tag, TYPE_INT32)) != OK) {
198 return updateImpl(tag, (const void*)data, data_count);
201 status_t CameraMetadata::update(uint32_t tag,
202 const uint8_t *data, size_t data_count) {
205 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
206 return INVALID_OPERATION;
208 if ( (res = checkType(tag, TYPE_BYTE)) != OK) {
211 return updateImpl(tag, (const void*)data, data_count);
214 status_t CameraMetadata::update(uint32_t tag,
215 const float *data, size_t data_count) {
218 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
219 return INVALID_OPERATION;
221 if ( (res = checkType(tag, TYPE_FLOAT)) != OK) {
224 return updateImpl(tag, (const void*)data, data_count);
227 status_t CameraMetadata::update(uint32_t tag,
228 const int64_t *data, size_t data_count) {
231 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
232 return INVALID_OPERATION;
234 if ( (res = checkType(tag, TYPE_INT64)) != OK) {
237 return updateImpl(tag, (const void*)data, data_count);
240 status_t CameraMetadata::update(uint32_t tag,
241 const double *data, size_t data_count) {
244 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
245 return INVALID_OPERATION;
247 if ( (res = checkType(tag, TYPE_DOUBLE)) != OK) {
250 return updateImpl(tag, (const void*)data, data_count);
253 status_t CameraMetadata::update(uint32_t tag,
254 const camera_metadata_rational_t *data, size_t data_count) {
257 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
258 return INVALID_OPERATION;
260 if ( (res = checkType(tag, TYPE_RATIONAL)) != OK) {
263 return updateImpl(tag, (const void*)data, data_count);
266 status_t CameraMetadata::update(uint32_t tag,
267 const String8 &string) {
270 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
271 return INVALID_OPERATION;
273 if ( (res = checkType(tag, TYPE_BYTE)) != OK) {
276 // string.size() doesn't count the null termination character.
277 return updateImpl(tag, (const void*)string.string(), string.size() + 1);
280 status_t CameraMetadata::updateImpl(uint32_t tag, const void *data,
284 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
285 return INVALID_OPERATION;
287 int type = get_camera_metadata_tag_type(tag);
289 ALOGE("%s: Tag %d not found", __FUNCTION__, tag);
292 // Safety check - ensure that data isn't pointing to this metadata, since
293 // that would get invalidated if a resize is needed
294 size_t bufferSize = get_camera_metadata_size(mBuffer);
295 uintptr_t bufAddr = reinterpret_cast<uintptr_t>(mBuffer);
296 uintptr_t dataAddr = reinterpret_cast<uintptr_t>(data);
297 if (dataAddr > bufAddr && dataAddr < (bufAddr + bufferSize)) {
298 ALOGE("%s: Update attempted with data from the same metadata buffer!",
300 return INVALID_OPERATION;
303 size_t data_size = calculate_camera_metadata_entry_data_size(type,
306 res = resizeIfNeeded(1, data_size);
309 camera_metadata_entry_t entry;
310 res = find_camera_metadata_entry(mBuffer, tag, &entry);
311 if (res == NAME_NOT_FOUND) {
312 res = add_camera_metadata_entry(mBuffer,
313 tag, data, data_count);
314 } else if (res == OK) {
315 res = update_camera_metadata_entry(mBuffer,
316 entry.index, data, data_count, NULL);
321 ALOGE("%s: Unable to update metadata entry %s.%s (%x): %s (%d)",
322 __FUNCTION__, get_camera_metadata_section_name(tag),
323 get_camera_metadata_tag_name(tag), tag, strerror(-res), res);
327 ALOGE_IF(validate_camera_metadata_structure(mBuffer, /*size*/NULL) !=
330 "%s: Failed to validate metadata structure after update %p",
331 __FUNCTION__, mBuffer);
337 bool CameraMetadata::exists(uint32_t tag) const {
338 camera_metadata_ro_entry entry;
339 return find_camera_metadata_ro_entry(mBuffer, tag, &entry) == 0;
342 camera_metadata_entry_t CameraMetadata::find(uint32_t tag) {
344 camera_metadata_entry entry;
346 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
350 res = find_camera_metadata_entry(mBuffer, tag, &entry);
351 if (CC_UNLIKELY( res != OK )) {
353 entry.data.u8 = NULL;
358 camera_metadata_ro_entry_t CameraMetadata::find(uint32_t tag) const {
360 camera_metadata_ro_entry entry;
361 res = find_camera_metadata_ro_entry(mBuffer, tag, &entry);
362 if (CC_UNLIKELY( res != OK )) {
364 entry.data.u8 = NULL;
369 status_t CameraMetadata::erase(uint32_t tag) {
370 camera_metadata_entry_t entry;
373 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
374 return INVALID_OPERATION;
376 res = find_camera_metadata_entry(mBuffer, tag, &entry);
377 if (res == NAME_NOT_FOUND) {
379 } else if (res != OK) {
380 ALOGE("%s: Error looking for entry %s.%s (%x): %s %d",
382 get_camera_metadata_section_name(tag),
383 get_camera_metadata_tag_name(tag), tag, strerror(-res), res);
386 res = delete_camera_metadata_entry(mBuffer, entry.index);
388 ALOGE("%s: Error deleting entry %s.%s (%x): %s %d",
390 get_camera_metadata_section_name(tag),
391 get_camera_metadata_tag_name(tag), tag, strerror(-res), res);
396 void CameraMetadata::dump(int fd, int verbosity, int indentation) const {
397 dump_indented_camera_metadata(mBuffer, fd, verbosity, indentation);
400 status_t CameraMetadata::resizeIfNeeded(size_t extraEntries, size_t extraData) {
401 if (mBuffer == NULL) {
402 mBuffer = allocate_camera_metadata(extraEntries * 2, extraData * 2);
403 if (mBuffer == NULL) {
404 ALOGE("%s: Can't allocate larger metadata buffer", __FUNCTION__);
408 size_t currentEntryCount = get_camera_metadata_entry_count(mBuffer);
409 size_t currentEntryCap = get_camera_metadata_entry_capacity(mBuffer);
410 size_t newEntryCount = currentEntryCount +
412 newEntryCount = (newEntryCount > currentEntryCap) ?
413 newEntryCount * 2 : currentEntryCap;
415 size_t currentDataCount = get_camera_metadata_data_count(mBuffer);
416 size_t currentDataCap = get_camera_metadata_data_capacity(mBuffer);
417 size_t newDataCount = currentDataCount +
419 newDataCount = (newDataCount > currentDataCap) ?
420 newDataCount * 2 : currentDataCap;
422 if (newEntryCount > currentEntryCap ||
423 newDataCount > currentDataCap) {
424 camera_metadata_t *oldBuffer = mBuffer;
425 mBuffer = allocate_camera_metadata(newEntryCount,
427 if (mBuffer == NULL) {
428 ALOGE("%s: Can't allocate larger metadata buffer", __FUNCTION__);
431 append_camera_metadata(mBuffer, oldBuffer);
432 free_camera_metadata(oldBuffer);
438 status_t CameraMetadata::readFromParcel(const Parcel& data,
439 camera_metadata_t** out) {
443 camera_metadata_t* metadata = NULL;
449 // See CameraMetadata::writeToParcel for parcel data layout diagram and explanation.
450 // arg0 = blobSize (int32)
451 int32_t blobSizeTmp = -1;
452 if ((err = data.readInt32(&blobSizeTmp)) != OK) {
453 ALOGE("%s: Failed to read metadata size (error %d %s)",
454 __FUNCTION__, err, strerror(-err));
457 const size_t blobSize = static_cast<size_t>(blobSizeTmp);
458 const size_t alignment = get_camera_metadata_alignment();
460 // Special case: zero blob size means zero sized (NULL) metadata.
462 ALOGV("%s: Read 0-sized metadata", __FUNCTION__);
466 if (blobSize <= alignment) {
467 ALOGE("%s: metadata blob is malformed, blobSize(%zu) should be larger than alignment(%zu)",
468 __FUNCTION__, blobSize, alignment);
472 const size_t metadataSize = blobSize - alignment;
474 // NOTE: this doesn't make sense to me. shouldn't the blob
475 // know how big it is? why do we have to specify the size
476 // to Parcel::readBlob ?
478 // arg1 = metadata (blob)
480 if ((err = data.readBlob(blobSize, &blob)) != OK) {
481 ALOGE("%s: Failed to read metadata blob (sized %zu). Possible "
482 " serialization bug. Error %d %s",
483 __FUNCTION__, blobSize, err, strerror(-err));
487 // arg2 = offset (blob)
488 // Must be after blob since we don't know offset until after writeBlob.
490 if ((err = data.readInt32(&offsetTmp)) != OK) {
491 ALOGE("%s: Failed to read metadata offsetTmp (error %d %s)",
492 __FUNCTION__, err, strerror(-err));
495 const size_t offset = static_cast<size_t>(offsetTmp);
496 if (offset >= alignment) {
497 ALOGE("%s: metadata offset(%zu) should be less than alignment(%zu)",
498 __FUNCTION__, blobSize, alignment);
503 const uintptr_t metadataStart = reinterpret_cast<uintptr_t>(blob.data()) + offset;
504 const camera_metadata_t* tmp =
505 reinterpret_cast<const camera_metadata_t*>(metadataStart);
506 ALOGV("%s: alignment is: %zu, metadata start: %p, offset: %zu",
507 __FUNCTION__, alignment, tmp, offset);
508 metadata = allocate_copy_camera_metadata_checked(tmp, metadataSize);
509 if (metadata == NULL) {
510 // We consider that allocation only fails if the validation
511 // also failed, therefore the readFromParcel was a failure.
512 ALOGE("%s: metadata allocation and copy failed", __FUNCTION__);
519 ALOGV("%s: Set out metadata to %p", __FUNCTION__, metadata);
521 } else if (metadata != NULL) {
522 ALOGV("%s: Freed camera metadata at %p", __FUNCTION__, metadata);
523 free_camera_metadata(metadata);
529 status_t CameraMetadata::writeToParcel(Parcel& data,
530 const camera_metadata_t* metadata) {
534 * Below is the camera metadata parcel layout:
536 * |--------------------------------------------|
539 * |--------------------------------------------|<--Skip the rest if blobSize == 0.
543 * | (length = variable, see arg1 layout below) |
546 * |--------------------------------------------|
549 * |--------------------------------------------|
552 // arg0 = blobSize (int32)
553 if (metadata == NULL) {
554 // Write zero blobSize for null metadata.
555 return data.writeInt32(0);
559 * Always make the blob size sufficiently larger, as we need put alignment
560 * padding and metadata into the blob. Since we don't know the alignment
561 * offset before writeBlob. Then write the metadata to aligned offset.
563 const size_t metadataSize = get_camera_metadata_compact_size(metadata);
564 const size_t alignment = get_camera_metadata_alignment();
565 const size_t blobSize = metadataSize + alignment;
566 res = data.writeInt32(static_cast<int32_t>(blobSize));
573 * arg1 = metadata (blob).
575 * The blob size is the sum of front padding size, metadata size and back padding
576 * size, which is equal to metadataSize + alignment.
578 * The blob layout is:
579 * |------------------------------------|<----Start address of the blob (unaligned).
581 * | (size = offset) |
582 * |------------------------------------|<----Aligned start address of metadata.
586 * | (size = metadataSize) |
589 * |------------------------------------|
591 * | (size = alignment - offset) |
592 * |------------------------------------|<----End address of blob.
593 * (Blob start address + blob size).
597 res = data.writeBlob(blobSize, false, &blob);
601 const uintptr_t metadataStart = ALIGN_TO(blob.data(), alignment);
602 offset = metadataStart - reinterpret_cast<uintptr_t>(blob.data());
603 ALOGV("%s: alignment is: %zu, metadata start: %p, offset: %zu",
604 __FUNCTION__, alignment,
605 reinterpret_cast<const void *>(metadataStart), offset);
606 copy_camera_metadata(reinterpret_cast<void*>(metadataStart), metadataSize, metadata);
608 // Not too big of a problem since receiving side does hard validation
609 // Don't check the size since the compact size could be larger
610 if (validate_camera_metadata_structure(metadata, /*size*/NULL) != OK) {
611 ALOGW("%s: Failed to validate metadata %p before writing blob",
612 __FUNCTION__, metadata);
618 // arg2 = offset (int32)
619 res = data.writeInt32(static_cast<int32_t>(offset));
624 status_t CameraMetadata::readFromParcel(Parcel *parcel) {
626 ALOGV("%s: parcel = %p", __FUNCTION__, parcel);
630 if (parcel == NULL) {
631 ALOGE("%s: parcel is null", __FUNCTION__);
636 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
637 return INVALID_OPERATION;
640 camera_metadata *buffer = NULL;
641 // TODO: reading should return a status code, in case validation fails
642 res = CameraMetadata::readFromParcel(*parcel, &buffer);
644 if (res != NO_ERROR) {
645 ALOGE("%s: Failed to read from parcel. Metadata is unchanged.",
656 status_t CameraMetadata::writeToParcel(Parcel *parcel) const {
658 ALOGV("%s: parcel = %p", __FUNCTION__, parcel);
660 if (parcel == NULL) {
661 ALOGE("%s: parcel is null", __FUNCTION__);
665 return CameraMetadata::writeToParcel(*parcel, mBuffer);
668 void CameraMetadata::swap(CameraMetadata& other) {
670 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
672 } else if (other.mLocked) {
673 ALOGE("%s: Other CameraMetadata is locked", __FUNCTION__);
677 camera_metadata* thisBuf = mBuffer;
678 camera_metadata* otherBuf = other.mBuffer;
680 other.mBuffer = thisBuf;
684 }; // namespace android