1 /*
2 * Copyright (c) 2012-2014, Linux Foundation. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above
10 * copyright notice, this list of conditions and the following
11 * disclaimer in the documentation and/or other materials provided
12 * with the distribution.
13 * * Neither the name of Linux Foundation nor the names of its
14 * contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 #ifndef LOG_TAG
31 #define LOG_TAG "qsfdump"
32 #endif
33 #define LOG_NDEBUG 0
34 #include <hwc_utils.h>
35 #include <hwc_dump_layers.h>
36 #include <cutils/log.h>
37 #include <sys/stat.h>
38 #include <comptype.h>
39 #ifdef STDC_FORMAT_MACROS
40 #include <inttypes.h>
41 #endif
42
43 namespace qhwc {
44
45 // MAX_ALLOWED_FRAMEDUMPS must be capped to (LONG_MAX - 1)
46 // 60fps => 216000 frames per hour
47 // Below setting of 216000 * 24 * 7 => 1 week or 168 hours of capture.
48 enum {
49 MAX_ALLOWED_FRAMEDUMPS = (216000 * 24 * 7)
50 };
51
52 bool HwcDebug::sDumpEnable = false;
53
HwcDebug(uint32_t dpy)54 HwcDebug::HwcDebug(uint32_t dpy):
55 mDumpCntLimRaw(0),
56 mDumpCntrRaw(1),
57 mDumpCntLimPng(0),
58 mDumpCntrPng(1),
59 mDpy(dpy) {
60 char dumpPropStr[PROPERTY_VALUE_MAX];
61 if(mDpy) {
62 strlcpy(mDisplayName, "external", sizeof(mDisplayName));
63 } else {
64 strlcpy(mDisplayName, "primary", sizeof(mDisplayName));
65 }
66 snprintf(mDumpPropKeyDisplayType, sizeof(mDumpPropKeyDisplayType),
67 "debug.sf.dump.%s", (char *)mDisplayName);
68
69 if ((property_get("debug.sf.dump.enable", dumpPropStr, NULL) > 0)) {
70 if(!strncmp(dumpPropStr, "true", strlen("true"))) {
71 sDumpEnable = true;
72 }
73 }
74 }
75
dumpLayers(hwc_display_contents_1_t * list)76 void HwcDebug::dumpLayers(hwc_display_contents_1_t* list)
77 {
78 // Check need for dumping layers for debugging.
79 if (UNLIKELY(sDumpEnable) && UNLIKELY(needToDumpLayers()) && LIKELY(list)) {
80 logHwcProps(list->flags);
81 for (size_t i = 0; i < list->numHwLayers; i++) {
82 logLayer(i, list->hwLayers);
83 dumpLayer(i, list->hwLayers);
84 }
85 }
86 }
87
needToDumpLayers()88 bool HwcDebug::needToDumpLayers()
89 {
90 bool bDumpLayer = false;
91 char dumpPropStr[PROPERTY_VALUE_MAX];
92 // Enable primary dump and disable external dump by default.
93 bool bDumpEnable = !mDpy;
94 time_t timeNow;
95 tm dumpTime;
96
97 // Override the bDumpEnable based on the property value, if the property
98 // is present in the build.prop file.
99 if ((property_get(mDumpPropKeyDisplayType, dumpPropStr, NULL) > 0)) {
100 if(!strncmp(dumpPropStr, "true", strlen("true")))
101 bDumpEnable = true;
102 else
103 bDumpEnable = false;
104 }
105
106 if (false == bDumpEnable)
107 return false;
108
109 time(&timeNow);
110 localtime_r(&timeNow, &dumpTime);
111
112 if ((property_get("debug.sf.dump.png", dumpPropStr, NULL) > 0) &&
113 (strncmp(dumpPropStr, mDumpPropStrPng, PROPERTY_VALUE_MAX - 1))) {
114 // Strings exist & not equal implies it has changed, so trigger a dump
115 strlcpy(mDumpPropStrPng, dumpPropStr, sizeof(mDumpPropStrPng));
116 mDumpCntLimPng = atoi(dumpPropStr);
117 if (mDumpCntLimPng > MAX_ALLOWED_FRAMEDUMPS) {
118 ALOGW("Warning: Using debug.sf.dump.png %d (= max)",
119 MAX_ALLOWED_FRAMEDUMPS);
120 mDumpCntLimPng = MAX_ALLOWED_FRAMEDUMPS;
121 }
122 mDumpCntLimPng = (mDumpCntLimPng < 0) ? 0: mDumpCntLimPng;
123 if (mDumpCntLimPng) {
124 snprintf(mDumpDirPng, sizeof(mDumpDirPng),
125 "/data/sfdump.png.%04d.%02d.%02d.%02d.%02d.%02d",
126 dumpTime.tm_year + 1900, dumpTime.tm_mon + 1,
127 dumpTime.tm_mday, dumpTime.tm_hour,
128 dumpTime.tm_min, dumpTime.tm_sec);
129 if (0 == mkdir(mDumpDirPng, 0777))
130 mDumpCntrPng = 0;
131 else {
132 ALOGE("Error: %s. Failed to create sfdump directory: %s",
133 strerror(errno), mDumpDirPng);
134 mDumpCntrPng = mDumpCntLimPng + 1;
135 }
136 }
137 }
138
139 if (mDumpCntrPng <= mDumpCntLimPng)
140 mDumpCntrPng++;
141
142 if ((property_get("debug.sf.dump", dumpPropStr, NULL) > 0) &&
143 (strncmp(dumpPropStr, mDumpPropStrRaw, PROPERTY_VALUE_MAX - 1))) {
144 // Strings exist & not equal implies it has changed, so trigger a dump
145 strlcpy(mDumpPropStrRaw, dumpPropStr, sizeof(mDumpPropStrRaw));
146 mDumpCntLimRaw = atoi(dumpPropStr);
147 if (mDumpCntLimRaw > MAX_ALLOWED_FRAMEDUMPS) {
148 ALOGW("Warning: Using debug.sf.dump %d (= max)",
149 MAX_ALLOWED_FRAMEDUMPS);
150 mDumpCntLimRaw = MAX_ALLOWED_FRAMEDUMPS;
151 }
152 mDumpCntLimRaw = (mDumpCntLimRaw < 0) ? 0: mDumpCntLimRaw;
153 if (mDumpCntLimRaw) {
154 snprintf(mDumpDirRaw, sizeof(mDumpDirRaw),
155 "/data/sfdump.raw.%04d.%02d.%02d.%02d.%02d.%02d",
156 dumpTime.tm_year + 1900, dumpTime.tm_mon + 1,
157 dumpTime.tm_mday, dumpTime.tm_hour,
158 dumpTime.tm_min, dumpTime.tm_sec);
159 if (0 == mkdir(mDumpDirRaw, 0777))
160 mDumpCntrRaw = 0;
161 else {
162 ALOGE("Error: %s. Failed to create sfdump directory: %s",
163 strerror(errno), mDumpDirRaw);
164 mDumpCntrRaw = mDumpCntLimRaw + 1;
165 }
166 }
167 }
168
169 if (mDumpCntrRaw <= mDumpCntLimRaw)
170 mDumpCntrRaw++;
171
172 bDumpLayer = (mDumpCntLimPng || mDumpCntLimRaw)? true : false;
173 return bDumpLayer;
174 }
175
logHwcProps(uint32_t listFlags)176 void HwcDebug::logHwcProps(uint32_t listFlags)
177 {
178 static int hwcModuleCompType = -1;
179 static int sMdpCompMaxLayers = 0;
180 static String8 hwcModuleCompTypeLog("");
181 if (-1 == hwcModuleCompType) {
182 // One time stuff
183 char mdpCompPropStr[PROPERTY_VALUE_MAX];
184 if (property_get("debug.mdpcomp.maxlayer", mdpCompPropStr, NULL) > 0) {
185 sMdpCompMaxLayers = atoi(mdpCompPropStr);
186 }
187 hwcModuleCompType =
188 qdutils::QCCompositionType::getInstance().getCompositionType();
189 hwcModuleCompTypeLog.appendFormat("%s%s%s%s%s%s",
190 // Is hwc module composition type now a bit-field?!
191 (hwcModuleCompType == qdutils::COMPOSITION_TYPE_GPU)?
192 "[GPU]": "",
193 (hwcModuleCompType & qdutils::COMPOSITION_TYPE_MDP)?
194 "[MDP]": "",
195 (hwcModuleCompType & qdutils::COMPOSITION_TYPE_C2D)?
196 "[C2D]": "",
197 (hwcModuleCompType & qdutils::COMPOSITION_TYPE_CPU)?
198 "[CPU]": "",
199 (hwcModuleCompType & qdutils::COMPOSITION_TYPE_DYN)?
200 "[DYN]": "",
201 (hwcModuleCompType >= (qdutils::COMPOSITION_TYPE_DYN << 1))?
202 "[???]": "");
203 }
204 ALOGI("Display[%s] Layer[*] %s-HwcModuleCompType, %d-layer MdpComp %s",
205 mDisplayName, hwcModuleCompTypeLog.string(), sMdpCompMaxLayers,
206 (listFlags & HWC_GEOMETRY_CHANGED)? "[HwcList Geometry Changed]": "");
207 }
208
logLayer(size_t layerIndex,hwc_layer_1_t hwLayers[])209 void HwcDebug::logLayer(size_t layerIndex, hwc_layer_1_t hwLayers[])
210 {
211 if (NULL == hwLayers) {
212 ALOGE("Display[%s] Layer[%d] Error. No hwc layers to log.",
213 mDisplayName, layerIndex);
214 return;
215 }
216
217 hwc_layer_1_t *layer = &hwLayers[layerIndex];
218 hwc_rect_t sourceCrop = integerizeSourceCrop(layer->sourceCropf);
219 hwc_rect_t displayFrame = layer->displayFrame;
220 size_t numHwcRects = layer->visibleRegionScreen.numRects;
221 hwc_rect_t const *hwcRects = layer->visibleRegionScreen.rects;
222 private_handle_t *hnd = (private_handle_t *)layer->handle;
223
224 char pixFormatStr[32] = "None";
225 String8 hwcVisRegsScrLog("[None]");
226
227 for (size_t i = 0 ; (hwcRects && (i < numHwcRects)); i++) {
228 if (0 == i)
229 hwcVisRegsScrLog.clear();
230 hwcVisRegsScrLog.appendFormat("[%dl, %dt, %dr, %db]",
231 hwcRects[i].left, hwcRects[i].top,
232 hwcRects[i].right, hwcRects[i].bottom);
233 }
234
235 if (hnd)
236 getHalPixelFormatStr(hnd->format, pixFormatStr);
237
238 // Log Line 1
239 ALOGI("Display[%s] Layer[%d] SrcBuff[%dx%d] SrcCrop[%dl, %dt, %dr, %db] "
240 "DispFrame[%dl, %dt, %dr, %db] VisRegsScr%s", mDisplayName, layerIndex,
241 (hnd)? getWidth(hnd) : -1, (hnd)? getHeight(hnd) : -1,
242 sourceCrop.left, sourceCrop.top,
243 sourceCrop.right, sourceCrop.bottom,
244 displayFrame.left, displayFrame.top,
245 displayFrame.right, displayFrame.bottom,
246 hwcVisRegsScrLog.string());
247 // Log Line 2
248 ALOGI("Display[%s] Layer[%d] LayerCompType = %s, Format = %s, "
249 "Orientation = %s, Flags = %s%s%s, Hints = %s%s%s, "
250 "Blending = %s%s%s", mDisplayName, layerIndex,
251 (layer->compositionType == HWC_FRAMEBUFFER)? "Framebuffer(GPU)":
252 (layer->compositionType == HWC_OVERLAY)? "Overlay":
253 (layer->compositionType == HWC_BACKGROUND)? "Background":"???",
254 pixFormatStr,
255 (layer->transform == 0)? "ROT_0":
256 (layer->transform == HWC_TRANSFORM_FLIP_H)? "FLIP_H":
257 (layer->transform == HWC_TRANSFORM_FLIP_V)? "FLIP_V":
258 (layer->transform == HWC_TRANSFORM_ROT_90)? "ROT_90":
259 "ROT_INVALID",
260 (layer->flags)? "": "[None]",
261 (layer->flags & HWC_SKIP_LAYER)? "[Skip layer]":"",
262 (layer->flags & qhwc::HWC_MDPCOMP)? "[MDP Comp]":"",
263 (layer->hints)? "":"[None]",
264 (layer->hints & HWC_HINT_TRIPLE_BUFFER)? "[Triple Buffer]":"",
265 (layer->hints & HWC_HINT_CLEAR_FB)? "[Clear FB]":"",
266 (layer->blending == HWC_BLENDING_NONE)? "[None]":"",
267 (layer->blending == HWC_BLENDING_PREMULT)? "[PreMult]":"",
268 (layer->blending == HWC_BLENDING_COVERAGE)? "[Coverage]":"");
269 }
270
dumpLayer(size_t layerIndex,hwc_layer_1_t hwLayers[])271 void HwcDebug::dumpLayer(size_t layerIndex, hwc_layer_1_t hwLayers[])
272 {
273 char dumpLogStrPng[128] = "";
274 char dumpLogStrRaw[128] = "";
275 bool needDumpRaw = (mDumpCntrRaw <= mDumpCntLimRaw)? true:false;
276
277 if (needDumpRaw) {
278 snprintf(dumpLogStrRaw, sizeof(dumpLogStrRaw),
279 "[raw-dump-frame: %03d of %03d]", mDumpCntrRaw,
280 mDumpCntLimRaw);
281 }
282
283 if (!needDumpRaw)
284 return;
285
286 if (NULL == hwLayers) {
287 ALOGE("Display[%s] Layer[%d] %s%s Error: No hwc layers to dump.",
288 mDisplayName, layerIndex, dumpLogStrRaw, dumpLogStrPng);
289 return;
290 }
291
292 hwc_layer_1_t *layer = &hwLayers[layerIndex];
293 private_handle_t *hnd = (private_handle_t *)layer->handle;
294 char pixFormatStr[32] = "None";
295
296 if (NULL == hnd) {
297 ALOGI("Display[%s] Layer[%d] %s%s Skipping dump: Bufferless layer.",
298 mDisplayName, layerIndex, dumpLogStrRaw, dumpLogStrPng);
299 return;
300 }
301
302 getHalPixelFormatStr(hnd->format, pixFormatStr);
303
304 if (needDumpRaw && hnd->base) {
305 char dumpFilename[PATH_MAX];
306 bool bResult = false;
307 snprintf(dumpFilename, sizeof(dumpFilename),
308 "%s/sfdump%03d.layer%d.%dx%d.%s.%s.raw",
309 mDumpDirRaw, mDumpCntrRaw,
310 layerIndex, getWidth(hnd), getHeight(hnd),
311 pixFormatStr, mDisplayName);
312 FILE* fp = fopen(dumpFilename, "w+");
313 if (NULL != fp) {
314 bResult = (bool) fwrite((void*)hnd->base, hnd->size, 1, fp);
315 fclose(fp);
316 }
317 ALOGI("Display[%s] Layer[%d] %s Dump to %s: %s",
318 mDisplayName, layerIndex, dumpLogStrRaw,
319 dumpFilename, bResult ? "Success" : "Fail");
320 }
321 }
322
getHalPixelFormatStr(int format,char pixFormatStr[])323 void HwcDebug::getHalPixelFormatStr(int format, char pixFormatStr[])
324 {
325 if (!pixFormatStr)
326 return;
327
328 switch(format) {
329 case HAL_PIXEL_FORMAT_RGBA_8888:
330 strlcpy(pixFormatStr, "RGBA_8888", sizeof(pixFormatStr));
331 break;
332 case HAL_PIXEL_FORMAT_RGBX_8888:
333 strlcpy(pixFormatStr, "RGBX_8888", sizeof(pixFormatStr));
334 break;
335 case HAL_PIXEL_FORMAT_RGB_888:
336 strlcpy(pixFormatStr, "RGB_888", sizeof(pixFormatStr));
337 break;
338 case HAL_PIXEL_FORMAT_RGB_565:
339 strlcpy(pixFormatStr, "RGB_565", sizeof(pixFormatStr));
340 break;
341 case HAL_PIXEL_FORMAT_BGRA_8888:
342 strlcpy(pixFormatStr, "BGRA_8888", sizeof(pixFormatStr));
343 break;
344 case HAL_PIXEL_FORMAT_YV12:
345 strlcpy(pixFormatStr, "YV12", sizeof(pixFormatStr));
346 break;
347 case HAL_PIXEL_FORMAT_YCbCr_422_SP:
348 strlcpy(pixFormatStr, "YCbCr_422_SP_NV16", sizeof(pixFormatStr));
349 break;
350 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
351 strlcpy(pixFormatStr, "YCrCb_420_SP_NV21", sizeof(pixFormatStr));
352 break;
353 case HAL_PIXEL_FORMAT_YCbCr_422_I:
354 strlcpy(pixFormatStr, "YCbCr_422_I_YUY2", sizeof(pixFormatStr));
355 break;
356 case HAL_PIXEL_FORMAT_YCrCb_422_I:
357 strlcpy(pixFormatStr, "YCrCb_422_I_YVYU", sizeof(pixFormatStr));
358 break;
359 case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
360 strlcpy(pixFormatStr, "NV12_ENCODEABLE", sizeof(pixFormatStr));
361 break;
362 case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
363 strlcpy(pixFormatStr, "YCbCr_420_SP_TILED_TILE_4x2",
364 sizeof(pixFormatStr));
365 break;
366 case HAL_PIXEL_FORMAT_YCbCr_420_SP:
367 strlcpy(pixFormatStr, "YCbCr_420_SP", sizeof(pixFormatStr));
368 break;
369 case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO:
370 strlcpy(pixFormatStr, "YCrCb_420_SP_ADRENO", sizeof(pixFormatStr));
371 break;
372 case HAL_PIXEL_FORMAT_YCrCb_422_SP:
373 strlcpy(pixFormatStr, "YCrCb_422_SP", sizeof(pixFormatStr));
374 break;
375 case HAL_PIXEL_FORMAT_R_8:
376 strlcpy(pixFormatStr, "R_8", sizeof(pixFormatStr));
377 break;
378 case HAL_PIXEL_FORMAT_RG_88:
379 strlcpy(pixFormatStr, "RG_88", sizeof(pixFormatStr));
380 break;
381 case HAL_PIXEL_FORMAT_INTERLACE:
382 strlcpy(pixFormatStr, "INTERLACE", sizeof(pixFormatStr));
383 break;
384 case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
385 strlcpy(pixFormatStr, "YCbCr_420_SP_VENUS", sizeof(pixFormatStr));
386 break;
387 default:
388 snprintf(pixFormatStr, sizeof(pixFormatStr), "Unknown0x%X", format);
389 break;
390 }
391 }
392
393 } // namespace qhwc
394
395