@@ -23,32 +23,48 @@ import javax.inject.Singleton
23
23
24
24
/* * Manage process data, used for detecting cold app starts. */
25
25
internal 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. */
27
33
val myUuid: String
28
34
29
35
/* * Checks if this is a cold app start, meaning all processes in the mapping table are stale. */
30
36
fun isColdStart (processDataMap : Map <String , ProcessData >): Boolean
31
37
38
+ /* * Checks if this process is stale. */
39
+ fun isMyProcessStale (processDataMap : Map <String , ProcessData >): Boolean
40
+
32
41
/* * Call to notify the process data manager that a session has been generated. */
33
42
fun onSessionGenerated ()
34
43
35
44
/* * Update the mapping of the current processes with data about this process. */
36
45
fun updateProcessDataMap (processDataMap : Map <String , ProcessData >? ): Map <String , ProcessData >
37
46
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 ())
40
49
}
41
50
42
- /* * Manage process data, used for detecting cold app starts. */
43
51
@Singleton
44
52
internal class ProcessDataManagerImpl
45
53
@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
+
48
64
override val myUuid: String by lazy { uuidGenerator.next().toString() }
49
65
50
- private val myProcessName : String by lazy {
51
- ProcessDetailsProvider .getCurrentProcessDetails(appContext).processName
66
+ private val myProcessDetails by lazy {
67
+ ProcessDetailsProvider .getCurrentProcessDetails(appContext)
52
68
}
53
69
54
70
private var hasGeneratedSession: Boolean = false
@@ -59,7 +75,8 @@ constructor(private val appContext: Context, private val uuidGenerator: UuidGene
59
75
return false
60
76
}
61
77
62
- return ProcessDetailsProvider .getAppProcessDetails(appContext)
78
+ // A cold start is when all app processes are stale
79
+ return getAppProcessDetails()
63
80
.mapNotNull { processDetails ->
64
81
processDataMap[processDetails.processName]?.let { processData ->
65
82
Pair (processDetails, processData)
@@ -68,6 +85,11 @@ constructor(private val appContext: Context, private val uuidGenerator: UuidGene
68
85
.all { (processDetails, processData) -> isProcessStale(processDetails, processData) }
69
86
}
70
87
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
+
71
93
override fun onSessionGenerated () {
72
94
hasGeneratedSession = true
73
95
}
@@ -81,17 +103,22 @@ constructor(private val appContext: Context, private val uuidGenerator: UuidGene
81
103
?.toMap()
82
104
? : mapOf (myProcessName to ProcessData (Process .myPid(), myUuid))
83
105
106
+ /* * Gets the current details for all of the app's running processes. */
107
+ private fun getAppProcessDetails () = ProcessDetailsProvider .getAppProcessDetails(appContext)
108
+
84
109
/* *
85
110
* Returns true if the process is stale, meaning the persisted process data does not match the
86
111
* running process details.
112
+ *
113
+ * The [processDetails] is the running process details, and [processData] is the persisted data.
87
114
*/
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
94
119
} 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
96
123
}
97
124
}
0 commit comments