1 /*
2  * Copyright (C) 2012 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #include "ExynosHWCDebug.h"
17 #include "ExynosDisplay.h"
18 #include <sync/sync.h>
19 #include "exynos_sync.h"
20 
21 uint32_t mErrLogSize = 0;
22 uint32_t mFenceLogSize = 0;
23 
saveErrorLog(const String8 & errString,ExynosDisplay * display)24 int32_t saveErrorLog(const String8 &errString, ExynosDisplay *display)
25 {
26     int32_t ret = NO_ERROR;
27     if (mErrLogSize >= ERR_LOG_SIZE)
28         return -1;
29 
30     FILE *pFile = NULL;
31     char filePath[128];
32     sprintf(filePath, "%s/hwc_error_log.txt", ERROR_LOG_PATH0);
33     pFile = fopen(filePath, "a");
34     if (pFile == NULL) {
35         ALOGE("Fail to open file %s/hwc_error_log.txt, error: %s", ERROR_LOG_PATH0, strerror(errno));
36         sprintf(filePath, "%s/hwc_error_log.txt", ERROR_LOG_PATH1);
37         pFile = fopen(filePath, "a");
38     }
39     if (pFile == NULL) {
40         ALOGE("Fail to open file %s/hwc_error_log.txt, error: %s", ERROR_LOG_PATH1, strerror(errno));
41         return -errno;
42     }
43 
44     mErrLogSize = ftell(pFile);
45     if (mErrLogSize >= ERR_LOG_SIZE) {
46         if (pFile != NULL)
47             fclose(pFile);
48         return -1;
49     }
50 
51     String8 saveString;
52     struct timeval tv;
53     struct tm* localTime;
54     gettimeofday(&tv, NULL);
55     localTime = (struct tm*)localtime((time_t*)&tv.tv_sec);
56 
57     if (display != NULL) {
58         saveString.appendFormat("%02d-%02d %02d:%02d:%02d.%03lu(%lu) %s %" PRIu64 ": %s\n",
59                 localTime->tm_mon+1, localTime->tm_mday,
60                 localTime->tm_hour, localTime->tm_min,
61                 localTime->tm_sec, tv.tv_usec/1000, ((tv.tv_sec * 1000) + (tv.tv_usec / 1000)),
62                 display->mDisplayName.string(), display->mErrorFrameCount,
63                 errString.string());
64     } else {
65         saveString.appendFormat("%02d-%02d %02d:%02d:%02d.%03lu(%lu) : %s\n",
66                 localTime->tm_mon+1, localTime->tm_mday,
67                 localTime->tm_hour, localTime->tm_min,
68                 localTime->tm_sec, tv.tv_usec/1000, ((tv.tv_sec * 1000) + (tv.tv_usec / 1000)),
69                 errString.string());
70     }
71 
72     if (pFile != NULL) {
73         fwrite(saveString.string(), 1, saveString.size(), pFile);
74         mErrLogSize = (uint32_t)ftell(pFile);
75         ret = mErrLogSize;
76         fclose(pFile);
77     }
78     return ret;
79 }
80 
saveFenceTrace(ExynosDisplay * display)81 int32_t saveFenceTrace(ExynosDisplay *display) {
82     int32_t ret = NO_ERROR;
83 
84     if (mFenceLogSize >= FENCE_ERR_LOG_SIZE)
85         return -1;
86 
87     FILE *pFile = NULL;
88     char filePath[128];
89     sprintf(filePath, "%s/hwc_fence_state.txt", ERROR_LOG_PATH0);
90     pFile = fopen(filePath, "a");
91     if (pFile == NULL) {
92         ALOGE("Fail to open file %s/hwc_fence_state.txt, error: %s", ERROR_LOG_PATH0, strerror(errno));
93         sprintf(filePath, "%s/hwc_fence_state.txt", ERROR_LOG_PATH1);
94         pFile = fopen(filePath, "a");
95     }
96     if (pFile == NULL) {
97         ALOGE("Fail to open file %s, error: %s", ERROR_LOG_PATH1, strerror(errno));
98         return -errno;
99     }
100 
101     mFenceLogSize = ftell(pFile);
102     if (mFenceLogSize >= FENCE_ERR_LOG_SIZE) {
103         if (pFile != NULL)
104             fclose(pFile);
105         return -1;
106     }
107 
108     String8 saveString;
109     struct timeval tv;
110 
111     ExynosDevice *device = display->mDevice;
112     hwc_fence_info_t* _info = device->mFenceInfo;
113 
114     if (device != NULL) {
115         for(int i=0; i<1024;i ++){
116 
117             bool sysFdOpen = false;
118             hwc_fence_info_t info = _info[i];
119 
120             // FIXME: sync_fence_info and sync_pt_info are deprecated
121             //        HWC guys should fix this
122 #if 0
123             struct sync_pt_info* pt_info = NULL;
124             info.sync_data = sync_fence_info(i);
125             if (info.sync_data != NULL) {
126                 pt_info = sync_pt_info(info.sync_data, pt_info);
127                 if (pt_info !=NULL) {
128                     saveString.appendFormat("\n-- FD sys : %d\n", i);
129                     saveString.appendFormat("real name : %s, status : %s, pt_obj : %s, pt_drv : %s, time : %llu",
130                             info.sync_data->name, info.sync_data->status==1 ? "Active":"Signaled",
131                             pt_info->obj_name, pt_info->driver_name, static_cast<unsigned long long>(pt_info->timestamp_ns));
132                 } else {
133                     saveString.appendFormat("\n-- FD sys : %d\n", i);
134                     saveString.appendFormat("real name : %s, status : %d, pt_info : %p",
135                             info.sync_data->name, info.sync_data->status, pt_info);
136                 }
137                 sysFdOpen = true;
138                 sync_fence_info_free(info.sync_data);
139             }
140 #endif
141 
142             if ((info.usage == 0) && !sysFdOpen) continue;
143 
144             saveString.appendFormat("\n-- FD hwc : %d, usage %d\n", i, info.usage);
145 
146             switch(info.last_dir) {
147             case FENCE_FROM:
148                 saveString.appendFormat("Last state : from %d, %d\n",
149                         info.from.type, info.from.ip);
150                 tv = info.from.time;
151                 break;
152             case FENCE_TO:
153                 saveString.appendFormat("Last state : to %d, %d\n",
154                         info.to.type, info.to.ip);
155                 tv = info.to.time;
156                 break;
157             case FENCE_DUP:
158                 saveString.appendFormat("Last state : dup %d, %d\n",
159                         info.dup.type, info.dup.ip);
160                 tv = info.dup.time;
161                 break;
162             case FENCE_CLOSE:
163                 saveString.appendFormat("Last state : Close %d, %d\n",
164                         info.close.type, info.close.ip);
165                 tv = info.close.time;
166                 break;
167                 break;
168             default:
169                 saveString.appendFormat("Fence trace : Undefined direction!\n");
170                 break;
171             }
172 
173             struct tm* localTime = (struct tm*)localtime((time_t*)&tv.tv_sec);
174 
175             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",
176                     info.from.type, info.from.ip, info.from.curFlag,
177                     info.to.type, info.to.ip, info.to.curFlag,
178                     info.dup.type, info.dup.ip, info.dup.curFlag,
179                     info.close.type, info.close.ip, info.close.curFlag);
180             saveString.appendFormat("usage : %d, time:%02d-%02d %02d:%02d:%02d.%03lu(%lu)", info.usage,
181                     localTime->tm_mon+1, localTime->tm_mday,
182                     localTime->tm_hour, localTime->tm_min,
183                     localTime->tm_sec, tv.tv_usec/1000,
184                     ((tv.tv_sec * 1000) + (tv.tv_usec / 1000)));
185         }
186     }
187 
188     if (pFile != NULL) {
189         fwrite(saveString.string(), 1, saveString.size(), pFile);
190         mFenceLogSize = (uint32_t)ftell(pFile);
191         ret = mFenceLogSize;
192         fclose(pFile);
193     }
194 
195     return ret;
196 }
197