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 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 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 96 void TagMonitor::disableMonitoring() { 97 mMonitoringEnabled = false; 98 mLastMonitoredRequestValues.clear(); 99 mLastMonitoredResultValues.clear(); 100 } 101 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 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 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> 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 305 TagMonitor::MonitorEvent::~MonitorEvent() { 306 } 307 308 } // namespace android 309