Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion KeepAnnotationsSample/gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[versions]
agp = "9.5.0-alpha05"
agp = "9.5.0-alpha01"
annotationKeep = "1.0.0-SNAPSHOT"
coreKtx = "1.19.0"
junit = "4.13.2"
Expand Down
14 changes: 12 additions & 2 deletions MacrobenchmarkSample/app/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import org.jetbrains.kotlin.gradle.dsl.JvmTarget

/*
* Copyright 2021 The Android Open Source Project
*
Expand All @@ -17,7 +19,6 @@
plugins {
alias(libs.plugins.application)
alias(libs.plugins.compose)
alias(libs.plugins.kotlin)
alias(libs.plugins.baselineprofile)
}

Expand Down Expand Up @@ -50,7 +51,6 @@ android {
)
// In real app, this would use its own release keystore
signingConfig = signingConfigs.getByName("debug")
baselineProfile.automaticGenerationDuringBuild = true
}
}
// [END macrobenchmark_setup_app_build_type]
Expand All @@ -61,6 +61,16 @@ android {
}
}

kotlin {
compilerOptions {
jvmTarget.set(JvmTarget.JVM_17)
}
}

baselineProfile {
automaticGenerationDuringBuild = true
}

dependencies {
val composeBom = platform(libs.compose.bom)
implementation(composeBom)
Expand Down
8 changes: 4 additions & 4 deletions MacrobenchmarkSample/gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
[versions]
agp = "8.13.1"
agp = "9.4.1"
activity = "1.11.0"
appcompat = "1.7.1"
benchmark = "1.4.1"
benchmark = "1.6.0-SNAPSHOT"
composeBom = "2025.11.00"
constraintLayout = "2.2.1"
core = "1.17.0"
Expand All @@ -15,7 +15,7 @@ jUnit = "1.3.0"
kotlin = "2.2.21"
lifecycle = "2.9.4"
material = "1.13.0"
profileInstaller = "1.4.1"
profileInstaller = "1.5.0-SNAPSHOT"
runtimeTracing = "1.9.4"
tracing = "1.3.0"
tracingPerfetto = "1.0.0"
Expand Down Expand Up @@ -52,7 +52,7 @@ viewmodel = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-ktx", ve
[plugins]

application = { id = "com.android.application", version.ref = "agp" }
baselineprofile = { id = "androidx.baselineprofile", version.ref = "benchmark" }
baselineprofile = { id = "androidx.baselineprofile", version = "1.5.0" }
compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
library = { id = "com.android.library", version.ref = "agp" }
test = { id = "com.android.test", version.ref = "agp" }
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-9.7.1-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
Expand Down
9 changes: 7 additions & 2 deletions MacrobenchmarkSample/macrobenchmark/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,10 @@
*/

import com.android.build.api.dsl.ManagedVirtualDevice
import org.jetbrains.kotlin.gradle.dsl.JvmTarget

plugins {
id("kotlin-android")
alias(libs.plugins.test)
alias(libs.plugins.kotlin)
alias(libs.plugins.baselineprofile)
}

Expand Down Expand Up @@ -59,6 +58,12 @@ android {
}
// [END macrobenchmark_setup_android]

kotlin {
compilerOptions {
jvmTarget.set(JvmTarget.JVM_17)
}
}

baselineProfile {

// This specifies the managed devices to use that you run the tests on. The default
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class LoginBaselineProfileGenerator {
stableIterations = 3
) {
uiAutomator {
startIntent(Intent("$packageName.LOGIN_ACTIVITY"))
startActivityIntent(Intent("$packageName.LOGIN_ACTIVITY"))
onElement { isEditable and !isPassword }.text = "user"
onElement { isEditable && isPassword }.text = "password"
onElement { textAsString() == "Login" }.click()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package com.example.macrobenchmark.benchmark.startup


import androidx.test.filters.SdkSuppress
import androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner
import com.example.macrobenchmark.benchmark.util.DEFAULT_ITERATIONS
import com.example.macrobenchmark.benchmark.util.TARGET_PACKAGE
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith

@RunWith(AndroidJUnit4ClassRunner::class)
class MemoryStartupBenchmark {
@get:Rule
val benchmarkRule = Macrobench()

@SdkSuppress(minSdkVersion = 36)
@androidx.benchmark.ExperimentalBenchmarkConfigApi
@androidx.benchmark.macro.ExperimentalMetricApi
@Test
fun startupMemory() = benchmarkRule.measureRepeated(
packageName = TARGET_PACKAGE,
metrics = listOf(
StartupTimingMetric(),
androidx.benchmark.macro.MemoryUsageMetric(
androidx.benchmark.macro.MemoryUsageMetric.Mode.Last,
listOf(
androidx.benchmark.macro.MemoryUsageMetric.SubMetric.HeapSize,
androidx.benchmark.macro.MemoryUsageMetric.SubMetric.RssAnon,
androidx.benchmark.macro.MemoryUsageMetric.SubMetric.Swap
)
)
),
compilationMode = CompilationMode.None(),
iterations = DEFAULT_ITERATIONS,
startupMode = StartupMode.COLD,
experimentalConfig = androidx.benchmark.ExperimentalConfig(
memoryProfilingConfig = androidx.benchmark.MemoryProfilingConfig(
isSampleArtHeapEnabled = true,
isSampleNativeHeapEnabled = true
)
)
) {
startActivityAndWait()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package com.example.macrobenchmark.benchmark.startup

import androidx.benchmark.macro.ArtMetric
import androidx.benchmark.macro.StartupTimingMetric
import androidx.benchmark.macro.junit4.MacrobenchmarkRule
import androidx.test.ext.junit.runners.AndroidJUnit4
Expand All @@ -37,7 +38,7 @@ class SampleStartupBenchmark {
@Test
fun startup() = benchmarkRule.measureRepeated(
packageName = TARGET_PACKAGE,
metrics = listOf(StartupTimingMetric()),
metrics = listOf(StartupTimingMetric(), ArtMetric()),
iterations = DEFAULT_ITERATIONS,
) {
// starts default launch activity
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,11 @@ abstract class AbstractStartupBenchmark(private val startupMode: StartupMode) {
iterations = DEFAULT_ITERATIONS,
startupMode = startupMode,
) {
uiAutomator {
startApp(TARGET_PACKAGE)
}
startActivityAndWait()
}
}
}
/**
* Run this benchmark from Studio to see memory measurements, and captured system traces
* for investigating your app's memory usage during startup.
*/

4 changes: 4 additions & 0 deletions MacrobenchmarkSample/settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,17 @@ include(":macrobenchmark")
pluginManagement {
repositories {
google()
maven("https://androidx.dev/snapshots/builds/LATEST/artifacts/repository")
mavenLocal()
mavenCentral()
gradlePluginPortal()
}
}
dependencyResolutionManagement {
repositories {
google()
maven("https://androidx.dev/snapshots/builds/LATEST/artifacts/repository")
mavenLocal()
mavenCentral()
gradlePluginPortal()
}
Expand Down
16 changes: 16 additions & 0 deletions UsedByNativeSample/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
*.iml
.gradle
/local.properties
/.idea/caches
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
.DS_Store
/build
/captures
.externalNativeBuild
.cxx
local.properties
.kotlin/
60 changes: 60 additions & 0 deletions UsedByNativeSample/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# KeepAnnotations Sample

This examples shows the use of the `androidx.annotation.keep` Gradle plugin.

- This programmatically generates `keep` rules when an `app` / `android library` / `java library` module uses `androidx.annotation:annotation-keep`.

## Testing

### Android AAR Modules (Android Libraries, KMP AAR Modules)

```bash

// App Modules

./gradlew <variantName>ExtractKeepRules

// For Android AAR Modules

./gradlew <variantName>KeepRulesTransformAar
```

### Java / Kotlin Library Modules

For Java Libraries, you need to do the following.

* Apply the Gradle Plugin.

```kotlin
plugins {
alias(libs.plugins.androidx.annotation.keep)
}
```

* Register a new task that can generate the artifact with keep rules.

```kotlin
val jarTask = project.tasks.named<org.gradle.jvm.tasks.Jar>("jar")
val outputJar = jarTask.flatMap { it.archiveFile }
val outputFile = jarTask.flatMap { it.archiveFileName }.map { fileName ->
"keep${fileName.uppercaseFirstChar()}"
}

// Register the JAR transform for extracting keep rules.
val artifactTask = annotationKeep.registerJavaArchiveTransform(
taskName = "keepRulesJar",
input = outputJar,
fileName = outputFile
)
```

* Register the output artifact for publication.

```kotlin
// Register the new artifact.
project.configurations.configureEach {
if (name == "apiElements" || name == "runtimeElements") {
outgoing.artifact(artifactTask.flatMap { it.outputJar })
}
}
```
1 change: 1 addition & 0 deletions UsedByNativeSample/app/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
66 changes: 66 additions & 0 deletions UsedByNativeSample/app/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import kotlin.math.sign

plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.compose)
alias(libs.plugins.androidx.annotation.keep)
id("kotlin-parcelize")
}

android {
namespace = "org.example"
compileSdk {
version = release(37)
}

defaultConfig {
applicationId = "org.example"
minSdk = 24
targetSdk = 37
versionCode = 1
versionName = "1.0"

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}

buildTypes {
release {
optimization {
enable = true
}
signingConfig = signingConfigs.getByName("debug")
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
buildFeatures {
compose = true
}
// Native library used by the JNI examples (downcalls + C++ -> Kotlin upcalls).
ndkVersion = "29.0.14206865"
externalNativeBuild {
cmake {
path = file("src/main/cpp/CMakeLists.txt")
version = "3.22.1"
}
}
}

dependencies {
implementation(libs.androidx.annotation.keep)
implementation(platform(libs.androidx.compose.bom))
implementation(libs.androidx.activity.compose)
implementation(libs.androidx.compose.material3)
implementation(libs.androidx.compose.ui)
implementation(libs.androidx.compose.ui.graphics)
implementation(libs.androidx.compose.ui.tooling.preview)
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.lifecycle.runtime.ktx)
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.espresso.core)
androidTestImplementation(libs.androidx.junit)
debugImplementation(libs.androidx.compose.ui.test.manifest)
debugImplementation(libs.androidx.compose.ui.tooling)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package org.example

import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4

import org.junit.Test
import org.junit.runner.RunWith

import org.junit.Assert.*

/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("org.example", appContext.packageName)
}
}
Loading
Loading