Skip to content

Commit 2dd41ce

Browse files
authored
Synchronize old and new heartbeats (#3177)
* synchronize heartbeats * update * gJF * update * update * make synchornized * update * update
1 parent feb69dd commit 2dd41ce

File tree

7 files changed

+195
-239
lines changed

7 files changed

+195
-239
lines changed

firebase-common/src/main/java/com/google/firebase/FirebaseCommonRegistrar.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
import com.google.firebase.components.Component;
2121
import com.google.firebase.components.ComponentRegistrar;
2222
import com.google.firebase.heartbeatinfo.DefaultHeartBeatController;
23-
import com.google.firebase.heartbeatinfo.DefaultHeartBeatInfo;
2423
import com.google.firebase.platforminfo.DefaultUserAgentPublisher;
2524
import com.google.firebase.platforminfo.KotlinDetector;
2625
import com.google.firebase.platforminfo.LibraryVersionComponent;
@@ -44,7 +43,6 @@ public class FirebaseCommonRegistrar implements ComponentRegistrar {
4443
public List<Component<?>> getComponents() {
4544
List<Component<?>> result = new ArrayList<>();
4645
result.add(DefaultUserAgentPublisher.component());
47-
result.add(DefaultHeartBeatInfo.component());
4846
result.add(DefaultHeartBeatController.component());
4947
result.add(
5048
LibraryVersionComponent.create(FIREBASE_ANDROID, String.valueOf(Build.VERSION.SDK_INT)));

firebase-common/src/main/java/com/google/firebase/heartbeatinfo/DefaultHeartBeatController.java

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,11 @@
3737
import org.json.JSONObject;
3838

3939
/** Provides a function to store heartbeats and another function to retrieve stored heartbeats. */
40-
public class DefaultHeartBeatController implements HeartBeatController {
40+
public class DefaultHeartBeatController implements HeartBeatController, HeartBeatInfo {
4141

4242
private final Provider<HeartBeatInfoStorage> storageProvider;
4343

44-
private Context applicationContext;
44+
private final Context applicationContext;
4545

4646
private final Provider<UserAgentPublisher> userAgentProvider;
4747

@@ -114,24 +114,27 @@ private DefaultHeartBeatController(
114114
consumers,
115115
new ThreadPoolExecutor(
116116
0, 1, 30, TimeUnit.SECONDS, new LinkedBlockingQueue<>(), THREAD_FACTORY),
117-
userAgentProvider);
118-
this.applicationContext = context;
117+
userAgentProvider,
118+
context);
119119
}
120120

121121
@VisibleForTesting
122122
DefaultHeartBeatController(
123123
Provider<HeartBeatInfoStorage> testStorage,
124124
Set<HeartBeatConsumer> consumers,
125125
Executor executor,
126-
Provider<UserAgentPublisher> userAgentProvider) {
126+
Provider<UserAgentPublisher> userAgentProvider,
127+
Context context) {
127128
storageProvider = testStorage;
128129
this.consumers = consumers;
129130
this.backgroundExecutor = executor;
130131
this.userAgentProvider = userAgentProvider;
132+
this.applicationContext = context;
131133
}
132134

133135
public static @NonNull Component<DefaultHeartBeatController> component() {
134-
return Component.builder(DefaultHeartBeatController.class, HeartBeatController.class)
136+
return Component.builder(
137+
DefaultHeartBeatController.class, HeartBeatController.class, HeartBeatInfo.class)
135138
.add(Dependency.required(Context.class))
136139
.add(Dependency.required(FirebaseApp.class))
137140
.add(Dependency.setOf(HeartBeatConsumer.class))
@@ -145,4 +148,18 @@ private DefaultHeartBeatController(
145148
c.getProvider(UserAgentPublisher.class)))
146149
.build();
147150
}
151+
152+
@Override
153+
@NonNull
154+
public synchronized HeartBeat getHeartBeatCode(@NonNull String heartBeatTag) {
155+
long presentTime = System.currentTimeMillis();
156+
HeartBeatInfoStorage storage = storageProvider.get();
157+
boolean shouldSendGlobalHB = storage.shouldSendGlobalHeartBeat(presentTime);
158+
if (shouldSendGlobalHB) {
159+
storage.postHeartBeatCleanUp();
160+
return HeartBeat.GLOBAL;
161+
} else {
162+
return HeartBeat.NONE;
163+
}
164+
}
148165
}

firebase-common/src/main/java/com/google/firebase/heartbeatinfo/DefaultHeartBeatInfo.java

Lines changed: 0 additions & 93 deletions
This file was deleted.

firebase-common/src/main/java/com/google/firebase/heartbeatinfo/HeartBeatInfoStorage.java

Lines changed: 59 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -53,24 +53,17 @@ class HeartBeatInfoStorage {
5353
// As soon as you hit the limit of heartbeats. The number of stored heartbeats is halved.
5454
private static final int HEART_BEAT_COUNT_LIMIT = 30;
5555

56-
private static final SimpleDateFormat FORMATTER = new SimpleDateFormat("dd/MM/yyyy z");
57-
58-
private SharedPreferences sharedPreferences;
59-
private SharedPreferences firebaseSharedPreferences;
56+
private final SharedPreferences firebaseSharedPreferences;
6057

6158
public HeartBeatInfoStorage(Context applicationContext, String persistenceKey) {
62-
this.sharedPreferences =
63-
applicationContext.getSharedPreferences(
64-
PREFERENCES_NAME + persistenceKey, Context.MODE_PRIVATE);
6559
this.firebaseSharedPreferences =
6660
applicationContext.getSharedPreferences(
6761
HEARTBEAT_PREFERENCES_NAME + persistenceKey, Context.MODE_PRIVATE);
6862
}
6963

7064
@VisibleForTesting
7165
@RestrictTo(RestrictTo.Scope.TESTS)
72-
HeartBeatInfoStorage(SharedPreferences preferences, SharedPreferences firebaseSharedPreferences) {
73-
this.sharedPreferences = preferences;
66+
HeartBeatInfoStorage(SharedPreferences firebaseSharedPreferences) {
7467
this.firebaseSharedPreferences = firebaseSharedPreferences;
7568
}
7669

@@ -81,7 +74,14 @@ int getHeartBeatCount() {
8174
}
8275

8376
synchronized void deleteAllHeartBeats() {
84-
firebaseSharedPreferences.edit().clear().apply();
77+
SharedPreferences.Editor editor = firebaseSharedPreferences.edit();
78+
for (Map.Entry<String, ?> entry : this.firebaseSharedPreferences.getAll().entrySet()) {
79+
if (entry.getValue() instanceof Set) {
80+
editor.remove(entry.getKey());
81+
}
82+
}
83+
editor.remove(HEART_BEAT_COUNT_TAG);
84+
editor.commit();
8585
}
8686

8787
synchronized List<HeartBeatResult> getAllHeartBeats() {
@@ -93,10 +93,48 @@ synchronized List<HeartBeatResult> getAllHeartBeats() {
9393
entry.getKey(), new ArrayList<String>((Set<String>) entry.getValue())));
9494
}
9595
}
96+
updateGlobalHeartBeat(System.currentTimeMillis());
9697
return heartBeatResults;
9798
}
9899

99-
synchronized String getFormattedDate(long millis) {
100+
private synchronized String getStoredUserAgentString(String dateString) {
101+
for (Map.Entry<String, ?> entry : firebaseSharedPreferences.getAll().entrySet()) {
102+
if (entry.getValue() instanceof Set) {
103+
Set<String> dateSet = (Set<String>) entry.getValue();
104+
for (String date : dateSet) {
105+
if (dateString.equals(date)) {
106+
return entry.getKey();
107+
}
108+
}
109+
}
110+
}
111+
return null;
112+
}
113+
114+
private synchronized void removeStoredDate(String dateString) {
115+
// Find stored heartbeat and clear it.
116+
String userAgentString = getStoredUserAgentString(dateString);
117+
if (userAgentString == null) {
118+
return;
119+
}
120+
Set<String> userAgentDateSet =
121+
new HashSet<String>(
122+
firebaseSharedPreferences.getStringSet(userAgentString, new HashSet<String>()));
123+
userAgentDateSet.remove(dateString);
124+
if (userAgentDateSet.isEmpty()) {
125+
firebaseSharedPreferences.edit().remove(userAgentString).commit();
126+
} else {
127+
firebaseSharedPreferences.edit().putStringSet(userAgentString, userAgentDateSet).commit();
128+
}
129+
}
130+
131+
synchronized void postHeartBeatCleanUp() {
132+
String dateString = getFormattedDate(System.currentTimeMillis());
133+
firebaseSharedPreferences.edit().putString(LAST_STORED_DATE, dateString).commit();
134+
removeStoredDate(dateString);
135+
}
136+
137+
private synchronized String getFormattedDate(long millis) {
100138
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
101139
Instant instant = new Date(millis).toInstant();
102140
LocalDateTime ldt = instant.atOffset(ZoneOffset.UTC).toLocalDateTime();
@@ -127,7 +165,7 @@ synchronized void storeHeartBeat(long millis, String userAgentString) {
127165
.putStringSet(userAgentString, userAgentDateSet)
128166
.putLong(HEART_BEAT_COUNT_TAG, heartBeatCount)
129167
.putString(LAST_STORED_DATE, dateString)
130-
.apply();
168+
.commit();
131169
}
132170

133171
private synchronized void cleanUpStoredHeartBeats() {
@@ -153,21 +191,19 @@ private synchronized void cleanUpStoredHeartBeats() {
153191
.edit()
154192
.putStringSet(userAgentString, userAgentDateSet)
155193
.putLong(HEART_BEAT_COUNT_TAG, heartBeatCount - 1)
156-
.apply();
194+
.commit();
157195
}
158196

159197
synchronized long getLastGlobalHeartBeat() {
160-
return sharedPreferences.getLong(GLOBAL, -1);
198+
return firebaseSharedPreferences.getLong(GLOBAL, -1);
161199
}
162200

163201
synchronized void updateGlobalHeartBeat(long millis) {
164-
sharedPreferences.edit().putLong(GLOBAL, millis).apply();
202+
firebaseSharedPreferences.edit().putLong(GLOBAL, millis).commit();
165203
}
166204

167-
static boolean isSameDateUtc(long base, long target) {
168-
Date baseDate = new Date(base);
169-
Date targetDate = new Date(target);
170-
return !(FORMATTER.format(baseDate).equals(FORMATTER.format(targetDate)));
205+
synchronized boolean isSameDateUtc(long base, long target) {
206+
return getFormattedDate(base).equals(getFormattedDate(target));
171207
}
172208

173209
/*
@@ -176,14 +212,14 @@ static boolean isSameDateUtc(long base, long target) {
176212
when the last heartbeat send for the sdk was later than a day before.
177213
*/
178214
synchronized boolean shouldSendSdkHeartBeat(String heartBeatTag, long millis) {
179-
if (sharedPreferences.contains(heartBeatTag)) {
180-
if (isSameDateUtc(sharedPreferences.getLong(heartBeatTag, -1), millis)) {
181-
sharedPreferences.edit().putLong(heartBeatTag, millis).apply();
215+
if (firebaseSharedPreferences.contains(heartBeatTag)) {
216+
if (!this.isSameDateUtc(firebaseSharedPreferences.getLong(heartBeatTag, -1), millis)) {
217+
firebaseSharedPreferences.edit().putLong(heartBeatTag, millis).commit();
182218
return true;
183219
}
184220
return false;
185221
} else {
186-
sharedPreferences.edit().putLong(heartBeatTag, millis).apply();
222+
firebaseSharedPreferences.edit().putLong(heartBeatTag, millis).commit();
187223
return true;
188224
}
189225
}

0 commit comments

Comments
 (0)