[focus] For #1797578 - Create toggle option in the toolbar that allow a site to be...
[gecko.git] / mobile / android / focus-android / app / build.gradle
blobe259cdc2ac872c4f48c3420ae1d30096c526d797
1 plugins {
2     id "com.jetbrains.python.envs" version "0.0.26"
5 apply plugin: 'com.android.application'
6 apply plugin: 'kotlin-android'
7 apply plugin: 'kotlin-parcelize'
8 apply plugin: 'jacoco'
9 apply from: "$project.rootDir/tools/gradle/versionCode.gradle"
11 import com.android.build.OutputFile
12 import groovy.json.JsonOutput
14 android {
15     compileSdkVersion 33
17     if (project.hasProperty("testBuildType")) {
18         // Allowing to configure the test build type via command line flag (./gradlew -PtestBuildType=beta ..)
19         // in order to run UI tests against other build variants than debug in automation.
20         testBuildType project.property("testBuildType")
21     }
23     defaultConfig {
24         applicationId "org.mozilla"
25         minSdkVersion 21
26         targetSdkVersion 32
27         versionCode 11 // This versionCode is "frozen" for local builds. For "release" builds we
28                        // override this with a generated versionCode at build time.
29         // The versionName is dynamically overridden for all the build variants at build time.
30         versionName Config.generateDebugVersionName()
31         testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
32         testInstrumentationRunnerArguments clearPackageData: 'true'
34         vectorDrawables.useSupportLibrary = true
36         multiDexEnabled true
37     }
39     compileOptions {
40         sourceCompatibility JavaVersion.VERSION_1_8
41         targetCompatibility JavaVersion.VERSION_1_8
42     }
44     lintOptions {
45         lintConfig file("lint.xml")
46     }
48     // We have a three dimensional build configuration:
49     // BUILD TYPE (debug, release) X PRODUCT FLAVOR (focus, klar)
51     buildTypes {
52         release {
53             // We allow disabling optimization by passing `-PdisableOptimization` to gradle. This is used
54             // in automation for UI testing non-debug builds.
55             shrinkResources !project.hasProperty("disableOptimization")
56             minifyEnabled !project.hasProperty("disableOptimization")
57             proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
58             matchingFallbacks = ['release']
60             if (gradle.hasProperty("localProperties.autosignReleaseWithDebugKey")) {
61                 println ("All builds will be automatically signed with the debug key")
62                 signingConfig signingConfigs.debug
63             }
65             if (gradle.hasProperty("localProperties.debuggable")) {
66                 println ("All builds will be debuggable")
67                 debuggable true
68             }
69         }
70         debug {
71             applicationIdSuffix ".debug"
72             matchingFallbacks = ['debug']
73         }
74         beta {
75             initWith release
76             applicationIdSuffix ".beta"
77             // This is used when the user selects text in other third-party apps. See https://github.com/mozilla-mobile/focus-android/issues/6478
78             manifestPlaceholders = [textSelectionSearchAction: "@string/text_selection_search_action_focus_beta"]
79         }
80         nightly {
81             initWith release
82             applicationIdSuffix ".nightly"
83             // This is used when the user selects text in other third-party apps. See https://github.com/mozilla-mobile/focus-android/issues/6478
84             manifestPlaceholders = [textSelectionSearchAction: "@string/text_selection_search_action_focus_nightly"]
85         }
86     }
87     testOptions {
88         execution 'ANDROIDX_TEST_ORCHESTRATOR'
89         animationsDisabled = true
90         unitTests {
91             includeAndroidResources = true
92         }
93     }
95     buildFeatures {
96         compose true
97         viewBinding true
98     }
100     composeOptions {
101         kotlinCompilerExtensionVersion = FocusVersions.google_compose_compiler
102     }
104     flavorDimensions "product"
106     productFlavors {
107         // In most countries we are Firefox Focus - but in some we need to be Firefox Klar
108         focus {
109             dimension "product"
111             applicationIdSuffix ".focus"
113             // This is used when the user selects text in other third-party apps. See https://github.com/mozilla-mobile/focus-android/issues/6478
114             manifestPlaceholders = [textSelectionSearchAction: "@string/text_selection_search_action_focus"]
115         }
116         klar {
117             dimension "product"
119             applicationIdSuffix ".klar"
121             // This is used when the user selects text in other third-party apps. See https://github.com/mozilla-mobile/focus-android/issues/6478
122             manifestPlaceholders = [textSelectionSearchAction: "@string/text_selection_search_action_klar"]
123         }
124     }
126     splits {
127         abi {
128             enable true
130             reset()
132             include "x86", "armeabi-v7a", "arm64-v8a", "x86_64"
133         }
134     }
136     sourceSets {
137         test {
138             resources {
139                 // Make the default asset folder available as test resource folder. Robolectric seems
140                 // to fail to read assets for our setup. With this we can just read the files directly
141                 // and do not need to rely on Robolectric.
142                 srcDir "${projectDir}/src/main/assets/"
143             }
144         }
146         // Release
147         focusRelease.root = 'src/focusRelease'
148         klarRelease.root = 'src/klarRelease'
150         // Debug
151         focusDebug.root = 'src/focusDebug'
152         klarDebug.root = 'src/klarDebug'
154         // Nightly
155         focusNightly.root = 'src/focusNightly'
156         klarNightly.root = 'src/klarNightly'
157     }
159     packagingOptions {
160         pickFirst 'META-INF/atomicfu.kotlin_module'
161         pickFirst 'META-INF/proguard/coroutines.pro'
162     }
165 tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
166         kotlinOptions {
167             allWarningsAsErrors = true
168             freeCompilerArgs += "-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi"
169             freeCompilerArgs += "-opt-in=kotlin.RequiresOptIn"
170             freeCompilerArgs += "-Xjvm-default=all"
171             jvmTarget = '1.8'
172         }
175 // -------------------------------------------------------------------------------------------------
176 // Generate Kotlin code for the Focus Glean metrics.
177 // -------------------------------------------------------------------------------------------------
178 apply plugin: "org.mozilla.telemetry.glean-gradle-plugin"
179 apply plugin: "org.mozilla.components.nimbus-gradle-plugin"
181 nimbus {
182     // The path to the Nimbus feature manifest file
183     manifestFile = "nimbus.fml.yaml"
184     // The fully qualified class name for the generated features.
185     // If the classname begins with a '.' this is taken as a suffix to the app's package name
186     destinationClass = ".nimbus.FocusNimbus"
187     // Map from the variant name to the channel as experimenter and nimbus understand it.
188     // If nimbus's channels were accurately set up well for this project, then this
189     // shouldn't be needed.
190     channels = [
191             focusDebug: "debug",
192             focusNightly: "nightly",
193             focusBeta: "beta",
194             focusRelease: "release",
195             klarDebug: "debug",
196             klarNightly: "nightly",
197             klarBeta: "beta",
198             klarRelease: "release"
199     ]
200     // This is generated by the FML and should be checked into git.
201     // It will be fetched by Experimenter (the Nimbus experiment website)
202     // and used to inform experiment configuration.
203     experimenterManifest = ".experimenter.yaml"
206 configurations {
207     // There's an interaction between Gradle's resolution of dependencies with different types
208     // (@jar, @aar) for `implementation` and `testImplementation` and with Android Studio's built-in
209     // JUnit test runner.  The runtime classpath in the built-in JUnit test runner gets the
210     // dependency from the `implementation`, which is type @aar, and therefore the JNA dependency
211     // doesn't provide the JNI dispatch libraries in the correct Java resource directories.  I think
212     // what's happening is that @aar type in `implementation` resolves to the @jar type in
213     // `testImplementation`, and that it wins the dependency resolution battle.
214     //
215     // A workaround is to add a new configuration which depends on the @jar type and to reference
216     // the underlying JAR file directly in `testImplementation`.  This JAR file doesn't resolve to
217     // the @aar type in `implementation`.  This works when invoked via `gradle`, but also sets the
218     // correct runtime classpath when invoked with Android Studio's built-in JUnit test runner.
219     // Success!
220     jnaForTest
223 dependencies {
224     implementation FocusDependencies.androidx_appcompat
225     implementation FocusDependencies.androidx_browser
226     implementation FocusDependencies.androidx_cardview
227     implementation FocusDependencies.androidx_compose_ui
228     implementation FocusDependencies.androidx_compose_ui_tooling
229     implementation FocusDependencies.androidx_compose_foundation
230     implementation FocusDependencies.androidx_compose_material
231     implementation FocusDependencies.androidx_compose_runtime_livedata
232     implementation FocusDependencies.androidx_constraint_layout
233     implementation FocusDependencies.androidx_constraint_layout_compose
234     implementation FocusDependencies.androidx_core_ktx
235     implementation FocusDependencies.androidx_fragment
236     implementation FocusDependencies.androidx_lifecycle_process
237     implementation FocusDependencies.androidx_lifecycle_viewmodel
238     implementation FocusDependencies.androidx_palette
239     implementation FocusDependencies.androidx_preference
240     implementation FocusDependencies.androidx_recyclerview
241     implementation FocusDependencies.androidx_savedstate
242     implementation FocusDependencies.androidx_splashscreen
243     implementation FocusDependencies.androidx_transition
244     implementation FocusDependencies.androidx_work_ktx
246     implementation FocusDependencies.google_accompanist_insets_ui
247     implementation FocusDependencies.google_play
249     implementation FocusDependencies.google_material
251     implementation FocusDependencies.sentry
253     implementation "org.mozilla.components:browser-engine-gecko:${AndroidComponents.VERSION}"
254     implementation "org.mozilla.components:browser-domains:${AndroidComponents.VERSION}"
255     implementation "org.mozilla.components:browser-errorpages:${AndroidComponents.VERSION}"
256     implementation "org.mozilla.components:browser-icons:${AndroidComponents.VERSION}"
257     implementation "org.mozilla.components:browser-menu:${AndroidComponents.VERSION}"
258     implementation "org.mozilla.components:browser-state:${AndroidComponents.VERSION}"
259     implementation "org.mozilla.components:browser-toolbar:${AndroidComponents.VERSION}"
261     implementation "org.mozilla.components:concept-awesomebar:${AndroidComponents.VERSION}"
262     implementation "org.mozilla.components:concept-engine:${AndroidComponents.VERSION}"
263     implementation "org.mozilla.components:concept-fetch:${AndroidComponents.VERSION}"
264     implementation "org.mozilla.components:concept-menu:${AndroidComponents.VERSION}"
266     implementation "org.mozilla.components:compose-awesomebar:${AndroidComponents.VERSION}"
268     implementation "org.mozilla.components:feature-awesomebar:${AndroidComponents.VERSION}"
269     implementation "org.mozilla.components:feature-app-links:${AndroidComponents.VERSION}"
270     implementation "org.mozilla.components:feature-customtabs:${AndroidComponents.VERSION}"
271     implementation "org.mozilla.components:feature-contextmenu:${AndroidComponents.VERSION}"
272     implementation "org.mozilla.components:feature-downloads:${AndroidComponents.VERSION}"
273     implementation "org.mozilla.components:feature-findinpage:${AndroidComponents.VERSION}"
274     implementation "org.mozilla.components:feature-intent:${AndroidComponents.VERSION}"
275     implementation "org.mozilla.components:feature-prompts:${AndroidComponents.VERSION}"
276     implementation "org.mozilla.components:feature-session:${AndroidComponents.VERSION}"
277     implementation "org.mozilla.components:feature-search:${AndroidComponents.VERSION}"
278     implementation "org.mozilla.components:feature-tabs:${AndroidComponents.VERSION}"
279     implementation "org.mozilla.components:feature-toolbar:${AndroidComponents.VERSION}"
280     implementation "org.mozilla.components:feature-top-sites:${AndroidComponents.VERSION}"
281     implementation "org.mozilla.components:feature-sitepermissions:${AndroidComponents.VERSION}"
282     implementation "org.mozilla.components:lib-crash:${AndroidComponents.VERSION}"
283     implementation "org.mozilla.components:lib-crash-sentry:${AndroidComponents.VERSION}"
284     implementation "org.mozilla.components:lib-state:${AndroidComponents.VERSION}"
285     implementation "org.mozilla.components:feature-media:${AndroidComponents.VERSION}"
286     implementation "org.mozilla.components:lib-auth:${AndroidComponents.VERSION}"
287     implementation "org.mozilla.components:lib-publicsuffixlist:${AndroidComponents.VERSION}"
289     implementation "org.mozilla.components:service-glean:${AndroidComponents.VERSION}", {
290         exclude group: 'org.mozilla.telemetry', module: 'glean-native'
291     }
292     implementation "org.mozilla.components:service-location:${AndroidComponents.VERSION}"
293     implementation "org.mozilla.components:service-nimbus:${AndroidComponents.VERSION}"
295     implementation "org.mozilla.components:support-ktx:${AndroidComponents.VERSION}"
296     implementation "org.mozilla.components:support-utils:${AndroidComponents.VERSION}"
297     implementation "org.mozilla.components:support-rusthttp:${AndroidComponents.VERSION}"
298     implementation "org.mozilla.components:support-rustlog:${AndroidComponents.VERSION}"
300     implementation "org.mozilla.components:ui-autocomplete:${AndroidComponents.VERSION}"
301     implementation "org.mozilla.components:ui-colors:${AndroidComponents.VERSION}"
302     implementation "org.mozilla.components:ui-icons:${AndroidComponents.VERSION}"
303     implementation "org.mozilla.components:ui-tabcounter:${AndroidComponents.VERSION}"
304     implementation "org.mozilla.components:feature-webcompat:${AndroidComponents.VERSION}"
305     implementation "org.mozilla.components:feature-webcompat-reporter:${AndroidComponents.VERSION}"
306     implementation "org.mozilla.components:support-webextensions:${AndroidComponents.VERSION}"
307     implementation "org.mozilla.components:support-locale:${AndroidComponents.VERSION}"
308     implementation "org.mozilla.components:compose-cfr:${AndroidComponents.VERSION}"
310     implementation project(':service-telemetry')
312     implementation FocusDependencies.kotlin_coroutines
313     debugImplementation FocusDependencies.leakcanary
315     focusImplementation FocusDependencies.adjust
316     focusImplementation FocusDependencies.install_referrer // Required by Adjust
318     jnaForTest FocusDependencies.jna
319     testImplementation files(configurations.jnaForTest.copyRecursive().files)
320     testImplementation "org.mozilla.telemetry:glean-native-forUnitTests:${project.ext.glean_version}"
322     testImplementation FocusDependencies.testing_junit_api
323     testRuntimeOnly FocusDependencies.testing_junit_engine
324     testImplementation FocusDependencies.testing_junit_params
325     testImplementation FocusDependencies.testing_robolectric
326     testImplementation FocusDependencies.testing_mockito
327     testImplementation FocusDependencies.testing_coroutines
328     testImplementation FocusDependencies.androidx_work_testing
329     testImplementation FocusDependencies.androidx_arch_core_testing
330     testImplementation "org.mozilla.components:support-test:${AndroidComponents.VERSION}"
331     testImplementation "org.mozilla.components:support-test-libstate:${AndroidComponents.VERSION}"
332     androidTestImplementation FocusDependencies.espresso_core, {
333         exclude group: 'com.android.support', module: 'support-annotations'
334     }
335     androidTestImplementation FocusDependencies.espresso_idling_resource
336     androidTestImplementation FocusDependencies.espresso_web, {
337         exclude group: 'com.android.support', module: 'support-annotations'
338     }
339     androidTestImplementation FocusDependencies.espresso_intents
341     androidTestImplementation FocusDependencies.testing_mockwebserver
342     testImplementation FocusDependencies.testing_mockwebserver
343     testImplementation "org.mozilla.components:lib-fetch-okhttp:${AndroidComponents.VERSION}"
345     androidTestImplementation FocusDependencies.fastlane
346     implementation FocusDependencies.falcon // Required by fastlane
348     androidTestImplementation FocusDependencies.espresso_contrib, {
349         exclude module: 'appcompat-v7'
350         exclude module: 'support-v4'
351         exclude module: 'support-annotations'
352         exclude module: 'recyclerview-v7'
353         exclude module: 'design'
354         exclude module: 'espresso-core'
355     }
356     testImplementation FocusDependencies.androidx_test_core
357     testImplementation FocusDependencies.androidx_test_runner
358     testImplementation FocusDependencies.androidx_test_rules
360     androidTestImplementation FocusDependencies.androidx_test_core_ktx
361     androidTestImplementation FocusDependencies.androidx_junit_ktx
362     androidTestImplementation FocusDependencies.androidx_uiautomator
363     androidTestImplementation FocusDependencies.androidx_test_runner
364     androidTestUtil FocusDependencies.androidx_orchestrator
367 // -------------------------------------------------------------------------------------------------
368 //  Dynamically set versionCode (See tools/build/versionCode.gradle
369 // -------------------------------------------------------------------------------------------------
371 android.applicationVariants.all { variant ->
372     def buildType = variant.buildType.name
374     println("----------------------------------------------")
375     println("Variant name:      " + variant.name)
376     println("Application ID:    " + [variant.applicationId, variant.buildType.applicationIdSuffix].findAll().join())
377     println("Build type:        " + variant.buildType.name)
378     println("Flavor:            " + variant.flavorName)
380     if (buildType == "release" || buildType == "nightly" || buildType == "beta") {
381         def baseVersionCode = generatedVersionCode
382         def versionName = buildType == "nightly" ? Config.nightlyVersionName() : Config.releaseVersionName(project)
383         println("versionName override: $versionName")
385         // The Google Play Store does not allow multiple APKs for the same app that all have the
386         // same version code. Therefore we need to have different version codes for our ARM and x86
387         // builds.
389         // Our generated version code now has a length of 9 (See tools/gradle/versionCode.gradle).
390         // Our x86 builds need a higher version code to avoid installing ARM builds on an x86 device
391         // with ARM compatibility mode.
393         variant.outputs.each { output ->
394             def abi = output.getFilter(OutputFile.ABI)
395             // We use the same version code generator, that we inherited from Fennec, across all channels - even on
396             // channels that never shipped a Fennec build.
398             def versionCodeOverride = baseVersionCode
400             if (abi == "x86_64") {
401                 versionCodeOverride = versionCodeOverride + 3
402             } else if (abi == "x86") {
403                 versionCodeOverride = versionCodeOverride + 2
404             } else if (abi == "arm64-v8a") {
405                 versionCodeOverride = versionCodeOverride + 1
406             } else if (abi == "armeabi-v7a") {
407                 versionCodeOverride = versionCodeOverride + 0
408             } else {
409                 throw new RuntimeException("Unknown ABI: " + abi)
410             }
412             if (versionName != null) {
413                 output.versionNameOverride = versionName
414             }
415             output.versionCodeOverride = versionCodeOverride
417             println("versionCode for $abi = $versionCodeOverride")
418         }
420     }
423 // -------------------------------------------------------------------------------------------------
424 // MLS: Read token from local file if it exists (Only release builds)
425 // -------------------------------------------------------------------------------------------------
427 android.applicationVariants.all {
428     print("MLS token: ")
429     try {
430         def token = new File("${rootDir}/.mls_token").text.trim()
431         buildConfigField 'String', 'MLS_TOKEN', '"' + token + '"'
432         println "(Added from .mls_token file)"
433     } catch (FileNotFoundException ignored) {
434         buildConfigField 'String', 'MLS_TOKEN', '""'
435         println("X_X")
436     }
439 // -------------------------------------------------------------------------------------------------
440 // Adjust: Read token from local file if it exists (Only release builds)
441 // -------------------------------------------------------------------------------------------------
443 android.applicationVariants.all { variant ->
444     def variantName = variant.getName()
446     print("Adjust token: ")
448     if (variantName.contains("Release") && variantName.contains("focus")) {
449         try {
450             def token = new File("${rootDir}/.adjust_token").text.trim()
451             buildConfigField 'String', 'ADJUST_TOKEN', '"' + token + '"'
452             println "(Added from .adjust_token file)"
453         } catch (FileNotFoundException ignored) {
454             if (gradle.hasProperty("localProperties.autosignReleaseWithDebugKey")) {
455                 buildConfigField 'String', 'ADJUST_TOKEN', '"fake"'
456                 println("fake - only for local development")
457             } else {
458                 buildConfigField 'String', 'ADJUST_TOKEN', 'null'
459                 println("X_X")
460             }
461         }
462     } else {
463         buildConfigField 'String', 'ADJUST_TOKEN', 'null'
464         println("--")
465     }
468 // -------------------------------------------------------------------------------------------------
469 // Sentry: Read token from local file if it exists (Only release builds)
470 // -------------------------------------------------------------------------------------------------
472 android.applicationVariants.all {
473     print("Sentry token: ")
474     try {
475         def token = new File("${rootDir}/.sentry_token").text.trim()
476         buildConfigField 'String', 'SENTRY_TOKEN', '"' + token + '"'
477         println "(Added from .sentry_token file)"
478     } catch (FileNotFoundException ignored) {
479         buildConfigField 'String', 'SENTRY_TOKEN', '""'
480         println("X_X")
481     }
484 // -------------------------------------------------------------------------------------------------
485 // L10N: Generate list of locales
486 // Focus provides its own (Android independent) locale switcher. That switcher requires a list
487 // of locale codes. We generate that list here to avoid having to manually maintain a list of locales:
488 // -------------------------------------------------------------------------------------------------
490 def getEnabledLocales() {
491     def resDir = file('src/main/res')
493     def potentialLanguageDirs = resDir.listFiles(new FilenameFilter() {
494         @Override
495         boolean accept(File dir, String name) {
496             return name.startsWith("values-")
497         }
498     })
500     def langs = potentialLanguageDirs.findAll {
501         // Only select locales where strings.xml exists
502         // Some locales might only contain e.g. sumo URLS in urls.xml, and should be skipped (see es vs es-ES/es-MX/etc)
503         return  file(new File(it, "strings.xml")).exists()
504     } .collect {
505         // And reduce down to actual values-* names
506         return it.name
507     } .collect {
508         return it.substring("values-".length())
509     } .collect {
510         if (it.length() > 3 && it.contains("-r")) {
511             // Android resource dirs add an "r" prefix to the region - we need to strip that for java usage
512             // Add 1 to have the index of the r, without the dash
513             def regionPrefixPosition = it.indexOf("-r") + 1
515             return it.substring(0, regionPrefixPosition) + it.substring(regionPrefixPosition + 1)
516         } else {
517             return it
518         }
519     }.collect {
520         return '"' + it + '"'
521     }
523     // en-US is the default language (in "values") and therefore needs to be added separately
524     langs << "\"en-US\""
526     return langs.sort { it }
529 // -------------------------------------------------------------------------------------------------
530 // Nimbus: Read endpoint from local.properties of a local file if it exists
531 // -------------------------------------------------------------------------------------------------
533 print("Nimbus endpoint: ")
534 android.applicationVariants.all { variant ->
535     def variantName = variant.getName()
537     if (!variantName.contains("Debug")) {
538         try {
539             def url = new File("${rootDir}/.nimbus").text.trim()
540             buildConfigField 'String', 'NIMBUS_ENDPOINT', '"' + url + '"'
541             println "(Added from .nimbus file)"
542         } catch (FileNotFoundException ignored) {
543             buildConfigField 'String', 'NIMBUS_ENDPOINT', 'null'
544             println("X_X")
545         }
546     } else if (gradle.hasProperty("localProperties.nimbus.remote-settings.url")) {
547         def url = gradle.getProperty("localProperties.nimbus.remote-settings.url")
548         buildConfigField 'String', 'NIMBUS_ENDPOINT', '"' + url + '"'
549         println "(Added from local.properties file)"
550     } else {
551         buildConfigField 'String', 'NIMBUS_ENDPOINT', 'null'
552         println("--")
553     }
556 def generatedLocaleListDir = 'src/main/java/org/mozilla/focus/generated'
557 def generatedLocaleListFilename = 'LocaleList.java'
559 task generateLocaleList {
560     doLast {
561         def dir = file(generatedLocaleListDir)
562         dir.mkdir()
563         def localeList = file(new File(dir, generatedLocaleListFilename))
565         localeList.delete()
566         localeList.createNewFile()
567         localeList << "package org.mozilla.focus.generated;" << "\n" << "\n"
568         localeList << "import java.util.Arrays;" << "\n"
569         localeList << "import java.util.Collections;" << "\n"
570         localeList << "import java.util.List;" << "\n"
571         localeList << "\n"
572         localeList << "public class LocaleList {" << "\n"
573         // findbugs doesn't like "public static final String[]", see http://findbugs.sourceforge.net/bugDescriptions.html#MS_MUTABLE_ARRAY
574         localeList << "    public static final List<String> BUNDLED_LOCALES = Collections.unmodifiableList(Arrays.asList(new String[] { "
575         localeList << getEnabledLocales().join(", ") + " }));" << "\n"
576         localeList << "}" << "\n"
577     }
580 tasks.whenTaskAdded { task ->
581     if (name.contains("compile")) {
582         task.dependsOn generateLocaleList
583     }
586 clean.doLast {
587     file(generatedLocaleListDir).deleteDir()
590 if (project.hasProperty("coverage")) {
591     tasks.withType(Test) {
592         jacoco.includeNoLocationClasses = true
593     }
595     android.applicationVariants.all { variant ->
596         task "jacoco${variant.name.capitalize()}TestReport"(type: JacocoReport,
597                 dependsOn: ["test${variant.name.capitalize()}UnitTest"]) {
599             reports {
600                 html.enabled true
601                 xml.enabled true
602             }
604             def fileFilter = ['**/R.class', '**/R$*.class', '**/BuildConfig.*', '**/Manifest*.*',
605                               '**/*Test*.*', 'android/**/*.*', '**/*$[0-9].*']
606             def kotlinTree = fileTree(dir: "$project.buildDir/tmp/kotlin-classes/${variant.name}", excludes: fileFilter)
607             def javaTree = fileTree(dir: "$project.buildDir/intermediates/classes/${variant.flavorName}/${variant.buildType.name}",
608                     excludes: fileFilter)
609             def mainSrc = "$project.projectDir/src/main/java"
610             sourceDirectories = files([mainSrc])
611             classDirectories = files([kotlinTree, javaTree])
612             executionData = fileTree(dir: project.buildDir, includes: [
613                     "jacoco/test${variant.name.capitalize()}UnitTest.exec", 'outputs/code-coverage/connected/*coverage.ec'
614             ])
615         }
616     }
618     android {
619         buildTypes {
620             debug {
621                 testCoverageEnabled true
622                 applicationIdSuffix ".coverage"
623             }
624         }
625     }
628 if (gradle.hasProperty('localProperties.autoPublish.android-components.dir')) {
629     ext.acSrcDir = gradle."localProperties.autoPublish.android-components.dir"
630     apply from: "../${acSrcDir}/substitute-local-ac.gradle"
633 if (gradle.hasProperty('localProperties.autoPublish.application-services.dir')) {
634     ext.appServicesSrcDir = gradle."localProperties.autoPublish.application-services.dir"
635     apply from: "../${appServicesSrcDir}/build-scripts/substitute-local-appservices.gradle"
638 if (gradle.hasProperty('localProperties.autoPublish.glean.dir')) {
639     ext.gleanSrcDir = gradle."localProperties.autoPublish.glean.dir"
640     apply from: "../${gleanSrcDir}/build-scripts/substitute-local-glean.gradle"
643 // -------------------------------------------------------------------------------------------------
644 // Task for printing APK information for the requested variant
645 // Taskgraph Usage: "./gradlew printVariants
646 // -------------------------------------------------------------------------------------------------
647 tasks.register('printVariants') {
648     doLast {
649         def variants = android.applicationVariants.collect { variant -> [
650             apks: variant.outputs.collect { output -> [
651                 abi: output.getFilter(com.android.build.VariantOutput.FilterType.ABI),
652                 fileName: output.outputFile.name
653             ]},
654             build_type: variant.buildType.name,
655             name: variant.name,
656         ]}
657         // AndroidTest is a special case not included above
658         variants.add([
659             apks: [[
660                 abi: 'noarch',
661                 fileName: 'app-debug-androidTest.apk',
662             ]],
663             build_type: 'androidTest',
664             name: 'androidTest',
665         ])
666         println 'variants: ' + JsonOutput.toJson(variants)
667     }
670 // Enable expiration by major version.
671 ext.gleanExpireByVersion = 1