Android TV 高效调试技巧

文章目录


  在开发机顶盒ROM时,有一些高效的开发技巧,可以让开发工作效率大大提升,本篇文章基于Android4.4.2系统,简单介绍下一些常见的高效调试方法。

一、编译

  先说编译,是因为Android系统开发和Android应用开发有个明显不同的地方:完整ROM编译的时间会比较长,可能会达到一个小时以上,所以要谨慎全编版本

1.1 版本全编

  先简单说下全编译版本,此处就以Hi3798MV300为例介绍,全编ROM的过程分为3个步骤:
   1>source build/envsetup.sh
     该步骤其实是调用了build/envsetup.sh脚本,该脚本的作用是初始化编译环境,并引入一些辅助的Shell函数,如mm、mmm等。
   2>lunch Hi3798MV300H-eng
     该步骤是调用了lunch函数,这个函数后面的参数包含两部分:硬件类型和版本类型。
   3>make bigfish -j 2>&1 | tee log_Hi3798MV300H.txt
     此时开始真正编译,make bigfish是编译版本的命令;2>&1是将将标准错误重定向到标准输出;tee log_Hi3798MV300H.txt是从标准输入设备读取数据,将其内容输出到标准输出设备,同时保存成文件。简单来说,就是开始编译版本,并且将编译日志保存到log_Hi3798MV300H.txt文件。

1.2 公共单编模块

  说完了全编,接下来就要说单编某个模块。要单编模块,需要先执行source build/envsetup.sh和lunch Hi3798MV300H-eng命令,然后再执行单编命令。经常单编的模块如下:
   1>apk
     在packages/app/ApkName目录,执行mm -B即可。编出来的 Apk 在 out/target/product/Hi3798MV300H/system/app目录。
   2>jar
     此处指的是修改framework代码,单编命令也是mm -B,常见的单编命令执行目录及其对应的jar如下:

目录 jar
frameworks/base/services services.jar
frameworks/base/policy android.policy.jar
frameworks/base framework.jar

   3>so
     在调试播放器、HDMI等涉及到较底层代码时,常常会编译出so文件,如在device/hisilicon/bigfish/frameworks/hidisplaymanager/hal执行mm -B,会生成out/target/product/Hi3798MV300H/system/lib/hw/hidisplay.bigfish.so文件。
   4>bin
     在frameworks/base/cmds/bootanimation目录执行mm -B,会生成out/target/product/Hi3798MV300H/system/bin/bootanimation文件;在external/dhcpcd执行mm -B,会生成out/target/product/Hi3798MV300H/system/bin/dhcpcd文件。

1.3 芯片特有单编模块

  除了这些公共的可以单编的模块,在不同的芯片平台,还有一些特殊的可以单编的模块,如在Amlogic905上,就有以下模块可以单编:

1.3.1 Uboot

  即Amlogic的bootloader,此处以gxlx_p261.dts配置为例,编译uboot文件方式如下:
   1、配置编译环境
     export PATH=sdk路径/toolchain/gcc-arm-none-eabi-6-2017-q2-update/bin/:$PATH
    2、修改makefile脚本

diff --git a/uboot/Makefile b/uboot/Makefile
index 641b28c..551c757 100755
--- a/uboot/Makefile
+++ b/uboot/Makefile
@@ -246,7 +246,7 @@ ifeq ($(HOSTARCH),$(ARCH))
 CROSS_COMPILE ?=
 endif
 
-export CROSS_COMPILE=/opt/gcc-linaro-aarch64-none-elf-4.8-2013.11_linux/bin/aarch64-none-elf-
+export CROSS_COMPILE=sdk路径/toolchain/gcc-linaro-aarch64-none-elf-4.8-2013.11_linux/bin/aarch64-none-elf-
 
 KCONFIG_CONFIG ?= .config

    3、在sdk/uboot目录执行: ./mk gxl_p211_v1
    生成的uboot文件为:uboot/fip/gxl目录下的u-boot.bin、u-boot.bin.sd.bin、u-boot.bin.usb.bl2和u-boot.bin.usb.tpl。

1.3.2 boot.img&dt.img

   编译的命令为:make bootimage,此命令会同时生成boot.img和dt.img。

二、调试

  编译简单介绍完了,就要说调试了,机顶盒ROM的调试方式比较多样,就先接着第一章节,介绍一下上面的问题怎么替换。

2.1 文件替换

2.1.1 常规文件替换

  第一章节编出来的文件有apk、so、bin、jar等,替换到out目录下对应的机顶盒路径中即可。这句话可能有点不好理解,例子如下:

源码目录 机顶盒中路径
out/target/product/Hi3798MV300H/system/bin/dhcpcd system/bin/dhcpcd
out/target/product/Hi3798MV300H/system/framework/android.policy.jar system/framework/android.policy.jar
out/target/product/Hi3798MV300H/system/lib/hw/hidisplay.bigfish.so system/lib/hw/hidisplay.bigfish.so
out/target/product/Hi3798MV300H/system/app/BluetoothSet.apk system/app/BluetoothSet.apk

  替换文件时,除了apk、so、jar之外,别的(还有如:20-dns.conf、bootAnimation.zip等)都要保持替换前后权限一致。查看文件权限的命令是"ll filename",文件权限为"r:4 w:2 x:1 ",常见的权限如下:

    -rw------- (600)      只有拥有者有读写权限。
    -rw-r--r-- (644)      只有拥有者有读写权限;而属组用户和其他用户只有读权限。
    -rwx------ (700)     只有拥有者有读、写、执行权限。
    -rwxr-xr-x (755)    拥有者有读、写、执行权限;而属组用户和其他用户只有读、执行权限。
    -rwx--x--x (711)    拥有者有读、写、执行权限;而属组用户和其他用户只有执行权限。
    -rw-rw-rw- (666)   所有用户都有文件读、写权限。
    -rwxrwxrwx (777)  所有用户都有读、写、执行权限。

2.1.2 特殊文件替换

  特殊的文件,可简单理解为不能直接替换到机顶盒中的文件,比如1.3章节中编出的文件,替换方式如下(usb_disk代表U盘挂载到终端后的路径):
   1>boot.img
    cat usb_disk/boot.img > /dev/block/boot
   2>uboot
    cat usb_disk/u-boot.bin.sd.bin > /dev/block/bootloader

2.2 常用调试命令

  要想让开发过程变得高效,常用的调试命令必须要能够熟练地使用。在不同的芯片平台上,U盘挂载后的路径是不同的,如下:

芯片 常规U盘路径
海思 mnt/sda/sda1
Amlogic storage/external_storage/sda1
Mstar mnt/usb/sda1

  为方便表示,下文中的U盘路径均用usb_disk表示。

2.2.1 ADB命令

ADB命令 串口命令 意义
adb connect IP:port - 连接 Android 设备
adb disconnect - 断开 ADB 连接
adb kill-server - 关闭 PC ADB 调试,效果等同断开连接
adb shell - 进入 shell 模式,效果等同于串口连接
adb remount mount -o remount,rw /system 将 ‘/system’ 部分置于可写入的模式
ll file(adb shell后) ll file 查看文件权限
chmod 755 file(adb shell后) chmod 755 file 赋予文件755权限
adb reboot reboot 重启
reboot recovery(adb shell后) reboot recovery 重启后进入recovery
adb install -r **.apk pm install -r **.apk 覆盖安装某个应用
adb uninstall com.exp.test pm uninstall com.exp.test 卸载某个应用(com.exp.test为应用的包名)
pm list packages(adb shell后) pm list packages 查看已安装的应用及其对应的包名
adb logcat –c logcat -c 清除log缓存
logcat(adb shell后) logcat 直接查看运行log
adb logcat –v threadtime >E:\1.log logcat -v threadtime -f /sdcard/.log 抓取1.log
dmesg(adb shell后) dmesg 直接查看运行内核log
tcpdump -s 0 -i eth0 -w /data/dhcp.pcap(adb shell后) tcpdump -s 0 -i eth0 -w /data/dhcp.pcap 抓网络包
adb pull system/media/bootanimation.zip E:\ cp -r system/media/bootanimation.zip usb_disk 从终端中拷贝文件出来
adb push E:\Provision.apk system/app/Provision.apk cp -r usb_disk/Provision.apk system/app/Provision.apk 替换文件到终端中
adb shell sync sync 将内存缓冲区中的数据 写入到磁盘
am start -n 包名/完整Activity路径(adb shell后) am start -n 包名/完整Activity路径 启动Activity
am broadcast -a “broadcastactionfilter”(adb shell后) am broadcast -a “broadcastactionfilter” 发送Broadcast
am startservice “com.exm.test/.TestService”(adb shell后) am startservice “com.exm.test/.TestService” 启动Service
content query --uri content://stbconfig/authentication(adb shell后) content query --uri content://stbconfig/authentication 查询ContentProvider内容
am force-stop com.exp.test(adb shell后) am force-stop com.exp.test 强制关闭应用
screencap /sdcard/screen.png(adb shell后) screencap /sdcard/test.png 截屏
screenrecord /sdcard/demo.mp4(adb shell后) screenrecord /sdcard/demo.mp4 录制视频
input text “”(adb shell后) input text “” 输入一段字符串
input keyevent 23(adb shell后) input keyevent 23 模拟按键
dumpsys -l/service list(adb shell后) dumpsys -l/service list 查看当前运行的Service
dumpsys package(adb shell后) dumpsys package 查看应用的四大组件信息
dumpsys activity (adb shell后) dumpsys activity 查询AMS服务相关信息
dumpsys window(adb shell后) dumpsys window 查询WMS服务相关信息
dumpsys cpuinfo(adb shell后) dumpsys cpuinfo 查询CPU情况
dumpsys meminfo(adb shell后) dumpsys meminfo 查询内存情况
top(adb shell后) top 查询试试内存情况
ps(adb shell后) ps 查看进程
start adbd(adb shell后) start adbd 启用adbd,可以使用adb连接功能
stop adbd(adb shell后) stop adbd 禁用adbd
start console(adb shell后) start console 启用串口调试功能
stop console(adb shell后) stop console 禁用串口调试功能
getprop(adb shell后) getprop 查看属性
setprop prop_name prop_val(adb shell后) setprop prop_name prop_val 设置属性值
cat node_path(adb shell后) cat node_path 查看节点值
remotecfg(adb shell后,Amlogic上使用)
stop ir_user(adb shell后,海思上使用)
busybox devmem 0x1f007b00 16 0x0000 (adb shell后,Mstar9380上使用)
remotecfg(Amlogic上使用)
stop ir_user(海思上使用)
busybox devmem 0x1f007b00 16 0x0000 (Mstar9380上使用)
禁用红外遥控器使用功能
./system/bin/remotecfg.sh(adb shell后,Amlogic上使用)
start ir_user(adb shell后,海思上使用)
busybox devmem 0x1f007b00 16 0x01bf(adb shell后,Mstar9380上使用)
./system/bin/remotecfg.sh(Amlogic上使用)
start ir_user(海思上使用)
busybox devmem 0x1f007b00 16 0x01bf (Mstar9380上使用)
启用红外遥控器使用功能
settings get secure ntp_server (adb shell后) settings get secure ntp_server 查看系统数据库中值
settings put secure ntp_server cn.pool.ntp.org(adb shell后) settings put secure ntp_server cn.pool.ntp.org 设置系统数据库中值
wm size(adb shell后) wm size 查看UI分辨率
wm size 1920x1080(adb shell后) wm size 1920x1080 修改UI分辨率
wm density(adb shell后) wm density 查看屏幕密度
wm density 240(adb shell后) wm density 240 修改屏幕密度
cat /proc/cpuinfo(adb shell后) cat /proc/cpuinfo 查看CPU信息

2.2.2 LINUX命令

LINUX命令 意义
cd /
cd -
cd dirA
切换到根目录
切换到上次操作目录
切换到dirA目录
pwd 查看当前目录
su userName 切换用户
df 查看磁盘使用情况
mkdir 创建目录
rm –f fileName 强制删除文件
rm –rf folderName 强制删除文件夹(慎用)
mv aName bName 文件(夹)重命名
cp –rf dirA dirB 拷贝文件夹 A 内容到文件夹 B
find . –name fileName 在当前目录搜索某文件
grep –rin “str” ./* 在当前目录检索字符串
tar –cvf test.tar ./fName 压缩 fName 目录文件为 test.tar
tar –xvf a.tar 解压 test.tar
make clean 清除编译内容
busybox md5sum fileName 查看文件 md5
java -Xmx2048m -jar signapk.jar -w platform.x509.pem platform.pk8 test.apk test_sign.apk apk签名
java -Xmx2048m -jar signapk.jar -w testkey.x509.pem testkey.pk8 update.zip update_signed.zip update.zip签名

2.2.3 VIM命令

VIM命令 意义
vi fileName 打开文件
:set nu 显示行数
/ 检索
:w 保存修改
:q 退出
i 进入编辑模式
Esc 退出编辑模式
dd 删除一行

2.2.4 GIT命令

VIM命令 意义
git branch 查看本地分支
git status . 查看当前目录哪些文件修改过还未提交
git diff filename/folderName 查看某个文件/文件夹具体修改内容
git log 查看本地所以修改记录
git log filename/folderName 查看某个文件/文件夹修改记录
git checkout fileName 回退某个文件未提交的修改
git pull 更新本地代码,与服务器同步
git show commitId 查看某次 commit 内容
git show –-stat commitId 查看某次提交修改的文件
git clone + gitUrl 拉取远程代码到本地
git checkout A B 从分支 A 切换到分支 B
git add/rm 添加到暂存区/删除文件
git commit –m “” 将修改提交到本地
git push origin branchRemoteName 将本地分支修改提交到远程分支

2.2.5 命令使用小技巧

  首先,要尽量将上述ADB命令与" |grep "结合使用,如"ll/ls"与" |grep"使用,可过滤特定名称的文件/文件夹;“getprop"与” |grep "使用,可过滤特定名称的属性;“dumpsys meminfo"与” |grep"使用,可过滤特定名称
应用的内存使用情况;“logcat"与” |grep "使用,可过滤某些特定日志。
  其次,多使用模糊搜索/特定目录搜索,如:"find frameworks/base –name Window.java"可搜索 frameworks/base 目录下名称中带 Window 的java文件。
  再者,在 shell 界面使用 linux 命令时,命令前都要加上"busybox"
  最后,在向机顶盒中 push 文件或从机顶盒向外 pull 文件后,尽量使用一下"adb shell sync",来确保文件传输完整。

三、积累关键功能调试经验

  在以上两个章节中,涵盖了较多的日常机顶盒ROM调试命令。除此之外,还有些命令之外的技巧需要积累,如下:

3.1 功能开关

  某些功能,在源码中是已经实现好了的,在检测ROM中是否包含该功能时,只需要检查特定的属性或文件即可。如:
  1>海思上的CEC开关
   persist.sys.hdmi.cec为true,代表打开该功能;为false,代表关闭该功能。
  2>海思上的HDMI待机开关
   persist.hdmi.suspend.enable为1,代表打开该功能;为0,代表关闭该功能;
   persist.hdmi.suspend.time为具体的待机时间,一般为5。
  3>Amlogic静帧功能
   system/etc目录下的blackout_whitelist.txt文件,文件内逐行写入要实现静帧功能的应用的包名、类名。
  3>Amlogic DHCP重连功能
   net.dhcp.repeat为enabled,代表打开DHCP重连功能;
   net.dhcp.repeat.count为重试次数。

3.2 调试思路

  当某一功能实现出现问题,要遵循"先硬件/环境,再软件"和"先底层,再上层"的排查思路,如下:
   1>先硬件/环境,再软件
    遇到一个问题时,要先了解问题出现的具体情况,是否与环境、复现问题方式、机顶盒硬件有关,先做对比验证。确定是软件问题后,再从软件侧进行排查。
   2>先底层,再上层
    遇到一个问题时,可以先用命令从底层了解功能是否OK。如果底层OK,那就是上层调用逻辑出现了问题,再层层向上、逐步缩小debug范围。
  至此,高效的调试技巧已介绍完毕。

上一篇:Android 每日一句(英语)


下一篇:广播数据写入界面的心得体会