xref: /aosp_15_r20/external/leakcanary2/leakcanary-android-core/src/main/java/leakcanary/TvEventListener.kt (revision d9e8da70d8c9df9a41d7848ae506fb3115cae6e6)
1 package leakcanary
2 
3 import com.squareup.leakcanary.core.R
4 import leakcanary.EventListener.Event
5 import leakcanary.EventListener.Event.HeapAnalysisDone
6 import leakcanary.internal.InternalLeakCanary
7 import leakcanary.internal.activity.LeakActivity
8 import leakcanary.internal.friendly.mainHandler
9 import leakcanary.internal.tv.TvToast
10 import shark.HeapAnalysis
11 import shark.HeapAnalysisFailure
12 import shark.HeapAnalysisSuccess
13 import shark.SharkLog
14 
15 object TvEventListener : EventListener {
16 
17   private val appContext = InternalLeakCanary.application
18 
onEventnull19   override fun onEvent(event: Event) {
20     when (event) {
21       is HeapAnalysisDone<*> -> {
22         showToast(event.heapAnalysis)
23         printIntentInfo()
24       }
25     }
26   }
27 
28   /**
29    * Android TV devices do not have notifications, therefore the only easy and non-invasive way
30    * to communicate with user is via Toast messages. These are used just to grab user attention and
31    * to direct them to Logcat where a much more detailed report will be printed.
32    */
showToastnull33   private fun showToast(heapAnalysis: HeapAnalysis) {
34     mainHandler.post {
35       val resumedActivity = InternalLeakCanary.resumedActivity ?: return@post
36       val message: String = when (heapAnalysis) {
37         is HeapAnalysisSuccess -> {
38           appContext.getString(
39             R.string.leak_canary_tv_analysis_success,
40             heapAnalysis.applicationLeaks.size,
41             heapAnalysis.libraryLeaks.size
42           )
43         }
44         is HeapAnalysisFailure -> appContext.getString(R.string.leak_canary_tv_analysis_failure)
45       }
46       TvToast.makeText(resumedActivity, message)
47         .show()
48     }
49   }
50 
51   /**
52    * Android TV with API 26+ has a bug where the launcher icon doesn't appear, so users won't know how
53    * to launch LeakCanary Activity.
54    * This method prints an adb command that launched LeakCanary into the logcat
55    */
printIntentInfonull56   private fun printIntentInfo() {
57     val leakClass = LeakActivity::class.java
58     SharkLog.d {"""
59       ====================================
60       ANDROID TV LAUNCH INTENT
61       ====================================
62       Run the following adb command to display the list of leaks:
63 
64       adb shell am start -n "${appContext.packageName}/${leakClass.`package`?.name}.LeakLauncherActivity"
65       ====================================""".trimIndent()
66     }
67   }
68 }
69