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