Add 'watch' command to CameraService
Currently there is no way to monitor tags and dump per frame data from
Camera devices without calling dumpsys, which in turn dumps a lot of
unnecessary information.
This CL adds a 'watch' command to CameraService which can be called
through `cmd`. 'watch' provides a path to manage tag monitoring without
dumpsys. 'watch' currently has four functions:
1. start <taglist>: starts mornitoring the provided tags in attached
devices.
2. stop: stop monitoring all tags
3. live: prints monitored information to the terminal live
4. dump: dumps any collected camera traces
This CL adds a function to camera device each for the three tag
monitoring function listed above.
Test: n/a
Bug: 199746421
Change-Id: Ia5ce13f6e50c82085afcc676309cdbffef915a41
diff --git a/services/camera/libcameraservice/utils/CameraTraces.cpp b/services/camera/libcameraservice/utils/CameraTraces.cpp
index 0198690..0cd4f5d 100644
--- a/services/camera/libcameraservice/utils/CameraTraces.cpp
+++ b/services/camera/libcameraservice/utils/CameraTraces.cpp
@@ -64,7 +64,7 @@
ATRACE_END();
}
-status_t CameraTraces::dump(int fd, const Vector<String16> &args __attribute__((unused))) {
+status_t CameraTraces::dump(int fd) {
ALOGV("%s: fd = %d", __FUNCTION__, fd);
Mutex::Autolock al(sImpl.tracesLock);
List<ProcessCallStack>& pcsList = sImpl.pcsList;
diff --git a/services/camera/libcameraservice/utils/CameraTraces.h b/services/camera/libcameraservice/utils/CameraTraces.h
index 13ca16d..71fa334 100644
--- a/services/camera/libcameraservice/utils/CameraTraces.h
+++ b/services/camera/libcameraservice/utils/CameraTraces.h
@@ -42,7 +42,7 @@
*
* <p>Each line is indented by DUMP_INDENT spaces.</p>
*/
- static status_t dump(int fd, const Vector<String16>& args);
+ static status_t dump(int fd);
private:
enum {
diff --git a/services/camera/libcameraservice/utils/TagMonitor.cpp b/services/camera/libcameraservice/utils/TagMonitor.cpp
index 4488098..461f5e9 100644
--- a/services/camera/libcameraservice/utils/TagMonitor.cpp
+++ b/services/camera/libcameraservice/utils/TagMonitor.cpp
@@ -239,38 +239,59 @@
} 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.%s: ",
- event.frameNumber, event.timestamp,
- 2, event.cameraId.c_str(),
- indentation,
- event.source == REQUEST ? "REQ:" : "RES:",
- get_local_camera_metadata_section_name_vendor_id(event.tag,
- mVendorTagId),
- get_local_camera_metadata_tag_name_vendor_id(event.tag,
- mVendorTagId));
- 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, event.outputStreamIds, event.inputStreamId);
- }
- }
- }
+ if (mMonitoringEvents.size() == 0) { return; }
+
+ dprintf(fd, " Monitored tag event log:\n");
+
+ std::vector<std::string> eventStrs;
+ dumpMonitoredTagEventsToVectorLocked(eventStrs);
+ for (const std::string &eventStr : eventStrs) {
+ dprintf(fd, " %s", eventStr.c_str());
+ }
}
-// TODO: Consolidate with printData from camera_metadata.h
+void TagMonitor::getLatestMonitoredTagEvents(std::vector<std::string> &out) {
+ std::lock_guard<std::mutex> lock(mMonitorMutex);
+ dumpMonitoredTagEventsToVectorLocked(out);
+}
+
+void TagMonitor::dumpMonitoredTagEventsToVectorLocked(std::vector<std::string> &vec) {
+ if (mMonitoringEvents.size() == 0) { return; }
+
+ for (const auto& event : mMonitoringEvents) {
+ int indentation = (event.source == REQUEST) ? 15 : 30;
+ String8 eventString = String8::format("f%d:%" PRId64 "ns:%*s%*s%s.%s: ",
+ event.frameNumber, event.timestamp,
+ 2, event.cameraId.c_str(),
+ indentation,
+ event.source == REQUEST ? "REQ:" : "RES:",
+ get_local_camera_metadata_section_name_vendor_id(event.tag, mVendorTagId),
+ get_local_camera_metadata_tag_name_vendor_id(event.tag, mVendorTagId));
+ if (event.newData.size() == 0) {
+ eventString += " (Removed)";
+ } else {
+ eventString += getEventDataString(event.newData.data(),
+ event.tag,
+ event.type,
+ event.newData.size() / camera_metadata_type_size[event.type],
+ indentation + 18,
+ event.outputStreamIds,
+ event.inputStreamId);
+ }
+ vec.emplace_back(eventString.string());
+ }
+}
#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, const std::unordered_set<int32_t> &outputStreamIds,
- int32_t inputStreamId) {
+String8 TagMonitor::getEventDataString(const uint8_t* data_ptr,
+ uint32_t tag,
+ int type,
+ int count,
+ int indentation,
+ const std::unordered_set<int32_t>& outputStreamIds,
+ int32_t inputStreamId) {
static int values_per_line[NUM_TYPES] = {
[TYPE_BYTE] = 16,
[TYPE_INT32] = 8,
@@ -279,6 +300,7 @@
[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;
@@ -286,10 +308,11 @@
int lines = count / values_per_line[type];
if (count % values_per_line[type] != 0) lines++;
+ String8 returnStr = String8();
int index = 0;
int j, k;
for (j = 0; j < lines; j++) {
- dprintf(fd, "%*s[", (j != 0) ? indentation + 4 : 0, "");
+ returnStr.appendFormat("%*s[", (j != 0) ? indentation + 4 : 0, "");
for (k = 0;
k < values_per_line[type] && count > 0;
k++, count--, index += type_size) {
@@ -302,10 +325,9 @@
value_string_tmp,
sizeof(value_string_tmp))
== OK) {
- dprintf(fd, "%s ", value_string_tmp);
+ returnStr += value_string_tmp;
} else {
- dprintf(fd, "%hhu ",
- *(data_ptr + index));
+ returnStr.appendFormat("%hhu", *(data_ptr + index));
}
break;
case TYPE_INT32:
@@ -316,47 +338,43 @@
value_string_tmp,
sizeof(value_string_tmp))
== OK) {
- dprintf(fd, "%s ", value_string_tmp);
+ returnStr += value_string_tmp;
} else {
- dprintf(fd, "%" PRId32 " ",
- *(int32_t*)(data_ptr + index));
+ returnStr.appendFormat("%" PRId32 " ", *(int32_t*)(data_ptr + index));
}
break;
case TYPE_FLOAT:
- dprintf(fd, "%0.8f ",
- *(float*)(data_ptr + index));
+ returnStr.appendFormat("%0.8f", *(float*)(data_ptr + index));
break;
case TYPE_INT64:
- dprintf(fd, "%" PRId64 " ",
- *(int64_t*)(data_ptr + index));
+ returnStr.appendFormat("%" PRId64 " ", *(int64_t*)(data_ptr + index));
break;
case TYPE_DOUBLE:
- dprintf(fd, "%0.8f ",
- *(double*)(data_ptr + index));
+ returnStr.appendFormat("%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);
+ returnStr.appendFormat("(%d / %d) ", numerator, denominator);
break;
}
default:
- dprintf(fd, "??? ");
+ returnStr += "??? ";
}
}
- dprintf(fd, "] ");
- if (outputStreamIds.size() > 0) {
- dprintf(fd, "output stream ids: ");
+ returnStr += "] ";
+ if (!outputStreamIds.empty()) {
+ returnStr += "output stream ids: ";
for (const auto &id : outputStreamIds) {
- dprintf(fd, " %d ", id);
+ returnStr.appendFormat(" %d ", id);
}
}
if (inputStreamId != -1) {
- dprintf(fd, "input stream id: %d", inputStreamId);
+ returnStr.appendFormat("input stream id: %d", inputStreamId);
}
- dprintf(fd, "\n");
+ returnStr += "\n";
}
+ return returnStr;
}
template<typename T>
diff --git a/services/camera/libcameraservice/utils/TagMonitor.h b/services/camera/libcameraservice/utils/TagMonitor.h
index f6df4b7..088d6fe 100644
--- a/services/camera/libcameraservice/utils/TagMonitor.h
+++ b/services/camera/libcameraservice/utils/TagMonitor.h
@@ -74,11 +74,23 @@
// Dump current event log to the provided fd
void dumpMonitoredMetadata(int fd);
- private:
+ // Dumps the latest monitored Tag events to the passed vector.
+ // NOTE: The events are appended to the vector in reverser chronological order
+ // (i.e. most recent first)
+ void getLatestMonitoredTagEvents(std::vector<std::string> &out);
- static void printData(int fd, const uint8_t *data_ptr, uint32_t tag,
- int type, int count, int indentation,
- const std::unordered_set<int32_t> &outputStreamIds, int32_t inputStreamId);
+ private:
+ // Dumps monitored tag events to the passed vector without acquiring
+ // mMonitorMutex. mMonitorMutex must be acquired before calling this
+ // function.
+ void dumpMonitoredTagEventsToVectorLocked(std::vector<std::string> &out);
+
+ static String8 getEventDataString(const uint8_t *data_ptr,
+ uint32_t tag, int type,
+ int count,
+ int indentation,
+ const std::unordered_set<int32_t> &outputStreamIds,
+ int32_t inputStreamId);
void monitorSingleMetadata(TagMonitor::eventSource source, int64_t frameNumber,
nsecs_t timestamp, const std::string& cameraId, uint32_t tag,