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