Call to “DisplayManagerGlobal.getDisplayInfo()” causes App Not Responding (ANR) in the app

a 夏天 提交于 2021-01-27 21:03:31

问题


Apparently, something in the application calls the method from different threads (both main and a binder thread) which causes an internal ANR. It happens quite frequently and I don't have an idea as to where it happens because I cannot reproduce it on emulators or the test devices that I have got.

What the app does: It is an app locker application, which draws a full screen lock view on application overlay and asks for a password (pattern), which also supports fingerprint unlock mechanism. To successfully listen the fingerprint, we also have to use a transparent activity to make the app go "foreground", and then wait for the fingerprint input, as otherwise, fingerprint mechanism does not listen and it doesn't have a callback for it either. Maybe that is the cause, because the activity starts and finishes frequently, on every locked app.

ANR is reported under two matters:

Broadcast of Intent { act=android.intent.action.SCREEN_ON flg=0x50200010 (has extras) } Broadcast of Intent { act=android.intent.action.SCREEN_OFF flg=0x50200010 (has extras) }

Regarding to this, the app has a foreground service that always runs, because it needs to lock apps at any time as a requirement, and it listens to these events from a dynamic broadcast receiver. However, there are no blocking calls or synchronized calls in any of them, just a start-stop mechanism for the continuous worker thread that checks the current foreground app.

Full ANR report

Related ANR report (related section, reported from Android 10 device, API 29):

"main" prio=5 tid=1 Blocked
  | group="main" sCount=1 dsCount=0 flags=1 obj=0x71773f98 self=0x7f95a7d000
  | sysTid=28841 nice=-4 cgrp=default sched=0/0 handle=0x7f96febee8
  | state=S schedstat=( 151471598466 24930775143 453988 ) utm=9534 stm=5612 core=3 HZ=100
  | stack=0x7fddb4d000-0x7fddb4f000 stackSize=8192KB
  | held mutexes=
  at android.hardware.display.DisplayManagerGlobal.getDisplayInfo (DisplayManagerGlobal.java:177)
- waiting to lock <0x038dbdd7> (a java.lang.Object) held by thread 6
  at android.view.Display.updateDisplayInfoLocked (Display.java:1214)
  at android.view.Display.updateDisplayInfoLocked (Display.java:1209)
  at android.view.Display.getState (Display.java:1174)
- locked <0x053b6aeb> (a android.view.Display)
  at android.view.ViewRootImpl$1.onDisplayChanged (ViewRootImpl.java:1601)
  at android.hardware.display.DisplayManagerGlobal$DisplayListenerDelegate.handleMessage (DisplayManagerGlobal.java:1417)
  at android.os.Handler.dispatchMessage (Handler.java:107)
  at android.os.Looper.loop (Looper.java:237)
  at android.app.ActivityThread.main (ActivityThread.java:7811)
  at java.lang.reflect.Method.invoke (Native method)
  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:493)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1068)

"Binder:28841_6" prio=5 tid=6 Runnable
  | group="main" sCount=0 dsCount=0 flags=0 obj=0x132c19b0 self=0x7f08d9a400
  | sysTid=29512 nice=0 cgrp=default sched=0/0 handle=0x7f0133ed50
  | state=R schedstat=( 673333745225 29381013522 76199 ) utm=67111 stm=221 core=7 HZ=100
  | stack=0x7f01248000-0x7f0124a000 stackSize=991KB
  | held mutexes= "mutator lock"(shared held)
  at android.os.MessageQueue.enqueueMessage (MessageQueue.java:581)
- locked <0x0306e956> (a android.os.MessageQueue)
  at android.os.Handler.enqueueMessage (Handler.java:754)
  at android.os.Handler.sendMessageAtTime (Handler.java:703)
  at android.os.Handler.sendMessageDelayed (Handler.java:673)
  at android.os.Handler.sendMessage (Handler.java:611)
  at android.hardware.display.DisplayManagerGlobal$DisplayListenerDelegate.sendDisplayEvent (DisplayManagerGlobal.java:1403)
  at android.hardware.display.DisplayManagerGlobal.handleDisplayEvent (DisplayManagerGlobal.java:408)
- locked <0x038dbdd7> (a java.lang.Object)
  at android.hardware.display.DisplayManagerGlobal.access$100 (DisplayManagerGlobal.java:70)
  at android.hardware.display.DisplayManagerGlobal$DisplayManagerCallback.onDisplayEvent (DisplayManagerGlobal.java:1354)
  at android.hardware.display.IDisplayManagerCallback$Stub.onTransact (IDisplayManagerCallback.java:119)
  at android.os.Binder.execTransactInternal (Binder.java:1021)
  at android.os.Binder.execTransact (Binder.java:994)

I'm not exactly sure what causes this, as there are no stack traces to the app itself, in any threads. And I can see that main thread is blocked due to waiting to lock <0x038dbdd7>, since the binder thread already locked it: locked <0x038dbdd7> but did not release it.

Any opinions on this matter? I appreciate any help, thank you very much.


回答1:


Well, I've found the problem. It is caused because of an internal memory leak under Android's WindowManagerGlobal class. Here is what it caused it:

The app is using the overlay permission, and doing so we were asking the users to give permission, and automatically detect it if the user gives one. After this, we've also been creating a foreground service that runs in between 2 seconds of interval in a loop, never stopping, also checking the permission in between. Since I've encountered some bugs regarding to Settings.canDrawOverlays(Context) method, I've decided to look up for an answer, and found this answer which lead to the huge memory leak.

You see, calling the drawing an invisible overlay part creates a leak. It adds the view root into the memory, but in between, fails to add the overlay because of a SecurityException and the view never gets removed. Since that code creates a new view each time to check the permission, new view roots, new displays and new listeners to the call onDisplayChanged. After debugging, I was finally able to see this and caught the memory leak. Removing that code resolved the issue entirely, no ANRs relating to it are visible now.

I've also tried to remove the view calling WindowManager.removeView(view) if addView fails, but regardless the failed view to be added remained in the listener and memory. So, I'd say this approach should be avoided in any case and another alternative should be found.



来源:https://stackoverflow.com/questions/61183961/call-to-displaymanagerglobal-getdisplayinfo-causes-app-not-responding-anr

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!