Android: C++ thread not waking up if screen-locked or in background. Works fine when app is in use
Asked Answered
S

1

4

In our Android app, we have UI component and core C++11 module. A thread is running based on std::chrono::system_clock::time_point, such as below:

while(this->m_ConditionVariable.wait_until(lock, this->m_Object.to_time_point())
      == std::cv_status::no_timeout)
{
  // ... handle any notify() or arbitrary sleep breaks
}

Execute();  // <--- not being called consistently 

Now, we are testing with 1 minute time_point. If the app is in use, then the Execute() is invoked as expected. However, if the app is moved to background or if even the screen is locked, then the Execute()-s behavior is not consistent.
Sometimes, it may work properly every minute for 15 mins and after that it will be invoked after 2 minutes or 3 minutes or 10 minutes, instead of fixed 1 minute. Using debugs, we checked that, the time_point supplied is proper.

Suppose if we run the app in debug mode (using Android Studio) then it works fine even in background and screen locked mode.

Does Android have any threading priority for the app running in background?


Update 1: Basically the background thread is collecting location information. I came across below question, which suggests that in Android, when the phone is locked, the thread execution is halted. Am I stuck to that problem?
App seems to stop working when the screen goes to sleep

Update 2: With partial Wake lock, it works fine. But not sure if that's a good solution. If that's the only way, then I would appreciate strategy for how to use it optimally.

Update 3: If I replace wait() with smaller sleep(), then it works fine even without any Android wake lock. However we are yet to do regressive testing on it.

Sulfate answered 29/11, 2016 at 12:7 Comment(0)
R
5

When the device is idle, the CPU is stopped and any thread running is paused (C++ or Java). If it wakes up for any reason your C++ thread will start working again, hence the random behavior: Other apps or services might wake-up the device every now and then.

Adding a partial wake lock works in your case but that will prevent the CPU from going idle, which will cause some battery drain. If you don't care you can use this approach, if battery live is an issue, you can use the Java alarm API to wake up the device on a regular basis. Then the java API can call the C++ code through JNI.

Android documentation for repeated alarms: https://developer.android.com/training/scheduling/alarms.html

For the update 3, using a small sleep rather than wait(), I suspect android is not going in idle mode while a thread is running, maybe it waits for a small timeout without any thread active before it goes idle. This approach will have the same effect on the battery drain than the wake lock.

Rabato answered 6/12, 2016 at 11:26 Comment(2)
Do you have any idea, why sleep() things works. i.e. if I put sleep(1), then it will come out of it after 1 second. Actually, we tried Java Alarm API. At high level, it seems that this API affects to the main GUI thread. C++ thread remained unaffected & still couldn't wake-up. It will be beneficial, if you can put some more info on this API & any relation it has with C++ threads.Sulfate
I replied by editing my comment. It's just a guess though. For the Java Alarm API, I guess you'll need to call it from a service thread for it not to be linked with the GUI.Rabato

© 2022 - 2024 — McMap. All rights reserved.