blob: 15c295e9e65cb7c70fca4f288b2aed6bfdc9c553 [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
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -080053CameraMetadata::CameraMetadata(camera_metadata_t *buffer) :
54 mBuffer(NULL), mLocked(false) {
Igor Murashkin7efa5202013-02-13 15:53:56 -080055 acquire(buffer);
56}
57
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -070058CameraMetadata &CameraMetadata::operator=(const CameraMetadata &other) {
59 return operator=(other.mBuffer);
60}
61
62CameraMetadata &CameraMetadata::operator=(const camera_metadata_t *buffer) {
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -080063 if (mLocked) {
64 ALOGE("%s: Assignment to a locked CameraMetadata!", __FUNCTION__);
65 return *this;
66 }
67
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -070068 if (CC_LIKELY(buffer != mBuffer)) {
69 camera_metadata_t *newBuffer = clone_camera_metadata(buffer);
70 clear();
71 mBuffer = newBuffer;
72 }
73 return *this;
74}
75
76CameraMetadata::~CameraMetadata() {
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -080077 mLocked = false;
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -070078 clear();
79}
80
Yin-Chia Yeh54298b32015-03-24 16:51:41 -070081const camera_metadata_t* CameraMetadata::getAndLock() const {
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -080082 mLocked = true;
83 return mBuffer;
84}
85
Yin-Chia Yeh8aac03f2016-03-03 15:45:23 -080086status_t CameraMetadata::unlock(const camera_metadata_t *buffer) const {
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -080087 if (!mLocked) {
88 ALOGE("%s: Can't unlock a non-locked CameraMetadata!", __FUNCTION__);
89 return INVALID_OPERATION;
90 }
91 if (buffer != mBuffer) {
92 ALOGE("%s: Can't unlock CameraMetadata with wrong pointer!",
93 __FUNCTION__);
94 return BAD_VALUE;
95 }
96 mLocked = false;
97 return OK;
98}
99
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700100camera_metadata_t* CameraMetadata::release() {
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800101 if (mLocked) {
102 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
103 return NULL;
104 }
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700105 camera_metadata_t *released = mBuffer;
106 mBuffer = NULL;
107 return released;
108}
109
110void CameraMetadata::clear() {
Shuzhen Wang47cdcf32019-11-08 15:48:19 -0800111 ATRACE_CALL();
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800112 if (mLocked) {
113 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
114 return;
115 }
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700116 if (mBuffer) {
117 free_camera_metadata(mBuffer);
118 mBuffer = NULL;
119 }
120}
121
122void CameraMetadata::acquire(camera_metadata_t *buffer) {
Shuzhen Wang47cdcf32019-11-08 15:48:19 -0800123 ATRACE_CALL();
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800124 if (mLocked) {
125 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
126 return;
127 }
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700128 clear();
129 mBuffer = buffer;
Igor Murashkine2d1e3d2013-04-30 18:18:06 -0700130
131 ALOGE_IF(validate_camera_metadata_structure(mBuffer, /*size*/NULL) != OK,
132 "%s: Failed to validate metadata structure %p",
133 __FUNCTION__, buffer);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700134}
135
136void CameraMetadata::acquire(CameraMetadata &other) {
Shuzhen Wang47cdcf32019-11-08 15:48:19 -0800137 ATRACE_CALL();
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800138 if (mLocked) {
139 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
140 return;
141 }
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700142 acquire(other.release());
143}
144
145status_t CameraMetadata::append(const CameraMetadata &other) {
Shuzhen Wang47cdcf32019-11-08 15:48:19 -0800146 ATRACE_CALL();
Eino-Ville Talvalafd6ecdd2013-10-11 09:51:09 -0700147 return append(other.mBuffer);
148}
149
150status_t CameraMetadata::append(const camera_metadata_t* other) {
Shuzhen Wang47cdcf32019-11-08 15:48:19 -0800151 ATRACE_CALL();
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800152 if (mLocked) {
153 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
154 return INVALID_OPERATION;
155 }
Eino-Ville Talvalafd6ecdd2013-10-11 09:51:09 -0700156 size_t extraEntries = get_camera_metadata_entry_count(other);
157 size_t extraData = get_camera_metadata_data_count(other);
158 resizeIfNeeded(extraEntries, extraData);
159
160 return append_camera_metadata(mBuffer, other);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700161}
162
163size_t CameraMetadata::entryCount() const {
164 return (mBuffer == NULL) ? 0 :
165 get_camera_metadata_entry_count(mBuffer);
166}
167
Eino-Ville Talvalada6665c2012-08-29 17:37:16 -0700168bool CameraMetadata::isEmpty() const {
169 return entryCount() == 0;
170}
171
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700172status_t CameraMetadata::sort() {
Shuzhen Wang47cdcf32019-11-08 15:48:19 -0800173 ATRACE_CALL();
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800174 if (mLocked) {
175 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
176 return INVALID_OPERATION;
177 }
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700178 return sort_camera_metadata(mBuffer);
179}
180
181status_t CameraMetadata::checkType(uint32_t tag, uint8_t expectedType) {
Emilian Peev71c73a22017-03-21 16:35:51 +0000182 int tagType = get_local_camera_metadata_tag_type(tag, mBuffer);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700183 if ( CC_UNLIKELY(tagType == -1)) {
184 ALOGE("Update metadata entry: Unknown tag %d", tag);
185 return INVALID_OPERATION;
186 }
187 if ( CC_UNLIKELY(tagType != expectedType) ) {
188 ALOGE("Mismatched tag type when updating entry %s (%d) of type %s; "
189 "got type %s data instead ",
Emilian Peev71c73a22017-03-21 16:35:51 +0000190 get_local_camera_metadata_tag_name(tag, mBuffer), tag,
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700191 camera_metadata_type_names[tagType],
192 camera_metadata_type_names[expectedType]);
193 return INVALID_OPERATION;
194 }
195 return OK;
196}
197
198status_t CameraMetadata::update(uint32_t tag,
199 const int32_t *data, size_t data_count) {
200 status_t res;
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800201 if (mLocked) {
202 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
203 return INVALID_OPERATION;
204 }
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700205 if ( (res = checkType(tag, TYPE_INT32)) != OK) {
206 return res;
207 }
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800208 return updateImpl(tag, (const void*)data, data_count);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700209}
210
211status_t CameraMetadata::update(uint32_t tag,
212 const uint8_t *data, size_t data_count) {
213 status_t res;
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800214 if (mLocked) {
215 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
216 return INVALID_OPERATION;
217 }
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700218 if ( (res = checkType(tag, TYPE_BYTE)) != OK) {
219 return res;
220 }
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800221 return updateImpl(tag, (const void*)data, data_count);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700222}
223
224status_t CameraMetadata::update(uint32_t tag,
225 const float *data, size_t data_count) {
226 status_t res;
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800227 if (mLocked) {
228 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
229 return INVALID_OPERATION;
230 }
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700231 if ( (res = checkType(tag, TYPE_FLOAT)) != OK) {
232 return res;
233 }
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800234 return updateImpl(tag, (const void*)data, data_count);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700235}
236
237status_t CameraMetadata::update(uint32_t tag,
238 const int64_t *data, size_t data_count) {
239 status_t res;
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800240 if (mLocked) {
241 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
242 return INVALID_OPERATION;
243 }
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700244 if ( (res = checkType(tag, TYPE_INT64)) != OK) {
245 return res;
246 }
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800247 return updateImpl(tag, (const void*)data, data_count);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700248}
249
250status_t CameraMetadata::update(uint32_t tag,
251 const double *data, size_t data_count) {
252 status_t res;
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800253 if (mLocked) {
254 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
255 return INVALID_OPERATION;
256 }
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700257 if ( (res = checkType(tag, TYPE_DOUBLE)) != OK) {
258 return res;
259 }
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800260 return updateImpl(tag, (const void*)data, data_count);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700261}
262
263status_t CameraMetadata::update(uint32_t tag,
264 const camera_metadata_rational_t *data, size_t data_count) {
265 status_t res;
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800266 if (mLocked) {
267 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
268 return INVALID_OPERATION;
269 }
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700270 if ( (res = checkType(tag, TYPE_RATIONAL)) != OK) {
271 return res;
272 }
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800273 return updateImpl(tag, (const void*)data, data_count);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700274}
275
276status_t CameraMetadata::update(uint32_t tag,
277 const String8 &string) {
278 status_t res;
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800279 if (mLocked) {
280 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
281 return INVALID_OPERATION;
282 }
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700283 if ( (res = checkType(tag, TYPE_BYTE)) != OK) {
284 return res;
285 }
Zhijun He7595c472014-03-27 16:46:15 -0700286 // string.size() doesn't count the null termination character.
287 return updateImpl(tag, (const void*)string.string(), string.size() + 1);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700288}
289
Eino-Ville Talvala4d453832016-07-15 11:56:53 -0700290status_t CameraMetadata::update(const camera_metadata_ro_entry &entry) {
291 status_t res;
292 if (mLocked) {
293 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
294 return INVALID_OPERATION;
295 }
296 if ( (res = checkType(entry.tag, entry.type)) != OK) {
297 return res;
298 }
299 return updateImpl(entry.tag, (const void*)entry.data.u8, entry.count);
300}
301
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800302status_t CameraMetadata::updateImpl(uint32_t tag, const void *data,
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700303 size_t data_count) {
Shuzhen Wang47cdcf32019-11-08 15:48:19 -0800304 ATRACE_CALL();
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700305 status_t res;
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800306 if (mLocked) {
307 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
308 return INVALID_OPERATION;
309 }
Emilian Peev71c73a22017-03-21 16:35:51 +0000310 int type = get_local_camera_metadata_tag_type(tag, mBuffer);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700311 if (type == -1) {
312 ALOGE("%s: Tag %d not found", __FUNCTION__, tag);
313 return BAD_VALUE;
314 }
Eino-Ville Talvalae2b60c82015-07-17 16:21:44 -0700315 // Safety check - ensure that data isn't pointing to this metadata, since
316 // that would get invalidated if a resize is needed
317 size_t bufferSize = get_camera_metadata_size(mBuffer);
318 uintptr_t bufAddr = reinterpret_cast<uintptr_t>(mBuffer);
319 uintptr_t dataAddr = reinterpret_cast<uintptr_t>(data);
320 if (dataAddr > bufAddr && dataAddr < (bufAddr + bufferSize)) {
321 ALOGE("%s: Update attempted with data from the same metadata buffer!",
322 __FUNCTION__);
323 return INVALID_OPERATION;
324 }
325
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700326 size_t data_size = calculate_camera_metadata_entry_data_size(type,
327 data_count);
328
329 res = resizeIfNeeded(1, data_size);
330
331 if (res == OK) {
332 camera_metadata_entry_t entry;
333 res = find_camera_metadata_entry(mBuffer, tag, &entry);
334 if (res == NAME_NOT_FOUND) {
335 res = add_camera_metadata_entry(mBuffer,
336 tag, data, data_count);
337 } else if (res == OK) {
338 res = update_camera_metadata_entry(mBuffer,
339 entry.index, data, data_count, NULL);
340 }
341 }
342
343 if (res != OK) {
344 ALOGE("%s: Unable to update metadata entry %s.%s (%x): %s (%d)",
Emilian Peev71c73a22017-03-21 16:35:51 +0000345 __FUNCTION__, get_local_camera_metadata_section_name(tag, mBuffer),
346 get_local_camera_metadata_tag_name(tag, mBuffer), tag,
347 strerror(-res), res);
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700348 }
Igor Murashkine2d1e3d2013-04-30 18:18:06 -0700349
350 IF_ALOGV() {
351 ALOGE_IF(validate_camera_metadata_structure(mBuffer, /*size*/NULL) !=
352 OK,
353
354 "%s: Failed to validate metadata structure after update %p",
355 __FUNCTION__, mBuffer);
356 }
357
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700358 return res;
359}
360
Igor Murashkinfc42642a2013-02-13 18:23:39 -0800361bool CameraMetadata::exists(uint32_t tag) const {
Shuzhen Wang47cdcf32019-11-08 15:48:19 -0800362 ATRACE_CALL();
Igor Murashkinfc42642a2013-02-13 18:23:39 -0800363 camera_metadata_ro_entry entry;
364 return find_camera_metadata_ro_entry(mBuffer, tag, &entry) == 0;
365}
366
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700367camera_metadata_entry_t CameraMetadata::find(uint32_t tag) {
Shuzhen Wang47cdcf32019-11-08 15:48:19 -0800368 ATRACE_CALL();
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700369 status_t res;
370 camera_metadata_entry entry;
Eino-Ville Talvala3b53bc92013-02-27 18:02:26 -0800371 if (mLocked) {
372 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
373 entry.count = 0;
374 return entry;
375 }
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700376 res = find_camera_metadata_entry(mBuffer, tag, &entry);
377 if (CC_UNLIKELY( res != OK )) {
378 entry.count = 0;
379 entry.data.u8 = NULL;
380 }
381 return entry;
382}
383
384camera_metadata_ro_entry_t CameraMetadata::find(uint32_t tag) const {
Shuzhen Wang47cdcf32019-11-08 15:48:19 -0800385 ATRACE_CALL();
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700386 status_t res;
387 camera_metadata_ro_entry entry;
388 res = find_camera_metadata_ro_entry(mBuffer, tag, &entry);
389 if (CC_UNLIKELY( res != OK )) {
390 entry.count = 0;
391 entry.data.u8 = NULL;
392 }
393 return entry;
394}
395
396status_t CameraMetadata::erase(uint32_t tag) {
Shuzhen Wang47cdcf32019-11-08 15:48:19 -0800397 ATRACE_CALL();
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700398 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) {
Shuzhen Wang47cdcf32019-11-08 15:48:19 -0800428 ATRACE_CALL();
Emilian Peeve20c6372018-08-14 18:45:53 +0100429 uint32_t tagCount = 0;
430 std::vector<uint32_t> tagsToRemove;
431
432 if (tagsRemoved == nullptr) {
433 return BAD_VALUE;
434 }
435
436 sp<VendorTagDescriptor> vTags = VendorTagDescriptor::getGlobalVendorTagDescriptor();
437 if ((nullptr == vTags.get()) || (0 >= vTags->getTagCount())) {
438 sp<VendorTagDescriptorCache> cache =
439 VendorTagDescriptorCache::getGlobalVendorTagCache();
440 if (cache.get()) {
441 cache->getVendorTagDescriptor(vendorId, &vTags);
442 }
443 }
444
445 if ((nullptr != vTags.get()) && (vTags->getTagCount() > 0)) {
446 tagCount = vTags->getTagCount();
447 uint32_t *vendorTags = new uint32_t[tagCount];
448 if (nullptr == vendorTags) {
449 return NO_MEMORY;
450 }
451 vTags->getTagArray(vendorTags);
452
453 tagsToRemove.reserve(tagCount);
454 tagsToRemove.insert(tagsToRemove.begin(), vendorTags, vendorTags + tagCount);
455
456 delete [] vendorTags;
457 tagCount = 0;
458 }
459
460 auto tagsNeedingPermission = get_camera_metadata_permission_needed(&tagCount);
461 if (tagCount > 0) {
462 tagsToRemove.reserve(tagsToRemove.capacity() + tagCount);
463 tagsToRemove.insert(tagsToRemove.end(), tagsNeedingPermission,
464 tagsNeedingPermission + tagCount);
465 }
466
467 tagsRemoved->reserve(tagsToRemove.size());
468 for (const auto &it : tagsToRemove) {
469 if (exists(it)) {
470 auto rc = erase(it);
471 if (NO_ERROR != rc) {
472 ALOGE("%s: Failed to erase tag: %x", __func__, it);
473 return rc;
474 }
475 tagsRemoved->push_back(it);
476 }
477 }
478
479 // Update the available characterstics accordingly
480 if (exists(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS)) {
481 std::vector<uint32_t> currentKeys;
482
483 std::sort(tagsRemoved->begin(), tagsRemoved->end());
484 auto keys = find(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS);
485 currentKeys.reserve(keys.count);
486 currentKeys.insert(currentKeys.end(), keys.data.i32, keys.data.i32 + keys.count);
487 std::sort(currentKeys.begin(), currentKeys.end());
488
489 std::vector<int32_t> newKeys(keys.count);
490 auto end = std::set_difference(currentKeys.begin(), currentKeys.end(), tagsRemoved->begin(),
491 tagsRemoved->end(), newKeys.begin());
492 newKeys.resize(end - newKeys.begin());
493
494 update(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS, newKeys.data(), newKeys.size());
495 }
496
497 return NO_ERROR;
498}
499
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700500void CameraMetadata::dump(int fd, int verbosity, int indentation) const {
501 dump_indented_camera_metadata(mBuffer, fd, verbosity, indentation);
502}
503
504status_t CameraMetadata::resizeIfNeeded(size_t extraEntries, size_t extraData) {
Shuzhen Wang47cdcf32019-11-08 15:48:19 -0800505 ATRACE_CALL();
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700506 if (mBuffer == NULL) {
507 mBuffer = allocate_camera_metadata(extraEntries * 2, extraData * 2);
508 if (mBuffer == NULL) {
509 ALOGE("%s: Can't allocate larger metadata buffer", __FUNCTION__);
510 return NO_MEMORY;
511 }
512 } else {
513 size_t currentEntryCount = get_camera_metadata_entry_count(mBuffer);
514 size_t currentEntryCap = get_camera_metadata_entry_capacity(mBuffer);
515 size_t newEntryCount = currentEntryCount +
516 extraEntries;
517 newEntryCount = (newEntryCount > currentEntryCap) ?
518 newEntryCount * 2 : currentEntryCap;
519
520 size_t currentDataCount = get_camera_metadata_data_count(mBuffer);
521 size_t currentDataCap = get_camera_metadata_data_capacity(mBuffer);
522 size_t newDataCount = currentDataCount +
523 extraData;
524 newDataCount = (newDataCount > currentDataCap) ?
525 newDataCount * 2 : currentDataCap;
526
527 if (newEntryCount > currentEntryCap ||
528 newDataCount > currentDataCap) {
529 camera_metadata_t *oldBuffer = mBuffer;
530 mBuffer = allocate_camera_metadata(newEntryCount,
531 newDataCount);
532 if (mBuffer == NULL) {
533 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) {
Shuzhen Wang47cdcf32019-11-08 15:48:19 -0800545 ATRACE_CALL();
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) {
Shuzhen Wang47cdcf32019-11-08 15:48:19 -0800636 ATRACE_CALL();
Igor Murashkine7ee7632013-06-11 18:10:18 -0700637 status_t res = OK;
638
Zhijun He146aed12013-12-05 07:46:51 -0800639 /**
640 * Below is the camera metadata parcel layout:
641 *
642 * |--------------------------------------------|
643 * | arg0: blobSize |
644 * | (length = 4) |
645 * |--------------------------------------------|<--Skip the rest if blobSize == 0.
646 * | |
647 * | |
648 * | arg1: blob |
649 * | (length = variable, see arg1 layout below) |
650 * | |
651 * | |
652 * |--------------------------------------------|
653 * | arg2: offset |
654 * | (length = 4) |
655 * |--------------------------------------------|
656 */
Igor Murashkine7ee7632013-06-11 18:10:18 -0700657
Zhijun He146aed12013-12-05 07:46:51 -0800658 // arg0 = blobSize (int32)
Igor Murashkine7ee7632013-06-11 18:10:18 -0700659 if (metadata == NULL) {
Zhijun He146aed12013-12-05 07:46:51 -0800660 // Write zero blobSize for null metadata.
Igor Murashkine7ee7632013-06-11 18:10:18 -0700661 return data.writeInt32(0);
662 }
663
Zhijun He146aed12013-12-05 07:46:51 -0800664 /**
665 * Always make the blob size sufficiently larger, as we need put alignment
666 * padding and metadata into the blob. Since we don't know the alignment
667 * offset before writeBlob. Then write the metadata to aligned offset.
668 */
Igor Murashkine7ee7632013-06-11 18:10:18 -0700669 const size_t metadataSize = get_camera_metadata_compact_size(metadata);
Zhijun He146aed12013-12-05 07:46:51 -0800670 const size_t alignment = get_camera_metadata_alignment();
671 const size_t blobSize = metadataSize + alignment;
672 res = data.writeInt32(static_cast<int32_t>(blobSize));
Igor Murashkine7ee7632013-06-11 18:10:18 -0700673 if (res != OK) {
674 return res;
675 }
676
Zhijun He146aed12013-12-05 07:46:51 -0800677 size_t offset = 0;
678 /**
679 * arg1 = metadata (blob).
680 *
681 * The blob size is the sum of front padding size, metadata size and back padding
682 * size, which is equal to metadataSize + alignment.
683 *
684 * The blob layout is:
685 * |------------------------------------|<----Start address of the blob (unaligned).
686 * | front padding |
687 * | (size = offset) |
688 * |------------------------------------|<----Aligned start address of metadata.
689 * | |
690 * | |
691 * | metadata |
692 * | (size = metadataSize) |
693 * | |
694 * | |
695 * |------------------------------------|
696 * | back padding |
697 * | (size = alignment - offset) |
698 * |------------------------------------|<----End address of blob.
699 * (Blob start address + blob size).
700 */
Igor Murashkine7ee7632013-06-11 18:10:18 -0700701 WritableBlob blob;
702 do {
Jeff Browne8df5392015-06-05 15:10:44 -0700703 res = data.writeBlob(blobSize, false, &blob);
Igor Murashkine7ee7632013-06-11 18:10:18 -0700704 if (res != OK) {
705 break;
706 }
Zhijun He146aed12013-12-05 07:46:51 -0800707 const uintptr_t metadataStart = ALIGN_TO(blob.data(), alignment);
708 offset = metadataStart - reinterpret_cast<uintptr_t>(blob.data());
709 ALOGV("%s: alignment is: %zu, metadata start: %p, offset: %zu",
Mark Salyzyn1a93f0c2014-06-09 16:34:58 -0700710 __FUNCTION__, alignment,
711 reinterpret_cast<const void *>(metadataStart), offset);
Zhijun He146aed12013-12-05 07:46:51 -0800712 copy_camera_metadata(reinterpret_cast<void*>(metadataStart), metadataSize, metadata);
Igor Murashkine7ee7632013-06-11 18:10:18 -0700713
714 // Not too big of a problem since receiving side does hard validation
715 // Don't check the size since the compact size could be larger
716 if (validate_camera_metadata_structure(metadata, /*size*/NULL) != OK) {
717 ALOGW("%s: Failed to validate metadata %p before writing blob",
718 __FUNCTION__, metadata);
719 }
720
721 } while(false);
722 blob.release();
723
Zhijun He146aed12013-12-05 07:46:51 -0800724 // arg2 = offset (int32)
725 res = data.writeInt32(static_cast<int32_t>(offset));
726
Igor Murashkine7ee7632013-06-11 18:10:18 -0700727 return res;
728}
729
Eino-Ville Talvalad56db1d2015-12-17 16:50:35 -0800730status_t CameraMetadata::readFromParcel(const Parcel *parcel) {
Shuzhen Wang47cdcf32019-11-08 15:48:19 -0800731 ATRACE_CALL();
Igor Murashkine7ee7632013-06-11 18:10:18 -0700732 ALOGV("%s: parcel = %p", __FUNCTION__, parcel);
733
734 status_t res = OK;
735
736 if (parcel == NULL) {
737 ALOGE("%s: parcel is null", __FUNCTION__);
738 return BAD_VALUE;
739 }
740
741 if (mLocked) {
742 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
743 return INVALID_OPERATION;
744 }
745
746 camera_metadata *buffer = NULL;
747 // TODO: reading should return a status code, in case validation fails
748 res = CameraMetadata::readFromParcel(*parcel, &buffer);
749
750 if (res != NO_ERROR) {
751 ALOGE("%s: Failed to read from parcel. Metadata is unchanged.",
752 __FUNCTION__);
753 return res;
754 }
755
756 clear();
757 mBuffer = buffer;
758
759 return OK;
760}
761
762status_t CameraMetadata::writeToParcel(Parcel *parcel) const {
Shuzhen Wang47cdcf32019-11-08 15:48:19 -0800763 ATRACE_CALL();
Igor Murashkine7ee7632013-06-11 18:10:18 -0700764 ALOGV("%s: parcel = %p", __FUNCTION__, parcel);
765
766 if (parcel == NULL) {
767 ALOGE("%s: parcel is null", __FUNCTION__);
768 return BAD_VALUE;
769 }
770
771 return CameraMetadata::writeToParcel(*parcel, mBuffer);
772}
773
774void CameraMetadata::swap(CameraMetadata& other) {
775 if (mLocked) {
776 ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
777 return;
778 } else if (other.mLocked) {
779 ALOGE("%s: Other CameraMetadata is locked", __FUNCTION__);
780 return;
781 }
782
783 camera_metadata* thisBuf = mBuffer;
784 camera_metadata* otherBuf = other.mBuffer;
785
786 other.mBuffer = thisBuf;
787 mBuffer = otherBuf;
788}
789
Eino-Ville Talvala4d453832016-07-15 11:56:53 -0700790status_t CameraMetadata::getTagFromName(const char *name,
791 const VendorTagDescriptor* vTags, uint32_t *tag) {
Shuzhen Wang47cdcf32019-11-08 15:48:19 -0800792 ATRACE_CALL();
Eino-Ville Talvala4d453832016-07-15 11:56:53 -0700793 if (name == nullptr || tag == nullptr) return BAD_VALUE;
794
795 size_t nameLength = strlen(name);
796
797 const SortedVector<String8> *vendorSections;
798 size_t vendorSectionCount = 0;
799
800 if (vTags != NULL) {
801 vendorSections = vTags->getAllSectionNames();
802 vendorSectionCount = vendorSections->size();
803 }
804
805 // First, find the section by the longest string match
806 const char *section = NULL;
807 size_t sectionIndex = 0;
808 size_t sectionLength = 0;
809 size_t totalSectionCount = ANDROID_SECTION_COUNT + vendorSectionCount;
810 for (size_t i = 0; i < totalSectionCount; ++i) {
811
812 const char *str = (i < ANDROID_SECTION_COUNT) ? camera_metadata_section_names[i] :
813 (*vendorSections)[i - ANDROID_SECTION_COUNT].string();
814
815 ALOGV("%s: Trying to match against section '%s'", __FUNCTION__, str);
816
817 if (strstr(name, str) == name) { // name begins with the section name
818 size_t strLength = strlen(str);
819
820 ALOGV("%s: Name begins with section name", __FUNCTION__);
821
822 // section name is the longest we've found so far
823 if (section == NULL || sectionLength < strLength) {
824 section = str;
825 sectionIndex = i;
826 sectionLength = strLength;
827
828 ALOGV("%s: Found new best section (%s)", __FUNCTION__, section);
829 }
830 }
831 }
832
833 // TODO: Make above get_camera_metadata_section_from_name ?
834
835 if (section == NULL) {
836 return NAME_NOT_FOUND;
837 } else {
838 ALOGV("%s: Found matched section '%s' (%zu)",
839 __FUNCTION__, section, sectionIndex);
840 }
841
842 // Get the tag name component of the name
843 const char *nameTagName = name + sectionLength + 1; // x.y.z -> z
844 if (sectionLength + 1 >= nameLength) {
845 return BAD_VALUE;
846 }
847
848 // Match rest of name against the tag names in that section only
849 uint32_t candidateTag = 0;
850 if (sectionIndex < ANDROID_SECTION_COUNT) {
851 // Match built-in tags (typically android.*)
852 uint32_t tagBegin, tagEnd; // [tagBegin, tagEnd)
853 tagBegin = camera_metadata_section_bounds[sectionIndex][0];
854 tagEnd = camera_metadata_section_bounds[sectionIndex][1];
855
856 for (candidateTag = tagBegin; candidateTag < tagEnd; ++candidateTag) {
857 const char *tagName = get_camera_metadata_tag_name(candidateTag);
858
859 if (strcmp(nameTagName, tagName) == 0) {
860 ALOGV("%s: Found matched tag '%s' (%d)",
861 __FUNCTION__, tagName, candidateTag);
862 break;
863 }
864 }
865
866 if (candidateTag == tagEnd) {
867 return NAME_NOT_FOUND;
868 }
869 } else if (vTags != NULL) {
870 // Match vendor tags (typically com.*)
871 const String8 sectionName(section);
872 const String8 tagName(nameTagName);
873
874 status_t res = OK;
875 if ((res = vTags->lookupTag(tagName, sectionName, &candidateTag)) != OK) {
876 return NAME_NOT_FOUND;
877 }
878 }
879
880 *tag = candidateTag;
881 return OK;
882}
883
884
Eino-Ville Talvalacab96a42012-08-24 11:29:22 -0700885}; // namespace android