• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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