CameraMetadata.cpp revision fd6ecdd39bd83ea020f78b425e96310380d66c35
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
28typedef Parcel::WritableBlob WritableBlob;
29typedef Parcel::ReadableBlob ReadableBlob;
30
31CameraMetadata::CameraMetadata() :
32        mBuffer(NULL), mLocked(false) {
33}
34
35CameraMetadata::CameraMetadata(size_t entryCapacity, size_t dataCapacity) :
36        mLocked(false)
37{
38    mBuffer = allocate_camera_metadata(entryCapacity, dataCapacity);
39}
40
41CameraMetadata::CameraMetadata(const CameraMetadata &other) :
42        mLocked(false) {
43    mBuffer = clone_camera_metadata(other.mBuffer);
44}
45
46CameraMetadata::CameraMetadata(camera_metadata_t *buffer) :
47        mBuffer(NULL), mLocked(false) {
48    acquire(buffer);
49}
50
51CameraMetadata &CameraMetadata::operator=(const CameraMetadata &other) {
52    return operator=(other.mBuffer);
53}
54
55CameraMetadata &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
69CameraMetadata::~CameraMetadata() {
70    mLocked = false;
71    clear();
72}
73
74const camera_metadata_t* CameraMetadata::getAndLock() {
75    mLocked = true;
76    return mBuffer;
77}
78
79status_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
93camera_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
103void 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
114void 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
127void CameraMetadata::acquire(CameraMetadata &other) {
128    if (mLocked) {
129        ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
130        return;
131    }
132    acquire(other.release());
133}
134
135status_t CameraMetadata::append(const CameraMetadata &other) {
136    return append(other.mBuffer);
137}
138
139status_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
151size_t CameraMetadata::entryCount() const {
152    return (mBuffer == NULL) ? 0 :
153            get_camera_metadata_entry_count(mBuffer);
154}
155
156bool CameraMetadata::isEmpty() const {
157    return entryCount() == 0;
158}
159
160status_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
168status_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
185status_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
198status_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
211status_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
224status_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
237status_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
250status_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
263status_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
276status_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
322bool 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
327camera_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
343camera_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
354status_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
381void CameraMetadata::dump(int fd, int verbosity, int indentation) const {
382    dump_indented_camera_metadata(mBuffer, fd, verbosity, indentation);
383}
384
385status_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
423status_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
484status_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
534status_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
566status_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
578void 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