From ef581d2b048e69e2150d8b1a14c2bb042fe10c39 Mon Sep 17 00:00:00 2001 From: Josh Kasten Date: Tue, 23 Apr 2024 16:15:20 -0400 Subject: [PATCH 1/2] In OSTaskController switch to LinkedBlockingQueue Android 12 has a bug where ConcurrentLinkedQueue.poll() can return the wrong value. This is rare but results in a few crash reports in OSTaskController, see issue #1761. To workaround this issue we switched to LinkedBlockingQueue. --- .../src/main/java/com/onesignal/OSTaskController.java | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/OneSignalSDK/onesignal/src/main/java/com/onesignal/OSTaskController.java b/OneSignalSDK/onesignal/src/main/java/com/onesignal/OSTaskController.java index 6de9599f00..cef31f1c06 100644 --- a/OneSignalSDK/onesignal/src/main/java/com/onesignal/OSTaskController.java +++ b/OneSignalSDK/onesignal/src/main/java/com/onesignal/OSTaskController.java @@ -2,11 +2,10 @@ import androidx.annotation.NonNull; -import java.util.Arrays; -import java.util.HashSet; -import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.Queue; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.ThreadFactory; import java.util.concurrent.atomic.AtomicLong; @@ -15,8 +14,8 @@ class OSTaskController { static final String OS_PENDING_EXECUTOR = "OS_PENDING_EXECUTOR_"; - // The concurrent queue in which we pin pending tasks upon finishing initialization - private final ConcurrentLinkedQueue taskQueueWaitingForInit = new ConcurrentLinkedQueue<>(); + // The queue in which we pin pending tasks upon finishing initialization + private final Queue taskQueueWaitingForInit = new LinkedBlockingQueue<>(); private final AtomicLong lastTaskId = new AtomicLong(); private ExecutorService pendingTaskExecutor; @@ -105,7 +104,7 @@ private void onTaskRan(long taskId) { } } - ConcurrentLinkedQueue getTaskQueueWaitingForInit() { + Queue getTaskQueueWaitingForInit() { synchronized (taskQueueWaitingForInit) { return taskQueueWaitingForInit; } From 93676f3e4b538ec3aa1853b7d618238c3292be4f Mon Sep 17 00:00:00 2001 From: Josh Kasten Date: Tue, 23 Apr 2024 16:45:12 -0400 Subject: [PATCH 2/2] ConcurrentLinkedQueue to LinkedBlockingQueue Switch renaming usages of ConcurrentLinkedQueue to LinkedBlockingQueue to avoid a possible crash on Android 12, due to a bug it has with it. While we haven't gotten any crash reports of these usages they could happen. See previous commit, ef581d2b048e69e2150d8b1a14c2bb042fe10c39, for more details. --- .../main/java/com/onesignal/UserStateSynchronizer.java | 8 ++++---- .../java/com/onesignal/OneSignalPackagePrivateHelper.java | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/OneSignalSDK/onesignal/src/main/java/com/onesignal/UserStateSynchronizer.java b/OneSignalSDK/onesignal/src/main/java/com/onesignal/UserStateSynchronizer.java index 80e5ecf93a..2837f6e90b 100644 --- a/OneSignalSDK/onesignal/src/main/java/com/onesignal/UserStateSynchronizer.java +++ b/OneSignalSDK/onesignal/src/main/java/com/onesignal/UserStateSynchronizer.java @@ -18,7 +18,7 @@ import java.util.HashMap; import java.util.Queue; import java.util.Set; -import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.atomic.AtomicBoolean; import static com.onesignal.OSInAppMessageController.IN_APP_MESSAGES_JSON_KEY; @@ -93,9 +93,9 @@ String getRegistrationId() { // Maintain a list of handlers so that if the user calls // sendTags() multiple times it will call each callback - final private Queue sendTagsHandlers = new ConcurrentLinkedQueue<>(); - final private Queue externalUserIdUpdateHandlers = new ConcurrentLinkedQueue<>(); - final private Queue deviceInfoCompletionHandler = new ConcurrentLinkedQueue<>(); + final private Queue sendTagsHandlers = new LinkedBlockingQueue<>(); + final private Queue externalUserIdUpdateHandlers = new LinkedBlockingQueue<>(); + final private Queue deviceInfoCompletionHandler = new LinkedBlockingQueue<>(); boolean hasQueuedHandlers() { return externalUserIdUpdateHandlers.size() > 0; diff --git a/OneSignalSDK/unittest/src/test/java/com/onesignal/OneSignalPackagePrivateHelper.java b/OneSignalSDK/unittest/src/test/java/com/onesignal/OneSignalPackagePrivateHelper.java index c9463c3984..ea1cfbc105 100644 --- a/OneSignalSDK/unittest/src/test/java/com/onesignal/OneSignalPackagePrivateHelper.java +++ b/OneSignalSDK/unittest/src/test/java/com/onesignal/OneSignalPackagePrivateHelper.java @@ -22,8 +22,8 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.Queue; import java.util.Set; -import java.util.concurrent.ConcurrentLinkedQueue; import static com.test.onesignal.TestHelpers.threadAndTaskWait; import static org.robolectric.Shadows.shadowOf; @@ -295,7 +295,7 @@ public static DelayedConsentInitializationParameters OneSignal_delayedInitParams return OneSignal.getDelayedInitParams(); } - public static ConcurrentLinkedQueue OneSignal_taskQueueWaitingForInit() { + public static Queue OneSignal_taskQueueWaitingForInit() { return OneSignal.getTaskRemoteController().getTaskQueueWaitingForInit(); }