Fix foreground service start/stop race.

This commit is contained in:
Clark
2023-06-14 14:42:08 -04:00
committed by GitHub
parent 62f62d89c5
commit 08c661bb14
3 changed files with 29 additions and 8 deletions

View File

@@ -47,7 +47,6 @@ class FcmFetchForegroundService : Service() {
return if (intent != null && intent.getBooleanExtra(KEY_STOP_SELF, false)) {
stopForeground(true)
stopSelf()
FcmFetchManager.onForegroundFetchServiceStop()
START_NOT_STICKY
} else {
START_STICKY
@@ -70,6 +69,7 @@ class FcmFetchForegroundService : Service() {
override fun onDestroy() {
Log.i(TAG, "onDestroy()")
FcmFetchManager.onDestroyForegroundFetchService()
}
override fun onBind(intent: Intent?): IBinder? {

View File

@@ -42,6 +42,9 @@ object FcmFetchManager {
@Volatile
private var stoppingForeground = false
@Volatile
private var startForegroundOnDestroy = false
/**
* @return True if a service was successfully started, otherwise false.
*/
@@ -52,8 +55,13 @@ object FcmFetchManager {
if (foreground) {
Log.i(TAG, "Starting in the foreground.")
if (!startedForeground) {
ForegroundServiceUtil.startWhenCapableOrThrow(context, Intent(context, FcmFetchForegroundService::class.java), MAX_BLOCKING_TIME_MS)
startedForeground = true
if (!stoppingForeground) {
ForegroundServiceUtil.startWhenCapableOrThrow(context, Intent(context, FcmFetchForegroundService::class.java), MAX_BLOCKING_TIME_MS)
startedForeground = true
} else {
Log.w(TAG, "Foreground service currently stopping, enqueuing a start after destroy")
startForegroundOnDestroy = true
}
} else {
Log.i(TAG, "Already started foreground service")
}
@@ -108,6 +116,7 @@ object FcmFetchManager {
synchronized(this) {
if (startedForeground || stoppingForeground) {
if (stoppingForeground) {
startForegroundOnDestroy = true
Log.i(TAG, "Legacy fallback: foreground service is stopping, but trying to run in background anyways.")
}
val performedReplace = EXECUTOR.enqueue { fetch(context) }
@@ -142,10 +151,17 @@ object FcmFetchManager {
}
}
fun onForegroundFetchServiceStop() {
fun onDestroyForegroundFetchService() {
synchronized(this) {
stoppingForeground = false
Log.i(TAG, "Foreground service stopped successfully")
if (startForegroundOnDestroy) {
startForegroundOnDestroy = false
try {
enqueue(ApplicationDependencies.getApplication(), true)
} catch (e: Exception) {
Log.e(TAG, "Failed to restart foreground service after onDestroy")
}
}
}
}
}

View File

@@ -79,9 +79,10 @@ public class FcmReceiveService extends FirebaseMessagingService {
private static void handleReceivedNotification(Context context, @Nullable RemoteMessage remoteMessage) {
boolean enqueueSuccessful = false;
boolean highPriority = false;
try {
boolean highPriority = remoteMessage != null && remoteMessage.getPriority() == RemoteMessage.PRIORITY_HIGH;
highPriority = remoteMessage != null && remoteMessage.getPriority() == RemoteMessage.PRIORITY_HIGH;
long timeSinceLastRefresh = System.currentTimeMillis() - SignalStore.misc().getLastFcmForegroundServiceTime();
Log.d(TAG, String.format(Locale.US, "[handleReceivedNotification] API: %s, FeatureFlag: %s, RemoteMessagePriority: %s, TimeSinceLastRefresh: %s ms", Build.VERSION.SDK_INT, FeatureFlags.useFcmForegroundService(), remoteMessage != null ? remoteMessage.getPriority() : "n/a", timeSinceLastRefresh));
@@ -101,7 +102,11 @@ public class FcmReceiveService extends FirebaseMessagingService {
}
if (!enqueueSuccessful) {
Log.w(TAG, "Unable to start service. Falling back to legacy approach.");
if (highPriority) {
Log.w(TAG, "Unable to start service though high priority push. Falling back to legacy approach.");
} else {
Log.d(TAG, "Low priority push, trying legacy fallback");
}
FcmFetchManager.tryLegacyFallback(context);
}
}