Fix Androidx.tracing compat behavior, avoid class verification error

Fixes:204368464
Test: AndroidxTracingTraceTest on API 24

Note that the test can't run against tip of tree androidx.tracing long
term (and will have to revert to a stable dependency when benchmark
goes beta), but it's still useful for now.

Change-Id: I2b28acecd32e440c84f2814a5d748f047bfe9d68
diff --git a/benchmark/benchmark-macro/build.gradle b/benchmark/benchmark-macro/build.gradle
index 1a0de1c..ee51dc4 100644
--- a/benchmark/benchmark-macro/build.gradle
+++ b/benchmark/benchmark-macro/build.gradle
@@ -48,7 +48,7 @@
 
     implementation(project(":benchmark:benchmark-common"))
     implementation("androidx.profileinstaller:profileinstaller:1.0.3")
-    implementation("androidx.tracing:tracing-ktx:1.0.0")
+    implementation(project(":tracing:tracing-ktx"))
     implementation(libs.testCore)
     implementation(libs.testUiautomator)
 
diff --git a/benchmark/benchmark-macro/src/androidTest/java/androidx/benchmark/macro/perfetto/AndroidxTracingTraceTest.kt b/benchmark/benchmark-macro/src/androidTest/java/androidx/benchmark/macro/perfetto/AndroidxTracingTraceTest.kt
new file mode 100644
index 0000000..16d883e
--- /dev/null
+++ b/benchmark/benchmark-macro/src/androidTest/java/androidx/benchmark/macro/perfetto/AndroidxTracingTraceTest.kt
@@ -0,0 +1,165 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.benchmark.macro.perfetto
+
+import androidx.benchmark.macro.FileLinkingRule
+import androidx.benchmark.macro.Packages
+import androidx.benchmark.perfetto.PerfettoCapture
+import androidx.benchmark.perfetto.PerfettoHelper
+import androidx.benchmark.perfetto.PerfettoHelper.Companion.isAbiSupported
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.LargeTest
+import androidx.test.filters.SdkSuppress
+import androidx.tracing.Trace
+import androidx.tracing.trace
+import org.junit.After
+import org.junit.Assert.assertTrue
+import org.junit.Assume.assumeTrue
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import kotlin.test.assertEquals
+import kotlin.test.assertTrue
+
+/**
+ * Tests for androidx.tracing.Trace, which validate actual trace content
+ *
+ * These can't be defined in the androidx.tracing library, as Trace capture / validation APIs
+ * are only available to the benchmark group.
+ */
+@SdkSuppress(minSdkVersion = 23)
+@RunWith(AndroidJUnit4::class)
+class AndroidxTracingTraceTest {
+    @get:Rule
+    val linkRule = FileLinkingRule()
+
+    @Before
+    @After
+    fun cleanup() {
+        PerfettoHelper.stopAllPerfettoProcesses()
+    }
+
+    @LargeTest
+    @Test
+    fun captureAndValidateTrace() {
+        assumeTrue(isAbiSupported())
+
+        val traceFilePath = linkRule.createReportedTracePath(Packages.TEST)
+        val perfettoCapture = PerfettoCapture()
+
+        verifyTraceEnable(false)
+
+        perfettoCapture.start(listOf(Packages.TEST))
+
+        assertTrue(
+            Trace.isEnabled(),
+            "In-process tracing should be enabled immediately after trace capture is started"
+        )
+
+        repeat(20) {
+            "$PREFIX$it".also { label ->
+                // actual test content. This is done in the middle of the other sections
+                // to isolate it from trace truncation issues
+                if (it == 10) {
+                    Trace.setCounter("${PREFIX}counter", 1)
+                    Trace.beginSection("${PREFIX}beginSection")
+                    Trace.beginAsyncSection("${PREFIX}beginAsyncSection", 9827)
+                    Thread.sleep(50)
+                    Trace.setCounter("${PREFIX}counter", 0)
+                    Trace.endSection()
+                    Trace.endAsyncSection("${PREFIX}beginAsyncSection", 9827)
+                }
+
+                // trace sections before and after actual test content, to look for problems in
+                // front/back trace truncation. If these sections are missing, it's most likely
+                // issues in trace capture
+                trace(label) { Thread.sleep(50) }
+            }
+        }
+
+        perfettoCapture.stop(traceFilePath)
+
+        val queryResult = PerfettoTraceProcessor.rawQuery(
+            absoluteTracePath = traceFilePath,
+            query = QUERY
+        )
+        val matchingSlices = Slice.parseListFromQueryResult(queryResult)
+        assertEquals(
+            List(10) { "$PREFIX$it" } +
+                listOf(
+                    "${PREFIX}counter1.0",
+                    "${PREFIX}beginSection",
+                    "${PREFIX}beginAsyncSection",
+                    "${PREFIX}counter0.0",
+                ) +
+                List(10) { "$PREFIX${it + 10}" },
+            matchingSlices.map { it.name }
+        )
+        matchingSlices
+            .forEach {
+                if (it.name.startsWith("${PREFIX}counter")) {
+                    assertEquals(0L, it.dur) // counter has no length
+                } else {
+                    assertTrue(it.dur > 30_000_000) // should be at least 30ms
+                }
+            }
+    }
+    companion object {
+        const val PREFIX = "AndroidxTracingTraceTest_"
+
+        const val QUERY = """
+            ------ select all relevant standard slices
+            SELECT
+                slice.name as name,
+                slice.ts as ts,
+                slice.dur as dur
+            FROM slice
+                INNER JOIN thread_track on slice.track_id = thread_track.id
+                INNER JOIN thread USING(utid)
+                INNER JOIN process USING(upid)
+            WHERE
+                slice.name LIKE "$PREFIX%" AND
+                process.name LIKE "androidx.benchmark.macro.test"
+            UNION
+            ------ add in async slices
+            SELECT
+                slice.name as name,
+                slice.ts as ts,
+                slice.dur as dur
+            FROM slice
+                INNER JOIN process_track on slice.track_id = process_track.id
+                INNER JOIN process USING(upid)
+            WHERE
+                slice.name LIKE "$PREFIX%" AND
+                process.name LIKE "androidx.benchmark.macro.test"
+            UNION
+            ------ add in the counter values, with value prepended to name
+            SELECT
+                counter_track.name || counter.value as name,
+                counter.ts as ts,
+                0 as dur
+            FROM counter
+                INNER JOIN counter_track on counter.track_id = counter_track.id
+            WHERE
+                counter_track.name LIKE "${PREFIX}counter"
+            ------ order the whole thing by timestamp
+            ORDER BY
+                ts
+        """
+    }
+}
diff --git a/tracing/tracing/src/main/java/androidx/tracing/Trace.java b/tracing/tracing/src/main/java/androidx/tracing/Trace.java
index 0520f2e..03c6ead 100644
--- a/tracing/tracing/src/main/java/androidx/tracing/Trace.java
+++ b/tracing/tracing/src/main/java/androidx/tracing/Trace.java
@@ -16,7 +16,6 @@
 
 package androidx.tracing;
 
-import android.annotation.SuppressLint;
 import android.os.Build;
 import android.util.Log;
 
@@ -55,12 +54,10 @@
      *
      * @return true if tracing is currently enabled, false otherwise
      */
-    @SuppressLint("NewApi")
     public static boolean isEnabled() {
         if (Build.VERSION.SDK_INT >= 29) {
             return TraceApi29Impl.isEnabled();
         }
-
         return isEnabledFallback();
     }
 
@@ -103,16 +100,12 @@
      * @param methodName The method name to appear in the trace.
      * @param cookie     Unique identifier for distinguishing simultaneous events
      */
-    @SuppressLint("NewApi")
     public static void beginAsyncSection(@NonNull String methodName, int cookie) {
-        try {
-            if (sAsyncTraceBeginMethod == null) {
-                TraceApi29Impl.beginAsyncSection(methodName, cookie);
-                return;
-            }
-        } catch (NoSuchMethodError | NoClassDefFoundError ignore) {
+        if (Build.VERSION.SDK_INT >= 29) {
+            TraceApi29Impl.beginAsyncSection(methodName, cookie);
+        } else {
+            beginAsyncSectionFallback(methodName, cookie);
         }
-        beginAsyncSectionFallback(methodName, cookie);
     }
 
     /**
@@ -123,16 +116,12 @@
      * @param methodName The method name to appear in the trace.
      * @param cookie     Unique identifier for distinguishing simultaneous events
      */
-    @SuppressLint("NewApi")
     public static void endAsyncSection(@NonNull String methodName, int cookie) {
-        try {
-            if (sAsyncTraceEndMethod == null) {
-                TraceApi29Impl.endAsyncSection(methodName, cookie);
-                return;
-            }
-        } catch (NoSuchMethodError | NoClassDefFoundError ignore) {
+        if (Build.VERSION.SDK_INT >= 29) {
+            TraceApi29Impl.endAsyncSection(methodName, cookie);
+        } else {
+            endAsyncSectionFallback(methodName, cookie);
         }
-        endAsyncSectionFallback(methodName, cookie);
     }
 
     /**
@@ -141,16 +130,12 @@
      * @param counterName  The counter name to appear in the trace.
      * @param counterValue The counter value.
      */
-    @SuppressLint("NewApi")
     public static void setCounter(@NonNull String counterName, int counterValue) {
-        try {
-            if (sTraceCounterMethod == null) {
-                TraceApi29Impl.setCounter(counterName, counterValue);
-                return;
-            }
-        } catch (NoSuchMethodError | NoClassDefFoundError ignore) {
+        if (Build.VERSION.SDK_INT >= 29) {
+            TraceApi29Impl.setCounter(counterName, counterValue);
+        } else {
+            setCounterFallback(counterName, counterValue);
         }
-        setCounterFallback(counterName, counterValue);
     }
 
     private static boolean isEnabledFallback() {