• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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