CameraMetadata.cpp revision 1a93f0cbb99fc5a59c92bd913f29409022ae236d
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    // string.size() doesn't count the null termination character.
277    return updateImpl(tag, (const void*)string.string(), string.size() + 1);
278}
279
280status_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
326bool 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
331camera_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
347camera_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
358status_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
385void CameraMetadata::dump(int fd, int verbosity, int indentation) const {
386    dump_indented_camera_metadata(mBuffer, fd, verbosity, indentation);
387}
388
389status_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
427status_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
518status_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
613status_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
645status_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
657void 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