Skip to content

Commit

Permalink
Merge pull request #2097 from square/py/service_inspector
Browse files Browse the repository at this point in the history
Add object inspector for services
  • Loading branch information
pyricau authored Mar 26, 2021
2 parents 4a74e78 + 1b89055 commit 295f948
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 0 deletions.
6 changes: 6 additions & 0 deletions shark-android/api/shark-android.api
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ public abstract class shark/AndroidObjectInspectors : java/lang/Enum, shark/Obje
public static final field MESSAGE_QUEUE Lshark/AndroidObjectInspectors;
public static final field MORTAR_PRESENTER Lshark/AndroidObjectInspectors;
public static final field MORTAR_SCOPE Lshark/AndroidObjectInspectors;
public static final field SERVICE Lshark/AndroidObjectInspectors;
public static final field SUPPORT_FRAGMENT Lshark/AndroidObjectInspectors;
public static final field TOAST Lshark/AndroidObjectInspectors;
public static final field VIEW Lshark/AndroidObjectInspectors;
Expand Down Expand Up @@ -166,3 +167,8 @@ public final class shark/AndroidResourceIdNames$Companion {
public final fun saveToMemory (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)V
}

public final class shark/AndroidServices {
public static final field INSTANCE Lshark/AndroidServices;
public final fun getAliveAndroidServiceObjectIds (Lshark/HeapGraph;)Ljava/util/List;
}

21 changes: 21 additions & 0 deletions shark-android/src/main/java/shark/AndroidObjectInspectors.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
package shark

import shark.AndroidServices.aliveAndroidServiceObjectIds
import shark.AndroidObjectInspectors.Companion.appDefaults
import shark.FilteringLeakingObjectFinder.LeakingObjectFilter
import shark.HeapObject.HeapInstance
Expand Down Expand Up @@ -209,6 +210,26 @@ enum class AndroidObjectInspectors : ObjectInspector {
}
},

SERVICE {
override val leakingObjectFilter = { heapObject: HeapObject ->
heapObject is HeapInstance &&
heapObject instanceOf "android.app.Service" &&
heapObject.objectId !in heapObject.graph.aliveAndroidServiceObjectIds
}

override fun inspect(
reporter: ObjectReporter
) {
reporter.whenInstanceOf("android.app.Service") { instance ->
if (instance.objectId in instance.graph.aliveAndroidServiceObjectIds) {
notLeakingReasons += "Service held by ActivityThread"
} else {
leakingReasons += "Service not held by ActivityThread"
}
}
}
},

CONTEXT_FIELD {
override fun inspect(reporter: ObjectReporter) {
val instance = reporter.heapObject
Expand Down
28 changes: 28 additions & 0 deletions shark-android/src/main/java/shark/AndroidServices.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package shark

object AndroidServices {
val HeapGraph.aliveAndroidServiceObjectIds: List<Long>
get() {
return context.getOrPut(AndroidServices::class.java.name) {
val activityThreadClass = findClassByName("android.app.ActivityThread")!!
val currentActivityThread = activityThreadClass
.readStaticField("sCurrentActivityThread")!!
.valueAsInstance!!

val mServices = currentActivityThread["android.app.ActivityThread", "mServices"]!!
.valueAsInstance!!

val servicesArray = mServices["android.util.ArrayMap", "mArray"]!!.valueAsObjectArray!!

servicesArray.readElements()
.filterIndexed { index, heapValue ->
// ArrayMap<IBinder, Service>
// even: key, odd: value
index % 2 == 1
&& heapValue.isNonNullReference
}
.map { it.asNonNullObjectId!! }
.toList()
}
}
}

0 comments on commit 295f948

Please sign in to comment.