You can automatically generate profiles for every app release using the Jetpack
Macrobenchmark library and
BaselineProfileRule
. We recommend that you
use com.android.tools.build:gradle:8.0.0
or higher, which
comes with build improvements when using Baseline Profiles.
Define the Baseline Profile generator
To create Baseline Profiles using the Macrobenchmark library, perform the following steps:
Android Studio Hedgehog Canary 1
Baseline Profile Generator module template
The Android Studio Baseline Profile Generator module template automates the creation of a new module to generate and benchmark Baseline Profiles. Running the template generates most of the typical build configuration, Baseline Profile generation, and verification code. The template creates code to generate and benchmark Baseline Profiles to measure app startup.
You need to manually define the Critical User Journeys (CUJs) within your app so that the generated Baseline Profiles provide the required optimizations for those CUJs.
Create a Baseline Profile Generator module using the template
To run the Baseline Profile module template, perform the following steps:
- Select File > New... > New Module...
- Select the Baseline Profile Generator template in the
Templates panel and configure it:
Figure 1. Baseline Profile Generator module template. The fields in the template are the following:
- Target application: this drop-down contains a list of the app modules in your project and defines which app the baseline profile is generated for. When you have only a single app module in your project, there is only one item in this list.
- Module name: the name you want for the Baseline Profile module being created.
- Package name: the package name you want for the Baseline Profile module.
- Language: whether you want the generated code to be Kotlin or Java.
- Build configuration language: whether you want to use Kotlin Script (KTS) or Groovy for your build configuration scripts.
- Click Finish and the new module is created. If you are using source control, you might be prompted to add the newly created module files to source control.
The newly created module contains code to both generate and benchmark the Baseline Profile and test only basic app startup times. We recommend that you augment these to include CUJs. It helps maintainability if you abstract these CUJs outside of the generated Baseline Profile and benchmark code so that they can be used for both. This means that changes to your CUJs are used consistently.
Generate the Baseline Profile
The Baseline Profile module template adds a new Run Configuration to generate the Baseline Profile:

To do this from the command-line interface, you can run the
:app:generaterBaselineProfile
or
:app:generate
Gradle tasks. This both
generates the Baseline Profile and installs it to the app being profiled.
Install the Baseline Profile
When the "Generate Baseline Profile" run configuration completes, it copies
the generated Baseline Profile to
src/release/generated/baselineProfiles/baseline-prof.txt
in the
module that is being profiled.
The generated Baseline Profile is created in build/outputs
.
However, the full path is dictated by the variant or flavor of the app being
profiled and whether you use a Gradle Managed Device or a connected device for
profiling.
If you use the names used by the code and build configurations generated by
the template, it is created in
build/outputs/managed_device_android_test_additional_output/nonminifiedrelease/pixel6Api31/BaselineProfileGenerator_generate-baseline-prof.txt
.
Android Studio Giraffe and older
- Set up a Macrobenchmark module in your Gradle project.
- Define a new test called
BaselineProfileGenerator
:class BaselineProfileGenerator { @get:Rule val baselineProfileRule = BaselineProfileRule() @Test fun startup() = baselineProfileRule.collectBaselineProfile( packageName = "com.example.app", profileBlock = { startActivityAndWait() } ) }
The generator can contain interactions with your app beyond app startup. This lets you optimize the runtime performance of your app, such as scrolling lists, running animations, and navigating within an
Activity
. See other examples of tests that use@BaselineProfileRule
to improve critical user journeys. - (Optional) Turn off obfuscation when generating Baseline
Profiles. You can do this by creating another ProGuard file in your app
module and adding
-dontobfuscate
for only yourbenchmark
build type that is responsible for generating the profiles.Kotlin
buildTypes { val benchmark by creating { // Only use benchmark Proguard rules. proguardFiles("benchmark-rules.pro") // ... } }
Groovy
buildTypes { benchmark { // Only use benchmark Proguard rules. proguardFiles 'benchmark-rules.pro' // ... } }
Generate the Baseline Profile
Run the generator as an instrumented test on a rooted physical device,
emulator, or
Gradle Managed Device. To
set up a managed device, open your build.gradle.kts
file. In the
testOptions
configuration block, add managedDevices
and devices
and create an emulator definition. Use
aosp
as the systemImageSource
, because you need root
access for the Baseline Profile generator.
Kotlin
testOptions { managedDevices { devices { create ("pixel6Api31", ManagedVirtualDevice::class) { device = "Pixel 6" apiLevel = 31 systemImageSource = "aosp" } } } }
Groovy
testOptions { managedDevices { devices { pixel6Api31(com.android.build.api.dsl.ManagedVirtualDevice) { device = "Pixel 6" apiLevel = 31 systemImageSource = "aosp" } } } }
Gradle creates the required tasks based on the selected device name and the
build variants available in the module. It is formatted as
[emulator_name][flavor][build type]AndroidTest
. You can execute
this task from a terminal:
./gradlew :benchmark:pixel6Api31BenchmarkAndroidTest
Benchmark the Baseline Profile
To benchmark your Baseline Profile, create a new Android Instrumented Test Run
configuration from the gutter action that executes the benchmarks defined in
StartupBenchmarks.kt
or StartupBencharks.java
. To learn more about benchmark
testing, see Create a Macrobenchmark
class
and Automate measurement with the Macrobenchmark
library.

When you run this within Android Studio, the build output contains details of the speed improvements that the Baseline Profile provides:
StartupBenchmarks_startupCompilationBaselineProfiles timeToInitialDisplayMs min 161.8, median 178.9, max 194.6 StartupBenchmarks_startupCompilationNone timeToInitialDisplayMs min 184.7, median 196.9, max 202.9
Capture all required code paths
The two key metrics for measuring app startup times are time to initial display (TTID) and time to full display (TTFD). TTID is the time it takes to display the first frame of the application UI. TTFD also includes the time to display content that is loaded asynchronously after the initial frame is displayed.
TTFD is reported once the
reportFullyDrawn()
method of the
ComponentActivity
is called. If reportFullyDrawn()
is never called, the TTID is reported
instead. You might need to delay when reportFullyDrawn()
is called until after
the asynchronous loading is complete. For example, if the UI contains a dynamic
list such as a RecyclerView
or lazy
list, this might be populated by a background task
that completes after the list is first drawn and, therefore, after the UI is
marked as fully drawn. In such cases, code that runs after the UI reaches fully
drawn state isn't included in the Baseline Profile.
To include the list population as part of your Baseline Profile, get the
FullyDrawnReporter
by using
getFullyDrawnReporter()
and add a reporter to it in your app code. Release the reporter once the
background task finishes populating the list. The FullyDrawnReporter
doesn't
call the reportFullyDrawn()
method until all reporters are released. By doing
this, Baseline Profile includes the code paths required to populate the list.
This doesn't change the app's behavior for the user, but it lets the Baseline
Profile include all the necessary code paths.
If your app uses Jetpack Compose, use the following APIs to indicate fully drawn state:
ReportDrawn
indicates that your composable is immediately ready for interaction.ReportDrawnWhen
takes a predicate, such aslist.count > 0
, to indicate when your composable is ready for interaction.ReportDrawnAfter
takes a suspending method that, when it completes, indicates that your composable is ready for interaction.
Baseline Profile Gradle plugin
The Baseline Profile Gradle plugin makes it easier to generate and maintain Baseline Profiles. It performs necessary steps to generate and install a Baseline Profile into your application module.
To use the plugin, add an instrumented test module to your project and define a set of tests that navigate through your app to simulate critical user journeys. When you run the instrumented test, the Baseline Profile Gradle plugin tracks all classes and methods that are executed during these user journeys and generates a baseline profile based on these classes and methods. It then copies the generated baseline profile into the application module.
The instrumented test module is the profile producer. The app module is the profile consumer.
The main areas that you need to focus on are the initial setup and creating the tests to simulate the critical user journeys.
What you need to use the plugin
- AGP 8.0.0 or newer
- Dependency on the latest Gradle plugin version (alpha13 and higher)
Use the plugin
The following example assumes the existence of an application module named
:app
.
There are 2 modules in the following example:
- Profile consumer: the application module to generate the profile for. In
the following example, it's
:app
. - Profile producer: the Baseline Profile test module that contains the
instrumentation tests to generate the profile. In the following example,
it's named
:baseline-profile
.
To use the plugin, perform the following steps:
- Create a new
com.android.test
module—for example,:baseline-profile
. - Configure
build.gradle
for:baseline-profile
: - Apply the
androidx.baselineprofile
plugin. - Ensure the
targetProjectPath
points to the:app
module. - Optionally, add GMD. In the following example, it's
pixel6Api31
. If not specified, the plugin uses a connected device, either emulated or physical. - Apply the configuration you want, as shown in the following example.
- Create a Baseline Profile test in the
:baseline-profile
test module. The following example is a test that starts the app and waits for idle. - Update the configuration in
build.gradle
in the app module:app
. - Apply the plugin
androidx.baselineprofile
. - Add a
baselineProfile
dependency to the:baseline-profile
module. - Generate the profile by running the following code:
./gradlew :app:generateBaselineProfile
.
Kotlin
plugins { id("com.android.test") id("androidx.baselineprofile") } android { // There are no changes here. It's documented for completeness. defaultConfig { ... } // This must point to the app module. targetProjectPath = ":app" // This is the optional managed device. testOptions.managedDevices.devices { pixel6Api31(com.android.build.api.dsl.ManagedVirtualDevice) { device = "Pixel 6" apiLevel = 31 systemImageSource = "aosp" } } } // There are no changes here. It's documented for completeness. dependencies { ... } // This is the plugin configuration. Everything is optional. Defaults are in the // comments. In this example, you use the GMD added earlier and disable // connected devices. baselineProfile { // This specifies the managed devices to use that you run the tests on. The // default is none. managedDevices += "pixel6Api31" // This enables using connected devices to generate profiles. The default is // true. When using connected devices, they must be rooted or API 33 and // higher. useConnectedDevices = false }
Groovy
plugins { id 'com.android.test' id 'androidx.baselineprofile' } android { // There are no changes here. It's documented for completeness. defaultConfig { ... } // This must point to the app module. targetProjectPath ':app' // This is the optional managed device. testOptions.managedDevices.devices { pixel6Api31(com.android.build.api.dsl.ManagedVirtualDevice) { device 'Pixel 6' apiLevel 31 systemImageSource 'aosp' } } } // There are no changes here. It's documented for completeness. dependencies { ... } // This is the plugin configuration. Everything is optional. Defaults are in the // comments. In this example, you use the GMD added earlier and disable // connected devices. baselineProfile { // This specifies the managed devices to use that you run the tests on. The // default is none. managedDevices ['pixel6Api31'] // This enables using connected devices to generate profiles. The default is // true. When using connected devices, they must be rooted or API 33 and // higher. useConnectedDevices false }
Kotlin
class BaselineProfileGenerator { @get:Rule val baselineRule = BaselineProfileRule() @Test fun startupBaselineProfile() { baselineRule.collectBaselineProfile("com.myapp") { startActivityAndWait() } } }
Java
public class BaselineProfileGenerator { @Rule Public BaselineProfileRule baselineRule = new BaselineProfileRule(); @Test Public void startupBaselineProfile() { baselineRule.collectBaselineProfile( "com.myapp", (scope -> { scope.startActivityAndWait(); Return Unit.INSTANCE; }) } } }
Kotlin
plugins { id("com.android.application") id("androidx.baselineprofile") } android { // There are no changes to the `android` block. ... } dependencies { ... // Add a baselineProfile dependency to the :baseline-profile module. baselineProfile(project(":baseline-profile")) }
Groovy
plugins { id 'com.android.application' id 'androidx.baselineprofile' } android { // No changes to the `android` block. ... } dependencies { ... // Add a baselineProfile dependency to the :baseline-profile module. baselineProfile ':baseline-profile"' }
At the end of the generation task, the Baseline Profile is stored in
app/src/release/generated/baselineProfiles
.
Generate a Baseline Profile for a library
In the following example, the library module is named :library
and the
application module is named :sample-app
, which contains an app that utilizes
the library.
In this example, you need three modules:
- App target: an application module that contains a sample app. In the
following example, it's
:sample-app
. - Profile consumer: the library module to generate the profile for. In the
following example, it's
:library
. - The profile producer: the Baseline Profile test module that contains the instrumentation tests to generate the module.
To generate a Baseline Profile for a library, perform the following steps:
- Create a new
com.android.test
module—for example,:baseline-profile
. - Configure
build.gradle
for:baseline-profile
: - Apply the
androidx.baselineprofile
plugin. - Ensure the
targetProjectPath
points to the:sample-app
module. - Optionally, add a GMD. In the following example, it's
pixel6Api31
. - Apply the configuration you want, as shown in the following example.
- Create a Baseline Profile test in the
:baseline-profile
test module. This needs to be specific to the sample app and must use all the functionalities of the library. - Update the configuration in
build.gradle
in the library module:library
. - Apply the plugin
androidx.baselineprofile
. - Add a
baselineProfile
dependency to the:baseline-profile
module. - Apply the consumer plugin configuration you want, as shown in the following example.
- Update the configuration in
build.gradle
in the app module:sample-app
, adding theandroidx.baselineprofile
plugin. - Generate the profile by running the following code:
./gradlew :library:generateBaselineProfile
.
Kotlin
plugins { id("com.android.test") id("androidx.baselineprofile") } android { // There are no changes here. It's reported for completeness. defaultConfig { minSdkVersion 23 testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } // This must point to the app module. targetProjectPath = ":app" // This is the optional managed device. testOptions.managedDevices.devices { create("pixel6Api31") { device = "Pixel 6" apiLevel = 31 systemImageSource = "aosp" } } } // There's nothing to change here. dependencies { ... } // This is the plugin configuration. Everything is optional. Defaults are in the // comments. In this example, you use the GMD added earlier and disable // connected devices. baselineProfile { // This specifies the managed devices to use that you run the tests on. The // default is none. managedDevices += "pixel6Api31" // This enables using connected devices to generate profiles. The default is // true. When using connected devices, they must be rooted or API 33 and // higher. useConnectedDevices = false }
Groovy
plugins { id 'com.android.test' id 'androidx.baselineprofile' } android { // There are no changes here. It's reported for completeness. defaultConfig { ... } // This must point to the app module. targetProjectPath ':app' // This is the optional managed device. testOptions.managedDevices.devices { pixel6Api31(com.android.build.api.dsl.ManagedVirtualDevice) { device 'Pixel 6' apiLevel 31 systemImageSource 'aosp' } } } // There's nothing to change here. dependencies { ... } // This is the plugin configuration. Everything is optional. Defaults are in the // comments. In this example, you use the GMD added earlier and disable // connected devices. baselineProfile { // This specifies the managed devices to use that you run the tests on. The // default is none. managedDevices ['pixel6Api31'] // This enables using connected devices to generate profiles. The default is // true. When using connected devices, they must be rooted or API 33 and // higher. useConnectedDevices false }
Kotlin
plugins { id("com.android.library") id("androidx.baselineprofile") } // There are no changes to the android block. android { ... } dependencies { ... // Add a baselineProfile dependency to the :baseline-profile module. baselineProfile(project(":baseline-profile")) } // This is the plugin configuration. baselineProfile { // This filters the generated profile rules. In this example, you keep // all the classes in com.library and in all the subpackages. filter { include "com.mylibrary.**" } }
Groovy
plugins { id 'com.android.library' id 'androidx.baselineprofile' } // There are no changes to the android block. android { ... } dependencies { ... // Add a baselineProfile dependency to the :baseline-profile module. baselineProfile ':baseline-profile' } // This is the plugin configuration. baselineProfile { // This filters the generated profile rules. In this example, you keep // all the classes in com.library and in all the subpackages. filter { include 'com.mylibrary.**' } }
Kotlin
plugins { ... id("androidx.baselineprofile") } // There are no other changes to the configuration.
Groovy
plugins { ... id 'androidx.baselineprofile' } // There are no other changes to the configuration.
At the end of the generation task, the Baseline Profile is stored in
library/src/main/generated/baselineProfiles
.
DSL
While this documentation refers to the Baseline Profile Gradle plugin as a
single plugin, there are actually three plugins that perform different tasks
according to which module they're applied to. The plugin ID in this
documentation is androidx.baselineprofile
, and it's a shortcut for the three
plugins.
To better understand this concept, see the following modules you need to generate a Baseline Profile:
- An application to run the Baseline Profile tests against. This is an
Android application module with
com.android.application
applied. When generating a profile for a library, this can be a sample app. When generating a profile for an application, it's the application itself. In the following example,androidx.baselineprofile
plugin internally appliesandroidx.baselineprofile.apptarget
. - A Baseline Profile test module that contains the tests to run. This is an
Android test module with
com.android.test
applied. In the following example,androidx.baselineprofile
plugin internally appliesandroidx.baselineprofile.producer
. - A module that ultimately consumes the Baseline Profile in the build
process. This is an android application
com.android.application
or librarycom.android.library
module. In the following example,androidx.baselineprofile
plugin internally appliesandroidx.baselineprofile.consumer
.
App target (androidx.baselineprofile.apptarget)
This doesn't have any configuration.
Profile producer (androidx.baselineprofile.producer)
Support for Gradle-managed devices
To utilize a Gradle-managed device, add one in the build.gradle
configuration
of the profile producer module, as shown in the following example:
Kotlin
android { testOptions.managedDevices.devices { create("pixel6Api31") { device = "Pixel 6" apiLevel = 31 systemImageSource = "aosp" } } }
Groovy
android { testOptions.managedDevices.devices { pixel6Api31(ManagedVirtualDevice) { device 'Pixel 6' apiLevel = 31 systemImageSource 'aosp' } } }
You can then use the created GMD to generate Baseline Profiles by adding it to the following:
Kotlin
baselineProfile { managedDevices += "pixel6Api31" }
Groovy
baselineProfile { managedDevices = ['pixel6Api31'] }
The following examples are additional options available to enable or disable the connected devices to generate Baseline Profiles.
Kotlin
baselineProfile { ... useConnectedDevices = true }
Groovy
baselineProfile { ... useConnectedDevices true }
Profile consumer (androidx.baselineprofile.consumer)
Generate profiles per flavor and one for all variants
You can generate profiles per variant, per flavor, or as a single file to utilize for all the variants. You can control this behavior through the merge setting, as shown in the following example.
Kotlin
baselineProfile { mergeIntoMain = true / false }
Groovy
baselineProfile { mergeIntoMain true / false }
- Set
mergeIntoMain
totrue
to merge all the generated profiles for each variant in a single profile. It isn't possible to generate per-variant Baseline Profiles when this setting istrue
, so only a single generation task namedgenerateBaselineProfile
exists. The profile output issrc/main/generated/baselineProfiles
. - Set
mergeIntoMain
tofalse
to disable merging and to have one profile per variant. It's possible to generate per-variant Baseline Profiles in the following example so multiple generation tasks exist—one per variant. For example, when there are two flavors—such as free and paid—and one release build type, the generated tasks are the following:generateFreeReleaseBaselineProfile
generatePaidReleaseBaselineProfile
generateReleaseBaselineProfile
By default, this setting is true
for libraries and false
for applications.
You can also specify this behavior per variant:
Kotlin
baselineProfile { variants { freeRelease { mergeIntoMain = true / false } } }
Groovy
baselineProfile { variants { freeRelease { mergeIntoMain true / false } } }
In the preceding example, the variants where the flag is set to true
are all
merged into src/main/generated/baselineProfiles
, while the profiles for the
variants where the flag is set to false are kept in the folder
src/<variant>/generated/baselineProfiles
.
Automatically generate Baseline Profile when assembling a new release
You can manually trigger Baseline Profile generation through the task
generateBaselineProfile
or automatically when building a release. This is
controlled by the following flag:
Kotlin
baselineProfile { automaticallyGenerateDuringBuild = true / false }
Groovy
baselineProfile { automaticallyGenerateDuringBuild true / false }
Setting this flag to true
triggers a new Baseline Profile to be generated for
each assembly. This way, the most updated profile is included in the build. This
means that running an assemble release build task—such as
./gradlew:app:assembleRelease
—also triggers
:app:generateReleaseBaselineProfile
. This also starts the Baseline Profile
instrumentation tests and builds the Baseline Profile build on which they run.
While this helps ensure that users gain the best performance benefit, it also
increases the build time because of the double build and instrumentation tests.
You can also specify this behavior per variant, as shown in the following example:
Kotlin
baselineProfile { variants { freeRelease { automaticallyGenerateDuringBuild = true / false } } }
Groovy
baselineProfile { variants { freeRelease { automaticallyGenerateDuringBuild true / false } } }
In the preceding example, the task generateFreeReleaseBaselineProfile
runs
when starting assembleFreeRelease
. This helps when the user wants to have, for
example, a release
for distribution build that always generates the profile
when building, and a releaseWithoutProfile
build for internal testing.
Store Baseline Profiles into sources
You can store Baseline Profiles in the source directory through the saveInSrc
flag:
true
: the Baseline Profile is stored insrc/<variant>/generated/baselineProfiles
. This lets you commit the latest generated profile with your sources.false
: the Baseline Profile is stored in the intermediate files in the build directory. This way, when committing your code, you don't save the latest generated profile.
Kotlin
baselineProfile { saveInSrc = true / false }
Groovy
baselineProfile { saveInSrc true / false }
You can also specify this behavior per variant:
Kotlin
baselineProfile { variants { freeRelease { saveInSrc = true / false } } }
Groovy
baselineProfile { variants { freeRelease { saveInSrc true / false } } }
Filter profile rules
You can filter the Baseline Profile rules generated through plugin configuration. This is particularly helpful for libraries if you want to exclude profile rules for classes and methods that are part of other dependencies of the sample app or the library itself. The filters can specify, include, and exclude for packages and classes. When you only specify excludes, only matching Baseline Profile rules are excluded and everything else is included.
The filters specification can be any of the following:
- Package name ending with double wildcards to match the specified package and
all subpackages. For example,
com.example.**
matchescom.example.foo
andcom.example.foo.bar
. - Package name ending with wildcard to match specified package only. For
example,
com.example.*
matchescom.example.foo
but doesn't matchcom.example.foo.bar
. - Class names to match a specific class—for example,
com.example.MyClass
.
The following examples show how to include and exclude specific packages:
Kotlin
baselineProfile { filter { include("com.somelibrary.widget.grid.**") exclude("com.somelibrary.widget.grid.debug.**") include("com.somelibrary.widget.list.**") exclude("com.somelibrary.widget.list.debug.**") include("com.somelibrary.widget.text.**") exclude("com.somelibrary.widget.text.debug.**") } }
Groovy
baselineProfile { filter { include 'com.somelibrary.widget.grid.**' exclude 'com.somelibrary.widget.grid.debug.**' include 'com.somelibrary.widget.list.**' exclude 'com.somelibrary.widget.list.debug.**' include 'com.somelibrary.widget.text.**' exclude 'com.somelibrary.widget.text.debug.**' } }
Filters also support variants and you can express them as follows:
Kotlin
// Non-specific filters applied to all the variants. baselineProfile { filter { include("com.myapp.**") } } // Flavor-specific filters. baselineProfile { variants { free { filter { include("com.myapp.free.**") } } paid { filter { include("com.myapp.paid.**") } } } } // Build-type-specific filters. baselineProfile { variants { release { filter { include("com.myapp.**") } } } } // Variant-specific filters. baselineProfile { variants { freeRelease { filter { include("com.myapp.**") } } } }
Groovy
// Non-specific filters applied to all the variants. baselineProfile { filter { include 'com.myapp.**' } } // Flavor-specific filters. baselineProfile { variants { free { filter { include 'com.myapp.free.**' } } paid { filter { include 'com.myapp.paid.**' } } } } // Build-type specific filters. baselineProfile { variants { release { filter { include 'com.myapp.**' } } } } // Variant-specific filters. baselineProfile { variants { freeRelease { filter { include 'com.myapp.**' } } } }
(Optional) Apply the generated rules manually
The Baseline Profile generator creates a Human Readable Format (HRF) text file on the device and copies it to your host machine. To apply the generated profile to your code, follow these steps:
Locate the HRF file in the build folder of the module you generate the profile in:
[module]/build/outputs/managed_device_android_test_additional_output/[device]
.Profiles follow the
[class name]-[test method name]-baseline-prof.txt
naming pattern, which looks like this:BaselineProfileGenerator-startup-baseline-prof.txt
.Copy the generated profile to
src/flavor/baselineProfiles
in your app module for any given flavor. To apply the profile to all flavors, copy it tosrc/main/baselineProfiles
.Add a dependency to the ProfileInstaller library in your app's
build.gradle.kts
file to enable local Baseline Profile compilation where Cloud Profiles aren't available. This is the only way to sideload a Baseline Profile locally.dependencies { implementation("androidx.profileinstaller:profileinstaller:1.3.1") }
Build the production version of your app while the applied HRF rules are compiled into binary form and included in the APK or AAB. Then distribute your app as usual.
Additional notes
When creating Baseline Profiles, here are some additional things to be aware of:
Compiled Baseline Profiles must be smaller than 1.5 MB. This doesn't apply to the text format in your source files, which are typically much larger prior to compilation. Verify the size of your binary Baseline Profile by locating it in the output artifact under
assets/dexopt/baseline.prof
for APK orBUNDLE-METADATA/com.android.tools.build.profiles/baseline.prof
for AAB.Broad rules that compile too much of the application can slow down startup due to increased disk access. If you're just starting with Baseline Profiles, don't worry about this. However, depending on your app and the size and number of journeys, adding a lot of journeys can result in suboptimal performance. Test the performance of your app by trying different profiles and verifying that the performance doesn't regress after the additions.