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