BuffedWriter save of large amounts of BLE data causes GKI error - android

I have an Android app from which I receive BLE data (every 62ms via notifications). The app can save data via a BufferedWriter to a file. Upon ending the save of large amounts of data, I see an error such as this: GKI_exception out of buffers https://code.google.com/p/android/issues/detail?id=65455 (except my code is not scanning but receiving notifications). I don't see this error for 100s of kB saves, but I see it on 1-2MB saves in logcat, and on >5-6MB saves I need to power cycle the Nexus 7 (the app and BLE become totally unresponsive). I call close() on the BufferedWriter at the end of the save. How do I fix this?

The issue is likely thread related. You need to make sure that the "save" operation (which is writing file data to disk...an operation that takes a long time) is not happening in the same thread context that could block your BLE notifications or a related callback. If you block a thread that keeps a BLE callback method from returning, you will see the Bluetooth stack get starved, which is what that callback usually means.
Simplest thing is to always make sure you write file data in a new background thread (like an AsyncTask, Thread, or IntentService for instance), ensuring that regardless of what thread you were coming from, the long write to flash memory won't block the current context.

Related

UI blocking loops behaviours differ( Oreo vs Mashmallow)

I have a small Android application which does a server call to post some User data to a server.
Following is the code :
private boolean completed = false;
public String postData( Data data){
new Thread(new Runnable() {
#Override
public void run() {
try{
String response = callApi(data);
completed = true;
}catch(Exception e){
Log.e("API Error",e.getMessage());
completed = true;
return;
}
}
}).start();
while(!completed){
// Log.i("Inside loop","yes");
}
return response.toString();
}
The above method calls the API to post data and returns the response received which works fine.
The loop at the bottom is a UI blocking loop which blocks the UI until a response is received or an error.
The problem :
I tried the same code for Marshmallow and Oreo device and the results were different.
For Marshmallow : Things moved in line with my expectation. :)
For Oreo (8.1.0) :
The very first API call works good enough after I open the App. However, the subsequent API calls after, cause the UI to block forever although an Error or Response is received from the Server(verified by logging and debugging).
However, on setting breakpoints(running in Debug mode) the App moves with much less trouble.
It seems the system is unable to exit the UI blocking loop although the condition is met.
The second behavior which was noticed is when I log a message in the UI blocking thread, the System is able to exit the loop and return from the Method though the API response is not logged.
Could someone help understand such inconsistency across these two flavors of Android and what could be the change introduced causing such a behavior for Oreo but not for Marshmallow?
Any insight would be extremely helpful.
It's more likely to be differences in the processor cache implementation in the two different hardware devices you're using. Probably not the JVM at all.
Memory consistency is a pretty complicated topic, I recommend checking out a tutorial like this for a more in-depth treatment. Also see this java memory model explainer for details on the guarantees that the JVM will provide, irrespective of your hardware.
I'll explain a hypothetical scenario in which the behavior you've observed could happen, without knowing the specific details of your chipset:
HYPOTHETICAL SCENARIO
Two threads: Your "UI thread" (let's say it's running on core 1), and the "background thread" (core 2). Your variable, completed, is assigned a single, fixed memory location at compile time (assume that we have dereferenced this, etc., and we've established what that location is). completed is represented by a single byte, initial value of "0".
The UI thread, on core 1, quickly reaches the busy-wait loop. The first time it tries to read completed, there is a "cache miss". Thus the request goes through the cache, and reads completed (along with the other 31 bytes in the cache line) out of main memory. Now that the cache line is in core 1's L1 cache, it reads the value, and it finds that it is "0". (Cores are not connected directly to main memory; they can only access it via their cache.) So the busy-wait continues; core 1 requests the same memory location, completed, again and again, but instead of a cache miss, L1 is now able to satisfy each request, and need no longer communicate with main memory.
Meanwhile, on core 2, the background thread is working to complete the API call. Eventually it finishes, and attempts to write a "1" to that same memory location, completed. Again, there is a cache miss, and the same sort of thing happens. Core 2 writes a "1" into appropriate location in its own L1 cache. But that cache line doesn't necessarily get written back to main memory yet. Even if it did, core 1 isn't referencing main memory anyway, so it wouldn't see the change. Core 2 then completes the thread, returns, and goes off to do work someplace else.
(By the time core 2 is assigned to a different process, its cache has probably been synchronized to main memory, and flushed. So, the "1" does make it back to main memory. Not that that makes any difference to core 1, which continues to run exclusively from its L1 cache.)
And things continue in this way, until something happens to suggest to core 1's cache that it is dirty, and it needs to refresh. As I mentioned in the comments, this could be a fence occurring as part of a System.out.println() call, debugger entry, etc. Naturally, if you had used a synchronized block, the compiler would've placed a fence in your own code.
TAKEAWAYS
...and that's why you always protect accesses to shared variables with a synchronized block! (So you don't have to spend days reading processor manuals, trying to understand the details of the memory model on the particular hardware you are using, just to share a byte of information between two threads.) A volatile keyword will also solve the problem, but see some of the links in the Jenkov article for scenarios in which this is insufficient.

App is quit after a certain time [duplicate]

I have an android app, which listens to a socket from the server and retrieves data in json format and save data in the database. Resource cursor adapter is used to display the data in a list. When the app is idle for 10 minutes or more, it is not reponding. Any solutions?
ANR occurs when the main thread is blocked for a few time. Specifically, 5 seconds in an Activity, 10 seconds in a BroadcastReceiver and 20 seconds in a Service. So, to avoid ANR, you need to ensure that you don't do something like these in you UI thread: reading or writing files, connecting the internet, operating databases and so on, which spend a lot of time. So, if you want to do things above, you may start a new thread to do that. Specifically, AsyncTask ThreadHandler and something like that.
I hope this will help you.
ANR occurs when Android detects the system is unable to respond to user input for more than a few seconds.
CursorWindow﹕ Window is full: requested allocation 396488 bytes,
free space 285853 bytes, window size 2097152 bytes
04-01 05:32:34.328 1598-1607/com.inxed W/CursorWrapperInner﹕
Cursor finalized without prior close()
you need to close the cursor.
ANR display if application cannot respond to the user input.According to the Google doc,you should not perform the work on the UI thread. I recommend you to perform network request or long running operation in worker thread instead of UI thread. for more this
It looks like your DB cursor its full. After saving data from the cursor, close it, set it to null and create a new one so no buffers are kept in memory.
this SO answer gives more information

Android app not responding (ANR)

I have an android app, which listens to a socket from the server and retrieves data in json format and save data in the database. Resource cursor adapter is used to display the data in a list. When the app is idle for 10 minutes or more, it is not reponding. Any solutions?
ANR occurs when the main thread is blocked for a few time. Specifically, 5 seconds in an Activity, 10 seconds in a BroadcastReceiver and 20 seconds in a Service. So, to avoid ANR, you need to ensure that you don't do something like these in you UI thread: reading or writing files, connecting the internet, operating databases and so on, which spend a lot of time. So, if you want to do things above, you may start a new thread to do that. Specifically, AsyncTask ThreadHandler and something like that.
I hope this will help you.
ANR occurs when Android detects the system is unable to respond to user input for more than a few seconds.
CursorWindow﹕ Window is full: requested allocation 396488 bytes,
free space 285853 bytes, window size 2097152 bytes
04-01 05:32:34.328 1598-1607/com.inxed W/CursorWrapperInner﹕
Cursor finalized without prior close()
you need to close the cursor.
ANR display if application cannot respond to the user input.According to the Google doc,you should not perform the work on the UI thread. I recommend you to perform network request or long running operation in worker thread instead of UI thread. for more this
It looks like your DB cursor its full. After saving data from the cursor, close it, set it to null and create a new one so no buffers are kept in memory.
this SO answer gives more information

Background server approach

I have built an Android chat application. It has a TCP server which is connected to via using a Socket.
I want the server connection to work in the background always - even if the app is not in foreground - and listen to data sent from the server.
For now I am using a while loop to checking if there is something new, but the OS close my thread when Android needs resources.
I have thought about using the readline() method in my thread instead of using the while loop because readline() is a blocking method.
Is this the right approach to take, which will lead to, prevention of the OS from killing my application?
Is there any way, like a custom broadcast receiver that will launch only when the incoming socket is available?
Thanks!
In short, Android can and will kill any applications that hog up resources in order to keep running. The onus is on you on how to handle the scenarios which can threaten your app to be killed.
I suggest looking at the service's life-cycle as found on the developer's site.
For a start, any application, be it service/activity, that hogs up too much, in this manner is considered... "rude" in the eyes of Android, and therefore, is prepared to be killed in this manner regardless!
For example, listen in the onLowMemory override method and act accordingly, such as saving data and what-nots.
What really, should be happening, is this, the service, spawns a thread to periodically listen for incoming connections in this manner,
while (!terminating){
Socket incomingClientSocket = ourServerSocket.accept();
// How you handle this part is up to you?
Thread.sleep(500); // Sleep for 500 ms
}
The terminating variable is a boolean and is the deciding variable that controls when to terminate the loop. Notice how the Thread.sleep method is used, to "calm down" the execution, if omitted, Android will put a cross-hair on the app and terminate it, in other words, be polite to system resources.
Hint: Extend the Thread class, to hold the functionality of handling incoming connections via the accept() method.
When the incomingClientSocket becomes non-null, then another thread is created in which it opens the input/output stream of the incomingClientSocket and read/write to it using binary fashion.
Do not use the readline method as that is an indication of poor design and assuming the data is text-ual, because one incoming packet to the client could be for example, 720bytes, the next packet coming in after that, could well be 564 bytes, that is the nature of TCP/IP.
You need to come up with a more reliable way of establishing boundaries for the data transmission, for example, a begin and end marker, and let the server read the incoming data and distinguish the byte stream that composes of a begin and end markers, once both are present, then extract the real data in-between the markers and act on it accordingly.
You could for instance, say, upon incomingClientSocket that actually becomes non-null, send a broadcast to your activity to act on it, and let the activity, take that socket, and open the connection and read/write to/from the input/output streams associated with the socket.

Complicated android multithreading problem, looking for some guidance

New to stackoverflow, been very helpful searching, but alas the time has come to ask a question.
I am trying to use an android 2.2 single core phone to do some research. I have implemented an algorithm that does quite a few calculations and produces a lot of data. These data must be processed, and the solution presented back to a client app within a 40ms time frame, then process again with new state data coming from the client. Also, the result of the calculations must be stored to the SD card as a data log. So being new to multithreading and android both, what should I use to do the following in my app: (As a side note, this phone, when in research mode is not intended to be used as a phone, phone will be in airplane mode with wireless off, and all apps that can be turned off will be turned off, and there is no need for UI display or interaction once it is up and running...)
need to process packets coming in over adb on serial port, these packets are state data that the program needs to perform its calcs on. These packets will be coming every 40ms, so I planned on using their arrival to trigger the start of the processing.
need to know if the algorithm is taking longer than 40ms and cancel it if so and send a message back on the serial port that it overran.
the calculation results need to be sent back over the serial connection via tcp and adb
The calculation intermediate data need to be recorded to SD. This can be quite a lot of data, on order of 140k, every 40ms.
So I have had trouble getting all the pieces together. I can't get my head around how a single core is going to keep up with all this going on at once?
So here is my thought, please tell me if I am headed in the right path. I am not asking for you to solve my problem, only any advice on how to break this beast down:
So i start a service to process the tcp packets coming in from the client
Use a service bound to the main worker thread to handle writes to the SD card
So assuming this setup, can i make the algorithm part of this somewhat deterministic so that it always runs if it gets a new tcp packet, and preempts the SD write going on in the background?
Argh...should have picked something simpler for my first program
Thanks.
Yes I think you are right, that it would be better to pick something easier for your first App ;)
But as far as I understand what you are trying to do, I don't think, that you need asynchronous multiprocessing. You get some data want to process it and pass a result. I think a HandlerThread is exactly what you are looking for. It is able to recieve Messages
with data inside. You send them to the Handler and process them in an overridden handleMessage(Message m) method. So everytime you recive a Message you could just log the Time
and see if the last one is older than your limit. If it is, you could just throw the Message or the whole queue, or send a Message to your serial-port inicating the overflow.
This could be implemented as you suggest in a Service. Another HandlerThread can be started with Thread.PRIORITY_BACKGROUND to write everything to SD.
You can send Messages even very compfortable if you apply a Messenger to the Handlers

Categories

Resources