summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWiwit Rifa'i <wiwitrifai@google.com>2022-11-08 16:20:06 +0800
committerWiwit Rifa'i <wiwitrifai@google.com>2022-12-09 20:12:07 +0800
commite29a42bc92f0e180145233b4fd58229b9d485b10 (patch)
treed4f166ca455658de1efa4eeeded8cabc9cef3212
parent81e2e51b1351d4df010dd7303adba3b0eb6d491d (diff)
libhwc2.1: always update log files with the latest info
Previously, the log files would not be updated anymore if the size is already more than 1 MB. But now, the log files should always be updated but the total size and the file count are still guaranteed to be limited. This will also change the log files to be per display (to avoid race condition for multi-display). Bug: 245511651 Test: make many errors and check HWC log files Test: vndservice call Exynos.HWCService 11 i32 0 i32 308 i32 1 Change-Id: I3f3f0ead7bb5b513d51388a13fcb67762031d93e
-rw-r--r--libhwc2.1/ExynosHWCDebug.cpp77
-rw-r--r--libhwc2.1/libdevice/ExynosDevice.cpp15
-rw-r--r--libhwc2.1/libdevice/ExynosDisplay.cpp132
-rw-r--r--libhwc2.1/libdevice/ExynosDisplay.h45
4 files changed, 157 insertions, 112 deletions
diff --git a/libhwc2.1/ExynosHWCDebug.cpp b/libhwc2.1/ExynosHWCDebug.cpp
index bbf676c..dc42369 100644
--- a/libhwc2.1/ExynosHWCDebug.cpp
+++ b/libhwc2.1/ExynosHWCDebug.cpp
@@ -18,33 +18,13 @@
#include <sync/sync.h>
#include "exynos_sync.h"
-uint32_t mErrLogSize = 0;
-uint32_t mFenceLogSize = 0;
-
-int32_t saveErrorLog(const String8 &errString, ExynosDisplay *display)
-{
+int32_t saveErrorLog(const String8 &errString, ExynosDisplay *display) {
+ if (display == nullptr) return -1;
int32_t ret = NO_ERROR;
- if (mErrLogSize >= ERR_LOG_SIZE)
- return -1;
- FILE *pFile = NULL;
- char filePath[128];
- sprintf(filePath, "%s/hwc_error_log.txt", ERROR_LOG_PATH0);
- pFile = fopen(filePath, "a");
- if (pFile == NULL) {
- ALOGE("Fail to open file %s/hwc_error_log.txt, error: %s", ERROR_LOG_PATH0, strerror(errno));
- sprintf(filePath, "%s/hwc_error_log.txt", ERROR_LOG_PATH1);
- pFile = fopen(filePath, "a");
- }
- if (pFile == NULL) {
- ALOGE("Fail to open file %s/hwc_error_log.txt, error: %s", ERROR_LOG_PATH1, strerror(errno));
- return -errno;
- }
+ auto &fileWriter = display->mErrLogFileWriter;
- mErrLogSize = ftell(pFile);
- if (mErrLogSize >= ERR_LOG_SIZE) {
- if (pFile != NULL)
- fclose(pFile);
+ if (!fileWriter.chooseOpenedFile()) {
return -1;
}
@@ -52,47 +32,19 @@ int32_t saveErrorLog(const String8 &errString, ExynosDisplay *display)
struct timeval tv;
gettimeofday(&tv, NULL);
- if (display != NULL) {
- saveString.appendFormat("%s %s %" PRIu64 ": %s\n", getLocalTimeStr(tv).string(),
- display->mDisplayName.string(), display->mErrorFrameCount,
- errString.string());
- } else {
- saveString.appendFormat("%s : %s\n", getLocalTimeStr(tv).string(), errString.string());
- }
+ saveString.appendFormat("%s errFrameNumber %" PRIu64 ": %s\n", getLocalTimeStr(tv).string(),
+ display->mErrorFrameCount, errString.string());
- if (pFile != NULL) {
- fwrite(saveString.string(), 1, saveString.size(), pFile);
- mErrLogSize = (uint32_t)ftell(pFile);
- ret = mErrLogSize;
- fclose(pFile);
- }
+ fileWriter.write(saveString);
+ fileWriter.flush();
return ret;
}
int32_t saveFenceTrace(ExynosDisplay *display) {
int32_t ret = NO_ERROR;
+ auto &fileWriter = display->mFenceFileWriter;
- if (mFenceLogSize >= FENCE_ERR_LOG_SIZE)
- return -1;
-
- FILE *pFile = NULL;
- char filePath[128];
- sprintf(filePath, "%s/hwc_fence_state.txt", ERROR_LOG_PATH0);
- pFile = fopen(filePath, "a");
- if (pFile == NULL) {
- ALOGE("Fail to open file %s/hwc_fence_state.txt, error: %s", ERROR_LOG_PATH0, strerror(errno));
- sprintf(filePath, "%s/hwc_fence_state.txt", ERROR_LOG_PATH1);
- pFile = fopen(filePath, "a");
- }
- if (pFile == NULL) {
- ALOGE("Fail to open file %s, error: %s", ERROR_LOG_PATH1, strerror(errno));
- return -errno;
- }
-
- mFenceLogSize = ftell(pFile);
- if (mFenceLogSize >= FENCE_ERR_LOG_SIZE) {
- if (pFile != NULL)
- fclose(pFile);
+ if (!fileWriter.chooseOpenedFile()) {
return -1;
}
@@ -117,12 +69,7 @@ int32_t saveFenceTrace(ExynosDisplay *display) {
}
}
- if (pFile != NULL) {
- fwrite(saveString.string(), 1, saveString.size(), pFile);
- mFenceLogSize = (uint32_t)ftell(pFile);
- ret = mFenceLogSize;
- fclose(pFile);
- }
-
+ fileWriter.write(saveString);
+ fileWriter.flush();
return ret;
}
diff --git a/libhwc2.1/libdevice/ExynosDevice.cpp b/libhwc2.1/libdevice/ExynosDevice.cpp
index 5bf43c2..42eb27d 100644
--- a/libhwc2.1/libdevice/ExynosDevice.cpp
+++ b/libhwc2.1/libdevice/ExynosDevice.cpp
@@ -43,7 +43,6 @@ using aidl::android::hardware::graphics::composer3::IComposerCallback;
class ExynosDevice;
-extern uint32_t mFenceLogSize;
extern void PixelDisplayInit(ExynosDisplay *exynos_display, const std::string_view instance_str);
static const std::map<const uint32_t, const std::string_view> pixelDisplayIntfName =
@@ -161,10 +160,15 @@ ExynosDevice::ExynosDevice()
sprintf(fence_names[i], "_%2dh", i);
}
- String8 saveString;
- saveString.appendFormat("ExynosDevice is initialized");
- uint32_t errFileSize = saveErrorLog(saveString);
- ALOGI("Initial errlog size: %d bytes\n", errFileSize);
+ for (auto it : mDisplays) {
+ std::string displayName = std::string(it->mDisplayName.string());
+ it->mErrLogFileWriter.setPrefixName(displayName + "_hwc_error_log");
+ it->mDebugDumpFileWriter.setPrefixName(displayName + "_hwc_debug");
+ it->mFenceFileWriter.setPrefixName(displayName + "_hwc_fence_state");
+ String8 saveString;
+ saveString.appendFormat("ExynosDisplay %s is initialized", it->mDisplayName.string());
+ saveErrorLog(saveString, it);
+ }
initDeviceInterface(mInterfaceType);
@@ -859,7 +863,6 @@ bool ExynosDevice::validateFences(ExynosDisplay *display) {
if (exynosHWCControl.doFenceFileDump) {
ALOGD("Fence file dump !");
- if (mFenceLogSize != 0) ALOGD("Fence file not empty!");
saveFenceTrace(display);
exynosHWCControl.doFenceFileDump = false;
}
diff --git a/libhwc2.1/libdevice/ExynosDisplay.cpp b/libhwc2.1/libdevice/ExynosDisplay.cpp
index bc17c2e..cd20a92 100644
--- a/libhwc2.1/libdevice/ExynosDisplay.cpp
+++ b/libhwc2.1/libdevice/ExynosDisplay.cpp
@@ -1018,7 +1018,10 @@ ExynosDisplay::ExynosDisplay(uint32_t index, ExynosDevice *device)
mVsyncPeriodChangeConstraints{systemTime(SYSTEM_TIME_MONOTONIC), 0},
mVsyncAppliedTimeLine{false, 0, systemTime(SYSTEM_TIME_MONOTONIC)},
mConfigRequestState(hwc_request_state_t::SET_CONFIG_STATE_NONE),
- mPowerHalHint(getDisplayId(mDisplayId, mIndex)) {
+ mPowerHalHint(getDisplayId(mDisplayId, mIndex)),
+ mErrLogFileWriter(2, ERR_LOG_SIZE),
+ mDebugDumpFileWriter(10, 1, ".dump"),
+ mFenceFileWriter(2, FENCE_ERR_LOG_SIZE) {
mDisplayControl.enableCompositionCrop = true;
mDisplayControl.enableExynosCompositionOptimization = true;
mDisplayControl.enableClientCompositionOptimization = true;
@@ -2407,31 +2410,15 @@ int ExynosDisplay::setWinConfigData() {
return 0;
}
-void ExynosDisplay::printDebugInfos(String8 &reason)
-{
- FILE *pFile = NULL;
+void ExynosDisplay::printDebugInfos(String8 &reason) {
struct timeval tv;
gettimeofday(&tv, NULL);
reason.appendFormat("errFrameNumber: %" PRId64 " time:%s\n", mErrorFrameCount,
getLocalTimeStr(tv).string());
ALOGD("%s", reason.string());
- if (mErrorFrameCount < HWC_PRINT_FRAME_NUM) {
- char filePath[128];
- sprintf(filePath, "%s/%s_hwc_debug%d.dump", ERROR_LOG_PATH0, mDisplayName.string(), (int)mErrorFrameCount);
- pFile = fopen(filePath, "wb");
- if (pFile == NULL) {
- ALOGE("Fail to open file %s, error: %s", filePath, strerror(errno));
- sprintf(filePath, "%s/%s_hwc_debug%d.dump", ERROR_LOG_PATH1, mDisplayName.string(), (int)mErrorFrameCount);
- pFile = fopen(filePath, "wb");
- }
- if (pFile == NULL) {
- ALOGE("Fail to open file %s, error: %s", filePath, strerror(errno));
- } else {
- ALOGI("%s was created", filePath);
- fwrite(reason.string(), 1, reason.size(), pFile);
- }
- }
+ bool fileOpened = mDebugDumpFileWriter.chooseOpenedFile();
+ mDebugDumpFileWriter.write(reason);
mErrorFrameCount++;
android::String8 result;
@@ -2443,24 +2430,20 @@ void ExynosDisplay::printDebugInfos(String8 &reason)
clientCompInfo.dump(result);
exynosCompInfo.dump(result);
ALOGD("%s", result.string());
- if (pFile != NULL) {
- fwrite(result.string(), 1, result.size(), pFile);
- }
+ mDebugDumpFileWriter.write(result);
result.clear();
result.appendFormat("======================= dump exynos layers (%zu) ================================\n",
mLayers.size());
ALOGD("%s", result.string());
- if (pFile != NULL) {
- fwrite(result.string(), 1, result.size(), pFile);
- }
+ mDebugDumpFileWriter.write(result);
result.clear();
for (uint32_t i = 0; i < mLayers.size(); i++) {
ExynosLayer *layer = mLayers[i];
layer->printLayer();
- if (pFile != NULL) {
+ if (fileOpened) {
layer->dump(result);
- fwrite(result.string(), 1, result.size(), pFile);
+ mDebugDumpFileWriter.write(result);
result.clear();
}
}
@@ -2469,16 +2452,14 @@ void ExynosDisplay::printDebugInfos(String8 &reason)
result.appendFormat("======================= dump ignore layers (%zu) ================================\n",
mIgnoreLayers.size());
ALOGD("%s", result.string());
- if (pFile != NULL) {
- fwrite(result.string(), 1, result.size(), pFile);
- }
+ mDebugDumpFileWriter.write(result);
result.clear();
for (uint32_t i = 0; i < mIgnoreLayers.size(); i++) {
ExynosLayer *layer = mIgnoreLayers[i];
layer->printLayer();
- if (pFile != NULL) {
+ if (fileOpened) {
layer->dump(result);
- fwrite(result.string(), 1, result.size(), pFile);
+ mDebugDumpFileWriter.write(result);
result.clear();
}
}
@@ -2486,23 +2467,19 @@ void ExynosDisplay::printDebugInfos(String8 &reason)
result.appendFormat("============================= dump win configs ===================================\n");
ALOGD("%s", result.string());
- if (pFile != NULL) {
- fwrite(result.string(), 1, result.size(), pFile);
- }
+ mDebugDumpFileWriter.write(result);
result.clear();
for (size_t i = 0; i < mDpuData.configs.size(); i++) {
ALOGD("config[%zu]", i);
printConfig(mDpuData.configs[i]);
- if (pFile != NULL) {
+ if (fileOpened) {
result.appendFormat("config[%zu]\n", i);
dumpConfig(result, mDpuData.configs[i]);
- fwrite(result.string(), 1, result.size(), pFile);
+ mDebugDumpFileWriter.write(result);
result.clear();
}
}
- if (pFile != NULL) {
- fclose(pFile);
- }
+ mDebugDumpFileWriter.flush();
}
int32_t ExynosDisplay::validateWinConfigData()
@@ -6082,3 +6059,76 @@ int ExynosDisplay::lookupDisplayConfigs(const int32_t &width,
}
return HWC2_ERROR_BAD_CONFIG;
}
+
+FILE *ExynosDisplay::RotatingLogFileWriter::openLogFile(const std::string &filename,
+ const std::string &mode) {
+ FILE *file = nullptr;
+ auto fullpath = std::string(ERROR_LOG_PATH0) + "/" + filename;
+ file = fopen(fullpath.c_str(), mode.c_str());
+ if (file != nullptr) {
+ return file;
+ }
+ ALOGE("Fail to open file %s, error: %s", fullpath.c_str(), strerror(errno));
+ fullpath = std::string(ERROR_LOG_PATH1) + "/" + filename;
+ file = fopen(fullpath.c_str(), mode.c_str());
+ if (file == nullptr) {
+ ALOGE("Fail to open file %s, error: %s", fullpath.c_str(), strerror(errno));
+ }
+ return file;
+}
+
+std::optional<nsecs_t> ExynosDisplay::RotatingLogFileWriter::getLastModifiedTimestamp(
+ const std::string &filename) {
+ struct stat fileStat;
+ auto fullpath = std::string(ERROR_LOG_PATH0) + "/" + filename;
+ if (stat(fullpath.c_str(), &fileStat) == 0) {
+ return fileStat.st_mtim.tv_sec * nsecsPerSec + fileStat.st_mtim.tv_nsec;
+ }
+ fullpath = std::string(ERROR_LOG_PATH1) + "/" + filename;
+ if (stat(fullpath.c_str(), &fileStat) == 0) {
+ return fileStat.st_mtim.tv_sec * nsecsPerSec + fileStat.st_mtim.tv_nsec;
+ }
+ return std::nullopt;
+}
+
+bool ExynosDisplay::RotatingLogFileWriter::chooseOpenedFile() {
+ if (mLastFileIndex < 0) {
+ // HWC could be restarted, so choose to open new file or continue the last modified file
+ int chosenIndex = 0;
+ nsecs_t lastModifTimestamp = 0;
+ for (int i = 0; i < mMaxFileCount; ++i) {
+ auto timestamp = getLastModifiedTimestamp(mPrefixName + std::to_string(i) + mExtension);
+ if (!timestamp.has_value()) {
+ chosenIndex = i;
+ break;
+ }
+ if (i == 0 || lastModifTimestamp < *timestamp) {
+ chosenIndex = i;
+ lastModifTimestamp = *timestamp;
+ }
+ }
+ auto filename = mPrefixName + std::to_string(chosenIndex) + mExtension;
+ mFile = openLogFile(filename, "ab");
+ if (mFile == nullptr) {
+ ALOGE("Unable to open log file for %s", filename.c_str());
+ return false;
+ }
+ mLastFileIndex = chosenIndex;
+ }
+
+ // Choose to use the same last file or move on to the next file
+ for (int i = 0; i < 2; ++i) {
+ if (mFile == nullptr) {
+ mFile = openLogFile(mPrefixName + std::to_string(mLastFileIndex) + mExtension,
+ (i == 0) ? "ab" : "wb");
+ }
+ if (mFile != nullptr) {
+ auto fileSize = ftell(mFile);
+ if (fileSize < mThresholdSizePerFile) return true;
+ fclose(mFile);
+ mFile = nullptr;
+ }
+ mLastFileIndex = (mLastFileIndex + 1) % mMaxFileCount;
+ }
+ return false;
+}
diff --git a/libhwc2.1/libdevice/ExynosDisplay.h b/libhwc2.1/libdevice/ExynosDisplay.h
index 12ad1f1..6fd6df9 100644
--- a/libhwc2.1/libdevice/ExynosDisplay.h
+++ b/libhwc2.1/libdevice/ExynosDisplay.h
@@ -1519,6 +1519,51 @@ class ExynosDisplay {
// Resource TDM (Time-Division Multiplexing)
std::map<uint32_t, displayTDMInfo> mDisplayTDMInfo;
+
+ class RotatingLogFileWriter {
+ public:
+ RotatingLogFileWriter(uint32_t maxFileCount, uint32_t thresholdSizePerFile,
+ std::string extension = ".txt")
+ : mMaxFileCount(maxFileCount),
+ mThresholdSizePerFile(thresholdSizePerFile),
+ mPrefixName(""),
+ mExtension(extension),
+ mLastFileIndex(-1),
+ mFile(nullptr) {}
+
+ ~RotatingLogFileWriter() {
+ if (mFile) {
+ fclose(mFile);
+ }
+ }
+
+ bool chooseOpenedFile();
+ void write(const String8& content) {
+ if (mFile) {
+ fwrite(content.string(), 1, content.size(), mFile);
+ }
+ }
+ void flush() {
+ if (mFile) {
+ fflush(mFile);
+ }
+ }
+ void setPrefixName(const std::string& prefixName) { mPrefixName = prefixName; }
+
+ private:
+ FILE* openLogFile(const std::string& filename, const std::string& mode);
+ std::optional<nsecs_t> getLastModifiedTimestamp(const std::string& filename);
+
+ uint32_t mMaxFileCount;
+ uint32_t mThresholdSizePerFile;
+ std::string mPrefixName;
+ std::string mExtension;
+ int32_t mLastFileIndex;
+ FILE* mFile;
+ };
+ RotatingLogFileWriter mErrLogFileWriter;
+ RotatingLogFileWriter mDebugDumpFileWriter;
+ RotatingLogFileWriter mFenceFileWriter;
};
#endif //_EXYNOSDISPLAY_H