呼叫系统服务(例如电话服务)时的ANR

时间:2018-10-19 12:12:40

标签: android native android-anr-dialog

自Android 8起,我在Google Play开发者控制台中报告的ANR数量有所增加。他们都有一个共同点,即ANR似乎与我的代码不直接相关,但始终与本机系统调用相关。 请参见以下示例:

示例1:

"main" prio=5 tid=1 Native
  | group="main" sCount=1 dsCount=0 flags=1 obj=0x73798b10 self=0x73186a3a00
  | sysTid=12505 nice=0 cgrp=default sched=0/0 handle=0x731d5c49b0
  | state=S schedstat=( 28971945984 27609449667 173830 ) utm=1926 stm=970 core=1 HZ=100
  | stack=0x7fd4e3d000-0x7fd4e3f000 stackSize=8MB
  | held mutexes=
  #00  pc 000000000001db2c  /system/lib64/libc.so (syscall+28)
  #01  pc 00000000000e1f30  /system/lib64/libart.so (_ZN3art17ConditionVariable16WaitHoldingLocksEPNS_6ThreadE+152)
  #02  pc 00000000004e21a4  /system/lib64/libart.so (_ZN3artL12GoToRunnableEPNS_6ThreadE+440)
  #03  pc 00000000004e1fa4  /system/lib64/libart.so (_ZN3art12JniMethodEndEjPNS_6ThreadE+28)
  #04  pc 0000000000991b3c  /system/framework/arm64/boot-framework.oat (Java_android_os_BinderProxy_transactNative__ILandroid_os_Parcel_2Landroid_os_Parcel_2I+220)
  at android.os.BinderProxy.transactNative (Native method)
  at android.os.BinderProxy.transact (Binder.java:761)
  at android.os.ServiceManagerProxy.getService (ServiceManagerNative.java:123)
  at android.os.ServiceManager.getService (ServiceManager.java:66)
  at android.telephony.SubscriptionManager.getPhoneId (SubscriptionManager.java:953)
  at android.telephony.TelephonyManager.getNetworkOperatorName (TelephonyManager.java:1693)
  at android.telephony.TelephonyManager.getNetworkOperatorName (TelephonyManager.java:1679)

    [...]

  at com.xx.x.v$1.onSignalStrengthsChanged (MyPhoneStateObserver.java:99)
  at android.telephony.PhoneStateListener$1.handleMessage (PhoneStateListener.java:349)
  at android.os.Handler.dispatchMessage (Handler.java:105)
  at android.os.Looper.loop (Looper.java:164)
  at android.app.ActivityThread.main (ActivityThread.java:6944)
  at java.lang.reflect.Method.invoke (Native method)
  at com.android.internal.os.Zygote$MethodAndArgsCaller.run (Zygote.java:327)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1374)

示例2:

"main" prio=5 tid=1 Native
  | group="main" sCount=1 dsCount=0 flags=1 obj=0x737b5bb0 self=0x7e0f4a3a00
  | sysTid=24248 nice=0 cgrp=default sched=0/0 handle=0x7e144ca9b0
  | state=S schedstat=( 36923767919 38940772860 261304 ) utm=2358 stm=1334 core=7 HZ=100
  | stack=0x7fdc8c2000-0x7fdc8c4000 stackSize=8MB
  | held mutexes=
  #00  pc 000000000001da2c  /system/lib64/libc.so (syscall+28)
  #01  pc 00000000000e1ee4  /system/lib64/libart.so (_ZN3art17ConditionVariable16WaitHoldingLocksEPNS_6ThreadE+152)
  #02  pc 00000000004e35c8  /system/lib64/libart.so (_ZN3artL12GoToRunnableEPNS_6ThreadE+440)
  #03  pc 00000000004e33c8  /system/lib64/libart.so (_ZN3art12JniMethodEndEjPNS_6ThreadE+28)
  #04  pc 000000000098b14c  /system/framework/arm64/boot-framework.oat (Java_android_os_BinderProxy_transactNative__ILandroid_os_Parcel_2Landroid_os_Parcel_2I+220)
  at android.os.BinderProxy.transactNative (Native method)
  at android.os.BinderProxy.transact (Binder.java:751)
  at android.net.INetworkStatsService$Stub$Proxy.getMobileIfaces (INetworkStatsService.java:318)

     [...]

  at com.xx.(MyPhoneStateObserver.java)
  at android.telephony.PhoneStateListener$1.handleMessage (PhoneStateListener.java:331)
  at android.os.Handler.dispatchMessage (Handler.java:108)
  at android.os.Looper.loop (Looper.java:166)
  at android.app.ActivityThread.main (ActivityThread.java:7425)
  at java.lang.reflect.Method.invoke (Native method)
  at com.android.internal.os.Zygote$MethodAndArgsCaller.run (Zygote.java:245)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:921)

公开问题

从这些跟踪信息中我可以看到,每次服务调用期间,系统似乎都被卡住了。电话服务。有什么解释为什么会这样吗? 我希望如果执行时间>〜10sec,就会发生ANR,所以一定有死锁吗? 可能的解决方案是将所有事件处理都移到另一个线程,但这不能解释问题,我希望异步执行也会被卡住?

编辑:可笑的是,所有这些ANR的标题均为:

  

意向广播{act = android.intent.action.SCREEN_OFF   flg = 0x50200010}

2 个答案:

答案 0 :(得分:1)

尝试以下操作,我发现了类似的结算错误堆栈:

请勿在 MyPhoneStateObserver 或任何广播接收器中拨打任何网络电话,读取或写入文件,操作数据库等。您可能正在调用某种阻塞应用程序线程的方法。我建议从单独的线程中调用这类方法。

请问为什么会发生这种情况? 我认为您应该仔细检查您的 MyPhoneStateObserver 类,我想您正在进行一些网络调用,读取或写入文件,操作数据库或任何操作应该在单独的线程中完成。您在此类或重写方法中实现的操作/代码尝试在单独的线程中进行操作。

我希望如果执行时间>〜10秒,那么就会发生ANR,因此必须存在死锁?当主线程被阻塞几次时,就会发生ANR。具体来说,活动中为5秒,广播接收器中为10秒,服务中为20秒。

可能的解决方案是将所有事件处理移至另一个线程,但这不能解释问题,并且我希望异步执行也会被卡住?是的,您是对的将您的代码移动到另一个线程。但是我认为asysnctask不能在这里工作,在服务或后台侦听器中,我相信您需要使用线程。

答案 1 :(得分:0)

根据您的错误代码。

  

意图广播{act = android.intent.action.SCREEN_OFF flg = 0x50200010}

请尝试使用Wakelock。这将防止系统在您关闭唤醒锁之前关闭应用程序进程。

您可以按以下方式获取唤醒锁

PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
    "MyApp::MyWakelockTag");
wakeLock.acquire();

有关更多详细信息,请参阅文档。 https://developer.android.com/training/scheduling/wakelock#java

另请参阅https://developer.android.com/about/versions/oreo/background 正如评论中指出的那样,Android系统会尝试优化资源,这可能是导致您的情况下出现ANR的问题。

希望这会有所帮助。