Signal-Android/app/src/main/java/org/thoughtcrime/securesms/jobs/ForegroundUtil.kt

75 wiersze
2.5 KiB
Kotlin

package org.thoughtcrime.securesms.jobs
import android.app.AlarmManager
import android.app.PendingIntent
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.os.Build
import android.os.SystemClock
import org.signal.core.util.PendingIntentFlags
import org.signal.core.util.logging.Log
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
import org.thoughtcrime.securesms.service.GenericForegroundService
import org.thoughtcrime.securesms.service.NotificationController
import org.thoughtcrime.securesms.util.ServiceUtil
import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit
import java.util.concurrent.locks.ReentrantLock
import kotlin.concurrent.withLock
/**
* Helps start foreground services from the background.
*/
object ForegroundUtil {
private val TAG = Log.tag(ForegroundUtil::class.java)
private val updateMutex: ReentrantLock = ReentrantLock()
private var activeLatch: CountDownLatch? = null
@Throws(GenericForegroundService.UnableToStartException::class)
@JvmStatic
fun requireForegroundTask(context: Context, task: String): NotificationController {
val alarmManager = ServiceUtil.getAlarmManager(context)
if (Build.VERSION.SDK_INT < 31 || ApplicationDependencies.getAppForegroundObserver().isForegrounded || !alarmManager.canScheduleExactAlarms()) {
return GenericForegroundService.startForegroundTask(context, task)
}
val latch: CountDownLatch? = updateMutex.withLock {
if (activeLatch == null) {
if (alarmManager.canScheduleExactAlarms()) {
activeLatch = CountDownLatch(1)
val pendingIntent = PendingIntent.getBroadcast(context, 0, Intent(context, Receiver::class.java), PendingIntentFlags.mutable())
alarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + 1000, pendingIntent)
} else {
Log.w(TAG, "Unable to schedule alarm")
}
}
activeLatch
}
if (latch != null) {
try {
if (!latch.await(1, TimeUnit.MINUTES)) {
Log.w(TAG, "Time ran out waiting for foreground")
}
} catch (e: InterruptedException) {
Log.w(TAG, "Interrupted while waiting for foreground")
}
}
return GenericForegroundService.startForegroundTask(context, task)
}
class Receiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
updateMutex.withLock {
activeLatch?.countDown()
activeLatch = null
}
}
}
}