diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 769787ce..940eed5c 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -71,6 +71,11 @@ android { "proguard-rules.pro" ) } + create("benchmark") { + initWith(buildTypes.getByName("release")) + signingConfig = signingConfigs.getByName("debug") + matchingFallbacks += listOf("release") + } } flavorDimensions += "mainFlavorDimension" diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index dacceec5..a3b75e25 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,5 +1,6 @@ - + @@ -7,36 +8,44 @@ android:name=".UnittoApplication" android:icon="@mipmap/ic_launcher_icon" android:label="@string/calculator_title" - android:supportsRtl="false" android:localeConfig="@xml/locales_config" + android:supportsRtl="false" android:theme="@style/Theme.Unitto"> + + + android:exported="true" + android:windowSoftInputMode="adjustPan"> + + - + + + android:permission="android.permission.BIND_QUICK_SETTINGS_TILE"> - - + \ No newline at end of file diff --git a/benchmark/.gitignore b/benchmark/.gitignore new file mode 100644 index 00000000..42afabfd --- /dev/null +++ b/benchmark/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/benchmark/build.gradle.kts b/benchmark/build.gradle.kts new file mode 100644 index 00000000..7e257d9b --- /dev/null +++ b/benchmark/build.gradle.kts @@ -0,0 +1,65 @@ +/* + * Unitto is a unit converter for Android + * Copyright (c) 2023 Elshan Agaev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +@Suppress("DSL_SCOPE_VIOLATION") // TODO: Remove once KTIJ-19369 is fixed +plugins { + alias(libs.plugins.baselineprofile) + id("unitto.android.test") +} + +android { + namespace = "com.sadellie.unitto.benchmark" + compileSdk = 34 + + defaultConfig { + minSdk = 24 + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + // This benchmark buildType is used for benchmarking, and should function like your + // release build (for example, with minification on). It"s signed with a debug key + // for easy local/CI testing. + create("benchmark") { + isDebuggable = true + signingConfig = getByName("debug").signingConfig + matchingFallbacks += listOf("release") + } + } + + targetProjectPath = ":app" + experimentalProperties["android.experimental.self-instrumenting"] = true +} + +dependencies { + implementation(libs.androidx.test.core) + implementation(libs.androidx.test.ext.junit.ktx) + implementation(libs.androidx.test.rules) + implementation(libs.androidx.test.runner) + implementation(libs.androidx.test.uiautomator) + implementation(libs.androidx.test.espresso.core) + implementation(libs.androidx.test.uiautomator) + implementation(libs.androidx.benchmark.macro) +} + +androidComponents { + beforeVariants(selector().all()) { + it.enable = it.buildType == "benchmark" + } +} \ No newline at end of file diff --git a/benchmark/src/main/AndroidManifest.xml b/benchmark/src/main/AndroidManifest.xml new file mode 100644 index 00000000..227314ee --- /dev/null +++ b/benchmark/src/main/AndroidManifest.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/benchmark/src/main/java/com/sadellie/unitto/benchmark/StartupBaselineProfile.kt b/benchmark/src/main/java/com/sadellie/unitto/benchmark/StartupBaselineProfile.kt new file mode 100644 index 00000000..1993d840 --- /dev/null +++ b/benchmark/src/main/java/com/sadellie/unitto/benchmark/StartupBaselineProfile.kt @@ -0,0 +1,39 @@ +/* + * Unitto is a unit converter for Android + * Copyright (c) 2023 Elshan Agaev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.sadellie.unitto.benchmark + +import android.os.Build +import androidx.annotation.RequiresApi +import androidx.benchmark.macro.junit4.BaselineProfileRule +import org.junit.Rule +import org.junit.Test + +@RequiresApi(Build.VERSION_CODES.P) +class StartupBaselineProfile { + @get:Rule val baselineProfileRule = BaselineProfileRule() + + @Test + fun generate() = baselineProfileRule.collect( + packageName = "com.sadellie.unitto", + includeInStartupProfile = true + ) { + startActivityAndWait() + device.pressBack() + } +} diff --git a/benchmark/src/main/java/com/sadellie/unitto/benchmark/StartupBenchmark.kt b/benchmark/src/main/java/com/sadellie/unitto/benchmark/StartupBenchmark.kt new file mode 100644 index 00000000..6b1f7b20 --- /dev/null +++ b/benchmark/src/main/java/com/sadellie/unitto/benchmark/StartupBenchmark.kt @@ -0,0 +1,56 @@ +/* + * Unitto is a unit converter for Android + * Copyright (c) 2023 Elshan Agaev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.sadellie.unitto.benchmark + +import androidx.benchmark.macro.StartupMode +import androidx.benchmark.macro.StartupTimingMetric +import androidx.benchmark.macro.junit4.MacrobenchmarkRule +import androidx.test.ext.junit.runners.AndroidJUnit4 +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith + +/** + * This is an example startup benchmark. + * + * It navigates to the device's home screen, and launches the default activity. + * + * Before running this benchmark: + * 1) switch your app's active build variant in the Studio (affects Studio runs only) + * 2) add `` to your app's manifest, within the `` tag + * + * Run this benchmark from Studio to see startup measurements, and captured system traces + * for investigating your app's performance. + */ +@RunWith(AndroidJUnit4::class) +class StartupBenchmark { + @get:Rule + val benchmarkRule = MacrobenchmarkRule() + + @Test + fun startup() = benchmarkRule.measureRepeated( + packageName = "com.sadellie.unitto", + metrics = listOf(StartupTimingMetric()), + iterations = 5, + startupMode = StartupMode.COLD + ) { + pressHome() + startActivityAndWait() + } +} diff --git a/build-logic/convention/build.gradle.kts b/build-logic/convention/build.gradle.kts index a5651a5c..11ebcfde 100644 --- a/build-logic/convention/build.gradle.kts +++ b/build-logic/convention/build.gradle.kts @@ -75,5 +75,10 @@ gradlePlugin { id = "unitto.android.library.jacoco" implementationClass = "UnittoAndroidLibraryJacocoPlugin" } + + register("unittoAndroidTestConventionPlugin") { + id = "unitto.android.test" + implementationClass = "UnittoAndroidTestConventionPlugin" + } } } diff --git a/build-logic/convention/src/main/java/UnittoAndroidTestConventionPlugin.kt b/build-logic/convention/src/main/java/UnittoAndroidTestConventionPlugin.kt new file mode 100644 index 00000000..8aead459 --- /dev/null +++ b/build-logic/convention/src/main/java/UnittoAndroidTestConventionPlugin.kt @@ -0,0 +1,40 @@ +/* + * Unitto is a unit converter for Android + * Copyright (c) 2023 Elshan Agaev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import com.android.build.gradle.TestExtension +import com.sadellie.unitto.configureKotlinAndroid +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.kotlin.dsl.configure + +@Suppress("UNUSED") +class UnittoAndroidTestConventionPlugin : Plugin { + override fun apply(target: Project) { + with(target) { + with(pluginManager) { + apply("com.android.test") + apply("org.jetbrains.kotlin.android") + } + + extensions.configure { + configureKotlinAndroid(this) + defaultConfig.targetSdk = 34 + } + } + } +} diff --git a/build.gradle.kts b/build.gradle.kts index 13b1c958..34dd29b4 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -5,6 +5,7 @@ plugins { alias(libs.plugins.hilt) apply false alias(libs.plugins.ksp) apply false alias(libs.plugins.room) apply false + alias(libs.plugins.androidTest) apply false } tasks.register("clean", Delete::class) { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index a54e47e8..e2629191 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -10,13 +10,16 @@ androidxComposeCompiler = "1.5.0" androidxComposeMaterial3 = "1.2.0-alpha12" androidxCoreCoreKts = "1.12.0" androidxDatastoreDatastorePreferences = "1.0.0" +androidxEspresso = "3.5.1" androidxHiltHiltNavigationCompose = "1.1.0" +androidxMacroBenchmark = "1.2.2" androidxLifecycleLifecycleRuntimeCompose = "2.6.2" androidxNavigationNavigationCompose = "2.7.5" androidxRoom = "2.6.1" androidxTest = "1.5.0" androidxTestExtJunitKtx = "1.1.5" androidxTestRunner = "1.5.2" +androidxUiAutomator = "2.2.0" androidxWindowWindow = "1.2.0" comAndroidToolsDesugarJdkLibs = "2.0.4" comGithubSadellieThemmo = "1.1.2" @@ -34,6 +37,7 @@ orgRobolectricRobolectric = "4.10.3" [libraries] androidx-appcompat-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "androidxAppCompatAppCompat" } +androidx-benchmark-macro = { group = "androidx.benchmark", name = "benchmark-macro-junit4", version.ref = "androidxMacroBenchmark" } androidx-browser-browser = { group = "androidx.browser", name = "browser", version.ref = "androidxBrowserBrowser" } androidx-compose-material3 = { group = "androidx.compose.material3", name = "material3", version.ref = "androidxComposeMaterial3" } androidx-compose-material3-window-size = { group = "androidx.compose.material3", name = "material3-window-size-class", version.ref = "androidxComposeMaterial3" } @@ -52,9 +56,11 @@ androidx-room-runtime = { group = "androidx.room", name = "room-runtime", versio androidx-room-ktx = { group = "androidx.room", name = "room-ktx", version.ref = "androidxRoom" } androidx-room-compiler = { group = "androidx.room", name = "room-compiler", version.ref = "androidxRoom" } androidx-test-core = { group = "androidx.test", name = "core", version.ref = "androidxTest" } +androidx-test-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "androidxEspresso" } androidx-test-ext-junit-ktx = { group = "androidx.test.ext", name = "junit-ktx", version.ref = "androidxTestExtJunitKtx" } androidx-test-runner = { group = "androidx.test", name = "runner", version.ref = "androidxTestRunner" } androidx-test-rules = { group = "androidx.test", name = "rules", version.ref = "androidxTest" } +androidx-test-uiautomator = { group = "androidx.test.uiautomator", name = "uiautomator", version.ref = "androidxUiAutomator" } androidx-window-window = { group = "androidx.window", name = "window", version.ref = "androidxWindowWindow" } com-android-tools-desugar-jdk-libs = { group = "com.android.tools", name = "desugar_jdk_libs", version.ref = "comAndroidToolsDesugarJdkLibs" } com-github-sadellie-themmo = { group = "com.github.sadellie", name = "themmo", version.ref = "comGithubSadellieThemmo" } @@ -82,4 +88,6 @@ android-gradlePlugin = { id = "com.android.application", version.ref = "androidG kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } hilt = { id = "com.google.dagger.hilt.android", version.ref = "comGoogleDagger" } ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" } -room = { id = "androidx.room", version.ref = "androidxRoom" } \ No newline at end of file +room = { id = "androidx.room", version.ref = "androidxRoom" } +androidTest = { id = "com.android.test", version.ref = "androidGradlePlugin" } +baselineprofile = { id = "androidx.baselineprofile", version.ref = "androidxMacroBenchmark"} \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index 78ca8da2..f53e5060 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -35,3 +35,4 @@ include(":data:common") include(":data:evaluatto") include(":data:timezone") include(":data:backup") +include(":benchmark")