Several days ago I saw a ANR during monkey test. The ANR trace looked like this.
At the exact moment of ANR, Thread-176 was executing a shell command with Runtime.getRuntime.exec(), which entered the lock section in ProcessManager.exec().
So when our Main thread tried to execute a command later, it's blocked for a long time which caused the ANR. The "processReferences" is a HashMap which records the exit value of each child process. When ProcessManager is initialized, it creates a Thread which checks the status of every child in an infinite loop. When the status of one child process is exited or signaled, it will set the exit value accordingly.
The case is clear. We should prevent calling any method which takes a lock. With lock involved, you won't know how long your UI thread will wait before other threads release the lock. Runtime.exec() should be invoked asynchronously instead. If your UI relies on the result of exec(), place it at a earlier stage and cache it for later reference. In some extreme case, use NDK to fork the process.