@@ -19,7 +19,6 @@ package com.google.firebase.sessions
19
19
import android.util.Log
20
20
import androidx.datastore.core.DataStore
21
21
import com.google.firebase.annotations.concurrent.Background
22
- import com.google.firebase.sessions.ProcessDetailsProvider.getProcessName
23
22
import com.google.firebase.sessions.api.FirebaseSessionsDependencies
24
23
import com.google.firebase.sessions.api.SessionSubscriber
25
24
import com.google.firebase.sessions.settings.SessionsSettings
@@ -92,7 +91,7 @@ constructor(
92
91
return
93
92
}
94
93
val sessionData = localSessionData
95
- Log .d(TAG , " App backgrounded on ${getProcessName() } - $sessionData " )
94
+ Log .d(TAG , " App backgrounded on ${processDataManager.myProcessName } - $sessionData " )
96
95
97
96
CoroutineScope (backgroundDispatcher).launch {
98
97
try {
@@ -113,32 +112,58 @@ constructor(
113
112
return
114
113
}
115
114
val sessionData = localSessionData
116
- Log .d(TAG , " App foregrounded on ${getProcessName() } - $sessionData " )
115
+ Log .d(TAG , " App foregrounded on ${processDataManager.myProcessName } - $sessionData " )
117
116
118
- if (shouldInitiateNewSession(sessionData)) {
117
+ // Check if maybe the session data needs to be updated
118
+ if (isSessionExpired(sessionData) || isMyProcessStale(sessionData)) {
119
119
CoroutineScope (backgroundDispatcher).launch {
120
120
try {
121
121
sessionDataStore.updateData { currentSessionData ->
122
- // Double-check pattern
123
- if (shouldInitiateNewSession(currentSessionData)) {
122
+ // Check again using the current session data on disk
123
+ val isSessionExpired = isSessionExpired(currentSessionData)
124
+ val isColdStart = isColdStart(currentSessionData)
125
+ val isMyProcessStale = isMyProcessStale(currentSessionData)
126
+
127
+ val newProcessDataMap =
128
+ if (isColdStart) {
129
+ // Generate a new process data map for cold app start
130
+ processDataManager.generateProcessDataMap()
131
+ } else if (isMyProcessStale) {
132
+ // Update the data map with this process if stale
133
+ processDataManager.updateProcessDataMap(currentSessionData.processDataMap)
134
+ } else {
135
+ // No change
136
+ currentSessionData.processDataMap
137
+ }
138
+
139
+ // This is an expression, and returns the updated session data
140
+ if (isSessionExpired || isColdStart) {
124
141
val newSessionDetails =
125
- sessionGenerator.generateNewSession(sessionData .sessionDetails)
142
+ sessionGenerator.generateNewSession(currentSessionData .sessionDetails)
126
143
sessionFirelogPublisher.mayLogSession(sessionDetails = newSessionDetails)
127
144
processDataManager.onSessionGenerated()
128
- currentSessionData.copy(sessionDetails = newSessionDetails, backgroundTime = null )
145
+ currentSessionData.copy(
146
+ sessionDetails = newSessionDetails,
147
+ backgroundTime = null ,
148
+ processDataMap = newProcessDataMap,
149
+ )
150
+ } else if (isMyProcessStale) {
151
+ currentSessionData.copy(
152
+ processDataMap = processDataManager.updateProcessDataMap(newProcessDataMap)
153
+ )
129
154
} else {
130
155
currentSessionData
131
156
}
132
157
}
133
158
} catch (ex: Exception ) {
134
159
Log .d(TAG , " App appForegrounded, failed to update data. Message: ${ex.message} " )
135
- val newSessionDetails = sessionGenerator.generateNewSession( sessionData.sessionDetails)
136
- localSessionData =
137
- localSessionData.copy(sessionDetails = newSessionDetails, backgroundTime = null )
138
- sessionFirelogPublisher.mayLogSession (sessionDetails = newSessionDetails)
139
-
140
- val sessionId = newSessionDetails.sessionId
141
- notifySubscribers(sessionId, NotificationType . FALLBACK )
160
+ if (isSessionExpired( sessionData)) {
161
+ val newSessionDetails = sessionGenerator.generateNewSession(sessionData.sessionDetails)
162
+ localSessionData =
163
+ sessionData.copy (sessionDetails = newSessionDetails, backgroundTime = null )
164
+ sessionFirelogPublisher.mayLogSession(sessionDetails = newSessionDetails)
165
+ notifySubscribers( newSessionDetails.sessionId, NotificationType . FALLBACK )
166
+ }
142
167
}
143
168
}
144
169
}
@@ -161,22 +186,47 @@ constructor(
161
186
}
162
187
}
163
188
164
- private fun shouldInitiateNewSession (sessionData : SessionData ): Boolean {
189
+ /* * Checks if the session has expired. If no background time, consider it not expired. */
190
+ private fun isSessionExpired (sessionData : SessionData ): Boolean {
165
191
sessionData.backgroundTime?.let { backgroundTime ->
166
192
val interval = timeProvider.currentTime() - backgroundTime
167
- if (interval > sessionsSettings.sessionRestartTimeout) {
168
- Log .d( TAG , " Passed session restart timeout, so initiate a new session " )
169
- return true
193
+ val sessionExpired = (interval > sessionsSettings.sessionRestartTimeout)
194
+ if (sessionExpired) {
195
+ Log .d( TAG , " Session ${sessionData.sessionDetails.sessionId} is expired " )
170
196
}
197
+ return sessionExpired
171
198
}
172
199
200
+ Log .d(TAG , " Session ${sessionData.sessionDetails.sessionId} has not backgrounded yet" )
201
+ return false
202
+ }
203
+
204
+ /* * Checks for cold app start. If no process data map, consider it a cold start. */
205
+ private fun isColdStart (sessionData : SessionData ): Boolean {
173
206
sessionData.processDataMap?.let { processDataMap ->
174
- Log .d(TAG , " Has not passed session restart timeout, so check for cold app start" )
175
- return processDataManager.isColdStart(processDataMap)
207
+ val coldStart = processDataManager.isColdStart(processDataMap)
208
+ if (coldStart) {
209
+ Log .d(TAG , " Cold app start detected" )
210
+ }
211
+ return coldStart
176
212
}
177
213
178
- Log .d(TAG , " No process has backgrounded yet and no process data, should not change the session" )
179
- return false
214
+ Log .d(TAG , " No process data map" )
215
+ return true
216
+ }
217
+
218
+ /* * Checks if this process is stale. If no process data map, consider the process stale. */
219
+ private fun isMyProcessStale (sessionData : SessionData ): Boolean {
220
+ sessionData.processDataMap?.let { processDataMap ->
221
+ val myProcessStale = processDataManager.isMyProcessStale(processDataMap)
222
+ if (myProcessStale) {
223
+ Log .d(TAG , " Process ${processDataManager.myProcessName} is stale" )
224
+ }
225
+ return myProcessStale
226
+ }
227
+
228
+ Log .d(TAG , " No process data for ${processDataManager.myProcessName} " )
229
+ return true
180
230
}
181
231
182
232
private companion object {
0 commit comments