1/*
2 * Copyright (C) 2016 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 "CamComm1.0-MD"
20#include <log/log.h>
21#include <utils/Errors.h>
22
23#include "CameraMetadata.h"
24#include "VendorTagDescriptor.h"
25
26namespace android {
27namespace hardware {
28namespace camera {
29namespace common {
30namespace V1_0 {
31namespace helper {
32
33#define ALIGN_TO(val, alignment) \
34    (((uintptr_t)(val) + ((alignment) - 1)) & ~((alignment) - 1))
35
36CameraMetadata::CameraMetadata() :
37        mBuffer(NULL), mLocked(false) {
38}
39
40CameraMetadata::CameraMetadata(size_t entryCapacity, size_t dataCapacity) :
41        mLocked(false)
42{
43    mBuffer = allocate_camera_metadata(entryCapacity, dataCapacity);
44}
45
46CameraMetadata::CameraMetadata(const CameraMetadata &other) :
47        mLocked(false) {
48    mBuffer = clone_camera_metadata(other.mBuffer);
49}
50
51CameraMetadata::CameraMetadata(camera_metadata_t *buffer) :
52        mBuffer(NULL), mLocked(false) {
53    acquire(buffer);
54}
55
56CameraMetadata &CameraMetadata::operator=(const CameraMetadata &other) {
57    return operator=(other.mBuffer);
58}
59
60CameraMetadata &CameraMetadata::operator=(const camera_metadata_t *buffer) {
61    if (mLocked) {
62        ALOGE("%s: Assignment to a locked CameraMetadata!", __FUNCTION__);
63        return *this;
64    }
65
66    if (CC_LIKELY(buffer != mBuffer)) {
67        camera_metadata_t *newBuffer = clone_camera_metadata(buffer);
68        clear();
69        mBuffer = newBuffer;
70    }
71    return *this;
72}
73
74CameraMetadata::~CameraMetadata() {
75    mLocked = false;
76    clear();
77}
78
79const camera_metadata_t* CameraMetadata::getAndLock() const {
80    mLocked = true;
81    return mBuffer;
82}
83
84status_t CameraMetadata::unlock(const camera_metadata_t *buffer) const {
85    if (!mLocked) {
86        ALOGE("%s: Can't unlock a non-locked CameraMetadata!", __FUNCTION__);
87        return INVALID_OPERATION;
88    }
89    if (buffer != mBuffer) {
90        ALOGE("%s: Can't unlock CameraMetadata with wrong pointer!",
91                __FUNCTION__);
92        return BAD_VALUE;
93    }
94    mLocked = false;
95    return OK;
96}
97
98camera_metadata_t* CameraMetadata::release() {
99    if (mLocked) {
100        ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
101        return NULL;
102    }
103    camera_metadata_t *released = mBuffer;
104    mBuffer = NULL;
105    return released;
106}
107
108void CameraMetadata::clear() {
109    if (mLocked) {
110        ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
111        return;
112    }
113    if (mBuffer) {
114        free_camera_metadata(mBuffer);
115        mBuffer = NULL;
116    }
117}
118
119void CameraMetadata::acquire(camera_metadata_t *buffer) {
120    if (mLocked) {
121        ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
122        return;
123    }
124    clear();
125    mBuffer = buffer;
126
127    ALOGE_IF(validate_camera_metadata_structure(mBuffer, /*size*/NULL) != OK,
128             "%s: Failed to validate metadata structure %p",
129             __FUNCTION__, buffer);
130}
131
132void CameraMetadata::acquire(CameraMetadata &other) {
133    if (mLocked) {
134        ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
135        return;
136    }
137    acquire(other.release());
138}
139
140status_t CameraMetadata::append(const CameraMetadata &other) {
141    return append(other.mBuffer);
142}
143
144status_t CameraMetadata::append(const camera_metadata_t* other) {
145    if (mLocked) {
146        ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
147        return INVALID_OPERATION;
148    }
149    size_t extraEntries = get_camera_metadata_entry_count(other);
150    size_t extraData = get_camera_metadata_data_count(other);
151    resizeIfNeeded(extraEntries, extraData);
152
153    return append_camera_metadata(mBuffer, other);
154}
155
156size_t CameraMetadata::entryCount() const {
157    return (mBuffer == NULL) ? 0 :
158            get_camera_metadata_entry_count(mBuffer);
159}
160
161bool CameraMetadata::isEmpty() const {
162    return entryCount() == 0;
163}
164
165status_t CameraMetadata::sort() {
166    if (mLocked) {
167        ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
168        return INVALID_OPERATION;
169    }
170    return sort_camera_metadata(mBuffer);
171}
172
173status_t CameraMetadata::checkType(uint32_t tag, uint8_t expectedType) {
174    int tagType = get_camera_metadata_tag_type(tag);
175    if ( CC_UNLIKELY(tagType == -1)) {
176        ALOGE("Update metadata entry: Unknown tag %d", tag);
177        return INVALID_OPERATION;
178    }
179    if ( CC_UNLIKELY(tagType != expectedType) ) {
180        ALOGE("Mismatched tag type when updating entry %s (%d) of type %s; "
181                "got type %s data instead ",
182                get_camera_metadata_tag_name(tag), tag,
183                camera_metadata_type_names[tagType],
184                camera_metadata_type_names[expectedType]);
185        return INVALID_OPERATION;
186    }
187    return OK;
188}
189
190status_t CameraMetadata::update(uint32_t tag,
191        const int32_t *data, size_t data_count) {
192    status_t res;
193    if (mLocked) {
194        ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
195        return INVALID_OPERATION;
196    }
197    if ( (res = checkType(tag, TYPE_INT32)) != OK) {
198        return res;
199    }
200    return updateImpl(tag, (const void*)data, data_count);
201}
202
203status_t CameraMetadata::update(uint32_t tag,
204        const uint8_t *data, size_t data_count) {
205    status_t res;
206    if (mLocked) {
207        ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
208        return INVALID_OPERATION;
209    }
210    if ( (res = checkType(tag, TYPE_BYTE)) != OK) {
211        return res;
212    }
213    return updateImpl(tag, (const void*)data, data_count);
214}
215
216status_t CameraMetadata::update(uint32_t tag,
217        const float *data, size_t data_count) {
218    status_t res;
219    if (mLocked) {
220        ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
221        return INVALID_OPERATION;
222    }
223    if ( (res = checkType(tag, TYPE_FLOAT)) != OK) {
224        return res;
225    }
226    return updateImpl(tag, (const void*)data, data_count);
227}
228
229status_t CameraMetadata::update(uint32_t tag,
230        const int64_t *data, size_t data_count) {
231    status_t res;
232    if (mLocked) {
233        ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
234        return INVALID_OPERATION;
235    }
236    if ( (res = checkType(tag, TYPE_INT64)) != OK) {
237        return res;
238    }
239    return updateImpl(tag, (const void*)data, data_count);
240}
241
242status_t CameraMetadata::update(uint32_t tag,
243        const double *data, size_t data_count) {
244    status_t res;
245    if (mLocked) {
246        ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
247        return INVALID_OPERATION;
248    }
249    if ( (res = checkType(tag, TYPE_DOUBLE)) != OK) {
250        return res;
251    }
252    return updateImpl(tag, (const void*)data, data_count);
253}
254
255status_t CameraMetadata::update(uint32_t tag,
256        const camera_metadata_rational_t *data, size_t data_count) {
257    status_t res;
258    if (mLocked) {
259        ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
260        return INVALID_OPERATION;
261    }
262    if ( (res = checkType(tag, TYPE_RATIONAL)) != OK) {
263        return res;
264    }
265    return updateImpl(tag, (const void*)data, data_count);
266}
267
268status_t CameraMetadata::update(uint32_t tag,
269        const String8 &string) {
270    status_t res;
271    if (mLocked) {
272        ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
273        return INVALID_OPERATION;
274    }
275    if ( (res = checkType(tag, TYPE_BYTE)) != OK) {
276        return res;
277    }
278    // string.size() doesn't count the null termination character.
279    return updateImpl(tag, (const void*)string.string(), string.size() + 1);
280}
281
282status_t CameraMetadata::update(const camera_metadata_ro_entry &entry) {
283    status_t res;
284    if (mLocked) {
285        ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
286        return INVALID_OPERATION;
287    }
288    if ( (res = checkType(entry.tag, entry.type)) != OK) {
289        return res;
290    }
291    return updateImpl(entry.tag, (const void*)entry.data.u8, entry.count);
292}
293
294status_t CameraMetadata::updateImpl(uint32_t tag, const void *data,
295        size_t data_count) {
296    status_t res;
297    if (mLocked) {
298        ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
299        return INVALID_OPERATION;
300    }
301    int type = get_camera_metadata_tag_type(tag);
302    if (type == -1) {
303        ALOGE("%s: Tag %d not found", __FUNCTION__, tag);
304        return BAD_VALUE;
305    }
306    // Safety check - ensure that data isn't pointing to this metadata, since
307    // that would get invalidated if a resize is needed
308    size_t bufferSize = get_camera_metadata_size(mBuffer);
309    uintptr_t bufAddr = reinterpret_cast<uintptr_t>(mBuffer);
310    uintptr_t dataAddr = reinterpret_cast<uintptr_t>(data);
311    if (dataAddr > bufAddr && dataAddr < (bufAddr + bufferSize)) {
312        ALOGE("%s: Update attempted with data from the same metadata buffer!",
313                __FUNCTION__);
314        return INVALID_OPERATION;
315    }
316
317    size_t data_size = calculate_camera_metadata_entry_data_size(type,
318            data_count);
319
320    res = resizeIfNeeded(1, data_size);
321
322    if (res == OK) {
323        camera_metadata_entry_t entry;
324        res = find_camera_metadata_entry(mBuffer, tag, &entry);
325        if (res == NAME_NOT_FOUND) {
326            res = add_camera_metadata_entry(mBuffer,
327                    tag, data, data_count);
328        } else if (res == OK) {
329            res = update_camera_metadata_entry(mBuffer,
330                    entry.index, data, data_count, NULL);
331        }
332    }
333
334    if (res != OK) {
335        ALOGE("%s: Unable to update metadata entry %s.%s (%x): %s (%d)",
336                __FUNCTION__, get_camera_metadata_section_name(tag),
337                get_camera_metadata_tag_name(tag), tag, strerror(-res), res);
338    }
339
340    IF_ALOGV() {
341        ALOGE_IF(validate_camera_metadata_structure(mBuffer, /*size*/NULL) !=
342                 OK,
343
344                 "%s: Failed to validate metadata structure after update %p",
345                 __FUNCTION__, mBuffer);
346    }
347
348    return res;
349}
350
351bool CameraMetadata::exists(uint32_t tag) const {
352    camera_metadata_ro_entry entry;
353    return find_camera_metadata_ro_entry(mBuffer, tag, &entry) == 0;
354}
355
356camera_metadata_entry_t CameraMetadata::find(uint32_t tag) {
357    status_t res;
358    camera_metadata_entry entry;
359    if (mLocked) {
360        ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
361        entry.count = 0;
362        return entry;
363    }
364    res = find_camera_metadata_entry(mBuffer, tag, &entry);
365    if (CC_UNLIKELY( res != OK )) {
366        entry.count = 0;
367        entry.data.u8 = NULL;
368    }
369    return entry;
370}
371
372camera_metadata_ro_entry_t CameraMetadata::find(uint32_t tag) const {
373    status_t res;
374    camera_metadata_ro_entry entry;
375    res = find_camera_metadata_ro_entry(mBuffer, tag, &entry);
376    if (CC_UNLIKELY( res != OK )) {
377        entry.count = 0;
378        entry.data.u8 = NULL;
379    }
380    return entry;
381}
382
383status_t CameraMetadata::erase(uint32_t tag) {
384    camera_metadata_entry_t entry;
385    status_t res;
386    if (mLocked) {
387        ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
388        return INVALID_OPERATION;
389    }
390    res = find_camera_metadata_entry(mBuffer, tag, &entry);
391    if (res == NAME_NOT_FOUND) {
392        return OK;
393    } else if (res != OK) {
394        ALOGE("%s: Error looking for entry %s.%s (%x): %s %d",
395                __FUNCTION__,
396                get_camera_metadata_section_name(tag),
397                get_camera_metadata_tag_name(tag), tag, strerror(-res), res);
398        return res;
399    }
400    res = delete_camera_metadata_entry(mBuffer, entry.index);
401    if (res != OK) {
402        ALOGE("%s: Error deleting entry %s.%s (%x): %s %d",
403                __FUNCTION__,
404                get_camera_metadata_section_name(tag),
405                get_camera_metadata_tag_name(tag), tag, strerror(-res), res);
406    }
407    return res;
408}
409
410void CameraMetadata::dump(int fd, int verbosity, int indentation) const {
411    dump_indented_camera_metadata(mBuffer, fd, verbosity, indentation);
412}
413
414status_t CameraMetadata::resizeIfNeeded(size_t extraEntries, size_t extraData) {
415    if (mBuffer == NULL) {
416        mBuffer = allocate_camera_metadata(extraEntries * 2, extraData * 2);
417        if (mBuffer == NULL) {
418            ALOGE("%s: Can't allocate larger metadata buffer", __FUNCTION__);
419            return NO_MEMORY;
420        }
421    } else {
422        size_t currentEntryCount = get_camera_metadata_entry_count(mBuffer);
423        size_t currentEntryCap = get_camera_metadata_entry_capacity(mBuffer);
424        size_t newEntryCount = currentEntryCount +
425                extraEntries;
426        newEntryCount = (newEntryCount > currentEntryCap) ?
427                newEntryCount * 2 : currentEntryCap;
428
429        size_t currentDataCount = get_camera_metadata_data_count(mBuffer);
430        size_t currentDataCap = get_camera_metadata_data_capacity(mBuffer);
431        size_t newDataCount = currentDataCount +
432                extraData;
433        newDataCount = (newDataCount > currentDataCap) ?
434                newDataCount * 2 : currentDataCap;
435
436        if (newEntryCount > currentEntryCap ||
437                newDataCount > currentDataCap) {
438            camera_metadata_t *oldBuffer = mBuffer;
439            mBuffer = allocate_camera_metadata(newEntryCount,
440                    newDataCount);
441            if (mBuffer == NULL) {
442                ALOGE("%s: Can't allocate larger metadata buffer", __FUNCTION__);
443                return NO_MEMORY;
444            }
445            append_camera_metadata(mBuffer, oldBuffer);
446            free_camera_metadata(oldBuffer);
447        }
448    }
449    return OK;
450}
451
452void CameraMetadata::swap(CameraMetadata& other) {
453    if (mLocked) {
454        ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
455        return;
456    } else if (other.mLocked) {
457        ALOGE("%s: Other CameraMetadata is locked", __FUNCTION__);
458        return;
459    }
460
461    camera_metadata* thisBuf = mBuffer;
462    camera_metadata* otherBuf = other.mBuffer;
463
464    other.mBuffer = thisBuf;
465    mBuffer = otherBuf;
466}
467
468status_t CameraMetadata::getTagFromName(const char *name,
469        const VendorTagDescriptor* vTags, uint32_t *tag) {
470
471    if (name == nullptr || tag == nullptr) return BAD_VALUE;
472
473    size_t nameLength = strlen(name);
474
475    const SortedVector<String8> *vendorSections;
476    size_t vendorSectionCount = 0;
477
478    if (vTags != NULL) {
479        vendorSections = vTags->getAllSectionNames();
480        vendorSectionCount = vendorSections->size();
481    }
482
483    // First, find the section by the longest string match
484    const char *section = NULL;
485    size_t sectionIndex = 0;
486    size_t sectionLength = 0;
487    size_t totalSectionCount = ANDROID_SECTION_COUNT + vendorSectionCount;
488    for (size_t i = 0; i < totalSectionCount; ++i) {
489
490        const char *str = (i < ANDROID_SECTION_COUNT) ? camera_metadata_section_names[i] :
491                (*vendorSections)[i - ANDROID_SECTION_COUNT].string();
492
493        ALOGV("%s: Trying to match against section '%s'", __FUNCTION__, str);
494
495        if (strstr(name, str) == name) { // name begins with the section name
496            size_t strLength = strlen(str);
497
498            ALOGV("%s: Name begins with section name", __FUNCTION__);
499
500            // section name is the longest we've found so far
501            if (section == NULL || sectionLength < strLength) {
502                section = str;
503                sectionIndex = i;
504                sectionLength = strLength;
505
506                ALOGV("%s: Found new best section (%s)", __FUNCTION__, section);
507            }
508        }
509    }
510
511    if (section == NULL) {
512        return NAME_NOT_FOUND;
513    } else {
514        ALOGV("%s: Found matched section '%s' (%zu)",
515              __FUNCTION__, section, sectionIndex);
516    }
517
518    // Get the tag name component of the name
519    const char *nameTagName = name + sectionLength + 1; // x.y.z -> z
520    if (sectionLength + 1 >= nameLength) {
521        return BAD_VALUE;
522    }
523
524    // Match rest of name against the tag names in that section only
525    uint32_t candidateTag = 0;
526    if (sectionIndex < ANDROID_SECTION_COUNT) {
527        // Match built-in tags (typically android.*)
528        uint32_t tagBegin, tagEnd; // [tagBegin, tagEnd)
529        tagBegin = camera_metadata_section_bounds[sectionIndex][0];
530        tagEnd = camera_metadata_section_bounds[sectionIndex][1];
531
532        for (candidateTag = tagBegin; candidateTag < tagEnd; ++candidateTag) {
533            const char *tagName = get_camera_metadata_tag_name(candidateTag);
534
535            if (strcmp(nameTagName, tagName) == 0) {
536                ALOGV("%s: Found matched tag '%s' (%d)",
537                      __FUNCTION__, tagName, candidateTag);
538                break;
539            }
540        }
541
542        if (candidateTag == tagEnd) {
543            return NAME_NOT_FOUND;
544        }
545    } else if (vTags != NULL) {
546        // Match vendor tags (typically com.*)
547        const String8 sectionName(section);
548        const String8 tagName(nameTagName);
549
550        status_t res = OK;
551        if ((res = vTags->lookupTag(tagName, sectionName, &candidateTag)) != OK) {
552            return NAME_NOT_FOUND;
553        }
554    }
555
556    *tag = candidateTag;
557    return OK;
558}
559
560
561} // namespace helper
562} // namespace V1_0
563} // namespace common
564} // namespace camera
565} // namespace hardware
566} // namespace android
567