• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download

<lambda>null1 package leakcanary.internal.activity.screen
2 
3 import android.app.ActivityManager
4 import android.text.Html
5 import android.text.SpannableStringBuilder
6 import android.text.method.LinkMovementMethod
7 import android.view.View
8 import android.view.ViewGroup
9 import android.widget.TextView
10 import com.squareup.leakcanary.core.R
11 import java.util.UUID
12 import leakcanary.EventListener.Event.HeapDump
13 import leakcanary.internal.InternalLeakCanary
14 import leakcanary.internal.activity.db.HeapAnalysisTable
15 import leakcanary.internal.activity.db.executeOnDb
16 import leakcanary.internal.activity.shareHeapDump
17 import leakcanary.internal.activity.shareToGitHubIssue
18 import leakcanary.internal.activity.ui.UiUtils
19 import leakcanary.internal.navigation.Screen
20 import leakcanary.internal.navigation.activity
21 import leakcanary.internal.navigation.goBack
22 import leakcanary.internal.navigation.inflate
23 import leakcanary.internal.navigation.onCreateOptionsMenu
24 import shark.HeapAnalysisFailure
25 
26 internal class HeapAnalysisFailureScreen(
27   private val analysisId: Long
28 ) : Screen() {
29 
30   override fun createView(container: ViewGroup) =
31     container.inflate(R.layout.leak_canary_heap_analysis_failure_screen).apply {
32       activity.title = resources.getString(R.string.leak_canary_loading_title)
33       executeOnDb {
34         val heapAnalysis = HeapAnalysisTable.retrieve<HeapAnalysisFailure>(db, analysisId)
35         if (heapAnalysis == null) {
36           updateUi {
37             activity.title = resources.getString(R.string.leak_canary_analysis_deleted_title)
38           }
39         } else {
40           val heapDumpFileExist = heapAnalysis.heapDumpFile.exists()
41           updateUi { onFailureRetrieved(heapAnalysis, heapDumpFileExist) }
42         }
43       }
44     }
45 
46   private fun View.onFailureRetrieved(
47     heapAnalysis: HeapAnalysisFailure,
48     heapDumpFileExist: Boolean
49   ) {
50     activity.title = resources.getString(R.string.leak_canary_analysis_failed)
51 
52     val failureText =
53       if (heapDumpFileExist) {
54         "You can <a href=\"try_again\">run the analysis again</a>.<br><br>"
55       } else {
56         ""
57       } + """
58       Please <a href="file_issue">click here</a> to file a bug report.
59       The stacktrace details will be copied into the clipboard and you just need to paste into the
60       GitHub issue description.""" + (if (heapDumpFileExist) {
61         """
62         <br><br>To help reproduce the issue, please share the
63         <a href="share_hprof">Heap Dump file</a> and upload it to the GitHub issue.
64       """
65       } else "")
66 
67     val failure = Html.fromHtml(failureText) as SpannableStringBuilder
68 
69     UiUtils.replaceUrlSpanWithAction(failure) { urlSpan ->
70       when (urlSpan) {
71         "file_issue" -> {
72           {
73             shareToGitHubIssue(heapAnalysis)
74           }
75         }
76         "share_hprof" -> {
77           {
78             shareHeapDump(heapAnalysis.heapDumpFile)
79           }
80         }
81         "try_again" -> {
82           {
83             InternalLeakCanary.sendEvent(
84               HeapDump(
85                 uniqueId = UUID.randomUUID().toString(),
86                 file = heapAnalysis.heapDumpFile,
87                 durationMillis = heapAnalysis.dumpDurationMillis,
88                 reason = "Retrying heap analysis after failure."
89               )
90             )
91           }
92         }
93         else -> null
94       }
95     }
96     findViewById<TextView>(R.id.leak_canary_header_text).apply {
97       movementMethod = LinkMovementMethod.getInstance()
98       text = failure
99     }
100 
101     findViewById<TextView>(R.id.leak_canary_stacktrace).text = heapAnalysis.exception.toString()
102 
103     onCreateOptionsMenu { menu ->
104       if (!ActivityManager.isUserAMonkey()) {
105         menu.add(R.string.leak_canary_delete)
106           .setOnMenuItemClickListener {
107             executeOnDb {
108               HeapAnalysisTable.delete(db, analysisId, heapAnalysis.heapDumpFile)
109               updateUi {
110                 goBack()
111               }
112             }
113             true
114           }
115       }
116     }
117   }
118 }
119