/* * Copyright (C) 2012 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "ExynosHWCDebug.h" #include "ExynosDisplay.h" #include #include "exynos_sync.h" uint32_t mErrLogSize = 0; uint32_t mFenceLogSize = 0; int32_t saveErrorLog(const String8 &errString, ExynosDisplay *display) { 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; } mErrLogSize = ftell(pFile); if (mErrLogSize >= ERR_LOG_SIZE) { if (pFile != NULL) fclose(pFile); return -1; } String8 saveString; struct timeval tv; struct tm* localTime; gettimeofday(&tv, NULL); localTime = (struct tm*)localtime((time_t*)&tv.tv_sec); if (display != NULL) { saveString.appendFormat("%02d-%02d %02d:%02d:%02d.%03lu(%lu) %s %" PRIu64 ": %s\n", localTime->tm_mon+1, localTime->tm_mday, localTime->tm_hour, localTime->tm_min, localTime->tm_sec, tv.tv_usec/1000, ((tv.tv_sec * 1000) + (tv.tv_usec / 1000)), display->mDisplayName.string(), display->mErrorFrameCount, errString.string()); } else { saveString.appendFormat("%02d-%02d %02d:%02d:%02d.%03lu(%lu) : %s\n", localTime->tm_mon+1, localTime->tm_mday, localTime->tm_hour, localTime->tm_min, localTime->tm_sec, tv.tv_usec/1000, ((tv.tv_sec * 1000) + (tv.tv_usec / 1000)), errString.string()); } if (pFile != NULL) { fwrite(saveString.string(), 1, saveString.size(), pFile); mErrLogSize = (uint32_t)ftell(pFile); ret = mErrLogSize; fclose(pFile); } return ret; } int32_t saveFenceTrace(ExynosDisplay *display) { int32_t ret = NO_ERROR; 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); return -1; } String8 saveString; struct timeval tv; ExynosDevice *device = display->mDevice; hwc_fence_info_t* _info = device->mFenceInfo; if (device != NULL) { for(int i=0; i<1024;i ++){ bool sysFdOpen = false; hwc_fence_info_t info = _info[i]; // FIXME: sync_fence_info and sync_pt_info are deprecated // HWC guys should fix this #if 0 struct sync_pt_info* pt_info = NULL; info.sync_data = sync_fence_info(i); if (info.sync_data != NULL) { pt_info = sync_pt_info(info.sync_data, pt_info); if (pt_info !=NULL) { saveString.appendFormat("\n-- FD sys : %d\n", i); saveString.appendFormat("real name : %s, status : %s, pt_obj : %s, pt_drv : %s, time : %llu", info.sync_data->name, info.sync_data->status==1 ? "Active":"Signaled", pt_info->obj_name, pt_info->driver_name, static_cast(pt_info->timestamp_ns)); } else { saveString.appendFormat("\n-- FD sys : %d\n", i); saveString.appendFormat("real name : %s, status : %d, pt_info : %p", info.sync_data->name, info.sync_data->status, pt_info); } sysFdOpen = true; sync_fence_info_free(info.sync_data); } #endif if ((info.usage == 0) && !sysFdOpen) continue; saveString.appendFormat("\n-- FD hwc : %d, usage %d\n", i, info.usage); switch(info.last_dir) { case FENCE_FROM: saveString.appendFormat("Last state : from %d, %d\n", info.from.type, info.from.ip); tv = info.from.time; break; case FENCE_TO: saveString.appendFormat("Last state : to %d, %d\n", info.to.type, info.to.ip); tv = info.to.time; break; case FENCE_DUP: saveString.appendFormat("Last state : dup %d, %d\n", info.dup.type, info.dup.ip); tv = info.dup.time; break; case FENCE_CLOSE: saveString.appendFormat("Last state : Close %d, %d\n", info.close.type, info.close.ip); tv = info.close.time; break; break; default: saveString.appendFormat("Fence trace : Undefined direction!\n"); break; } struct tm* localTime = (struct tm*)localtime((time_t*)&tv.tv_sec); saveString.appendFormat("from : %d, %d (cur : %d), to : %d, %d (cur : %d), hwc_dup : %d, %d (cur : %d), hwc_close : %d, %d (cur : %d)\n", info.from.type, info.from.ip, info.from.curFlag, info.to.type, info.to.ip, info.to.curFlag, info.dup.type, info.dup.ip, info.dup.curFlag, info.close.type, info.close.ip, info.close.curFlag); saveString.appendFormat("usage : %d, time:%02d-%02d %02d:%02d:%02d.%03lu(%lu)", info.usage, localTime->tm_mon+1, localTime->tm_mday, localTime->tm_hour, localTime->tm_min, localTime->tm_sec, tv.tv_usec/1000, ((tv.tv_sec * 1000) + (tv.tv_usec / 1000))); } } if (pFile != NULL) { fwrite(saveString.string(), 1, saveString.size(), pFile); mFenceLogSize = (uint32_t)ftell(pFile); ret = mFenceLogSize; fclose(pFile); } return ret; }