summaryrefslogtreecommitdiffstats
path: root/mobile/android/fenix/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'mobile/android/fenix/plugins')
-rw-r--r--mobile/android/fenix/plugins/apksize/build.gradle29
-rw-r--r--mobile/android/fenix/plugins/apksize/settings.gradle19
-rw-r--r--mobile/android/fenix/plugins/apksize/src/main/java/ApkSizePlugin.kt153
-rw-r--r--mobile/android/fenix/plugins/fenixdependencies/build.gradle25
-rw-r--r--mobile/android/fenix/plugins/fenixdependencies/settings.gradle19
-rw-r--r--mobile/android/fenix/plugins/fenixdependencies/src/main/java/FenixDependenciesPlugin.kt111
6 files changed, 356 insertions, 0 deletions
diff --git a/mobile/android/fenix/plugins/apksize/build.gradle b/mobile/android/fenix/plugins/apksize/build.gradle
new file mode 100644
index 0000000000..f9d4b5d404
--- /dev/null
+++ b/mobile/android/fenix/plugins/apksize/build.gradle
@@ -0,0 +1,29 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+plugins {
+ id "org.gradle.kotlin.kotlin-dsl" version "4.2.1"
+}
+
+repositories {
+ gradle.mozconfig.substs.GRADLE_MAVEN_REPOSITORIES.each { repository ->
+ maven {
+ url repository
+ if (gradle.mozconfig.substs.ALLOW_INSECURE_GRADLE_REPOSITORIES) {
+ allowInsecureProtocol = true
+ }
+ }
+ }
+}
+
+dependencies {
+ implementation "org.json:json:20210307"
+}
+
+gradlePlugin {
+ plugins.register("ApkSizePlugin") {
+ id = "ApkSizePlugin"
+ implementationClass = "ApkSizePlugin"
+ }
+}
diff --git a/mobile/android/fenix/plugins/apksize/settings.gradle b/mobile/android/fenix/plugins/apksize/settings.gradle
new file mode 100644
index 0000000000..16701d4aac
--- /dev/null
+++ b/mobile/android/fenix/plugins/apksize/settings.gradle
@@ -0,0 +1,19 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Prevents gradle builds from looking for a root settings.gradle
+pluginManagement {
+ apply from: file('../../../gradle/mozconfig.gradle')
+
+ repositories {
+ gradle.mozconfig.substs.GRADLE_MAVEN_REPOSITORIES.each { repository ->
+ maven {
+ url repository
+ if (gradle.mozconfig.substs.ALLOW_INSECURE_GRADLE_REPOSITORIES) {
+ allowInsecureProtocol = true
+ }
+ }
+ }
+ }
+}
diff --git a/mobile/android/fenix/plugins/apksize/src/main/java/ApkSizePlugin.kt b/mobile/android/fenix/plugins/apksize/src/main/java/ApkSizePlugin.kt
new file mode 100644
index 0000000000..6a70a4da88
--- /dev/null
+++ b/mobile/android/fenix/plugins/apksize/src/main/java/ApkSizePlugin.kt
@@ -0,0 +1,153 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+import org.gradle.api.DefaultTask
+import org.gradle.api.Plugin
+import org.gradle.api.initialization.Settings
+import org.gradle.api.tasks.Input
+import org.gradle.api.tasks.TaskAction
+import org.json.JSONArray
+import org.json.JSONException
+import org.json.JSONObject
+import java.io.File
+import java.nio.file.Files
+import java.nio.file.Paths
+
+class ApkSizePlugin : Plugin<Settings> {
+ override fun apply(settings: Settings) = Unit
+}
+
+/**
+ * Gradle task for determining the size of APKs and logging them in a perfherder compatible format.
+ */
+open class ApkSizeTask : DefaultTask() {
+ /**
+ * Name of the build variant getting built.
+ */
+ @Input
+ var variantName: String? = null
+
+ /**
+ * List of APKs that get build for the build variant.
+ */
+ @Input
+ var apks: List<String>? = null
+
+ @TaskAction
+ fun logApkSize() {
+ val apkSizes = determineApkSizes()
+ if (apkSizes.isEmpty()) {
+ println("Couldn't determine APK sizes for perfherder")
+ return
+ }
+
+ val json = buildPerfherderJson(apkSizes) ?: return
+
+ println("PERFHERDER_DATA: $json")
+ }
+
+ private fun determineApkSizes(): Map<String, Long> {
+ val variantOutputPath = variantName?.removePrefix("fenix")?.lowercase()
+ val basePath = listOf(
+ "${project.projectDir}", "build", "outputs", "apk", "fenix", variantOutputPath
+ ).joinToString(File.separator)
+
+ return requireNotNull(apks).associateWith { apk ->
+ val rawPath = "$basePath${File.separator}$apk"
+
+ try {
+ val path = Paths.get(rawPath)
+ Files.size(path)
+ } catch (t: Throwable) {
+ println("Could not determine size of $apk ($rawPath)")
+ t.printStackTrace()
+ 0
+ }
+ }.filter { (_, size) -> size > 0 }
+ }
+
+ /**
+ * Returns perfherder compatible JSON for tracking the file size of APKs.
+ *
+ * ```
+ * {
+ * "framework": {
+ * "name": "build_metrics"
+ * },
+ * "suites": [
+ * {
+ * "name": "apk-size-[debug,nightly,beta,release]",
+ * "lowerIsBetter": true,
+ * "subtests": [
+ * { "name": "app-arm64-v8a-debug.apk", "value": 98855735 },
+ * { "name": "app-armeabi-v7a-debug.apk", "value": 92300031 },
+ * { "name": "app-x86-debug.apk", "value": 103410909 },
+ * { "name": "app-x86_64-debug.apk", "value": 102465675 }
+ * ],
+ * "value":98855735,
+ * "shouldAlert":false
+ * }
+ * ]
+ * }
+ * ```
+ */
+ private fun buildPerfherderJson(apkSize: Map<String, Long>): JSONObject? {
+ return try {
+ val data = JSONObject()
+
+ val framework = JSONObject()
+ framework.put("name", "build_metrics")
+ data.put("framework", framework)
+
+ val suites = JSONArray()
+
+ val suite = JSONObject()
+ suite.put("name", "apk-size-$variantName")
+ suite.put("value", getSummarySize(apkSize))
+ suite.put("lowerIsBetter", true)
+ suite.put("alertChangeType", "absolute")
+ suite.put("alertThreshold", 1024 * 1024)
+
+ // Debug variants do not have alerts
+ if (variantName?.contains("debug", ignoreCase = true) == true) {
+ suite.put("shouldAlert", false)
+ }
+
+ val subtests = JSONArray()
+ apkSize.forEach { (apk, size) ->
+ val subtest = JSONObject()
+ subtest.put("name", apk)
+ subtest.put("value", size)
+ subtests.put(subtest)
+ }
+ suite.put("subtests", subtests)
+
+ suites.put(suite)
+
+ data.put("suites", suites)
+
+ data
+ } catch (e: JSONException) {
+ println("Couldn't generate perfherder JSON")
+ e.printStackTrace()
+ null
+ }
+ }
+}
+
+/**
+ * Returns a summarized size for the APKs. This is the main value that is getting tracked. The size
+ * of the individual APKs will be reported as "subtests".
+ */
+private fun getSummarySize(apkSize: Map<String, Long>): Long {
+ val arm64size = apkSize.keys.find { it.contains("arm64") }?.let { apk -> apkSize[apk] }
+ if (arm64size != null) {
+ // If available we will report the size of the arm64 APK as the summary. This is the most
+ // important and most installed APK.
+ return arm64size
+ }
+
+ // If there's no arm64 APK then we calculate a simple average.
+ return apkSize.values.sum() / apkSize.size
+}
diff --git a/mobile/android/fenix/plugins/fenixdependencies/build.gradle b/mobile/android/fenix/plugins/fenixdependencies/build.gradle
new file mode 100644
index 0000000000..d377cc4118
--- /dev/null
+++ b/mobile/android/fenix/plugins/fenixdependencies/build.gradle
@@ -0,0 +1,25 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+plugins {
+ id "org.gradle.kotlin.kotlin-dsl" version "4.2.1"
+}
+
+repositories {
+ gradle.mozconfig.substs.GRADLE_MAVEN_REPOSITORIES.each { repository ->
+ maven {
+ url repository
+ if (gradle.mozconfig.substs.ALLOW_INSECURE_GRADLE_REPOSITORIES) {
+ allowInsecureProtocol = true
+ }
+ }
+ }
+}
+
+gradlePlugin {
+ plugins.register("FenixDependenciesPlugin") {
+ id = "FenixDependenciesPlugin"
+ implementationClass = "FenixDependenciesPlugin"
+ }
+}
diff --git a/mobile/android/fenix/plugins/fenixdependencies/settings.gradle b/mobile/android/fenix/plugins/fenixdependencies/settings.gradle
new file mode 100644
index 0000000000..16701d4aac
--- /dev/null
+++ b/mobile/android/fenix/plugins/fenixdependencies/settings.gradle
@@ -0,0 +1,19 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Prevents gradle builds from looking for a root settings.gradle
+pluginManagement {
+ apply from: file('../../../gradle/mozconfig.gradle')
+
+ repositories {
+ gradle.mozconfig.substs.GRADLE_MAVEN_REPOSITORIES.each { repository ->
+ maven {
+ url repository
+ if (gradle.mozconfig.substs.ALLOW_INSECURE_GRADLE_REPOSITORIES) {
+ allowInsecureProtocol = true
+ }
+ }
+ }
+ }
+}
diff --git a/mobile/android/fenix/plugins/fenixdependencies/src/main/java/FenixDependenciesPlugin.kt b/mobile/android/fenix/plugins/fenixdependencies/src/main/java/FenixDependenciesPlugin.kt
new file mode 100644
index 0000000000..9df93af3fa
--- /dev/null
+++ b/mobile/android/fenix/plugins/fenixdependencies/src/main/java/FenixDependenciesPlugin.kt
@@ -0,0 +1,111 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+import org.gradle.api.Plugin
+import org.gradle.api.initialization.Settings
+
+// If you ever need to force a toolchain rebuild (taskcluster) then edit the following comment.
+// FORCE REBUILD 2023-05-12
+
+class FenixDependenciesPlugin : Plugin<Settings> {
+ override fun apply(settings: Settings) = Unit
+}
+
+object FenixVersions {
+ const val osslicenses_plugin = "0.10.4"
+
+ const val falcon = "2.2.0"
+ const val fastlane = "2.1.1"
+
+ const val androidx_activity = "1.7.2"
+ const val androidx_benchmark = "1.2.3"
+ const val androidx_profileinstaller = "1.3.1"
+ const val androidx_splash_screen = "1.0.1"
+ const val androidx_transition = "1.4.1"
+ const val androidx_datastore = "1.0.0"
+ const val google_accompanist = "0.32.0"
+
+ const val adjust = "4.38.2"
+ const val installreferrer = "2.2"
+
+ const val junit = "5.10.2"
+ const val mockk = "1.13.10"
+
+ const val google_ads_id_version = "16.0.0"
+
+ const val google_play_review_version = "2.0.1"
+
+ // keep in sync with the versions used in AS.
+ const val protobuf = "3.21.10"
+ const val protobuf_plugin = "0.9.4"
+}
+
+@Suppress("unused")
+object FenixDependencies {
+ const val tools_benchmarkgradle = "androidx.benchmark:benchmark-gradle-plugin:${FenixVersions.androidx_benchmark}"
+
+ const val osslicenses_plugin = "com.google.android.gms:oss-licenses-plugin:${FenixVersions.osslicenses_plugin}"
+
+ const val androidx_benchmark_junit4 = "androidx.benchmark:benchmark-junit4:${FenixVersions.androidx_benchmark}"
+ const val androidx_benchmark_macro_junit4 = "androidx.benchmark:benchmark-macro-junit4:${FenixVersions.androidx_benchmark}"
+ const val androidx_core_splashscreen = "androidx.core:core-splashscreen:${FenixVersions.androidx_splash_screen}"
+ const val androidx_profileinstaller = "androidx.profileinstaller:profileinstaller:${FenixVersions.androidx_profileinstaller}"
+ const val androidx_activity_ktx = "androidx.activity:activity-ktx:${FenixVersions.androidx_activity}"
+ const val androidx_transition = "androidx.transition:transition:${FenixVersions.androidx_transition}"
+ const val androidx_datastore = "androidx.datastore:datastore:${FenixVersions.androidx_datastore}"
+
+ const val google_accompanist_drawablepainter = "com.google.accompanist:accompanist-drawablepainter:${FenixVersions.google_accompanist}"
+
+ const val protobuf_javalite = "com.google.protobuf:protobuf-javalite:${FenixVersions.protobuf}"
+ const val protobuf_compiler = "com.google.protobuf:protoc:${FenixVersions.protobuf}"
+
+ const val adjust = "com.adjust.sdk:adjust-android:${FenixVersions.adjust}"
+ const val installreferrer = "com.android.installreferrer:installreferrer:${FenixVersions.installreferrer}"
+
+ const val mockk = "io.mockk:mockk:${FenixVersions.mockk}"
+ const val mockk_android = "io.mockk:mockk-android:${FenixVersions.mockk}"
+ const val falcon = "com.jraska:falcon:${FenixVersions.falcon}"
+ const val fastlane = "tools.fastlane:screengrab:${FenixVersions.fastlane}"
+
+ // --- START AndroidX test dependencies --- //
+ // N.B.: the versions of these dependencies appear to be pinned together. To avoid bugs, they
+ // should always be updated together based on the latest version from the Android test releases page:
+ // https://developer.android.com/jetpack/androidx/releases/test
+ // For the full IDs of these test dependencies, see:
+ // https://developer.android.com/training/testing/set-up-project#android-test-dependencies
+ private const val androidx_test_orchestrator = "1.4.2"
+ private const val androidx_espresso_version = "3.5.1"
+ const val espresso_contrib = "androidx.test.espresso:espresso-contrib:$androidx_espresso_version"
+ const val espresso_idling_resources = "androidx.test.espresso:espresso-idling-resource:$androidx_espresso_version"
+ const val espresso_intents = "androidx.test.espresso:espresso-intents:$androidx_espresso_version"
+ // Monitor is unused
+ const val orchestrator = "androidx.test:orchestrator:$androidx_test_orchestrator"
+ // Truth is unused
+ // Test services is unused
+ // --- END AndroidX test dependencies --- //
+
+ const val google_ads_id = "com.google.android.gms:play-services-ads-identifier:${FenixVersions.google_ads_id_version}"
+
+ // Required for in-app reviews
+ const val google_play_review = "com.google.android.play:review:${FenixVersions.google_play_review_version}"
+ const val google_play_review_ktx = "com.google.android.play:review-ktx:${FenixVersions.google_play_review_version}"
+
+ const val junitApi = "org.junit.jupiter:junit-jupiter-api:${FenixVersions.junit}"
+ const val junitParams = "org.junit.jupiter:junit-jupiter-params:${FenixVersions.junit}"
+ const val junitEngine = "org.junit.jupiter:junit-jupiter-engine:${FenixVersions.junit}"
+}
+
+/**
+ * Functionality to limit specific dependencies to specific repositories. These are typically expected to be used by
+ * dependency group name (i.e. with `include/excludeGroup`). For additional info, see:
+ * https://docs.gradle.org/current/userguide/declaring_repositories.html#sec::matching_repositories_to_dependencies
+ *
+ * Note: I wanted to nest this in Deps but for some reason gradle can't find it so it's top-level now. :|
+ */
+object RepoMatching {
+ const val mozilla = "org\\.mozilla\\..*"
+ const val androidx = "androidx\\..*"
+ const val comAndroid = "com\\.android.*"
+ const val comGoogle = "com\\.google\\..*"
+}