| /* |
| * Copyright (C) 2016 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #define LOG_TAG "Camera3-TagMonitor" |
| #define ATRACE_TAG ATRACE_TAG_CAMERA |
| //#define LOG_NDEBUG 0 |
| |
| #include "TagMonitor.h" |
| |
| #include <inttypes.h> |
| #include <utils/Log.h> |
| #include <camera/VendorTagDescriptor.h> |
| |
| namespace android { |
| |
| TagMonitor::TagMonitor(): |
| mMonitoringEnabled(false), |
| mMonitoringEvents(kMaxMonitorEvents) |
| {} |
| |
| const char* TagMonitor::k3aTags = |
| "android.control.aeMode, android.control.afMode, android.control.awbMode," |
| "android.control.aeState, android.control.afState, android.control.awbState," |
| "android.control.aePrecaptureTrigger, android.control.afTrigger," |
| "android.control.aeRegions, android.control.awbRegions, android.control.afRegions," |
| "android.control.aeExposureCompensation, android.control.aeLock, android.control.awbLock," |
| "android.control.aeAntibandingMode, android.control.aeTargetFpsRange," |
| "android.control.effectMode, android.control.mode, android.control.sceneMode," |
| "android.control.videoStabilizationMode"; |
| |
| void TagMonitor::parseTagsToMonitor(String8 tagNames) { |
| std::lock_guard<std::mutex> lock(mMonitorMutex); |
| |
| // Expand shorthands |
| if (ssize_t idx = tagNames.find("3a") != -1) { |
| ssize_t end = tagNames.find(",", idx); |
| char* start = tagNames.lockBuffer(tagNames.size()); |
| start[idx] = '\0'; |
| char* rest = (end != -1) ? (start + end) : (start + tagNames.size()); |
| tagNames = String8::format("%s%s%s", start, k3aTags, rest); |
| } |
| |
| sp<VendorTagDescriptor> vTags = |
| VendorTagDescriptor::getGlobalVendorTagDescriptor(); |
| |
| bool gotTag = false; |
| |
| char *tokenized = tagNames.lockBuffer(tagNames.size()); |
| char *savePtr; |
| char *nextTagName = strtok_r(tokenized, ", ", &savePtr); |
| while (nextTagName != nullptr) { |
| uint32_t tag; |
| status_t res = CameraMetadata::getTagFromName(nextTagName, vTags.get(), &tag); |
| if (res != OK) { |
| ALOGW("%s: Unknown tag %s, ignoring", __FUNCTION__, nextTagName); |
| } else { |
| if (!gotTag) { |
| mMonitoredTagList.clear(); |
| gotTag = true; |
| } |
| mMonitoredTagList.push_back(tag); |
| } |
| nextTagName = strtok_r(nullptr, ", ", &savePtr); |
| } |
| |
| tagNames.unlockBuffer(); |
| |
| if (gotTag) { |
| // Got at least one new tag |
| mMonitoringEnabled = true; |
| } |
| } |
| |
| void TagMonitor::disableMonitoring() { |
| mMonitoringEnabled = false; |
| mLastMonitoredRequestValues.clear(); |
| mLastMonitoredResultValues.clear(); |
| } |
| |
| void TagMonitor::monitorMetadata(eventSource source, int64_t frameNumber, nsecs_t timestamp, |
| const CameraMetadata& metadata) { |
| if (!mMonitoringEnabled) return; |
| |
| std::lock_guard<std::mutex> lock(mMonitorMutex); |
| |
| if (timestamp == 0) { |
| timestamp = systemTime(SYSTEM_TIME_BOOTTIME); |
| } |
| |
| for (auto tag : mMonitoredTagList) { |
| camera_metadata_ro_entry entry = metadata.find(tag); |
| CameraMetadata &lastValues = (source == REQUEST) ? |
| mLastMonitoredRequestValues : mLastMonitoredResultValues; |
| camera_metadata_entry lastEntry = lastValues.find(tag); |
| |
| if (entry.count > 0) { |
| bool isDifferent = false; |
| if (lastEntry.count > 0) { |
| // Have a last value, compare to see if changed |
| if (lastEntry.type == entry.type && |
| lastEntry.count == entry.count) { |
| // Same type and count, compare values |
| size_t bytesPerValue = camera_metadata_type_size[lastEntry.type]; |
| size_t entryBytes = bytesPerValue * lastEntry.count; |
| int cmp = memcmp(entry.data.u8, lastEntry.data.u8, entryBytes); |
| if (cmp != 0) { |
| isDifferent = true; |
| } |
| } else { |
| // Count or type has changed |
| isDifferent = true; |
| } |
| } else { |
| // No last entry, so always consider to be different |
| isDifferent = true; |
| } |
| |
| if (isDifferent) { |
| ALOGV("%s: Tag %s changed", __FUNCTION__, get_camera_metadata_tag_name(tag)); |
| lastValues.update(entry); |
| mMonitoringEvents.emplace(source, frameNumber, timestamp, entry); |
| } |
| } else if (lastEntry.count > 0) { |
| // Value has been removed |
| ALOGV("%s: Tag %s removed", __FUNCTION__, get_camera_metadata_tag_name(tag)); |
| lastValues.erase(tag); |
| entry.tag = tag; |
| entry.type = get_camera_metadata_tag_type(tag); |
| entry.count = 0; |
| mMonitoringEvents.emplace(source, frameNumber, timestamp, entry); |
| } |
| } |
| } |
| |
| void TagMonitor::dumpMonitoredMetadata(int fd) { |
| std::lock_guard<std::mutex> lock(mMonitorMutex); |
| |
| if (mMonitoringEnabled) { |
| dprintf(fd, " Tag monitoring enabled for tags:\n"); |
| for (uint32_t tag : mMonitoredTagList) { |
| dprintf(fd, " %s.%s\n", |
| get_camera_metadata_section_name(tag), |
| get_camera_metadata_tag_name(tag)); |
| } |
| } else { |
| dprintf(fd, " Tag monitoring disabled (enable with -m <name1,..,nameN>)\n"); |
| } |
| if (mMonitoringEvents.size() > 0) { |
| dprintf(fd, " Monitored tag event log:\n"); |
| for (const auto& event : mMonitoringEvents) { |
| int indentation = (event.source == REQUEST) ? 15 : 30; |
| dprintf(fd, " f%d:%" PRId64 "ns: %*s%s.%s: ", |
| event.frameNumber, event.timestamp, |
| indentation, |
| event.source == REQUEST ? "REQ:" : "RES:", |
| get_camera_metadata_section_name(event.tag), |
| get_camera_metadata_tag_name(event.tag)); |
| if (event.newData.size() == 0) { |
| dprintf(fd, " (Removed)\n"); |
| } else { |
| printData(fd, event.newData.data(), event.tag, |
| event.type, event.newData.size() / camera_metadata_type_size[event.type], |
| indentation + 18); |
| } |
| } |
| } |
| |
| } |
| |
| // TODO: Consolidate with printData from camera_metadata.h |
| |
| #define CAMERA_METADATA_ENUM_STRING_MAX_SIZE 29 |
| |
| void TagMonitor::printData(int fd, const uint8_t *data_ptr, uint32_t tag, |
| int type, int count, int indentation) { |
| static int values_per_line[NUM_TYPES] = { |
| [TYPE_BYTE] = 16, |
| [TYPE_INT32] = 8, |
| [TYPE_FLOAT] = 8, |
| [TYPE_INT64] = 4, |
| [TYPE_DOUBLE] = 4, |
| [TYPE_RATIONAL] = 4, |
| }; |
| size_t type_size = camera_metadata_type_size[type]; |
| char value_string_tmp[CAMERA_METADATA_ENUM_STRING_MAX_SIZE]; |
| uint32_t value; |
| |
| int lines = count / values_per_line[type]; |
| if (count % values_per_line[type] != 0) lines++; |
| |
| int index = 0; |
| int j, k; |
| for (j = 0; j < lines; j++) { |
| dprintf(fd, "%*s[", (j != 0) ? indentation + 4 : 0, ""); |
| for (k = 0; |
| k < values_per_line[type] && count > 0; |
| k++, count--, index += type_size) { |
| |
| switch (type) { |
| case TYPE_BYTE: |
| value = *(data_ptr + index); |
| if (camera_metadata_enum_snprint(tag, |
| value, |
| value_string_tmp, |
| sizeof(value_string_tmp)) |
| == OK) { |
| dprintf(fd, "%s ", value_string_tmp); |
| } else { |
| dprintf(fd, "%hhu ", |
| *(data_ptr + index)); |
| } |
| break; |
| case TYPE_INT32: |
| value = |
| *(int32_t*)(data_ptr + index); |
| if (camera_metadata_enum_snprint(tag, |
| value, |
| value_string_tmp, |
| sizeof(value_string_tmp)) |
| == OK) { |
| dprintf(fd, "%s ", value_string_tmp); |
| } else { |
| dprintf(fd, "%" PRId32 " ", |
| *(int32_t*)(data_ptr + index)); |
| } |
| break; |
| case TYPE_FLOAT: |
| dprintf(fd, "%0.8f ", |
| *(float*)(data_ptr + index)); |
| break; |
| case TYPE_INT64: |
| dprintf(fd, "%" PRId64 " ", |
| *(int64_t*)(data_ptr + index)); |
| break; |
| case TYPE_DOUBLE: |
| dprintf(fd, "%0.8f ", |
| *(double*)(data_ptr + index)); |
| break; |
| case TYPE_RATIONAL: { |
| int32_t numerator = *(int32_t*)(data_ptr + index); |
| int32_t denominator = *(int32_t*)(data_ptr + index + 4); |
| dprintf(fd, "(%d / %d) ", |
| numerator, denominator); |
| break; |
| } |
| default: |
| dprintf(fd, "??? "); |
| } |
| } |
| dprintf(fd, "]\n"); |
| } |
| } |
| |
| template<typename T> |
| TagMonitor::MonitorEvent::MonitorEvent(eventSource src, uint32_t frameNumber, nsecs_t timestamp, |
| const T &value) : |
| source(src), |
| frameNumber(frameNumber), |
| timestamp(timestamp), |
| tag(value.tag), |
| type(value.type), |
| newData(value.data.u8, value.data.u8 + camera_metadata_type_size[value.type] * value.count) { |
| } |
| |
| TagMonitor::MonitorEvent::~MonitorEvent() { |
| } |
| |
| } // namespace android |