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