@@ -19,7 +19,6 @@ package com.google.firebase.sessions
1919import android.util.Log
2020import androidx.datastore.core.DataStore
2121import com.google.firebase.annotations.concurrent.Background
22- import com.google.firebase.sessions.ProcessDetailsProvider.getProcessName
2322import com.google.firebase.sessions.api.FirebaseSessionsDependencies
2423import com.google.firebase.sessions.api.SessionSubscriber
2524import com.google.firebase.sessions.settings.SessionsSettings
@@ -92,7 +91,7 @@ constructor(
9291 return
9392 }
9493 val sessionData = localSessionData
95- Log .d(TAG , " App backgrounded on ${getProcessName() } - $sessionData " )
94+ Log .d(TAG , " App backgrounded on ${processDataManager.myProcessName } - $sessionData " )
9695
9796 CoroutineScope (backgroundDispatcher).launch {
9897 try {
@@ -113,32 +112,58 @@ constructor(
113112 return
114113 }
115114 val sessionData = localSessionData
116- Log .d(TAG , " App foregrounded on ${getProcessName() } - $sessionData " )
115+ Log .d(TAG , " App foregrounded on ${processDataManager.myProcessName } - $sessionData " )
117116
118- if (shouldInitiateNewSession(sessionData)) {
117+ // Check if maybe the session data needs to be updated
118+ if (isSessionExpired(sessionData) || isMyProcessStale(sessionData)) {
119119 CoroutineScope (backgroundDispatcher).launch {
120120 try {
121121 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) {
124141 val newSessionDetails =
125- sessionGenerator.generateNewSession(sessionData .sessionDetails)
142+ sessionGenerator.generateNewSession(currentSessionData .sessionDetails)
126143 sessionFirelogPublisher.mayLogSession(sessionDetails = newSessionDetails)
127144 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+ )
129154 } else {
130155 currentSessionData
131156 }
132157 }
133158 } catch (ex: Exception ) {
134159 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+ }
142167 }
143168 }
144169 }
@@ -161,22 +186,47 @@ constructor(
161186 }
162187 }
163188
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 {
165191 sessionData.backgroundTime?.let { backgroundTime ->
166192 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 " )
170196 }
197+ return sessionExpired
171198 }
172199
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 {
173206 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
176212 }
177213
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
180230 }
181231
182232 private companion object {
0 commit comments