Merge pull request #2679 from square/py/fix_android_growth_crash

Fix warmup for Android heap growth
diff --git a/leakcanary/leakcanary-android-test/build.gradle b/leakcanary/leakcanary-android-test/build.gradle
index 84424b4..dac237e 100644
--- a/leakcanary/leakcanary-android-test/build.gradle
+++ b/leakcanary/leakcanary-android-test/build.gradle
@@ -8,6 +8,11 @@
   api projects.leakcanary.leakcanaryCore
   api projects.leakcanary.leakcanaryAndroidUtils
   api projects.shark.sharkAndroid
+
+  androidTestImplementation libs.androidX.multidex
+  androidTestImplementation libs.androidX.test.core
+  androidTestImplementation libs.androidX.test.runner
+  androidTestImplementation libs.assertjCore
 }
 
 android {
@@ -15,7 +20,10 @@
   defaultConfig {
     targetSdk versions.compileSdk
     minSdk versions.minSdk
+    testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+    multiDexEnabled true
   }
   buildFeatures.buildConfig = false
-  namespace 'com.squareup.leakcanary.core'
+  namespace 'com.squareup.leakcanary.android.test'
+  testNamespace 'com.squareup.leakcanary.android.test.test'
 }
diff --git a/leakcanary/leakcanary-android-test/src/androidTest/AndroidManifest.xml b/leakcanary/leakcanary-android-test/src/androidTest/AndroidManifest.xml
new file mode 100644
index 0000000..d56e207
--- /dev/null
+++ b/leakcanary/leakcanary-android-test/src/androidTest/AndroidManifest.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android">
+
+  <application
+    android:name="androidx.multidex.MultiDexApplication"
+    >
+  </application>
+</manifest>
diff --git a/leakcanary/leakcanary-android-test/src/androidTest/java/leakcanary/RepeatingAndroidInProcessScenarioTest.kt b/leakcanary/leakcanary-android-test/src/androidTest/java/leakcanary/RepeatingAndroidInProcessScenarioTest.kt
new file mode 100644
index 0000000..d2d6bde
--- /dev/null
+++ b/leakcanary/leakcanary-android-test/src/androidTest/java/leakcanary/RepeatingAndroidInProcessScenarioTest.kt
@@ -0,0 +1,38 @@
+package leakcanary
+
+import org.assertj.core.api.Assertions.assertThat
+import org.junit.Test
+import shark.ObjectGrowthDetector
+import shark.RepeatingScenarioObjectGrowthDetector.Companion.DEFAULT_MAX_HEAP_DUMPS
+import shark.RepeatingScenarioObjectGrowthDetector.Companion.IN_PROCESS_SCENARIO_LOOPS_PER_DUMP
+import shark.forAndroidHeap
+
+class RepeatingAndroidInProcessScenarioTest {
+
+  private val growingList = mutableListOf<String>()
+
+  @Test fun failing_scenario_iterates_to_max_heap_dumps_times_loops_per_dump() {
+    val detector = ObjectGrowthDetector.forAndroidHeap()
+      .repeatingAndroidInProcessScenario()
+    var iteration = 0
+    detector.findRepeatedlyGrowingObjects {
+      growingList += "growth $iteration"
+      iteration++
+    }
+
+    assertThat(iteration).isEqualTo(DEFAULT_MAX_HEAP_DUMPS * IN_PROCESS_SCENARIO_LOOPS_PER_DUMP)
+  }
+
+  @Test fun failing_scenario_finds_expected_growing_object() {
+    val detector = ObjectGrowthDetector.forAndroidHeap()
+      .repeatingAndroidInProcessScenario()
+    var iteration = 0
+    val heapGrowth = detector.findRepeatedlyGrowingObjects {
+      growingList += "growth $iteration"
+      iteration++
+    }
+
+    val growingObject = heapGrowth.growingObjects.single()
+    assertThat(growingObject.name).startsWith("INSTANCE_FIELD RepeatingAndroidInProcessScenarioTest.growingList")
+  }
+}
diff --git a/leakcanary/leakcanary-android-test/src/main/java/leakcanary/RepeatingAndroidInProcessScenario.kt b/leakcanary/leakcanary-android-test/src/main/java/leakcanary/RepeatingAndroidInProcessScenario.kt
index fc65e2d..1dddeb2 100644
--- a/leakcanary/leakcanary-android-test/src/main/java/leakcanary/RepeatingAndroidInProcessScenario.kt
+++ b/leakcanary/leakcanary-android-test/src/main/java/leakcanary/RepeatingAndroidInProcessScenario.kt
@@ -17,14 +17,13 @@
  */
 fun ObjectGrowthDetector.repeatingAndroidInProcessScenario(
   maxHeapDumps: Int = RepeatingScenarioObjectGrowthDetector.DEFAULT_MAX_HEAP_DUMPS,
-  // In process => More than one to account for the impact of running the analysis.
-  scenarioLoopsPerDump: Int = 2,
+  scenarioLoopsPerDump: Int = RepeatingScenarioObjectGrowthDetector.IN_PROCESS_SCENARIO_LOOPS_PER_DUMP,
 ): RepeatingScenarioObjectGrowthDetector {
   return repeatingScenario(
     heapGraphProvider = HeapGraphProvider.dumpingAndDeleting(
       heapDumper = HeapDumper.forAndroidInProcess()
         .withGc(gcTrigger = GcTrigger.inProcess())
-        .withDetectorWarmup(this),
+        .withDetectorWarmup(this, androidHeap = true),
       heapDumpFileProvider = HeapDumpFileProvider.tempFile()
     ),
     maxHeapDumps = maxHeapDumps,
diff --git a/leakcanary/leakcanary-core/api/leakcanary-core.api b/leakcanary/leakcanary-core/api/leakcanary-core.api
index af0bddc..f9db10d 100644
--- a/leakcanary/leakcanary-core/api/leakcanary-core.api
+++ b/leakcanary/leakcanary-core/api/leakcanary-core.api
@@ -51,7 +51,7 @@
 
 public final class leakcanary/ObjectGrowthWarmupHeapDumper : leakcanary/HeapDumper {
 	public static final field Companion Lleakcanary/ObjectGrowthWarmupHeapDumper$Companion;
-	public fun <init> (Lshark/ObjectGrowthDetector;Lleakcanary/HeapDumper;)V
+	public fun <init> (Lshark/ObjectGrowthDetector;Lleakcanary/HeapDumper;Z)V
 	public fun dumpHeap (Ljava/io/File;)V
 }
 
@@ -59,7 +59,7 @@
 }
 
 public final class leakcanary/ObjectGrowthWarmupHeapDumperKt {
-	public static final fun withDetectorWarmup (Lleakcanary/HeapDumper;Lshark/ObjectGrowthDetector;)Lleakcanary/HeapDumper;
+	public static final fun withDetectorWarmup (Lleakcanary/HeapDumper;Lshark/ObjectGrowthDetector;Z)Lleakcanary/HeapDumper;
 }
 
 public final class leakcanary/TempHeapDumpFileProvider : leakcanary/HeapDumpFileProvider {
diff --git a/leakcanary/leakcanary-core/src/main/java/leakcanary/ObjectGrowthWarmupHeapDumper.kt b/leakcanary/leakcanary-core/src/main/java/leakcanary/ObjectGrowthWarmupHeapDumper.kt
index ee184cb..2890991 100644
--- a/leakcanary/leakcanary-core/src/main/java/leakcanary/ObjectGrowthWarmupHeapDumper.kt
+++ b/leakcanary/leakcanary-core/src/main/java/leakcanary/ObjectGrowthWarmupHeapDumper.kt
@@ -9,7 +9,8 @@
 
 class ObjectGrowthWarmupHeapDumper(
   private val objectGrowthDetector: ObjectGrowthDetector,
-  private val delegate: HeapDumper
+  private val delegate: HeapDumper,
+  private val androidHeap: Boolean
 ) : HeapDumper {
 
   private var warm = false
@@ -23,7 +24,8 @@
   }
 
   private fun warmup() {
-    val heapDumpsAsHex = listOf({ heapDump1Hex() }, { heapDump2Hex() }, { heapDump3Hex() })
+    val heapDumpsAsHex = listOf({ heapDump1Hex(androidHeap) }, { heapDump2Hex(androidHeap) },
+      { heapDump3Hex(androidHeap) })
     val heapDumpsAsHexIterator = heapDumpsAsHex.iterator()
     val warmupDetector = objectGrowthDetector.repeatingScenario(
       heapGraphProvider = {
@@ -44,16 +46,28 @@
     // then 00 is the string separator
     // 00000004 is the identifier byte size, 4 bytes
     // 0b501e7e ca55e77e (obsolete cassette) is a cool heap dump timestamp.
-    internal fun heapDump1Hex() =
+    internal fun heapDump1Hex(androidHeap: Boolean) = if (androidHeap) {
+      "4a4156412050524f46494c4520312e302e3300000000040b501e7eca55e77e01000000000000001b000000016a6176612e6c616e672e7265662e5265666572656e63650200000000000000100000000100000002000000010000000101000000000000000c000000037265666572656e74010000000000000014000000046a6176612e6c616e672e4f626a656374020000000000000010000000010000000500000001000000040c000000000000006520000000050000000100000000000000000000000000000000000000000000000000000000000000000000050000000520000000020000000100000005000000000000000000000000000000000000000000000004000000000001000000030205000000022c000000000000000001000000000000001f000000066a6176612e6c616e672e7265662e5765616b5265666572656e6365020000000000000010000000010000000700000001000000060c00000000000000302000000007000000010000000200000000000000000000000000000000000000000000000400000000000005000000072c0000000000000000010000000000000021000000086c65616b63616e6172792e4b657965645765616b5265666572656e6365020000000000000010000000010000000900000001000000080100000000000000180000000a6865617044756d70557074696d654d696c6c69730100000000000000070000000b6b65790100000000000000080000000c6e616d650100000000000000150000000d7761746368557074696d654d696c6c69730100000000000000180000000e72657461696e6564557074696d654d696c6c69730c00000000000000512000000009000000010000000700000000000000000000000000000000000000000000001c000000010000000a0b000000000000753000040000000b020000000c020000000d0b0000000e0b05000000092c00000000000000000100000000000000140000000f6a6176612e6c616e672e537472696e670200000000000000100000000100000010000000010000000f0100000000000000090000001176616c756501000000000000000900000012636f756e740c000000000000008c200000001000000001000000050000000000000000000000000000000000000000000000080000000000020000001102000000120a05000000102300000013000000010000000105004d2100000014000000010000001000000008000000130000000123000000150000000100000001050049210000001600000001000000100000000800000015000000012c000000000000000001000000000000001400000017616e64726f69642e6f732e4275696c6402000000000000001000000001000000180000000100000017010000000000000010000000194d414e5546414354555245520100000000000000060000001a49440c000000000000004220000000180000000100000005000000000000000000000000000000000000000000000000000000020000001902000000140000001a0200000016000005000000182c000000000000000001000000000000001c0000001b616e64726f69642e6f732e4275696c642456455253494f4e020000000000000010000000010000001c000000010000001b01000000000000000b0000001d53444b5f494e540c000000000000004a200000001c0000000100000005000000000000000000000000000000000000000000000000000000010000001d0a0000002a0000050000001c210000001e0000000100000005000000002c00000000000000000100000000000000160000001f6a6176612e6c616e672e4f626a6563745b5d0200000000000000100000000100000020000000010000001f0c000000000000004520000000200000000100000005000000000000000000000000000000000000000000000000000000000000050000002022000000210000000100000001000000200000001e2c000000000000000001000000000000000a00000022486f6c64657202000000000000001000000001000000230000000100000022010000000000000008000000246c6973740c00000000000000392000000023000000010000000500000000000000000000000000000000000000000000000000000001000000240200000021000005000000232c0000000000000000"
+    } else {
       "4a4156412050524f46494c4520312e302e3300000000040b501e7eca55e77e01000000000000001b000000016a6176612e6c616e672e7265662e5265666572656e63650200000000000000100000000100000002000000010000000101000000000000000c000000037265666572656e74010000000000000014000000046a6176612e6c616e672e4f626a656374020000000000000010000000010000000500000001000000040c000000000000006520000000050000000100000000000000000000000000000000000000000000000000000000000000000000050000000520000000020000000100000005000000000000000000000000000000000000000000000004000000000001000000030205000000022c000000000000000001000000000000001f000000066a6176612e6c616e672e7265662e5765616b5265666572656e6365020000000000000010000000010000000700000001000000060c00000000000000302000000007000000010000000200000000000000000000000000000000000000000000000400000000000005000000072c0000000000000000010000000000000021000000086c65616b63616e6172792e4b657965645765616b5265666572656e6365020000000000000010000000010000000900000001000000080100000000000000180000000a6865617044756d70557074696d654d696c6c69730100000000000000070000000b6b65790100000000000000080000000c6e616d650100000000000000150000000d7761746368557074696d654d696c6c69730100000000000000180000000e72657461696e6564557074696d654d696c6c69730c00000000000000622000000009000000010000000700000000000000000000000000000000000000000000001c000000010000000a0b000000000000753000040000000b020000000c020000000d0b0000000e0b0500000009210000000f0000000100000005000000002c0000000000000000010000000000000016000000106a6176612e6c616e672e4f626a6563745b5d020000000000000010000000010000001100000001000000100c000000000000004520000000110000000100000005000000000000000000000000000000000000000000000000000000000000050000001122000000120000000100000001000000110000000f2c000000000000000001000000000000000a00000013486f6c64657202000000000000001000000001000000140000000100000013010000000000000008000000156c6973740c00000000000000392000000014000000010000000500000000000000000000000000000000000000000000000000000001000000150200000012000005000000142c0000000000000000"
+    }
 
-    internal fun heapDump2Hex() =
+    internal fun heapDump2Hex(androidHeap: Boolean) = if (androidHeap) {
+      "4a4156412050524f46494c4520312e302e3300000000040b501e7eca55e77e01000000000000001b000000016a6176612e6c616e672e7265662e5265666572656e63650200000000000000100000000100000002000000010000000101000000000000000c000000037265666572656e74010000000000000014000000046a6176612e6c616e672e4f626a656374020000000000000010000000010000000500000001000000040c000000000000006520000000050000000100000000000000000000000000000000000000000000000000000000000000000000050000000520000000020000000100000005000000000000000000000000000000000000000000000004000000000001000000030205000000022c000000000000000001000000000000001f000000066a6176612e6c616e672e7265662e5765616b5265666572656e6365020000000000000010000000010000000700000001000000060c00000000000000302000000007000000010000000200000000000000000000000000000000000000000000000400000000000005000000072c0000000000000000010000000000000021000000086c65616b63616e6172792e4b657965645765616b5265666572656e6365020000000000000010000000010000000900000001000000080100000000000000180000000a6865617044756d70557074696d654d696c6c69730100000000000000070000000b6b65790100000000000000080000000c6e616d650100000000000000150000000d7761746368557074696d654d696c6c69730100000000000000180000000e72657461696e6564557074696d654d696c6c69730c00000000000000512000000009000000010000000700000000000000000000000000000000000000000000001c000000010000000a0b000000000000753000040000000b020000000c020000000d0b0000000e0b05000000092c00000000000000000100000000000000140000000f6a6176612e6c616e672e537472696e670200000000000000100000000100000010000000010000000f0100000000000000090000001176616c756501000000000000000900000012636f756e740c000000000000008c200000001000000001000000050000000000000000000000000000000000000000000000080000000000020000001102000000120a05000000102300000013000000010000000105004d2100000014000000010000001000000008000000130000000123000000150000000100000001050049210000001600000001000000100000000800000015000000012c000000000000000001000000000000001400000017616e64726f69642e6f732e4275696c6402000000000000001000000001000000180000000100000017010000000000000010000000194d414e5546414354555245520100000000000000060000001a49440c000000000000004220000000180000000100000005000000000000000000000000000000000000000000000000000000020000001902000000140000001a0200000016000005000000182c000000000000000001000000000000001c0000001b616e64726f69642e6f732e4275696c642456455253494f4e020000000000000010000000010000001c000000010000001b01000000000000000b0000001d53444b5f494e540c000000000000005b200000001c0000000100000005000000000000000000000000000000000000000000000000000000010000001d0a0000002a0000050000001c210000001e000000010000000500000000210000001f0000000100000005000000002c0000000000000000010000000000000016000000206a6176612e6c616e672e4f626a6563745b5d020000000000000010000000010000002100000001000000200c000000000000004920000000210000000100000005000000000000000000000000000000000000000000000000000000000000050000002122000000220000000100000002000000210000001e0000001f2c000000000000000001000000000000000a00000023486f6c64657202000000000000001000000001000000240000000100000023010000000000000008000000256c6973740c00000000000000392000000024000000010000000500000000000000000000000000000000000000000000000000000001000000250200000022000005000000242c0000000000000000"
+    } else {
       "4a4156412050524f46494c4520312e302e3300000000040b501e7eca55e77e01000000000000001b000000016a6176612e6c616e672e7265662e5265666572656e63650200000000000000100000000100000002000000010000000101000000000000000c000000037265666572656e74010000000000000014000000046a6176612e6c616e672e4f626a656374020000000000000010000000010000000500000001000000040c000000000000006520000000050000000100000000000000000000000000000000000000000000000000000000000000000000050000000520000000020000000100000005000000000000000000000000000000000000000000000004000000000001000000030205000000022c000000000000000001000000000000001f000000066a6176612e6c616e672e7265662e5765616b5265666572656e6365020000000000000010000000010000000700000001000000060c00000000000000302000000007000000010000000200000000000000000000000000000000000000000000000400000000000005000000072c0000000000000000010000000000000021000000086c65616b63616e6172792e4b657965645765616b5265666572656e6365020000000000000010000000010000000900000001000000080100000000000000180000000a6865617044756d70557074696d654d696c6c69730100000000000000070000000b6b65790100000000000000080000000c6e616d650100000000000000150000000d7761746368557074696d654d696c6c69730100000000000000180000000e72657461696e6564557074696d654d696c6c69730c00000000000000732000000009000000010000000700000000000000000000000000000000000000000000001c000000010000000a0b000000000000753000040000000b020000000c020000000d0b0000000e0b0500000009210000000f00000001000000050000000021000000100000000100000005000000002c0000000000000000010000000000000016000000116a6176612e6c616e672e4f626a6563745b5d020000000000000010000000010000001200000001000000110c000000000000004920000000120000000100000005000000000000000000000000000000000000000000000000000000000000050000001222000000130000000100000002000000120000000f000000102c000000000000000001000000000000000a00000014486f6c64657202000000000000001000000001000000150000000100000014010000000000000008000000166c6973740c00000000000000392000000015000000010000000500000000000000000000000000000000000000000000000000000001000000160200000013000005000000152c0000000000000000"
+    }
 
-    internal fun heapDump3Hex() =
+    internal fun heapDump3Hex(androidHeap: Boolean) = if (androidHeap) {
+      "4a4156412050524f46494c4520312e302e3300000000040b501e7eca55e77e01000000000000001b000000016a6176612e6c616e672e7265662e5265666572656e63650200000000000000100000000100000002000000010000000101000000000000000c000000037265666572656e74010000000000000014000000046a6176612e6c616e672e4f626a656374020000000000000010000000010000000500000001000000040c000000000000006520000000050000000100000000000000000000000000000000000000000000000000000000000000000000050000000520000000020000000100000005000000000000000000000000000000000000000000000004000000000001000000030205000000022c000000000000000001000000000000001f000000066a6176612e6c616e672e7265662e5765616b5265666572656e6365020000000000000010000000010000000700000001000000060c00000000000000302000000007000000010000000200000000000000000000000000000000000000000000000400000000000005000000072c0000000000000000010000000000000021000000086c65616b63616e6172792e4b657965645765616b5265666572656e6365020000000000000010000000010000000900000001000000080100000000000000180000000a6865617044756d70557074696d654d696c6c69730100000000000000070000000b6b65790100000000000000080000000c6e616d650100000000000000150000000d7761746368557074696d654d696c6c69730100000000000000180000000e72657461696e6564557074696d654d696c6c69730c00000000000000512000000009000000010000000700000000000000000000000000000000000000000000001c000000010000000a0b000000000000753000040000000b020000000c020000000d0b0000000e0b05000000092c00000000000000000100000000000000140000000f6a6176612e6c616e672e537472696e670200000000000000100000000100000010000000010000000f0100000000000000090000001176616c756501000000000000000900000012636f756e740c000000000000008c200000001000000001000000050000000000000000000000000000000000000000000000080000000000020000001102000000120a05000000102300000013000000010000000105004d2100000014000000010000001000000008000000130000000123000000150000000100000001050049210000001600000001000000100000000800000015000000012c000000000000000001000000000000001400000017616e64726f69642e6f732e4275696c6402000000000000001000000001000000180000000100000017010000000000000010000000194d414e5546414354555245520100000000000000060000001a49440c000000000000004220000000180000000100000005000000000000000000000000000000000000000000000000000000020000001902000000140000001a0200000016000005000000182c000000000000000001000000000000001c0000001b616e64726f69642e6f732e4275696c642456455253494f4e020000000000000010000000010000001c000000010000001b01000000000000000b0000001d53444b5f494e540c000000000000006c200000001c0000000100000005000000000000000000000000000000000000000000000000000000010000001d0a0000002a0000050000001c210000001e000000010000000500000000210000001f00000001000000050000000021000000200000000100000005000000002c0000000000000000010000000000000016000000216a6176612e6c616e672e4f626a6563745b5d020000000000000010000000010000002200000001000000210c000000000000004d20000000220000000100000005000000000000000000000000000000000000000000000000000000000000050000002222000000230000000100000003000000220000001e0000001f000000202c000000000000000001000000000000000a00000024486f6c64657202000000000000001000000001000000250000000100000024010000000000000008000000266c6973740c00000000000000392000000025000000010000000500000000000000000000000000000000000000000000000000000001000000260200000023000005000000252c0000000000000000"
+    } else {
       "4a4156412050524f46494c4520312e302e3300000000040b501e7eca55e77e01000000000000001b000000016a6176612e6c616e672e7265662e5265666572656e63650200000000000000100000000100000002000000010000000101000000000000000c000000037265666572656e74010000000000000014000000046a6176612e6c616e672e4f626a656374020000000000000010000000010000000500000001000000040c000000000000006520000000050000000100000000000000000000000000000000000000000000000000000000000000000000050000000520000000020000000100000005000000000000000000000000000000000000000000000004000000000001000000030205000000022c000000000000000001000000000000001f000000066a6176612e6c616e672e7265662e5765616b5265666572656e6365020000000000000010000000010000000700000001000000060c00000000000000302000000007000000010000000200000000000000000000000000000000000000000000000400000000000005000000072c0000000000000000010000000000000021000000086c65616b63616e6172792e4b657965645765616b5265666572656e6365020000000000000010000000010000000900000001000000080100000000000000180000000a6865617044756d70557074696d654d696c6c69730100000000000000070000000b6b65790100000000000000080000000c6e616d650100000000000000150000000d7761746368557074696d654d696c6c69730100000000000000180000000e72657461696e6564557074696d654d696c6c69730c00000000000000842000000009000000010000000700000000000000000000000000000000000000000000001c000000010000000a0b000000000000753000040000000b020000000c020000000d0b0000000e0b0500000009210000000f000000010000000500000000210000001000000001000000050000000021000000110000000100000005000000002c0000000000000000010000000000000016000000126a6176612e6c616e672e4f626a6563745b5d020000000000000010000000010000001300000001000000120c000000000000004d20000000130000000100000005000000000000000000000000000000000000000000000000000000000000050000001322000000140000000100000003000000130000000f00000010000000112c000000000000000001000000000000000a00000015486f6c64657202000000000000001000000001000000160000000100000015010000000000000008000000176c6973740c00000000000000392000000016000000010000000500000000000000000000000000000000000000000000000000000001000000170200000014000005000000162c0000000000000000"
+    }
   }
 }
 
-fun HeapDumper.withDetectorWarmup(objectGrowthDetector: ObjectGrowthDetector): HeapDumper =
-  ObjectGrowthWarmupHeapDumper(objectGrowthDetector, this)
+fun HeapDumper.withDetectorWarmup(
+  objectGrowthDetector: ObjectGrowthDetector,
+  androidHeap: Boolean
+): HeapDumper =
+  ObjectGrowthWarmupHeapDumper(objectGrowthDetector, this, androidHeap)
diff --git a/leakcanary/leakcanary-core/src/test/java/leakcanary/ObjectGrowthWarmupHeapDumperTest.kt b/leakcanary/leakcanary-core/src/test/java/leakcanary/ObjectGrowthWarmupHeapDumperTest.kt
index 002d0da..271a739 100644
--- a/leakcanary/leakcanary-core/src/test/java/leakcanary/ObjectGrowthWarmupHeapDumperTest.kt
+++ b/leakcanary/leakcanary-core/src/test/java/leakcanary/ObjectGrowthWarmupHeapDumperTest.kt
@@ -5,34 +5,68 @@
 import org.assertj.core.api.Assertions.assertThat
 import org.junit.Test
 import shark.HprofHeader
+import shark.HprofWriterHelper
+import shark.ValueHolder
 import shark.dumpToBytes
 
 class ObjectGrowthWarmupHeapDumperTest {
 
   @Test fun `heap dump 1 as hex constant matches generated heap dump hex`() {
-    assertThat(ObjectGrowthWarmupHeapDumper.heapDump1Hex()).isEqualTo(dumpGrowingListHeapAsHex(1))
+    assertThat(ObjectGrowthWarmupHeapDumper.heapDump1Hex(androidHeap = false)).isEqualTo(dumpGrowingListHeapAsHex(1))
   }
 
   @Test fun `heap dump 2 as hex constant matches generated heap dump hex`() {
-    assertThat(ObjectGrowthWarmupHeapDumper.heapDump2Hex()).isEqualTo(dumpGrowingListHeapAsHex(2))
+    assertThat(ObjectGrowthWarmupHeapDumper.heapDump2Hex(androidHeap = false)).isEqualTo(dumpGrowingListHeapAsHex(2))
   }
 
   @Test fun `heap dump 3 as hex constant matches generated heap dump hex`() {
-    assertThat(ObjectGrowthWarmupHeapDumper.heapDump3Hex()).isEqualTo(dumpGrowingListHeapAsHex(3))
+    assertThat(ObjectGrowthWarmupHeapDumper.heapDump3Hex(androidHeap = false)).isEqualTo(dumpGrowingListHeapAsHex(3))
+  }
+
+  @Test fun `android heap dump 1 as hex constant matches generated heap dump hex`() {
+    assertThat(ObjectGrowthWarmupHeapDumper.heapDump1Hex(androidHeap = true)).isEqualTo(dumpAndroidGrowingListHeapAsHex(1))
+  }
+
+  @Test fun `android heap dump 2 as hex constant matches generated heap dump hex`() {
+    assertThat(ObjectGrowthWarmupHeapDumper.heapDump2Hex(androidHeap = true)).isEqualTo(dumpAndroidGrowingListHeapAsHex(2))
+  }
+
+  @Test fun `android heap dump 3 as hex constant matches generated heap dump hex`() {
+    assertThat(ObjectGrowthWarmupHeapDumper.heapDump3Hex(androidHeap = true)).isEqualTo(dumpAndroidGrowingListHeapAsHex(3))
   }
 
   private fun dumpGrowingListHeapAsHex(listItemCount: Int): String {
     val heapDumpTimestamp = ("0b501e7e" + "ca55e77e").decodeHex().toByteArray().toLong()
     return dumpToBytes(hprofHeader = HprofHeader(heapDumpTimestamp = heapDumpTimestamp)) {
-      "Holder" clazz {
-        val refs = (1..listItemCount).map {
-          instance(objectClassId)
-        }.toTypedArray()
-        staticField["list"] = objectArray(*refs)
-      }
+      growingList(listItemCount)
     }.toByteString().hex()
   }
 
+  private fun dumpAndroidGrowingListHeapAsHex(listItemCount: Int): String {
+    val heapDumpTimestamp = ("0b501e7e" + "ca55e77e").decodeHex().toByteArray().toLong()
+    return dumpToBytes(hprofHeader = HprofHeader(heapDumpTimestamp = heapDumpTimestamp)) {
+      "android.os.Build" clazz {
+        staticField["MANUFACTURER"] = string("M")
+        staticField["ID"] = string("I")
+      }
+      "android.os.Build\$VERSION" clazz {
+        staticField["SDK_INT"] = ValueHolder.IntHolder(42)
+      }
+      growingList(listItemCount)
+    }.toByteString().hex()
+  }
+
+
+  private fun HprofWriterHelper.growingList(listItemCount: Int) {
+    "Holder" clazz {
+      val refs = (1..listItemCount).map {
+        instance(objectClassId)
+      }.toTypedArray()
+      staticField["list"] = objectArray(*refs)
+    }
+  }
+
+
   private fun ByteArray.toLong(): Long {
     check(size == 8)
     var pos = 0
diff --git a/leakcanary/leakcanary-jvm-test/src/main/java/leakcanary/RepeatingJvmInProcessScenario.kt b/leakcanary/leakcanary-jvm-test/src/main/java/leakcanary/RepeatingJvmInProcessScenario.kt
index 9dede19..a476123 100644
--- a/leakcanary/leakcanary-jvm-test/src/main/java/leakcanary/RepeatingJvmInProcessScenario.kt
+++ b/leakcanary/leakcanary-jvm-test/src/main/java/leakcanary/RepeatingJvmInProcessScenario.kt
@@ -17,14 +17,13 @@
  */
 fun ObjectGrowthDetector.repeatingJvmInProcessScenario(
   maxHeapDumps: Int = RepeatingScenarioObjectGrowthDetector.DEFAULT_MAX_HEAP_DUMPS,
-  // In process => More than one to account for the impact of running the analysis.
-  scenarioLoopsPerDump: Int = 2,
+  scenarioLoopsPerDump: Int = RepeatingScenarioObjectGrowthDetector.IN_PROCESS_SCENARIO_LOOPS_PER_DUMP,
 ): RepeatingScenarioObjectGrowthDetector {
   return repeatingScenario(
     heapGraphProvider = HeapGraphProvider.dumpingAndDeleting(
       heapDumper = HeapDumper.forJvmInProcess()
         .withGc(gcTrigger = GcTrigger.inProcess())
-        .withDetectorWarmup(this),
+        .withDetectorWarmup(this, androidHeap = false),
       heapDumpFileProvider = HeapDumpFileProvider.tempFile()
     ),
     maxHeapDumps = maxHeapDumps,
diff --git a/shark/shark/api/shark.api b/shark/shark/api/shark.api
index c6577c1..1224855 100644
--- a/shark/shark/api/shark.api
+++ b/shark/shark/api/shark.api
@@ -940,6 +940,7 @@
 	public static final field Companion Lshark/RepeatingScenarioObjectGrowthDetector$Companion;
 	public static final field DEFAULT_MAX_HEAP_DUMPS I
 	public static final field DEFAULT_SCENARIO_LOOPS_PER_DUMP I
+	public static final field IN_PROCESS_SCENARIO_LOOPS_PER_DUMP I
 	public fun <init> (Lshark/HeapGraphProvider;Lshark/ObjectGrowthDetector;II)V
 	public synthetic fun <init> (Lshark/HeapGraphProvider;Lshark/ObjectGrowthDetector;IIILkotlin/jvm/internal/DefaultConstructorMarker;)V
 	public final fun findRepeatedlyGrowingObjects (Lkotlin/jvm/functions/Function0;)Lshark/HeapGrowthTraversal;
diff --git a/shark/shark/src/main/java/shark/RepeatingScenarioObjectGrowthDetector.kt b/shark/shark/src/main/java/shark/RepeatingScenarioObjectGrowthDetector.kt
index d98e735..52dcd48 100644
--- a/shark/shark/src/main/java/shark/RepeatingScenarioObjectGrowthDetector.kt
+++ b/shark/shark/src/main/java/shark/RepeatingScenarioObjectGrowthDetector.kt
@@ -48,6 +48,11 @@
   companion object {
     const val DEFAULT_MAX_HEAP_DUMPS = 5
     const val DEFAULT_SCENARIO_LOOPS_PER_DUMP = 1
+
+    /**
+     * In process => More than one to account for the impact of running the analysis.
+     */
+    const val IN_PROCESS_SCENARIO_LOOPS_PER_DUMP = 2
   }
 }