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 #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()77 const camera_metadata_t* CameraMetadata::getAndLock() {
78 mLocked = true;
79 return mBuffer;
80 }
81
unlock(const camera_metadata_t * buffer)82 status_t CameraMetadata::unlock(const camera_metadata_t *buffer) {
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_camera_metadata_tag_type(tag);
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_camera_metadata_tag_name(tag), 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
updateImpl(uint32_t tag,const void * data,size_t data_count)280 status_t CameraMetadata::updateImpl(uint32_t tag, const void *data,
281 size_t data_count) {
282 status_t res;
283 if (mLocked) {
284 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
285 return INVALID_OPERATION;
286 }
287 int type = get_camera_metadata_tag_type(tag);
288 if (type == -1) {
289 ALOGE("%s: Tag %d not found", __FUNCTION__, tag);
290 return BAD_VALUE;
291 }
292 size_t data_size = calculate_camera_metadata_entry_data_size(type,
293 data_count);
294
295 res = resizeIfNeeded(1, data_size);
296
297 if (res == OK) {
298 camera_metadata_entry_t entry;
299 res = find_camera_metadata_entry(mBuffer, tag, &entry);
300 if (res == NAME_NOT_FOUND) {
301 res = add_camera_metadata_entry(mBuffer,
302 tag, data, data_count);
303 } else if (res == OK) {
304 res = update_camera_metadata_entry(mBuffer,
305 entry.index, data, data_count, NULL);
306 }
307 }
308
309 if (res != OK) {
310 ALOGE("%s: Unable to update metadata entry %s.%s (%x): %s (%d)",
311 __FUNCTION__, get_camera_metadata_section_name(tag),
312 get_camera_metadata_tag_name(tag), tag, strerror(-res), res);
313 }
314
315 IF_ALOGV() {
316 ALOGE_IF(validate_camera_metadata_structure(mBuffer, /*size*/NULL) !=
317 OK,
318
319 "%s: Failed to validate metadata structure after update %p",
320 __FUNCTION__, mBuffer);
321 }
322
323 return res;
324 }
325
exists(uint32_t tag) const326 bool CameraMetadata::exists(uint32_t tag) const {
327 camera_metadata_ro_entry entry;
328 return find_camera_metadata_ro_entry(mBuffer, tag, &entry) == 0;
329 }
330
find(uint32_t tag)331 camera_metadata_entry_t CameraMetadata::find(uint32_t tag) {
332 status_t res;
333 camera_metadata_entry entry;
334 if (mLocked) {
335 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
336 entry.count = 0;
337 return entry;
338 }
339 res = find_camera_metadata_entry(mBuffer, tag, &entry);
340 if (CC_UNLIKELY( res != OK )) {
341 entry.count = 0;
342 entry.data.u8 = NULL;
343 }
344 return entry;
345 }
346
find(uint32_t tag) const347 camera_metadata_ro_entry_t CameraMetadata::find(uint32_t tag) const {
348 status_t res;
349 camera_metadata_ro_entry entry;
350 res = find_camera_metadata_ro_entry(mBuffer, tag, &entry);
351 if (CC_UNLIKELY( res != OK )) {
352 entry.count = 0;
353 entry.data.u8 = NULL;
354 }
355 return entry;
356 }
357
erase(uint32_t tag)358 status_t CameraMetadata::erase(uint32_t tag) {
359 camera_metadata_entry_t entry;
360 status_t res;
361 if (mLocked) {
362 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
363 return INVALID_OPERATION;
364 }
365 res = find_camera_metadata_entry(mBuffer, tag, &entry);
366 if (res == NAME_NOT_FOUND) {
367 return OK;
368 } else if (res != OK) {
369 ALOGE("%s: Error looking for entry %s.%s (%x): %s %d",
370 __FUNCTION__,
371 get_camera_metadata_section_name(tag),
372 get_camera_metadata_tag_name(tag), tag, strerror(-res), res);
373 return res;
374 }
375 res = delete_camera_metadata_entry(mBuffer, entry.index);
376 if (res != OK) {
377 ALOGE("%s: Error deleting entry %s.%s (%x): %s %d",
378 __FUNCTION__,
379 get_camera_metadata_section_name(tag),
380 get_camera_metadata_tag_name(tag), tag, strerror(-res), res);
381 }
382 return res;
383 }
384
dump(int fd,int verbosity,int indentation) const385 void CameraMetadata::dump(int fd, int verbosity, int indentation) const {
386 dump_indented_camera_metadata(mBuffer, fd, verbosity, indentation);
387 }
388
resizeIfNeeded(size_t extraEntries,size_t extraData)389 status_t CameraMetadata::resizeIfNeeded(size_t extraEntries, size_t extraData) {
390 if (mBuffer == NULL) {
391 mBuffer = allocate_camera_metadata(extraEntries * 2, extraData * 2);
392 if (mBuffer == NULL) {
393 ALOGE("%s: Can't allocate larger metadata buffer", __FUNCTION__);
394 return NO_MEMORY;
395 }
396 } else {
397 size_t currentEntryCount = get_camera_metadata_entry_count(mBuffer);
398 size_t currentEntryCap = get_camera_metadata_entry_capacity(mBuffer);
399 size_t newEntryCount = currentEntryCount +
400 extraEntries;
401 newEntryCount = (newEntryCount > currentEntryCap) ?
402 newEntryCount * 2 : currentEntryCap;
403
404 size_t currentDataCount = get_camera_metadata_data_count(mBuffer);
405 size_t currentDataCap = get_camera_metadata_data_capacity(mBuffer);
406 size_t newDataCount = currentDataCount +
407 extraData;
408 newDataCount = (newDataCount > currentDataCap) ?
409 newDataCount * 2 : currentDataCap;
410
411 if (newEntryCount > currentEntryCap ||
412 newDataCount > currentDataCap) {
413 camera_metadata_t *oldBuffer = mBuffer;
414 mBuffer = allocate_camera_metadata(newEntryCount,
415 newDataCount);
416 if (mBuffer == NULL) {
417 ALOGE("%s: Can't allocate larger metadata buffer", __FUNCTION__);
418 return NO_MEMORY;
419 }
420 append_camera_metadata(mBuffer, oldBuffer);
421 free_camera_metadata(oldBuffer);
422 }
423 }
424 return OK;
425 }
426
readFromParcel(const Parcel & data,camera_metadata_t ** out)427 status_t CameraMetadata::readFromParcel(const Parcel& data,
428 camera_metadata_t** out) {
429
430 status_t err = OK;
431
432 camera_metadata_t* metadata = NULL;
433
434 if (out) {
435 *out = NULL;
436 }
437
438 // See CameraMetadata::writeToParcel for parcel data layout diagram and explanation.
439 // arg0 = blobSize (int32)
440 int32_t blobSizeTmp = -1;
441 if ((err = data.readInt32(&blobSizeTmp)) != OK) {
442 ALOGE("%s: Failed to read metadata size (error %d %s)",
443 __FUNCTION__, err, strerror(-err));
444 return err;
445 }
446 const size_t blobSize = static_cast<size_t>(blobSizeTmp);
447 const size_t alignment = get_camera_metadata_alignment();
448
449 // Special case: zero blob size means zero sized (NULL) metadata.
450 if (blobSize == 0) {
451 ALOGV("%s: Read 0-sized metadata", __FUNCTION__);
452 return OK;
453 }
454
455 if (blobSize <= alignment) {
456 ALOGE("%s: metadata blob is malformed, blobSize(%zu) should be larger than alignment(%zu)",
457 __FUNCTION__, blobSize, alignment);
458 return BAD_VALUE;
459 }
460
461 const size_t metadataSize = blobSize - alignment;
462
463 // NOTE: this doesn't make sense to me. shouldn't the blob
464 // know how big it is? why do we have to specify the size
465 // to Parcel::readBlob ?
466 ReadableBlob blob;
467 // arg1 = metadata (blob)
468 do {
469 if ((err = data.readBlob(blobSize, &blob)) != OK) {
470 ALOGE("%s: Failed to read metadata blob (sized %zu). Possible "
471 " serialization bug. Error %d %s",
472 __FUNCTION__, blobSize, err, strerror(-err));
473 break;
474 }
475
476 // arg2 = offset (blob)
477 // Must be after blob since we don't know offset until after writeBlob.
478 int32_t offsetTmp;
479 if ((err = data.readInt32(&offsetTmp)) != OK) {
480 ALOGE("%s: Failed to read metadata offsetTmp (error %d %s)",
481 __FUNCTION__, err, strerror(-err));
482 break;
483 }
484 const size_t offset = static_cast<size_t>(offsetTmp);
485 if (offset >= alignment) {
486 ALOGE("%s: metadata offset(%zu) should be less than alignment(%zu)",
487 __FUNCTION__, blobSize, alignment);
488 err = BAD_VALUE;
489 break;
490 }
491
492 const uintptr_t metadataStart = reinterpret_cast<uintptr_t>(blob.data()) + offset;
493 const camera_metadata_t* tmp =
494 reinterpret_cast<const camera_metadata_t*>(metadataStart);
495 ALOGV("%s: alignment is: %zu, metadata start: %p, offset: %zu",
496 __FUNCTION__, alignment, tmp, offset);
497 metadata = allocate_copy_camera_metadata_checked(tmp, metadataSize);
498 if (metadata == NULL) {
499 // We consider that allocation only fails if the validation
500 // also failed, therefore the readFromParcel was a failure.
501 ALOGE("%s: metadata allocation and copy failed", __FUNCTION__);
502 err = BAD_VALUE;
503 }
504 } while(0);
505 blob.release();
506
507 if (out) {
508 ALOGV("%s: Set out metadata to %p", __FUNCTION__, metadata);
509 *out = metadata;
510 } else if (metadata != NULL) {
511 ALOGV("%s: Freed camera metadata at %p", __FUNCTION__, metadata);
512 free_camera_metadata(metadata);
513 }
514
515 return err;
516 }
517
writeToParcel(Parcel & data,const camera_metadata_t * metadata)518 status_t CameraMetadata::writeToParcel(Parcel& data,
519 const camera_metadata_t* metadata) {
520 status_t res = OK;
521
522 /**
523 * Below is the camera metadata parcel layout:
524 *
525 * |--------------------------------------------|
526 * | arg0: blobSize |
527 * | (length = 4) |
528 * |--------------------------------------------|<--Skip the rest if blobSize == 0.
529 * | |
530 * | |
531 * | arg1: blob |
532 * | (length = variable, see arg1 layout below) |
533 * | |
534 * | |
535 * |--------------------------------------------|
536 * | arg2: offset |
537 * | (length = 4) |
538 * |--------------------------------------------|
539 */
540
541 // arg0 = blobSize (int32)
542 if (metadata == NULL) {
543 // Write zero blobSize for null metadata.
544 return data.writeInt32(0);
545 }
546
547 /**
548 * Always make the blob size sufficiently larger, as we need put alignment
549 * padding and metadata into the blob. Since we don't know the alignment
550 * offset before writeBlob. Then write the metadata to aligned offset.
551 */
552 const size_t metadataSize = get_camera_metadata_compact_size(metadata);
553 const size_t alignment = get_camera_metadata_alignment();
554 const size_t blobSize = metadataSize + alignment;
555 res = data.writeInt32(static_cast<int32_t>(blobSize));
556 if (res != OK) {
557 return res;
558 }
559
560 size_t offset = 0;
561 /**
562 * arg1 = metadata (blob).
563 *
564 * The blob size is the sum of front padding size, metadata size and back padding
565 * size, which is equal to metadataSize + alignment.
566 *
567 * The blob layout is:
568 * |------------------------------------|<----Start address of the blob (unaligned).
569 * | front padding |
570 * | (size = offset) |
571 * |------------------------------------|<----Aligned start address of metadata.
572 * | |
573 * | |
574 * | metadata |
575 * | (size = metadataSize) |
576 * | |
577 * | |
578 * |------------------------------------|
579 * | back padding |
580 * | (size = alignment - offset) |
581 * |------------------------------------|<----End address of blob.
582 * (Blob start address + blob size).
583 */
584 WritableBlob blob;
585 do {
586 res = data.writeBlob(blobSize, &blob);
587 if (res != OK) {
588 break;
589 }
590 const uintptr_t metadataStart = ALIGN_TO(blob.data(), alignment);
591 offset = metadataStart - reinterpret_cast<uintptr_t>(blob.data());
592 ALOGV("%s: alignment is: %zu, metadata start: %p, offset: %zu",
593 __FUNCTION__, alignment,
594 reinterpret_cast<const void *>(metadataStart), offset);
595 copy_camera_metadata(reinterpret_cast<void*>(metadataStart), metadataSize, metadata);
596
597 // Not too big of a problem since receiving side does hard validation
598 // Don't check the size since the compact size could be larger
599 if (validate_camera_metadata_structure(metadata, /*size*/NULL) != OK) {
600 ALOGW("%s: Failed to validate metadata %p before writing blob",
601 __FUNCTION__, metadata);
602 }
603
604 } while(false);
605 blob.release();
606
607 // arg2 = offset (int32)
608 res = data.writeInt32(static_cast<int32_t>(offset));
609
610 return res;
611 }
612
readFromParcel(Parcel * parcel)613 status_t CameraMetadata::readFromParcel(Parcel *parcel) {
614
615 ALOGV("%s: parcel = %p", __FUNCTION__, parcel);
616
617 status_t res = OK;
618
619 if (parcel == NULL) {
620 ALOGE("%s: parcel is null", __FUNCTION__);
621 return BAD_VALUE;
622 }
623
624 if (mLocked) {
625 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
626 return INVALID_OPERATION;
627 }
628
629 camera_metadata *buffer = NULL;
630 // TODO: reading should return a status code, in case validation fails
631 res = CameraMetadata::readFromParcel(*parcel, &buffer);
632
633 if (res != NO_ERROR) {
634 ALOGE("%s: Failed to read from parcel. Metadata is unchanged.",
635 __FUNCTION__);
636 return res;
637 }
638
639 clear();
640 mBuffer = buffer;
641
642 return OK;
643 }
644
writeToParcel(Parcel * parcel) const645 status_t CameraMetadata::writeToParcel(Parcel *parcel) const {
646
647 ALOGV("%s: parcel = %p", __FUNCTION__, parcel);
648
649 if (parcel == NULL) {
650 ALOGE("%s: parcel is null", __FUNCTION__);
651 return BAD_VALUE;
652 }
653
654 return CameraMetadata::writeToParcel(*parcel, mBuffer);
655 }
656
swap(CameraMetadata & other)657 void CameraMetadata::swap(CameraMetadata& other) {
658 if (mLocked) {
659 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
660 return;
661 } else if (other.mLocked) {
662 ALOGE("%s: Other CameraMetadata is locked", __FUNCTION__);
663 return;
664 }
665
666 camera_metadata* thisBuf = mBuffer;
667 camera_metadata* otherBuf = other.mBuffer;
668
669 other.mBuffer = thisBuf;
670 mBuffer = otherBuf;
671 }
672
673 }; // namespace android
674