Reputation: 761
I have got some ANRs in my android vitals:
Broadcast of Intent { act=android.intent.action.SCREEN_ON flg=0x50200010 (has extras) } or
Broadcast of Intent { act=android.intent.action.SCREEN_ON flg=0x50000010 }.
I have also have got some ANRs:
Broadcast of Intent { act=android.intent.action.SCREEN_OFF flg=0x50000010 }
It seems that those ANRs happen regularly.
From my research i did not found a solution.
Specifically i wonder if these ANRs are related with
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
in my onCreate to keep screen on.
I do not use any BroadcastReceiver in my app.
Any help?
Error logs from android vitals:
"main" tid=1 Waiting
"main" prio=5 tid=1 Waiting
| group="main" sCount=1 dsCount=0 flags=1 obj=0x73c98680 self=0xee259000
| sysTid=24710 nice=0 cgrp=default sched=0/0 handle=0xf26ff4bc
| state=S schedstat=( 2919404633 900616698 9273 ) utm=197 stm=94 core=0 HZ=100
| stack=0xff6b6000-0xff6b8000 stackSize=8MB
| held mutexes=
at java.lang.Object.wait (Native method)
- waiting on <0x03bec179> (a com.myPackageName)
at com.myPackageName.framework.impl.GLGame.onPause (GLGame.java:714)
- locked <0x03bec179> (a com.myPackageName)
at com.myPackageName.onPause (MyApp.java:39)
at android.app.Activity.performPause (Activity.java:7399)
at android.app.Instrumentation.callActivityOnPause (Instrumentation.java:1414)
at android.app.ActivityThread.performPauseActivityIfNeeded (ActivityThread.java:4115)
at android.app.ActivityThread.performPauseActivity (ActivityThread.java:4092)
at android.app.ActivityThread.performPauseActivity (ActivityThread.java:4066)
at android.app.ActivityThread.handlePauseActivity (ActivityThread.java:4040)
at android.app.ActivityThread.-wrap16 (ActivityThread.java)
at android.app.ActivityThread$H.handleMessage (ActivityThread.java:1708)
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)
Upvotes: 29
Views: 16459
Reputation: 328
Your GLGame class has been derived from the GLSurfaceView class.
This is a standard way of writing games on Android.
GLSurfaceView.onPause is then called after Activity.onPause.
Inside GLSurfaceView.onPause is the blocking wait():
public void onPause() {
synchronized (sGLThreadManager) {
if (LOG_PAUSE_RESUME) {
Log.i("GLThread", "onPause tid=" + getId());
}
mRequestPaused = true;
sGLThreadManager.notifyAll();
while ((! mExited) && (! mPaused)) {
if (LOG_PAUSE_RESUME) {
Log.i("Main thread", "onPause waiting for mPaused.");
}
try {
sGLThreadManager.wait(); // <<<<<<<<<<< Causing ANR.
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
}
}
This is rarely a problem and I have used this method for several games. Potentially a bad GL driver on the device. It may be fixable by running GLSurfaceView.onPause on its own thread.
Upvotes: 0
Reputation: 393
We encountered the same issue. It has nothing to do with the SCREEN_ON flag, whether you do it programmatically or via XML.
In our case, the crash was happening because of a missing channel for notification onReceive()
https://developer.android.com/training/notify-user/channels
Starting in Android 8.0 (API level 26), all notifications must be assigned to a channel. For each channel, you can set the visual and auditory behavior that is applied to all notifications in that channel. Then, users can change these settings and decide which notification channels from your app should be intrusive or visible at all.
You may want to look for similar issue.
Upvotes: 2
Reputation: 1875
If you are using following code snippet in activity's onCreate method
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setContentView(R.layout.main);
Just replace these with below lines of code
View view = getLayoutInflater().inflate(R.layout.main, null);
view.setKeepScreenOn(true);
setContentView(view);
I hope it will help you to get solution.
Happy Coding :)
Upvotes: 3
Reputation: 12899
The broadcast has nothing to do with your issue
at java.lang.Object.wait (Native method)
- waiting on <0x03bec179> (a com.myPackageName)
at com.myPackageName.framework.impl.GLGame.onPause (GLGame.java:714)
you are doing synchronized operations in the main thread.
Object.wait()
is used for manual synchronization, you should never do this kind of stuff in the main thread.
whatever you are doing at com.myPackageName.framework.impl.GLGame.onPause
in file GLGame.java
at line 714
is causing this synchronization.
there you are waiting for something to happen that either take too much (even few milliseconds) or it's completely stuck (deadlock).
Regardless of how much it stay there waiting you should not have synchronization code in your mainthread. But if it's a deadlock moving it outside of the main thread will only fix the ANR, finding and fixing the deadlock will be another problem on its own.
If you didn't already check the official doc about ANR which also talk about synchronization and wait/notify, which is probably related to your issue.
In short: move your synchronization logic outside of the mainthread (do not do it onPause / onResume) and into some background work.
It's impossible to help you more than this without seeing the actual offending code and knowing what it does.
Upvotes: 1
Reputation: 3147
I'm pretty sure this ANR is caused by a synchronized block, unless line 714 points to super.onPause()
. In your GLGame.onPause (GLGame.java:714)
you either wait on an object in the main thread intentionally, or using a synchronized final variable (that can be a synchronized list, set, map etc...) Since you haven't shared any source code, I cannot tell what is actually causing it without looking.
In a main thread, using this kind of approach may block your thread which is something you definitely don't want (assuming the lock is also used in another thread)
// One example
@Override
public void onPause() {
synchronized(mLock) {
// access the variable
}
}
// Another example
@Override
public void onPause() {
synchronizedList.add(new Object())
}
Both of these approaches will be blocked if there is another thread that, at the moment, accessing the lock or the synchronized list, map etc... and doesn't give up the lock. For a solution, I could recommend using ReentrantLock with Lock
interface using like Lock mLock = new ReentrantLock()
and turn your calls into something like this:
@Override
public void onPause() {
if (mLock.tryLock()){
try{
// do your work here
} finally {
mLock.unlock();
}
}
}
// Another example
@Override
public void onPause() {
if (mLock.tryLock()){
try{
// The list or set should not be synchronized.
// The synchronization must be managed with lock's
// "tryLock" method. The "tryLock" also has an
// overload with a timeout which you can use
// in your background thread, but you must not
// use on the main thread.
normalList.add(new Object());
} finally {
mLock.unlock();
}
}
}
The variables that are accessed on main thread should not block, or the worker thread should block them as little as possible so main thread can acquire the lock immediately after if you want to ensure synchronization. So I suggest checking your entire code about shared variables and references between main thread and other threads, and only synchronize the changes on the variables instead of an entire code block that takes long to execute.
Upvotes: 4