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