blob: a4ae71be2c6bb7fe008e5e08beb970d2602f4633 [file] [log] [blame]
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -07001/*
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
Igor Murashkine2d1e3d2013-04-30 18:18:06 -070017// #define LOG_NDEBUG 0
18
Eino-Ville Talvala4bb81182012-09-24 09:46:53 -070019#define LOG_TAG "Camera2-Metadata"
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -070020#include <utils/Log.h>
21#include <utils/Errors.h>
22
Igor Murashkine7ee7632013-06-11 18:10:18 -070023#include <binder/Parcel.h>
Eino-Ville Talvala4d453832016-07-15 11:56:53 -070024#include <camera/CameraMetadata.h>
Emilian Peev0ec234e2020-08-24 11:48:50 -070025#include <camera_metadata_hidden.h>
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -070026
27namespace android {
28
Zhijun He146aed12013-12-05 07:46:51 -080029#define ALIGN_TO(val, alignment) \
30 (((uintptr_t)(val) + ((alignment) - 1)) & ~((alignment) - 1))
31
Igor Murashkine7ee7632013-06-11 18:10:18 -070032typedef Parcel::WritableBlob WritableBlob;
33typedef Parcel::ReadableBlob ReadableBlob;
34
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -070035CameraMetadata::CameraMetadata() :
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -080036 mBuffer(NULL), mLocked(false) {
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -070037}
38
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -080039CameraMetadata::CameraMetadata(size_t entryCapacity, size_t dataCapacity) :
40 mLocked(false)
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -070041{
42 mBuffer = allocate_camera_metadata(entryCapacity, dataCapacity);
43}
44
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -080045CameraMetadata::CameraMetadata(const CameraMetadata &other) :
46 mLocked(false) {
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -070047 mBuffer = clone_camera_metadata(other.mBuffer);
48}
49
Jayant Chowdhary8a0be292020-01-08 13:10:38 -080050CameraMetadata::CameraMetadata(CameraMetadata &&other) :mBuffer(NULL), mLocked(false) {
51 acquire(other);
52}
53
54CameraMetadata &CameraMetadata::operator=(CameraMetadata &&other) {
55 acquire(other);
56 return *this;
57}
58
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -080059CameraMetadata::CameraMetadata(camera_metadata_t *buffer) :
60 mBuffer(NULL), mLocked(false) {
Igor Murashkin7efa5202013-02-13 15:53:56 -080061 acquire(buffer);
62}
63
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -070064CameraMetadata &CameraMetadata::operator=(const CameraMetadata &other) {
65 return operator=(other.mBuffer);
66}
67
68CameraMetadata &CameraMetadata::operator=(const camera_metadata_t *buffer) {
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -080069 if (mLocked) {
70 ALOGE("%s: Assignment to a locked CameraMetadata!", __FUNCTION__);
71 return *this;
72 }
73
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -070074 if (CC_LIKELY(buffer != mBuffer)) {
75 camera_metadata_t *newBuffer = clone_camera_metadata(buffer);
76 clear();
77 mBuffer = newBuffer;
78 }
79 return *this;
80}
81
82CameraMetadata::~CameraMetadata() {
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -080083 mLocked = false;
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -070084 clear();
85}
86
Yin-Chia Yeh54298b32015-03-24 16:51:41 -070087const camera_metadata_t* CameraMetadata::getAndLock() const {
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -080088 mLocked = true;
89 return mBuffer;
90}
91
Yin-Chia Yeh8aac03f2016-03-03 15:45:23 -080092status_t CameraMetadata::unlock(const camera_metadata_t *buffer) const {
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -080093 if (!mLocked) {
94 ALOGE("%s: Can't unlock a non-locked CameraMetadata!", __FUNCTION__);
95 return INVALID_OPERATION;
96 }
97 if (buffer != mBuffer) {
98 ALOGE("%s: Can't unlock CameraMetadata with wrong pointer!",
99 __FUNCTION__);
100 return BAD_VALUE;
101 }
102 mLocked = false;
103 return OK;
104}
105
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700106camera_metadata_t* CameraMetadata::release() {
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800107 if (mLocked) {
108 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
109 return NULL;
110 }
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700111 camera_metadata_t *released = mBuffer;
112 mBuffer = NULL;
113 return released;
114}
115
116void CameraMetadata::clear() {
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800117 if (mLocked) {
118 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
119 return;
120 }
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700121 if (mBuffer) {
122 free_camera_metadata(mBuffer);
123 mBuffer = NULL;
124 }
125}
126
127void CameraMetadata::acquire(camera_metadata_t *buffer) {
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800128 if (mLocked) {
129 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
130 return;
131 }
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700132 clear();
133 mBuffer = buffer;
Igor Murashkine2d1e3d2013-04-30 18:18:06 -0700134
135 ALOGE_IF(validate_camera_metadata_structure(mBuffer, /*size*/NULL) != OK,
136 "%s: Failed to validate metadata structure %p",
137 __FUNCTION__, buffer);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700138}
139
140void CameraMetadata::acquire(CameraMetadata &other) {
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800141 if (mLocked) {
142 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
143 return;
144 }
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700145 acquire(other.release());
146}
147
148status_t CameraMetadata::append(const CameraMetadata &other) {
Eino-Ville Talvalafd6ecdd2013-10-11 09:51:09 -0700149 return append(other.mBuffer);
150}
151
152status_t CameraMetadata::append(const camera_metadata_t* other) {
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800153 if (mLocked) {
154 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
155 return INVALID_OPERATION;
156 }
Eino-Ville Talvalafd6ecdd2013-10-11 09:51:09 -0700157 size_t extraEntries = get_camera_metadata_entry_count(other);
158 size_t extraData = get_camera_metadata_data_count(other);
159 resizeIfNeeded(extraEntries, extraData);
160
161 return append_camera_metadata(mBuffer, other);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700162}
163
164size_t CameraMetadata::entryCount() const {
165 return (mBuffer == NULL) ? 0 :
166 get_camera_metadata_entry_count(mBuffer);
167}
168
Eino-Ville Talvalada6665c2012-08-29 17:37:16 -0700169bool CameraMetadata::isEmpty() const {
170 return entryCount() == 0;
171}
172
Emilian Peev5f268f32020-09-09 17:29:48 -0700173size_t CameraMetadata::bufferSize() const {
174 return (mBuffer == NULL) ? 0 :
175 get_camera_metadata_size(mBuffer);
176}
177
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700178status_t CameraMetadata::sort() {
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800179 if (mLocked) {
180 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
181 return INVALID_OPERATION;
182 }
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700183 return sort_camera_metadata(mBuffer);
184}
185
186status_t CameraMetadata::checkType(uint32_t tag, uint8_t expectedType) {
Emilian Peev71c73a22017-03-21 16:35:51 +0000187 int tagType = get_local_camera_metadata_tag_type(tag, mBuffer);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700188 if ( CC_UNLIKELY(tagType == -1)) {
189 ALOGE("Update metadata entry: Unknown tag %d", tag);
190 return INVALID_OPERATION;
191 }
192 if ( CC_UNLIKELY(tagType != expectedType) ) {
193 ALOGE("Mismatched tag type when updating entry %s (%d) of type %s; "
194 "got type %s data instead ",
Emilian Peev71c73a22017-03-21 16:35:51 +0000195 get_local_camera_metadata_tag_name(tag, mBuffer), tag,
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700196 camera_metadata_type_names[tagType],
197 camera_metadata_type_names[expectedType]);
198 return INVALID_OPERATION;
199 }
200 return OK;
201}
202
203status_t CameraMetadata::update(uint32_t tag,
204 const int32_t *data, size_t data_count) {
205 status_t res;
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800206 if (mLocked) {
207 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
208 return INVALID_OPERATION;
209 }
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700210 if ( (res = checkType(tag, TYPE_INT32)) != OK) {
211 return res;
212 }
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800213 return updateImpl(tag, (const void*)data, data_count);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700214}
215
216status_t CameraMetadata::update(uint32_t tag,
217 const uint8_t *data, size_t data_count) {
218 status_t res;
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800219 if (mLocked) {
220 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
221 return INVALID_OPERATION;
222 }
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700223 if ( (res = checkType(tag, TYPE_BYTE)) != OK) {
224 return res;
225 }
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800226 return updateImpl(tag, (const void*)data, data_count);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700227}
228
229status_t CameraMetadata::update(uint32_t tag,
230 const float *data, size_t data_count) {
231 status_t res;
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800232 if (mLocked) {
233 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
234 return INVALID_OPERATION;
235 }
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700236 if ( (res = checkType(tag, TYPE_FLOAT)) != OK) {
237 return res;
238 }
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800239 return updateImpl(tag, (const void*)data, data_count);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700240}
241
242status_t CameraMetadata::update(uint32_t tag,
243 const int64_t *data, size_t data_count) {
244 status_t res;
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800245 if (mLocked) {
246 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
247 return INVALID_OPERATION;
248 }
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700249 if ( (res = checkType(tag, TYPE_INT64)) != OK) {
250 return res;
251 }
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800252 return updateImpl(tag, (const void*)data, data_count);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700253}
254
255status_t CameraMetadata::update(uint32_t tag,
256 const double *data, size_t data_count) {
257 status_t res;
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800258 if (mLocked) {
259 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
260 return INVALID_OPERATION;
261 }
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700262 if ( (res = checkType(tag, TYPE_DOUBLE)) != OK) {
263 return res;
264 }
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800265 return updateImpl(tag, (const void*)data, data_count);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700266}
267
268status_t CameraMetadata::update(uint32_t tag,
269 const camera_metadata_rational_t *data, size_t data_count) {
270 status_t res;
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800271 if (mLocked) {
272 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
273 return INVALID_OPERATION;
274 }
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700275 if ( (res = checkType(tag, TYPE_RATIONAL)) != OK) {
276 return res;
277 }
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800278 return updateImpl(tag, (const void*)data, data_count);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700279}
280
281status_t CameraMetadata::update(uint32_t tag,
282 const String8 &string) {
283 status_t res;
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800284 if (mLocked) {
285 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
286 return INVALID_OPERATION;
287 }
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700288 if ( (res = checkType(tag, TYPE_BYTE)) != OK) {
289 return res;
290 }
Zhijun He7595c472014-03-27 16:46:15 -0700291 // string.size() doesn't count the null termination character.
292 return updateImpl(tag, (const void*)string.string(), string.size() + 1);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700293}
294
Eino-Ville Talvala4d453832016-07-15 11:56:53 -0700295status_t CameraMetadata::update(const camera_metadata_ro_entry &entry) {
296 status_t res;
297 if (mLocked) {
298 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
299 return INVALID_OPERATION;
300 }
301 if ( (res = checkType(entry.tag, entry.type)) != OK) {
302 return res;
303 }
304 return updateImpl(entry.tag, (const void*)entry.data.u8, entry.count);
305}
306
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800307status_t CameraMetadata::updateImpl(uint32_t tag, const void *data,
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700308 size_t data_count) {
309 status_t res;
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800310 if (mLocked) {
311 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
312 return INVALID_OPERATION;
313 }
Emilian Peev71c73a22017-03-21 16:35:51 +0000314 int type = get_local_camera_metadata_tag_type(tag, mBuffer);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700315 if (type == -1) {
316 ALOGE("%s: Tag %d not found", __FUNCTION__, tag);
317 return BAD_VALUE;
318 }
Eino-Ville Talvalae2b60c82015-07-17 16:21:44 -0700319 // Safety check - ensure that data isn't pointing to this metadata, since
320 // that would get invalidated if a resize is needed
321 size_t bufferSize = get_camera_metadata_size(mBuffer);
322 uintptr_t bufAddr = reinterpret_cast<uintptr_t>(mBuffer);
323 uintptr_t dataAddr = reinterpret_cast<uintptr_t>(data);
324 if (dataAddr > bufAddr && dataAddr < (bufAddr + bufferSize)) {
325 ALOGE("%s: Update attempted with data from the same metadata buffer!",
326 __FUNCTION__);
327 return INVALID_OPERATION;
328 }
329
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700330 size_t data_size = calculate_camera_metadata_entry_data_size(type,
331 data_count);
332
333 res = resizeIfNeeded(1, data_size);
334
335 if (res == OK) {
336 camera_metadata_entry_t entry;
337 res = find_camera_metadata_entry(mBuffer, tag, &entry);
338 if (res == NAME_NOT_FOUND) {
339 res = add_camera_metadata_entry(mBuffer,
340 tag, data, data_count);
341 } else if (res == OK) {
342 res = update_camera_metadata_entry(mBuffer,
343 entry.index, data, data_count, NULL);
344 }
345 }
346
347 if (res != OK) {
348 ALOGE("%s: Unable to update metadata entry %s.%s (%x): %s (%d)",
Emilian Peev71c73a22017-03-21 16:35:51 +0000349 __FUNCTION__, get_local_camera_metadata_section_name(tag, mBuffer),
350 get_local_camera_metadata_tag_name(tag, mBuffer), tag,
351 strerror(-res), res);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700352 }
Igor Murashkine2d1e3d2013-04-30 18:18:06 -0700353
354 IF_ALOGV() {
355 ALOGE_IF(validate_camera_metadata_structure(mBuffer, /*size*/NULL) !=
356 OK,
357
358 "%s: Failed to validate metadata structure after update %p",
359 __FUNCTION__, mBuffer);
360 }
361
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700362 return res;
363}
364
Igor Murashkinfc42642a2013-02-13 18:23:39 -0800365bool CameraMetadata::exists(uint32_t tag) const {
366 camera_metadata_ro_entry entry;
367 return find_camera_metadata_ro_entry(mBuffer, tag, &entry) == 0;
368}
369
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700370camera_metadata_entry_t CameraMetadata::find(uint32_t tag) {
371 status_t res;
372 camera_metadata_entry entry;
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800373 if (mLocked) {
374 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
375 entry.count = 0;
376 return entry;
377 }
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700378 res = find_camera_metadata_entry(mBuffer, tag, &entry);
379 if (CC_UNLIKELY( res != OK )) {
380 entry.count = 0;
381 entry.data.u8 = NULL;
382 }
383 return entry;
384}
385
386camera_metadata_ro_entry_t CameraMetadata::find(uint32_t tag) const {
387 status_t res;
388 camera_metadata_ro_entry entry;
389 res = find_camera_metadata_ro_entry(mBuffer, tag, &entry);
390 if (CC_UNLIKELY( res != OK )) {
391 entry.count = 0;
392 entry.data.u8 = NULL;
393 }
394 return entry;
395}
396
397status_t CameraMetadata::erase(uint32_t tag) {
398 camera_metadata_entry_t entry;
399 status_t res;
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800400 if (mLocked) {
401 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
402 return INVALID_OPERATION;
403 }
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700404 res = find_camera_metadata_entry(mBuffer, tag, &entry);
405 if (res == NAME_NOT_FOUND) {
406 return OK;
407 } else if (res != OK) {
408 ALOGE("%s: Error looking for entry %s.%s (%x): %s %d",
409 __FUNCTION__,
Emilian Peev71c73a22017-03-21 16:35:51 +0000410 get_local_camera_metadata_section_name(tag, mBuffer),
411 get_local_camera_metadata_tag_name(tag, mBuffer),
412 tag, strerror(-res), res);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700413 return res;
414 }
415 res = delete_camera_metadata_entry(mBuffer, entry.index);
416 if (res != OK) {
417 ALOGE("%s: Error deleting entry %s.%s (%x): %s %d",
418 __FUNCTION__,
Emilian Peev71c73a22017-03-21 16:35:51 +0000419 get_local_camera_metadata_section_name(tag, mBuffer),
420 get_local_camera_metadata_tag_name(tag, mBuffer),
421 tag, strerror(-res), res);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700422 }
423 return res;
424}
425
Emilian Peeve20c6372018-08-14 18:45:53 +0100426status_t CameraMetadata::removePermissionEntries(metadata_vendor_id_t vendorId,
427 std::vector<int32_t> *tagsRemoved) {
428 uint32_t tagCount = 0;
429 std::vector<uint32_t> tagsToRemove;
430
431 if (tagsRemoved == nullptr) {
432 return BAD_VALUE;
433 }
434
435 sp<VendorTagDescriptor> vTags = VendorTagDescriptor::getGlobalVendorTagDescriptor();
436 if ((nullptr == vTags.get()) || (0 >= vTags->getTagCount())) {
437 sp<VendorTagDescriptorCache> cache =
438 VendorTagDescriptorCache::getGlobalVendorTagCache();
439 if (cache.get()) {
440 cache->getVendorTagDescriptor(vendorId, &vTags);
441 }
442 }
443
444 if ((nullptr != vTags.get()) && (vTags->getTagCount() > 0)) {
445 tagCount = vTags->getTagCount();
446 uint32_t *vendorTags = new uint32_t[tagCount];
447 if (nullptr == vendorTags) {
448 return NO_MEMORY;
449 }
450 vTags->getTagArray(vendorTags);
451
452 tagsToRemove.reserve(tagCount);
453 tagsToRemove.insert(tagsToRemove.begin(), vendorTags, vendorTags + tagCount);
454
455 delete [] vendorTags;
456 tagCount = 0;
457 }
458
459 auto tagsNeedingPermission = get_camera_metadata_permission_needed(&tagCount);
460 if (tagCount > 0) {
461 tagsToRemove.reserve(tagsToRemove.capacity() + tagCount);
462 tagsToRemove.insert(tagsToRemove.end(), tagsNeedingPermission,
463 tagsNeedingPermission + tagCount);
464 }
465
466 tagsRemoved->reserve(tagsToRemove.size());
467 for (const auto &it : tagsToRemove) {
468 if (exists(it)) {
469 auto rc = erase(it);
470 if (NO_ERROR != rc) {
471 ALOGE("%s: Failed to erase tag: %x", __func__, it);
472 return rc;
473 }
474 tagsRemoved->push_back(it);
475 }
476 }
477
478 // Update the available characterstics accordingly
479 if (exists(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS)) {
480 std::vector<uint32_t> currentKeys;
481
482 std::sort(tagsRemoved->begin(), tagsRemoved->end());
483 auto keys = find(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS);
484 currentKeys.reserve(keys.count);
485 currentKeys.insert(currentKeys.end(), keys.data.i32, keys.data.i32 + keys.count);
486 std::sort(currentKeys.begin(), currentKeys.end());
487
488 std::vector<int32_t> newKeys(keys.count);
489 auto end = std::set_difference(currentKeys.begin(), currentKeys.end(), tagsRemoved->begin(),
490 tagsRemoved->end(), newKeys.begin());
491 newKeys.resize(end - newKeys.begin());
492
493 update(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS, newKeys.data(), newKeys.size());
494 }
495
496 return NO_ERROR;
497}
498
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700499void CameraMetadata::dump(int fd, int verbosity, int indentation) const {
500 dump_indented_camera_metadata(mBuffer, fd, verbosity, indentation);
501}
502
503status_t CameraMetadata::resizeIfNeeded(size_t extraEntries, size_t extraData) {
504 if (mBuffer == NULL) {
505 mBuffer = allocate_camera_metadata(extraEntries * 2, extraData * 2);
506 if (mBuffer == NULL) {
507 ALOGE("%s: Can't allocate larger metadata buffer", __FUNCTION__);
508 return NO_MEMORY;
509 }
510 } else {
511 size_t currentEntryCount = get_camera_metadata_entry_count(mBuffer);
512 size_t currentEntryCap = get_camera_metadata_entry_capacity(mBuffer);
513 size_t newEntryCount = currentEntryCount +
514 extraEntries;
515 newEntryCount = (newEntryCount > currentEntryCap) ?
516 newEntryCount * 2 : currentEntryCap;
517
518 size_t currentDataCount = get_camera_metadata_data_count(mBuffer);
519 size_t currentDataCap = get_camera_metadata_data_capacity(mBuffer);
520 size_t newDataCount = currentDataCount +
521 extraData;
522 newDataCount = (newDataCount > currentDataCap) ?
523 newDataCount * 2 : currentDataCap;
524
525 if (newEntryCount > currentEntryCap ||
526 newDataCount > currentDataCap) {
527 camera_metadata_t *oldBuffer = mBuffer;
528 mBuffer = allocate_camera_metadata(newEntryCount,
529 newDataCount);
530 if (mBuffer == NULL) {
Jayant Chowdharya94cbe62021-04-29 13:22:58 -0700531 // Maintain old buffer to avoid potential memory leak.
532 mBuffer = oldBuffer;
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700533 ALOGE("%s: Can't allocate larger metadata buffer", __FUNCTION__);
534 return NO_MEMORY;
535 }
536 append_camera_metadata(mBuffer, oldBuffer);
537 free_camera_metadata(oldBuffer);
538 }
539 }
540 return OK;
541}
542
Igor Murashkine7ee7632013-06-11 18:10:18 -0700543status_t CameraMetadata::readFromParcel(const Parcel& data,
544 camera_metadata_t** out) {
Jayant Chowdhary2e310da2020-05-12 12:40:36 -0700545
Igor Murashkine7ee7632013-06-11 18:10:18 -0700546 status_t err = OK;
547
548 camera_metadata_t* metadata = NULL;
549
550 if (out) {
551 *out = NULL;
552 }
553
Zhijun He146aed12013-12-05 07:46:51 -0800554 // See CameraMetadata::writeToParcel for parcel data layout diagram and explanation.
555 // arg0 = blobSize (int32)
556 int32_t blobSizeTmp = -1;
557 if ((err = data.readInt32(&blobSizeTmp)) != OK) {
Igor Murashkine7ee7632013-06-11 18:10:18 -0700558 ALOGE("%s: Failed to read metadata size (error %d %s)",
559 __FUNCTION__, err, strerror(-err));
560 return err;
561 }
Zhijun He146aed12013-12-05 07:46:51 -0800562 const size_t blobSize = static_cast<size_t>(blobSizeTmp);
563 const size_t alignment = get_camera_metadata_alignment();
Igor Murashkine7ee7632013-06-11 18:10:18 -0700564
Zhijun He146aed12013-12-05 07:46:51 -0800565 // Special case: zero blob size means zero sized (NULL) metadata.
566 if (blobSize == 0) {
Igor Murashkine7ee7632013-06-11 18:10:18 -0700567 ALOGV("%s: Read 0-sized metadata", __FUNCTION__);
568 return OK;
569 }
570
Zhijun He146aed12013-12-05 07:46:51 -0800571 if (blobSize <= alignment) {
572 ALOGE("%s: metadata blob is malformed, blobSize(%zu) should be larger than alignment(%zu)",
573 __FUNCTION__, blobSize, alignment);
574 return BAD_VALUE;
575 }
576
577 const size_t metadataSize = blobSize - alignment;
578
579 // NOTE: this doesn't make sense to me. shouldn't the blob
Igor Murashkine7ee7632013-06-11 18:10:18 -0700580 // know how big it is? why do we have to specify the size
581 // to Parcel::readBlob ?
Igor Murashkine7ee7632013-06-11 18:10:18 -0700582 ReadableBlob blob;
583 // arg1 = metadata (blob)
584 do {
Zhijun He146aed12013-12-05 07:46:51 -0800585 if ((err = data.readBlob(blobSize, &blob)) != OK) {
586 ALOGE("%s: Failed to read metadata blob (sized %zu). Possible "
Igor Murashkine7ee7632013-06-11 18:10:18 -0700587 " serialization bug. Error %d %s",
Zhijun He146aed12013-12-05 07:46:51 -0800588 __FUNCTION__, blobSize, err, strerror(-err));
Igor Murashkine7ee7632013-06-11 18:10:18 -0700589 break;
590 }
Igor Murashkine7ee7632013-06-11 18:10:18 -0700591
Zhijun He146aed12013-12-05 07:46:51 -0800592 // arg2 = offset (blob)
593 // Must be after blob since we don't know offset until after writeBlob.
594 int32_t offsetTmp;
595 if ((err = data.readInt32(&offsetTmp)) != OK) {
596 ALOGE("%s: Failed to read metadata offsetTmp (error %d %s)",
597 __FUNCTION__, err, strerror(-err));
598 break;
599 }
600 const size_t offset = static_cast<size_t>(offsetTmp);
601 if (offset >= alignment) {
602 ALOGE("%s: metadata offset(%zu) should be less than alignment(%zu)",
603 __FUNCTION__, blobSize, alignment);
604 err = BAD_VALUE;
605 break;
606 }
607
608 const uintptr_t metadataStart = reinterpret_cast<uintptr_t>(blob.data()) + offset;
609 const camera_metadata_t* tmp =
610 reinterpret_cast<const camera_metadata_t*>(metadataStart);
611 ALOGV("%s: alignment is: %zu, metadata start: %p, offset: %zu",
612 __FUNCTION__, alignment, tmp, offset);
Igor Murashkine7ee7632013-06-11 18:10:18 -0700613 metadata = allocate_copy_camera_metadata_checked(tmp, metadataSize);
614 if (metadata == NULL) {
615 // We consider that allocation only fails if the validation
616 // also failed, therefore the readFromParcel was a failure.
Zhijun He146aed12013-12-05 07:46:51 -0800617 ALOGE("%s: metadata allocation and copy failed", __FUNCTION__);
Igor Murashkine7ee7632013-06-11 18:10:18 -0700618 err = BAD_VALUE;
619 }
620 } while(0);
621 blob.release();
622
623 if (out) {
624 ALOGV("%s: Set out metadata to %p", __FUNCTION__, metadata);
625 *out = metadata;
626 } else if (metadata != NULL) {
627 ALOGV("%s: Freed camera metadata at %p", __FUNCTION__, metadata);
628 free_camera_metadata(metadata);
629 }
630
631 return err;
632}
633
634status_t CameraMetadata::writeToParcel(Parcel& data,
635 const camera_metadata_t* metadata) {
636 status_t res = OK;
637
Zhijun He146aed12013-12-05 07:46:51 -0800638 /**
639 * Below is the camera metadata parcel layout:
640 *
641 * |--------------------------------------------|
642 * | arg0: blobSize |
643 * | (length = 4) |
644 * |--------------------------------------------|<--Skip the rest if blobSize == 0.
645 * | |
646 * | |
647 * | arg1: blob |
648 * | (length = variable, see arg1 layout below) |
649 * | |
650 * | |
651 * |--------------------------------------------|
652 * | arg2: offset |
653 * | (length = 4) |
654 * |--------------------------------------------|
655 */
Igor Murashkine7ee7632013-06-11 18:10:18 -0700656
Zhijun He146aed12013-12-05 07:46:51 -0800657 // arg0 = blobSize (int32)
Igor Murashkine7ee7632013-06-11 18:10:18 -0700658 if (metadata == NULL) {
Zhijun He146aed12013-12-05 07:46:51 -0800659 // Write zero blobSize for null metadata.
Igor Murashkine7ee7632013-06-11 18:10:18 -0700660 return data.writeInt32(0);
661 }
662
Zhijun He146aed12013-12-05 07:46:51 -0800663 /**
664 * Always make the blob size sufficiently larger, as we need put alignment
665 * padding and metadata into the blob. Since we don't know the alignment
666 * offset before writeBlob. Then write the metadata to aligned offset.
667 */
Igor Murashkine7ee7632013-06-11 18:10:18 -0700668 const size_t metadataSize = get_camera_metadata_compact_size(metadata);
Zhijun He146aed12013-12-05 07:46:51 -0800669 const size_t alignment = get_camera_metadata_alignment();
670 const size_t blobSize = metadataSize + alignment;
671 res = data.writeInt32(static_cast<int32_t>(blobSize));
Igor Murashkine7ee7632013-06-11 18:10:18 -0700672 if (res != OK) {
673 return res;
674 }
675
Zhijun He146aed12013-12-05 07:46:51 -0800676 size_t offset = 0;
677 /**
678 * arg1 = metadata (blob).
679 *
680 * The blob size is the sum of front padding size, metadata size and back padding
681 * size, which is equal to metadataSize + alignment.
682 *
683 * The blob layout is:
684 * |------------------------------------|<----Start address of the blob (unaligned).
685 * | front padding |
686 * | (size = offset) |
687 * |------------------------------------|<----Aligned start address of metadata.
688 * | |
689 * | |
690 * | metadata |
691 * | (size = metadataSize) |
692 * | |
693 * | |
694 * |------------------------------------|
695 * | back padding |
696 * | (size = alignment - offset) |
697 * |------------------------------------|<----End address of blob.
698 * (Blob start address + blob size).
699 */
Igor Murashkine7ee7632013-06-11 18:10:18 -0700700 WritableBlob blob;
701 do {
Jeff Browne8df5392015-06-05 15:10:44 -0700702 res = data.writeBlob(blobSize, false, &blob);
Igor Murashkine7ee7632013-06-11 18:10:18 -0700703 if (res != OK) {
704 break;
705 }
Zhijun He146aed12013-12-05 07:46:51 -0800706 const uintptr_t metadataStart = ALIGN_TO(blob.data(), alignment);
707 offset = metadataStart - reinterpret_cast<uintptr_t>(blob.data());
708 ALOGV("%s: alignment is: %zu, metadata start: %p, offset: %zu",
Mark Salyzyn1a93f0c2014-06-09 16:34:58 -0700709 __FUNCTION__, alignment,
710 reinterpret_cast<const void *>(metadataStart), offset);
Zhijun He146aed12013-12-05 07:46:51 -0800711 copy_camera_metadata(reinterpret_cast<void*>(metadataStart), metadataSize, metadata);
Igor Murashkine7ee7632013-06-11 18:10:18 -0700712
713 // Not too big of a problem since receiving side does hard validation
714 // Don't check the size since the compact size could be larger
715 if (validate_camera_metadata_structure(metadata, /*size*/NULL) != OK) {
716 ALOGW("%s: Failed to validate metadata %p before writing blob",
717 __FUNCTION__, metadata);
718 }
719
720 } while(false);
721 blob.release();
722
Zhijun He146aed12013-12-05 07:46:51 -0800723 // arg2 = offset (int32)
724 res = data.writeInt32(static_cast<int32_t>(offset));
725
Igor Murashkine7ee7632013-06-11 18:10:18 -0700726 return res;
727}
728
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800729status_t CameraMetadata::readFromParcel(const Parcel *parcel) {
Jayant Chowdhary2e310da2020-05-12 12:40:36 -0700730
Igor Murashkine7ee7632013-06-11 18:10:18 -0700731 ALOGV("%s: parcel = %p", __FUNCTION__, parcel);
732
733 status_t res = OK;
734
735 if (parcel == NULL) {
736 ALOGE("%s: parcel is null", __FUNCTION__);
737 return BAD_VALUE;
738 }
739
740 if (mLocked) {
741 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
742 return INVALID_OPERATION;
743 }
744
745 camera_metadata *buffer = NULL;
746 // TODO: reading should return a status code, in case validation fails
747 res = CameraMetadata::readFromParcel(*parcel, &buffer);
748
749 if (res != NO_ERROR) {
750 ALOGE("%s: Failed to read from parcel. Metadata is unchanged.",
751 __FUNCTION__);
752 return res;
753 }
754
755 clear();
756 mBuffer = buffer;
757
758 return OK;
759}
760
761status_t CameraMetadata::writeToParcel(Parcel *parcel) const {
Jayant Chowdhary2e310da2020-05-12 12:40:36 -0700762
Igor Murashkine7ee7632013-06-11 18:10:18 -0700763 ALOGV("%s: parcel = %p", __FUNCTION__, parcel);
764
765 if (parcel == NULL) {
766 ALOGE("%s: parcel is null", __FUNCTION__);
767 return BAD_VALUE;
768 }
769
770 return CameraMetadata::writeToParcel(*parcel, mBuffer);
771}
772
773void CameraMetadata::swap(CameraMetadata& other) {
774 if (mLocked) {
775 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
776 return;
777 } else if (other.mLocked) {
778 ALOGE("%s: Other CameraMetadata is locked", __FUNCTION__);
779 return;
780 }
781
782 camera_metadata* thisBuf = mBuffer;
783 camera_metadata* otherBuf = other.mBuffer;
784
785 other.mBuffer = thisBuf;
786 mBuffer = otherBuf;
787}
788
Eino-Ville Talvala4d453832016-07-15 11:56:53 -0700789status_t CameraMetadata::getTagFromName(const char *name,
790 const VendorTagDescriptor* vTags, uint32_t *tag) {
Jayant Chowdhary2e310da2020-05-12 12:40:36 -0700791
Eino-Ville Talvala4d453832016-07-15 11:56:53 -0700792 if (name == nullptr || tag == nullptr) return BAD_VALUE;
793
794 size_t nameLength = strlen(name);
795
796 const SortedVector<String8> *vendorSections;
797 size_t vendorSectionCount = 0;
798
799 if (vTags != NULL) {
800 vendorSections = vTags->getAllSectionNames();
801 vendorSectionCount = vendorSections->size();
802 }
803
804 // First, find the section by the longest string match
805 const char *section = NULL;
806 size_t sectionIndex = 0;
807 size_t sectionLength = 0;
808 size_t totalSectionCount = ANDROID_SECTION_COUNT + vendorSectionCount;
809 for (size_t i = 0; i < totalSectionCount; ++i) {
810
811 const char *str = (i < ANDROID_SECTION_COUNT) ? camera_metadata_section_names[i] :
812 (*vendorSections)[i - ANDROID_SECTION_COUNT].string();
813
814 ALOGV("%s: Trying to match against section '%s'", __FUNCTION__, str);
815
816 if (strstr(name, str) == name) { // name begins with the section name
817 size_t strLength = strlen(str);
818
819 ALOGV("%s: Name begins with section name", __FUNCTION__);
820
821 // section name is the longest we've found so far
822 if (section == NULL || sectionLength < strLength) {
823 section = str;
824 sectionIndex = i;
825 sectionLength = strLength;
826
827 ALOGV("%s: Found new best section (%s)", __FUNCTION__, section);
828 }
829 }
830 }
831
832 // TODO: Make above get_camera_metadata_section_from_name ?
833
834 if (section == NULL) {
835 return NAME_NOT_FOUND;
836 } else {
837 ALOGV("%s: Found matched section '%s' (%zu)",
838 __FUNCTION__, section, sectionIndex);
839 }
840
841 // Get the tag name component of the name
842 const char *nameTagName = name + sectionLength + 1; // x.y.z -> z
843 if (sectionLength + 1 >= nameLength) {
844 return BAD_VALUE;
845 }
846
847 // Match rest of name against the tag names in that section only
848 uint32_t candidateTag = 0;
849 if (sectionIndex < ANDROID_SECTION_COUNT) {
850 // Match built-in tags (typically android.*)
851 uint32_t tagBegin, tagEnd; // [tagBegin, tagEnd)
852 tagBegin = camera_metadata_section_bounds[sectionIndex][0];
853 tagEnd = camera_metadata_section_bounds[sectionIndex][1];
854
855 for (candidateTag = tagBegin; candidateTag < tagEnd; ++candidateTag) {
856 const char *tagName = get_camera_metadata_tag_name(candidateTag);
857
858 if (strcmp(nameTagName, tagName) == 0) {
859 ALOGV("%s: Found matched tag '%s' (%d)",
860 __FUNCTION__, tagName, candidateTag);
861 break;
862 }
863 }
864
865 if (candidateTag == tagEnd) {
866 return NAME_NOT_FOUND;
867 }
868 } else if (vTags != NULL) {
869 // Match vendor tags (typically com.*)
870 const String8 sectionName(section);
871 const String8 tagName(nameTagName);
872
873 status_t res = OK;
874 if ((res = vTags->lookupTag(tagName, sectionName, &candidateTag)) != OK) {
875 return NAME_NOT_FOUND;
876 }
877 }
878
879 *tag = candidateTag;
880 return OK;
881}
882
Emilian Peev0ec234e2020-08-24 11:48:50 -0700883metadata_vendor_id_t CameraMetadata::getVendorId() {
884 return get_camera_metadata_vendor_id(mBuffer);
885}
Eino-Ville Talvala4d453832016-07-15 11:56:53 -0700886
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700887}; // namespace android