blob: 4745ee8ab9ad1f4750530e38d45a6998ac1b214e [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"
Shuzhen Wang47cdcf32019-11-08 15:48:19 -080020#define ATRACE_TAG ATRACE_TAG_CAMERA
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -070021#include <utils/Log.h>
Shuzhen Wang47cdcf32019-11-08 15:48:19 -080022#include <utils/Trace.h>
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -070023#include <utils/Errors.h>
24
Igor Murashkine7ee7632013-06-11 18:10:18 -070025#include <binder/Parcel.h>
Eino-Ville Talvala4d453832016-07-15 11:56:53 -070026#include <camera/CameraMetadata.h>
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -070027
28namespace android {
29
Zhijun He146aed12013-12-05 07:46:51 -080030#define ALIGN_TO(val, alignment) \
31 (((uintptr_t)(val) + ((alignment) - 1)) & ~((alignment) - 1))
32
Igor Murashkine7ee7632013-06-11 18:10:18 -070033typedef Parcel::WritableBlob WritableBlob;
34typedef Parcel::ReadableBlob ReadableBlob;
35
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -070036CameraMetadata::CameraMetadata() :
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -080037 mBuffer(NULL), mLocked(false) {
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -070038}
39
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -080040CameraMetadata::CameraMetadata(size_t entryCapacity, size_t dataCapacity) :
41 mLocked(false)
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -070042{
Shuzhen Wang47cdcf32019-11-08 15:48:19 -080043 ATRACE_CALL();
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -070044 mBuffer = allocate_camera_metadata(entryCapacity, dataCapacity);
45}
46
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -080047CameraMetadata::CameraMetadata(const CameraMetadata &other) :
48 mLocked(false) {
Shuzhen Wang47cdcf32019-11-08 15:48:19 -080049 ATRACE_CALL();
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -070050 mBuffer = clone_camera_metadata(other.mBuffer);
51}
52
Jayant Chowdhary8a0be292020-01-08 13:10:38 -080053CameraMetadata::CameraMetadata(CameraMetadata &&other) :mBuffer(NULL), mLocked(false) {
54 acquire(other);
55}
56
57CameraMetadata &CameraMetadata::operator=(CameraMetadata &&other) {
58 acquire(other);
59 return *this;
60}
61
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -080062CameraMetadata::CameraMetadata(camera_metadata_t *buffer) :
63 mBuffer(NULL), mLocked(false) {
Igor Murashkin7efa5202013-02-13 15:53:56 -080064 acquire(buffer);
65}
66
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -070067CameraMetadata &CameraMetadata::operator=(const CameraMetadata &other) {
68 return operator=(other.mBuffer);
69}
70
71CameraMetadata &CameraMetadata::operator=(const camera_metadata_t *buffer) {
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -080072 if (mLocked) {
73 ALOGE("%s: Assignment to a locked CameraMetadata!", __FUNCTION__);
74 return *this;
75 }
76
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -070077 if (CC_LIKELY(buffer != mBuffer)) {
78 camera_metadata_t *newBuffer = clone_camera_metadata(buffer);
79 clear();
80 mBuffer = newBuffer;
81 }
82 return *this;
83}
84
85CameraMetadata::~CameraMetadata() {
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -080086 mLocked = false;
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -070087 clear();
88}
89
Yin-Chia Yeh54298b32015-03-24 16:51:41 -070090const camera_metadata_t* CameraMetadata::getAndLock() const {
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -080091 mLocked = true;
92 return mBuffer;
93}
94
Yin-Chia Yeh8aac03f2016-03-03 15:45:23 -080095status_t CameraMetadata::unlock(const camera_metadata_t *buffer) const {
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -080096 if (!mLocked) {
97 ALOGE("%s: Can't unlock a non-locked CameraMetadata!", __FUNCTION__);
98 return INVALID_OPERATION;
99 }
100 if (buffer != mBuffer) {
101 ALOGE("%s: Can't unlock CameraMetadata with wrong pointer!",
102 __FUNCTION__);
103 return BAD_VALUE;
104 }
105 mLocked = false;
106 return OK;
107}
108
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700109camera_metadata_t* CameraMetadata::release() {
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800110 if (mLocked) {
111 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
112 return NULL;
113 }
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700114 camera_metadata_t *released = mBuffer;
115 mBuffer = NULL;
116 return released;
117}
118
119void CameraMetadata::clear() {
Shuzhen Wang47cdcf32019-11-08 15:48:19 -0800120 ATRACE_CALL();
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800121 if (mLocked) {
122 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
123 return;
124 }
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700125 if (mBuffer) {
126 free_camera_metadata(mBuffer);
127 mBuffer = NULL;
128 }
129}
130
131void CameraMetadata::acquire(camera_metadata_t *buffer) {
Shuzhen Wang47cdcf32019-11-08 15:48:19 -0800132 ATRACE_CALL();
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800133 if (mLocked) {
134 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
135 return;
136 }
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700137 clear();
138 mBuffer = buffer;
Igor Murashkine2d1e3d2013-04-30 18:18:06 -0700139
140 ALOGE_IF(validate_camera_metadata_structure(mBuffer, /*size*/NULL) != OK,
141 "%s: Failed to validate metadata structure %p",
142 __FUNCTION__, buffer);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700143}
144
145void CameraMetadata::acquire(CameraMetadata &other) {
Shuzhen Wang47cdcf32019-11-08 15:48:19 -0800146 ATRACE_CALL();
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800147 if (mLocked) {
148 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
149 return;
150 }
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700151 acquire(other.release());
152}
153
154status_t CameraMetadata::append(const CameraMetadata &other) {
Shuzhen Wang47cdcf32019-11-08 15:48:19 -0800155 ATRACE_CALL();
Eino-Ville Talvalafd6ecdd2013-10-11 09:51:09 -0700156 return append(other.mBuffer);
157}
158
159status_t CameraMetadata::append(const camera_metadata_t* other) {
Shuzhen Wang47cdcf32019-11-08 15:48:19 -0800160 ATRACE_CALL();
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800161 if (mLocked) {
162 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
163 return INVALID_OPERATION;
164 }
Eino-Ville Talvalafd6ecdd2013-10-11 09:51:09 -0700165 size_t extraEntries = get_camera_metadata_entry_count(other);
166 size_t extraData = get_camera_metadata_data_count(other);
167 resizeIfNeeded(extraEntries, extraData);
168
169 return append_camera_metadata(mBuffer, other);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700170}
171
172size_t CameraMetadata::entryCount() const {
173 return (mBuffer == NULL) ? 0 :
174 get_camera_metadata_entry_count(mBuffer);
175}
176
Eino-Ville Talvalada6665c2012-08-29 17:37:16 -0700177bool CameraMetadata::isEmpty() const {
178 return entryCount() == 0;
179}
180
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700181status_t CameraMetadata::sort() {
Shuzhen Wang47cdcf32019-11-08 15:48:19 -0800182 ATRACE_CALL();
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800183 if (mLocked) {
184 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
185 return INVALID_OPERATION;
186 }
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700187 return sort_camera_metadata(mBuffer);
188}
189
190status_t CameraMetadata::checkType(uint32_t tag, uint8_t expectedType) {
Emilian Peev71c73a22017-03-21 16:35:51 +0000191 int tagType = get_local_camera_metadata_tag_type(tag, mBuffer);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700192 if ( CC_UNLIKELY(tagType == -1)) {
193 ALOGE("Update metadata entry: Unknown tag %d", tag);
194 return INVALID_OPERATION;
195 }
196 if ( CC_UNLIKELY(tagType != expectedType) ) {
197 ALOGE("Mismatched tag type when updating entry %s (%d) of type %s; "
198 "got type %s data instead ",
Emilian Peev71c73a22017-03-21 16:35:51 +0000199 get_local_camera_metadata_tag_name(tag, mBuffer), tag,
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700200 camera_metadata_type_names[tagType],
201 camera_metadata_type_names[expectedType]);
202 return INVALID_OPERATION;
203 }
204 return OK;
205}
206
207status_t CameraMetadata::update(uint32_t tag,
208 const int32_t *data, size_t data_count) {
209 status_t res;
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800210 if (mLocked) {
211 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
212 return INVALID_OPERATION;
213 }
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700214 if ( (res = checkType(tag, TYPE_INT32)) != OK) {
215 return res;
216 }
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800217 return updateImpl(tag, (const void*)data, data_count);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700218}
219
220status_t CameraMetadata::update(uint32_t tag,
221 const uint8_t *data, size_t data_count) {
222 status_t res;
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800223 if (mLocked) {
224 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
225 return INVALID_OPERATION;
226 }
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700227 if ( (res = checkType(tag, TYPE_BYTE)) != OK) {
228 return res;
229 }
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800230 return updateImpl(tag, (const void*)data, data_count);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700231}
232
233status_t CameraMetadata::update(uint32_t tag,
234 const float *data, size_t data_count) {
235 status_t res;
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800236 if (mLocked) {
237 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
238 return INVALID_OPERATION;
239 }
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700240 if ( (res = checkType(tag, TYPE_FLOAT)) != OK) {
241 return res;
242 }
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800243 return updateImpl(tag, (const void*)data, data_count);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700244}
245
246status_t CameraMetadata::update(uint32_t tag,
247 const int64_t *data, size_t data_count) {
248 status_t res;
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800249 if (mLocked) {
250 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
251 return INVALID_OPERATION;
252 }
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700253 if ( (res = checkType(tag, TYPE_INT64)) != OK) {
254 return res;
255 }
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800256 return updateImpl(tag, (const void*)data, data_count);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700257}
258
259status_t CameraMetadata::update(uint32_t tag,
260 const double *data, size_t data_count) {
261 status_t res;
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800262 if (mLocked) {
263 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
264 return INVALID_OPERATION;
265 }
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700266 if ( (res = checkType(tag, TYPE_DOUBLE)) != OK) {
267 return res;
268 }
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800269 return updateImpl(tag, (const void*)data, data_count);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700270}
271
272status_t CameraMetadata::update(uint32_t tag,
273 const camera_metadata_rational_t *data, size_t data_count) {
274 status_t res;
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800275 if (mLocked) {
276 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
277 return INVALID_OPERATION;
278 }
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700279 if ( (res = checkType(tag, TYPE_RATIONAL)) != OK) {
280 return res;
281 }
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800282 return updateImpl(tag, (const void*)data, data_count);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700283}
284
285status_t CameraMetadata::update(uint32_t tag,
286 const String8 &string) {
287 status_t res;
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800288 if (mLocked) {
289 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
290 return INVALID_OPERATION;
291 }
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700292 if ( (res = checkType(tag, TYPE_BYTE)) != OK) {
293 return res;
294 }
Zhijun He7595c472014-03-27 16:46:15 -0700295 // string.size() doesn't count the null termination character.
296 return updateImpl(tag, (const void*)string.string(), string.size() + 1);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700297}
298
Eino-Ville Talvala4d453832016-07-15 11:56:53 -0700299status_t CameraMetadata::update(const camera_metadata_ro_entry &entry) {
300 status_t res;
301 if (mLocked) {
302 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
303 return INVALID_OPERATION;
304 }
305 if ( (res = checkType(entry.tag, entry.type)) != OK) {
306 return res;
307 }
308 return updateImpl(entry.tag, (const void*)entry.data.u8, entry.count);
309}
310
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800311status_t CameraMetadata::updateImpl(uint32_t tag, const void *data,
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700312 size_t data_count) {
Shuzhen Wang47cdcf32019-11-08 15:48:19 -0800313 ATRACE_CALL();
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700314 status_t res;
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800315 if (mLocked) {
316 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
317 return INVALID_OPERATION;
318 }
Emilian Peev71c73a22017-03-21 16:35:51 +0000319 int type = get_local_camera_metadata_tag_type(tag, mBuffer);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700320 if (type == -1) {
321 ALOGE("%s: Tag %d not found", __FUNCTION__, tag);
322 return BAD_VALUE;
323 }
Eino-Ville Talvalae2b60c82015-07-17 16:21:44 -0700324 // Safety check - ensure that data isn't pointing to this metadata, since
325 // that would get invalidated if a resize is needed
326 size_t bufferSize = get_camera_metadata_size(mBuffer);
327 uintptr_t bufAddr = reinterpret_cast<uintptr_t>(mBuffer);
328 uintptr_t dataAddr = reinterpret_cast<uintptr_t>(data);
329 if (dataAddr > bufAddr && dataAddr < (bufAddr + bufferSize)) {
330 ALOGE("%s: Update attempted with data from the same metadata buffer!",
331 __FUNCTION__);
332 return INVALID_OPERATION;
333 }
334
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700335 size_t data_size = calculate_camera_metadata_entry_data_size(type,
336 data_count);
337
338 res = resizeIfNeeded(1, data_size);
339
340 if (res == OK) {
341 camera_metadata_entry_t entry;
342 res = find_camera_metadata_entry(mBuffer, tag, &entry);
343 if (res == NAME_NOT_FOUND) {
344 res = add_camera_metadata_entry(mBuffer,
345 tag, data, data_count);
346 } else if (res == OK) {
347 res = update_camera_metadata_entry(mBuffer,
348 entry.index, data, data_count, NULL);
349 }
350 }
351
352 if (res != OK) {
353 ALOGE("%s: Unable to update metadata entry %s.%s (%x): %s (%d)",
Emilian Peev71c73a22017-03-21 16:35:51 +0000354 __FUNCTION__, get_local_camera_metadata_section_name(tag, mBuffer),
355 get_local_camera_metadata_tag_name(tag, mBuffer), tag,
356 strerror(-res), res);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700357 }
Igor Murashkine2d1e3d2013-04-30 18:18:06 -0700358
359 IF_ALOGV() {
360 ALOGE_IF(validate_camera_metadata_structure(mBuffer, /*size*/NULL) !=
361 OK,
362
363 "%s: Failed to validate metadata structure after update %p",
364 __FUNCTION__, mBuffer);
365 }
366
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700367 return res;
368}
369
Igor Murashkinfc42642a2013-02-13 18:23:39 -0800370bool CameraMetadata::exists(uint32_t tag) const {
Shuzhen Wang47cdcf32019-11-08 15:48:19 -0800371 ATRACE_CALL();
Igor Murashkinfc42642a2013-02-13 18:23:39 -0800372 camera_metadata_ro_entry entry;
373 return find_camera_metadata_ro_entry(mBuffer, tag, &entry) == 0;
374}
375
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700376camera_metadata_entry_t CameraMetadata::find(uint32_t tag) {
Shuzhen Wang47cdcf32019-11-08 15:48:19 -0800377 ATRACE_CALL();
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700378 status_t res;
379 camera_metadata_entry entry;
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800380 if (mLocked) {
381 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
382 entry.count = 0;
383 return entry;
384 }
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700385 res = find_camera_metadata_entry(mBuffer, tag, &entry);
386 if (CC_UNLIKELY( res != OK )) {
387 entry.count = 0;
388 entry.data.u8 = NULL;
389 }
390 return entry;
391}
392
393camera_metadata_ro_entry_t CameraMetadata::find(uint32_t tag) const {
Shuzhen Wang47cdcf32019-11-08 15:48:19 -0800394 ATRACE_CALL();
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700395 status_t res;
396 camera_metadata_ro_entry entry;
397 res = find_camera_metadata_ro_entry(mBuffer, tag, &entry);
398 if (CC_UNLIKELY( res != OK )) {
399 entry.count = 0;
400 entry.data.u8 = NULL;
401 }
402 return entry;
403}
404
405status_t CameraMetadata::erase(uint32_t tag) {
Shuzhen Wang47cdcf32019-11-08 15:48:19 -0800406 ATRACE_CALL();
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700407 camera_metadata_entry_t entry;
408 status_t res;
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800409 if (mLocked) {
410 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
411 return INVALID_OPERATION;
412 }
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700413 res = find_camera_metadata_entry(mBuffer, tag, &entry);
414 if (res == NAME_NOT_FOUND) {
415 return OK;
416 } else if (res != OK) {
417 ALOGE("%s: Error looking for 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 return res;
423 }
424 res = delete_camera_metadata_entry(mBuffer, entry.index);
425 if (res != OK) {
426 ALOGE("%s: Error deleting entry %s.%s (%x): %s %d",
427 __FUNCTION__,
Emilian Peev71c73a22017-03-21 16:35:51 +0000428 get_local_camera_metadata_section_name(tag, mBuffer),
429 get_local_camera_metadata_tag_name(tag, mBuffer),
430 tag, strerror(-res), res);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700431 }
432 return res;
433}
434
Emilian Peeve20c6372018-08-14 18:45:53 +0100435status_t CameraMetadata::removePermissionEntries(metadata_vendor_id_t vendorId,
436 std::vector<int32_t> *tagsRemoved) {
Shuzhen Wang47cdcf32019-11-08 15:48:19 -0800437 ATRACE_CALL();
Emilian Peeve20c6372018-08-14 18:45:53 +0100438 uint32_t tagCount = 0;
439 std::vector<uint32_t> tagsToRemove;
440
441 if (tagsRemoved == nullptr) {
442 return BAD_VALUE;
443 }
444
445 sp<VendorTagDescriptor> vTags = VendorTagDescriptor::getGlobalVendorTagDescriptor();
446 if ((nullptr == vTags.get()) || (0 >= vTags->getTagCount())) {
447 sp<VendorTagDescriptorCache> cache =
448 VendorTagDescriptorCache::getGlobalVendorTagCache();
449 if (cache.get()) {
450 cache->getVendorTagDescriptor(vendorId, &vTags);
451 }
452 }
453
454 if ((nullptr != vTags.get()) && (vTags->getTagCount() > 0)) {
455 tagCount = vTags->getTagCount();
456 uint32_t *vendorTags = new uint32_t[tagCount];
457 if (nullptr == vendorTags) {
458 return NO_MEMORY;
459 }
460 vTags->getTagArray(vendorTags);
461
462 tagsToRemove.reserve(tagCount);
463 tagsToRemove.insert(tagsToRemove.begin(), vendorTags, vendorTags + tagCount);
464
465 delete [] vendorTags;
466 tagCount = 0;
467 }
468
469 auto tagsNeedingPermission = get_camera_metadata_permission_needed(&tagCount);
470 if (tagCount > 0) {
471 tagsToRemove.reserve(tagsToRemove.capacity() + tagCount);
472 tagsToRemove.insert(tagsToRemove.end(), tagsNeedingPermission,
473 tagsNeedingPermission + tagCount);
474 }
475
476 tagsRemoved->reserve(tagsToRemove.size());
477 for (const auto &it : tagsToRemove) {
478 if (exists(it)) {
479 auto rc = erase(it);
480 if (NO_ERROR != rc) {
481 ALOGE("%s: Failed to erase tag: %x", __func__, it);
482 return rc;
483 }
484 tagsRemoved->push_back(it);
485 }
486 }
487
488 // Update the available characterstics accordingly
489 if (exists(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS)) {
490 std::vector<uint32_t> currentKeys;
491
492 std::sort(tagsRemoved->begin(), tagsRemoved->end());
493 auto keys = find(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS);
494 currentKeys.reserve(keys.count);
495 currentKeys.insert(currentKeys.end(), keys.data.i32, keys.data.i32 + keys.count);
496 std::sort(currentKeys.begin(), currentKeys.end());
497
498 std::vector<int32_t> newKeys(keys.count);
499 auto end = std::set_difference(currentKeys.begin(), currentKeys.end(), tagsRemoved->begin(),
500 tagsRemoved->end(), newKeys.begin());
501 newKeys.resize(end - newKeys.begin());
502
503 update(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS, newKeys.data(), newKeys.size());
504 }
505
506 return NO_ERROR;
507}
508
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700509void CameraMetadata::dump(int fd, int verbosity, int indentation) const {
510 dump_indented_camera_metadata(mBuffer, fd, verbosity, indentation);
511}
512
513status_t CameraMetadata::resizeIfNeeded(size_t extraEntries, size_t extraData) {
Shuzhen Wang47cdcf32019-11-08 15:48:19 -0800514 ATRACE_CALL();
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700515 if (mBuffer == NULL) {
516 mBuffer = allocate_camera_metadata(extraEntries * 2, extraData * 2);
517 if (mBuffer == NULL) {
518 ALOGE("%s: Can't allocate larger metadata buffer", __FUNCTION__);
519 return NO_MEMORY;
520 }
521 } else {
522 size_t currentEntryCount = get_camera_metadata_entry_count(mBuffer);
523 size_t currentEntryCap = get_camera_metadata_entry_capacity(mBuffer);
524 size_t newEntryCount = currentEntryCount +
525 extraEntries;
526 newEntryCount = (newEntryCount > currentEntryCap) ?
527 newEntryCount * 2 : currentEntryCap;
528
529 size_t currentDataCount = get_camera_metadata_data_count(mBuffer);
530 size_t currentDataCap = get_camera_metadata_data_capacity(mBuffer);
531 size_t newDataCount = currentDataCount +
532 extraData;
533 newDataCount = (newDataCount > currentDataCap) ?
534 newDataCount * 2 : currentDataCap;
535
536 if (newEntryCount > currentEntryCap ||
537 newDataCount > currentDataCap) {
538 camera_metadata_t *oldBuffer = mBuffer;
539 mBuffer = allocate_camera_metadata(newEntryCount,
540 newDataCount);
541 if (mBuffer == NULL) {
542 ALOGE("%s: Can't allocate larger metadata buffer", __FUNCTION__);
543 return NO_MEMORY;
544 }
545 append_camera_metadata(mBuffer, oldBuffer);
546 free_camera_metadata(oldBuffer);
547 }
548 }
549 return OK;
550}
551
Igor Murashkine7ee7632013-06-11 18:10:18 -0700552status_t CameraMetadata::readFromParcel(const Parcel& data,
553 camera_metadata_t** out) {
Shuzhen Wang47cdcf32019-11-08 15:48:19 -0800554 ATRACE_CALL();
Igor Murashkine7ee7632013-06-11 18:10:18 -0700555 status_t err = OK;
556
557 camera_metadata_t* metadata = NULL;
558
559 if (out) {
560 *out = NULL;
561 }
562
Zhijun He146aed12013-12-05 07:46:51 -0800563 // See CameraMetadata::writeToParcel for parcel data layout diagram and explanation.
564 // arg0 = blobSize (int32)
565 int32_t blobSizeTmp = -1;
566 if ((err = data.readInt32(&blobSizeTmp)) != OK) {
Igor Murashkine7ee7632013-06-11 18:10:18 -0700567 ALOGE("%s: Failed to read metadata size (error %d %s)",
568 __FUNCTION__, err, strerror(-err));
569 return err;
570 }
Zhijun He146aed12013-12-05 07:46:51 -0800571 const size_t blobSize = static_cast<size_t>(blobSizeTmp);
572 const size_t alignment = get_camera_metadata_alignment();
Igor Murashkine7ee7632013-06-11 18:10:18 -0700573
Zhijun He146aed12013-12-05 07:46:51 -0800574 // Special case: zero blob size means zero sized (NULL) metadata.
575 if (blobSize == 0) {
Igor Murashkine7ee7632013-06-11 18:10:18 -0700576 ALOGV("%s: Read 0-sized metadata", __FUNCTION__);
577 return OK;
578 }
579
Zhijun He146aed12013-12-05 07:46:51 -0800580 if (blobSize <= alignment) {
581 ALOGE("%s: metadata blob is malformed, blobSize(%zu) should be larger than alignment(%zu)",
582 __FUNCTION__, blobSize, alignment);
583 return BAD_VALUE;
584 }
585
586 const size_t metadataSize = blobSize - alignment;
587
588 // NOTE: this doesn't make sense to me. shouldn't the blob
Igor Murashkine7ee7632013-06-11 18:10:18 -0700589 // know how big it is? why do we have to specify the size
590 // to Parcel::readBlob ?
Igor Murashkine7ee7632013-06-11 18:10:18 -0700591 ReadableBlob blob;
592 // arg1 = metadata (blob)
593 do {
Zhijun He146aed12013-12-05 07:46:51 -0800594 if ((err = data.readBlob(blobSize, &blob)) != OK) {
595 ALOGE("%s: Failed to read metadata blob (sized %zu). Possible "
Igor Murashkine7ee7632013-06-11 18:10:18 -0700596 " serialization bug. Error %d %s",
Zhijun He146aed12013-12-05 07:46:51 -0800597 __FUNCTION__, blobSize, err, strerror(-err));
Igor Murashkine7ee7632013-06-11 18:10:18 -0700598 break;
599 }
Igor Murashkine7ee7632013-06-11 18:10:18 -0700600
Zhijun He146aed12013-12-05 07:46:51 -0800601 // arg2 = offset (blob)
602 // Must be after blob since we don't know offset until after writeBlob.
603 int32_t offsetTmp;
604 if ((err = data.readInt32(&offsetTmp)) != OK) {
605 ALOGE("%s: Failed to read metadata offsetTmp (error %d %s)",
606 __FUNCTION__, err, strerror(-err));
607 break;
608 }
609 const size_t offset = static_cast<size_t>(offsetTmp);
610 if (offset >= alignment) {
611 ALOGE("%s: metadata offset(%zu) should be less than alignment(%zu)",
612 __FUNCTION__, blobSize, alignment);
613 err = BAD_VALUE;
614 break;
615 }
616
617 const uintptr_t metadataStart = reinterpret_cast<uintptr_t>(blob.data()) + offset;
618 const camera_metadata_t* tmp =
619 reinterpret_cast<const camera_metadata_t*>(metadataStart);
620 ALOGV("%s: alignment is: %zu, metadata start: %p, offset: %zu",
621 __FUNCTION__, alignment, tmp, offset);
Igor Murashkine7ee7632013-06-11 18:10:18 -0700622 metadata = allocate_copy_camera_metadata_checked(tmp, metadataSize);
623 if (metadata == NULL) {
624 // We consider that allocation only fails if the validation
625 // also failed, therefore the readFromParcel was a failure.
Zhijun He146aed12013-12-05 07:46:51 -0800626 ALOGE("%s: metadata allocation and copy failed", __FUNCTION__);
Igor Murashkine7ee7632013-06-11 18:10:18 -0700627 err = BAD_VALUE;
628 }
629 } while(0);
630 blob.release();
631
632 if (out) {
633 ALOGV("%s: Set out metadata to %p", __FUNCTION__, metadata);
634 *out = metadata;
635 } else if (metadata != NULL) {
636 ALOGV("%s: Freed camera metadata at %p", __FUNCTION__, metadata);
637 free_camera_metadata(metadata);
638 }
639
640 return err;
641}
642
643status_t CameraMetadata::writeToParcel(Parcel& data,
644 const camera_metadata_t* metadata) {
Shuzhen Wang47cdcf32019-11-08 15:48:19 -0800645 ATRACE_CALL();
Igor Murashkine7ee7632013-06-11 18:10:18 -0700646 status_t res = OK;
647
Zhijun He146aed12013-12-05 07:46:51 -0800648 /**
649 * Below is the camera metadata parcel layout:
650 *
651 * |--------------------------------------------|
652 * | arg0: blobSize |
653 * | (length = 4) |
654 * |--------------------------------------------|<--Skip the rest if blobSize == 0.
655 * | |
656 * | |
657 * | arg1: blob |
658 * | (length = variable, see arg1 layout below) |
659 * | |
660 * | |
661 * |--------------------------------------------|
662 * | arg2: offset |
663 * | (length = 4) |
664 * |--------------------------------------------|
665 */
Igor Murashkine7ee7632013-06-11 18:10:18 -0700666
Zhijun He146aed12013-12-05 07:46:51 -0800667 // arg0 = blobSize (int32)
Igor Murashkine7ee7632013-06-11 18:10:18 -0700668 if (metadata == NULL) {
Zhijun He146aed12013-12-05 07:46:51 -0800669 // Write zero blobSize for null metadata.
Igor Murashkine7ee7632013-06-11 18:10:18 -0700670 return data.writeInt32(0);
671 }
672
Zhijun He146aed12013-12-05 07:46:51 -0800673 /**
674 * Always make the blob size sufficiently larger, as we need put alignment
675 * padding and metadata into the blob. Since we don't know the alignment
676 * offset before writeBlob. Then write the metadata to aligned offset.
677 */
Igor Murashkine7ee7632013-06-11 18:10:18 -0700678 const size_t metadataSize = get_camera_metadata_compact_size(metadata);
Zhijun He146aed12013-12-05 07:46:51 -0800679 const size_t alignment = get_camera_metadata_alignment();
680 const size_t blobSize = metadataSize + alignment;
681 res = data.writeInt32(static_cast<int32_t>(blobSize));
Igor Murashkine7ee7632013-06-11 18:10:18 -0700682 if (res != OK) {
683 return res;
684 }
685
Zhijun He146aed12013-12-05 07:46:51 -0800686 size_t offset = 0;
687 /**
688 * arg1 = metadata (blob).
689 *
690 * The blob size is the sum of front padding size, metadata size and back padding
691 * size, which is equal to metadataSize + alignment.
692 *
693 * The blob layout is:
694 * |------------------------------------|<----Start address of the blob (unaligned).
695 * | front padding |
696 * | (size = offset) |
697 * |------------------------------------|<----Aligned start address of metadata.
698 * | |
699 * | |
700 * | metadata |
701 * | (size = metadataSize) |
702 * | |
703 * | |
704 * |------------------------------------|
705 * | back padding |
706 * | (size = alignment - offset) |
707 * |------------------------------------|<----End address of blob.
708 * (Blob start address + blob size).
709 */
Igor Murashkine7ee7632013-06-11 18:10:18 -0700710 WritableBlob blob;
711 do {
Jeff Browne8df5392015-06-05 15:10:44 -0700712 res = data.writeBlob(blobSize, false, &blob);
Igor Murashkine7ee7632013-06-11 18:10:18 -0700713 if (res != OK) {
714 break;
715 }
Zhijun He146aed12013-12-05 07:46:51 -0800716 const uintptr_t metadataStart = ALIGN_TO(blob.data(), alignment);
717 offset = metadataStart - reinterpret_cast<uintptr_t>(blob.data());
718 ALOGV("%s: alignment is: %zu, metadata start: %p, offset: %zu",
Mark Salyzyn1a93f0c2014-06-09 16:34:58 -0700719 __FUNCTION__, alignment,
720 reinterpret_cast<const void *>(metadataStart), offset);
Zhijun He146aed12013-12-05 07:46:51 -0800721 copy_camera_metadata(reinterpret_cast<void*>(metadataStart), metadataSize, metadata);
Igor Murashkine7ee7632013-06-11 18:10:18 -0700722
723 // Not too big of a problem since receiving side does hard validation
724 // Don't check the size since the compact size could be larger
725 if (validate_camera_metadata_structure(metadata, /*size*/NULL) != OK) {
726 ALOGW("%s: Failed to validate metadata %p before writing blob",
727 __FUNCTION__, metadata);
728 }
729
730 } while(false);
731 blob.release();
732
Zhijun He146aed12013-12-05 07:46:51 -0800733 // arg2 = offset (int32)
734 res = data.writeInt32(static_cast<int32_t>(offset));
735
Igor Murashkine7ee7632013-06-11 18:10:18 -0700736 return res;
737}
738
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800739status_t CameraMetadata::readFromParcel(const Parcel *parcel) {
Shuzhen Wang47cdcf32019-11-08 15:48:19 -0800740 ATRACE_CALL();
Igor Murashkine7ee7632013-06-11 18:10:18 -0700741 ALOGV("%s: parcel = %p", __FUNCTION__, parcel);
742
743 status_t res = OK;
744
745 if (parcel == NULL) {
746 ALOGE("%s: parcel is null", __FUNCTION__);
747 return BAD_VALUE;
748 }
749
750 if (mLocked) {
751 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
752 return INVALID_OPERATION;
753 }
754
755 camera_metadata *buffer = NULL;
756 // TODO: reading should return a status code, in case validation fails
757 res = CameraMetadata::readFromParcel(*parcel, &buffer);
758
759 if (res != NO_ERROR) {
760 ALOGE("%s: Failed to read from parcel. Metadata is unchanged.",
761 __FUNCTION__);
762 return res;
763 }
764
765 clear();
766 mBuffer = buffer;
767
768 return OK;
769}
770
771status_t CameraMetadata::writeToParcel(Parcel *parcel) const {
Shuzhen Wang47cdcf32019-11-08 15:48:19 -0800772 ATRACE_CALL();
Igor Murashkine7ee7632013-06-11 18:10:18 -0700773 ALOGV("%s: parcel = %p", __FUNCTION__, parcel);
774
775 if (parcel == NULL) {
776 ALOGE("%s: parcel is null", __FUNCTION__);
777 return BAD_VALUE;
778 }
779
780 return CameraMetadata::writeToParcel(*parcel, mBuffer);
781}
782
783void CameraMetadata::swap(CameraMetadata& other) {
784 if (mLocked) {
785 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
786 return;
787 } else if (other.mLocked) {
788 ALOGE("%s: Other CameraMetadata is locked", __FUNCTION__);
789 return;
790 }
791
792 camera_metadata* thisBuf = mBuffer;
793 camera_metadata* otherBuf = other.mBuffer;
794
795 other.mBuffer = thisBuf;
796 mBuffer = otherBuf;
797}
798
Eino-Ville Talvala4d453832016-07-15 11:56:53 -0700799status_t CameraMetadata::getTagFromName(const char *name,
800 const VendorTagDescriptor* vTags, uint32_t *tag) {
Shuzhen Wang47cdcf32019-11-08 15:48:19 -0800801 ATRACE_CALL();
Eino-Ville Talvala4d453832016-07-15 11:56:53 -0700802 if (name == nullptr || tag == nullptr) return BAD_VALUE;
803
804 size_t nameLength = strlen(name);
805
806 const SortedVector<String8> *vendorSections;
807 size_t vendorSectionCount = 0;
808
809 if (vTags != NULL) {
810 vendorSections = vTags->getAllSectionNames();
811 vendorSectionCount = vendorSections->size();
812 }
813
814 // First, find the section by the longest string match
815 const char *section = NULL;
816 size_t sectionIndex = 0;
817 size_t sectionLength = 0;
818 size_t totalSectionCount = ANDROID_SECTION_COUNT + vendorSectionCount;
819 for (size_t i = 0; i < totalSectionCount; ++i) {
820
821 const char *str = (i < ANDROID_SECTION_COUNT) ? camera_metadata_section_names[i] :
822 (*vendorSections)[i - ANDROID_SECTION_COUNT].string();
823
824 ALOGV("%s: Trying to match against section '%s'", __FUNCTION__, str);
825
826 if (strstr(name, str) == name) { // name begins with the section name
827 size_t strLength = strlen(str);
828
829 ALOGV("%s: Name begins with section name", __FUNCTION__);
830
831 // section name is the longest we've found so far
832 if (section == NULL || sectionLength < strLength) {
833 section = str;
834 sectionIndex = i;
835 sectionLength = strLength;
836
837 ALOGV("%s: Found new best section (%s)", __FUNCTION__, section);
838 }
839 }
840 }
841
842 // TODO: Make above get_camera_metadata_section_from_name ?
843
844 if (section == NULL) {
845 return NAME_NOT_FOUND;
846 } else {
847 ALOGV("%s: Found matched section '%s' (%zu)",
848 __FUNCTION__, section, sectionIndex);
849 }
850
851 // Get the tag name component of the name
852 const char *nameTagName = name + sectionLength + 1; // x.y.z -> z
853 if (sectionLength + 1 >= nameLength) {
854 return BAD_VALUE;
855 }
856
857 // Match rest of name against the tag names in that section only
858 uint32_t candidateTag = 0;
859 if (sectionIndex < ANDROID_SECTION_COUNT) {
860 // Match built-in tags (typically android.*)
861 uint32_t tagBegin, tagEnd; // [tagBegin, tagEnd)
862 tagBegin = camera_metadata_section_bounds[sectionIndex][0];
863 tagEnd = camera_metadata_section_bounds[sectionIndex][1];
864
865 for (candidateTag = tagBegin; candidateTag < tagEnd; ++candidateTag) {
866 const char *tagName = get_camera_metadata_tag_name(candidateTag);
867
868 if (strcmp(nameTagName, tagName) == 0) {
869 ALOGV("%s: Found matched tag '%s' (%d)",
870 __FUNCTION__, tagName, candidateTag);
871 break;
872 }
873 }
874
875 if (candidateTag == tagEnd) {
876 return NAME_NOT_FOUND;
877 }
878 } else if (vTags != NULL) {
879 // Match vendor tags (typically com.*)
880 const String8 sectionName(section);
881 const String8 tagName(nameTagName);
882
883 status_t res = OK;
884 if ((res = vTags->lookupTag(tagName, sectionName, &candidateTag)) != OK) {
885 return NAME_NOT_FOUND;
886 }
887 }
888
889 *tag = candidateTag;
890 return OK;
891}
892
893
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700894}; // namespace android