From 4c63428b71c7367a3194f70e259cd45b6be79684 Mon Sep 17 00:00:00 2001 From: Greyson Parrelli Date: Mon, 8 Oct 2018 17:44:23 -0700 Subject: [PATCH] Ensure GenericForegroundService is started with startForegroundService. If we don't, we run the risk of the app crashing if the service is started in the background. --- .../service/GenericForegroundService.java | 62 ++++++++++++------- 1 file changed, 41 insertions(+), 21 deletions(-) diff --git a/src/org/thoughtcrime/securesms/service/GenericForegroundService.java b/src/org/thoughtcrime/securesms/service/GenericForegroundService.java index e963a72cab..f6ea036cd1 100644 --- a/src/org/thoughtcrime/securesms/service/GenericForegroundService.java +++ b/src/org/thoughtcrime/securesms/service/GenericForegroundService.java @@ -9,15 +9,18 @@ import android.os.IBinder; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v4.app.NotificationCompat; +import android.support.v4.content.ContextCompat; +import android.util.Log; import org.thoughtcrime.securesms.ConversationListActivity; import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.notifications.NotificationChannels; - -import java.util.concurrent.atomic.AtomicInteger; +import org.whispersystems.libsignal.util.guava.Preconditions; public class GenericForegroundService extends Service { + private static final String TAG = GenericForegroundService.class.getSimpleName(); + private static final int NOTIFICATION_ID = 827353982; private static final String EXTRA_TITLE = "extra_title"; private static final String EXTRA_CHANNEL_ID = "extra_channel_id"; @@ -25,7 +28,9 @@ public class GenericForegroundService extends Service { private static final String ACTION_START = "start"; private static final String ACTION_STOP = "stop"; - private final AtomicInteger foregroundCount = new AtomicInteger(0); + private int foregroundCount; + private String activeTitle; + private String activeChannelId; @Override public void onCreate() { @@ -34,36 +39,51 @@ public class GenericForegroundService extends Service { @Override public int onStartCommand(Intent intent, int flags, int startId) { - if (intent != null && ACTION_START.equals(intent.getAction())) handleStart(intent); - else if (intent != null && ACTION_STOP.equals(intent.getAction())) handleStop(); + synchronized (GenericForegroundService.class) { + if (intent != null && ACTION_START.equals(intent.getAction())) handleStart(intent); + else if (intent != null && ACTION_STOP.equals(intent.getAction())) handleStop(); + else throw new IllegalStateException("Action needs to be START or STOP."); - return START_NOT_STICKY; + return START_NOT_STICKY; + } } private void handleStart(@NonNull Intent intent) { - String title = intent.getStringExtra(EXTRA_TITLE); - String channelId = intent.getStringExtra(EXTRA_CHANNEL_ID); - - assert title != null; - assert channelId != null; - - if (foregroundCount.getAndIncrement() == 0) { - startForeground(NOTIFICATION_ID, new NotificationCompat.Builder(this, channelId) - .setSmallIcon(R.drawable.ic_signal_grey_24dp) - .setContentTitle(title) - .setContentIntent(PendingIntent.getActivity(this, 0, new Intent(this, ConversationListActivity.class), 0)) - .build()); + String title = Preconditions.checkNotNull(intent.getStringExtra(EXTRA_TITLE)); + String channelId = Preconditions.checkNotNull(intent.getStringExtra(EXTRA_CHANNEL_ID)); + + foregroundCount++; + + if (foregroundCount == 1) { + Log.d(TAG, "First request. Title: " + title + " ChannelId: " + channelId); + activeTitle = title; + activeChannelId = channelId; } + + postObligatoryForegroundNotification(activeTitle, activeChannelId); } private void handleStop() { - if (foregroundCount.decrementAndGet() == 0) { + postObligatoryForegroundNotification(activeTitle, activeChannelId); + + foregroundCount--; + + if (foregroundCount == 0) { + Log.d(TAG, "Last request. Ending foreground service."); stopForeground(true); stopSelf(); } } + private void postObligatoryForegroundNotification(String title, String channelId) { + startForeground(NOTIFICATION_ID, new NotificationCompat.Builder(this, channelId) + .setSmallIcon(R.drawable.ic_signal_grey_24dp) + .setContentTitle(title) + .setContentIntent(PendingIntent.getActivity(this, 0, new Intent(this, ConversationListActivity.class), 0)) + .build()); + } + @Nullable @Override public IBinder onBind(Intent intent) { @@ -80,13 +100,13 @@ public class GenericForegroundService extends Service { intent.putExtra(EXTRA_TITLE, task); intent.putExtra(EXTRA_CHANNEL_ID, channelId); - context.startService(intent); + ContextCompat.startForegroundService(context, intent); } public static void stopForegroundTask(@NonNull Context context) { Intent intent = new Intent(context, GenericForegroundService.class); intent.setAction(ACTION_STOP); - context.startService(intent); + ContextCompat.startForegroundService(context, intent); } }