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