winscope怎么實(shí)現(xiàn)user版本上導(dǎo)出方案設(shè)計(jì)探討-千里馬android framework車載系統(tǒng)開發(fā)
背景
在馬哥給講解怎么用winscope來分析各種閃黑,黑屏等問題后,很多買課的同學(xué)都開始使用這個(gè)工具用于實(shí)際公司的項(xiàng)目了,但是很多同學(xué)又開始發(fā)現(xiàn)有一個(gè)問題,那就發(fā)現(xiàn)在user版本的手機(jī)設(shè)備上發(fā)現(xiàn)無法抓取相關(guān)的winscope,哪怕可以抓取也發(fā)現(xiàn)沒辦法導(dǎo)出來分析。這個(gè)問題在群里求助馬哥,這邊今天就給出相關(guān)的一些解決方案。相關(guān)winscope深入使用解決閃黑等請看我的b站視頻或者付費(fèi)視頻,可以直接+W:androidframework007
WMS實(shí)戰(zhàn)專題系統(tǒng)閃黑問題的終結(jié)者-千里馬android framework手機(jī)車機(jī)高階必備知識
winscope在user手機(jī)上的效果如下:

可以看出一直是顯示個(gè)error,但是具體是啥原因error呢?從服務(wù)端的python程序輸出日日志看看:

明顯看到其實(shí)服務(wù)端也只是去執(zhí)行相關(guān)的adb?shell命令,只不過這個(gè)命令需要有su?root這樣高級別的權(quán)限。自然在user手機(jī)上是沒有的
2、手機(jī)上可以抓取,但是無權(quán)限獲取文件
快捷按鈕可以去setting中放開

抓取完成后有相關(guān)的trace文件:

可以看到trace文件被導(dǎo)出到了?data/misc/wmtrace文件夾,那么嘗試取出發(fā)現(xiàn)有如下權(quán)限問題

可以看出這個(gè)wmtrace文件夾壓根沒有權(quán)限哈,自然無法取出
3、嘗試探索解決辦法
使用bugreoport命令:
test@test:~$?adb?bugreport
看看這個(gè)bugreport命令導(dǎo)出的相關(guān)文件:
/data/user_de/0/com.android.shell/files/bugreports/bugreport-crosshatch-SP1A.210812.016.C1-2022-06-28-12-21-13.zip:?1?file?pulled.?27.7?MB/s?(11790205?bytes?in?0.406s)
test@test:~$?adb?pull?/data/user_de/0/com.android.shell/files/bugreports/bugreport-crosshatch-SP1A.210812.016.C1-2022-06-28-12-21-13.zip?
/data/user_de/0/com.android.shell/files/bugreports/bugreport-crosshatch-SP1A.210812.016.C1-2022-06-28-12-21-13.zip:?1?file?pulled.?27.7?MB/s?(11790205?bytes?in?0.406s)

發(fā)現(xiàn)FS文件夾下面有個(gè)data的文件夾,還有misc,因為本身misc根本adb?shell是沒有權(quán)限可以查看的,看著是不是很有希望。。

但是情況卻如下:

只有recovery相關(guān),沒有看到wmtrace相關(guān)文件夾
但是明明就是/data/misc/wmtrace路徑,為啥沒有導(dǎo)出呢?需要知道這個(gè)原因就必須要看源碼了首先需要了解點(diǎn)bugreport其實(shí)本質(zhì)上也最多只能有shell權(quán)限,因為也屬于adb?shell拉起的進(jìn)程,但是為啥它可以導(dǎo)出data/misc/下面相關(guān)文件夾
為了解密這個(gè)我們可以來看看相關(guān)源碼frameworks/native/cmds/bugreport/bugreport.cpp
int?main()?{
????fprintf(stderr,
????????????"=============================================================================\n");
????fprintf(stderr,?"WARNING:?Flat?(text?file,?non-zipped)?bugreports?are?deprecated.\n");
????fprintf(stderr,?"WARNING:?Please?generate?zipped?bugreports?instead.\n");
????fprintf(stderr,?"WARNING:?On?the?host?use:?adb?bugreport?filename.zip\n");
????fprintf(stderr,?"WARNING:?On?the?device?use:?bugreportz\n");
????fprintf(stderr,?"WARNING:?bugreportz?will?output?the?filename?to?use?with?adb?pull.\n");
????fprintf(stderr,
????????????"=============================================================================\n\n\n");
????return?0;
}
可以看出的這里其實(shí)bugreport已經(jīng)是一個(gè)空殼了,真正還是bugreportz在起作用看看bugreportz的相關(guān)命令:frameworks/native/cmds/bugreportz/main.cpp
int?main(int?argc,?char*?argv[])?{
總結(jié)如下圖所示:
??//省略
????//?TODO:?code?below?was?copy-and-pasted?from?bugreport.cpp?(except?by?the
????//?timeout?value);
????//?should?be?reused?instead.
????//?Start?the?dumpstatez?service.
????//啟動(dòng)相關(guān)的?dumpstate服務(wù)
????if?(stream_data)?{
????????property_set("ctl.start",?"dumpstate");
????}?else?{
????????property_set("ctl.start",?"dumpstatez");
????}
????//?Socket?will?not?be?available?until?service?starts.
????int?s?=?-1;
????for?(int?i?=?0;?i?<?20;?i++)?{
????//與dumpstate進(jìn)行本地socket跨進(jìn)程通訊
????????????s?=?socket_local_client("dumpstate",?ANDROID_SOCKET_NAMESPACE_RESERVED,?SOCK_STREAM);
????????if?(s?>=?0)?break;
????????//?Try?again?in?1?second.
????????sleep(1);
????}
????int?ret;
????//socket接受相關(guān)的數(shù)據(jù)進(jìn)行處理
????if?(stream_data)?{
????????ret?=?bugreportz_stream(s);
????}?else?{
????????ret?=?bugreportz(s,?show_progress);
????}
????return?ret;
}

驗(yàn)證方式:
在執(zhí)行bugreport命令時(shí)候:
test@test:~/aosp/frameworks/native/cmds$?adb?bugreport
[??5%]?generating?bugreport-crosshatch-SP1A.210812.016.C1-2022-06-28-13-02-19.zip
開另一個(gè)在終端進(jìn)行adb?shell查看一下dumpstate服務(wù)是啥權(quán)限:
crosshatch:/?$?ps?-A?|?grep?dump????????????????????????????????????????????????????????????????????????
root?????????16137?????1?10878140??5172?0???????????????????0?S?dumpstate
明顯看到是一個(gè)root權(quán)限的進(jìn)程
4、原因尋找及解決辦法
上面已經(jīng)分析了bugreport的原理,實(shí)際是借助dumpstate來實(shí)現(xiàn)獲取高權(quán)限root的,那么問題來了,為啥wmtrace相關(guān)文件夾呢?這個(gè)問題就得看dumpstate相關(guān)源碼了:
frameworks/native/cmds/dumpstate/dumpstate.cpp看到了如下的代碼:
#define?PSTORE_LAST_KMSG?"/sys/fs/pstore/console-ramoops"
#define?ALT_PSTORE_LAST_KMSG?"/sys/fs/pstore/console-ramoops-0"
#define?BLK_DEV_SYS_DIR?"/sys/block"
#define?RECOVERY_DIR?"/cache/recovery"
#define?RECOVERY_DATA_DIR?"/data/misc/recovery"
#define?UPDATE_ENGINE_LOG_DIR?"/data/misc/update_engine_log"
#define?LOGPERSIST_DATA_DIR?"/data/misc/logd"
#define?PREREBOOT_DATA_DIR?"/data/misc/prereboot"
#define?PROFILE_DATA_DIR_CUR?"/data/misc/profiles/cur"
#define?PROFILE_DATA_DIR_REF?"/data/misc/profiles/ref"
#define?XFRM_STAT_PROC_FILE?"/proc/net/xfrm_stat"
#define?WLUTIL?"/vendor/xbin/wlutil"
#define?WMTRACE_DATA_DIR?"/data/misc/wmtrace"
#define?OTA_METADATA_DIR?"/metadata/ota"
#define?SNAPSHOTCTL_LOG_DIR?"/data/misc/snapshotctl_log"
#define?LINKERCONFIG_DIR?"/linkerconfig"
#define?PACKAGE_DEX_USE_LIST?"/data/system/package-dex-usage.list"
#define?SYSTEM_TRACE_SNAPSHOT?"/data/misc/perfetto-traces/bugreport/systrace.pftrace"
#define?CGROUPFS_DIR?"/sys/fs/cgroup"
可以看到有列出一個(gè)個(gè)的data相關(guān)目錄,有RECOVERY_DATA_DIR和WMTRACE_DATA_DIR,這里重點(diǎn)看看WMTRACE_DATA_DIR為啥沒有被導(dǎo)出看看是否有相關(guān)的限制條件:
看到了如下的代碼,這里有一個(gè)條件就是!PropertiesHelper::IsUserBuild()即只有在非user手機(jī)才可以導(dǎo)出WMTRACE_DATA_DIR目錄
????/*?Add?window?and?surface?trace?files.?*/
????if?(!PropertiesHelper::IsUserBuild())?{
????????ds.AddDir(WMTRACE_DATA_DIR,?false);
????}
修改方案探索:1、直接刪除??if?(!PropertiesHelper::IsUserBuild())?條件(比較暴力不安全)
???//if?(!PropertiesHelper::IsUserBuild())?{
????????ds.AddDir(WMTRACE_DATA_DIR,?false);
??//??}
2、可以加一個(gè)或條件,加入自己的暗門(建議這種),比如自己也搞一個(gè)prop,可以通過adb?shell改變的prop
???if?(!PropertiesHelper::IsUserBuild()?||?isEnableProp())?{
????????ds.AddDir(WMTRACE_DATA_DIR,?false);
????}
isEnableProp即可以實(shí)現(xiàn)自己的prop判斷