44import static io .sentry .IConnectionStatusProvider .ConnectionStatus .DISCONNECTED ;
55import static java .util .concurrent .TimeUnit .SECONDS ;
66
7- import android .annotation .SuppressLint ;
8- import android .content .Context ;
97import android .os .Build ;
108import io .sentry .CompositePerformanceCollector ;
119import io .sentry .DataCategory ;
@@ -53,10 +51,6 @@ public class AndroidContinuousProfiler
5351 private boolean isInitialized = false ;
5452 private final @ NotNull SentryFrameMetricsCollector frameMetricsCollector ;
5553 private @ Nullable AndroidProfiler profiler = null ;
56- private @ Nullable PerfettoProfiler perfettoProfiler = null ;
57- private final boolean useProfilingManager ;
58- private final @ Nullable Context context ;
59- private boolean isPerfettoActive = false ;
6054 private boolean isRunning = false ;
6155 private @ Nullable IScopes scopes ;
6256 private @ Nullable Future <?> stopFuture ;
@@ -74,10 +68,6 @@ public class AndroidContinuousProfiler
7468 private final AutoClosableReentrantLock lock = new AutoClosableReentrantLock ();
7569 private final AutoClosableReentrantLock payloadLock = new AutoClosableReentrantLock ();
7670
77- /**
78- * Creates a profiler using the legacy Debug.startMethodTracingSampling engine. This is the
79- * default path used for app-start profiling and devices below API 35.
80- */
8171 public static AndroidContinuousProfiler createLegacy (
8272 final @ NotNull BuildInfoProvider buildInfoProvider ,
8373 final @ NotNull SentryFrameMetricsCollector frameMetricsCollector ,
@@ -90,40 +80,15 @@ public static AndroidContinuousProfiler createLegacy(
9080 frameMetricsCollector ,
9181 executorServiceSupplier ,
9282 logger ,
93- null ,
94- false ,
9583 profilingTracesHz ,
9684 profilingTracesDirPath );
9785 }
9886
99- /**
100- * Creates a profiler using Android's ProfilingManager (Perfetto) on API 35+. On older devices, no
101- * profiling data is collected — the legacy Debug-based profiler is not used as a fallback.
102- */
103- public static AndroidContinuousProfiler createWithProfilingManager (
104- final @ NotNull Context context ,
105- final @ NotNull BuildInfoProvider buildInfoProvider ,
106- final @ NotNull SentryFrameMetricsCollector frameMetricsCollector ,
107- final @ NotNull ILogger logger ,
108- final @ NotNull LazyEvaluator .Evaluator <ISentryExecutorService > executorServiceSupplier ) {
109- return new AndroidContinuousProfiler (
110- buildInfoProvider ,
111- frameMetricsCollector ,
112- executorServiceSupplier ,
113- logger ,
114- context ,
115- true ,
116- 0 ,
117- null );
118- }
119-
12087 private AndroidContinuousProfiler (
12188 final @ NotNull BuildInfoProvider buildInfoProvider ,
12289 final @ NotNull SentryFrameMetricsCollector frameMetricsCollector ,
12390 final @ NotNull LazyEvaluator .Evaluator <ISentryExecutorService > executorServiceSupplier ,
12491 final @ NotNull ILogger logger ,
125- final @ Nullable Context context ,
126- final boolean useProfilingManager ,
12792 final int profilingTracesHz ,
12893 final @ Nullable String profilingTracesDirPath ) {
12994 this .logger = logger ;
@@ -132,33 +97,15 @@ private AndroidContinuousProfiler(
13297 this .profilingTracesDirPath = profilingTracesDirPath ;
13398 this .profilingTracesHz = profilingTracesHz ;
13499 this .executorServiceSupplier = executorServiceSupplier ;
135- this .useProfilingManager = useProfilingManager ;
136- this .context = context ;
137100 }
138101
139- @ SuppressLint ("NewApi" )
140102 private void init () {
141- logger .log (
142- SentryLevel .DEBUG ,
143- "AndroidContinuousProfiler.init() isInitialized=%s, useProfilingManager=%s, apiLevel=%d" ,
144- isInitialized ,
145- useProfilingManager ,
146- buildInfoProvider .getSdkInfoVersion ());
147-
148103 // We initialize it only once
149104 if (isInitialized ) {
150105 return ;
151106 }
152107 isInitialized = true ;
153108
154- if (useProfilingManager ) {
155- initProfilingManager ();
156- } else {
157- initLegacy ();
158- }
159- }
160-
161- private void initLegacy () {
162109 if (profilingTracesDirPath == null ) {
163110 logger .log (
164111 SentryLevel .WARNING ,
@@ -182,20 +129,6 @@ private void initLegacy() {
182129 logger );
183130 }
184131
185- @ SuppressLint ("NewApi" )
186- private void initProfilingManager () {
187- if (buildInfoProvider .getSdkInfoVersion () >= Build .VERSION_CODES .VANILLA_ICE_CREAM
188- && context != null ) {
189- perfettoProfiler = new PerfettoProfiler (context , frameMetricsCollector , logger );
190- logger .log (SentryLevel .DEBUG , "Using Perfetto profiler (ProfilingManager)." );
191- } else {
192- logger .log (
193- SentryLevel .WARNING ,
194- "useProfilingManager requested but not available (requires API 35+). "
195- + "No profiling data will be collected." );
196- }
197- }
198-
199132 @ Override
200133 public void startProfiler (
201134 final @ NotNull ProfileLifecycle profileLifecycle ,
@@ -236,21 +169,24 @@ public void startProfiler(
236169 }
237170 }
238171
239- private void initScopes () {
172+ private void tryResolveScopes () {
240173 if ((scopes == null || scopes == NoOpScopes .getInstance ())
241174 && Sentry .getCurrentScopes () != NoOpScopes .getInstance ()) {
242- this .scopes = Sentry .getCurrentScopes ();
243- this .performanceCollector =
244- Sentry .getCurrentScopes ().getOptions ().getCompositePerformanceCollector ();
245- final @ Nullable RateLimiter rateLimiter = scopes .getRateLimiter ();
246- if (rateLimiter != null ) {
247- rateLimiter .addRateLimitObserver (this );
248- }
175+ onScopesAvailable (Sentry .getCurrentScopes ());
176+ }
177+ }
178+
179+ private void onScopesAvailable (final @ NotNull IScopes resolvedScopes ) {
180+ this .scopes = resolvedScopes ;
181+ this .performanceCollector = resolvedScopes .getOptions ().getCompositePerformanceCollector ();
182+ final @ Nullable RateLimiter rateLimiter = resolvedScopes .getRateLimiter ();
183+ if (rateLimiter != null ) {
184+ rateLimiter .addRateLimitObserver (this );
249185 }
250186 }
251187
252188 private void start () {
253- initScopes ();
189+ tryResolveScopes ();
254190
255191 // Debug.startMethodTracingSampling() is only available since Lollipop, but Android Profiler
256192 // causes crashes on api 21 -> https://github.com/getsentry/sentry-java/issues/3392
@@ -259,7 +195,7 @@ private void start() {
259195 // Let's initialize trace folder and profiling interval
260196 init ();
261197 // init() didn't create profiler, should never happen
262- if (profiler == null && perfettoProfiler == null ) {
198+ if (profiler == null ) {
263199 return ;
264200 }
265201
@@ -286,14 +222,7 @@ private void start() {
286222 } else {
287223 startProfileChunkTimestamp = new SentryNanotimeDate ();
288224 }
289- final AndroidProfiler .ProfileStartData startData ;
290- if (perfettoProfiler != null ) {
291- startData = perfettoProfiler .start (MAX_CHUNK_DURATION_MILLIS );
292- isPerfettoActive = startData != null ;
293- } else {
294- startData = profiler .start ();
295- isPerfettoActive = false ;
296- }
225+ final AndroidProfiler .ProfileStartData startData = profiler .start ();
297226 // check if profiling started
298227 if (startData == null ) {
299228 return ;
@@ -350,13 +279,13 @@ public void stopProfiler(final @NotNull ProfileLifecycle profileLifecycle) {
350279 }
351280
352281 private void stop (final boolean restartProfiler ) {
353- initScopes ();
282+ tryResolveScopes ();
354283 try (final @ NotNull ISentryLifecycleToken ignored = lock .acquire ()) {
355284 if (stopFuture != null ) {
356- stopFuture .cancel (false );
285+ stopFuture .cancel (true );
357286 }
358287 // check if profiler was created and it's running
359- if (( profiler == null && perfettoProfiler == null ) || !isRunning ) {
288+ if (profiler == null || !isRunning ) {
360289 // When the profiler is stopped due to an error (e.g. offline or rate limited), reset the
361290 // ids
362291 profilerId = SentryId .EMPTY_ID ;
@@ -375,18 +304,8 @@ private void stop(final boolean restartProfiler) {
375304 performanceCollectionData = performanceCollector .stop (chunkId .toString ());
376305 }
377306
378- final AndroidProfiler .ProfileEndData endData ;
379- final String platform ;
380- if (isPerfettoActive && perfettoProfiler != null ) {
381- endData = perfettoProfiler .endAndCollect ();
382- platform = ProfileChunk .PLATFORM_ANDROID ;
383- } else if (profiler != null ) {
384- endData = profiler .endAndCollect (false , performanceCollectionData );
385- platform = ProfileChunk .PLATFORM_ANDROID ;
386- } else {
387- endData = null ;
388- platform = ProfileChunk .PLATFORM_ANDROID ;
389- }
307+ final AndroidProfiler .ProfileEndData endData =
308+ profiler .endAndCollect (false , performanceCollectionData );
390309
391310 // check if profiler end successfully
392311 if (endData == null ) {
@@ -405,10 +324,7 @@ private void stop(final boolean restartProfiler) {
405324 endData .measurementsMap ,
406325 endData .traceFile ,
407326 startProfileChunkTimestamp ,
408- platform );
409- if (isPerfettoActive ) {
410- builder .setContentType ("perfetto" );
411- }
327+ ProfileChunk .PLATFORM_ANDROID );
412328 payloadBuilders .add (builder );
413329 }
414330 }
0 commit comments