I got a TransactionTooLargeException
. Not reproducible. In the docs it says
The Binder transaction failed because it was too large.
D
This is not a definitive answer, but it may shed some light on the causes of a TransactionTooLargeException
and help pinpoint the problem.
Although most answers refer to large amounts of data transferred, I see this exception being thrown incidentally after heavy scrolling and zooming and repeatedly opening an ActionBar spinner menu. The crash happens on tapping the action bar. (this is a custom mapping app)
The only data being passed around seem to be touches from the "Input Dispatcher" to the app. I think this cannot reasonably amount to anywhere near 1 mb in the "Transaction Buffer".
My app is running on a quad core 1.6 GHz device and uses 3 threads for heavylifting, keeping one core free for the UI thread. Furthermore, the app uses android:largeHeap, has 10 mb of unused heap left and has 100 mb of room left to grow the heap. So I wouldn't say it is a resource issue.
The crash is always immediately preceded by these lines:
W/InputDispatcher( 2271): channel ~ Consumer closed input channel or an error occurred. events=0x9
E/InputDispatcher( 2271): channel ~ Channel is unrecoverably broken and will be disposed!
E/JavaBinder(28182): !!! FAILED BINDER TRANSACTION !!!
Which are not neccesarily printed in that order, but (as far as I checked) happen on the same millisecond.
And the stack trace itself, for clarity, is the same as in the question:
E/AndroidRuntime(28182): java.lang.RuntimeException: Adding window failed
..
E/AndroidRuntime(28182): Caused by: android.os.TransactionTooLargeException
Delving into the source code of android one finds these lines:
frameworks/base/core/jni/android_util_Binder.cpp:
case FAILED_TRANSACTION:
ALOGE("!!! FAILED BINDER TRANSACTION !!!");
// TransactionTooLargeException is a checked exception, only throw from certain methods.
// FIXME: Transaction too large is the most common reason for FAILED_TRANSACTION
// but it is not the only one. The Binder driver can return BR_FAILED_REPLY
// for other reasons also, such as if the transaction is malformed or
// refers to an FD that has been closed. We should change the driver
// to enable us to distinguish these cases in the future.
jniThrowException(env, canThrowRemoteException
? "android/os/TransactionTooLargeException"
: "java/lang/RuntimeException", NULL);
To me it sounds like I'm possibly hitting this undocumented feature, where the transaction fails for other reasons than a Transaction being TooLarge. They should have named it TransactionTooLargeOrAnotherReasonException
.
At this time I did not solve the issue, but if I find something useful I will update this answer.
update: it turned out my code leaked some file descriptors, the number of which is maximized in linux (typically 1024), and this seems to have triggered the exception. So it was a resource issue after all. I verified this by opening /dev/zero
1024 times, which resulted in all kinds of weird exceptions in UI related actions, including the exception above, and even some SIGSEGV's. Apparently failure to open a file/socket is not something which is handled/reported very cleanly throughout Android.