diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 7d108273d..40c26140b 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" 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..4c2d2d23b 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 = "ProfilingManager"; + @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -69,5 +77,53 @@ 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( + "ProfileTest", + "Received profiling result file=" + profilingResult.getResultFilePath()); + setupProfileUploadWorker(profilingResult.getResultFilePath()); + } else { + Log.e( + "ProfileTest", + "Profiling failed errorcode=" + + profilingResult.getErrorCode() + + " errormsg=" + + profilingResult.getErrorMessage()); + } + } + }; + profilingManager.registerForAllProfilingResults(mainExecutor, resultCallback); + profilingManager.addProfilingTriggers(triggers); + + // [START_EXCLUDE silent] + Choreographer.getInstance().postFrameCallback((f) -> { + // This will cause the TRIGGER_TYPE_APP_FULLY_DRAWN to be emitted. + reportFullyDrawn(); + }); + // [END_EXCLUDE silent] + } + // [END android_profiling_manager_triggered_trace_java] + + // [START android_profiling_manager_triggered_trace_setup_upload_job_java] + public void setupProfileUploadWorker(String resultFilePath) { + // Setup job to upload the profiling result file. + } + // [END android_profiling_manager_triggered_trace_setup_upload_job_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..b54ba67b0 100644 --- a/misc/src/main/java/com/example/snippets/profiling/ProfilingManagerKotlinSnippets.kt +++ b/misc/src/main/java/com/example/snippets/profiling/ProfilingManagerKotlinSnippets.kt @@ -20,20 +20,29 @@ import android.app.Activity import android.os.Build import android.os.Bundle import android.os.CancellationSignal +import android.os.ProfilingManager import android.os.ProfilingResult +import android.os.ProfilingTrigger import android.util.Log +import android.view.Choreographer import androidx.annotation.RequiresApi import androidx.core.os.BufferFillPolicy import androidx.core.os.SystemTraceRequestBuilder import androidx.core.os.requestProfiling import androidx.tracing.Trace +import java.util.ArrayList 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,51 @@ 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( + "ProfileTest", + "Received profiling result file=" + profilingResult.resultFilePath + ) + setupProfileUploadWorker(profilingResult.resultFilePath) + } else { + Log.e( + "ProfileTest", + "Profiling failed errorcode=" + profilingResult.errorCode + " errormsg=" + profilingResult.errorMessage + ) + } + } + + profilingManager.registerForAllProfilingResults(mainExecutor, resultCallback) + profilingManager.addProfilingTriggers(triggers) + + // [START_EXCLUDE silent] + Choreographer.getInstance().postFrameCallback { frameTimeNanos -> + // This will cause the TRIGGER_TYPE_APP_FULLY_DRAWN to be emitted. + reportFullyDrawn() + } + // [END_EXCLUDE silent] + } + // [END android_profiling_manager_triggered_trace] + + // [START android_profiling_manager_triggered_trace_setup_upload_job] + fun setupProfileUploadWorker(resultFilePath: String?) { + // Setup job to upload the profiling result file. + } + // [END android_profiling_manager_triggered_trace_setup_upload_job] } }