@@ -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,57 @@ 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+             val  isSessionExpired =  isSessionExpired(currentSessionData)
123+             val  isColdStart =  isColdStart(currentSessionData)
124+             val  isMyProcessStale =  isMyProcessStale(currentSessionData)
125+ 
126+             val  newProcessDataMap = 
127+               if  (isColdStart) {
128+                 //  Generate a new process data map for cold app start
129+                 processDataManager.generateProcessDataMap()
130+               } else  if  (isMyProcessStale) {
131+                 //  Update the data map with this process if stale
132+                 processDataManager.updateProcessDataMap(currentSessionData.processDataMap)
133+               } else  {
134+                 //  No change
135+                 currentSessionData.processDataMap
136+               }
137+ 
138+             //  This is an expression, and returns the updated session data
139+             if  (isSessionExpired ||  isColdStart) {
124140              val  newSessionDetails = 
125-                 sessionGenerator.generateNewSession(sessionData .sessionDetails)
141+                 sessionGenerator.generateNewSession(currentSessionData .sessionDetails)
126142              sessionFirelogPublisher.mayLogSession(sessionDetails =  newSessionDetails)
127143              processDataManager.onSessionGenerated()
128-               currentSessionData.copy(sessionDetails =  newSessionDetails, backgroundTime =  null )
144+               currentSessionData.copy(
145+                 sessionDetails =  newSessionDetails,
146+                 backgroundTime =  null ,
147+                 processDataMap =  newProcessDataMap,
148+               )
149+             } else  if  (isMyProcessStale) {
150+               currentSessionData.copy(
151+                 processDataMap =  processDataManager.updateProcessDataMap(newProcessDataMap)
152+               )
129153            } else  {
130154              currentSessionData
131155            }
132156          }
133157        } catch  (ex:  Exception ) {
134158          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 ) 
159+           if  (isSessionExpired( sessionData)) { 
160+              val  newSessionDetails  =  sessionGenerator.generateNewSession(sessionData.sessionDetails) 
161+             localSessionData  = 
162+               sessionData.copy (sessionDetails =  newSessionDetails, backgroundTime  =   null )
163+             sessionFirelogPublisher.mayLogSession(sessionDetails  =  newSessionDetails) 
164+             notifySubscribers( newSessionDetails.sessionId,  NotificationType . FALLBACK ) 
165+           } 
142166        }
143167      }
144168    }
@@ -161,22 +185,47 @@ constructor(
161185    }
162186  }
163187
164-   private  fun  shouldInitiateNewSession (sessionData :  SessionData ): Boolean  {
188+   /* * Checks if the session has expired. If no background time, consider it not expired. */ 
189+   private  fun  isSessionExpired (sessionData :  SessionData ): Boolean  {
165190    sessionData.backgroundTime?.let  { backgroundTime -> 
166191      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 
192+       val  sessionExpired  =   (interval >  sessionsSettings.sessionRestartTimeout)
193+       if  (sessionExpired) { 
194+         Log .d( TAG ,  " Session  ${sessionData.sessionDetails.sessionId}  is expired " ) 
170195      }
196+       return  sessionExpired
171197    }
172198
199+     Log .d(TAG , " Session ${sessionData.sessionDetails.sessionId}  has not backgrounded yet" 
200+     return  false 
201+   }
202+ 
203+   /* * Checks for cold app start. If no process data map, consider it a cold start. */ 
204+   private  fun  isColdStart (sessionData :  SessionData ): Boolean  {
173205    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)
206+       val  coldStart =  processDataManager.isColdStart(processDataMap)
207+       if  (coldStart) {
208+         Log .d(TAG , " Cold app start detected" 
209+       }
210+       return  coldStart
176211    }
177212
178-     Log .d(TAG , " No process has backgrounded yet and no process data, should not change the session" 
179-     return  false 
213+     Log .d(TAG , " No process data map" 
214+     return  true 
215+   }
216+ 
217+   /* * Checks if this process is stale. If no process data map, consider the process stale. */ 
218+   private  fun  isMyProcessStale (sessionData :  SessionData ): Boolean  {
219+     sessionData.processDataMap?.let  { processDataMap -> 
220+       val  myProcessStale =  processDataManager.isMyProcessStale(processDataMap)
221+       if  (myProcessStale) {
222+         Log .d(TAG , " Process ${processDataManager.myProcessName}  is stale" 
223+       }
224+       return  myProcessStale
225+     }
226+ 
227+     Log .d(TAG , " No process data for ${processDataManager.myProcessName} " 
228+     return  true 
180229  }
181230
182231  private  companion  object  {
0 commit comments