HeapAnalyzerWorker.kt
TLDR
This file contains the HeapAnalyzerWorker
class, which extends the Android Worker
class. It is responsible for running a heap analysis in the background and sending events to InternalLeakCanary
. It also includes several helper methods for serializing and deserializing events and handling notifications.
Classes
HeapAnalyzerWorker
The HeapAnalyzerWorker
class extends the Android Worker
class and is responsible for running a heap analysis in the background. It overrides the doWork
method to run the analysis using AndroidDebugHeapAnalyzer
and sends the events to InternalLeakCanary
. It also overrides the getForegroundInfoAsync
method to provide information for displaying a foreground notification during the analysis.
Internal classes and methods
-
companion object
: Contains several helper methods used within theHeapAnalyzerWorker
class:-
Event.asWorkerInputData
method: Converts anEvent
object into aData
object that can be used as input data for theWorker
. -
Data.asEvent
method: Converts theData
object back into anEvent
object. -
Context.heapAnalysisForegroundInfoAsync
method: Creates and sets up a foreground notification for the heap analysis.
-
package leakcanary.internal
import android.app.Notification
import android.content.Context
import androidx.work.Data
import androidx.work.ForegroundInfo
import androidx.work.Worker
import androidx.work.WorkerParameters
import androidx.work.impl.utils.futures.SettableFuture
import com.google.common.util.concurrent.ListenableFuture
import com.squareup.leakcanary.core.R
import leakcanary.EventListener.Event
internal class HeapAnalyzerWorker(appContext: Context, workerParams: WorkerParameters) :
Worker(appContext, workerParams) {
override fun doWork(): Result {
val doneEvent =
AndroidDebugHeapAnalyzer.runAnalysisBlocking(inputData.asEvent()) { event ->
InternalLeakCanary.sendEvent(event)
}
InternalLeakCanary.sendEvent(doneEvent)
return Result.success()
}
override fun getForegroundInfoAsync(): ListenableFuture<ForegroundInfo> {
return applicationContext.heapAnalysisForegroundInfoAsync()
}
companion object {
private const val EVENT_BYTES = "EVENT_BYTES"
fun Event.asWorkerInputData(dataBuilder: Data.Builder = Data.Builder()) = dataBuilder
.putByteArray(EVENT_BYTES, toByteArray())
.build()
inline fun <reified T> Data.asEvent(): T =
Serializables.fromByteArray<T>(getByteArray(EVENT_BYTES)!!)!!
fun Context.heapAnalysisForegroundInfoAsync(): ListenableFuture<ForegroundInfo> {
val infoFuture = SettableFuture.create<ForegroundInfo>()
val builder = Notification.Builder(this)
.setContentTitle(getString(R.string.leak_canary_notification_analysing))
.setContentText("LeakCanary is working.")
.setProgress(100, 0, true)
val notification =
Notifications.buildNotification(this, builder, NotificationType.LEAKCANARY_LOW)
infoFuture.set(
ForegroundInfo(
R.id.leak_canary_notification_analyzing_heap,
notification
)
)
return infoFuture
}
}
}