xref: /aosp_15_r20/external/leakcanary2/shark/src/main/java/shark/KeyedWeakReferenceFinder.kt (revision d9e8da70d8c9df9a41d7848ae506fb3115cae6e6)

<lambda>null1 package shark
2 
3 import shark.ObjectInspectors.KEYED_WEAK_REFERENCE
4 import shark.internal.KeyedWeakReferenceMirror
5 
6 /**
7  * Finds all objects tracked by a KeyedWeakReference, ie all objects that were passed to
8  * ObjectWatcher.watch.
9  */
10 object KeyedWeakReferenceFinder : LeakingObjectFinder {
11 
12   override fun findLeakingObjectIds(graph: HeapGraph): Set<Long> =
13     findKeyedWeakReferences(graph)
14       .filter { it.hasReferent && it.isRetained }
15       .map { it.referent.value }
16       .toSet()
17 
18   fun heapDumpUptimeMillis(graph: HeapGraph): Long? {
19     return graph.context.getOrPut("heapDumpUptimeMillis") {
20       val keyedWeakReferenceClass = graph.findClassByName("leakcanary.KeyedWeakReference")
21       val heapDumpUptimeMillis = if (keyedWeakReferenceClass == null) {
22         null
23       } else {
24         keyedWeakReferenceClass["heapDumpUptimeMillis"]?.value?.asLong
25       }
26       if (heapDumpUptimeMillis == null) {
27         SharkLog.d {
28           "leakcanary.KeyedWeakReference.heapDumpUptimeMillis field not found"
29         }
30       }
31       heapDumpUptimeMillis
32     }
33   }
34 
35   internal fun findKeyedWeakReferences(graph: HeapGraph): List<KeyedWeakReferenceMirror> {
36     return graph.context.getOrPut(KEYED_WEAK_REFERENCE.name) {
37       val keyedWeakReferenceClass = graph.findClassByName("leakcanary.KeyedWeakReference")
38 
39       val keyedWeakReferenceClassId = keyedWeakReferenceClass?.objectId ?: 0
40       val legacyKeyedWeakReferenceClassId =
41         graph.findClassByName("com.squareup.leakcanary.KeyedWeakReference")?.objectId ?: 0
42 
43       val heapDumpUptimeMillis = heapDumpUptimeMillis(graph)
44 
45       val addedToContext: List<KeyedWeakReferenceMirror> = graph.instances
46         .filter { instance ->
47           instance.instanceClassId == keyedWeakReferenceClassId || instance.instanceClassId == legacyKeyedWeakReferenceClassId
48         }
49         .map {
50           KeyedWeakReferenceMirror.fromInstance(
51             it, heapDumpUptimeMillis
52           )
53         }
54         .toList()
55       graph.context[KEYED_WEAK_REFERENCE.name] = addedToContext
56       addedToContext
57     }
58   }
59 }