diff options
-rw-r--r-- | libhwc2.1/ExynosHWCDebug.cpp | 77 | ||||
-rw-r--r-- | libhwc2.1/libdevice/ExynosDevice.cpp | 15 | ||||
-rw-r--r-- | libhwc2.1/libdevice/ExynosDisplay.cpp | 132 | ||||
-rw-r--r-- | libhwc2.1/libdevice/ExynosDisplay.h | 45 |
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 |