Whoops.
From dalvik/vm/Thread.cpp (line 2105):
/*
* If we're doing method trace profiling, we don't want threads to exit,
* because if they do we'll end up reusing thread IDs. This complicates
* analysis and makes it impossible to have reasonable output in the
* "threads" section of the "key" file.
Ordinarily this works out fine -- if the thread is exiting, it has nothing left to do, so it doesn't matter if we keep it around a bit longer. The signaling for Thread#join()
has already happened, so there's nothing left to do.
But in this case, the thread was temporarily attached to the VM by the native ACodec
thread that provides the onFrameAvailable()
callback. So this pure-native thread wants to attach itself to the VM, invoke the callback, detach itself, and go back to work. But because method profiling is active, the thread detach stalls until method profiling completes... but method profiling won't complete until code execution resumes. So we're deadlocked.
So there's two problems here:
- Dalvik shouldn't be keeping the thread alive. It would make method profiling more complicated since it loses the convenient unique thread ID, but that's just a matter of housekeeping.
- libstagefright shouldn't be attaching and detaching every time it wants to send a "frame available" message. That's a relatively expensive operation that requires allocating a Thread object, foiling attempts to run allocation-free.
I don't see a clean way to work around this by changing the app -- you'd have to go without the frame available notification. The best bet is to forgo the TraceView profiling and use systrace instead.