ANR at android.os.MessageQueue.nativePollOnce

53.1k views Asked by At

We are seeing this ANR in different parts of our app. Wanted to understand what causes this ANR?

main (native): tid=1 systid=31940
#00 pc 0x5431c libc.so 
#01 pc 0x1313a5 libart.so 
#02 pc 0x2ab05b libart.so 
#03 pc 0x3659 libnativehelper.so 
#04 pc 0x9dee9 libandroid_runtime.so 
#05 pc 0x65c45 libgui.so 
#06 pc 0x11dcd libutils.so 
#07 pc 0x11abf libutils.so 
#08 pc 0xbcc7d libandroid_runtime.so 
       at android.os.MessageQueue.nativePollOnce(MessageQueue.java)
       at android.os.MessageQueue.next(MessageQueue.java:339)
       at android.os.Looper.loop(Looper.java:199)
       at android.app.ActivityThread.main(ActivityThread.java:8276)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:612)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1006)

This is what firebase has to say about this ANR -

This thread was idle when the ANR occurred. We don't have sufficient information to determine the root cause.

5

There are 5 answers

0
Omer Eizenberg On

Facing the same issue - I've read that it related to Admob or unity ads and there is an open thread for google : https://issuetracker.google.com/issues/230950647?pli=1

1
Krishna Sony On

On the latest release of Cloud Messaging dependencies v23.0.7 Firebase Mention that this release might reduce the ANR. here is his words mentioned in its documentation.

Message broadcasts now finish immediately after binding to the service. This change should reduce the chance of ANRs

1
Yaqoob Bhatti On

NativePollOnce:

It appears when the CPU is waiting for a new task/message.

Reasons:

  1. ANR may occur if BroadCast Receiver hasn’t finished execution within 10 Seconds.
  2. No response to an input event within 5 Seconds
  3. ANR may be caused when the app tries to show a dialog by mistake but the call is not from the main thread. (Note: verify all calls of UI View from UI thread)
  4. It may occur due to memory leaks.
  5. Handler.postDelayed may create an issue
  6. This type of crash is commonly seen, when the stack dump takes place, some app’s stack trace could be dumped for a long after the actual ANR time
  7. It may occur on SCREEN_ON BROADCAST and google ads are using SCREEN_ON BROADCAST.
  8. It may occur during the Garbage collection process (by
    Ezequiel Adrian comment)

Ways to collect ANRs:

  1. WatchDog
  2. Catching Native SIGQUIT
  3. ApplicationExitInfo (used by crashalytics)
  4. Collect from Google Play Console
  5. Firebase (firebase only collect from android 11 and above)

Challenges in Solving ANR:

Demystifying the ANRs Puzzle. Link

Solutions:

  1. Optimize initialization and Ad Loading. Link
  2. If you are using Media then release it in IO Thread
  3. Find memory leaks to track down using a leak canary or Android profiler
  4. Downgrade firebase to 28.4.2 (It will not collect ANR but it does not mean that it cannot occur)
  5. Verify all calls of UI View from the UI thread
  6. More Information from Issue Tracker
  7. More Info Stack Ans
  8. Reduced the usage of Static(java) or companion object(kotlin)'s, properties, and classes
2
Daniel Pína On

In my case, it was an error in the firebase cloud messaging lib. The bug was fixed in the latest version 23.1.1, which was released on 12/8/2022.

https://firebase.google.com/support/release-notes/android#messaging_v23-1-1

Hope it helps you.

0
wangpan On

A possible reason: The UI thread was blocked by sync barrier.

If MessageQueue of the UI thread has a sync barrier, all messages will be blocked (except asynchronous ones) until the sync barrier removed.

What will cause this issue?

If you invalidate your view in a Non-UI thread, you may get this issue.

Why?

// View.java
public void invalidate() {
    invalidate(true);
}
public void invalidate(boolean invalidateCache) {
    invalidateInternal(...);
}
void invalidateInternal(...) {
    final ViewParent p = mParent;
    p.invalidateChild(this, damage);
}

// ViewGroup.java
public final void invalidateChild(View child, final Rect dirty) {
    onDescendantInvalidated(child, child);
}

public void onDescendantInvalidated(@NonNull View child, @NonNull View target) {
    //...
    if (mParent != null) {
        mParent.onDescendantInvalidated(this, target);
    }
}

ViewRootImpl is the top-most ViewParent:

public void onDescendantInvalidated(@NonNull View child, @NonNull View descendant) {
    // TODO: Re-enable after camera is fixed or consider targetSdk checking this
    // checkThread();
    invalidate();
}
void invalidate() {
    scheduleTraversals();
}
void scheduleTraversals() {
    if (!mTraversalScheduled) {
        mTraversalScheduled = true;
        mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
    }
}

void unscheduleTraversals() {
    if (mTraversalScheduled) {
        mTraversalScheduled = false;
        mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);
    }
}

void doTraversal() {
    if (mTraversalScheduled) {
        mTraversalScheduled = false;
        mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);
}

Note the postSyncBarrier and removeSyncBarrier in the snippet above

Here in onDescendantInvalidated of ViewRootImpl, it didn't check if it's in UI thread.

So if you invalidate your view in a non-ui thread occasionally, you may leave a sync barrier in the message queue without being removed later and then you will get this issue.

Do I invalidate my view off ui thread?

In my case, I provide BitmapDrawables to many views and then I may change the bitmap of the BitmapDrawable in a work thread. This will cause the views using the BitmapDrawable being invalidated in the work thread.

How to check if any views is invalidated in non-ui thread?

In the top-most ViewGroup of your view hierarchy, override onDescendantInvalidated:

override fun onDescendantInvalidated(child: View, target: View) {
    super.onDescendantInvalidated(child, target)
    if (Looper.getMainLooper() != Looper.myLooper()) {
        throw RuntimeException("no ui thread")
    }
}

Typical symptoms of the issue

  1. RecyclerView or ListView can be scrolled normally, but click listeners of any view will not work.
  2. ANR may occurs with a low cpu overload and stack trace of the main thread contains MessageQueue.nativePollOnce
  3. The ANR may be a BroadcastTimeout anr or a ServiceTimeout anr but is NOT a KeyDispatchTimeout anr