1 /*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #define LOG_TAG "Camera3-TagMonitor"
18 #define ATRACE_TAG ATRACE_TAG_CAMERA
19 //#define LOG_NDEBUG 0
20
21 #include <iostream>
22 #include <sstream>
23
24 #include "TagMonitor.h"
25
26 #include <inttypes.h>
27 #include <utils/Log.h>
28 #include <camera/VendorTagDescriptor.h>
29 #include <camera/StringUtils.h>
30 #include <camera_metadata_hidden.h>
31 #include <device3/Camera3Stream.h>
32
33 namespace android {
34
TagMonitor()35 TagMonitor::TagMonitor():
36 mMonitoringEnabled(false),
37 mMonitoringEvents(kMaxMonitorEvents),
38 mVendorTagId(CAMERA_METADATA_INVALID_VENDOR_ID)
39 {}
40
TagMonitor(const TagMonitor & other)41 TagMonitor::TagMonitor(const TagMonitor& other):
42 mMonitoringEnabled(other.mMonitoringEnabled.load()),
43 mMonitoredTagList(other.mMonitoredTagList),
44 mLastMonitoredRequestValues(other.mLastMonitoredRequestValues),
45 mLastMonitoredResultValues(other.mLastMonitoredResultValues),
46 mLastMonitoredPhysicalRequestKeys(other.mLastMonitoredPhysicalRequestKeys),
47 mLastMonitoredPhysicalResultKeys(other.mLastMonitoredPhysicalResultKeys),
48 mMonitoringEvents(other.mMonitoringEvents),
49 mVendorTagId(other.mVendorTagId) {}
50
51 const std::string TagMonitor::kMonitorOption("-m");
52
53 const char* TagMonitor::k3aTags =
54 "android.control.aeMode, android.control.afMode, android.control.awbMode,"
55 "android.control.aeState, android.control.afState, android.control.awbState,"
56 "android.control.aePrecaptureTrigger, android.control.afTrigger,"
57 "android.control.aeRegions, android.control.awbRegions, android.control.afRegions,"
58 "android.control.aeExposureCompensation, android.control.aeLock, android.control.awbLock,"
59 "android.control.aeAntibandingMode, android.control.aeTargetFpsRange,"
60 "android.control.effectMode, android.control.mode, android.control.sceneMode,"
61 "android.control.videoStabilizationMode";
62
parseTagsToMonitor(std::string tagNames)63 void TagMonitor::parseTagsToMonitor(std::string tagNames) {
64 std::lock_guard<std::mutex> lock(mMonitorMutex);
65
66 // Expand shorthands
67 ssize_t idx = tagNames.find("3a");
68 if (idx != -1) {
69 ssize_t end = tagNames.find(",", idx);
70 tagNames = tagNames.substr(0, idx) + k3aTags;
71 if (end != -1) {
72 tagNames += tagNames.substr(end);
73 }
74 }
75
76 sp<VendorTagDescriptor> vTags =
77 VendorTagDescriptor::getGlobalVendorTagDescriptor();
78 if ((nullptr == vTags.get()) || (0 >= vTags->getTagCount())) {
79 sp<VendorTagDescriptorCache> cache =
80 VendorTagDescriptorCache::getGlobalVendorTagCache();
81 if (cache.get()) {
82 cache->getVendorTagDescriptor(mVendorTagId, &vTags);
83 }
84 }
85
86 bool gotTag = false;
87
88 std::istringstream iss(tagNames);
89 std::string nextTagName;
90 while (std::getline(iss, nextTagName, ',')) {
91 uint32_t tag;
92 status_t res = CameraMetadata::getTagFromName(nextTagName.c_str(), vTags.get(), &tag);
93 if (res != OK) {
94 ALOGW("%s: Unknown tag %s, ignoring", __FUNCTION__, nextTagName.c_str());
95 } else {
96 if (!gotTag) {
97 mMonitoredTagList.clear();
98 gotTag = true;
99 }
100 mMonitoredTagList.push_back(tag);
101 }
102 iss >> std::ws;
103 }
104
105 if (gotTag) {
106 // Got at least one new tag
107 mMonitoringEnabled = true;
108 }
109 }
110
disableMonitoring()111 void TagMonitor::disableMonitoring() {
112 mMonitoringEnabled = false;
113 mLastMonitoredRequestValues.clear();
114 mLastMonitoredResultValues.clear();
115 mLastMonitoredPhysicalRequestKeys.clear();
116 mLastMonitoredPhysicalResultKeys.clear();
117 mLastStreamIds.clear();
118 mLastInputStreamId = -1;
119 }
120
monitorMetadata(eventSource source,int64_t frameNumber,nsecs_t timestamp,const CameraMetadata & metadata,const std::unordered_map<std::string,CameraMetadata> & physicalMetadata,const camera3::camera_stream_buffer_t * outputBuffers,uint32_t numOutputBuffers,int32_t inputStreamId)121 void TagMonitor::monitorMetadata(eventSource source, int64_t frameNumber, nsecs_t timestamp,
122 const CameraMetadata& metadata,
123 const std::unordered_map<std::string, CameraMetadata>& physicalMetadata,
124 const camera3::camera_stream_buffer_t *outputBuffers, uint32_t numOutputBuffers,
125 int32_t inputStreamId) {
126 if (!mMonitoringEnabled) return;
127
128 std::lock_guard<std::mutex> lock(mMonitorMutex);
129
130 if (timestamp == 0) {
131 timestamp = systemTime(SYSTEM_TIME_BOOTTIME);
132 }
133 std::unordered_set<int32_t> outputStreamIds;
134 for (size_t i = 0; i < numOutputBuffers; i++) {
135 const camera3::camera_stream_buffer_t *src = outputBuffers + i;
136 int32_t streamId = camera3::Camera3Stream::cast(src->stream)->getId();
137 outputStreamIds.emplace(streamId);
138 }
139 std::string emptyId;
140 for (auto tag : mMonitoredTagList) {
141 monitorSingleMetadata(source, frameNumber, timestamp, emptyId, tag, metadata,
142 outputStreamIds, inputStreamId);
143
144 for (auto& m : physicalMetadata) {
145 monitorSingleMetadata(source, frameNumber, timestamp, m.first, tag, m.second,
146 outputStreamIds, inputStreamId);
147 }
148 }
149 }
150
monitorSingleMetadata(eventSource source,int64_t frameNumber,nsecs_t timestamp,const std::string & cameraId,uint32_t tag,const CameraMetadata & metadata,const std::unordered_set<int32_t> & outputStreamIds,int32_t inputStreamId)151 void TagMonitor::monitorSingleMetadata(eventSource source, int64_t frameNumber, nsecs_t timestamp,
152 const std::string& cameraId, uint32_t tag, const CameraMetadata& metadata,
153 const std::unordered_set<int32_t> &outputStreamIds, int32_t inputStreamId) {
154
155 CameraMetadata &lastValues = (source == REQUEST) ?
156 (cameraId.empty() ? mLastMonitoredRequestValues :
157 mLastMonitoredPhysicalRequestKeys[cameraId]) :
158 (cameraId.empty() ? mLastMonitoredResultValues :
159 mLastMonitoredPhysicalResultKeys[cameraId]);
160
161 camera_metadata_ro_entry entry = metadata.find(tag);
162 if (lastValues.isEmpty()) {
163 lastValues = CameraMetadata(mMonitoredTagList.size());
164 const camera_metadata_t *metaBuffer =
165 lastValues.getAndLock();
166 set_camera_metadata_vendor_id(
167 const_cast<camera_metadata_t *> (metaBuffer), mVendorTagId);
168 lastValues.unlock(metaBuffer);
169 }
170
171 camera_metadata_entry lastEntry = lastValues.find(tag);
172
173 // Monitor when the stream ids change, this helps visually see what
174 // monitored metadata values are for capture requests with different
175 // stream ids.
176 if (source == REQUEST) {
177 if (inputStreamId != mLastInputStreamId) {
178 mMonitoringEvents.emplace(source, frameNumber, timestamp, camera_metadata_ro_entry_t{},
179 cameraId, std::unordered_set<int>(), inputStreamId);
180 mLastInputStreamId = inputStreamId;
181 }
182
183 if (outputStreamIds != mLastStreamIds) {
184 mMonitoringEvents.emplace(source, frameNumber, timestamp, camera_metadata_ro_entry_t{},
185 cameraId, outputStreamIds, -1);
186 mLastStreamIds = outputStreamIds;
187 }
188 }
189 if (entry.count > 0) {
190 bool isDifferent = false;
191 if (lastEntry.count > 0) {
192 // Have a last value, compare to see if changed
193 if (lastEntry.type == entry.type &&
194 lastEntry.count == entry.count) {
195 // Same type and count, compare values
196 size_t bytesPerValue = camera_metadata_type_size[lastEntry.type];
197 size_t entryBytes = bytesPerValue * lastEntry.count;
198 int cmp = memcmp(entry.data.u8, lastEntry.data.u8, entryBytes);
199 if (cmp != 0) {
200 isDifferent = true;
201 }
202 } else {
203 // Count or type has changed
204 isDifferent = true;
205 }
206 } else {
207 // No last entry, so always consider to be different
208 isDifferent = true;
209 }
210
211 if (isDifferent) {
212 ALOGV("%s: Tag %s changed", __FUNCTION__,
213 get_local_camera_metadata_tag_name_vendor_id(
214 tag, mVendorTagId));
215 lastValues.update(entry);
216 mMonitoringEvents.emplace(source, frameNumber, timestamp, entry, cameraId,
217 std::unordered_set<int>(), -1);
218 }
219 } else if (lastEntry.count > 0) {
220 // Value has been removed
221 ALOGV("%s: Tag %s removed", __FUNCTION__,
222 get_local_camera_metadata_tag_name_vendor_id(
223 tag, mVendorTagId));
224 lastValues.erase(tag);
225 entry.tag = tag;
226 entry.type = get_local_camera_metadata_tag_type_vendor_id(tag,
227 mVendorTagId);
228 entry.count = 0;
229 mLastInputStreamId = inputStreamId;
230 mLastStreamIds = outputStreamIds;
231 mMonitoringEvents.emplace(source, frameNumber, timestamp, entry, cameraId,
232 std::unordered_set<int>(), -1);
233 }
234 }
235
dumpMonitoredMetadata(int fd)236 void TagMonitor::dumpMonitoredMetadata(int fd) {
237 std::lock_guard<std::mutex> lock(mMonitorMutex);
238
239 if (mMonitoringEnabled) {
240 dprintf(fd, " Tag monitoring enabled for tags:\n");
241 for (uint32_t tag : mMonitoredTagList) {
242 dprintf(fd, " %s.%s\n",
243 get_local_camera_metadata_section_name_vendor_id(tag,
244 mVendorTagId),
245 get_local_camera_metadata_tag_name_vendor_id(tag,
246 mVendorTagId));
247 }
248 } else {
249 dprintf(fd, " Tag monitoring disabled (enable with -m <name1,..,nameN>)\n");
250 }
251
252 if (mMonitoringEvents.size() == 0) { return; }
253
254 dprintf(fd, " Monitored tag event log:\n");
255
256 std::vector<std::string> eventStrs;
257 dumpMonitoredTagEventsToVectorLocked(eventStrs);
258 for (const std::string &eventStr : eventStrs) {
259 dprintf(fd, " %s", eventStr.c_str());
260 }
261 }
262
getLatestMonitoredTagEvents(std::vector<std::string> & out)263 void TagMonitor::getLatestMonitoredTagEvents(std::vector<std::string> &out) {
264 std::lock_guard<std::mutex> lock(mMonitorMutex);
265 dumpMonitoredTagEventsToVectorLocked(out);
266 }
267
dumpMonitoredTagEventsToVectorLocked(std::vector<std::string> & vec)268 void TagMonitor::dumpMonitoredTagEventsToVectorLocked(std::vector<std::string> &vec) {
269 if (mMonitoringEvents.size() == 0) { return; }
270
271 for (const auto& event : mMonitoringEvents) {
272 int indentation = (event.source == REQUEST) ? 15 : 30;
273 std::string eventString = fmt::sprintf("f%d:%" PRId64 "ns:%*s%*s",
274 event.frameNumber, event.timestamp,
275 2, event.cameraId.c_str(),
276 indentation,
277 event.source == REQUEST ? "REQ:" : "RES:");
278
279 if (!event.outputStreamIds.empty()) {
280 eventString += " output stream ids:";
281 for (const auto& id : event.outputStreamIds) {
282 eventString += fmt::sprintf(" %d", id);
283 }
284 eventString += "\n";
285 vec.emplace_back(eventString);
286 continue;
287 }
288
289 if (event.inputStreamId != -1) {
290 eventString += fmt::sprintf(" input stream id: %d\n", event.inputStreamId);
291 vec.emplace_back(eventString);
292 continue;
293 }
294
295 eventString += fmt::sprintf(
296 "%s.%s: ",
297 get_local_camera_metadata_section_name_vendor_id(event.tag, mVendorTagId),
298 get_local_camera_metadata_tag_name_vendor_id(event.tag, mVendorTagId));
299
300 if (event.newData.empty()) {
301 eventString += " (Removed)\n";
302 } else {
303 eventString += getEventDataString(
304 event.newData.data(), event.tag, event.type,
305 event.newData.size() / camera_metadata_type_size[event.type], indentation + 18);
306 }
307 vec.emplace_back(eventString);
308 }
309 }
310
311 #define CAMERA_METADATA_ENUM_STRING_MAX_SIZE 29
312
getEventDataString(const uint8_t * data_ptr,uint32_t tag,int type,int count,int indentation)313 std::string TagMonitor::getEventDataString(const uint8_t* data_ptr, uint32_t tag, int type,
314 int count, int indentation) {
315 static int values_per_line[NUM_TYPES] = {
316 [TYPE_BYTE] = 16,
317 [TYPE_INT32] = 8,
318 [TYPE_FLOAT] = 8,
319 [TYPE_INT64] = 4,
320 [TYPE_DOUBLE] = 4,
321 [TYPE_RATIONAL] = 4,
322 };
323
324 size_t type_size = camera_metadata_type_size[type];
325 char value_string_tmp[CAMERA_METADATA_ENUM_STRING_MAX_SIZE];
326 uint32_t value;
327
328 int lines = count / values_per_line[type];
329 if (count % values_per_line[type] != 0) lines++;
330
331 std::ostringstream returnStr;
332 int index = 0;
333 int j, k;
334 for (j = 0; j < lines; j++) {
335 returnStr << fmt::sprintf("%*s[", (j != 0) ? indentation + 4 : 0, "");
336 for (k = 0;
337 k < values_per_line[type] && count > 0;
338 k++, count--, index += type_size) {
339
340 switch (type) {
341 case TYPE_BYTE:
342 value = *(data_ptr + index);
343 if (camera_metadata_enum_snprint(tag,
344 value,
345 value_string_tmp,
346 sizeof(value_string_tmp))
347 == OK) {
348 returnStr << value_string_tmp;
349 } else {
350 returnStr << fmt::sprintf("%hhu ", *(data_ptr + index));
351 }
352 break;
353 case TYPE_INT32:
354 value =
355 *(int32_t*)(data_ptr + index);
356 if (camera_metadata_enum_snprint(tag,
357 value,
358 value_string_tmp,
359 sizeof(value_string_tmp))
360 == OK) {
361 returnStr << value_string_tmp;
362 } else {
363 returnStr << fmt::sprintf("%" PRId32 " ", *(int32_t*)(data_ptr + index));
364 }
365 break;
366 case TYPE_FLOAT:
367 returnStr << fmt::sprintf("%0.8f ", *(float*)(data_ptr + index));
368 break;
369 case TYPE_INT64:
370 returnStr << fmt::sprintf("%" PRId64 " ", *(int64_t*)(data_ptr + index));
371 break;
372 case TYPE_DOUBLE:
373 returnStr << fmt::sprintf("%0.8f ", *(double*)(data_ptr + index));
374 break;
375 case TYPE_RATIONAL: {
376 int32_t numerator = *(int32_t*)(data_ptr + index);
377 int32_t denominator = *(int32_t*)(data_ptr + index + 4);
378 returnStr << fmt::sprintf("(%d / %d) ", numerator, denominator);
379 break;
380 }
381 default:
382 returnStr << "??? ";
383 }
384 }
385 returnStr << "]\n";
386 }
387 return std::move(returnStr.str());
388 }
389
390 template<typename T>
MonitorEvent(eventSource src,uint32_t frameNumber,nsecs_t timestamp,const T & value,const std::string & cameraId,const std::unordered_set<int32_t> & outputStreamIds,int32_t inputStreamId)391 TagMonitor::MonitorEvent::MonitorEvent(eventSource src, uint32_t frameNumber, nsecs_t timestamp,
392 const T &value, const std::string& cameraId,
393 const std::unordered_set<int32_t> &outputStreamIds,
394 int32_t inputStreamId) :
395 source(src),
396 frameNumber(frameNumber),
397 timestamp(timestamp),
398 cameraId(cameraId),
399 tag(value.tag),
400 type(value.type),
401 newData(value.data.u8, value.data.u8 + camera_metadata_type_size[value.type] * value.count),
402 outputStreamIds(outputStreamIds),
403 inputStreamId(inputStreamId) {}
404
~MonitorEvent()405 TagMonitor::MonitorEvent::~MonitorEvent() {
406 }
407
408 } // namespace android
409