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