workaround for slow booting Samsung phones

pull/28/head
geeksville 2020-05-11 13:12:44 -07:00
rodzic 33265c7c2e
commit 407a38594f
4 zmienionych plików z 61 dodań i 20 usunięć

Wyświetl plik

@ -146,5 +146,11 @@ dependencies {
implementation('com.journeyapps:zxing-android-embedded:4.1.0') { transitive = false }
implementation 'com.google.zxing:core:3.4.0'
def work_version = "2.3.4"
// Work Request - used to delay boot event handling
// implementation "androidx.work:work-runtime:$work_version"
implementation "androidx.work:work-runtime-ktx:$work_version"
implementation project(':geeksville-androidlib')
}

Wyświetl plik

@ -674,10 +674,10 @@ class MainActivity : AppCompatActivity(), Logging,
if (model.meshService != null)
Exceptions.reportError("meshService was supposed to be null, ignoring (but reporting a bug)")
MeshService.startService(this)?.let { intent ->
// ALSO bind so we can use the api
mesh.connect(this, intent, Context.BIND_AUTO_CREATE + Context.BIND_ABOVE_CLIENT)
}
MeshService.startService(this) // Start the service so it stays running even after we unbind
// ALSO bind so we can use the api
mesh.connect(this, MeshService.intent, Context.BIND_AUTO_CREATE + Context.BIND_ABOVE_CLIENT)
}
private fun unbindMeshService() {

Wyświetl plik

@ -8,8 +8,7 @@ import com.geeksville.android.Logging
class BootCompleteReceiver : BroadcastReceiver(), Logging {
override fun onReceive(mContext: Context, intent: Intent) {
// FIXME - start listening for bluetooth messages from our device
info("Received boot complete announcement, starting mesh service")
MeshService.startService(mContext)
// start listening for bluetooth messages from our device
MeshService.startLater(mContext)
}
}

Wyświetl plik

@ -16,6 +16,7 @@ import androidx.annotation.UiThread
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationCompat.PRIORITY_MIN
import androidx.core.content.edit
import androidx.work.*
import com.geeksville.analytics.DataPair
import com.geeksville.android.GeeksvilleApplication
import com.geeksville.android.Logging
@ -33,6 +34,7 @@ import kotlinx.coroutines.*
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonConfiguration
import java.util.concurrent.TimeUnit
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext
@ -67,33 +69,67 @@ class MeshService : Service(), Logging {
class NodeNumNotFoundException(id: Int) : Exception("NodeNum not found $id")
class NotInMeshException() : Exception("We are not yet in a mesh")
/// Helper function to start running our service, returns the intent used to reach it
/// or null if the service could not be started (no bluetooth or no bonded device set)
fun startService(context: Context): Intent? {
/** A little helper that just calls startService
*/
class ServiceStarter(appContext: Context, workerParams: WorkerParameters) :
Worker(appContext, workerParams) {
override fun doWork(): Result = try {
startService(this.applicationContext)
// Indicate whether the task finished successfully with the Result
Result.success()
} catch (ex: Exception) {
errormsg("failure starting service, will retry", ex)
Result.retry()
}
}
/**
* Just after boot the android OS is super busy, so if we call startForegroundService then, our
* thread might be stalled long enough to expose this google/samsung bug:
* https://issuetracker.google.com/issues/76112072#comment56
*/
fun startLater(context: Context) {
info("Received boot complete announcement, starting mesh service in one minute")
val delayRequest = OneTimeWorkRequestBuilder<ServiceStarter>()
.setInitialDelay(1, TimeUnit.MINUTES)
.setBackoffCriteria(BackoffPolicy.EXPONENTIAL, 1, TimeUnit.MINUTES)
.addTag("startLater")
.build()
WorkManager.getInstance(context).enqueue(delayRequest)
}
val intent = Intent().apply {
setClassName(
"com.geeksville.mesh",
"com.geeksville.mesh.service.MeshService"
)
}
/// Helper function to start running our service
fun startService(context: Context) {
// bind to our service using the same mechanism an external client would use (for testing coverage)
// The following would work for us, but not external users
//val intent = Intent(this, MeshService::class.java)
//intent.action = IMeshService::class.java.name
val intent = Intent()
intent.setClassName(
"com.geeksville.mesh",
"com.geeksville.mesh.service.MeshService"
)
// Before binding we want to explicitly create - so the service stays alive forever (so it can keep
// listening for the bluetooth packets arriving from the radio. And when they arrive forward them
// to Signal or whatever.
logAssert(
info("Trying to start service")
val compName =
(if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// we have some samsung devices failing with https://issuetracker.google.com/issues/76112072#comment56 not sure what the fix is yet
context.startForegroundService(intent)
} else {
context.startService(intent)
}) != null
)
})
return intent
if (compName == null)
throw Exception("Failed to start service")
}
}