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