sunwengang blog

developer | android display/graphics

  1. 1. RenderThread渲染绘制(结合systrace)
  2. 2. 合成送显流程
    1. 2.1. SurfaceFlinger模块
    2. 2.2. HWC模块
    3. 2.3. DRM模块
  3. 3. Fence同步机制
  4. 4. Google平台帧率切换
  5. 5. 磁盘空间占满100%
  6. 6. Android设备分辨率、密度以及dp的理解
  7. 7. 低内存分析方向和技巧
    1. 7.1. 查看进程占用内存情况
  8. 8. ubuntu查看公网ip
  9. 9. 查看视频解码的分辨率及对应的帧率支持
  10. 10. linux和windows书签同步
  11. 11. getService配置权限
  12. 12. HIDL编写/升级流程
  13. 13. ssk-key生成current.txt hash值
  14. 14. 修改git remote -v的orign源
  15. 15. git报错无法push(不建议使用)
  16. 16. git commit修改作者名称
  17. 17. gerrit拉取Andorid指定模块代码
  18. 18. ubuntu命令查看dns
  19. 19. markdown数学公式语法
  20. 20. 安装adb和fastboot
  21. 21. 针对image编译
  22. 22. 安装APK报错
  23. 23. 查看当前前台app包名(实时)
  24. 24. 监控设备实时获取当前的包名
  25. 25. APP增加多国语言
  26. 26. native crash分析
  27. 27. YUV数据查看
  28. 28. 关闭硬件加速
  29. 29. linux绘图UML/序列图工具dia
  30. 30. 屏幕旋转/转向切换命令
  31. 31. Surface两种合成方式(dump sf)
  32. 32. getprop查看当前版本是user/userdebug
  33. 33. getprop查看设备信息
  34. 34. 滑动到边缘Pixel值调试
  35. 35. Input调试(PointerLocation)
    1. 35.1. systrace查看
    2. 35.2. 点击input事件(up/down)
    3. 35.3. input和wms的debug log开关打开
  36. 36. FPS帧率测试
    1. 36.1. 获取实时帧率(主要用于获取游戏/视频应用的fps数据)
    2. 36.2. dump gfxinfo信息
    3. 36.3. 查看帧率以及如何在systrace分析帧率
    4. 36.4. systrace中的Frame
  37. 37. 屏幕录制视频(限定时间长)
    1. 37.1. 截图命令
  38. 38. dump sf查看buffer/layer列表
    1. 38.1. dump windows/inpu/sf
  39. 39. 源码打开input debug日志开关
  40. 40. adb打印kernel log,即内核调试信息dmsg和kmsg
    1. 40.1. 合并kmsg log
  41. 41. 查看设备的白名单
  42. 42. Android.mk和Android.bp转换语法
  43. 43. 将HIDL接口服务从设备system移到vendor
    1. 43.1. Android.bp(可参考)
  44. 44. C函数memset(…)
  45. 45. domain.te错误类型
  46. 46. 查看手机硬件设备(包含屏幕信息)
  47. 47. ubuntu的ll命令不能使用
  48. 48. ubuntu挂载硬盘
  49. 49. find命令
    1. 49.1. 设置GPU频率
  50. 50. ☆CPU/GPU信息文件路径
  51. 51. 加大dequeuebuffer数目
  52. 52. windows cmd过滤log
  53. 53. vscode插件
  54. 54. 抓取perfetto-trace(替代systrace)
    1. 54.1. systrace打开空白或者打不开
    2. 54.2. atrace转换到html
    3. 54.3. systrace的类别和选项(直接添加)
  55. 55. SElinux权限相关
    1. 55.1. 自动生成selinux权限代码
    2. 55.2. 开启/关闭Selinux权限
  56. 56. 进入fastboot
  57. 57. LCD屏幕低温残影现象
  58. 58. makefile
  59. 59. 亮度单位nit
    1. 59.1. 光学单位lux
  60. 60. 启动activity/关闭activity
  61. 61. Git命令
    1. 61.1. 查看代码提交历史(具体到某一行)
    2. 61.2. 提交代码
    3. 61.3. 提交草稿代码
  62. 62. 提交代码、sync代码报错Agent admitted failure to sign using the key
  63. 63. apt-get报错不能进行正常更新
  64. 64. ubuntu自带截图快捷键
  65. 65. gedit乱码
  66. 66. 跳过开机向导
  67. 67. ubuntu快速下载命令
  68. 68. 谷歌GMS服务
    1. 68.1. GMS测试注意事项
    2. 68.2. 常见问题
      1. 68.2.1. 开机向导设置密码后关机再开机黑屏
      2. 68.2.2. Play Store无法正常连接
      3. 68.2.3. Play Store下载应用失败
      4. 68.2.4. GMS应用首次登陆闪退,第二次正常
      5. 68.2.5. GMS应用缺少部分菜单
      6. 68.2.6. GMS部分应用联网后消失

android display/graphics相关的调试方法和优化工作效率技巧整理

RenderThread渲染绘制(结合systrace)

参考:Android Systrace 基础知识(7) - Vsync 解读
参考:BufferQueue 学习总结(内附动态图)
参考:android 判断list里有这条数据_Android图形渲染原理(中)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
----
frameworks/base/libs/hwui/renderthread -- DrawFrameTask::drawFrame() ----->
DrawFrameTask::postAndWait() ---->
DrawFrameTask::run() ----->
(1) DrawFrameTask::syncFrameState 同步Frame的State ---->
CanvasContext::prepareTree
(2) context->draw() 绘制 ------>
frameworks/base/libs/hwui/renderthread -- CanvasContext::draw() ---->
----
(1) frameworks/base/libs/hwui/pipeline/skia -- SkiaOpenGLPipeline::getFrame() ---->
frameworks/base/libs/hwui/renderthread/EglManager.cpp - EglManager::beginFrame ---->
(1.1)EglManager::makeCurrent ----->
frameworks/native/opengl/libs/EGL/eglApi.cpp -- eglMakeCurrent --->
frameworks/native/libs/nativewindow/ANativeWindow.cpp -- ANativeWindow_dequeueBuffer ---->
frameworks/native/libs/gui/Surface.cpp -- Surface::dequeueBuffer (`systrace: HWC release`)

(1.2)EglManager::queryBufferAge
----
(2) SkiaOpenGLPipeline::draw() ---->
(2.1) EglManager::damageFrame
(2.2) SkiaPipeline::renderFrame (`systrace:flush commands` 后调用,systrace显示在后)[--->SkiaPipeline::renderOverdraw] --->
SkiaPipeline::renderFrameImpl (先调用,systrace显示在前) --->
RenderNodeDrawable::onDraw ---->
RenderNodeDrawable::forceDraw [------>RenderNodeDrawable::drawBackwardsProjectedNodes] ---->
RenderNodeDrawable::drawContent ---->
RenderNodeDrawable::setViewProperties (`systrace:alpha caused saveLayer`)
----
(3) SkiaOpenGLPipeline::swapBuffers ----->
frameworks/native/opengl/libs/EGL/eglApi.cpp -- eglSwapBuffersWithDamageKHR ---->
frameworks/native/libs/nativewindow/ANativeWindow.cpp -- ANativeWindow_queueBuffer --->
frameworks/native/libs/gui/Surface.cpp -- Surface::queueBuffer (`systrace: gpu completion`绘制完成)

合成送显流程

Android Q,非最新AOSP流程,有变动

SurfaceFlinger模块

1
2
3
4
5
6
7
8
9
10
SurfaceFlinger::handleMessageRefresh();
preComposition();
rebuildLayerStacks();
calculateWorkingSet();
doComposition();
doDisplayComposition();
postFramebuffer();
HWComposer::presentAndGetReleaseFences();
HWC2::Display::present();
Composer::presentDisplay();

HWC模块

1
2
3
4
5
6
7
8
9
10
11
HWCSession::PresentDisplay();
HWCDisplayBuiltIn::Present();
HWCDisplayBuiltIn::CommitLayerStack();
HWCDisplay::CommitLayerStack();
DisplayBuiltIn::Commit();
DisplayBase::Commit();
HWPeripheralDRM::Commit();
HWDeviceDRM::Commit();
HWDeviceDRM::AtomicCommit();
DRMAtomicReq::Commit();
drmModeAtomicCommit();

DRM模块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
msm_atomic_commit();
msm_atomic_commit_dispatch();
kthread_queue_work(commit->commit_work);

_msm_drm_commit_work_cb();
complete_commit();
drm_atomic_helper_commit_planes();
sde_crtc_atomic_begin();
_sde_crtc_setup_mixers();
_sde_crtc_blend_setup();
_sde_crtc_blend_setup_mixer();
_sde_crtc_setup_blend_cfg(); // blend_op
_sde_crtc_dest_scaler_setup();
sde_plane_atomic_update();
sde_plane_sspp_atomic_update();
sde_crtc_atomic_flush();
sde_plane_flush();
msm_atomic_helper_commit_modeset_enables();
sde_crtc_enable();
sde_encoder_virt_enable();
sde_encoder_resource_control(SDE_ENC_RC_EVENT_KICKOFF);
_sde_encoder_virt_enable_helper();
hw_mdptop->ops.reset_ubwc();
hw_ctl->ops.setup_intf_cfg_v1();
_sde_encoder_update_vsync_source();
sde_encoder_phys_cmd_setup_vsync_source();
sde_hw_intf_vsync_sel();
sde_encoder_control_te();
sde_encoder_phys_cmd_connect_te();
sde_hw_intf_connect_external_te();
sde_kms_commit();
sde_crtc_commit_kickoff();
sde_encoder_prepare_for_kickoff();
drm_bridge_enable();
dsi_bridge_enable();
msm_atomic_wait_for_commit_done();
sde_kms_wait_for_commit_done();
sde_encoder_wait_for_event(MSM_ENC_COMMIT_DONE);
sde_crtc_complete_flip();
drm_crtc_send_vblank_event();

Fence同步机制

DummySwSyncTimeline CreateDummyFence()创建软件模拟fence

核心只有两件事情:

  1. sw_sync_fence_create 创建一个软件模拟的fence
  2. sw_sync_timeline_inc sync_timeline 时间轴向后推一个时间同步点

BufferSlot对应的BufferItem中的mFence对象就是Fence类,最后会在setUpHwcComposer中prepareFrame设置到Hal中

在Android Framework中有一个用于操作fence同步栅的类(libsync中sync_wait类)


Google平台帧率切换

参考:Android UI架构四、五
参考:Android UI架构十、十一

关键函数:

  • setFrameRate

  • getRefreshRate

  • app: 用于接收vsync信号并且上报给App进程,App开始画图 属性名:VSYNC_EVENT_PHASE_OFFSET_NS

  • sf: 用于SurfaceFlinger接收vsync信号用于渲染 属性名:SF_VSYNC_EVENT_PHASE_OFFSET_NS


磁盘空间占满100%

  1. 使用命令 sudo du -sh * 查看各个目录的占内存情况,使用du -h -x --max-depth=1查看哪个深度1的目录占用过高
  2. 如果发现/usr/local/tomcat的目录占用的磁盘空间特别大,则进入该目录,发现logs的目录特别大,Tomcat的日志太大,可以将其删除。比如本地电脑发现~/.cache/vmware目录下的drag_and_drop文件很大,这是因为虚拟机和主系统之间每次拖拉文件,都会生成一个复制文件,造成该文件越来越大,可以删除。
  3. 再使用df -h发现磁盘空间

Android设备分辨率、密度以及dp的理解

参考:Android设备分辨率、密度以及dp的理解
参考:UI设计师不可不知的安卓屏幕知识

  • dpi计算方法:
  1. 分辨率的平方和开方(勾股定理) adb shell wm size
  2. 然后除以屏幕的物理英寸,即是dpi

adb shell wm density可以查看当前的dpi(一般有的手机会在计算的结果上调整)

  • dp计算方法(开发者选项最小宽度dp)

1.在安卓中,系统密度为160dpi的中密度手机屏幕为基准屏幕,即320×480的手机屏幕。在这个屏幕中,1dp=1px
2.分辨率的宽高分别除以dpi,获取到sw320dp,h533dp

可通过adb shell dumpsys window查看到

低内存分析方向和技巧

参考:Android ANR基本Log分析

参考:Android 系统内存耗用:VSS/RSS/PSS/USS 的介绍

dumpsys meminfo:

1
2
3
4
5
6
7
8
9
Total RAM: 2,697,524K (status normal)
Free RAM: 1,063,563K ( 252,355K cached pss + 717,200K cached kernel + 0K cached ion + 94,008K free)
ION: 189,688K ( 7,624K mapped + 182,064K unmapped + 0K pools)
totalSwapPss: 775,324K kernelCached: 272,476K
Used RAM: 2,677,904K (2,090,100K used pss + 587,804K kernel)
Lost RAM: -23,995K
ZRAM: 200,100K physical used for 669,848K in swap (1,572,860K total swap)
Tuning: 128 (large 512), oom 322,560K, restore limit 107,520K (high-end-gfx)
--------- 14.816s was the duration of dumpsys meminfo, ending at: 2021-01-05 16:09:23

查看进程占用内存情况

adb shell procrank

1
2
3
4
  PID       Vss      Rss      Pss      Uss     Swap    PSwap    USwap    ZSwap  cmdline
1195 9776476K 509716K 228733K 166648K 3748K 405K 352K 78K system_server
5466 7005964K 351036K 139327K 123836K 3404K 53K 0K 10K com.android.systemui
.....
  • VSS: 一个进程总共可访问的地址空间。其大小还包括了可能不在RAM中的内存(比如虽然malloc分配了空间,但尚未写入)。 VSS 很少被用于判断一个进程的真实内存使用量
  • RSS: 一个进程在RAM中真实存储的总内存。仅仅表示该进程所使用的所有共享库的大小,而不管有多少个进程使用该共享库,该共享库仅被加载到内存一次。所以RSS并不能准确反映单进程的内存占用情况
  • PSS: 按比例表示使用的共享库。系统中所有进程的PSS都相加的话,就刚好反映了系统中的总共占用的内存。而当一个进程被销毁之后, 其占用的共享库那部分比例的PSS,将会再次按比例分配给余下使用该库的进程
  • USS: 进程所占用的私有内存(内存泄漏的最佳观察数据)。不包含so库占用内存的

ubuntu查看公网ip

三种方法:

  1. curl www.icanhazip.com
  2. curl ifconfig.me
  3. curl -4sSkL https://myip.ipip.net

查看视频解码的分辨率及对应的帧率支持

日志关键词MediaCodec

配置文件:/vendor/etc/media_codecs.xml


linux和windows书签同步

about:config网址搜索sync:

  • identity.sync.tokenserver.uri

修改:

  • linux:https://sync.firefox.com.cn/token/1.0/sync/1.5

  • windows:https://token.services.mozilla.com/1.0/sync/1.5


getService配置权限

首先getService获取服务,紧接着就是getTransport的接口调用。如果在配置文件里面没找到我们所要求的服务,就会报错并结束服务的获取

  • 首先会去system/etc/vintf/manifest.xml文件去找我们调用者的服务名,如果找到就返回。
  • 如果没找到就会去vendor/etc/vintf/manifest.xml文件去找,如果找到就返回。如果没找到则返回NULLPRT。同时打印Cannot find entry xxx in either framework or device manifest.

所以,如果碰到这样的log,首先要去检测这两个文件里面有没有配置我们调用的服务,没有就要自己配置。

一般是没有配置引起的,当然也有可能是xml增加的语法有问题,比如格式对齐等。


HIDL编写/升级流程

参考:VINTF
参考:VINTF简介
参考:供应商接口对象

总体流程:

  1. 创建HIDL接口文件XXX.hal:HIDL为每个HAL模块设计了不同接口定义hal文件,以.hal结尾,在hidl-gen工具的帮助下即可自动编译生成对应接口C++实现或者Java实现
  2. hidl-gen生成interface hash, 添加至current.txt
  3. hidl-gen生成接口,更新接口, XXX.bp, XXX.mk
  4. 更新vendor manifest文件:对于TA开发来说, 底层TA是服务提供者(需求提供者), 因此提供的是manifest(vendor), 将vintf/manifests.xmlpush到设备端:adb push manifest.xml /vendor/etc/vintf;system(framwork是发起需求者,需要设什么样的需求), 这部分内容在新平台上也在vintf/manifests.xml,push到设备端:adb push compatibity.device.xml /system/etc/vintf
  5. 更新fcm(matrix),即compatibility matrix XML编写:manifest文件描述了提供给对方的feature, Matrix描述了需要对方提供什么样的feature. Manifest和Matrix在OTA升级之前会进行匹配检查, 确保framework和device是兼容的, 总的来说,manifest是feature提供端, matrix是feature需求端
  • 关于compatibility Matrices:
    • framework compatibility matrix:描述了framwork对device的需求, 这个matrix文件是和system.img关联的, 这些需求需要被device manifest支持
    • device compatibility matrix:描述了device对framework的需求
1
2
3
4
5
6
7
8
9
10
11
12
//xml manifest语法
<manifest version="1.0" type="device"> //version: 必选, manifest的主版本号;type: 必选, manifest的类型,属于vendor,值为device; 属于system,值为framework
<hal format="hidl"> //hal:可选,可以存在多个,代表HAL(HIDL或者native); format:可选, 值为hidl(默认),或者native,分别代表HIDL和native HALS
<name>vendor.android.hardware.test</name> // name 必选, 代表HAL的合规包名
<transport>hwbinder</transport> // 和format有关,format的值是hidl时,就是必选的,否则不必存在.申明了当这个包的接口被service manager查询时将使用何种transport方式
// 可以是hwbinder,代表绑定式hidl, 也可以是passthrough: 代表直通式hide
<version>1.1</version> //必选, 代表当前hidl的版本号
<interface> // 必选的,可以多个但是不能重复,声明了一个含有实例的接口
<name>ITestService</name> //必选 接口实例的名字
<instance>default</instance> //必选,不可重复
</interface>
.....

结构层级:

1
2
3
4
5
6
7
8
9
10
manifest:version  type //这一层级申明当前manifest
|--hal format 第二层级
|--name
|--transtport
|--version
|-- interface
|-- name
|-- instance
|--sepolicy
|--version
  1. 启动服务:首先需要将生成的库文件和服务守护进程分别push到设备端, 其次, 使用lshal查看对应的服务是否启动,如果为启动,需要查看对应的rc文件是否存在, 若不存在,则push(vendor/etc/xxx.rc), 手动启服务
  • 概念:hidl接口哈希,是一种旨在防止意外更改接口,并确保接口更改经过全面审查的机制.因为HIDL接口带有版本号, 因此,接口一旦发布就bade在更改

  • 布局:每个软件包根目录,都必须包含一个列出所有已经发布的HIDL接口的current.txt文件

  • 使用hidl-gen添加哈希:hidl-gen生成的每个接口定义库都包含哈希,通过调用IBase::getHashChain可检索这些哈希。hidl-gen 编译接口时,会检查HAL软件包根目录中的current.txt 文件,以查看HAL是否已被更改

    • 如果没有找到HAL的哈希,则接口会被视为未发布(处于开发阶段),并且编译会继续进行
    • 如果找到了相应哈希,则会对照当前接口对其进行检查

如果接口与哈希匹配,则编译会继续进行

如果接口与哈希不匹配,则编译会暂停,因为这意味着之前发布的接口会被更改

如要进行保留ABI的更改(ABI稳定性),必须先修改current.txt文件,然后编译才能继续进行

所有其他更改都应在接口的minor或major版本升级中进行

Tips:

  • 查看HIDL编写的hal服务是否启动:adb shell lshal
  1. 重启

ssk-key生成current.txt hash值

1
2
3
4
$ hidl-gen -L hash -r vendor.....Testservice(service名称):/vendor/.../interfaces/Testservice(路径) -r android.hidl:system/libhidl/transport vendor...Testservice@1.0

e147fb59c6ffd19c8ea7345423e6b99d8d450e6078ff40367122a9c4ee005da5 vendor...Testservice@1.0::types
8f202376e0d66fa4c9448d71415993994de99150b7326e32ac5a04b4b94aec09 vendor....Testservice@1.0::ITestQservice

修改git remote -v的orign源

  1. git remote -v查看远程提交信息
  2. git remote rm origin删除
  3. 添加:git remote add origin (正确的信息)ssh://..../platform/frameworks/native
  4. git remote -v查看,如果push未修改成功没有关系
  5. 提交代码,记得加上-u选项:git push -u orign master

git报错无法push(不建议使用)

报错信息:

1
2
fatal: Unpack error, check server log
error: remote unpack failed: error Missing tree 7d3329b06421654faca962eab6cb6f9da6b47b9f

使用:git push --no-thin origin dev

git commit修改作者名称

git commit --amend --author="wizzie <wizzie@test.com>"

gerrit拉取Andorid指定模块代码

  1. repo init
  2. gerrit提交代码的界面projects里面搜索要拉取的指定模块
  3. 复制git clone然后本地执行
  4. git branch -a查看所有分支,然后git checkout 分支名(不包含orign/master)
  5. git pull

ubuntu命令查看dns

nm-tool

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
- Device: eth0  [Auto Ethernet] ------------------------------------------------
Type: Wired
Driver: e1000e
State: connected
Default: yes
HW Address: ...:5D

Capabilities:
Carrier Detect: yes
Speed: 1000 Mb/s

Wired Properties
Carrier: on

IPv4 Settings:
Address: ....241
Prefix: 24 (255.255.255.0)
Gateway: ....1

DNS: ....74
DNS: ....75
DNS: ....73

markdown数学公式语法

参考:Markdown数学公式语法

  • 行内公式:将公式插入到本行内,符号:$公式内容$,如:$xyz$

  • 独行公式:将公式插入到新的一行内,并且居中,符号:$$公式内容$$,如:$$xyz$$

  • 上标符号,符号:^,如:$x^4$

  • 下标符号,符号:_,如:$x_1$

  • 组合符号,符号:{},如:${16}{8}O{2+}{2}$

安装adb和fastboot

sudo apt-get install android-tools-adb

sudo apt-get install android-tools-fastboot

或者使用Android SDK/platform-tools

针对image编译

  1. 编译所有image
1
2
3
source build/envsetup.sh
lunch XX-userdebug
./build.sh dist -j4
  1. 编译system.img,生成在qssi目录下
1
2
3
source build/envsetup.sh
lunch xx-userdebug
./build.sh dist qssi_only -j4
  1. 编译super.img
1
2
3
source build/envsetup.sh
lunch xx-userdebug
./build.sh dist merge_only -j4
  1. 编译其它img,例如vendorimage(如果不指定会编译其它所有img)
1
2
3
source build/envsetup.sh
lunch xx-userdebug
./build.sh vendorimage dist target_only -j4

安装APK报错

如果安装APK报错,控制台输出如下:

1
2
3
$ adb install test.apk
5451 KB/s (635477 bytes in 0.113s)
Failure [INSTALL_FAILED_UPDATE_INCOMPATIBLE: Package com.debug.test signatures do not match previously installed version; ignoring!]

需要先删除原先的APK,并且清楚缓存,重启:

1
2
3
4
5
6
7
8
9
10
11
12
adb shell dumpsys activity top|grep ACTIVITY
adb shell pm path com.debug.test

//删除卸载原APK
adb shell rm -rf ***

//清楚缓存
adb shell pm clear com.debug.test
adb reboot

//再次安装新的APK
adb install test.apk

查看当前前台app包名(实时)

adb shell dumpsys window | grep mCurrentFocus

监控设备实时获取当前的包名

adb shell am monitor

APP增加多国语言

参考:让App支持不同的语言
参考:语言代码
参考:Android多语言支持以及各国语言Values文件夹命名规则

  1. 目录在:res/values-***
  2. 将各个语言区域的字符串值添加到相应文件中。在运行时,Android 系统会根据当前为用户设备设置的语言区域使用相应的字符串资源集的
  3. 如需添加对更多语言的支持,在res/目录下创建名称末尾不同的values,其中目录末尾ISO语言代码则对应着相应语言,譬如:values-fr则代表着手机系统语言为法语时读取的目录

例如:

  • 英语(默认语言区域),/values/strings.xml
  • 中文,/values-zh/strings.xml
  • 法语,values-fr/strings.xml

native crash分析

使用addr2line命令定位堆栈地址:

1
2
/out/target/product/product/symbols/system/lib64$ addr2line -f -e libgui.so 00000000000c39a0
_ZNK7android12SortedVectorINS_12DisplayStateEE16do_move_backwardEPvPKvm

解释:-e后加上.so的文件名;-f可同时输出函数名称

分析工具:

  • addr2line:addr2line –e obj/local/armeabi/libhello-jni.so 00004de8, 用来分析单个pc地址对应的源码行数
  • objdump:objdump –S obj/local/armeabi/libhello-jni.so > hello.asm,或者symbols/out/target/product/merlin/symbols$ objdump -tT system/lib64/libdisplayfeature.so 用来把相应的so变成汇编语言的asm文件,然后根据地址信息(比如00000000000c39a0)就可以找到更加详细的相关函数信息;
  • ndk-stack:用来把log信息全部翻译成更加详细的带源码行数信息的log,相当于是在整个crash堆栈信息都执行addr2line命令。

addr2line -Cef .so address

或者:

  1. 可以使用readelf -a [.so/.bin]解析库地址
  2. 根据解析结果查询函数,C++在linux系统编译后会变成类似_ZNK...的修饰名。使用c++filt获取函数的原始名称:

c++filt [_ZNK...函数修饰名]


YUV数据查看

  1. 从ffmpeg官网:http://ffmpeg.org/download.html下载最新的ffmpeg安装包,然后通过如下命令解压:
    tar jxf ffmpeg-2.5.3.tar.bz2
  2. 查看YUV:
    ffplay -f rawvideo -video_size 1280x800 raw_1280x800_1878.yuv

或者使用YUVPlayer工具,执行:

wine yuvplayer.exe

YUV Player工具获取:


关闭硬件加速

三种不同针对对象的方法:

  1. 在AndroidManifest.xml中设置android:hardwareAccelerated="false",注意关闭整个app的硬件加速,慎用
  2. View有个方法支持单独的View关闭硬件加速,可以设置mView.setLaterType(View.LAYER_TYPE_SOFTWARE);
  3. 关闭某一个控件的硬件加速功能:findViewById(R.id.btn).setLayerType(View.LAYER_TYPE_SOFTWARE,null);

linux绘图UML/序列图工具dia

  1. 安装:sudo apt-get install dia
  2. 使用,终端执行:dia

屏幕旋转/转向切换命令

1
2
3
4
5
6
7
adb root
#turn off the automatic rotation
adb shell settings put system accelerometer_rotation 0
# rotate landscape
adb shell settings put system user_rotation 1
# rotate portrait
adb shell settings put system user_rotation 0

Surface两种合成方式(dump sf)

  • Client合成:Client合成方式是相对于硬件合成来说的,其合成方式是,将各个Layer的内容用GPU渲染到暂存缓冲区中,最后将暂存缓冲区传送到显示硬件。这个暂存缓冲区,我们称为FBTarget,每个Display设备有各自的FBTarget。Client合成,之前称为GLES合成,我们也可以称之为GPU合成。Client合成,采用RenderEngine进行合成

  • Device合成:就是用专门的硬件合成器进行合成HWComposer,所以硬件合成的能力就取决于硬件的实现。其合成方式是将各个Layer的数据全部传给显示硬件,并告知它从不同的缓冲区读取屏幕不同部分的数据。HWComposer是Devicehec的抽象。


getprop查看当前版本是user/userdebug

adb shell getprop ro.system.build.type

getprop查看设备信息

adb shell getprop ro.build.product


滑动到边缘Pixel值调试

AOSP源码位置:/frameworks/base/core/java/com/android/internal/widget/PointerLocationView.java的onDraw函数中有ps.mCoords.xps.mCoords.y(float类型),可以将其打印出来,如果有问题可以修改此处转换逻辑


Input调试(PointerLocation)

systrace查看

systrace可以查看到touch点击的事件

点击input事件(up/down)

adb shell getevent -lrt

查看帮助:
adb shell getevent -h

1
2
3
4
5
6
7
8
9
10
11
12
[    1423.973137] /dev/input/event2: EV_ABS       ABS_MT_TRACKING_ID   0000003b            
[ 1423.973137] /dev/input/event2: EV_ABS ABS_MT_POSITION_X 0000017e //十六进制转成十进制 1*16*16+7*16+14*1=382 横坐标X
[ 1423.973137] /dev/input/event2: EV_ABS ABS_MT_POSITION_Y 0000032d //3*16*16+2*16+13*1=813 纵坐标Y
[ 1423.973137] /dev/input/event2: EV_ABS ABS_MT_TOUCH_MAJOR 0000000a
[ 1423.973137] /dev/input/event2: EV_ABS ABS_MT_PRESSURE 000003e8
[ 1423.973137] /dev/input/event2: EV_KEY BTN_TOUCH DOWN
[ 1423.973137] /dev/input/event2: EV_SYN SYN_REPORT 00000000
[ 1436.084174] /dev/input/event2: EV_ABS ABS_MT_TOUCH_MAJOR 00000000
[ 1436.084174] /dev/input/event2: EV_ABS ABS_MT_PRESSURE 00000000
[ 1436.084174] /dev/input/event2: EV_ABS ABS_MT_TRACKING_ID ffffffff
[ 1436.084174] /dev/input/event2: EV_KEY BTN_TOUCH UP
[ 1436.084174] /dev/input/event2: EV_SYN SYN_REPORT 00000000 rate 0

input和wms的debug log开关打开

1
2
3
4
5
6
7
8
9
10
11
adb root
//wns debug
adb shell dumpsys window -d enable DEBUG_FOCUS
adb shell dumpsys window -d enable DEBUG_INPUT
//或者
adb shell dumpsys window -d enable a
//input debug
adb shell setprop sys.inputlog.enabled true
adb shell setprop sys.input.TouchFilterEnable true
adb shell setprop sys.input.TouchFilterLogEnable true
adb shell dumpsys input

FPS帧率测试

查看设备的帧率:while true;do adb shell dumpsys SurfaceFlinger | grep "refresh-rate";done

获取实时帧率(主要用于获取游戏/视频应用的fps数据)

参考前面的文章:Android 两种实时获取FPS的方法

  1. 查询当前的layer(直接dump sf):adb shell dumpsys SurfaceFlinger --list
  2. adb shell dumpsys SurfaceFlinger --latency SurfaceView

dump gfxinfo信息

adb shell dumpsys gfxinfo <package_name>

查看每一帧的信息:adb shell dumpsys gfxinfo <package_name> framestats

结果:

  • Graphics info for pid 31148 [com.android.settings]: 表明当前dump的为设置界面的帧信息,pid为31148
  • Total frames rendered: 105 本次dump搜集了105帧的信息
  • Janky frames: 2 (1.90%) 105帧中有2帧的耗时超过了16ms,卡顿概率为1.9%
  • Number Missed Vsync: 0 垂直同步失败的帧
  • Number High input latency: 0 处理input时间超时的帧数
  • Number Slow UI thread: 2 因UI线程上的工作导致超时的帧数
  • Number Slow bitmap uploads: 0 因bitmap的加载耗时的帧数
  • Number Slow issue draw commands: 1 因绘制导致耗时的帧数
  • HISTOGRAM: 5ms=78 6ms=16 7ms=4 … 直方图数据

例如:while true;do adb shell dumpsys gfxinfo com.android.home framestat;sleep 1;done|tee swipeHome_dumpgfx.log

然后通过一秒抓一次,递减总帧数,确认每秒绘制的帧数:

  • 重置:adb shell dumpsys gfxinfo com.android.home reset

  • 抓取:adb shell dumpsys gfxinfo com.android.home framestats

查看帧率以及如何在systrace分析帧率

1
2
3
4
5
adb root
adb shell setprop debug.gr.calcfps 1
adb shell setprop debug.gr.calcfps.period 5
adb shell stop
adb shell start

之后可以在logcat中通过fps关键字查看帧率

Tips:

  1. 该帧率为实时帧率,一个动画的首帧和尾帧存在误差,可以忽略
  2. debug.gr.calcfps.period n:后面的数字n控制统计的帧数
  3. 重启手机后将不再统计帧率

systrace中的Frame

在每个app进程,都有一个Frames行,正常情况以绿色的圆点表示。当圆点颜色为黄色或者红色时,意味着这一帧超过16.6ms(即发现丢帧),点击黄色或红色的Frames圆点便会有相关的提示信息;

另外,在systrace的最右侧,有一个Alerts tab可以展开,这里记录着所有的的警告提示信息;

也可以通过放大那一帧进一步分析问题。

对于Android 5.0(API level 21)或者更高的设备,该问题主要聚焦在UI ThreadRender Thread这两个线程当中


屏幕录制视频(限定时间长)

  • adb shell screenrecord --time-limit 10 --verbose /sdcard/record.mp4

录屏带--bugreport调试参数:

adb shell screenrecord --bugreport /sdcard/test.mp4

截图命令

adb shell screencap /sdcard/screencap.png


dump sf查看buffer/layer列表

adb shell dumpsys SurfaceFlinger --list

dump windows/inpu/sf

1
2
3
4
adb root
adb shell dumpsys input
adb shell dumpsys window -a
adb shell dumpsys SurfaceFlinger

源码打开input debug日志开关

  • frameworks/native/services/inputflinger/InputDispatcher.cpp:bool gInputLogEnabled = false;改为true
  • frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java:static final boolean DEBUG_INPUT = false;

adb打印kernel log,即内核调试信息dmsg和kmsg

Android的log信息分为内核空间和用户空间中LOG,查看用户空间(也就是app等上层的log)的log直接用adb logcat就可以

如果想过滤一些信息就用adb logcat | grep -E "log_xxx|log_aaa”命令,这样log只会显示含有log_aaa和log_xxx的log信息了。上层的log信息另行查看。

  1. 执行dmesg命令,可以查看全部消息。如果想把log信息保存到文件,可以用adb shell dmesg > E:/Kernel.log (输出内核信息)

  2. adb shell cat /proc/kmsg:程序里面用printk函数打印的信息会显示出来。

cat /proc/kmsg命令打印出来的信息跟与dmesg不同。第一次执行/proc/kmsg打印到当前时间的所有内核信息,再次执行cat /proc/kmsg,不会再打印已经打印的信息,只打印上一次执行之后打印出来的新的信息。

Tips:查看kernel log时间,前面是秒,然后隔一段时间会打印android time标记日志

合并kmsg log

adb shell logcat -v time -f /dev/kmsg | adb shell cat /proc/kmsg | tee kernel_logcat.txt

  • “-f”选项 : 该选向后面跟着输入日志的文件, 使用adb logcat -f /sdcard/log.txt命令, 注意这个log文件是输出到手机上,需要指定合适的路径

例如触屏inpu事件log抓取:

adb shell logcat -v threadtime -f /dev/kmsg | adb shell cat /proc/kmsg | grep -Ei "InputDispatcher|DOWN\!|Up\!|ViewRootImpl|onTouchEvent"


查看设备的白名单

  • adb shell cat vendor/etc/power_whitelist_cfg.xml

代码添加示例:

1
2
3
4
5
6
7
8
//vendor/PLATFORM/proprietary/hardware/power/config/平台型号/power_whitelist_cfg.xml
<Package name="com.android.gallery">
<Activity name="Common">
<PERF_RES_SCHED_BOOST_VALUE_TA Param1="10"/>
<PERF_RES_THERMAL_POLICY Param1="8"/>
<PERF_RES_DRAM_CM_MGR Param1="1"/>
</Activity>
</Package>

Android.mk和Android.bp转换语法

相互转换的定义在:

/build/soong/androidmk/cmd/androidmk/android.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//该代码Android Q AOSP,在R之后该文件有变化
func init() {
addStandardProperties(bpparser.StringType,
map[string]string{
"LOCAL_MODULE": "name",
"LOCAL_CXX_STL": "stl",
"LOCAL_STRIP_MODULE": "strip",
"LOCAL_MULTILIB": "compile_multilib",
"LOCAL_ARM_MODE_HACK": "instruction_set",
"LOCAL_SDK_VERSION": "sdk_version",
"LOCAL_NDK_STL_VARIANT": "stl",
"LOCAL_JAR_MANIFEST": "manifest",
"LOCAL_JARJAR_RULES": "jarjar_rules",
"LOCAL_CERTIFICATE": "certificate",
"LOCAL_PACKAGE_NAME": "name",
"LOCAL_MODULE_RELATIVE_PATH": "relative_install_path",
"LOCAL_PROTOC_OPTIMIZE_TYPE": "proto.type",
"LOCAL_MODULE_OWNER": "owner",
"LOCAL_RENDERSCRIPT_TARGET_API": "renderscript.target_api",
"LOCAL_NOTICE_FILE": "notice",
"LOCAL_JAVA_LANGUAGE_VERSION": "java_version",
"LOCAL_INSTRUMENTATION_FOR": "instrumentation_for",
"LOCAL_MANIFEST_FILE": "manifest",

"LOCAL_DEX_PREOPT_PROFILE_CLASS_LISTING": "dex_preopt.profile",

将HIDL接口服务从设备system移到vendor

  1. 修改Android.bp中添加vendor:true(或者vendor_avaiable:ture);如果是Android.mk,则添加如下:
1
2
LOCAL_MODULE_PATH_64 = $(TARGET_OUT_VENDOR)/lib64
LOCAL_MODULE_PATH_32 = $(TARGET_OUT_VENDOR)/lib32
  1. 如果有.rc文件,则需要修改其中的目录;其中class hal是不会自动启动的,所以需要将其修改成class main ;并且onrestart restart后面添加的是service名称。

可以在adb shell;cd /vendor/bin/里面手动执行bin文件,然后查看进程是否启动。

  1. 在seploicy添加权限:device/PLATFORM/sepolicy/basic/non_plat/file_contexts

Android.bp(可参考)

VNDK 构建系统支持

系统将通过以下规则确定cc_library或cc_library_shared的默认安装路径:

将核心变体安装到/system/lib[64]中

供应商变体安装路径可能会有所不同:

  • 如果vndk.enabled为false,则将供应商变体将安装到/vendor/lib[64]

  • 如果vndk.enabled为true,则vndk.support_system_process可以是true或false。如果:

    • 为false,则供应商变体将安装到/system/lib[64]/vndk-${VER}
    • 为true,则供应商变体将安装到/system/lib[64]/vndk-sp-${VER}

C函数memset(…)

函数解释:将s中当前位置后面的n个字节(typedef unsigned int size_t )用ch替换并返回s

  • memset:作用是在一段内存块中填充某个给定的值,它是对较大的结构体或数组进行清零操作的一种最快方法
  • memset()函数原型:是extern void *memset(void *buffer, int c, int count),buffer为指针或是数组,c是赋给buffer的值,count是buffer的长度

domain.te错误类型

错误日志:The following types on /vendor/ must be associated with the "vendor_file_type" attribute: ×××_exec

  • 如果是system/则type ***_exec, exec_type, system_file_type, file_type;
  • 如果是svendor/则type ***_exec, exec_type, vendor_file_type, file_type;

查看手机硬件设备(包含屏幕信息)

  • adb shell cat proc/cmdline

ubuntu的ll命令不能使用

ll作为一个别名:

.bash_profile
1
2
...
+ alias ll='ls -alF''

然后执行source .bash_profile生效

ubuntu挂载硬盘

  1. 查看硬盘:sudo fdisk -l

比如打印:Disk /dev/sdb: 3000.6 GB, 3000592982016 bytes

  1. 编辑添加到文件:sudo vim /etc/fstab

比如打印:/dev/sdb /sunwg/ ext4 defaults 0 0 (后面的目录是挂载的目录)

  1. 重启电脑,然后df -h查看系统分区

find命令

find ./ -iname "*gpuinfo*"


## 查看CPU/GPU硬件频率

  • 查看CPU: adb shell "cat /proc/cpufreq/*/cpufreq_freq"
  • 查看DDR: adb shell "cat /sys/devices/platform/10012000.dvfsrc/helio-dvfsrc/dvfsrc_dump | grep -e uv -e khz -e CONTROL -e VCORE_OPP -e DDR_OPP -e LEVEL -e RSV_9"
  • 查看GPU频率: adb shell cat /proc/gpufreq/gpufreq_var_dump或者adb shell cat /proc/gpufreq/gpufreq_opp_dump

设置GPU频率

1
2
adb root;
adb shell "echo 1000000 > /proc/gpufreq/gpufreq_opp_freq"

☆CPU/GPU信息文件路径

CPU信息是在:/sys/devices/system/cpu
GPU的信息在如下目录查看:/sys/class/kgsl/kgsl-3d0


加大dequeuebuffer数目

有时候从systrace中看到dequeuebuffer耗时长,如果可能和gpu/cpu相关,则可以参照上面的方式对gpu/cpu进行提频;

也可以尝试修改文件:/frameworks/native/services/surfaceflinger/BufferQueueLayer.cpp

mProducer->setMaxDequeuedBufferCount(1); //增加这里值

比如修改为3,看是否有改善


windows cmd过滤log

adb logcat |find "***"

vscode插件

gitlens:可以查看提交


抓取perfetto-trace(替代systrace)

  1. 打开开发者选项->系统跟踪->显示‘快捷设置’图块
    或者命令方式打开:adb shell am start com.android.traceur/com.android.traceur.MainActivity
  2. 然后点击“录制跟踪记录”开始抓取
  3. 点击停止后分享生成文件,或者命令导出:adb pull data/local/traces
  4. 使用chrome登录perfetto-trace网站:https://ui.perfetto.dev/#!/

或者转换成html格式:

1
2
3
4
5
6
// 仅支持python 2.7 且需要GLIBC_2.28版本
curl https://get.perfetto.dev/traceconv -o traceconv

chmod +x traceconv

./traceconv [text|json|systrace|profile] [input proto file] [output file]

systrace打开空白或者打不开

在chrome地址栏中输入”chrome:tracing”,然后点击load按钮load你的trace.html文件

atrace转换到html

./systrace.py --from-file 2-1.atrace

结果文件生成2-1.html

systrace的类别和选项(直接添加)

systrace脚本来源:Android\Sdk\platform-tools\systrace

示例命令:./systrace.py -b 8000 -t 5 –list-categories="Screen turning on" hal app sched gfx view wm power binder_driver -o systrace.html

options 描述
-o < FILE > 输出的目标文件
-t N, –time=N 执行时间,默认5s
-b N, –buf-size=N buffer大小(单位kB),用于限制trace总大小,默认无上限
-k < KFUNCS >,–ktrace=< KFUNCS > 追踪kernel函数,用逗号分隔
-a < APP_NAME >,–app=< APP_NAME > 追踪应用包名,用逗号分隔
–from-file=< FROM_FILE > 从文件中创建互动的systrace
-e < DEVICE_SERIAL >,–serial=< DEVICE_SERIAL > 指定设备
-l, –list-categories 列举可用的tags
category 描述
gfx Graphics
input Input
view View System
webview WebView
wm Window Manager
am Activity Manager
sm Sync Manager
audio Audio
video Video
camera Camera
hal Hardware Modules
app Application
res Resource Loading
dalvik Dalvik VM
rs RenderScript
bionic Bionic C Library
power Power Management
sched CPU Scheduling
irq IRQ Events
freq CPU Frequency
idle CPU Idle
disk Disk I/O
mmc eMMC commands
load CPU Load
sync Synchronization
workq Kernel Workqueueszuidi

几个比较常用的模块:

  • sched:CPU调度的信息,非常重要;你能看到CPU在每个时间段在运行什么线程;线程调度情况,比如锁信息
  • gfx:Graphic系统的相关信息,包括SurfaceFlinger,VSYNC消息,Texture,RenderThread等;分析卡顿非常依赖这个
  • view:View绘制系统的相关信息,比如onMeasure,onLayout等;对分析卡顿比较有帮助
  • am:ActivityManager调用的相关信息;用来分析Activity的启动过程比较有效
  • dalvik: 虚拟机相关信息,比如GC停顿等
  • binder_driver:Binder驱动的相关信息,如果你怀疑是Binder IPC的问题,不妨打开这个
  • core_services:SystemServer中系统核心Service的相关信息,分析特定问题用

SElinux权限相关

参考网站程序员大本营selinux

  • scontext表示进程的SContext,u:r:bluetooth:s0,属于bluetooth域;
  • tcontext表示目标的SContext,u:r:system_data_file:s0,属于system_data_file类型;
  • tclass表示进程要操作的ObjectClass,dir表示目录;

自动生成selinux权限代码

  1. 过滤avc关键词代码,导入到新文件log.txt

  2. 需要安装:policycoreutils

  3. 执行命令或区域权限的代码:
    cat log.txt | grep avc | audit2al

  4. 命令执行后生成权限相关代码,然后进行修改,例如下面:

1
2
3
4
5
#============= mcd ==============
allow mcd sysfs_battery_supply:dir search;
allow mcd sysfs_battery_supply:file { read open };
allow mcd sysfs_batteryinfo:dir search;
...

开启/关闭Selinux权限

1
2
adb shell setenforce 0 //设置成permissive模式,临时关闭selinux
adb shell setenforce 1 //设置成enforce模式

重启后失效

使用adb shell getenforce查看当前权限状态。

可能返回结果有三种:

  • Disabled代表SELinux被禁用
  • Permissive代表仅记录安全警告但不阻止可疑行
  • Enforcing代表记录警告且阻止可疑行为

进入fastboot

adb reboot fastboot

或者

adb reboot bootloader


LCD屏幕低温残影现象

LCD屏幕里的像素发光是由液晶偏转来控制的,而液晶这种材料对温度十分敏感,温度越低,液晶翻转的速度也就越慢,屏幕的响应速度也就会越慢。当画面已经刷新到了下一帧时,液晶还未翻转完成,新生成的画面与未消失的画面错位存在,看上去就像重影一样。

而OLED屏幕的像素点是由一个个单独控制的发光二级管所组成的,低温对其响应速度影响不大,所以单独发光的OLED的响应速度要远高于LCD屏幕。所以OLED屏幕的手机在低温下几乎不会出现拖影的问题。

此外,录屏是录取不到拖影的现象,需要拍视频才能看的到。


makefile

makefile中-D*表示:#define *

如:-DPOSGP730 等价于 #define POSGP730


亮度单位nit

nit(尼特),1nit=1坎德拉/平方米[cd/m2]

亮度(L)指物体明暗的程度,定义是单位面积的发光强度,是表示眼睛从某一方向所看到物体反射光的强度。

光学单位lux

0.1Lux是指摄像机的照度

Lux是一个光学单位,指的是每平方米的光照亮,可以理解成对光线强度的反应,在同等光线条件下,LUX越小的摄像机感光度越好。

场所/环境 光照度
晴天 30000~300000 lux
晴天室内 100~1000 lux
阴天 3000~10000 lux
阴暗夜晚 0.003~0.0007 lux
夜间路灯 0.1 lux

启动activity/关闭activity

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//使用Action方式打开系统设置-输入法设置
adb shell am start -a android.settings.INPUT_METHOD_SETTINGS

//使用组件名方式启动照相机功能
adb shell am start -n com.android.camera/.Camera

//打开拨号界面,并传递一个DATA_URI数据给拨号界面
am start -a android.intent.action.CALL -d tel:10086

//使用ComponentName方式启动一个Service
adb shell am startservice com.some.package.name/.YourServiceSubClassName

//关闭指定包名的应用程序
adb shell am force-stop com.some.package

//杀死进程
adb shell am kill com.some.package

Git命令

查看代码提交历史(具体到某一行)

git blame SurfaceFlinger.cpp(文件名)

提交代码

git push origin HEAD:refs/for/×××Branch

提交草稿代码

git push origin HEAD:refs/drafts/×××Branch

提交代码、sync代码报错Agent admitted failure to sign using the key

执行:ssh-add ~/.ssh/id_rsa


apt-get报错不能进行正常更新

提示错误信息The package lists or status file could not be parsed or opened

解决方法:

1
2
sudo rm -vf /var/lib/apt/lists/*
sudo apt-get update

ubuntu自带截图快捷键

1
2
3
4
5
6
7
8
9
Alt + Print Screen #截取选中的窗口

Shift + Print Screen #自由选区

Ctrl + Print Screen #整个桌面

Ctrl + Alt + Print Screen #选中的窗口

Shift + Ctrl + Print Screen #自由选区

gedit乱码

执行:gconftool-2 --set --type=list --list-type=string /apps/gedit-2/preferences/encodings/auto_detected "[UTF-8,CURRENT,GB18030,BIG5-HKSCS,UTF-16]"

跳过开机向导

1
2
adb shell settings put secure user_setup_complete 1
adb shell settings put global device_provisioned 1

ubuntu快速下载命令

axel -n 20 下载链接


谷歌GMS服务

GMS(Google Mobile Service),即谷歌移动服务,是Google提供的移动设备上的一系列应用服务,比如包含Play Sotre,Gmail,YouTube,Chrome,Google Maps等。
如果需要预置GMS应用,需要通过Google认证,比如CTS、GTS等跑测。

GMS测试注意事项

  1. 如果升级应用到最新版本不再复现,则是应用本身的问题,Google在升级过程中已进行修补
  2. 如果仍旧复现,则使用对比机器进行对比验证

常见问题

开机向导设置密码后关机再开机黑屏

修改方式:

  1. 找到frameworks/base/packages/SystemUI/src/com/android/systemui/Keyguard/KeyguardViewMediator.java
  2. 找到函数private void doKeyguardLocked(Bundle options)
  3. 修改if (!lockedOrMissing && !provisioned && !antiTheftLocked) —> if(!lockedOrMissing && shouldWaitForProvisioning() && !antiTheftLocked)

Play Store无法正常连接

无法登陆Google账户,提示与Google服务器通信时出现问题

如果可以登录Google账户(设置添加Google账户),而不能进入Google Play,可以抓取一份log,搜索关键字CheckinTask,如果出现如下log:

E CheckinTask: Checkin failed: https://android.clients.google.com/checkin (request #0): java.io.IOException: Bad Content-Type: text/html; charset=UTF-8

就先检查系统以下属性值的设定是否存在“非法”字符:

1
2
3
4
ro.product.model
ro.product.name
ro.product.device
ro.product.board

Play Store下载应用失败

从服务器检索信息时出错 (Error retrieving information from server)

可以参考:Google Play商店的各种报错解释以及修复方法

GMS应用首次登陆闪退,第二次正常

闪退问题先Check log中是否收到PACKAGE_CHANGED的广播

查看system log,Google Maps如果有发生package changed,这是厂商的Maps版本比较旧,开机后联网情况下会自动从server升级造成process kill,属于正常的行为。关键log如下:

1
2
3
V ActivityManager: Broadcast: Intent { act=android.intent.action.PACKAGE_CHANGED dat=package:com.google.android.apps.maps flg=0x4000010 (has extras) } ordered=false userid=0 callerApp=null
I ActivityManager: Force stopping com.google.android.apps.maps appid=10060 user=0: pkg changed
I ActivityManager: Killing 6004:com.google.android.apps.maps/u0a60 (adj 0): stop com.google.android.apps.maps

GMS应用缺少部分菜单

如果系统分区太小,会拿掉一些feature,你可以尝试更大的RAM size,比如1GB或更大。

GMS部分应用联网后消失

GMS中部分应用有地域使用限制,Play Books, Play Magazine, Play Movies等应用目前不支持在中国大陆这边使用,所以联网后应用会自己屏蔽掉,此为正常现象。

本文作者 : sunwengang
本文使用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 协议
本文链接 : https://alonealive.github.io/Blog/2021/06/07/2021/210607_android_debug3/

本文最后更新于 天前,文中所描述的信息可能已发生改变