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