From 22866005923deb818b15e06ac7d1c6786ffd549f Mon Sep 17 00:00:00 2001 From: Edgar Arriaga Date: Wed, 12 Nov 2025 20:27:01 +0000 Subject: [PATCH 1/5] Add snippets for trigger based profiling section of ProfilingManager docs --- .../ProfilingManagerJavaSnippets.java | 42 +++++++++++++++++++ .../ProfilingManagerKotlinSnippets.kt | 38 +++++++++++++++++ 2 files changed, 80 insertions(+) diff --git a/misc/src/main/java/com/example/snippets/profiling/ProfilingManagerJavaSnippets.java b/misc/src/main/java/com/example/snippets/profiling/ProfilingManagerJavaSnippets.java index 4dae4d353..6b66ae367 100644 --- a/misc/src/main/java/com/example/snippets/profiling/ProfilingManagerJavaSnippets.java +++ b/misc/src/main/java/com/example/snippets/profiling/ProfilingManagerJavaSnippets.java @@ -2,12 +2,18 @@ import android.app.Activity; import android.os.Bundle; +import android.os.ProfilingManager; +import android.os.ProfilingTrigger; import android.util.Log; +import java.util.List; +import java.util.ArrayList; import java.util.function.Consumer; import java.util.concurrent.Executor; +import java.util.concurrent.Executors; import android.os.ProfilingResult; import java.util.concurrent.Executors; import android.os.CancellationSignal; +import android.view.Choreographer; import androidx.tracing.Trace; import androidx.core.os.Profiling; import androidx.core.os.SystemTraceRequestBuilder; @@ -16,6 +22,8 @@ public class ProfilingManagerJavaSnippets { public class MainActivityJava extends Activity { + public static final String TAG = "EDGAR"; + @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -69,5 +77,39 @@ public void accept(ProfilingResult profilingResult) { stopSignal.cancel(); } // [END android_profiling_manager_record_system_trace_java] + + // [START android_profiling_manager_triggered_trace_java] + public void recordWithTrigger() { + ProfilingManager profilingManager = getApplicationContext().getSystemService( + ProfilingManager.class); + List triggers = new ArrayList<>(); + ProfilingTrigger.Builder triggerBuilder = new ProfilingTrigger.Builder( + ProfilingTrigger.TRIGGER_TYPE_APP_FULLY_DRAWN); + triggerBuilder.setRateLimitingPeriodHours(1); + triggers.add(triggerBuilder.build()); + + Executor mainExecutor = Executors.newSingleThreadExecutor(); + Consumer resultCallback = + new Consumer() { + @Override + public void accept(ProfilingResult profilingResult) { + // ... + if (profilingResult.getErrorCode() == ProfilingResult.ERROR_NONE) { + Log.d(TAG, + "Received profiling result. file: " + profilingResult.getResultFilePath()); + } + } + }; + profilingManager.registerForAllProfilingResults(mainExecutor, resultCallback); + profilingManager.addProfilingTriggers(triggers); + + Choreographer.getInstance().postFrameCallback((f) -> { + // This will cause the TRIGGER_TYPE_APP_FULLY_DRAWN to be emitted. + reportFullyDrawn(); + }); + } + // [END android_profiling_manager_triggered_trace_java] + + } } diff --git a/misc/src/main/java/com/example/snippets/profiling/ProfilingManagerKotlinSnippets.kt b/misc/src/main/java/com/example/snippets/profiling/ProfilingManagerKotlinSnippets.kt index f3f0ad99c..85600b4d5 100644 --- a/misc/src/main/java/com/example/snippets/profiling/ProfilingManagerKotlinSnippets.kt +++ b/misc/src/main/java/com/example/snippets/profiling/ProfilingManagerKotlinSnippets.kt @@ -21,19 +21,28 @@ import android.os.Build import android.os.Bundle import android.os.CancellationSignal import android.os.ProfilingResult +import android.os.ProfilingManager +import android.os.ProfilingTrigger import android.util.Log +import java.util.ArrayList import androidx.annotation.RequiresApi import androidx.core.os.BufferFillPolicy import androidx.core.os.SystemTraceRequestBuilder import androidx.core.os.requestProfiling +import android.view.Choreographer import androidx.tracing.Trace import java.util.concurrent.Executor +import java.util.concurrent.Executors import java.util.function.Consumer import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.asExecutor class ProfilingManagerKotlinSnippets { class MainActivity : Activity() { + companion object { + const val TAG = "MyApp" + } + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) sampleRecordSystemTrace() @@ -81,5 +90,34 @@ class ProfilingManagerKotlinSnippets { // Computations you want to profile } // [END android_profiling_manager_record_system_trace_kotlin] + + // [START android_profiling_manager_triggered_trace] + fun recordWithTrigger() { + val profilingManager = applicationContext.getSystemService(ProfilingManager::class.java) + + val triggers = ArrayList() + + val triggerBuilder = ProfilingTrigger.Builder(ProfilingTrigger.TRIGGER_TYPE_APP_FULLY_DRAWN) + .setRateLimitingPeriodHours(1) + + triggers.add(triggerBuilder.build()) + + val mainExecutor: Executor = Executors.newSingleThreadExecutor() + + val resultCallback = Consumer { profilingResult -> + if (profilingResult.errorCode == ProfilingResult.ERROR_NONE) { + Log.d(TAG, "Received profiling result. file: ${profilingResult.resultFilePath}") + } + } + + profilingManager.registerForAllProfilingResults(mainExecutor, resultCallback) + profilingManager.addProfilingTriggers(triggers) + + Choreographer.getInstance().postFrameCallback { frameTimeNanos -> + // This will cause the TRIGGER_TYPE_APP_FULLY_DRAWN to be emitted. + reportFullyDrawn() + } + } + // [END android_profiling_manager_triggered_trace] } } From 47e507603d926cd9859d3166707b1d3389759b05 Mon Sep 17 00:00:00 2001 From: edgararriagag <211581399+edgararriagag@users.noreply.github.com> Date: Wed, 12 Nov 2025 20:34:21 +0000 Subject: [PATCH 2/5] Apply Spotless --- .../snippets/profiling/ProfilingManagerKotlinSnippets.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/misc/src/main/java/com/example/snippets/profiling/ProfilingManagerKotlinSnippets.kt b/misc/src/main/java/com/example/snippets/profiling/ProfilingManagerKotlinSnippets.kt index 85600b4d5..775c5dd3e 100644 --- a/misc/src/main/java/com/example/snippets/profiling/ProfilingManagerKotlinSnippets.kt +++ b/misc/src/main/java/com/example/snippets/profiling/ProfilingManagerKotlinSnippets.kt @@ -20,17 +20,17 @@ import android.app.Activity import android.os.Build import android.os.Bundle import android.os.CancellationSignal -import android.os.ProfilingResult import android.os.ProfilingManager +import android.os.ProfilingResult import android.os.ProfilingTrigger import android.util.Log -import java.util.ArrayList +import android.view.Choreographer import androidx.annotation.RequiresApi import androidx.core.os.BufferFillPolicy import androidx.core.os.SystemTraceRequestBuilder import androidx.core.os.requestProfiling -import android.view.Choreographer import androidx.tracing.Trace +import java.util.ArrayList import java.util.concurrent.Executor import java.util.concurrent.Executors import java.util.function.Consumer From 88e7e0a44216d8d6fbe68854f7671f84a9f7cb5e Mon Sep 17 00:00:00 2001 From: Edgar Arriaga Date: Wed, 12 Nov 2025 20:37:07 +0000 Subject: [PATCH 3/5] Fix tag name --- .../snippets/profiling/ProfilingManagerJavaSnippets.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/misc/src/main/java/com/example/snippets/profiling/ProfilingManagerJavaSnippets.java b/misc/src/main/java/com/example/snippets/profiling/ProfilingManagerJavaSnippets.java index 6b66ae367..c28114f28 100644 --- a/misc/src/main/java/com/example/snippets/profiling/ProfilingManagerJavaSnippets.java +++ b/misc/src/main/java/com/example/snippets/profiling/ProfilingManagerJavaSnippets.java @@ -22,7 +22,7 @@ public class ProfilingManagerJavaSnippets { public class MainActivityJava extends Activity { - public static final String TAG = "EDGAR"; + public static final String TAG = "ProfilingManager"; @Override public void onCreate(Bundle savedInstanceState) { From 416e1243f92d8339775d0bd1d7de222da0390e45 Mon Sep 17 00:00:00 2001 From: Edgar Arriaga Date: Wed, 12 Nov 2025 22:51:50 +0000 Subject: [PATCH 4/5] Bump mindSdk so that new ProfilingManager snippets compile --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 3a2de6ba9..ebdd94276 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -68,7 +68,7 @@ material3-adaptive-navigation-suite = "1.4.0" media3 = "1.8.0" media3Ui = "1.8.0" # @keep -minSdk = "35" +minSdk = "36" okHttp = "5.2.1" playServicesWearable = "19.0.0" protobuf = "4.32.1" From f86ffefe136d9f5f796355f2959ecd49a31db2b1 Mon Sep 17 00:00:00 2001 From: Edgar Arriaga Date: Wed, 12 Nov 2025 23:20:11 +0000 Subject: [PATCH 5/5] Add snippets for anr case study for ProfilingManager v2 docs --- .../ProfilingManagerJavaSnippets.java | 85 ++++++++++++++++++- misc/src/main/res/layout/activity_main.xml | 7 ++ 2 files changed, 90 insertions(+), 2 deletions(-) diff --git a/misc/src/main/java/com/example/snippets/profiling/ProfilingManagerJavaSnippets.java b/misc/src/main/java/com/example/snippets/profiling/ProfilingManagerJavaSnippets.java index c28114f28..b269faad6 100644 --- a/misc/src/main/java/com/example/snippets/profiling/ProfilingManagerJavaSnippets.java +++ b/misc/src/main/java/com/example/snippets/profiling/ProfilingManagerJavaSnippets.java @@ -18,10 +18,13 @@ import androidx.core.os.Profiling; import androidx.core.os.SystemTraceRequestBuilder; import androidx.core.os.BufferFillPolicy; +import com.example.snippets.R; public class ProfilingManagerJavaSnippets { public class MainActivityJava extends Activity { - + // [START android_profiling_manager_anr_case_study_java_snippet_2] + private static final int NETWORK_TIMEOUT_MILLISECS = 2000; + // [END android_profiling_manager_anr_case_study_java_snippet_2] public static final String TAG = "ProfilingManager"; @Override @@ -110,6 +113,84 @@ public void accept(ProfilingResult profilingResult) { } // [END android_profiling_manager_triggered_trace_java] - + // [START android_profiling_manager_anr_case_study_java_snippet_1] + public void addANRTrigger() { + ProfilingManager profilingManager = getApplicationContext().getSystemService(ProfilingManager.class); + List triggers = new ArrayList<>(); + ProfilingTrigger.Builder triggerBuilder = new ProfilingTrigger.Builder(ProfilingTrigger.TRIGGER_TYPE_ANR); + triggers.add(triggerBuilder.build()); + Executor mainExecutor = Executors.newSingleThreadExecutor(); + Consumer resultCallback = + profilingResult -> { + // Handle uploading trace to your back-end + }; + profilingManager.registerForAllProfilingResults(mainExecutor, resultCallback); + profilingManager.addProfilingTriggers(triggers); + } + // [END android_profiling_manager_anr_case_study_java_snippet_1] + + // [START android_profiling_manager_anr_case_study_java_snippet_2] + public void setupButtonCallback() { + findViewById(R.id.submit).setOnClickListener(submitButtonView -> { + Trace.beginSection("MyApp:SubmitButton"); + onClickSubmit(); + Trace.endSection(); + }); + } + + public void onClickSubmit() { + prepareNetworkRequest(); + + boolean networkRequestSuccess = false; + int maxAttempts = 10; + while (!networkRequestSuccess && maxAttempts > 0) { + networkRequestSuccess = performNetworkRequest(NETWORK_TIMEOUT_MILLISECS); + maxAttempts--; + } + + if (networkRequestSuccess) { + handleNetworkResponse(); + } + } + + boolean performNetworkRequest(int timeoutMiliseconds) { + // [START_EXCLUDE] + cpuIntensiveComputation(20); + try { + if (Math.random() < 0.2) { + // Simulate performing a network request by waiting a random period of time + int networkRequestTimeMs = (int)(Math.random() * timeoutMiliseconds); + Thread.sleep(networkRequestTimeMs); + return true; + } else { + // Simulate a timeout + Thread.sleep(timeoutMiliseconds); + } + } catch (InterruptedException e) {} + return false; + // [END_EXCLUDE] + } + + // [START_EXCLUDE silent] + void cpuIntensiveComputation(int durationMs) { + long start = System.currentTimeMillis(); + while (System.currentTimeMillis() - start < durationMs) {} + } + // [END_EXCLUDE silent] + + void prepareNetworkRequest() { + // [START_EXCLUDE] + cpuIntensiveComputation(1000); + // [END_EXCLUDE] + } + + public void handleNetworkResponse() { + Trace.beginSection("handleNetworkResponse"); + // [START_EXCLUDE] + cpuIntensiveComputation(2000); + // [END_EXCLUDE] + Trace.endSection(); + } + // [END android_profiling_manager_anr_case_study_java_snippet_2] } } diff --git a/misc/src/main/res/layout/activity_main.xml b/misc/src/main/res/layout/activity_main.xml index dbfa14759..1366cf438 100644 --- a/misc/src/main/res/layout/activity_main.xml +++ b/misc/src/main/res/layout/activity_main.xml @@ -40,4 +40,11 @@ app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" /> +