1 package leakcanary 2 3 import android.app.Instrumentation 4 import android.os.SystemClock 5 import androidx.test.platform.app.InstrumentationRegistry 6 import leakcanary.GcTrigger.Default 7 import leakcanary.HeapAnalysisDecision.NoHeapAnalysis 8 import leakcanary.HeapAnalysisDecision.AnalyzeHeap 9 10 class AndroidDetectLeaksInterceptor( 11 private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation(), 12 private val objectWatcher: ObjectWatcher = AppWatcher.objectWatcher, 13 private val retainedDelayMillis: Long = AppWatcher.retainedDelayMillis 14 ) : DetectLeaksInterceptor { 15 16 @Suppress("ReturnCount") waitUntilReadyForHeapAnalysisnull17 override fun waitUntilReadyForHeapAnalysis(): HeapAnalysisDecision { 18 val leakDetectionTime = SystemClock.uptimeMillis() 19 20 if (!objectWatcher.hasWatchedObjects) { 21 return NoHeapAnalysis("No watched objects.") 22 } 23 24 instrumentation.waitForIdleSync() 25 if (!objectWatcher.hasWatchedObjects) { 26 return NoHeapAnalysis("No watched objects after waiting for idle sync.") 27 } 28 29 Default.runGc() 30 if (!objectWatcher.hasWatchedObjects) { 31 return NoHeapAnalysis("No watched objects after triggering an explicit GC.") 32 } 33 34 // Waiting for any delayed UI post (e.g. scroll) to clear. This shouldn't be needed, but 35 // Android simply has way too many delayed posts that aren't canceled when views are detached. 36 SystemClock.sleep(2000) 37 38 if (!objectWatcher.hasWatchedObjects) { 39 return NoHeapAnalysis("No watched objects after delayed UI post is cleared.") 40 } 41 42 // Aaand we wait some more. 43 // 4 seconds (2+2) is greater than the 3 seconds delay for 44 // FINISH_TOKEN in android.widget.Filter 45 SystemClock.sleep(2000) 46 47 val endOfWatchDelay = retainedDelayMillis - (SystemClock.uptimeMillis() - leakDetectionTime) 48 if (endOfWatchDelay > 0) { 49 SystemClock.sleep(endOfWatchDelay) 50 } 51 52 Default.runGc() 53 54 if (!objectWatcher.hasRetainedObjects) { 55 return NoHeapAnalysis("No retained objects after waiting for retained delay.") 56 } 57 return AnalyzeHeap 58 } 59 } 60