[fenix] No issue: Move Do and OpenClass to utils pkg.
[gecko.git] / mobile / android / fenix / app / build.gradle
blobfb28f8d91e45448419319fb311e2d36dc4fa633d
1 // Allow installing Gradle plugins from the Mozilla Maven repositories
2 buildscript {
3     repositories {
4         maven {
5             url "https://nightly.maven.mozilla.org/maven2"
6         }
7         maven {
8             url "https://maven.mozilla.org/maven2"
9         }
11         dependencies {
12             classpath "org.mozilla.components:tooling-glean-gradle:${Versions.mozilla_android_components}"
13         }
14     }
17 plugins {
18     id "com.jetbrains.python.envs" version "0.0.26"
21 apply plugin: 'com.android.application'
22 apply plugin: 'kotlin-android'
23 apply plugin: 'kotlin-android-extensions'
24 apply plugin: 'kotlin-kapt'
25 apply plugin: 'jacoco'
26 apply from: "$project.rootDir/automation/gradle/versionCode.gradle"
27 apply plugin: 'androidx.navigation.safeargs.kotlin'
28 apply plugin: 'com.google.android.gms.oss-licenses-plugin'
31 import com.android.build.OutputFile
32 import org.gradle.internal.logging.text.StyledTextOutput.Style
33 import org.gradle.internal.logging.text.StyledTextOutputFactory
34 import org.mozilla.fenix.gradle.tasks.LintUnitTestRunner
36 import static org.gradle.api.tasks.testing.TestResult.ResultType
38 android {
39     compileSdkVersion 28
40     defaultConfig {
41         applicationId "org.mozilla"
42         minSdkVersion Config.minSdkVersion
43         targetSdkVersion Config.targetSdkVersion
44         versionCode 1
45         versionName Config.generateDebugVersionName()
46         vectorDrawables.useSupportLibrary = true
47         testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
48         testInstrumentationRunnerArguments clearPackageData: 'true'
49         resValue "bool", "IS_DEBUG", "false"
50         buildConfigField "boolean", "USE_RELEASE_VERSIONING", "false"
51         buildConfigField "String", "AMO_COLLECTION", "\"7e8d6dc651b54ab385fb8791bf9dac\""
52         manifestPlaceholders = [
53                 "isRaptorEnabled": "false",
54                 "deepLinkScheme": "fenix-dev"
55         ]
56     }
58     def releaseTemplate = {
59         shrinkResources true
60         minifyEnabled true
61         proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
62         matchingFallbacks = ['release'] // Use on the "release" build type in dependencies (AARs)
63     }
65     buildTypes {
66         debug {
67             shrinkResources false
68             minifyEnabled false
69             applicationIdSuffix ".fenix.debug"
70             manifestPlaceholders.isRaptorEnabled = "true"
71             resValue "bool", "IS_DEBUG", "true"
72             pseudoLocalesEnabled true
73         }
74         forPerformanceTest releaseTemplate >> { // the ">>" concatenates the raptor-specific options with the template
75             manifestPlaceholders.isRaptorEnabled = "true"
76             applicationIdSuffix ".fenix.performancetest"
77             debuggable true
78             manifestPlaceholders = [
79                 // Since we configure this build to behave like a "fennec" flavored build, we need
80                 // to set a shared user id for the manifest. The actual values does not matter.
81                 // However we pick a unique value to not "clash" with other Fenix/Fennec builds
82                 // installed on the device.
83                 "sharedUserId": "org.mozilla.fenix.performancetest.sharedID"
84             ]
85         }
86         fenixNightly releaseTemplate >> {
87             applicationIdSuffix ".fenix.nightly"
88             buildConfigField "boolean", "USE_RELEASE_VERSIONING", "true"
89             manifestPlaceholders = ["deepLinkScheme": "fenix-nightly"]
90         }
91         fenixBeta releaseTemplate >> {
92             applicationIdSuffix ".fenix.beta"
93             buildConfigField "boolean", "USE_RELEASE_VERSIONING", "true"
94             manifestPlaceholders = ["deepLinkScheme": "fenix-beta"]
95         }
96         fenixProduction releaseTemplate >> {
97             applicationIdSuffix ".fenix"
98             buildConfigField "boolean", "USE_RELEASE_VERSIONING", "true"
99             manifestPlaceholders = ["deepLinkScheme": "fenix"]
100         }
101         fennecProduction releaseTemplate >> {
102             buildConfigField "boolean", "USE_RELEASE_VERSIONING", "true"
103             applicationIdSuffix ".firefox"
104             manifestPlaceholders = [
105                     // This release type is meant to replace Firefox (Release channel) and therefore needs to inherit
106                     // its sharedUserId for all eternity. See:
107                     // https://searchfox.org/mozilla-central/search?q=moz_android_shared_id&case=false&regexp=false&path=
108                     // Shipping an app update without sharedUserId can have
109                     // fatal consequences. For example see:
110                     //  - https://issuetracker.google.com/issues/36924841
111                     //  - https://issuetracker.google.com/issues/36905922
112                     "sharedUserId": "org.mozilla.firefox.sharedID",
113                     "deepLinkScheme": "fenix"
114             ]
115         }
116         fennecBeta releaseTemplate >> {
117             buildConfigField "boolean", "USE_RELEASE_VERSIONING", "true"
118             applicationIdSuffix ".firefox_beta"
119             manifestPlaceholders = [
120                     // This release type is meant to replace Firefox (Release channel) and therefore needs to inherit
121                     // its sharedUserId for all eternity. See:
122                     // https://searchfox.org/mozilla-central/search?q=moz_android_shared_id&case=false&regexp=false&path=
123                     // Shipping an app update without sharedUserId can have
124                     // fatal consequences. For example see:
125                     //  - https://issuetracker.google.com/issues/36924841
126                     //  - https://issuetracker.google.com/issues/36905922
127                     "sharedUserId": "org.mozilla.firefox.sharedID",
128                     "deepLinkScheme": "fenix-beta"
129             ]
130         }
131         fennecNightly releaseTemplate >> {
132             buildConfigField "boolean", "USE_RELEASE_VERSIONING", "true"
133             applicationIdSuffix ".fennec_aurora"
134             manifestPlaceholders = [
135                     // This release type is meant to replace Firefox (Release channel) and therefore needs to inherit
136                     // its sharedUserId for all eternity. See:
137                     // https://searchfox.org/mozilla-central/search?q=moz_android_shared_id&case=false&regexp=false&path=
138                     // Shipping an app update without sharedUserId can have
139                     // fatal consequences. For example see:
140                     //  - https://issuetracker.google.com/issues/36924841
141                     //  - https://issuetracker.google.com/issues/36905922
142                     "sharedUserId": "org.mozilla.fennec.sharedID",
143                     "deepLinkScheme": "fenix-nightly"
144             ]
145         }
146     }
148     variantFilter { // There's a "release" build type that exists by default that we don't use (it's replaced by "nightly" and "beta")
149         if (buildType.name == 'release') {
150             setIgnore true
151         }
153         // Current build variant setup:
154         //
155         //                      | geckoNightly  | geckoBeta |
156         // |--------------------|---------------|-----------|
157         // | debug              | ✅            | ✅       | Both variants for testing and development.
158         // | forPerformanceTest | ✅            | ✅       | Both variants unless the perf team only cares about Nightly (TBD).
159         // | fenixNightly       | ✅            | ✅       | Built with both, but only the "geckoNightly" one is published to Google Play
160         // | fenixBeta          | ❌            | ✅       | Fenix Beta ships with GV Beta
161         // | fenixProduction    | ❌            | ✅       | Fenix Production ships with GV Beta
162         // | fennecProduction   | ❌            | ✅       | Fenix build to replace production Firefox builds
163         // | fennecBeta         | ❌            | ✅       | Fenix build to replace beta Firefox builds
164         // | fennecNightly      | ✅            | ❌       | Fenix build to replace Nightly Firefox builds
166         def flavors = flavors*.name.toString().toLowerCase()
168         if (buildType.name == 'fenixBeta' && flavors.contains("geckonightly")) {
169             setIgnore true
170         }
172         if (buildType.name == 'fenixProduction' && flavors.contains("geckonightly")) {
173             setIgnore true
174         }
176         if ((buildType.name == 'fennecProduction' || buildType.name == 'fennecBeta') && flavors.contains("geckonightly")) {
177             setIgnore true
178         }
180         if (buildType.name == 'fennecNightly' && flavors.contains("geckobeta")) {
181             setIgnore true
182         }
183     }
185     aaptOptions {
186         // All JavaScript code used internally by GeckoView is packaged in a
187         // file called omni.ja. If this file is compressed in the APK,
188         // GeckoView must uncompress it before it can do anything else which
189         // causes a significant delay on startup.
190         noCompress 'ja'
191     }
193     testOptions {
194         execution 'ANDROIDX_TEST_ORCHESTRATOR'
195         unitTests.includeAndroidResources = true
196         animationsDisabled = true
197     }
199     flavorDimensions "engine"
201     sourceSets {
202         androidTest {
203             resources.srcDirs += ['src/androidTest/resources']
204         }
205         fennecNightly {
206             java.srcDirs = ['src/migration/java']
207             manifest.srcFile "src/migration/AndroidManifest.xml"
208         }
209         fennecBeta {
210             java.srcDirs = ['src/migration/java']
211             manifest.srcFile "src/migration/AndroidManifest.xml"
212         }
213         fennecProduction {
214             java.srcDirs = ['src/migration/java']
215             manifest.srcFile "src/migration/AndroidManifest.xml"
216         }
217         forPerformanceTest {
218             // We want our performance test builds to use the same code as our "fennec" flavor builds
219             // since those builds will ship to our large user base.
220             java.srcDirs = ['src/migration/java']
221             manifest.srcFile "src/migration/AndroidManifest.xml"
222         }
223     }
225     productFlavors {
226         geckoNightly {
227             dimension "engine"
228         }
230         geckoBeta {
231             dimension "engine"
232         }
233     }
235     splits {
236         abi {
237             enable true
239             reset()
241             include "x86", "armeabi-v7a", "arm64-v8a", "x86_64"
242         }
243     }
245     compileOptions {
246         sourceCompatibility JavaVersion.VERSION_1_8
247         targetCompatibility JavaVersion.VERSION_1_8
248     }
250     lintOptions {
251         lintConfig file("lint.xml")
252     }
254     packagingOptions {
255         exclude 'META-INF/atomicfu.kotlin_module'
256     }
258     testOptions {
259         unitTests.returnDefaultValues = true
260     }
263 def baseVersionCode = generatedVersionCode
265 android.applicationVariants.all { variant ->
267 // -------------------------------------------------------------------------------------------------
268 // Set up kotlin-allopen plugin for writing tests
269 // -------------------------------------------------------------------------------------------------
271     boolean hasTest = gradle.startParameter.taskNames.find { it.contains("test") || it.contains("Test") } != null
272     if (hasTest) {
273         apply plugin: 'kotlin-allopen'
274         allOpen {
275             annotation("org.mozilla.fenix.utils.OpenClass")
276         }
277     }
279 // -------------------------------------------------------------------------------------------------
280 // Generate version codes for builds
281 // -------------------------------------------------------------------------------------------------
283     def isDebug = variant.buildType.resValues['IS_DEBUG']?.value ?: false
284     def useReleaseVersioning = variant.buildType.buildConfigFields['USE_RELEASE_VERSIONING']?.value ?: false
285     def versionName = Config.releaseVersionName(project)
287     println("----------------------------------------------")
288     println("Variant name:      " + variant.name)
289     println("Application ID:    " + [variant.mergedFlavor.applicationId, variant.buildType.applicationIdSuffix].findAll().join())
290     println("Build type:        " + variant.buildType.name)
291     println("Flavor:            " + variant.flavorName)
292     println("Telemetry enabled: " + !isDebug)
294     if (useReleaseVersioning) {
295         // The Google Play Store does not allow multiple APKs for the same app that all have the
296         // same version code. Therefore we need to have different version codes for our ARM and x86
297         // builds.
299         // Our generated version code now has a length of 9 (See automation/gradle/versionCode.gradle).
300         // Our x86 builds need a higher version code to avoid installing ARM builds on an x86 device
301         // with ARM compatibility mode.
303         variant.outputs.each { output ->
304             def abi = output.getFilter(OutputFile.ABI)
306             def versionCodeOverride
307             if (variant.name.contains("Fennec")) {
308                 versionCodeOverride = Config.generateFennecVersionCode(abi)
309             } else if (abi == "x86_64") {
310                 versionCodeOverride = baseVersionCode + 3
311             } else if (abi == "x86") {
312                 versionCodeOverride = baseVersionCode + 2
313             } else if (abi == "arm64-v8a") {
314                 versionCodeOverride = baseVersionCode + 1
315             } else if (abi == "armeabi-v7a") {
316                 versionCodeOverride = baseVersionCode
317             } else {
318                 throw RuntimeException("Unknown ABI: $abi")
319             }
321             println("versionCode for $abi = $versionCodeOverride")
323             output.versionNameOverride = versionName
324             output.versionCodeOverride = versionCodeOverride
325         }
326     }
328 // -------------------------------------------------------------------------------------------------
329 // BuildConfig: Set variables for Sentry, Crash Reporting, and Telemetry
330 // -------------------------------------------------------------------------------------------------
332     buildConfigField 'String', 'SENTRY_TOKEN', 'null'
333     if (!isDebug) {
334         buildConfigField 'boolean', 'CRASH_REPORTING', 'true'
335         // Reading sentry token from local file (if it exists). In a release task on taskcluster it will be available.
336         try {
337             def token = new File("${rootDir}/.sentry_token").text.trim()
338             buildConfigField 'String', 'SENTRY_TOKEN', '"' + token + '"'
339         } catch (FileNotFoundException ignored) {}
340     } else {
341         buildConfigField 'boolean', 'CRASH_REPORTING', 'false'
342     }
344     if (!isDebug) {
345         buildConfigField 'boolean', 'TELEMETRY', 'true'
346     } else {
347         buildConfigField 'boolean', 'TELEMETRY', 'false'
348     }
350     def buildDate = Config.generateBuildDate()
351     buildConfigField 'String', 'BUILD_DATE', '"' + buildDate + '"'
353     def variantName = variant.getName()
355 // -------------------------------------------------------------------------------------------------
356 // Adjust: Read token from local file if it exists (Only release builds)
357 // -------------------------------------------------------------------------------------------------
359     print("Adjust token: ")
361     if (!isDebug) {
362         try {
363             def token = new File("${rootDir}/.adjust_token").text.trim()
364             buildConfigField 'String', 'ADJUST_TOKEN', '"' + token + '"'
365             println "(Added from .adjust_token file)"
366         } catch (FileNotFoundException ignored) {
367             buildConfigField 'String', 'ADJUST_TOKEN', 'null'
368             println("X_X")
369         }
370     } else {
371         buildConfigField 'String', 'ADJUST_TOKEN', 'null'
372         println("--")
373     }
375 // -------------------------------------------------------------------------------------------------
376 // Leanplum: Read token from local file if it exists
377 // -------------------------------------------------------------------------------------------------
379     print("Leanplum token: ")
381     try {
382         def parts = new File("${rootDir}/.leanplum_token").text.trim().split(":")
383         def id = parts[0]
384         def key = parts[1]
385         buildConfigField 'String', 'LEANPLUM_ID', '"' + id + '"'
386         buildConfigField 'String', 'LEANPLUM_TOKEN', '"' + key + '"'
387         println "(Added from .leanplum_token file)"
388     } catch (FileNotFoundException ignored) {
389         buildConfigField 'String', 'LEANPLUM_ID', 'null'
390         buildConfigField 'String', 'LEANPLUM_TOKEN', 'null'
391         println("X_X")
392     }
394 // -------------------------------------------------------------------------------------------------
395 // Digital Asset Links: Read token from local file if it exists
396 // -------------------------------------------------------------------------------------------------
398     print("Digital Asset Links token: ")
400     try {
401         def token = new File("${rootDir}/.digital_asset_links_token").text.trim()
402         buildConfigField 'String', 'DIGITAL_ASSET_LINKS_TOKEN', '"' + token + '"'
403         println "(Added from .digital_asset_links_token file)"
404     } catch (FileNotFoundException ignored) {
405         buildConfigField 'String', 'DIGITAL_ASSET_LINKS_TOKEN', 'null'
406         println("X_X")
407     }
409 // -------------------------------------------------------------------------------------------------
410 // MLS: Read token from local file if it exists
411 // -------------------------------------------------------------------------------------------------
413     print("MLS token: ")
415     try {
416         def token = new File("${rootDir}/.mls_token").text.trim()
417         buildConfigField 'String', 'MLS_TOKEN', '"' + token + '"'
418         println "(Added from .mls_token file)"
419     } catch (FileNotFoundException ignored) {
420         buildConfigField 'String', 'MLS_TOKEN', '""'
421         println("X_X")
422     }
425 androidExtensions {
426     experimental = true
429 // Generate Kotlin code and markdown docs for the Fenix Glean metrics.
430 ext.gleanGenerateMarkdownDocs = true
431 ext.gleanDocsDirectory = "$rootDir/docs"
432 apply plugin: "org.mozilla.telemetry.glean-gradle-plugin"
434 dependencies {
435     geckoNightlyImplementation Deps.mozilla_browser_engine_gecko_nightly
436     geckoBetaImplementation Deps.mozilla_browser_engine_gecko_beta
438     implementation Deps.kotlin_stdlib
439     implementation Deps.kotlin_coroutines
440     implementation Deps.kotlin_coroutines_android
441     testImplementation Deps.kotlin_coroutines_test
442     implementation Deps.androidx_appcompat
443     implementation Deps.androidx_constraintlayout
444     implementation Deps.androidx_coordinatorlayout
446     implementation Deps.sentry
447     implementation Deps.osslicenses_library
449     implementation Deps.leanplum_core
450     implementation Deps.leanplum_fcm
452     implementation Deps.mozilla_concept_engine
453     implementation Deps.mozilla_concept_push
454     implementation Deps.mozilla_concept_storage
455     implementation Deps.mozilla_concept_sync
456     implementation Deps.mozilla_concept_toolbar
458     implementation Deps.mozilla_browser_awesomebar
459     implementation Deps.mozilla_feature_downloads
460     implementation Deps.mozilla_browser_domains
461     implementation Deps.mozilla_browser_icons
462     implementation Deps.mozilla_browser_menu
463     implementation Deps.mozilla_browser_search
464     implementation Deps.mozilla_browser_session
465     implementation Deps.mozilla_browser_state
466     implementation Deps.mozilla_browser_storage_sync
467     implementation Deps.mozilla_browser_toolbar
469     implementation Deps.mozilla_support_extensions
470     implementation Deps.mozilla_feature_addons
472     implementation Deps.mozilla_feature_accounts
473     implementation Deps.mozilla_feature_app_links
474     implementation Deps.mozilla_feature_awesomebar
475     implementation Deps.mozilla_feature_contextmenu
476     implementation Deps.mozilla_feature_customtabs
477     implementation Deps.mozilla_feature_downloads
478     implementation Deps.mozilla_feature_intent
479     implementation Deps.mozilla_feature_media
480     implementation Deps.mozilla_feature_prompts
481     implementation Deps.mozilla_feature_push
482     implementation Deps.mozilla_feature_pwa
483     implementation Deps.mozilla_feature_qr
484     implementation Deps.mozilla_feature_search
485     implementation Deps.mozilla_feature_session
486     implementation Deps.mozilla_feature_toolbar
487     implementation Deps.mozilla_feature_tabs
488     implementation Deps.mozilla_feature_findinpage
489     implementation Deps.mozilla_feature_site_permissions
490     implementation Deps.mozilla_feature_readerview
491     implementation Deps.mozilla_feature_tab_collections
492     implementation Deps.mozilla_feature_top_sites
493     implementation Deps.mozilla_feature_share
494     implementation Deps.mozilla_feature_accounts_push
495     implementation Deps.mozilla_feature_webcompat
496     implementation Deps.mozilla_feature_webnotifications
498     implementation Deps.mozilla_service_sync_logins
499     implementation Deps.mozilla_service_firefox_accounts
500     implementation Deps.mozilla_service_glean
501     implementation Deps.mozilla_service_experiments
502     implementation Deps.mozilla_service_location
505     implementation Deps.mozilla_support_base
506     implementation Deps.mozilla_support_ktx
507     implementation Deps.mozilla_support_rustlog
508     implementation Deps.mozilla_support_utils
509     implementation Deps.mozilla_support_locale
511     implementation Deps.mozilla_support_migration
513     implementation Deps.mozilla_ui_colors
514     implementation Deps.mozilla_ui_icons
515     implementation Deps.mozilla_ui_publicsuffixlist
517     implementation Deps.mozilla_lib_crash
518     implementation Deps.mozilla_lib_push_firebase
519     implementation Deps.mozilla_lib_dataprotect
520     debugImplementation Deps.leakcanary
522     implementation Deps.androidx_legacy
523     implementation Deps.androidx_biometric
524     implementation Deps.androidx_paging
525     implementation Deps.androidx_preference
526     implementation Deps.androidx_fragment
527     implementation Deps.androidx_navigation_fragment
528     implementation Deps.androidx_navigation_ui
529     implementation Deps.androidx_recyclerview
530     implementation Deps.androidx_lifecycle_livedata
531     implementation Deps.androidx_lifecycle_runtime
532     implementation Deps.androidx_lifecycle_viewmodel
533     implementation Deps.androidx_core
534     implementation Deps.androidx_core_ktx
535     implementation Deps.androidx_transition
536     implementation Deps.androidx_work_ktx
537     implementation Deps.google_material
539     implementation Deps.google_flexbox
541     implementation Deps.lottie
543     implementation Deps.adjust
544     implementation Deps.installreferrer // Required by Adjust
546     implementation Deps.google_ads_id // Required for the Google Advertising ID
548     androidTestImplementation Deps.uiautomator
549 // Removed pending AndroidX fixes
550     androidTestImplementation "tools.fastlane:screengrab:2.0.0"
551 //    androidTestImplementation "br.com.concretesolutions:kappuccino:1.2.1"
553     androidTestImplementation Deps.espresso_core, {
554         exclude group: 'com.android.support', module: 'support-annotations'
555     }
557     androidTestImplementation(Deps.espresso_contrib) {
558         exclude module: 'appcompat-v7'
559         exclude module: 'support-v4'
560         exclude module: 'support-annotations'
561         exclude module: 'recyclerview-v7'
562         exclude module: 'design'
563         exclude module: 'espresso-core'
564     }
566     androidTestImplementation Deps.androidx_test_core
567     androidTestImplementation Deps.espresso_idling_resources
568     androidTestImplementation Deps.espresso_intents
570     androidTestImplementation Deps.tools_test_runner
571     androidTestImplementation Deps.tools_test_rules
572     androidTestUtil Deps.orchestrator
573     androidTestImplementation Deps.espresso_core, {
574         exclude group: 'com.android.support', module: 'support-annotations'
575     }
577     androidTestImplementation Deps.androidx_junit
578     androidTestImplementation Deps.androidx_work_testing
579     androidTestImplementation Deps.mockwebserver
580     testImplementation Deps.mozilla_support_test
581     testImplementation Deps.androidx_junit
582     testImplementation Deps.androidx_work_testing
583     testImplementation (Deps.robolectric) {
584         exclude group: 'org.apache.maven'
585     }
587     testImplementation 'org.apache.maven:maven-ant-tasks:2.1.3'
588     implementation Deps.mozilla_support_rusthttp
590     testImplementation Deps.mockito_core
591     androidTestImplementation Deps.mockito_android
592     testImplementation Deps.mockk
594     // For the initial release of Glean 19, we require consumer applications to
595     // depend on a separate library for unit tests. This will be removed in future releases.
596     testImplementation "org.mozilla.telemetry:glean-forUnitTests:${project.ext.glean_version}"
598     lintChecks project(":mozilla-lint-rules")
601 if (project.hasProperty("raptor")) {
602     android.defaultConfig.manifestPlaceholders.isRaptorEnabled = "true"
605 if (project.hasProperty("coverage")) {
606     tasks.withType(Test) {
607         jacoco.includeNoLocationClasses = true
608     }
610     android.applicationVariants.all { variant ->
611         task "jacoco${variant.name.capitalize()}TestReport"(type: JacocoReport, dependsOn: "test${variant.name.capitalize()}UnitTest") {
612             reports {
613                 xml.enabled = true
614                 html.enabled = true
615             }
617             def fileFilter = ['**/R.class', '**/R$*.class', '**/BuildConfig.*', '**/Manifest*.*',
618                               '**/*Test*.*', 'android/**/*.*', '**/*$[0-9].*']
619             def kotlinDebugTree = fileTree(dir: "$project.buildDir/tmp/kotlin-classes/${variant.name}", excludes: fileFilter)
620             def javaDebugTree = fileTree(dir: "$project.buildDir/intermediates/classes/${variant.flavorName}/${variant.buildType.name}",
621                     excludes: fileFilter)
622             def mainSrc = "$project.projectDir/src/main/java"
624             sourceDirectories = files([mainSrc])
625             classDirectories = files([kotlinDebugTree, javaDebugTree])
626             executionData = fileTree(dir: project.buildDir, includes: [
627                     "jacoco/test${variant.name.capitalize()}UnitTest.exec", 'outputs/code-coverage/connected/*coverage.ec'
628             ])
629         }
630     }
632     android {
633         buildTypes {
634             debug {
635                 testCoverageEnabled true
636             }
637         }
638     }
641 // -------------------------------------------------------------------------------------------------
642 // Task for printing APK information for the requested variant
643 // Usage: "./gradlew printVariants
644 // -------------------------------------------------------------------------------------------------
645 task printVariants {
646     doLast {
647         def variants = android.applicationVariants.collect {[
648                 apks: it.variantData.outputScope.apkDatas.collect {[
649                         abi: it.filters.find { it.filterType == 'ABI' }.identifier,
650                         fileName: it.outputFileName,
651                 ]},
652                 build_type: it.buildType.name,
653                 engine: it.productFlavors.find { it.dimension == 'engine' }.name,
654                 name: it.name,
655         ]}
656         // AndroidTest is a special case not included above
657         variants.add([
658             apks: [[
659                 abi: 'noarch',
660                 fileName: 'app-geckoNightly-debug-androidTest.apk',
661             ]],
662             build_type: 'androidTest',
663             engine: 'geckoNightly',
664             name: 'androidTest',
665         ])
666         println 'variants: ' + groovy.json.JsonOutput.toJson(variants)
667     }
670 task buildTranslationArray {
671     def foundLocales = new StringBuilder()
672     foundLocales.append("new String[]{")
674     fileTree("src/main/res").visit { FileVisitDetails details ->
675         if(details.file.path.endsWith("/strings.xml")){
676             def languageCode = details.file.parent.tokenize('/').last().replaceAll('values-','').replaceAll('-r','-')
677             languageCode = (languageCode == "values") ? "en-US" : languageCode
678             foundLocales.append("\"").append(languageCode).append("\"").append(",")
679         }
680     }
682     foundLocales.append("}")
683     def foundLocalesString = foundLocales.toString().replaceAll(',}','}')
684     android.defaultConfig.buildConfigField "String[]", "SUPPORTED_LOCALE_ARRAY", foundLocalesString
687 task lintUnitTestRunner(type: LintUnitTestRunner)
689 afterEvaluate {
691     // Format test output. Ported from AC #2401
692     tasks.matching {it instanceof Test}.all {
693         systemProperty "robolectric.logging", "stdout"
694         systemProperty "logging.test-mode", "true"
696         testLogging.events = []
698         def out = services.get(StyledTextOutputFactory).create("tests")
700         beforeSuite { descriptor ->
701             if (descriptor.getClassName() != null) {
702                 out.style(Style.Header).println("\nSUITE: " + descriptor.getClassName())
703             }
704         }
706         beforeTest { descriptor ->
707             out.style(Style.Description).println("  TEST: " + descriptor.getName())
708         }
710         onOutput { descriptor, event ->
711             logger.lifecycle("    " + event.message.trim())
712         }
714         afterTest { descriptor, result ->
715             switch (result.getResultType()) {
716                 case ResultType.SUCCESS:
717                     out.style(Style.Success).println("  SUCCESS")
718                     break
720                 case ResultType.FAILURE:
721                     out.style(Style.Failure).println("  FAILURE")
722                     logger.lifecycle("", result.getException())
723                     break
725                 case ResultType.SKIPPED:
726                     out.style(Style.Info).println("  SKIPPED")
727                     break
728             }
729             logger.lifecycle("")
730         }
731     }
734 if (gradle.hasProperty('localProperties.dependencySubstitutions.geckoviewTopsrcdir')) {
735     if (gradle.hasProperty('localProperties.dependencySubstitutions.geckoviewTopobjdir')) {
736         ext.topobjdir = gradle."localProperties.dependencySubstitutions.geckoviewTopobjdir"
737     }
738     ext.topsrcdir = gradle."localProperties.dependencySubstitutions.geckoviewTopsrcdir"
739     apply from: "${topsrcdir}/substitute-local-geckoview.gradle"
742 if (gradle.hasProperty('localProperties.autoPublish.android-components.dir')) {
743     ext.acSrcDir = gradle."localProperties.autoPublish.android-components.dir"
744     apply from: "../${acSrcDir}/substitute-local-ac.gradle"
747 if (gradle.hasProperty('localProperties.autoPublish.application-services.dir')) {
748     ext.appServicesSrcDir = gradle."localProperties.autoPublish.application-services.dir"
749     apply from: "../${appServicesSrcDir}/build-scripts/substitute-local-appservices.gradle"