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'
9 apply from: "$project.rootDir/tools/gradle/versionCode.gradle"
11 import com.android.build.OutputFile
12 import groovy.json.JsonOutput
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")
24 applicationId "org.mozilla"
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
40 sourceCompatibility JavaVersion.VERSION_1_8
41 targetCompatibility JavaVersion.VERSION_1_8
45 lintConfig file("lint.xml")
48 // We have a three dimensional build configuration:
49 // BUILD TYPE (debug, release) X PRODUCT FLAVOR (focus, klar)
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
65 if (gradle.hasProperty("localProperties.debuggable")) {
66 println ("All builds will be debuggable")
71 applicationIdSuffix ".debug"
72 matchingFallbacks = ['debug']
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"]
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"]
88 execution 'ANDROIDX_TEST_ORCHESTRATOR'
89 animationsDisabled = true
91 includeAndroidResources = true
101 kotlinCompilerExtensionVersion = FocusVersions.google_compose_compiler
104 flavorDimensions "product"
107 // In most countries we are Firefox Focus - but in some we need to be Firefox Klar
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"]
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"]
132 include "x86", "armeabi-v7a", "arm64-v8a", "x86_64"
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/"
147 focusRelease.root = 'src/focusRelease'
148 klarRelease.root = 'src/klarRelease'
151 focusDebug.root = 'src/focusDebug'
152 klarDebug.root = 'src/klarDebug'
155 focusNightly.root = 'src/focusNightly'
156 klarNightly.root = 'src/klarNightly'
160 pickFirst 'META-INF/atomicfu.kotlin_module'
161 pickFirst 'META-INF/proguard/coroutines.pro'
165 tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
167 allWarningsAsErrors = true
168 freeCompilerArgs += "-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi"
169 freeCompilerArgs += "-opt-in=kotlin.RequiresOptIn"
170 freeCompilerArgs += "-Xjvm-default=all"
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"
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.
192 focusNightly: "nightly",
194 focusRelease: "release",
196 klarNightly: "nightly",
198 klarRelease: "release"
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"
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.
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.
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'
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'
335 androidTestImplementation FocusDependencies.espresso_idling_resource
336 androidTestImplementation FocusDependencies.espresso_web, {
337 exclude group: 'com.android.support', module: 'support-annotations'
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'
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
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
409 throw new RuntimeException("Unknown ABI: " + abi)
412 if (versionName != null) {
413 output.versionNameOverride = versionName
415 output.versionCodeOverride = versionCodeOverride
417 println("versionCode for $abi = $versionCodeOverride")
423 // -------------------------------------------------------------------------------------------------
424 // MLS: Read token from local file if it exists (Only release builds)
425 // -------------------------------------------------------------------------------------------------
427 android.applicationVariants.all {
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', '""'
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")) {
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")
458 buildConfigField 'String', 'ADJUST_TOKEN', 'null'
463 buildConfigField 'String', 'ADJUST_TOKEN', 'null'
468 // -------------------------------------------------------------------------------------------------
469 // Sentry: Read token from local file if it exists (Only release builds)
470 // -------------------------------------------------------------------------------------------------
472 android.applicationVariants.all {
473 print("Sentry token: ")
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', '""'
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() {
495 boolean accept(File dir, String name) {
496 return name.startsWith("values-")
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()
505 // And reduce down to actual values-* names
508 return it.substring("values-".length())
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)
520 return '"' + it + '"'
523 // en-US is the default language (in "values") and therefore needs to be added separately
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")) {
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'
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)"
551 buildConfigField 'String', 'NIMBUS_ENDPOINT', 'null'
556 def generatedLocaleListDir = 'src/main/java/org/mozilla/focus/generated'
557 def generatedLocaleListFilename = 'LocaleList.java'
559 task generateLocaleList {
561 def dir = file(generatedLocaleListDir)
563 def localeList = file(new File(dir, generatedLocaleListFilename))
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"
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"
580 tasks.whenTaskAdded { task ->
581 if (name.contains("compile")) {
582 task.dependsOn generateLocaleList
587 file(generatedLocaleListDir).deleteDir()
590 if (project.hasProperty("coverage")) {
591 tasks.withType(Test) {
592 jacoco.includeNoLocationClasses = true
595 android.applicationVariants.all { variant ->
596 task "jacoco${variant.name.capitalize()}TestReport"(type: JacocoReport,
597 dependsOn: ["test${variant.name.capitalize()}UnitTest"]) {
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'
621 testCoverageEnabled true
622 applicationIdSuffix ".coverage"
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') {
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
654 build_type: variant.buildType.name,
657 // AndroidTest is a special case not included above
661 fileName: 'app-debug-androidTest.apk',
663 build_type: 'androidTest',
666 println 'variants: ' + JsonOutput.toJson(variants)
670 // Enable expiration by major version.
671 ext.gleanExpireByVersion = 1