Boost priority of short-running SF FIFO threads slightly.
am: 35520634e2
Change-Id: Ic4a53cc1399dff489414ac1c891a041c2500b8e2
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index facf300..5885738 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -102,6 +102,7 @@
{ "pm", "Package Manager", ATRACE_TAG_PACKAGE_MANAGER, { } },
{ "ss", "System Server", ATRACE_TAG_SYSTEM_SERVER, { } },
{ "database", "Database", ATRACE_TAG_DATABASE, { } },
+ { "network", "Network", ATRACE_TAG_NETWORK, { } },
{ k_coreServiceCategory, "Core services", 0, { } },
{ "sched", "CPU Scheduling", 0, {
{ REQ, "/sys/kernel/debug/tracing/events/sched/sched_switch/enable" },
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 23629b3..d51fb77 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -35,6 +35,7 @@
#include <unistd.h>
#include <android-base/stringprintf.h>
+#include <android-base/file.h>
#include <cutils/properties.h>
#include "private/android_filesystem_config.h"
@@ -179,6 +180,118 @@
closedir(d);
}
+// return pid of a userspace process. If not found or error, return 0.
+static unsigned int pid_of_process(const char* ps_name) {
+ DIR *proc_dir;
+ struct dirent *ps;
+ unsigned int pid;
+ std::string cmdline;
+
+ if (!(proc_dir = opendir("/proc"))) {
+ MYLOGE("Can't open /proc\n");
+ return 0;
+ }
+
+ while ((ps = readdir(proc_dir))) {
+ if (!(pid = atoi(ps->d_name))) {
+ continue;
+ }
+ android::base::ReadFileToString("/proc/"
+ + std::string(ps->d_name) + "/cmdline", &cmdline);
+ if (cmdline.find(ps_name) == std::string::npos) {
+ continue;
+ } else {
+ closedir(proc_dir);
+ return pid;
+ }
+ }
+ closedir(proc_dir);
+ return 0;
+}
+
+// dump anrd's trace and add to the zip file.
+// 1. check if anrd is running on this device.
+// 2. send a SIGUSR1 to its pid which will dump anrd's trace.
+// 3. wait until the trace generation completes and add to the zip file.
+static bool dump_anrd_trace() {
+ unsigned int pid;
+ char buf[50], path[PATH_MAX];
+ struct dirent *trace;
+ struct stat st;
+ DIR *trace_dir;
+ long max_ctime = 0;
+ long long cur_size = 0;
+ const char *trace_path = "/data/misc/anrd/";
+
+ if (!zip_writer) {
+ MYLOGE("Not dumping anrd trace because zip_writer is not set\n");
+ return false;
+ }
+
+ // find anrd's pid if it is running.
+ pid = pid_of_process("/system/xbin/anrd");
+
+ if (pid > 0) {
+ // send SIGUSR1 to the anrd to generate a trace.
+ sprintf(buf, "%u", pid);
+ if (run_command("ANRD_DUMP", 1, "kill", "-SIGUSR1", buf, NULL)) {
+ MYLOGE("anrd signal timed out. Please manually collect trace\n");
+ return false;
+ }
+
+ // identify the trace file by its creation time.
+ if (!(trace_dir = opendir(trace_path))) {
+ MYLOGE("Can't open trace file under %s\n", trace_path);
+ }
+ while ((trace = readdir(trace_dir))) {
+ if (strcmp(trace->d_name, ".") == 0
+ || strcmp(trace->d_name, "..") == 0) {
+ continue;
+ }
+ sprintf(path, "%s%s", trace_path, trace->d_name);
+ if (stat(path, &st) == 0) {
+ if (st.st_ctime > max_ctime) {
+ max_ctime = st.st_ctime;
+ sprintf(buf, "%s", trace->d_name);
+ }
+ }
+ }
+ closedir(trace_dir);
+
+ // Wait until the dump completes by checking the size of the trace.
+ if (max_ctime > 0) {
+ sprintf(path, "%s%s", trace_path, buf);
+ while(true) {
+ sleep(1);
+ if (stat(path, &st) == 0) {
+ if (st.st_size == cur_size) {
+ break;
+ } else if (st.st_size > cur_size) {
+ cur_size = st.st_size;
+ } else {
+ return false;
+ }
+ } else {
+ MYLOGE("Cant stat() %s anymore\n", path);
+ return false;
+ }
+ }
+ // Add to the zip file.
+ if (!add_zip_entry("anrd_trace.txt", path)) {
+ MYLOGE("Unable to add anrd_trace file %s to zip file\n", path);
+ } else {
+ if (remove(path)) {
+ MYLOGE("Error removing anrd_trace file %s: %s", path, strerror(errno));
+ }
+ return true;
+ }
+ } else {
+ MYLOGE("Can't stats any trace file under %s\n", trace_path);
+ }
+ }
+ return false;
+}
+
static void dump_systrace() {
if (!zip_writer) {
MYLOGD("Not dumping systrace because zip_writer is not set\n");
@@ -1348,7 +1461,11 @@
print_header(version);
// Dumps systrace right away, otherwise it will be filled with unnecessary events.
- dump_systrace();
+ // First try to dump anrd trace if the daemon is running. Otherwise, dump
+ // the raw trace.
+ if (!dump_anrd_trace()) {
+ dump_systrace();
+ }
// TODO: Drop root user and move into dumpstate() once b/28633932 is fixed.
dump_raft();
diff --git a/data/etc/wearable_core_hardware.xml b/data/etc/wearable_core_hardware.xml
index 4ff00b5..84230da 100644
--- a/data/etc/wearable_core_hardware.xml
+++ b/data/etc/wearable_core_hardware.xml
@@ -24,6 +24,7 @@
<feature name="android.hardware.location" />
<!-- devices supporting compass/magnitometer sensor must include
android.hardware.sensor.compass.xml -->
+ <feature name="android.hardware.sensor.gyroscope" />
<feature name="android.hardware.sensor.accelerometer" />
<feature name="android.hardware.bluetooth" />
<feature name="android.hardware.touchscreen" />
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 785df1a..dfece93 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -591,19 +591,25 @@
const Transform& tr(displayDevice->getTransform());
Rect transformedFrame = tr.transform(frame);
auto error = hwcLayer->setDisplayFrame(transformedFrame);
- ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set display frame "
- "[%d, %d, %d, %d]: %s (%d)", mName.string(), transformedFrame.left,
- transformedFrame.top, transformedFrame.right,
- transformedFrame.bottom, to_string(error).c_str(),
- static_cast<int32_t>(error));
+ if (error != HWC2::Error::None) {
+ ALOGE("[%s] Failed to set display frame [%d, %d, %d, %d]: %s (%d)",
+ mName.string(), transformedFrame.left, transformedFrame.top,
+ transformedFrame.right, transformedFrame.bottom,
+ to_string(error).c_str(), static_cast<int32_t>(error));
+ } else {
+ hwcInfo.displayFrame = transformedFrame;
+ }
FloatRect sourceCrop = computeCrop(displayDevice);
error = hwcLayer->setSourceCrop(sourceCrop);
- ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set source crop "
- "[%.3f, %.3f, %.3f, %.3f]: %s (%d)", mName.string(),
- sourceCrop.left, sourceCrop.top, sourceCrop.right,
- sourceCrop.bottom, to_string(error).c_str(),
- static_cast<int32_t>(error));
+ if (error != HWC2::Error::None) {
+ ALOGE("[%s] Failed to set source crop [%.3f, %.3f, %.3f, %.3f]: "
+ "%s (%d)", mName.string(), sourceCrop.left, sourceCrop.top,
+ sourceCrop.right, sourceCrop.bottom, to_string(error).c_str(),
+ static_cast<int32_t>(error));
+ } else {
+ hwcInfo.sourceCrop = sourceCrop;
+ }
error = hwcLayer->setPlaneAlpha(s.alpha);
ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set plane alpha %.3f: "
@@ -2235,6 +2241,54 @@
}
}
+#ifdef USE_HWC2
+void Layer::miniDumpHeader(String8& result) {
+ result.append("----------------------------------------");
+ result.append("---------------------------------------\n");
+ result.append(" Layer name\n");
+ result.append(" Z | ");
+ result.append(" Comp Type | ");
+ result.append(" Disp Frame (LTRB) | ");
+ result.append(" Source Crop (LTRB)\n");
+ result.append("----------------------------------------");
+ result.append("---------------------------------------\n");
+}
+
+void Layer::miniDump(String8& result, int32_t hwcId) const {
+ if (mHwcLayers.count(hwcId) == 0) {
+ return;
+ }
+
+ String8 name;
+ if (mName.length() > 77) {
+ std::string shortened;
+ shortened.append(mName.string(), 36);
+ shortened.append("[...]");
+ shortened.append(mName.string() + (mName.length() - 36), 36);
+ name = shortened.c_str();
+ } else {
+ name = mName;
+ }
+
+ result.appendFormat(" %s\n", name.string());
+
+ const Layer::State& layerState(getDrawingState());
+ const HWCInfo& hwcInfo = mHwcLayers.at(hwcId);
+ result.appendFormat(" %10u | ", layerState.z);
+ result.appendFormat("%10s | ",
+ to_string(getCompositionType(hwcId)).c_str());
+ const Rect& frame = hwcInfo.displayFrame;
+ result.appendFormat("%4d %4d %4d %4d | ", frame.left, frame.top,
+ frame.right, frame.bottom);
+ const FloatRect& crop = hwcInfo.sourceCrop;
+ result.appendFormat("%6.1f %6.1f %6.1f %6.1f\n", crop.left, crop.top,
+ crop.right, crop.bottom);
+
+ result.append("- - - - - - - - - - - - - - - - - - - - ");
+ result.append("- - - - - - - - - - - - - - - - - - - -\n");
+}
+#endif
+
void Layer::dumpFrameStats(String8& result) const {
mFrameTracker.dumpStats(result);
}
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 6533953..2ce1340 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -402,6 +402,10 @@
/* always call base class first */
void dump(String8& result, Colorizer& colorizer) const;
+#ifdef USE_HWC2
+ static void miniDumpHeader(String8& result);
+ void miniDump(String8& result, int32_t hwcId) const;
+#endif
void dumpFrameStats(String8& result) const;
void clearFrameStats();
void logFrameStats();
@@ -588,6 +592,8 @@
bool forceClientComposition;
HWC2::Composition compositionType;
bool clearClientTarget;
+ Rect displayFrame;
+ FloatRect sourceCrop;
};
std::unordered_map<int32_t, HWCInfo> mHwcLayers;
#else
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 92c6571..8db071e 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -3057,6 +3057,26 @@
* VSYNC state
*/
mEventThread->dump(result);
+ result.append("\n");
+
+ /*
+ * HWC layer minidump
+ */
+ for (size_t d = 0; d < mDisplays.size(); d++) {
+ const sp<const DisplayDevice>& displayDevice(mDisplays[d]);
+ int32_t hwcId = displayDevice->getHwcDisplayId();
+ if (hwcId == DisplayDevice::DISPLAY_ID_INVALID) {
+ continue;
+ }
+
+ result.appendFormat("Display %d HWC layers:\n", hwcId);
+ Layer::miniDumpHeader(result);
+ for (size_t l = 0; l < count; l++) {
+ const sp<Layer>& layer(currentLayers[l]);
+ layer->miniDump(result, hwcId);
+ }
+ result.append("\n");
+ }
/*
* Dump HWComposer state