@@ -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 }
@@ -78,20 +100,24 @@ constructor(private val appContext: Context, private val uuidGenerator: UuidGene
78100 processDataMap
79101 ?.toMutableMap()
80102 ?.apply { this [myProcessName] = ProcessData (Process .myPid(), myUuid) }
81- ?.toMap()
82- ? : mapOf (myProcessName to ProcessData (Process .myPid(), myUuid))
103+ ?.toMap() ? : mapOf (myProcessName to ProcessData (Process .myPid(), myUuid))
104+
105+ /* * Gets the current details for all of the app's running processes. */
106+ private fun getAppProcessDetails () = ProcessDetailsProvider .getAppProcessDetails(appContext)
83107
84108 /* *
85109 * Returns true if the process is stale, meaning the persisted process data does not match the
86110 * running process details.
111+ *
112+ * The [processDetails] is the running process details, and [processData] is the persisted data.
87113 */
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
114+ private fun isProcessStale (processDetails : ProcessDetails , processData : ProcessData ): Boolean =
115+ if (myProcessName == processDetails.processName) {
116+ // For this process, check pid and uuid
117+ processDetails.pid != processData.pid || myUuid != processData.uuid
94118 } else {
95- runningProcessDetails.pid != persistedProcessData.pid
119+ // For other processes, only check pid to avoid inter-process communication
120+ // It is very unlikely for there to be a pid collision
121+ processDetails.pid != processData.pid
96122 }
97123}
0 commit comments