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