I'm trying to fix a bug in an app that rarely causes Application Not Responding (ANR).
I followed these steps to find the possible cause: Android - how do I investigate an ANR?
With it I've come across this entry in traces.txt:
"Emotiv USB dongle reading thread" prio=5 tid=29 Suspended
| group="main" sCount=1 dsCount=0 obj=0x32c077c0 self=0xa21de800
| sysTid=21942 nice=0 cgrp=default sched=0/0 handle=0xaf4e4000
| state=S schedstat=( 661311503042 260341162486 616738 ) utm=64211 stm=1920 core=3 HZ=100
| stack=0xa043e000-0xa0440000 stackSize=1036KB
| held mutexes=
at android.os.MessageQueue.enqueueMessage(MessageQueue.java:353)
- locked <0x2985cad6> (a android.os.MessageQueue)
at android.os.Handler.enqueueMessage(Handler.java:631)
at android.os.Handler.sendMessageAtTime(Handler.java:600)
at android.os.Handler.sendMessageDelayed(Handler.java:570)
at android.os.Handler.sendMessage(Handler.java:507)
at android.os.Handler$MessengerImpl.send(Handler.java:721)
at android.os.Messenger.send(Messenger.java:57)
at eeg_presentation_app.Driver.EmotivReaderRunnable.run(EmotivReaderRunnable.java:109)
at java.lang.Thread.run(Thread.java:818)
This leads me to believe, that the Messenger.send()
call in EmotivReaderRunnable.run()
is the reason for the ANR.
However, I've also noticed that at the beginning of traces.txt it says:
Heap: 0% free, 170MB/170MB; 3813172 objects
Is the full heap a symptom of a problem with the Messenger.send()
call or is it rather the other way around: The full heap causes a problem with the said call? In case of the latter, how could I find the reason for the full heap?
Here's the EmotivReaderRunnable.run():
public void run() {
/**
* set up connection to EEG
*/
final UsbInterface myInterface = device.getInterface(1); // communicate with interface 1
final UsbEndpoint myEndpoint = myInterface.getEndpoint(0); // endpoint for communication
UsbDeviceConnection connection = usbManager.openDevice(device); // start connection
connection.claimInterface(myInterface, true);
/**
* buffer for packet as it arrives, split up in bytes (encrypted)
*/
ByteBuffer encryptedPacket = ByteBuffer.wrap(new byte[32]);
UsbRequest usbRequest = new UsbRequest();
UsbRequest usbResult = null;
// initialize connection
usbRequest.initialize(connection, myEndpoint);
//as long as thread active
while (!Thread.interrupted()) {
// read 32 byte data into encryptedPacket, return true if successful
boolean success = usbRequest.queue(encryptedPacket, 32);
if (success) {
// get result of usbRequest
usbResult = connection.requestWait();
} else {
break; //something is wrong with the connection
}
// now packet was written to encryptedPacket
if (encryptedPacket.position() == 0) { //no content
break;
}
// how long since system was booted
long elapsedNanos = SystemClock.elapsedRealtimeNanos(); //this requires api level 17 (android 4.2)
//long elapsedNanos = SystemClock.elapsedRealtime(); //temporary, for debugging on my Android 4.1
// it allows very exact timing
// standard wall clock time -> time when packet was received
long receivedTime = System.currentTimeMillis();
// decrypt packet content with EmotivDecryptor
byte[] decryptedPacket = decryptor.decrypt(encryptedPacket.array());
Message message = Message.obtain();
message.setData(packetToBundle(elapsedNanos, receivedTime, decryptedPacket));
try {
messenger.send(message);
} catch (RemoteException e) {
Log.e(TAG, "RemoteException in run()");
e.printStackTrace();
break; // the service went away, so let's close this thread as well
}
}
if (usbResult != null) {
usbResult.close();
}
connection.releaseInterface(myInterface);
connection.close();
}
I don't see what could be wrong with my run()
. My only guess it that for some reason decryptedPacket
is becoming rather large. But the ANR happened once after 2 minutes of recording and once after about 30 minutes. I receive less than 1mb of data per minute. So that should be far from causing any out of memory problems.
Any recommendations on how I can continue from here?