1 package leakcanary 2 3 import androidx.work.Data 4 import androidx.work.OneTimeWorkRequest 5 import androidx.work.WorkManager 6 import androidx.work.multiprocess.RemoteListenableWorker.ARGUMENT_CLASS_NAME 7 import androidx.work.multiprocess.RemoteListenableWorker.ARGUMENT_PACKAGE_NAME 8 import leakcanary.EventListener.Event 9 import leakcanary.EventListener.Event.HeapDump 10 import leakcanary.internal.HeapAnalyzerWorker.Companion.asWorkerInputData 11 import leakcanary.internal.InternalLeakCanary 12 import leakcanary.internal.RemoteHeapAnalyzerWorker 13 import shark.SharkLog 14 15 /** 16 * When receiving a [HeapDump] event, starts a WorkManager worker that performs heap analysis in 17 * a dedicated :leakcanary process 18 */ 19 object RemoteWorkManagerHeapAnalyzer : EventListener { 20 21 private const val REMOTE_SERVICE_CLASS_NAME = "leakcanary.internal.RemoteLeakCanaryWorkerService" 22 <lambda>null23 internal val remoteLeakCanaryServiceInClasspath by lazy { 24 try { 25 Class.forName(REMOTE_SERVICE_CLASS_NAME) 26 true 27 } catch (ignored: Throwable) { 28 false 29 } 30 } 31 onEventnull32 override fun onEvent(event: Event) { 33 if (event is HeapDump) { 34 val application = InternalLeakCanary.application 35 val heapAnalysisRequest = 36 OneTimeWorkRequest.Builder(RemoteHeapAnalyzerWorker::class.java).apply { 37 val dataBuilder = Data.Builder() 38 .putString(ARGUMENT_PACKAGE_NAME, application.packageName) 39 .putString(ARGUMENT_CLASS_NAME, REMOTE_SERVICE_CLASS_NAME) 40 setInputData(event.asWorkerInputData(dataBuilder)) 41 with(WorkManagerHeapAnalyzer) { 42 addExpeditedFlag() 43 } 44 }.build() 45 SharkLog.d { "Enqueuing heap analysis for ${event.file} on WorkManager remote worker" } 46 val workManager = WorkManager.getInstance(application) 47 workManager.enqueue(heapAnalysisRequest) 48 } 49 } 50 } 51