Skip to content

Commit fa33217

Browse files
committed
make timeFocusedAtMs thread safe
Fixes rare cases where timeFocusedAtMs can become null right after the null check in getTimeFocusedElapsed(). We have seen crashes in the wild so it not just theoretical.
1 parent 33e3173 commit fa33217

File tree

1 file changed

+25
-14
lines changed

1 file changed

+25
-14
lines changed

OneSignalSDK/onesignal/src/main/java/com/onesignal/FocusTimeController.java

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ class FocusTimeController {
2828
// Only present if app is currently in focus.
2929
private Long timeFocusedAtMs;
3030

31+
private Object timeFocusedAtMsLock = new Object();
32+
3133
private OSFocusTimeProcessorFactory processorFactory;
3234
private OSLogger logger;
3335

@@ -42,13 +44,17 @@ private enum FocusEventType {
4244
}
4345

4446
void appForegrounded() {
45-
timeFocusedAtMs = OneSignal.getTime().getElapsedRealtime();
46-
logger.debug("Application foregrounded focus time: " + timeFocusedAtMs);
47+
synchronized (timeFocusedAtMsLock) {
48+
timeFocusedAtMs = OneSignal.getTime().getElapsedRealtime();
49+
logger.debug("Application foregrounded focus time: " + timeFocusedAtMs);
50+
}
4751
}
4852

4953
void appStopped() {
5054
Long timeElapsed = getTimeFocusedElapsed();
51-
logger.debug("Application stopped focus time: " + timeFocusedAtMs + " timeElapsed: " + timeElapsed);
55+
synchronized (timeFocusedAtMsLock) {
56+
logger.debug("Application stopped focus time: " + timeFocusedAtMs + " timeElapsed: " + timeElapsed);
57+
}
5258

5359
if (timeElapsed == null)
5460
return;
@@ -58,9 +64,11 @@ void appStopped() {
5864
}
5965

6066
void appBackgrounded() {
61-
logger.debug("Application backgrounded focus time: " + timeFocusedAtMs);
62-
processorFactory.getTimeProcessorSaved().sendUnsentTimeNow();
63-
timeFocusedAtMs = null;
67+
synchronized (timeFocusedAtMsLock) {
68+
logger.debug("Application backgrounded focus time: " + timeFocusedAtMs);
69+
processorFactory.getTimeProcessorSaved().sendUnsentTimeNow();
70+
timeFocusedAtMs = null;
71+
}
6472
}
6573

6674
void doBlockingBackgroundSyncOfUnsentTime() {
@@ -91,16 +99,19 @@ private boolean giveProcessorsValidFocusTime(@NonNull List<OSInfluence> influenc
9199
// Get time past since app was put into focus.
92100
// Will be null if time is invalid or 0
93101
private @Nullable Long getTimeFocusedElapsed() {
94-
// timeFocusedAtMs is cleared when the app goes into the background so we don't have a focus time
95-
if (timeFocusedAtMs == null)
96-
return null;
102+
synchronized (timeFocusedAtMsLock) {
103+
// timeFocusedAtMs is cleared when the app goes into the background so we don't have a focus time
104+
if (timeFocusedAtMs == null)
105+
return null;
106+
107+
long timeElapsed = (long) (((OneSignal.getTime().getElapsedRealtime() - timeFocusedAtMs) / 1_000d) + 0.5d);
97108

98-
long timeElapsed = (long)(((OneSignal.getTime().getElapsedRealtime() - timeFocusedAtMs) / 1_000d) + 0.5d);
99109

100-
// Time is invalid if below 1 or over a day
101-
if (timeElapsed < 1 || timeElapsed > 86_400)
102-
return null;
103-
return timeElapsed;
110+
// Time is invalid if below 1 or over a day
111+
if (timeElapsed < 1 || timeElapsed > 86_400)
112+
return null;
113+
return timeElapsed;
114+
}
104115
}
105116

106117
static class FocusTimeProcessorUnattributed extends FocusTimeProcessorBase {

0 commit comments

Comments
 (0)