@@ -6,9 +6,11 @@ import android.view.View
66import android.widget.SeekBar
77import android.widget.Toast
88import androidx.activity.OnBackPressedCallback
9+ import androidx.appcompat.app.AlertDialog
910import androidx.appcompat.app.AppCompatActivity
1011import androidx.recyclerview.widget.LinearLayoutManager
1112import io.sentry.ITransaction
13+ import io.sentry.ProfileLifecycle
1214import io.sentry.ProfilingTraceData
1315import io.sentry.Sentry
1416import io.sentry.SentryEnvelopeItem
@@ -24,6 +26,7 @@ class ProfilingActivity : AppCompatActivity() {
2426 private val executors = Executors .newFixedThreadPool(Runtime .getRuntime().availableProcessors())
2527 private var profileFinished = true
2628 private var manualProfilingActive = false
29+ private var lastProfilingResult: String? = null
2730
2831 override fun onCreate (savedInstanceState : Bundle ? ) {
2932 super .onCreate(savedInstanceState)
@@ -44,15 +47,49 @@ class ProfilingActivity : AppCompatActivity() {
4447 )
4548 binding = ActivityProfilingBinding .inflate(layoutInflater)
4649
47- // Show which profiler backend is active
4850 val options = Sentry .getCurrentScopes().options
4951 val isPerfetto = options.isUseProfilingManager && Build .VERSION .SDK_INT >= 35
52+ val isContinuousEnabled = options.isContinuousProfilingEnabled
53+ val lifecycle = options.profileLifecycle
54+
55+ // Status line: summarize the active profiler
5056 binding.profilingStatus.text =
51- if (isPerfetto) {
52- getString(R .string.profiling_status_perfetto)
53- } else {
54- getString(R .string.profiling_status_legacy)
57+ when {
58+ ! isContinuousEnabled -> getString(R .string.profiling_status_none)
59+ isPerfetto -> getString(R .string.profiling_status_perfetto)
60+ else -> getString(R .string.profiling_status_legacy)
61+ }
62+
63+ // Info button: show detailed config and last result in a dialog
64+ binding.profilingInfo.setOnClickListener {
65+ val config = buildString {
66+ appendLine(" traces.profiling.lifecycle: ${lifecycle.name} " )
67+ appendLine(" profiling.use-profiling-manager: ${options.isUseProfilingManager} " )
68+ appendLine(" Build.VERSION.SDK_INT: ${Build .VERSION .SDK_INT } " )
69+ appendLine(" traces.profiling.session-sample-rate: ${options.profileSessionSampleRate} " )
70+ appendLine(" traces.sample-rate: ${options.tracesSampleRate} " )
71+ if (lastProfilingResult != null ) {
72+ appendLine()
73+ append(lastProfilingResult)
74+ }
5575 }
76+ AlertDialog .Builder (this )
77+ .setTitle(R .string.profiling_config_title)
78+ .setMessage(config)
79+ .setPositiveButton(android.R .string.ok, null )
80+ .show()
81+ }
82+
83+ // Show only the controls relevant to the current lifecycle mode
84+ when (lifecycle) {
85+ ProfileLifecycle .MANUAL -> {
86+ binding.profilingStartTransaction.visibility = View .GONE
87+ // Duration slider only controls transaction length — irrelevant for manual mode
88+ binding.profilingDurationText.visibility = View .GONE
89+ binding.profilingDurationSeekbar.visibility = View .GONE
90+ }
91+ ProfileLifecycle .TRACE -> binding.profilingStartTransactionManual.visibility = View .GONE
92+ }
5693
5794 binding.profilingDurationSeekbar.setOnSeekBarChangeListener(
5895 object : SeekBar .OnSeekBarChangeListener {
@@ -89,7 +126,7 @@ class ProfilingActivity : AppCompatActivity() {
89126 binding.profilingList.layoutManager = LinearLayoutManager (this )
90127
91128 // Transaction-based profiling (existing)
92- binding.profilingStart .setOnClickListener {
129+ binding.profilingStartTransaction .setOnClickListener {
93130 binding.profilingProgressBar.visibility = View .VISIBLE
94131 profileFinished = false
95132 val seconds = getProfileDuration()
@@ -107,28 +144,28 @@ class ProfilingActivity : AppCompatActivity() {
107144 }
108145
109146 // Manual continuous profiling (exercises Perfetto path on API 35+)
110- binding.profilingStartManual .setOnClickListener {
147+ binding.profilingStartTransactionManual .setOnClickListener {
111148 if (! manualProfilingActive) {
112149 Sentry .startProfiler()
113150 manualProfilingActive = true
114151 profileFinished = false
115- binding.profilingStartManual .text = getString(R .string.profiling_stop_manual)
152+ binding.profilingStartTransactionManual .text = getString(R .string.profiling_stop_manual)
116153 binding.profilingProgressBar.visibility = View .VISIBLE
117154
118155 // Start background work to generate interesting profile data
119156 val threads = getBackgroundThreads()
120157 repeat(threads) { executors.submit { runMathOperations() } }
121158 executors.submit { swipeList() }
122159
123- binding.profilingResult.text = getString( R .string.profiling_manual_started)
160+ Toast .makeText( this , R .string.profiling_manual_started, Toast . LENGTH_SHORT ).show( )
124161 } else {
125162 Sentry .stopProfiler()
126163 manualProfilingActive = false
127164 profileFinished = true
128- binding.profilingStartManual .text = getString(R .string.profiling_start_manual)
165+ binding.profilingStartTransactionManual .text = getString(R .string.profiling_start_manual)
129166 binding.profilingProgressBar.visibility = View .GONE
130167
131- binding.profilingResult.text = getString( R .string.profiling_manual_stopped)
168+ Toast .makeText( this , R .string.profiling_manual_stopped, Toast . LENGTH_SHORT ).show( )
132169 }
133170 }
134171
@@ -176,9 +213,10 @@ class ProfilingActivity : AppCompatActivity() {
176213 val bos = ByteArrayOutputStream ()
177214 GZIPOutputStream (bos).bufferedWriter().use { it.write(String (itemData)) }
178215
216+ lastProfilingResult =
217+ getString(R .string.profiling_result, profileLength, itemData.size, bos.toByteArray().size)
179218 binding.root.post {
180- binding.profilingResult.text =
181- getString(R .string.profiling_result, profileLength, itemData.size, bos.toByteArray().size)
219+ Toast .makeText(this , " Profile captured — tap (i) for details" , Toast .LENGTH_SHORT ).show()
182220 }
183221 } catch (e: Exception ) {
184222 e.printStackTrace()
0 commit comments