Skip to content

Commit 69f99c9

Browse files
Nightsd01jkasten2
authored andcommitted
Fix Null Pointer Concurrency Issue
Fixes #513, where in very rare cases a concurrency issue could occur where shared preferences was accessed during a buffer flush before the object was actually initialized • Fixed by adding synchronization to all accesses/initialization of this object
1 parent ac09747 commit 69f99c9

File tree

1 file changed

+40
-33
lines changed

1 file changed

+40
-33
lines changed

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

Lines changed: 40 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ class OneSignalPrefs {
7575
static HashMap<String, HashMap<String, Object>> prefsToApply;
7676
public static WritePrefHandlerThread prefsHandler;
7777

78+
static final Object synchronizer = new Object();
79+
7880
static {
7981
initializePool();
8082
}
@@ -113,11 +115,11 @@ public void run() {
113115
}
114116

115117
private void flushBufferToDisk() {
116-
for (String pref : prefsToApply.keySet()) {
117-
SharedPreferences prefsToWrite = getSharedPrefsByName(pref);
118-
SharedPreferences.Editor editor = prefsToWrite.edit();
119-
HashMap<String, Object> prefHash = prefsToApply.get(pref);
120-
synchronized (prefHash) {
118+
synchronized(synchronizer) {
119+
for (String pref : prefsToApply.keySet()) {
120+
SharedPreferences prefsToWrite = getSharedPrefsByName(pref);
121+
SharedPreferences.Editor editor = prefsToWrite.edit();
122+
HashMap<String, Object> prefHash = prefsToApply.get(pref);
121123
for (String key : prefHash.keySet()) {
122124
Object value = prefHash.get(key);
123125
if (value instanceof String)
@@ -130,20 +132,23 @@ else if (value instanceof Long)
130132
editor.putLong(key, (Long)value);
131133
}
132134
prefHash.clear();
135+
136+
editor.apply();
133137
}
134-
editor.apply();
135-
}
136138

137-
lastSyncTime = System.currentTimeMillis();
139+
lastSyncTime = System.currentTimeMillis();
140+
}
138141
}
139142
}
140143

141144
public static void initializePool() {
142-
prefsToApply = new HashMap<>();
143-
prefsToApply.put(PREFS_ONESIGNAL, new HashMap<String, Object>());
144-
prefsToApply.put(PREFS_PLAYER_PURCHASES, new HashMap<String, Object>());
145+
synchronized(synchronizer) {
146+
prefsToApply = new HashMap<>();
147+
prefsToApply.put(PREFS_ONESIGNAL, new HashMap<String, Object>());
148+
prefsToApply.put(PREFS_PLAYER_PURCHASES, new HashMap<String, Object>());
145149

146-
prefsHandler = new WritePrefHandlerThread();
150+
prefsHandler = new WritePrefHandlerThread();
151+
}
147152
}
148153

149154
static void saveString(final String prefsName, final String key, final String value) {
@@ -163,11 +168,12 @@ static void saveLong(String prefsName, String key, long value) {
163168
}
164169

165170
static private void save(String prefsName, String key, Object value) {
166-
HashMap<String, Object> pref = prefsToApply.get(prefsName);
167-
synchronized (pref) {
171+
synchronized(synchronizer) {
172+
HashMap<String, Object> pref = prefsToApply.get(prefsName);
168173
pref.put(key, value);
174+
175+
prefsHandler.startDelayedWrite();
169176
}
170-
prefsHandler.startDelayedWrite();
171177
}
172178

173179
static String getString(String prefsName, String key, String defValue) {
@@ -188,34 +194,35 @@ static long getLong(String prefsName, String key, long defValue) {
188194

189195
// If type == Object then this is a contains check
190196
private static Object get(String prefsName, String key, Class type, Object defValue) {
191-
HashMap<String, Object> pref = prefsToApply.get(prefsName);
197+
synchronized(synchronizer) {
198+
HashMap<String, Object> pref = prefsToApply.get(prefsName);
192199

193-
synchronized (pref) {
194200
if (type.equals(Object.class) && pref.containsKey(key))
195201
return true;
196202

197203
Object cachedValue = pref.get(key);
198204
if (cachedValue != null || pref.containsKey(key))
199205
return cachedValue;
200-
}
201206

202-
SharedPreferences prefs = getSharedPrefsByName(prefsName);
203-
if (prefs != null ) {
204-
if (type.equals(String.class))
205-
return prefs.getString(key, (String)defValue);
206-
else if (type.equals(Boolean.class))
207-
return prefs.getBoolean(key, (Boolean)defValue);
208-
else if (type.equals(Integer.class))
209-
return prefs.getInt(key, (Integer)defValue);
210-
else if (type.equals(Long.class))
211-
return prefs.getLong(key, (Long)defValue);
212-
else if (type.equals(Object.class))
213-
return prefs.contains(key);
214207

215-
return null;
216-
}
208+
SharedPreferences prefs = getSharedPrefsByName(prefsName);
209+
if (prefs != null ) {
210+
if (type.equals(String.class))
211+
return prefs.getString(key, (String)defValue);
212+
else if (type.equals(Boolean.class))
213+
return prefs.getBoolean(key, (Boolean)defValue);
214+
else if (type.equals(Integer.class))
215+
return prefs.getInt(key, (Integer)defValue);
216+
else if (type.equals(Long.class))
217+
return prefs.getLong(key, (Long)defValue);
218+
else if (type.equals(Object.class))
219+
return prefs.contains(key);
220+
221+
return null;
222+
}
217223

218-
return defValue;
224+
return defValue;
225+
}
219226
}
220227

221228
private static synchronized SharedPreferences getSharedPrefsByName(String prefsName) {

0 commit comments

Comments
 (0)