I'm pretty baffled by the ANR I'm getting from my application as I don't understand how it could happen.
I've got mutliple ANR for these codes:
File(applicationContext.filesDir).mkdirs()
File(applicationContext.filesDir).exists()
and I get the following ANR report:
1.
main (native): tid=1 systid=30195
#00 pc 0xc57c8 libc.so
#01 pc 0x21580 libopenjdk.so
at java.io.UnixFileSystem.createDirectory0(UnixFileSystem.java)
at java.io.UnixFileSystem.createDirectory(UnixFileSystem.java:354)
at java.io.File.mkdir(File.java:1325)
at java.io.File.mkdirs(File.java:1352)
#01 pc 0x21fc0 libjavacore.so
at libcore.io.Linux.access(Linux.java)
at libcore.io.ForwardingOs.access(ForwardingOs.java:131)
at libcore.io.BlockGuardOs.access(BlockGuardOs.java:76)
at libcore.io.ForwardingOs.access(ForwardingOs.java:131)
at android.app.ActivityThread$AndroidOs.access(ActivityThread.java:8068)
at java.io.UnixFileSystem.checkAccess(UnixFileSystem.java:281)
at java.io.File.exists(File.java:813)
My application targets from Android 5 to Android 12 and only Android 11 and Android 12 are getting these ANRs.
Do you guys have any idea how to solve this ? Should I File(applicationContext.filesDir).mkdirs() on a different an IO Thread to avoid blocking ?
You should definitely perform all file operations off the main thread, regardless of what else is happening. It's definitely not a permissions issue -- if it were, you would just get a permission denial, not an ANR.
Having said that, you generally wouldn't get an ANR from just checking your app's fileDir, even on the main thread. But my guess is that wherever this AND came from, either the device's internal storage is really slow, or it's likely that your app was moved to external storage. Checking external storage availability takes longer.
Either way, as I said earlier, it doesn't actually matter why it's happening. You should just be performing all the file IO on a separate thread
Related
I'm having a very hard time debugging an Android ANR problem. This ANR is coming on play store and I am not able to reproduce the problem. In our app, we are listening to android.intent.action.MY_PACKAGE_REPLACED broadcast and on some devices we are getting ANR while parsing of File provider.
"main" prio=5 tid=1 Native
at java.io.UnixFileSystem.checkAccess0 (UnixFileSystem.java)
at java.io.UnixFileSystem.checkAccess (UnixFileSystem.java:252)
at java.io.File.exists (File.java:807)
at android.app.ContextImpl.ensureExternalDirsExistOrFilter (ContextImpl.java:2478)
at android.app.ContextImpl.getExternalFilesDirs (ContextImpl.java:639)
at android.content.ContextWrapper.getExternalFilesDirs (ContextWrapper.java:247)
at androidx.core.content.ContextCompat.getExternalFilesDirs (ContextCompat.java:381)
at androidx.core.content.FileProvider.parsePathStrategy (FileProvider.java:635)
at androidx.core.content.FileProvider.getPathStrategy (FileProvider.java:579)
Does anyone know what can usually cause these sorts of ANRs? I could think of app getting updated in Direct Boot mode and not able to access these locations on main thread and causing ANRs but that is based on hunch and could not support it with any strong argument.
The androidx FileProvider has both a PackageManager call and a disk read in it. Androidx should not be be doing these sorts of accesses on the startup path.
In any case, it seems you have a little control over it based on what tags are in your FILE_PROVIDER_PATHS xml. Your trace looks like there is a <external-files-path> tag somewhere, possibly in a third party library.
I'm using DDMS to monitor threads in my app, and I see that my app has a bunch of native threads as shown in follow picture. And time to time, the number of native threads increased as user interact with my app, which cause my app sometime does not serve as I expect. Is there anyway to kill these native threads?
There is no such thing as a "native thread" on Android, although some people might use that to refer to threads that are not attached to the VM (which would also make them invisible to DDMS). The threads happen to be executing (or waiting) in native code at the time you did a thread dump, but may spend most of their time executing bytecode. (A list of Dalvik thread states is available here.)
The names of the threads suggests that they were created without being given an explicit name. The one thread with a name, NsdManager probably exists because you're using NsdManager, which "responses to requests from an application are on listener callbacks on a seperate thread" [sic].
It's possible that you can glean some useful information from a stack trace. In DDMS, double-click the thread to get a backtrace. On a rooted device, you can kill -3 <pid> to get a full dump, including native stack frames.
Killing arbitrary threads is not allowed, as they might be holding locks or other resources. If you can determine what is starting them, and that they are unnecessary, you can prevent them from being started in the first place.
I have an Android native Server app compiled as Platform privileged module that forks itself. This module also uses Android services, like SurfaceFlinger. I need to fork to have one sandboxed process per client.
Fork() works fine and the parent process has no issue at all. But in the child process, when I try to access any Android service/resource I get:
signal 11 (SIGSEGV), code 2 (SEGV_ACCERR), fault addr xxxxxxxx ... ...
/system/lib/libbinder.so (android::Parcel::ipcSetDataReference
...
/system/lib/libbinder.so (android::BpBinder::transact
NativeCrashListener( 1203): Couldn't find ProcessRecord for pid XXXX
This happens even when I try to create a NEW client, thus, not using any previous created reference.
NativeCrashListener doesn't know about my child process, thus, maybe ActivityManager also doesn't.
I looked at the Zygote code but have not found anything helpful there. I'm probably missing some step or calling some function on the child process. Any ideas ??? =)
You can't create a new Binder process this way.
The problem is that fork() only clones the current thread, not all threads. In the new process, the Binder IPC code will expect the Binder helper threads to be running, but none of them will be. You need to fork() and then exec().
The zygote process avoids this issue by having only one thread running when fork() is called. It deliberately defers initialization of the Binder code to the child process. (In the current implementation, it actually has a couple of threads running in Dalvik, but the internal fork handling stops and restarts those threads on every fork).
fadden is right, fork() cannot be used to create a new process that uses Android APIs reliably. The best you can do with it is exec() to run a standalone command-line program, everything else is likely to not work as you expect.
However, the platform supports sandboxed processes, in the form of isolated service processes. See http://developer.android.com/guide/topics/manifest/service-element.html#isolated for more details. In essence, this runs your service in a special process under a random UID that has no permissions.
For the record, this is what Chrome on Android uses to isolate 'tabs' into sandboxed 'renderer processes'.
I am debugging an Android application and one of the activities just failed silently; it popped off the back stack and I got the previous activity.
I've seen silent failures of this type that can be attributed to memory problems, but in this case I am testing without the debugger attached. The logcat shows virtually no information: after some output from our touch listeners, I get
I/DEBUG(85): debuggerd committing suicide to free the zombie!
I/DEBUG(24919): debuggerd: Jul 8 2011 06:16:01
I/ActivityManager(157): Process com.tse.newsreader (pid 24415) has died.
I/WindowManager(157): WIN DEATH: Window{4108f938 com.tse.newsreader/com.tse.newsreader.activities.StorefrontFragmentActivity paused=false}
com.tse.newsreader is our process.
I would like to know if this is caused by a memory leak somewhere and I was hoping to add an HPROF dump to a global exception handler, somewhat as described in Is there a way to take a memory dump on app crash? but if there is no exception or OutOfMemoryError to catch, I don't see how that will help.
Can anyone suggest how I can get at the cause of these silent failures?
I'm not sure if this is what you mean, but you could consider adding something like bugsense to your app. It will pick up uncaught exceptions.
I have C++ codebase running on Android, and want to have crash reports sent by users.
I'm using ACRA library which works fine for Java code, but when something crashes in native code, I don't get enough information. Actually I'd like to receive stack trace of native function calls. I know crash info is printed into logcat after my process ends, and I can configure ACRA to read/send logcat. I've setup my code to detect native crash using signal handlers and calling back to Java for reporting by ACRA. It works also fine.
However there's bad timing with this approach - ACRA reads logs while crashing process is still alive, and Android (don't know exactly which part) writes crash report to logcat after crashed process completely ends. So I don't receive stack traces when using ACRA.
So I'm looking for a way to programatically read current stack trace from C++ code, and feed this info to ACRA (or maybe other crash reporting tool) myself.
All I need is some kind of this report written to logcat:
10-10 08:29:13.868: INFO/DEBUG(1121): #00 pc 0003fc7c /data/data/com.ex.lib/libapp.so
10-10 08:29:13.891: INFO/DEBUG(1121): #04 pc 00016df4 /system/lib/libdvm.so
10-10 08:29:13.891: INFO/DEBUG(1121): #05 pc 00045284 /system/lib/libdvm.so
10-10 08:29:13.899: INFO/DEBUG(1121): #15 pc 00047c56 /system/lib/libdvm.so
10-10 08:29:13.922: INFO/DEBUG(1121): #16 pc 00030e4c /system/lib/libandroid_runtime.so
Is there any way to get this stack trace from my code?
I have done this in my game base project - you can see the JNI code which handles this here:
https://bitbucket.org/xg/android-game-base/src/c0d969d44a55/jni/NativeActivityJNI.cpp#cl-40
which calls the Java method defined here:
https://bitbucket.org/xg/android-game-base/src/c0d969d44a55/src/com/gmail/whittock/tom/Util/NativeActivity.java#cl-91
The overall solution is based on handling signals, then in the signal handler firing a call up to java to dump the stack trace etc, in my code I start another activity to get the logcat information and email it to me.
ACRA can trap the application crashing. You could then instantiate a second process that would execute the logcat ( see this question ) command, filtering by your application name, and then have the process to send the dumped file to you. This is far from optimal because:
The Application that would span logcat has to have the WRITE_EXTERNAL_STORAGE and READ_LOGS permissions
Probably the user would be annoyed to having to install a new program
But I didn't found another alternative to do this.