@@ -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