分享一个android手机开不了机的问题

前段时间开发了一个小屏的功能(效果图如下:),果了一段时间,测试的人员说我们的手机有时开机不了:一直停止在开机的界面.刚开始都不知道什么原因.查了各种代码都没有发现问题.到后来感觉问题越来越严重了.

到后来感觉问题越来越严重了.重要的是这个时低概率事件,很难复现一次,所以有点难.好不容易出现,通过data/anr/traces.txt找到问题,下面来看看关键信息:

"WindowManag4 MONITOR
  | group="main" sCount=1 dsCount=0 obj=0x4275d4d8 self=0x57929cb0
  | sysTid=732 nice=-4 sched=0/0 cgrp=apps handle=1469227632
  | schedstat=( 1563495873 1380427864 20236 )
  - waiting to lock <0x427e72d8> (a Ljava/lang/Object; ) held by tid=1 (main)
| [0]:<0006> Landroid/hardware/display/DisplayManagerGlobal;.getDisplayInfo(I)Landroid/view/DisplayInfo; (<span style="color:#FF0000;">DisplayManagerGlobal.java:108</span>)
| [1]:<0008> Landroid/view/Display;.updateDisplayInfoLocked()V (Display.java:657)
| [2]:<0002> Landroid/view/Display;.getMetrics(Landroid/util/DisplayMetrics;)V (Display.java:585)
| [3]:<0104> Lcom/android/server/display/xunhuOverlayDisplayAdapter;.<init>(Lcom/android/server/display/DisplayManagerService$SyncRoot;Lan (<span style="color:#FF0000;">xunhuOverlayDisplayAdapter.java:104</span>)
| [4]:<0030> Lcom/android/server/display/DisplayManagerService;.register_xunhuOverlayDisplayAdapterLocked()V (DisplayManagerService.java:994)
"main" prio=5 tid=1 MONITOR
  | group="main" sCount=1 dsCount=0 obj=0x422c6cf8 self=0x4182e500
  | sysTid=715 nice=-2 sched=0/0 cgrp=apps handle=1074631044
  | schedstat=( 7254851604 2756007452 25767 )
  - waiting to lock <0x4277acc8> (a Lcom/android/server/display/DisplayManagerService$SyncRoot; ) held by tid=14 (WindowManager)
| [0]:<0020> Lcom/android/server/display/DisplayManagerService;.getDisplayInfo(I)Landroid/view/DisplayInfo; (<span style="color:#FF0000;">DisplayManagerService.java:449</span>)
| [1]:<0012> Landroid/hardware/display/DisplayManagerGlobal;.getDisplayInfo(I)Landroid/view/DisplayInfo; (<span style="color:#FF0000;">DisplayManagerGlobal.java:117</span>)
| [2]:<0000> Landroid/hardware/display/DisplayManagerGlobal;.getCompatibleDisplay(ILandroid/view/DisplayAdjustments;)Landroid/view/Display; (DisplayManagerGlobal.java:176)

上面两段信息的关键是:waiting to lock 看来貌似是进入一个死锁.两个锁等待都在这个文件出现:DisplayManagerGlobal.java,所以看看DisplayManagerGlobal就会发现问题:

    public DisplayInfo getDisplayInfo(int displayId) {
        try {
            synchronized (mLock) {<span style="color:#FF0000;">//108</span>
                DisplayInfo info;
                if (USE_CACHE) {
                    info = mDisplayInfoCache.get(displayId);
                    if (info != null) {
                        return info;
                    }
                }
                info = mDm.getDisplayInfo(displayId);<span style="color:#FF0000;">//117</span>
                if (info == null) {
                    return null;
                }

首先是这里mLock锁竞争.在这个锁里调用mDm.getDisplayInfo(displayId)的时候会回调到DisplayManagerService里面,如下代码:

    public DisplayInfo getDisplayInfo(int displayId) {
        final int callingUid = Binder.getCallingUid();
        final long token = Binder.clearCallingIdentity();
        try {
            synchronized (mSyncRoot) {<span style="color:#FF0000;">//449</span>
                /// M:[SmartBook]Ignore extra display devicee info
                if (FeatureOption.MTK_SMARTBOOK_SUPPORT) {
                    if (displayId == mExtraDisplayId) {
                        return null;
                    }
                }

很显然,在获取了 DisplayManagerGlobal里面的锁:mLock,还需要DisplayManagerService里面的锁mSyncRoot.

而我开发的小屏功能在DisplayManagerService里面register小屏的DisplayAdapter的时候已经获取了mSyncRoot锁,所以如果在这同时(register小屏的DisplayAdapter的时候)调用下面的代码:

        WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
        wm.getDefaultDisplay().getMetrics(metric);

就容易出现死锁. 因为在调用getDefaultDisplay()的时候最后会调用DisplayManagerGlobal的getDisplayInfo这个方法.而在开机的时候有大量其他地方调用DisplayManagerGlobal的getDisplayInfo这个方法.

时间: 2024-10-10 06:32:35

分享一个android手机开不了机的问题的相关文章

老李分享:android手机测试之适配(1)

老李分享:android手机测试之适配(1) Android的屏幕适配一直以来都在折磨着我们这些开发者,本篇文章以Google的官方文档为基础,全面而深入的讲解了Android屏幕适配的原因.重要概念.解决方案及最佳实践,我相信如果你能认真的学习本文,对于Android的屏幕适配,你将有所收获! Android屏幕适配出现的原因 重要概念 屏幕尺寸 屏幕分辨率 屏幕像素密度 dpdipdpisppx mdpihdpixdpixxdpi 解决方案 支持各种屏幕尺寸 使用wrap_contentma

分享一个Android版 仿QQ局域网即时通信软件(可发文件、语音、录音)

一.支持的功能有文字信息交互.语音聊天.发送文件和录音 源码会在后面附上. 二.UI展示图 三.经过我的测试,是非常成功的.只是有一点不足就是语音实时通话的时候声音会回声甚至死机. 文件传送和文字,录音都比较成功. 四.本软件是用Java编码,在安卓平台上的应用.使用了UDP协议和TCP协议. 大家可以学习这两部分的代码. 里面注释还是比较多. 五.当然我只是个学生,这个只是学生版本,仅供大家学习借鉴之用.绝对不能用于商业拿去直接卖,或者改改就上架某市场. 六.宣传下本人的小制作: 单机斗地主-

分享一个Android和java调用RESTful Web服务的利器Resting

分享一个Android和java调用RESTful Web服务的利器Resting 当我们调用Web服务,往往是最终目标是取HTTP响应,将其转化为将在应用中呈现的值对象.Resting可以用来实现这一功能.Resting,在Java的一个轻量级的REST框架,可用于调用一个RESTful Web服务,并转换成响应来自客户端应用程序定制的Java对象.由于它的简单,resting是适合Android等手持设备. resting目标?暴露简单的get(),post(),put()和delete()

手机串号imei防封秘诀,分享一个安卓手机串号模拟修改器

很多应用app或者游戏账号是绑定手机串号imei或者mac,有时候手机被朋友恶搞了一下,导致账号被封了,无法重现注册账号,这可怎么办?今天分享一个小秘诀,可以实现这种情况下再次注册账号. 首先我们在手机上下载安装一个琢石模拟器,琢石模拟器的功能是能让手机模拟新的imei和mac.型号等等手机参数,也就是说即使我们原来的串号不好使了,我们可以通过琢石模拟器模拟一套新的参数,这样就能重现注册账号了.是不是很方便,而且使用琢石模拟器我们还能保护手机真实的信息,同时还能起到安全的保护作用,一举两得,一箭

一个Android开发者开博一周年的成长日记——送给不知如何下手的【初级开发者】和【在校生】

今天一看日历,哟,2.12号,这不是我第一份工作入职的时间吗?不知不觉竟然已经工作了一年了,那根据“主席”的话说,应该算是中级开发者水平了!在这工作的一年里,我有过迷茫,有过动摇,但更多,则是坚持和努力,无论如何,我终于算是摸到了开发者的这一条道路的大门,剩下的就是更加坚定的走下去.平常和大家分享的都是技术文章,今天趁着公司没活,给还没找到入手点的初级开发者和在校生写点东西,算是一点经验之谈,给你们一点前进的方向. 其实我接触Android开发应该是很早的时候了,2012年就因为“齐鲁软件大赛”

android手机客户端与pc机进行socket通信

这两天做了一个手机和电脑通信利用socket进行网络通信的小程序,上图先: 在写程序的过程中发现了很多问题... 一.电脑和手机的IP必须在同一个网段,也就是IP的前三段必须是一样的. 刚开始电脑和手机都连着老师办公室的 无线,可是却连不上..折腾了好久才发现虽然都是连在同一个路由器,网段却不一样.(老师说应该是一样的,我也不知道怎么回事.)后来修改了手机的IP地址,才能连上.关于如何修改手机IP,百度一下就OK了. 二.ReadLine()读数据阻塞问题 终于连接上了,却读不出数据.经过deb

分享一个android仿ios桌面卸载的图标抖动动画

直接上代码,如有更好的,还请指教 <span style="font-size:18px;"><?xml version="1.0" encoding="UTF-8"?> <rotate android:toDegrees="2" android:repeatMode="reverse" android:repeatCount="infinite" andr

Android手机做无线中继路由器

为什么要拿手机做路由器?因为我现在每天要带着一个火柴盒大小的路由器(703n).它提供了一个f了q的无线网络,电脑,手机,平板等设备连接上这个无线网络之后之后就可以自由上twitter,看youtube.但是它还不够理想.,我不希望在拥挤的包里再塞一个设备,我还希望在路上只有3G网络没有USB电源的地方也可以刷刷twitter.最好的设备莫过于手机了. 手机拿来做fq路由器最大的缺陷在于,它不是一个路由器.最开始手机都是处于网络的终端,要么接收3G信号,要么接收wifi信号.后来技术发展之后,手

Android手机间使用socket进行文件互传实例

这是一个Android手机间文件传输的例子,两个手机同时装上此app,然后输入接收端的ip,选择文件,可以多选,点确定,就发送到另一个手机,一个简单快捷文件快传实例.可以直接运用到项目中. 下面是文件选择器: 代码 首先加入文件选择库 compile 'com.nononsenseapps:filepicker:2.5.2' 这个库的地址和用法在:https://github.com/spacecowboy/NoNonsense-FilePicker activity_main.xml <Rel