summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDileep Marchya <dmarchya@codeaurora.org>2015-12-03 14:39:35 -0800
committerSteve Kondik <steve@cyngn.com>2016-03-13 03:28:46 -0700
commita9cbaf5097c089372cf152401007d70bcb13a95d (patch)
treec1c3fc0de430c031e261efbb9e5212ea8e9ae571
parent0e898965c31abd6a861c0af3223f0759b1a4ef6d (diff)
downloadframeworks_native-a9cbaf5097c089372cf152401007d70bcb13a95d.zip
frameworks_native-a9cbaf5097c089372cf152401007d70bcb13a95d.tar.gz
frameworks_native-a9cbaf5097c089372cf152401007d70bcb13a95d.tar.bz2
SurfaceFlinger: Add support for continuous dumpsys to file.
- Collect dumpsys to an outfile file when triggered. - Collect dumpsys before calling Prepare on hwc module in each draw cycle. Recollect dumpsys if Commit goes through successfully and replace former dumpsys with this. - Wrap around if file size reaches appx 20 MB. - Generate output file at /data/misc/display/dumpsys.txt - Syntax: adb shell dumpsys SurfaceFlinger --file [--no-limit] --file : Ouput dumpsys to file --no-limit : Do not wrap around, keep appending Use same command to trigger start and end of dumping. - Output format: | start code | after commit? | time stamp | dump size | dump data | CRs-Fixed: 947084 Change-Id: Ie520f51c69757aeec88b9400688a7f3271472349
-rw-r--r--services/surfaceflinger/Android.mk5
-rw-r--r--services/surfaceflinger/ExSurfaceFlinger/ExSurfaceFlinger.cpp107
-rw-r--r--services/surfaceflinger/ExSurfaceFlinger/ExSurfaceFlinger.h14
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp4
-rw-r--r--services/surfaceflinger/SurfaceFlinger.h1
5 files changed, 131 insertions, 0 deletions
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index 37ad4ac..c1ddba1 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -39,6 +39,11 @@ LOCAL_SRC_FILES := \
DisplayUtils.cpp
LOCAL_CFLAGS := -DLOG_TAG=\"SurfaceFlinger\"
+
+ifeq ($(TARGET_BUILD_VARIANT),userdebug)
+LOCAL_CFLAGS += -DDEBUG_CONT_DUMPSYS
+endif
+
LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
ifeq ($(TARGET_BOARD_PLATFORM),omap4)
diff --git a/services/surfaceflinger/ExSurfaceFlinger/ExSurfaceFlinger.cpp b/services/surfaceflinger/ExSurfaceFlinger/ExSurfaceFlinger.cpp
index 0014e80..96d4b1d 100644
--- a/services/surfaceflinger/ExSurfaceFlinger/ExSurfaceFlinger.cpp
+++ b/services/surfaceflinger/ExSurfaceFlinger/ExSurfaceFlinger.cpp
@@ -28,6 +28,7 @@
#include "ExSurfaceFlinger.h"
#include "ExLayer.h"
+#include <fstream>
#include <cutils/properties.h>
#ifdef QTI_BSP
#include <hardware/display_defs.h>
@@ -266,4 +267,110 @@ void ExSurfaceFlinger::drawWormHoleIfRequired(HWComposer::LayerListIterator& cur
}
}
+#ifdef DEBUG_CONT_DUMPSYS
+status_t ExSurfaceFlinger::dump(int fd, const Vector<String16>& args) {
+ // Format: adb shell dumpsys SurfaceFlinger --file --no-limit
+ size_t numArgs = args.size();
+ status_t err = NO_ERROR;
+
+ if (!numArgs || (args[0] != String16("--file"))) {
+ return SurfaceFlinger::dump(fd, args);
+ }
+
+ Mutex::Autolock _l(mFileDump.lock);
+
+ // Same command is used to start and end dump.
+ mFileDump.running = !mFileDump.running;
+
+ if (mFileDump.running) {
+ // Create an empty file or erase existing file.
+ std::fstream fs;
+ fs.open(mFileDump.name, std::ios::out);
+ if (!fs) {
+ mFileDump.running = false;
+ err = UNKNOWN_ERROR;
+ } else {
+ mFileDump.position = 0;
+ if (numArgs >= 2 && (args[1] == String16("--nolimit"))) {
+ mFileDump.noLimit = true;
+ } else {
+ mFileDump.noLimit = false;
+ }
+ }
+ }
+
+ String8 result;
+ result += mFileDump.running ? "Start" : "End";
+ result += mFileDump.noLimit ? " unlimited" : " fixed limit";
+ result += " dumpsys to file : ";
+ result += mFileDump.name;
+ result += "\n";
+
+ write(fd, result.string(), result.size());
+
+ return NO_ERROR;
+}
+
+void ExSurfaceFlinger::dumpDrawCycle(bool prePrepare) {
+ Mutex::Autolock _l(mFileDump.lock);
+
+ // User might stop dump collection in middle of prepare & commit.
+ // Collect dumpsys again after commit and replace.
+ if (!mFileDump.running && !mFileDump.replaceAfterCommit) {
+ return;
+ }
+
+ Vector<String16> args;
+ size_t index = 0;
+ String8 dumpsys;
+
+ dumpAllLocked(args, index, dumpsys);
+
+ char timeStamp[32];
+ char dataSize[32];
+ char hms[32];
+ long millis;
+ struct timeval tv;
+ struct tm *ptm;
+
+ gettimeofday(&tv, NULL);
+ ptm = localtime(&tv.tv_sec);
+ strftime (hms, sizeof (hms), "%H:%M:%S", ptm);
+ millis = tv.tv_usec / 1000;
+ snprintf(timeStamp, sizeof(timeStamp), "Timestamp: %s.%03ld", hms, millis);
+ snprintf(dataSize, sizeof(dataSize), "Size: %8zu", dumpsys.size());
+
+ std::fstream fs;
+ fs.open(mFileDump.name, std::ios::in | std::ios::out);
+ if (!fs) {
+ ALOGE("Failed to open %s file for dumpsys", mFileDump.name);
+ return;
+ }
+
+ // Format:
+ // | start code | after commit? | time stamp | dump size | dump data |
+ fs.seekp(mFileDump.position, std::ios::beg);
+
+ fs << "#@#@-- DUMPSYS START --@#@#" << std::endl;
+ fs << "PostCommit: " << ( prePrepare ? "false" : "true" ) << std::endl;
+ fs << timeStamp << std::endl;
+ fs << dataSize << std::endl;
+ fs << dumpsys << std::endl;
+
+ if (prePrepare) {
+ mFileDump.replaceAfterCommit = true;
+ } else {
+ mFileDump.replaceAfterCommit = false;
+ // Reposition only after commit.
+ // Keem file size to appx 20 MB limit by default, wrap around if exceeds.
+ mFileDump.position = fs.tellp();
+ if (!mFileDump.noLimit && (mFileDump.position > (20 * 1024 * 1024))) {
+ mFileDump.position = 0;
+ }
+ }
+
+ fs.close();
+}
+#endif
+
}; // namespace android
diff --git a/services/surfaceflinger/ExSurfaceFlinger/ExSurfaceFlinger.h b/services/surfaceflinger/ExSurfaceFlinger/ExSurfaceFlinger.h
index 628fac7..068f2b9 100644
--- a/services/surfaceflinger/ExSurfaceFlinger/ExSurfaceFlinger.h
+++ b/services/surfaceflinger/ExSurfaceFlinger/ExSurfaceFlinger.h
@@ -79,6 +79,20 @@ protected:
bool mDebugLogs;
bool isDebug() { return mDebugLogs; }
bool mDisableExtAnimation;
+
+#ifdef DEBUG_CONT_DUMPSYS
+ virtual status_t dump(int fd, const Vector<String16>& args);
+ virtual void dumpDrawCycle(bool prePrepare );
+
+ struct {
+ Mutex lock;
+ const char *name = "/data/misc/display/dumpsys.txt";
+ bool running = false;
+ bool noLimit = false;
+ bool replaceAfterCommit = false;
+ long int position = 0;
+ } mFileDump;
+#endif
};
}; //namespace android
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 43a0bd8..a457019 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1081,6 +1081,8 @@ void SurfaceFlinger::postComposition()
mAnimFrameTracker.advanceFrame();
}
+ dumpDrawCycle(false);
+
if (hw->getPowerMode() == HWC_POWER_MODE_OFF) {
return;
}
@@ -1248,6 +1250,8 @@ void SurfaceFlinger::setUpHWComposer() {
}
}
+ dumpDrawCycle(true);
+
status_t err = hwc.prepare();
ALOGE_IF(err, "HWComposer::prepare failed (%s)", strerror(-err));
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 2028d67..1f7601a 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -471,6 +471,7 @@ private:
void logFrameStats();
void dumpStaticScreenStats(String8& result) const;
+ virtual void dumpDrawCycle(bool /* prePrepare */ ) { }
/* ------------------------------------------------------------------------
* Attributes