好久没更新博客,最近debug了一个比较有趣的bug,有时间闲下来,整理一下还是挺不错的。

先来看看这个bug是什么情况:

以上两张图片是android的动态logo,也就是BootAnimation logo。上面显示出来的是同一张logo,左边是正常的,但在显示了一半的时候,就成了右边的样子。

正常的情况下,无论哪个版本的android,启动的时候,logo都是好好的,但是为什么会出现上面的情况呢?那是因为在系统里面做了一个旋屏的功能。旋屏功能是怎样完成的?看看下面的思路:

也就是在添加了这个旋转的功能,而且把屏幕设置成旋转90度显示的时候出现的。

其中,在上图的第二步里面,android原生就有“ro.sf.hwrotation”这个属性来设置开机后屏幕的方向。但这个属性是“ro”的,所以这里,摒弃了这个属性,而是重新申请一个“persist”类的属性来完成此功能,这里把这个属性命名为:persist.sys.hwrotation。

下面正式来分析问题,既然是在动态logo的显示阶段图片显示异常,那么,先来看看android的“BootAnimation”服务。

看到了“readyToRun”的部分代码:

status_t BootAnimation::readyToRun() {mAssets.addDefaultAssets();sp<IBinder> dtoken(SurfaceComposerClient::getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain));DisplayInfo dinfo;status_t status = SurfaceComposerClient::getDisplayInfo(dtoken, &dinfo);if (status)return -1;// create the native surfacesp<SurfaceControl> control = session()->createSurface(String8("BootAnimation"),dinfo.w, dinfo.h, PIXEL_FORMAT_RGB_565)

很明显,这里直接决定了屏幕显示的尺寸:首先是通过“getDisplayInfo”获取屏幕分辨率(我这里设置的是1920x1080),然后创建一个“Surface”。

猜想:因为是将屏幕设置了“90”度旋转后出现的问题。而且看第一张图片,显示的情况明显是“0”度的显示,也就是没经过“90”度的选择。会不会“BootAnimation”在开始显示的时候,获取到的是“0”度的屏幕参数(也就是分辨率是1920x1080),到后面显示到一半的时候,“Surfaceflinger”检测到了“persist.sys.hwrotation”属性的值为90,然后强制性的把显示分辨率改为“1080x1920”?所有才导致了logo显示异常??

要证明这个设想,很简单,添加打印信息。

首先,在“BootAnimation”的“getDisplayInfo”后面打印出获取到的分辨率:

#logcat | grep BootAnimation
D/BootAnimation(2526): BootAnimation getDisplayInfo get dinfo.w=1920 dinfo.h=1080 !!!

看到,果然跟猜想的一样,“BootAnimation”获取到屏幕参数是“0”度的。然而“BootAnimation”获取屏幕参数是通过“getDisplayInfo”方法来获取的,也就是“Surfaceflinger”的API。看到“getDisplayInfo”方法里面判断屏幕参数的代码:

以下代码是添加进去的,所以贴出的是patch的部分代码:

+    int displayOrientation = DisplayState::eOrientationDefault;
+    char property[PROPERTY_VALUE_MAX];
+    if (type == DisplayDevice::DISPLAY_PRIMARY) {
+        if (property_get("persist.sys.hwrotation ", property, NULL) > 0) {
+            switch (atoi(property)) {
+                case 90:
+                    displayOrientation = DisplayState::eOrientation90;
+                    break;
+                case 180:
+                    displayOrientation = DisplayState::eOrientation180;
+                    break;
+                case 270:
+                    displayOrientation = DisplayState::eOrientation270;
+                    break;
+            }
+        }

好,这里是判断屏幕参数的唯一依据,如果屏幕参数变了,那么肯定要经过这里。也就是说,就是通过判断“persist.sys.hwrotation”,除非是“persist.sys.hwrotation”的值过程中有变化。

“persist.sys.hwrotation”真的有变化?如果“persist.sys.hwrotation”有变化,从上面的分析看来,也只能从“0”变为“90”。

判断的依据也很简单,打印一下就知道了。

因为在android启动的过程中,console服务起来,就可以进入用串口进入“command”行进行debug。所以,这里打印“persist.sys.hwrotation”,是在显示动态logo出现问题前后打印出来:

出问题前:

# getprop | grep persist.rw.hwrotation[persist.rw.hwrotation]: [0]

出问题后:

# getprop | grep persist.rw.hwrotation[persist.rw.hwrotation]: [90]

果然,通过获取“persist.sys.hwrotation”属性的值,我们恰恰看到了“persist.sys.hwrotation”是会从“0”变为“90”。奇了个怪,怎么会从“0”变为“90”呢??“persist”类的属性,应该是被设置了之后就会被保存起来才对。难道android property在启动的过程中会对“persist”类属性做什么特殊的处理??

好,看看property service,没看出有异样的地方。于是进入了焦灼状态,一时难以解释。

既然是这样,那就按照上面的方法,把android所有的属性都打印出来,做个对比。看其他属性会不会像“persist.sys.hwrotation”一样。其中,有一个属性“persist.sys.first_run”,是我在系统里面申请的另外一个“persist”类属性,是用来标识系统状态的。但也没见像“persist.sys.first_run”一样,启动过程中属性值会被改变。

在对比属性的过程中,也发现了一些挺有意思的属性,是系统用来做标识的:

[debug.force_rtl]: [0]
[dev.bootcomplete]: [1]
[init.svc.bootanim]: [stopped]
[init.svc.dhcpcd_eth0]: [running]
[ro.runtime.firstboot]: [1475205237873]
[service.bootanim.exit]: [1]
[sys.boot_completed]: [1]
[sys.interactive]: [active]
[sys.sysctl.extra_free_kbytes]: [24300]

如上面的“sys.boot_completed”,android系统启动完成之后,会发出广播,然后把“sys.boot_completed”置1。

回到问题中来,到底“persist.sys.hwrotation”为何会被改变??这个属性是我申请的,在android里面,除了“property service”之外,应该没有什么地方能改变到它。然后想到,我在android里面还启动了一个setrotation_prop服务,见上面蓝色的流程图。服务里面会去检查文件里面保存的屏幕旋转方向的值,然后去设置“persist.sys.hwrotation”属性对应的值。证明方法也很简单,把前后的结果打印出来就知道了。

果然,就是这个服务,在启动的过程中把“persist.sys.hwrotation”的值改变了。但话又说回来,这个“setrotation_prop”是通过判断“/sdcard/rotaion”文件来设置“persist.sys.hwrotation”。在查看一下,在init.rc里面:

symlink /storage/emulated/legacy /sdcard

/sdcard目录是被link 到了“/storage/emulated/legacy”,详细情况,可以查看以下链接:

# See storageconfig details at http://source.android.com/tech/storage/

那么,在android启动的过程中,当“setrotation_prop”检查不到“/sdcard/rotaion”文件的时候,“setrotation_prop”就会使用默认的值“0”;当“/sdcard/rotaion”文件被加载上了,“setrotation_prop”检查到“/sdcard/rotaion”里面保存的“90”的时候,又从新把“persist.sys.hwrotation”设置为“90”,所以就导致了“getDisplayInfo”前后获取的屏幕参数不一样,从而导致了显示图片错位。

既然定位到问题了,那么就要修复。之前代码里还做了一个功能,就是在setting里面添加多一个菜单选项,来设置屏幕旋转:

这样看来,这个处理逻辑有点分散,而且“setrotation_prop”服务的方式可靠性不好。所以,直接在setting选项菜单里面,代码添加一句:

SystemProperties.set(“persist.sys.hwrotation”,”90”);

然后摈弃“/sdcard/rotaion”和“setrotation_prop”,逻辑就成了:

问题解决。

android debug set screen rotation相关推荐

  1. Android Debug Bridge(adb)

    Adb google官方文档翻译,源文档地址如下 https://developer.android.google.cn/studio/command-line/adb Android Debug B ...

  2. android debug database 源码解析

    我们今天分析下android debug database 的源码: 项目地址: https://github.com/amitshekhariitbhu/Android-Debug-Database ...

  3. iOS5.1 + XCode4.5 device debug,the screen will ...

    2019独角兽企业重金招聘Python工程师标准>>> If you use XCode 4.5 + Device with iOS 5.1 to debug,the screen ...

  4. Android开发工具——ADB(Android Debug Bridge) 一概览

    Android Debug Bridge (adb) 是一个android开发人员必会的多功能的调试工具,确实它的名字一样,它在开发者和目标机器之间,架起了一座bridge. adb的用法很简单,只要 ...

  5. [ADB]ADB(Android Debug Bridge)简介及基础(不包含命令)

    "Android Debug Bridge (adb) is a versatile command line tool that lets you communicate with an ...

  6. 使用浏览器查看Android SQLite数据库-Android Debug Database用法

    本文转载自[http://blog.csdn.net/o279642707/article/details/68946230] 前言 Android客户端查看sqlite数据库是很繁琐的事情,需要DD ...

  7. Android SQLite开发调试工具 Android Debug Database

    Android Debug Database允许以一种非常简单的方式直接在浏览器中查看数据库 功能定义: See all the databases. See all the data in the ...

  8. 在WinCE中实现Screen Rotation(屏幕旋转)

    在WinCE中做Screen Rotation,首先确认显示设备的驱动是否支持Screen Rotation功能.在显示设备支持的前提下,可以通过以下两种方法做Screen Rotation: 1.通 ...

  9. adb(Android debug bridge)命令

    From:https://www.cnblogs.com/huanyou/p/5133737.html ADB 用法大全: github 地址:https://github.com/mzlogin/a ...

最新文章

  1. 初一下计算机课教案,川教版信息技术七下第1课《计算机资源管理》word教案1
  2. vim的配置管理和部署
  3. 2.6 多分类问题-机器学习笔记-斯坦福吴恩达教授
  4. 8.分布式数据库HBase第4部分
  5. 如何设计一个牛逼的API接口
  6. Easyexcel文件下载时,中文名称显示为下划线
  7. Android\OPhone动画分析之翻转效果
  8. illegal multibyte sequence python3
  9. 重磅!国内公司欧卡智舶发布全球首个「城市内河无人船」数据集
  10. linux 磁盘分区对齐,linux查看硬盘4K对齐方法
  11. [译] 如何在安卓应用中使用 TensorFlow Mobile
  12. 关于遥感图像的控制点片匹配算法的一点想法(一)
  13. cl.g4r.win index.php,win7 wamp环境配置Oracle数据库连接
  14. 快收下这枚 Scrapy Requests 口味的爬虫“回魂丹”
  15. Win32API大全
  16. KUKA youbot机械臂与Moveit工具包(2)
  17. 让PPT变高级的方法,PPT小白们快来学
  18. 「释放自我」后,敢说真话的人干趴了会写PPT的人!
  19. buctoj-2022寒假集训4
  20. 音视频开发系列--H264编解码总结

热门文章

  1. jmeter脚本录制入门详解
  2. 一篇文章搞懂 HDFS 的配额管理
  3. 【Yolo】Jetson Orin Nano下部署 YoloV5
  4. loadrunner--浏览器不支持或禁止了网页脚本,导致您无法正常登录
  5. 俞敏洪一分钟励志演讲:
  6. Qt边框border概述
  7. 1.无线通信:传播和衰落
  8. 【HTML】语义化标签
  9. 吴军亲述编程生涯:不用低效率的算法做事情
  10. flashback的配置