@@ -23,32 +23,48 @@ import javax.inject.Singleton
2323
2424/* * Manage process data, used for detecting cold app starts. */ 
2525internal  interface  ProcessDataManager  {
26-   /* * An in-memory uuid to uniquely identify this instance of this process. */ 
26+   /* * This process's name. */ 
27+   val  myProcessName:  String 
28+ 
29+   /* * This process's pid. */ 
30+   val  myPid:  Int 
31+ 
32+   /* * An in-memory uuid to uniquely identify this instance of this process, not the uid. */ 
2733  val  myUuid:  String 
2834
2935  /* * Checks if this is a cold app start, meaning all processes in the mapping table are stale. */ 
3036  fun  isColdStart (processDataMap :  Map <String , ProcessData >): Boolean 
3137
38+   /* * Checks if this process is stale. */ 
39+   fun  isMyProcessStale (processDataMap :  Map <String , ProcessData >): Boolean 
40+ 
3241  /* * Call to notify the process data manager that a session has been generated. */ 
3342  fun  onSessionGenerated ()
3443
3544  /* * Update the mapping of the current processes with data about this process. */ 
3645  fun  updateProcessDataMap (processDataMap :  Map <String , ProcessData >? ): Map <String , ProcessData >
3746
38-   /* * Generate a new mapping of process data with the current  process only. */ 
39-   fun  generateProcessDataMap ()  =  updateProcessDataMap(mapOf ())
47+   /* * Generate a new mapping of process data about this  process only. */ 
48+   fun  generateProcessDataMap ():  Map < String ,  ProcessData >  =  updateProcessDataMap(emptyMap ())
4049}
4150
42- /* * Manage process data, used for detecting cold app starts. */ 
4351@Singleton
4452internal  class  ProcessDataManagerImpl 
4553@Inject
46- constructor (private  val  appContext:  Context , private val  uuidGenerator:  UuidGenerator ) : 
47-   ProcessDataManager  {
54+ constructor (private  val  appContext:  Context , uuidGenerator:  UuidGenerator ) :  ProcessDataManager  {
55+   /* *
56+    * This process's name. 
57+    * 
58+    * This value is cached, so will not reflect changes to the process name during runtime. 
59+    */  
60+   override  val  myProcessName:  String  by lazy { myProcessDetails.processName }
61+ 
62+   override  val  myPid =  Process .myPid()
63+ 
4864  override  val  myUuid:  String  by lazy { uuidGenerator.next().toString() }
4965
50-   private  val  myProcessName :   String  by lazy {
51-     ProcessDetailsProvider .getCurrentProcessDetails(appContext).processName 
66+   private  val  myProcessDetails  by lazy {
67+     ProcessDetailsProvider .getCurrentProcessDetails(appContext)
5268  }
5369
5470  private  var  hasGeneratedSession:  Boolean  =  false 
@@ -59,7 +75,8 @@ constructor(private val appContext: Context, private val uuidGenerator: UuidGene
5975      return  false 
6076    }
6177
62-     return  ProcessDetailsProvider .getAppProcessDetails(appContext)
78+     //  A cold start is when all app processes are stale
79+     return  getAppProcessDetails()
6380      .mapNotNull { processDetails -> 
6481        processDataMap[processDetails.processName]?.let  { processData -> 
6582          Pair (processDetails, processData)
@@ -68,6 +85,11 @@ constructor(private val appContext: Context, private val uuidGenerator: UuidGene
6885      .all { (processDetails, processData) ->  isProcessStale(processDetails, processData) }
6986  }
7087
88+   override  fun  isMyProcessStale (processDataMap :  Map <String , ProcessData >): Boolean  {
89+     val  myProcessData =  processDataMap[myProcessName] ? :  return  true 
90+     return  myProcessData.pid !=  myPid ||  myProcessData.uuid !=  myUuid
91+   }
92+ 
7193  override  fun  onSessionGenerated () {
7294    hasGeneratedSession =  true 
7395  }
@@ -81,17 +103,22 @@ constructor(private val appContext: Context, private val uuidGenerator: UuidGene
81103      ?.toMap()
82104      ? :  mapOf (myProcessName to ProcessData (Process .myPid(), myUuid))
83105
106+   /* * Gets the current details for all of the app's running processes. */ 
107+   private  fun  getAppProcessDetails () =  ProcessDetailsProvider .getAppProcessDetails(appContext)
108+ 
84109  /* *
85110   * Returns true if the process is stale, meaning the persisted process data does not match the 
86111   * running process details. 
112+    * 
113+    * The [processDetails] is the running process details, and [processData] is the persisted data. 
87114   */  
88-   private  fun  isProcessStale (
89-     runningProcessDetails :  ProcessDetails ,
90-     persistedProcessData :  ProcessData ,
91-   ): Boolean  = 
92-     if  (myProcessName ==  runningProcessDetails.processName) {
93-       runningProcessDetails.pid !=  persistedProcessData.pid ||  myUuid !=  persistedProcessData.uuid
115+   private  fun  isProcessStale (processDetails :  ProcessDetails , processData :  ProcessData ): Boolean  = 
116+     if  (myProcessName ==  processDetails.processName) {
117+       //  For this process, check pid and uuid
118+       processDetails.pid !=  processData.pid ||  myUuid !=  processData.uuid
94119    } else  {
95-       runningProcessDetails.pid !=  persistedProcessData.pid
120+       //  For other processes, only check pid to avoid inter-process communication
121+       //  It is very unlikely for there to be a pid collision
122+       processDetails.pid !=  processData.pid
96123    }
97124}
0 commit comments