Added support to generate startup-prof.txt in BaselineProfileRule

This PR adds a profile type parameter when generating a baseline
profile. When the profile type is `STARTUP` the generated file is a
startup-prof.txt. The internal format is the same HRF of baseline
profile.

Relnote: Added profile type parameter when generating baseline profiles
Bug: 275093123
Test: ./gradlew :benchmark:integration-tests:baselineprofile-library-consumer:testBaselineProfileGeneration :benchmark:integration-tests:baselineprofile-flavor-consumer:testBaselineProfileGeneration :benchmark:integration-tests:baselineprofile-consumer:testBaselineProfileGeneration :benchmark:benchmark-baseline-profile-gradle-plugin:test
Change-Id: Ie20d730efea37940bf9df519c86cdb29a4074d34
diff --git a/benchmark/benchmark-common/src/main/java/androidx/benchmark/Arguments.kt b/benchmark/benchmark-common/src/main/java/androidx/benchmark/Arguments.kt
index 7af3fa9..8b9c181 100644
--- a/benchmark/benchmark-common/src/main/java/androidx/benchmark/Arguments.kt
+++ b/benchmark/benchmark-common/src/main/java/androidx/benchmark/Arguments.kt
@@ -193,7 +193,7 @@
             arguments.getBenchmarkArgument("killProcessDelayMillis")?.toLong() ?: 0L
 
         enableStartupProfiles =
-            arguments.getBenchmarkArgument("startupProfiles.enable")?.toBoolean() ?: false
+            arguments.getBenchmarkArgument("startupProfiles.enable")?.toBoolean() ?: true
 
         strictStartupProfiles =
             arguments.getBenchmarkArgument("startupProfiles.strict")?.toBoolean() ?: false
diff --git a/benchmark/benchmark-macro-junit4/api/current.txt b/benchmark/benchmark-macro-junit4/api/current.txt
index 3358929..0bcc71e 100644
--- a/benchmark/benchmark-macro-junit4/api/current.txt
+++ b/benchmark/benchmark-macro-junit4/api/current.txt
@@ -4,7 +4,8 @@
   @RequiresApi(28) public final class BaselineProfileRule implements org.junit.rules.TestRule {
     ctor public BaselineProfileRule();
     method public org.junit.runners.model.Statement apply(org.junit.runners.model.Statement base, org.junit.runner.Description description);
-    method public void collectBaselineProfile(String packageName, optional int iterations, optional String? outputFilePrefix, optional kotlin.jvm.functions.Function1<? super java.lang.String,java.lang.Boolean>? filterPredicate, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
+    method public void collectBaselineProfile(String packageName, optional int iterations, optional String? outputFilePrefix, optional boolean includeInStartupProfile, optional kotlin.jvm.functions.Function1<? super java.lang.String,java.lang.Boolean>? filterPredicate, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
+    method public void collectBaselineProfile(String packageName, optional int iterations, optional String? outputFilePrefix, optional boolean includeInStartupProfile, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
     method public void collectBaselineProfile(String packageName, optional int iterations, optional String? outputFilePrefix, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
     method public void collectBaselineProfile(String packageName, optional int iterations, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
     method public void collectBaselineProfile(String packageName, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
diff --git a/benchmark/benchmark-macro-junit4/api/public_plus_experimental_current.txt b/benchmark/benchmark-macro-junit4/api/public_plus_experimental_current.txt
index 6b25fae..bd292b7 100644
--- a/benchmark/benchmark-macro-junit4/api/public_plus_experimental_current.txt
+++ b/benchmark/benchmark-macro-junit4/api/public_plus_experimental_current.txt
@@ -4,12 +4,14 @@
   @RequiresApi(28) public final class BaselineProfileRule implements org.junit.rules.TestRule {
     ctor public BaselineProfileRule();
     method public org.junit.runners.model.Statement apply(org.junit.runners.model.Statement base, org.junit.runner.Description description);
-    method public void collectBaselineProfile(String packageName, optional int iterations, optional String? outputFilePrefix, optional kotlin.jvm.functions.Function1<? super java.lang.String,java.lang.Boolean>? filterPredicate, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
+    method public void collectBaselineProfile(String packageName, optional int iterations, optional String? outputFilePrefix, optional boolean includeInStartupProfile, optional kotlin.jvm.functions.Function1<? super java.lang.String,java.lang.Boolean>? filterPredicate, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
+    method public void collectBaselineProfile(String packageName, optional int iterations, optional String? outputFilePrefix, optional boolean includeInStartupProfile, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
     method public void collectBaselineProfile(String packageName, optional int iterations, optional String? outputFilePrefix, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
     method public void collectBaselineProfile(String packageName, optional int iterations, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
     method public void collectBaselineProfile(String packageName, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
-    method @androidx.benchmark.macro.ExperimentalStableBaselineProfilesApi public void collectStableBaselineProfile(String packageName, int maxIterations, optional int stableIterations, optional String? outputFilePrefix, optional boolean strictStability, optional kotlin.jvm.functions.Function1<? super java.lang.String,java.lang.Boolean>? filterPredicate, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
-    method @androidx.benchmark.macro.ExperimentalStableBaselineProfilesApi public void collectStableBaselineProfile(String packageName, int maxIterations, optional int stableIterations, optional String? outputFilePrefix, optional boolean strictStability, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
+    method @androidx.benchmark.macro.ExperimentalStableBaselineProfilesApi public void collectStableBaselineProfile(String packageName, int maxIterations, optional int stableIterations, optional String? outputFilePrefix, optional boolean includeInStartupProfile, optional boolean strictStability, optional kotlin.jvm.functions.Function1<? super java.lang.String,java.lang.Boolean>? filterPredicate, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
+    method @androidx.benchmark.macro.ExperimentalStableBaselineProfilesApi public void collectStableBaselineProfile(String packageName, int maxIterations, optional int stableIterations, optional String? outputFilePrefix, optional boolean includeInStartupProfile, optional boolean strictStability, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
+    method @androidx.benchmark.macro.ExperimentalStableBaselineProfilesApi public void collectStableBaselineProfile(String packageName, int maxIterations, optional int stableIterations, optional String? outputFilePrefix, optional boolean includeInStartupProfile, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
     method @androidx.benchmark.macro.ExperimentalStableBaselineProfilesApi public void collectStableBaselineProfile(String packageName, int maxIterations, optional int stableIterations, optional String? outputFilePrefix, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
     method @androidx.benchmark.macro.ExperimentalStableBaselineProfilesApi public void collectStableBaselineProfile(String packageName, int maxIterations, optional int stableIterations, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
     method @androidx.benchmark.macro.ExperimentalStableBaselineProfilesApi public void collectStableBaselineProfile(String packageName, int maxIterations, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
diff --git a/benchmark/benchmark-macro-junit4/api/restricted_current.txt b/benchmark/benchmark-macro-junit4/api/restricted_current.txt
index 3358929..0bcc71e 100644
--- a/benchmark/benchmark-macro-junit4/api/restricted_current.txt
+++ b/benchmark/benchmark-macro-junit4/api/restricted_current.txt
@@ -4,7 +4,8 @@
   @RequiresApi(28) public final class BaselineProfileRule implements org.junit.rules.TestRule {
     ctor public BaselineProfileRule();
     method public org.junit.runners.model.Statement apply(org.junit.runners.model.Statement base, org.junit.runner.Description description);
-    method public void collectBaselineProfile(String packageName, optional int iterations, optional String? outputFilePrefix, optional kotlin.jvm.functions.Function1<? super java.lang.String,java.lang.Boolean>? filterPredicate, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
+    method public void collectBaselineProfile(String packageName, optional int iterations, optional String? outputFilePrefix, optional boolean includeInStartupProfile, optional kotlin.jvm.functions.Function1<? super java.lang.String,java.lang.Boolean>? filterPredicate, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
+    method public void collectBaselineProfile(String packageName, optional int iterations, optional String? outputFilePrefix, optional boolean includeInStartupProfile, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
     method public void collectBaselineProfile(String packageName, optional int iterations, optional String? outputFilePrefix, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
     method public void collectBaselineProfile(String packageName, optional int iterations, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
     method public void collectBaselineProfile(String packageName, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
diff --git a/benchmark/benchmark-macro-junit4/src/main/java/androidx/benchmark/macro/junit4/BaselineProfileRule.kt b/benchmark/benchmark-macro-junit4/src/main/java/androidx/benchmark/macro/junit4/BaselineProfileRule.kt
index b9be975..12dca06 100644
--- a/benchmark/benchmark-macro-junit4/src/main/java/androidx/benchmark/macro/junit4/BaselineProfileRule.kt
+++ b/benchmark/benchmark-macro-junit4/src/main/java/androidx/benchmark/macro/junit4/BaselineProfileRule.kt
@@ -108,6 +108,12 @@
      * @param outputFilePrefix An optional file name prefix used when creating the output
      *    file with the contents of the human readable baseline profile.
      *    For example: `outputFilePrefix-baseline-prof.txt`
+     * @param includeInStartupProfile determines whether the generated profile should be also used
+     *   as a startup profile. A startup profile is utilized during the build process in order to
+     *   determine which classes are needed in the primary dex to optimize the startup time. This
+     *   flag should be used only for startup flows, such as main application startup pre and post
+     *   login or other entry points of the app. Note that methods collected in a startup profiles
+     *   are also utilized for baseline profiles.
      * @param filterPredicate Function used to filter individual rules / lines of the baseline
      *   profile. By default, no filters are applied. Note that this works only when the target
      *   application's code is not obfuscated.
@@ -118,6 +124,7 @@
         packageName: String,
         iterations: Int = 3,
         outputFilePrefix: String? = null,
+        includeInStartupProfile: Boolean = false,
         filterPredicate: ((String) -> Boolean)? = null,
         profileBlock: MacrobenchmarkScope.() -> Unit
     ) {
@@ -125,6 +132,7 @@
             uniqueName = outputFilePrefix ?: currentDescription.toUniqueName(),
             packageName = packageName,
             iterations = iterations,
+            includeInStartupProfile = includeInStartupProfile,
             filterPredicate = filterPredicate,
             profileBlock = profileBlock
         )
@@ -141,6 +149,12 @@
      * @param outputFilePrefix An optional file name prefix used when creating the output
      *    file with the contents of the human readable baseline profile.
      *    For example: `outputFilePrefix-baseline-prof.txt`
+     * @param includeInStartupProfile determines whether the generated profile should be also used
+     *   as a startup profile. A startup profile is utilized during the build process in order to
+     *   determine which classes are needed in the primary dex to optimize the startup time. This
+     *   flag should be used only for startup flows, such as main application startup pre and post
+     *   login or other entry points of the app. Note that methods collected in a startup profiles
+     *   are also utilized for baseline profiles.
      * @param strictStability Enforce if the generated profile was stable
      * @param filterPredicate Function used to filter individual rules / lines of the baseline
      *  profile. By default, no filters are applied. Note that this works only when the target
@@ -154,6 +168,7 @@
         maxIterations: Int,
         stableIterations: Int = 3,
         outputFilePrefix: String? = null,
+        includeInStartupProfile: Boolean = false,
         strictStability: Boolean = false,
         filterPredicate: ((String) -> Boolean)? = null,
         profileBlock: MacrobenchmarkScope.() -> Unit
@@ -163,6 +178,7 @@
             packageName = packageName,
             stableIterations = stableIterations,
             maxIterations = maxIterations,
+            includeInStartupProfile = includeInStartupProfile,
             strictStability = strictStability,
             filterPredicate = filterPredicate,
             profileBlock = profileBlock
diff --git a/benchmark/benchmark-macro/api/restricted_current.txt b/benchmark/benchmark-macro/api/restricted_current.txt
index 2176d91..a5eae3b 100644
--- a/benchmark/benchmark-macro/api/restricted_current.txt
+++ b/benchmark/benchmark-macro/api/restricted_current.txt
@@ -10,8 +10,8 @@
   }
 
   public final class BaselineProfilesKt {
-    method @RequiresApi(28) @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static void collectStableBaselineProfile(String uniqueName, String packageName, int stableIterations, int maxIterations, optional boolean strictStability, kotlin.jvm.functions.Function1<? super java.lang.String,java.lang.Boolean>? filterPredicate, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
-    method @RequiresApi(28) @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static void collectStableBaselineProfile(String uniqueName, String packageName, int stableIterations, int maxIterations, kotlin.jvm.functions.Function1<? super java.lang.String,java.lang.Boolean>? filterPredicate, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
+    method @RequiresApi(28) @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static void collectStableBaselineProfile(String uniqueName, String packageName, int stableIterations, int maxIterations, optional boolean strictStability, boolean includeInStartupProfile, kotlin.jvm.functions.Function1<? super java.lang.String,java.lang.Boolean>? filterPredicate, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
+    method @RequiresApi(28) @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static void collectStableBaselineProfile(String uniqueName, String packageName, int stableIterations, int maxIterations, boolean includeInStartupProfile, kotlin.jvm.functions.Function1<? super java.lang.String,java.lang.Boolean>? filterPredicate, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
   }
 
   @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public final class BatteryCharge {
diff --git a/benchmark/benchmark-macro/src/androidTest/java/androidx/benchmark/macro/StartupProfilesTest.kt b/benchmark/benchmark-macro/src/androidTest/java/androidx/benchmark/macro/StartupProfilesTest.kt
deleted file mode 100644
index f99856a..0000000
--- a/benchmark/benchmark-macro/src/androidTest/java/androidx/benchmark/macro/StartupProfilesTest.kt
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright 2022 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
-
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SmallTest
-import org.junit.Assert.assertEquals
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@RunWith(AndroidJUnit4::class)
-@SmallTest
-class StartupProfilesTest {
-    @Test
-    fun startupProfiles() {
-        // https://youtrack.jetbrains.com/issue/KT-2425
-        val dollar = "$"
-        val profile = """
-            Landroidx/Foo/Bar;
-            Lfoo/bar/Baz$dollar<Suffix>;
-            HSPLjava/io/DataOutputStream;->writeByte(I)V+]Ljava/io/OutputStream;missing_types
-        """.trimIndent()
-
-        val startupRules = startupProfile(profile, includeStartupOnly = false)
-        val expectedRules = """
-            SLandroidx/Foo/Bar;
-            SLfoo/bar/Baz;
-            SLjava/io/DataOutputStream;
-        """.trimIndent()
-        assertEquals(expectedRules, startupRules)
-    }
-
-    @Test
-    fun startupProfiles_includeStartupOnly() {
-        // https://youtrack.jetbrains.com/issue/KT-2425
-        val dollar = "$"
-        val profile = """
-            Landroidx/Foo/Bar;
-            Lfoo/bar/Baz$dollar<Suffix>;
-            HSPLjava/io/DataOutputStream;->writeByte(I)V+]Ljava/io/OutputStream;missing_types
-            HPLandroidx/startup/AppInitializer;->**(**)**
-        """.trimIndent()
-
-        val startupRules = startupProfile(profile, includeStartupOnly = true)
-        val expectedRules = """
-            SLandroidx/Foo/Bar;
-            SLfoo/bar/Baz;
-            SLjava/io/DataOutputStream;
-        """.trimIndent()
-        assertEquals(expectedRules, startupRules)
-    }
-}
diff --git a/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/BaselineProfiles.kt b/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/BaselineProfiles.kt
index 6a31a42..e41a947 100644
--- a/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/BaselineProfiles.kt
+++ b/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/BaselineProfiles.kt
@@ -41,6 +41,7 @@
     uniqueName: String,
     packageName: String,
     iterations: Int = 3,
+    includeInStartupProfile: Boolean,
     filterPredicate: ((String) -> Boolean)?,
     profileBlock: MacrobenchmarkScope.() -> Unit,
 ) {
@@ -84,7 +85,13 @@
         // Filter
         val profile = filterProfileRulesToTargetP(unfilteredProfile, sortRules = true)
         // Report
-        reportResults(profile, filterPredicate, uniqueName, startTime)
+        reportResults(
+            profile = profile,
+            filterPredicate = filterPredicate,
+            uniqueFilePrefix = uniqueName,
+            startTime = startTime,
+            includeInStartupProfile = includeInStartupProfile
+        )
     } finally {
         killProcessBlock.invoke()
     }
@@ -104,6 +111,7 @@
     stableIterations: Int,
     maxIterations: Int,
     strictStability: Boolean = false,
+    includeInStartupProfile: Boolean,
     filterPredicate: ((String) -> Boolean)?,
     profileBlock: MacrobenchmarkScope.() -> Unit
 ) {
@@ -188,7 +196,13 @@
         }
 
         val profile = filterProfileRulesToTargetP(lastProfile, sortRules = true)
-        reportResults(profile, filterPredicate, uniqueName, startTime)
+        reportResults(
+            profile = profile,
+            filterPredicate = filterPredicate,
+            uniqueFilePrefix = uniqueName,
+            startTime = startTime,
+            includeInStartupProfile = includeInStartupProfile
+        )
     } finally {
         killProcessBlock.invoke()
     }
@@ -231,53 +245,41 @@
     profile: String,
     filterPredicate: ((String) -> Boolean)?,
     uniqueFilePrefix: String,
-    startTime: Long
+    startTime: Long,
+    includeInStartupProfile: Boolean
 ) {
-    // Build a startup profile
-    var startupProfile: String? = null
-    if (Arguments.enableStartupProfiles) {
-        startupProfile =
-            startupProfile(profile, includeStartupOnly = Arguments.strictStartupProfiles)
-    }
-
     // Filter profile if necessary based on filters
     val filteredProfile = applyPackageFilters(profile, filterPredicate)
 
     // Write a file with a timestamp to be able to disambiguate between runs with the same
     // unique name.
 
-    val fileName = "$uniqueFilePrefix-baseline-prof.txt"
-    val absolutePath = Outputs.writeFile(fileName, "baseline-profile") {
-        it.writeText(filteredProfile)
-    }
-    var startupProfilePath: String? = null
-    if (startupProfile != null) {
-        val startupProfileFileName = "$uniqueFilePrefix-startup-prof.txt"
-        startupProfilePath = Outputs.writeFile(startupProfileFileName, "startup-profile") {
-            it.writeText(startupProfile)
+    val (fileName, reportKey, tsFileName) =
+        if (includeInStartupProfile && Arguments.enableStartupProfiles) {
+            arrayOf(
+                "$uniqueFilePrefix-startup-prof.txt",
+                "startup-profile",
+                "$uniqueFilePrefix-startup-prof-${Outputs.dateToFileName()}.txt"
+            )
+        } else {
+            arrayOf(
+                "$uniqueFilePrefix-baseline-prof.txt",
+                "baseline-profile",
+                "$uniqueFilePrefix-baseline-prof-${Outputs.dateToFileName()}.txt"
+            )
         }
-    }
-    val tsFileName = "$uniqueFilePrefix-baseline-prof-${Outputs.dateToFileName()}.txt"
+
+    val absolutePath = Outputs.writeFile(fileName, reportKey) { it.writeText(filteredProfile) }
     val tsAbsolutePath = Outputs.writeFile(tsFileName, "baseline-profile-ts") {
         Log.d(TAG, "Pull Baseline Profile with: `adb pull \"${it.absolutePath}\" .`")
         it.writeText(filteredProfile)
     }
-    var tsStartupAbsolutePath: String? = null
-    if (startupProfile != null) {
-        val tsStartupFileName = "$uniqueFilePrefix-startup-prof-${Outputs.dateToFileName()}.txt"
-        tsStartupAbsolutePath = Outputs.writeFile(tsStartupFileName, "startup-profile-ts") {
-            Log.d(TAG, "Pull Startup Profile with: `adb pull \"${it.absolutePath}\" .`")
-            it.writeText(startupProfile)
-        }
-    }
 
     val totalRunTime = System.nanoTime() - startTime
     val results = Summary(
         totalRunTime = totalRunTime,
         profilePath = absolutePath,
-        profileTsPath = tsAbsolutePath,
-        startupProfilePath = startupProfilePath,
-        startupTsProfilePath = tsStartupAbsolutePath
+        profileTsPath = tsAbsolutePath
     )
     InstrumentationResults.instrumentationReport {
         val summary = summaryRecord(results)
@@ -411,21 +413,7 @@
         """.trimIndent()
     )
 
-    // Link to a path with timestamp to prevent studio from caching the file
-    val startupTsProfilePath = record.startupTsProfilePath
-    if (!startupTsProfilePath.isNullOrBlank()) {
-        val startupRelativePath = Outputs.relativePathFor(startupTsProfilePath)
-            .replace("(", "\\(")
-            .replace(")", "\\)")
-        summary.append("\n").append(
-            """
-                Startup profile [results](file://$startupRelativePath)
-            """.trimIndent()
-        )
-    }
-
     // Add commands that can be used to pull these files.
-
     summary.append("\n")
         .append("\n")
         .append(
@@ -434,18 +422,6 @@
                 adb ${deviceSpecifier}pull "${record.profilePath}" .
             """.trimIndent()
         )
-
-    val startupProfilePath = record.startupProfilePath
-    if (!startupProfilePath.isNullOrBlank()) {
-        summary.append("\n")
-            .append("\n")
-            .append(
-                """
-                    To copy the startup profile use:
-                    adb ${deviceSpecifier}pull "${record.startupProfilePath}" .
-                """.trimIndent()
-            )
-    }
     return summary.toString()
 }
 
@@ -471,14 +447,4 @@
     val totalRunTime: Long,
     val profilePath: String,
     val profileTsPath: String,
-    val startupProfilePath: String? = null,
-    val startupTsProfilePath: String? = null
-) {
-    init {
-        if (startupProfilePath.isNullOrBlank()) {
-            require(startupTsProfilePath.isNullOrBlank())
-        } else {
-            require(!startupTsProfilePath.isNullOrBlank())
-        }
-    }
-}
+)
diff --git a/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/StartupProfiles.kt b/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/StartupProfiles.kt
deleted file mode 100644
index 8b50582..0000000
--- a/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/StartupProfiles.kt
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright 2022 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.
- */
-
-@file:RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-
-package androidx.benchmark.macro
-
-import androidx.annotation.RestrictTo
-
-private val PROFILE_RULE_REGEX = "(H?S?P?)L([^$;]*)(.*)".toRegex()
-
-/**
- * Builds a startup profile for a given baseline profile.
- *
- * This startup profile can be used for dex layout optimizations.
- */
-fun startupProfile(profile: String, includeStartupOnly: Boolean = false): String {
-    val rules = profile.lines().mapNotNull { rule ->
-        when (val result = PROFILE_RULE_REGEX.find(rule)) {
-            null -> null
-            else -> {
-                val (flags, classPrefix, _) = result.destructured
-                // Empty flags are indicative that the class needs to be aggressively preloaded
-                // Therefore the class belongs in the primary dex.
-                val isStartup = flags.isEmpty() || flags.contains("S")
-                if (includeStartupOnly && !isStartup) {
-                    null
-                } else {
-                    "SL$classPrefix;"
-                }
-            }
-        }
-    }
-    val ruleSet = mutableSetOf<String>()
-    val startupRules = mutableListOf<String>()
-    // Try and keep the same order
-    rules.forEach { rule ->
-        if (!ruleSet.contains(rule)) {
-            ruleSet += rule
-            startupRules += rule
-        }
-    }
-    return startupRules.joinToString(separator = "\n")
-}
diff --git a/benchmark/integration-tests/macrobenchmark/src/androidTest/java/androidx/benchmark/integration/macrobenchmark/BaselineProfileRuleTest.kt b/benchmark/integration-tests/macrobenchmark/src/androidTest/java/androidx/benchmark/integration/macrobenchmark/BaselineProfileRuleTest.kt
index 4c36dffb3..9bbca93 100644
--- a/benchmark/integration-tests/macrobenchmark/src/androidTest/java/androidx/benchmark/integration/macrobenchmark/BaselineProfileRuleTest.kt
+++ b/benchmark/integration-tests/macrobenchmark/src/androidTest/java/androidx/benchmark/integration/macrobenchmark/BaselineProfileRuleTest.kt
@@ -40,6 +40,8 @@
     @get:Rule
     val baselineRule = BaselineProfileRule()
 
+    private val filterRegex = "^.*L${PACKAGE_NAME.replace(".", "/")}".toRegex()
+
     @Test
     fun appNotInstalled() {
         val error = assertFailsWith<AssertionError> {
@@ -64,9 +66,7 @@
         // Collects the baseline profile
         baselineRule.collectBaselineProfile(
             packageName = PACKAGE_NAME,
-            filterPredicate = {
-                it.contains("^.*L${PACKAGE_NAME.replace(".", "/")}".toRegex())
-            },
+            filterPredicate = { it.contains(filterRegex) },
             profileBlock = {
                 assertEquals(expectedIteration++, iteration)
                 startActivityAndWait(Intent(ACTION))
@@ -75,8 +75,13 @@
         )
         assertEquals(3, expectedIteration)
 
+        // Note: this name is automatically generated starting from class and method name,
+        // according to the patter `<class>_<method>-baseline-prof.txt`. Changes for class and
+        // method names should be reflected here in order for the test to succeed.
+        val baselineProfileOutputFileName = "BaselineProfileRuleTest_filter-baseline-prof.txt"
+
         // Asserts the output of the baseline profile
-        val lines = File(Outputs.outputDirectory, BASELINE_PROFILE_OUTPUT_FILE_NAME).readLines()
+        val lines = File(Outputs.outputDirectory, baselineProfileOutputFileName).readLines()
         assertThat(lines).containsExactly(
             "HSPLandroidx/benchmark/integration/macrobenchmark/target/EmptyActivity;" +
                 "-><init>()V",
@@ -86,16 +91,44 @@
         )
     }
 
+    @Test
+    fun profileType() {
+        assumeTrue(Build.VERSION.SDK_INT >= 33 || Shell.isSessionRooted())
+
+        data class TestConfig(val includeInStartupProfile: Boolean, val outputFileName: String)
+
+        arrayOf(
+            TestConfig(true, "BaselineProfileRuleTest_profileType-startup-prof.txt"),
+            TestConfig(false, "BaselineProfileRuleTest_profileType-baseline-prof.txt"),
+        ).forEach { (includeInStartupProfile, outputFilename) ->
+
+            // Collects the baseline profile
+            baselineRule.collectBaselineProfile(
+                packageName = PACKAGE_NAME,
+                filterPredicate = { it.contains(filterRegex) },
+                includeInStartupProfile = includeInStartupProfile,
+                profileBlock = {
+                    startActivityAndWait(Intent(ACTION))
+                    device.waitForIdle()
+                }
+            )
+
+            // Asserts the output of the baseline profile
+            val lines = File(Outputs.outputDirectory, outputFilename).readLines()
+            assertThat(lines).containsExactly(
+                "HSPLandroidx/benchmark/integration/macrobenchmark/target/EmptyActivity;" +
+                    "-><init>()V",
+                "HSPLandroidx/benchmark/integration/macrobenchmark/target/EmptyActivity;" +
+                    "->onCreate(Landroid/os/Bundle;)V",
+                "Landroidx/benchmark/integration/macrobenchmark/target/EmptyActivity;",
+            )
+        }
+    }
+
     companion object {
         private const val PACKAGE_NAME =
             "androidx.benchmark.integration.macrobenchmark.target"
         private const val ACTION =
             "androidx.benchmark.integration.macrobenchmark.target.EMPTY_ACTIVITY"
-
-        // Note: this name is automatically generated starting from class and method name,
-        // according to the patter `<class>_<method>-baseline-prof.txt`. Changes for class and
-        // method names should be reflected here in order for the test to succeed.
-        private const val BASELINE_PROFILE_OUTPUT_FILE_NAME =
-            "BaselineProfileRuleTest_filter-baseline-prof.txt"
     }
 }