/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.build.gradle.internal

import com.android.SdkConstants
import com.android.annotations.NonNull
import com.android.annotations.Nullable
import com.android.build.OutputFile
import com.android.build.gradle.BaseExtension
import com.android.build.gradle.LibraryExtension
import com.android.build.gradle.api.AndroidSourceSet
import com.android.build.gradle.internal.core.GradleVariantConfiguration
import com.android.build.gradle.internal.coverage.JacocoInstrumentTask
import com.android.build.gradle.internal.coverage.JacocoPlugin
import com.android.build.gradle.internal.coverage.JacocoReportTask
import com.android.build.gradle.internal.dependency.LibraryDependencyImpl
import com.android.build.gradle.internal.dependency.ManifestDependencyImpl
import com.android.build.gradle.internal.dependency.SymbolFileProviderImpl
import com.android.build.gradle.internal.dependency.VariantDependencies
import com.android.build.gradle.internal.dsl.AbiSplitOptions
import com.android.build.gradle.internal.dsl.SigningConfig
import com.android.build.gradle.internal.publishing.ApkPublishArtifact
import com.android.build.gradle.internal.publishing.MappingPublishArtifact
import com.android.build.gradle.internal.publishing.MetadataPublishArtifact
import com.android.build.gradle.internal.scope.AndroidTask
import com.android.build.gradle.internal.scope.AndroidTaskRegistry
import com.android.build.gradle.internal.scope.GlobalScope
import com.android.build.gradle.internal.scope.VariantOutputScope
import com.android.build.gradle.internal.scope.VariantScope
import com.android.build.gradle.internal.tasks.AndroidReportTask
import com.android.build.gradle.internal.tasks.CheckManifest
import com.android.build.gradle.internal.tasks.DependencyReportTask
import com.android.build.gradle.internal.tasks.DeviceProviderInstrumentTestLibraryTask
import com.android.build.gradle.internal.tasks.DeviceProviderInstrumentTestTask
import com.android.build.gradle.internal.tasks.FileSupplier
import com.android.build.gradle.internal.tasks.GenerateApkDataTask
import com.android.build.gradle.internal.tasks.InstallVariantTask
import com.android.build.gradle.internal.tasks.MockableAndroidJarTask
import com.android.build.gradle.internal.tasks.PrepareDependenciesTask
import com.android.build.gradle.internal.tasks.SigningReportTask
import com.android.build.gradle.internal.tasks.SourceSetsTask
import com.android.build.gradle.internal.tasks.TestServerTask
import com.android.build.gradle.internal.tasks.UninstallTask
import com.android.build.gradle.internal.tasks.multidex.CreateMainDexList
import com.android.build.gradle.internal.tasks.multidex.CreateManifestKeepList
import com.android.build.gradle.internal.tasks.multidex.JarMergingTask
import com.android.build.gradle.internal.tasks.multidex.RetraceMainDexList
import com.android.build.gradle.internal.test.TestDataImpl
import com.android.build.gradle.internal.test.report.ReportType
import com.android.build.gradle.internal.variant.ApkVariantData
import com.android.build.gradle.internal.variant.ApkVariantOutputData
import com.android.build.gradle.internal.variant.ApplicationVariantData
import com.android.build.gradle.internal.variant.BaseVariantData
import com.android.build.gradle.internal.variant.BaseVariantOutputData
import com.android.build.gradle.internal.variant.LibraryVariantData
import com.android.build.gradle.internal.variant.TestVariantData
import com.android.build.gradle.tasks.AidlCompile
import com.android.build.gradle.tasks.AndroidJarTask
import com.android.build.gradle.tasks.AndroidProGuardTask
import com.android.build.gradle.tasks.CompatibleScreensManifest
import com.android.build.gradle.tasks.Dex
import com.android.build.gradle.tasks.GenerateBuildConfig
import com.android.build.gradle.tasks.PreprocessResourcesTask
import com.android.build.gradle.tasks.GenerateResValues
import com.android.build.gradle.tasks.GenerateSplitAbiRes
import com.android.build.gradle.tasks.JackTask
import com.android.build.gradle.tasks.JillTask
import com.android.build.gradle.tasks.Lint
import com.android.build.gradle.tasks.MergeAssets
import com.android.build.gradle.tasks.MergeManifests
import com.android.build.gradle.tasks.MergeResources
import com.android.build.gradle.tasks.NdkCompile
import com.android.build.gradle.tasks.PackageApplication
import com.android.build.gradle.tasks.PackageSplitAbi
import com.android.build.gradle.tasks.PackageSplitRes
import com.android.build.gradle.tasks.PreCompilationVerificationTask
import com.android.build.gradle.tasks.PreDex
import com.android.build.gradle.tasks.ProcessAndroidResources
import com.android.build.gradle.tasks.ProcessManifest
import com.android.build.gradle.tasks.ProcessTestManifest
import com.android.build.gradle.tasks.RenderscriptCompile
import com.android.build.gradle.tasks.SplitZipAlign
import com.android.build.gradle.tasks.ZipAlign
import com.android.builder.core.AndroidBuilder
import com.android.builder.core.VariantConfiguration
import com.android.builder.core.VariantType
import com.android.builder.dependency.LibraryDependency
import com.android.builder.internal.testing.SimpleTestCallable
import com.android.builder.model.ApiVersion
import com.android.builder.model.ProductFlavor
import com.android.builder.model.SourceProvider
import com.android.builder.testing.ConnectedDeviceProvider
import com.android.builder.testing.TestData
import com.android.builder.testing.api.DeviceProvider
import com.android.builder.testing.api.TestServer
import com.android.resources.Density
import com.android.sdklib.AndroidTargetHash
import com.android.sdklib.BuildToolInfo
import com.android.sdklib.IAndroidTarget
import com.android.sdklib.SdkVersionInfo
import com.android.sdklib.repository.FullRevision
import com.google.common.base.CharMatcher
import com.google.common.collect.ImmutableList
import com.google.common.collect.ImmutableSet
import com.google.common.collect.Iterators
import com.google.common.collect.Lists
import com.google.common.collect.Sets
import groovy.transform.CompileDynamic
import groovy.transform.CompileStatic
import org.gradle.api.GradleException
import org.gradle.api.JavaVersion
import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.api.artifacts.Configuration
import org.gradle.api.execution.TaskExecutionGraph
import org.gradle.api.file.FileCollection
import org.gradle.api.internal.ConventionMapping
import org.gradle.api.logging.LogLevel
import org.gradle.api.logging.Logger
import org.gradle.api.logging.Logging
import org.gradle.api.plugins.BasePlugin
import org.gradle.api.plugins.JavaBasePlugin
import org.gradle.api.plugins.JavaPlugin
import org.gradle.api.reporting.ConfigurableReport
import org.gradle.api.tasks.Copy
import org.gradle.api.tasks.bundling.Jar
import org.gradle.api.tasks.compile.AbstractCompile
import org.gradle.api.tasks.compile.JavaCompile
import org.gradle.api.tasks.testing.Test
import org.gradle.api.tasks.testing.TestTaskReports
import org.gradle.language.jvm.tasks.ProcessResources
import org.gradle.tooling.BuildException
import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry
import proguard.gradle.ProGuardTask

import static com.android.SdkConstants.FN_ANDROID_MANIFEST_XML
import static com.android.builder.core.BuilderConstants.CONNECTED
import static com.android.builder.core.BuilderConstants.DEVICE
import static com.android.builder.core.BuilderConstants.FD_ANDROID_RESULTS
import static com.android.builder.core.BuilderConstants.FD_ANDROID_TESTS
import static com.android.builder.core.BuilderConstants.FD_FLAVORS
import static com.android.builder.core.BuilderConstants.FD_FLAVORS_ALL
import static com.android.builder.core.BuilderConstants.FD_REPORTS
import static com.android.builder.core.VariantType.ANDROID_TEST
import static com.android.builder.core.VariantType.DEFAULT
import static com.android.builder.core.VariantType.LIBRARY
import static com.android.builder.core.VariantType.UNIT_TEST
import static com.android.builder.model.AndroidProject.FD_GENERATED
import static com.android.builder.model.AndroidProject.FD_INTERMEDIATES
import static com.android.builder.model.AndroidProject.FD_OUTPUTS
import static com.android.builder.model.AndroidProject.PROPERTY_APK_LOCATION
import static com.android.sdklib.BuildToolInfo.PathId.ZIP_ALIGN
import static com.google.common.base.Preconditions.checkNotNull

/**
 * Manages tasks creation.
 */
@CompileStatic
abstract class TaskManager {

    public static final String FILE_JACOCO_AGENT = 'jacocoagent.jar'

    public static final String DEFAULT_PROGUARD_CONFIG_FILE = 'proguard-android.txt'

    public final static String DIR_BUNDLES = "bundles";

    private static final String INSTALL_GROUP = "Install"

    private static final String BUILD_GROUP = BasePlugin.BUILD_GROUP

    private static final String ANDROID_GROUP = "Android"

    protected Project project

    protected AndroidBuilder androidBuilder

    private DependencyManager dependencyManager

    protected SdkHandler sdkHandler

    protected BaseExtension extension

    private ToolingModelBuilderRegistry toolingRegistry

    private final GlobalScope globalScope

    private AndroidTaskRegistry androidTasks = new AndroidTaskRegistry();

    private Logger logger

    protected boolean isNdkTaskNeeded = true

    // Task names
    private static final String MAIN_PREBUILD = "preBuild"

    private static final String UNINSTALL_ALL = "uninstallAll"

    private static final String DEVICE_CHECK = "deviceCheck"

    protected static final String CONNECTED_CHECK = "connectedCheck"

    private static final String ASSEMBLE_ANDROID_TEST = "assembleAndroidTest"

    private static final String SOURCE_SETS = "sourceSets"

    // Tasks
    private Copy jacocoAgentTask

    public Task lintCompile

    protected Task lintAll

    public MockableAndroidJarTask createMockableJar

    public TaskManager(
            Project project,
            AndroidBuilder androidBuilder,
            BaseExtension extension,
            SdkHandler sdkHandler,
            DependencyManager dependencyManager,
            ToolingModelBuilderRegistry toolingRegistry) {
        this.project = project
        this.androidBuilder = androidBuilder
        this.sdkHandler = sdkHandler
        this.extension = extension
        this.toolingRegistry = toolingRegistry
        this.dependencyManager = dependencyManager
        logger = Logging.getLogger(this.class)

        globalScope = new GlobalScope(
                project,
                androidBuilder,
                getArchivesBaseName(project),
                extension);
    }

    private boolean isVerbose() {
        return project.logger.isEnabled(LogLevel.INFO)
    }

    private boolean isDebugLog() {
        return project.logger.isEnabled(LogLevel.DEBUG)
    }

    /**
     * Creates the tasks for a given BaseVariantData.
     * @param variantData the non-null BaseVariantData.
     * @param assembleTask an optional assembleTask to be used. If null, a new one is created.
     */
    abstract public void createTasksForVariantData(
            @NonNull TaskFactory tasks,
            @NonNull BaseVariantData<? extends BaseVariantOutputData> variantData)

    /**
     * Returns a collection of buildables that creates native object.
     *
     * A buildable is considered to be any object that can be used as the argument to
     * Task.dependsOn.  This could be a Task or a BuildableModelElement (e.g. BinarySpec).
     */
    protected Collection<Object> getNdkBuildable(BaseVariantData variantData) {
        return Collections.singleton(variantData.ndkCompileTask)
    }

    /**
     * Returns the directories of the NDK buildables.
     */
    protected Collection<File> getNdkOutputDirectories(BaseVariantData variantData) {
        return Collections.singleton(variantData.ndkCompileTask.soFolder)
    }

    private BaseExtension getExtension() {
        return extension
    }

    public void resolveDependencies(
            @NonNull VariantDependencies variantDeps,
            @Nullable VariantDependencies testedVariantDeps) {
        dependencyManager.resolveDependencies(variantDeps, testedVariantDeps)
    }

    /**
     * Create tasks before the evaluation (on plugin apply). This is useful for tasks that
     * could be referenced by custom build logic.
     */
    public void createTasksBeforeEvaluate(TaskFactory tasks) {
        tasks.create(UNINSTALL_ALL) {
            it.description = "Uninstall all applications."
            it.group = INSTALL_GROUP
        }

        tasks.create(DEVICE_CHECK) {
            it.description = "Runs all device checks using Device Providers and Test Servers."
            it.group = JavaBasePlugin.VERIFICATION_GROUP
        }

        tasks.create(CONNECTED_CHECK) {
            it.description = "Runs all device checks on currently connected devices."
            it.group = JavaBasePlugin.VERIFICATION_GROUP
        }

        tasks.create(MAIN_PREBUILD)

        tasks.create(SOURCE_SETS, SourceSetsTask) {
            it.description = "Prints out all the source sets defined in this project."
            it.group = ANDROID_GROUP
        }

        tasks.create(ASSEMBLE_ANDROID_TEST) {
            it.setGroup(BasePlugin.BUILD_GROUP);
            it.setDescription("Assembles all the Test applications.");
        }
    }

    public void createMockableJarTask() {
        createMockableJar = project.tasks.create("mockableAndroidJar", MockableAndroidJarTask)
        createMockableJar.group = BUILD_GROUP
        createMockableJar.description = "Creates a version of android.jar that's suitable for unit tests."

        conventionMapping(createMockableJar).map("androidJar") {
            new File(androidBuilder.target.getPath(IAndroidTarget.ANDROID_JAR))
        }

        CharMatcher safeCharacters = CharMatcher.JAVA_LETTER_OR_DIGIT.or(CharMatcher.anyOf('-.'))
        String sdkName = safeCharacters.negate().replaceFrom(extension.compileSdkVersion, '-')

        conventionMapping(createMockableJar).map("outputFile") {
            project.file(
                    "$project.buildDir/${FD_INTERMEDIATES}/mockable-${sdkName}.jar")
        }

        conventionMapping(createMockableJar).map("returnDefaultValues") {
            extension.testOptions.unitTests.returnDefaultValues
        }
    }

    public void createMergeAppManifestsTask(
            @NonNull BaseVariantData<? extends BaseVariantOutputData> variantData) {

        VariantConfiguration config = variantData.variantConfiguration
        ProductFlavor mergedFlavor = config.mergedFlavor

        ApplicationVariantData appVariantData = variantData as ApplicationVariantData
        Set<String> screenSizes = appVariantData.getCompatibleScreens()

        // loop on all outputs. The only difference will be the name of the task, and location
        // of the generated manifest
        for (BaseVariantOutputData vod : variantData.outputs) {
            final CompatibleScreensManifest csmTask =
                    (vod.getMainOutputFile().getFilter(OutputFile.DENSITY) != null
                            && !screenSizes.isEmpty()) ?
                            createCompatibleScreensManifest(vod, screenSizes) :
                            null

            // create final var inside the loop to ensure the closures will work.
            final BaseVariantOutputData variantOutputData = vod

            String outputName = variantOutputData.fullName.capitalize()
            String outputDirName = variantOutputData.dirName

            def processManifestTask = project.tasks.create(
                    "process${outputName}Manifest",
                    MergeManifests)

            variantOutputData.manifestProcessorTask = processManifestTask

            processManifestTask.androidBuilder = androidBuilder

            processManifestTask.dependsOn variantData.prepareDependenciesTask
            if (variantData.generateApkDataTask != null) {
                processManifestTask.dependsOn variantData.generateApkDataTask
            }
            if (csmTask != null) {
                processManifestTask.dependsOn csmTask
            }

            processManifestTask.variantConfiguration = config
            if (variantOutputData instanceof ApkVariantOutputData) {
                processManifestTask.variantOutputData = variantOutputData as ApkVariantOutputData
            }

            conventionMapping(processManifestTask).map("libraries") {
                List<ManifestDependencyImpl> manifests =
                        getManifestDependencies(config.directLibraries)

                if (variantData.generateApkDataTask != null &&
                    variantData.getVariantConfiguration().getBuildType().isEmbedMicroApp()) {
                    manifests.add(new ManifestDependencyImpl(
                            variantData.generateApkDataTask.getManifestFile(), []))
                }

                if (csmTask != null) {
                    manifests.add(
                            new ManifestDependencyImpl(csmTask.getManifestFile(), []))
                }

                return manifests
            }

            conventionMapping(processManifestTask).map("minSdkVersion") {
                if (androidBuilder.isPreviewTarget()) {
                    return androidBuilder.getTargetCodename()
                }

                mergedFlavor.minSdkVersion?.apiString
            }

            conventionMapping(processManifestTask).map("targetSdkVersion") {
                if (androidBuilder.isPreviewTarget()) {
                    return androidBuilder.getTargetCodename()
                }

                return mergedFlavor.targetSdkVersion?.apiString
            }

            conventionMapping(processManifestTask).map("maxSdkVersion") {
                if (androidBuilder.isPreviewTarget()) {
                    return null
                }

                return mergedFlavor.maxSdkVersion
            }

            conventionMapping(processManifestTask).map("manifestOutputFile") {
                project.file(
                        "$project.buildDir/${FD_INTERMEDIATES}/manifests/full/" +
                                "${outputDirName}/AndroidManifest.xml")
            }

            conventionMapping(processManifestTask).map("reportFile") {
                project.file(
                        "$project.buildDir/${FD_OUTPUTS}/logs/manifest-merger-${config.baseName}-report.txt")
            }
        }
    }

    private CompatibleScreensManifest createCompatibleScreensManifest(
            @NonNull BaseVariantOutputData variantOutputData,
            @NonNull Set<String> screenSizes) {

        CompatibleScreensManifest csmTask = project.tasks.create(
                "create${variantOutputData.fullName.capitalize()}CompatibleScreensManifest",
                CompatibleScreensManifest)

        csmTask.screenDensity = variantOutputData.getMainOutputFile().getFilter(OutputFile.DENSITY)
        csmTask.screenSizes = screenSizes

        conventionMapping(csmTask).map("manifestFile") {
            project.file(
                    "$project.buildDir/${FD_INTERMEDIATES}/manifests/density/" +
                            "${variantOutputData.dirName}/AndroidManifest.xml")
        }

        return csmTask;
    }

    @CompileDynamic
    private static ConventionMapping conventionMapping(Task task) {
        task.conventionMapping
    }

    /**
     * Using the BaseConventionPlugin does not work for archivesBaseName dynamic attribute,
     * revert to a dynamic property invocation.
     */
    @CompileDynamic
    private static String getArchivesBaseName(Project project){
        project.archivesBaseName
    }

    public void createMergeLibManifestsTask(
            @NonNull BaseVariantData<? extends BaseVariantOutputData> variantData,
            @NonNull String manifestOutDir) {
        VariantConfiguration config = variantData.variantConfiguration

        // get single output for now.
        BaseVariantOutputData variantOutputData = variantData.outputs.get(0)

        def processManifest = project.tasks.create(
                "process${variantData.variantConfiguration.fullName.capitalize()}Manifest",
                ProcessManifest)
        variantOutputData.manifestProcessorTask = processManifest
        processManifest.androidBuilder = androidBuilder

        processManifest.dependsOn variantData.prepareDependenciesTask
        processManifest.variantConfiguration = config

        ProductFlavor mergedFlavor = config.mergedFlavor

        conventionMapping(processManifest).map("minSdkVersion") {
            if (androidBuilder.isPreviewTarget()) {
                return androidBuilder.getTargetCodename()
            }
            return mergedFlavor.minSdkVersion?.apiString
        }

        conventionMapping(processManifest).map("targetSdkVersion") {
            if (androidBuilder.isPreviewTarget()) {
                return androidBuilder.getTargetCodename()
            }

            return mergedFlavor.targetSdkVersion?.apiString
        }

        conventionMapping(processManifest).map("maxSdkVersion") {
            if (androidBuilder.isPreviewTarget()) {
                return null
            }

            return mergedFlavor.maxSdkVersion
        }

        conventionMapping(processManifest).map("manifestOutputFile") {
            project.file(
                    "$project.buildDir/${FD_INTERMEDIATES}/${manifestOutDir}/" +
                            "${variantData.variantConfiguration.dirName}/AndroidManifest.xml")
        }

        conventionMapping(processManifest).map("aaptFriendlyManifestOutputFile") {
            project.file(
                    "$project.buildDir/${FD_INTERMEDIATES}/${manifestOutDir}/" +
                            "${variantData.variantConfiguration.dirName}/aapt/AndroidManifest.xml")
        }
    }

    protected void createProcessTestManifestTask(
            @NonNull BaseVariantData<? extends BaseVariantOutputData> variantData,
            @NonNull String manifestOurDir) {
        def processTestManifestTask;
        VariantConfiguration config = variantData.variantConfiguration
        processTestManifestTask = project.tasks.create(
                "process${variantData.variantConfiguration.fullName.capitalize()}Manifest",
                ProcessTestManifest)
        conventionMapping(processTestManifestTask).map("testManifestFile") {
            config.getMainManifest()
        }
        conventionMapping(processTestManifestTask).map("tmpDir") {
            project.file(
                    "$project.buildDir/${FD_INTERMEDIATES}/${manifestOurDir}/tmp")
        }

        // get single output for now.
        BaseVariantOutputData variantOutputData = variantData.outputs.get(0)

        variantOutputData.manifestProcessorTask = processTestManifestTask
        processTestManifestTask.dependsOn variantData.prepareDependenciesTask

        processTestManifestTask.androidBuilder = androidBuilder

        conventionMapping(processTestManifestTask).map("testApplicationId") {
            config.applicationId
        }
        conventionMapping(processTestManifestTask).map("minSdkVersion") {
            if (androidBuilder.isPreviewTarget()) {
                return androidBuilder.getTargetCodename()
            }

            config.minSdkVersion?.apiString
        }
        conventionMapping(processTestManifestTask).map("targetSdkVersion") {
            if (androidBuilder.isPreviewTarget()) {
                return androidBuilder.getTargetCodename()
            }

            return config.targetSdkVersion?.apiString
        }
        conventionMapping(processTestManifestTask).map("testedApplicationId") {
            config.testedApplicationId
        }
        conventionMapping(processTestManifestTask).map("instrumentationRunner") {
            config.instrumentationRunner
        }
        conventionMapping(processTestManifestTask).map("handleProfiling") {
            config.handleProfiling
        }
        conventionMapping(processTestManifestTask).map("functionalTest") {
            config.functionalTest
        }
        conventionMapping(processTestManifestTask).map("libraries") {
            getManifestDependencies(config.directLibraries)
        }
        conventionMapping(processTestManifestTask).map("manifestOutputFile") {
            project.file(
                    "$project.buildDir/${FD_INTERMEDIATES}/${manifestOurDir}/${variantData.variantConfiguration.dirName}/AndroidManifest.xml")
        }
        conventionMapping(processTestManifestTask).map("placeholdersValues") {
            variantData.getVariantConfiguration().getManifestPlaceholders()
        }
    }

    public void createRenderscriptTask(
            @NonNull BaseVariantData<? extends BaseVariantOutputData> variantData) {
        GradleVariantConfiguration config = variantData.variantConfiguration

        // get single output for now.
        BaseVariantOutputData variantOutputData = variantData.outputs.get(0)

        def renderscriptTask = project.tasks.create(
                "compile${variantData.variantConfiguration.fullName.capitalize()}Renderscript",
                RenderscriptCompile)
        variantData.renderscriptCompileTask = renderscriptTask
        if (config.type.isForTesting()) {
            renderscriptTask.dependsOn variantOutputData.manifestProcessorTask
        } else {
            renderscriptTask.dependsOn variantData.checkManifestTask
        }

        ProductFlavor mergedFlavor = config.mergedFlavor
        boolean ndkMode = config.renderscriptNdkModeEnabled

        variantData.resourceGenTask.dependsOn renderscriptTask
        // only put this dependency if rs will generate Java code
        if (!ndkMode) {
            variantData.sourceGenTask.dependsOn renderscriptTask
        }

        renderscriptTask.dependsOn variantData.prepareDependenciesTask
        renderscriptTask.androidBuilder = androidBuilder

        conventionMapping(renderscriptTask).map("targetApi") {
            int targetApi = mergedFlavor.renderscriptTargetApi != null ?
                    mergedFlavor.renderscriptTargetApi : -1
            ApiVersion apiVersion = config.getMinSdkVersion()
            if (apiVersion != null) {
                int minSdk = apiVersion.apiLevel
                if (apiVersion.codename != null) {
                    minSdk = SdkVersionInfo.getApiByBuildCode(apiVersion.codename, true)
                }

                return targetApi > minSdk ? targetApi : minSdk
            }

            return targetApi
        }

        renderscriptTask.supportMode = config.renderscriptSupportModeEnabled
        renderscriptTask.ndkMode = ndkMode
        renderscriptTask.debugBuild = config.buildType.renderscriptDebuggable
        renderscriptTask.optimLevel = config.buildType.renderscriptOptimLevel

        conventionMapping(renderscriptTask).map("sourceDirs") { config.renderscriptSourceList }
        conventionMapping(renderscriptTask).map("importDirs") { config.renderscriptImports }

        conventionMapping(renderscriptTask).map("sourceOutputDir") {
            project.file(
                    "$project.buildDir/${FD_GENERATED}/source/rs/${variantData.variantConfiguration.dirName}")
        }
        conventionMapping(renderscriptTask).map("resOutputDir") {
            project.file(
                    "$project.buildDir/${FD_GENERATED}/res/rs/${variantData.variantConfiguration.dirName}")
        }
        conventionMapping(renderscriptTask).map("objOutputDir") {
            project.file(
                    "$project.buildDir/${FD_INTERMEDIATES}/rs/${variantData.variantConfiguration.dirName}/obj")
        }
        conventionMapping(renderscriptTask).map("libOutputDir") {
            project.file(
                    "$project.buildDir/${FD_INTERMEDIATES}/rs/${variantData.variantConfiguration.dirName}/lib")
        }
        conventionMapping(renderscriptTask).map("ndkConfig") { config.ndkConfig }
    }

    public void createMergeResourcesTask(
            @NonNull BaseVariantData<? extends BaseVariantOutputData> variantData,
            final boolean process9Patch) {
        MergeResources mergeResourcesTask = basicCreateMergeResourcesTask(
                variantData,
                "merge",
                "$project.buildDir/${FD_INTERMEDIATES}/res/merged/${variantData.variantConfiguration.dirName}",
                true /*includeDependencies*/,
                process9Patch)
        variantData.mergeResourcesTask = mergeResourcesTask
    }

    public MergeResources basicCreateMergeResourcesTask(
            @NonNull BaseVariantData<? extends BaseVariantOutputData> variantData,
            @NonNull String taskNamePrefix,
            @NonNull String outputLocation,
            final boolean includeDependencies,
            final boolean process9Patch) {
        MergeResources mergeResourcesTask = project.tasks.create(
                "$taskNamePrefix${variantData.variantConfiguration.fullName.capitalize()}Resources",
                MergeResources)

        mergeResourcesTask.dependsOn variantData.prepareDependenciesTask,
                variantData.resourceGenTask
        mergeResourcesTask.androidBuilder = androidBuilder
        mergeResourcesTask.incrementalFolder = project.file(
                "$project.buildDir/${FD_INTERMEDIATES}/incremental/${taskNamePrefix}Resources/${variantData.variantConfiguration.dirName}")

        mergeResourcesTask.process9Patch = process9Patch
        mergeResourcesTask.crunchPng = extension.aaptOptions.getCruncherEnabled()
        mergeResourcesTask.normalizeResources = extension.buildToolsRevision.compareTo(new FullRevision(21, 0, 0)) < 0

        conventionMapping(mergeResourcesTask).
                map("useNewCruncher") { getExtension().aaptOptions.useNewCruncher }

        conventionMapping(mergeResourcesTask).map("inputResourceSets") {
            List<File> generatedResFolders = Lists.newArrayList(
                    variantData.renderscriptCompileTask.getResOutputDir(),
                    variantData.generateResValuesTask.getResOutputDir())
            if (variantData.extraGeneratedResFolders != null) {
                generatedResFolders += variantData.extraGeneratedResFolders
            }
            if (variantData.generateApkDataTask != null &&
                    variantData.getVariantConfiguration().getBuildType().isEmbedMicroApp()) {
                generatedResFolders.add(variantData.generateApkDataTask.getResOutputDir())
            }
            variantData.variantConfiguration.getResourceSets(generatedResFolders,
                    includeDependencies)
        }

        conventionMapping(mergeResourcesTask).map("outputDir") { project.file(outputLocation) }

        return mergeResourcesTask
    }

    public void createMergeAssetsTask(
            @NonNull BaseVariantData<? extends BaseVariantOutputData> variantData,
            @Nullable String outputLocation,
            final boolean includeDependencies) {
        if (outputLocation == null) {
            outputLocation =
                    "$project.buildDir/${FD_INTERMEDIATES}/assets/${variantData.variantConfiguration.dirName}"
        }

        VariantConfiguration variantConfig = variantData.variantConfiguration

        def mergeAssetsTask = project.tasks.create(
                "merge${variantConfig.fullName.capitalize()}Assets",
                MergeAssets)
        variantData.mergeAssetsTask = mergeAssetsTask

        mergeAssetsTask.dependsOn variantData.prepareDependenciesTask, variantData.assetGenTask
        mergeAssetsTask.androidBuilder = androidBuilder
        mergeAssetsTask.incrementalFolder =
                project.file(
                        "$project.buildDir/${FD_INTERMEDIATES}/incremental/mergeAssets/${variantConfig.dirName}")

        conventionMapping(mergeAssetsTask).map("inputAssetSets") {
            def generatedAssets = []
            if (variantData.copyApkTask != null) {
                generatedAssets.add(variantData.copyApkTask.destinationDir)
            }
            variantConfig.getAssetSets(generatedAssets, includeDependencies)
        }
        conventionMapping(mergeAssetsTask).map("outputDir") { project.file(outputLocation) }
    }

    public void createBuildConfigTask(
            @NonNull BaseVariantData<? extends BaseVariantOutputData> variantData) {
        def generateBuildConfigTask = project.tasks.create(
                "generate${variantData.variantConfiguration.fullName.capitalize()}BuildConfig",
                GenerateBuildConfig)

        variantData.generateBuildConfigTask = generateBuildConfigTask

        VariantConfiguration variantConfiguration = variantData.variantConfiguration

        variantData.sourceGenTask.dependsOn generateBuildConfigTask
        if (variantConfiguration.type.isForTesting()) {
            // in case of a test project, the manifest is generated so we need to depend
            // on its creation.

            // For test apps there should be a single output, so we get it.
            BaseVariantOutputData variantOutputData = variantData.outputs.get(0)

            generateBuildConfigTask.dependsOn variantOutputData.manifestProcessorTask
        } else {
            generateBuildConfigTask.dependsOn variantData.checkManifestTask
        }

        generateBuildConfigTask.androidBuilder = androidBuilder

        conventionMapping(generateBuildConfigTask).map("buildConfigPackageName") {
            variantConfiguration.originalApplicationId
        }

        conventionMapping(generateBuildConfigTask).map("appPackageName") {
            variantConfiguration.applicationId
        }

        conventionMapping(generateBuildConfigTask).map("versionName") {
            variantConfiguration.versionName
        }

        conventionMapping(generateBuildConfigTask).map("versionCode") {
            variantConfiguration.versionCode
        }

        conventionMapping(generateBuildConfigTask).map("debuggable") {
            variantConfiguration.buildType.isDebuggable()
        }

        conventionMapping(generateBuildConfigTask).map("buildTypeName") {
            variantConfiguration.buildType.name
        }

        conventionMapping(generateBuildConfigTask).map("flavorName") {
            variantConfiguration.flavorName
        }

        conventionMapping(generateBuildConfigTask).map("flavorNamesWithDimensionNames") {
            variantConfiguration.flavorNamesWithDimensionNames
        }

        conventionMapping(generateBuildConfigTask).map("items") {
            variantConfiguration.buildConfigItems
        }

        conventionMapping(generateBuildConfigTask).map("sourceOutputDir") {
            project.file(
                    "$project.buildDir/${FD_GENERATED}/source/buildConfig/${variantData.variantConfiguration.dirName}")
        }
    }

    public void createGenerateResValuesTask(
            @NonNull BaseVariantData<? extends BaseVariantOutputData> variantData) {
        GenerateResValues generateResValuesTask = project.tasks.create(
                "generate${variantData.variantConfiguration.fullName.capitalize()}ResValues",
                GenerateResValues)
        variantData.generateResValuesTask = generateResValuesTask
        variantData.resourceGenTask.dependsOn generateResValuesTask

        VariantConfiguration variantConfiguration = variantData.variantConfiguration

        generateResValuesTask.androidBuilder = androidBuilder

        conventionMapping(generateResValuesTask).map("items") {
            variantConfiguration.resValues
        }

        conventionMapping(generateResValuesTask).map("resOutputDir") {
            project.file(
                    "$project.buildDir/${FD_GENERATED}/res/resValues/${variantData.variantConfiguration.dirName}")
        }
    }

    public void createPreprocessResourcesTask(
            @NonNull BaseVariantData<? extends BaseVariantOutputData> variantData) {
        String variantName = variantData.variantConfiguration.fullName.capitalize()
        int minSdk = variantData.variantConfiguration.minSdkVersion.getApiLevel()

        if (extension.preprocessResources  && minSdk < PreprocessResourcesTask.MIN_SDK) {
            PreprocessResourcesTask preprocessResourcesTask = project.tasks.create(
                    "preprocess${variantName}Resources",
                    PreprocessResourcesTask)
            variantData.preprocessResourcesTask = preprocessResourcesTask

            preprocessResourcesTask.dependsOn variantData.mergeResourcesTask

            preprocessResourcesTask.mergedResDirectory =
                    variantData.mergeResourcesTask.outputDir
            preprocessResourcesTask.generatedResDirectory =
                    project.file("$project.buildDir/${FD_GENERATED}/res/pngs/${variantData.variantConfiguration.dirName}")
            preprocessResourcesTask.outputResDirectory =
                    project.file("$project.buildDir/${FD_INTERMEDIATES}/res/preprocessed/${variantData.variantConfiguration.dirName}")
            preprocessResourcesTask.incrementalFolder =
                    project.file("$project.buildDir/${FD_INTERMEDIATES}/incremental/preprocessResourcesTask/${variantData.variantConfiguration.dirName}")

            // TODO: configure this in the extension.
            preprocessResourcesTask.densitiesToGenerate = [Density.HIGH, Density.XHIGH]
        }
    }


    public void createProcessResTask(
            @NonNull BaseVariantData<? extends BaseVariantOutputData> variantData,
            boolean generateResourcePackage) {
        createProcessResTask(variantData,
                "$project.buildDir/${FD_INTERMEDIATES}/symbols/${variantData.variantConfiguration.dirName}",
                generateResourcePackage)
    }

    public void createProcessResTask(
            @NonNull BaseVariantData<? extends BaseVariantOutputData> variantData,
            @NonNull final String symbolLocation,
            boolean generateResourcePackage) {

        VariantConfiguration config = variantData.variantConfiguration

        // loop on all outputs. The only difference will be the name of the task, and location
        // of the generated data.
        for (BaseVariantOutputData vod : variantData.outputs) {
            // create final var inside the loop to ensure the closures will work.
            final BaseVariantOutputData variantOutputData = vod

            String outputName = variantOutputData.fullName.capitalize()
            String outputBaseName = variantOutputData.baseName

            ProcessAndroidResources processResources = project.tasks.create(
                    "process${outputName}Resources",
                    ProcessAndroidResources)

            variantOutputData.processResourcesTask = processResources

            processResources.dependsOn variantOutputData.manifestProcessorTask,
                    variantData.mergeResourcesTask, variantData.mergeAssetsTask
            // TODO: Make it non-optional once this is not behind a flag.
            optionalDependsOn(processResources, variantData.preprocessResourcesTask)
            processResources.androidBuilder = androidBuilder

            if (variantData.getSplitHandlingPolicy() ==
                    BaseVariantData.SplitHandlingPolicy.RELEASE_21_AND_AFTER_POLICY) {

                variantData.calculateFilters(getExtension().getSplits());
                Set<String> allFilters = new HashSet<>();
                allFilters.addAll(variantData.getFilters(OutputFile.FilterType.DENSITY))
                allFilters.addAll(variantData.getFilters(OutputFile.FilterType.LANGUAGE))
                processResources.splits = allFilters;
            }

            // only generate code if the density filter is null, and if we haven't generated
            // it yet (if you have abi + density splits, then several abi output will have no
            // densityFilter)
            if (variantOutputData.getMainOutputFile().getFilter(OutputFile.DENSITY) == null
                    && variantData.generateRClassTask == null) {
                variantData.generateRClassTask = processResources
                variantData.sourceGenTask.dependsOn processResources
                processResources.enforceUniquePackageName = getExtension().getEnforceUniquePackageName()

                conventionMapping(processResources).map("libraries") {
                    getTextSymbolDependencies(config.allLibraries)
                }
                conventionMapping(processResources).map("packageForR") {
                    config.originalApplicationId
                }

                // TODO: unify with generateBuilderConfig, compileAidl, and library packaging somehow?
                conventionMapping(processResources).map("sourceOutputDir") {
                    project.file(
                            "$project.buildDir/${FD_GENERATED}/source/r/${config.dirName}")
                }

                conventionMapping(processResources).map("textSymbolOutputDir") {
                    project.file(symbolLocation)
                }

                if (config.buildType.isMinifyEnabled()) {
                    if (config.buildType.shrinkResources && config.useJack) {
                        LoggingUtil.displayWarning(logger, project,
                                "shrinkResources does not yet work with useJack=true")
                    }
                    conventionMapping(processResources).map("proguardOutputFile") {
                        project.file(
                                "$project.buildDir/${FD_INTERMEDIATES}/proguard-rules/${config.dirName}/aapt_rules.txt")
                    }
                } else if (config.buildType.shrinkResources) {
                    LoggingUtil.displayWarning(logger, project,
                            "To shrink resources you must also enable ProGuard")
                }
            }

            conventionMapping(processResources).map("manifestFile") {
                variantOutputData.manifestProcessorTask.getOutputFile()
            }

            conventionMapping(processResources).map("resDir") {
                variantData.finalResourcesDir
            }

            conventionMapping(processResources).map("assetsDir") {
                variantData.mergeAssetsTask.outputDir
            }

            if (generateResourcePackage) {
                conventionMapping(processResources).map("packageOutputFile") {
                    project.file(
                            "$project.buildDir/${FD_INTERMEDIATES}/res/resources-${outputBaseName}.ap_")
                }
            }

            conventionMapping(processResources).map("type") { config.type }
            conventionMapping(processResources).map("debuggable") { config.buildType.debuggable }
            conventionMapping(processResources).map("aaptOptions") { getExtension().aaptOptions }
            conventionMapping(processResources).
                    map("pseudoLocalesEnabled") { config.buildType.pseudoLocalesEnabled }

            conventionMapping(processResources).map("resourceConfigs") {
                Collection<String> resConfigs = config.mergedFlavor.resourceConfigurations;
                if (resConfigs != null && resConfigs.size() == 1
                    && Iterators.getOnlyElement(resConfigs.iterator()).equals("auto")) {

                    return variantData.discoverListOfResourceConfigs();
                }
                return config.mergedFlavor.resourceConfigurations
            }
            conventionMapping(processResources).map("preferredDensity") {
                variantOutputData.getMainOutputFile().getFilter(OutputFile.DENSITY)
            }

        }
    }

    /**
     * Creates the split resources packages task if necessary. AAPT will produce split packages
     * for all --split provided parameters. These split packages should be signed and moved
     * unchanged to the APK build output directory.
     * @param variantData the variant configuration.
     */
    public void createSplitResourcesTasks(
            @NonNull BaseVariantData<? extends BaseVariantOutputData> variantData) {

        assert variantData.getSplitHandlingPolicy() ==
                BaseVariantData.SplitHandlingPolicy.RELEASE_21_AND_AFTER_POLICY;

        VariantConfiguration config = variantData.variantConfiguration
        Set<String> densityFilters = variantData.getFilters(OutputFile.FilterType.DENSITY)
        Set<String> abiFilters = variantData.getFilters(OutputFile.FilterType.ABI);
        Set<String> languageFilters = variantData.getFilters(OutputFile.FilterType.LANGUAGE);

        def outputs = variantData.outputs;
        if (outputs.size() != 1) {
            throw new RuntimeException("In release 21 and later, there can be only one main APK, " +
                    "found " + outputs.size());
        }

        BaseVariantOutputData variantOutputData = outputs.get(0);
        variantOutputData.packageSplitResourcesTask =
                project.tasks.create("package${config.fullName.capitalize()}SplitResources",
                        PackageSplitRes);
        variantOutputData.packageSplitResourcesTask.inputDirectory =
                variantOutputData.processResourcesTask.packageOutputFile.getParentFile()
        variantOutputData.packageSplitResourcesTask.densitySplits = densityFilters
        variantOutputData.packageSplitResourcesTask.languageSplits = languageFilters
        variantOutputData.packageSplitResourcesTask.outputBaseName = config.baseName
        variantOutputData.packageSplitResourcesTask.signingConfig =
                (SigningConfig) config.signingConfig
        variantOutputData.packageSplitResourcesTask.outputDirectory =
                new File("$project.buildDir/${FD_INTERMEDIATES}/splits/${config.dirName}")
        variantOutputData.packageSplitResourcesTask.androidBuilder = androidBuilder
        variantOutputData.packageSplitResourcesTask.dependsOn variantOutputData.processResourcesTask

        SplitZipAlign zipAlign = project.tasks.
                create("zipAlign${config.fullName.capitalize()}SplitPackages", SplitZipAlign)
        conventionMapping(zipAlign).map("zipAlignExe") {
            String path = androidBuilder.targetInfo?.buildTools?.getPath(ZIP_ALIGN)
            if (path != null) {
                return new File(path)
            }

            return null
        }

        zipAlign.outputDirectory = new File("$project.buildDir/outputs/apk")
        conventionMapping(zipAlign).map("densityOrLanguageInputFiles") {
            return  variantOutputData.packageSplitResourcesTask.getOutputFiles()
        }
        zipAlign.outputBaseName = config.baseName
        zipAlign.abiFilters = abiFilters
        zipAlign.languageFilters = languageFilters
        zipAlign.densityFilters = densityFilters
        File metadataDirectory = new File(zipAlign.outputDirectory.getParentFile(), "metadata")
        zipAlign.apkMetadataFile = new File(metadataDirectory, "${config.fullName}.mtd")
        ((ApkVariantOutputData) variantOutputData).splitZipAlign = zipAlign
        zipAlign.dependsOn(variantOutputData.packageSplitResourcesTask)
    }

    public void createSplitAbiTasks(@NonNull ApplicationVariantData variantData) {

        assert variantData.getSplitHandlingPolicy() ==
                BaseVariantData.SplitHandlingPolicy.RELEASE_21_AND_AFTER_POLICY;

        VariantConfiguration config = variantData.variantConfiguration
        Set<String> filters = AbiSplitOptions.getAbiFilters(
                getExtension().getSplits().getAbiFilters())
        if (filters.isEmpty()) {
            return;
        }
        def outputs = variantData.outputs;
        if (outputs.size() != 1) {
            throw new RuntimeException("In release 21 and later, there can be only one main APK, " +
                    "found " + outputs.size());
        }

        BaseVariantOutputData variantOutputData = outputs.get(0);
        // first create the split APK resources.
        GenerateSplitAbiRes generateSplitAbiRes = project.tasks.
                create("generate${config.fullName.capitalize()}SplitAbiRes",
                        GenerateSplitAbiRes)
        generateSplitAbiRes.androidBuilder = androidBuilder

        generateSplitAbiRes.outputDirectory =
                new File("$project.buildDir/${FD_INTERMEDIATES}/abi/${config.dirName}")
        generateSplitAbiRes.splits = filters
        generateSplitAbiRes.outputBaseName = config.baseName
        generateSplitAbiRes.applicationId = config.getApplicationId()
        generateSplitAbiRes.versionCode = config.getVersionCode()
        generateSplitAbiRes.versionName = config.getVersionName()
        generateSplitAbiRes.debuggable = {
            config.buildType.debuggable
        }
        conventionMapping(generateSplitAbiRes).map("aaptOptions") {
            getExtension().aaptOptions
        }
        generateSplitAbiRes.dependsOn variantOutputData.processResourcesTask

        // then package those resources with the appropriate JNI libraries.
        variantOutputData.packageSplitAbiTask =
                project.tasks.create("package${config.fullName.capitalize()}SplitAbi",
                        PackageSplitAbi);
        variantOutputData.packageSplitAbiTask.inputFiles = generateSplitAbiRes.getOutputFiles()
        variantOutputData.packageSplitAbiTask.splits = filters
        variantOutputData.packageSplitAbiTask.outputBaseName = config.baseName
        variantOutputData.packageSplitAbiTask.signingConfig =
                (SigningConfig) config.signingConfig
        variantOutputData.packageSplitAbiTask.outputDirectory =
                new File("$project.buildDir/${FD_INTERMEDIATES}/splits/${config.dirName}")
        variantOutputData.packageSplitAbiTask.androidBuilder = androidBuilder
        variantOutputData.packageSplitAbiTask.dependsOn generateSplitAbiRes
        variantOutputData.packageSplitAbiTask.dependsOn getNdkBuildable(variantData)

        conventionMapping(variantOutputData.packageSplitAbiTask).map("jniFolders") {
            getJniFolders(variantData);
        }
        conventionMapping(variantOutputData.packageSplitAbiTask).
                map("jniDebuggable") { config.buildType.jniDebuggable }
        conventionMapping(variantOutputData.packageSplitAbiTask).
                map("packagingOptions") { getExtension().packagingOptions }

        ((ApkVariantOutputData) variantOutputData).splitZipAlign.abiInputFiles.addAll(
                variantOutputData.packageSplitAbiTask.getOutputFiles())

        ((ApkVariantOutputData) variantOutputData).splitZipAlign.dependsOn variantOutputData.packageSplitAbiTask
    }

    /**
     * Calculate the list of folders that can contain jni artifacts for this variant.
     * @param variantData the variant
     * @return a potentially empty list of directories that exist or not and that may contains
     * native resources.
     */
    @NonNull
    public Set<File> getJniFolders(@NonNull ApkVariantData variantData) {
        VariantConfiguration config = variantData.variantConfiguration
        // for now only the project's compilation output.
        Set<File> set = Sets.newHashSet()
        set.addAll(getNdkOutputDirectories(variantData))
        set.addAll(variantData.renderscriptCompileTask.libOutputDir)
        set.addAll(config.libraryJniFolders)
        set.addAll(config.jniLibsList)

        if (config.mergedFlavor.renderscriptSupportModeEnabled) {
            File rsLibs = androidBuilder.getSupportNativeLibFolder()
            if (rsLibs != null && rsLibs.isDirectory()) {
                set.add(rsLibs);
            }
        }

        return set
    }

    public void createProcessJavaResTask(
            @NonNull BaseVariantData<? extends BaseVariantOutputData> variantData) {
        VariantConfiguration variantConfiguration = variantData.variantConfiguration

        Copy processResources = project.tasks.create(
                "process${variantData.variantConfiguration.fullName.capitalize()}JavaRes",
                ProcessResources);
        variantData.processJavaResourcesTask = processResources

        // set the input
        processResources.from(((AndroidSourceSet) variantConfiguration.defaultSourceSet).resources.
                getSourceFiles())

        if (variantConfiguration.type != ANDROID_TEST) {
            processResources.from(
                    ((AndroidSourceSet) variantConfiguration.buildTypeSourceSet).resources.
                            getSourceFiles())
        }
        if (variantConfiguration.hasFlavors()) {
            for (SourceProvider flavorSourceSet : variantConfiguration.flavorSourceProviders) {
                processResources.
                        from(((AndroidSourceSet) flavorSourceSet).resources.getSourceFiles())
            }
        }

        conventionMapping(processResources).map("destinationDir") {
            project.file(
                    "$project.buildDir/${FD_INTERMEDIATES}/javaResources/${variantData.variantConfiguration.dirName}")
        }
    }

    public void createAidlTask(
            @NonNull BaseVariantData<? extends BaseVariantOutputData> variantData,
            @Nullable File parcelableDir) {
        VariantConfiguration variantConfiguration = variantData.variantConfiguration

        def compileTask = project.tasks.create(
                "compile${variantData.variantConfiguration.fullName.capitalize()}Aidl",
                AidlCompile)
        variantData.aidlCompileTask = compileTask

        variantData.sourceGenTask.dependsOn compileTask
        variantData.aidlCompileTask.dependsOn variantData.prepareDependenciesTask

        compileTask.androidBuilder = androidBuilder
        compileTask.incrementalFolder =
                project.file(
                        "$project.buildDir/${FD_INTERMEDIATES}/incremental/aidl/${variantData.variantConfiguration.dirName}")

        conventionMapping(compileTask).map("sourceDirs") { variantConfiguration.aidlSourceList }
        conventionMapping(compileTask).map("importDirs") { variantConfiguration.aidlImports }

        conventionMapping(compileTask).map("sourceOutputDir") {
            project.file(
                    "$project.buildDir/${FD_GENERATED}/source/aidl/${variantData.variantConfiguration.dirName}")
        }
        compileTask.aidlParcelableDir = parcelableDir
    }

    public void createJackAndUnitTestVerificationTask(
            @NonNull BaseVariantData<? extends BaseVariantOutputData> variantData,
            @NonNull BaseVariantData<? extends BaseVariantOutputData> testedVariantData) {

        PreCompilationVerificationTask verificationTask = project.tasks.create(
                "preCompile${variantData.variantConfiguration.fullName.capitalize()}Java",
                PreCompilationVerificationTask)
        verificationTask.useJack = testedVariantData.getVariantConfiguration().getUseJack()
        verificationTask.testSourceFiles = variantData.getJavaSources()
        variantData.javaCompileTask.dependsOn verificationTask
    }

    public void createJavaCompileTask(
            @NonNull BaseVariantData<? extends BaseVariantOutputData> variantData,
            @Nullable BaseVariantData<? extends BaseVariantOutputData> testedVariantData) {
        def javaCompileTask = project.tasks.create(
                "compile${variantData.variantConfiguration.fullName.capitalize()}Java",
                JavaCompile)

        variantData.javaCompileTask = javaCompileTask
        variantData.compileTask.dependsOn variantData.javaCompileTask
        optionalDependsOn(
                variantData.javaCompileTask, variantData.sourceGenTask)

        javaCompileTask.source = variantData.getJavaSources()

        conventionMapping(javaCompileTask).map("classpath") {
            FileCollection classpath = project.files(
                    androidBuilder.getCompileClasspath(variantData.variantConfiguration))

            if (testedVariantData) {
                // For libraries, the classpath from androidBuilder includes the library output
                // (bundle/classes.jar) as a normal dependency. In unit tests we don't want to package
                // the jar at every run, so we use the *.class files instead.
                if (testedVariantData.type != LIBRARY || variantData.type == UNIT_TEST) {
                    classpath = classpath +
                            testedVariantData.javaCompileTask.classpath +
                            testedVariantData.javaCompileTask.outputs.files
                }

                if (variantData.type == UNIT_TEST && testedVariantData.type == LIBRARY) {
                    // The bundled classes.jar may exist, but it's probably old. Don't use it, we
                    // already have the *.class files in the classpath.
                    classpath -= project.files(testedVariantData.variantConfiguration.output.jarFile)
                }
            }

            return classpath
        }

        javaCompileTask.dependsOn variantData.prepareDependenciesTask
        javaCompileTask.dependsOn variantData.processJavaResourcesTask

        // TODO - dependency information for the compile classpath is being lost.
        // Add a temporary approximation
        javaCompileTask.dependsOn variantData.variantDependency.compileConfiguration.buildDependencies

        conventionMapping(javaCompileTask).map("destinationDir") {
            project.file(
                    "$project.buildDir/${FD_INTERMEDIATES}/classes/${variantData.variantConfiguration.dirName}")
        }
        conventionMapping(javaCompileTask).map("dependencyCacheDir") {
            project.file(
                    "$project.buildDir/${FD_INTERMEDIATES}/dependency-cache/${variantData.variantConfiguration.dirName}")
        }

        configureLanguageLevel(javaCompileTask)
        javaCompileTask.options.encoding = getExtension().compileOptions.encoding

        // setup the boot classpath just before the task actually runs since this will
        // force the sdk to be parsed.
        javaCompileTask.doFirst {
            javaCompileTask.options.bootClasspath =
                    androidBuilder.getBootClasspathAsStrings().join(File.pathSeparator)
        }

        // Create jar task for uses by external modules.
        if (variantData.variantDependency.classesConfiguration != null) {
            Jar jar = project.tasks.create(
                    "package${variantData.variantConfiguration.fullName.capitalize()}JarArtifact",
                    Jar);
            variantData.classesJarTask = jar
            jar.dependsOn javaCompileTask

            // add the class files (whether they are instrumented or not.
            jar.from({ variantData.javaCompileTask.destinationDir })

            jar.destinationDir = project.file(
                    "$project.buildDir/${FD_INTERMEDIATES}/classes-jar/${variantData.variantConfiguration.dirName}")
            jar.archiveName = "classes.jar"
        }
    }

    public void createGenerateMicroApkDataTask(
            @NonNull BaseVariantData<? extends BaseVariantOutputData> variantData,
            @NonNull Configuration config) {
        GenerateApkDataTask task = project.tasks.create(
                "handle${variantData.variantConfiguration.fullName.capitalize()}MicroApk",
                GenerateApkDataTask)

        variantData.generateApkDataTask = task

        task.androidBuilder = androidBuilder
        conventionMapping(task).map("resOutputDir") {
            project.file(
                    "$project.buildDir/${FD_GENERATED}/res/microapk/${variantData.variantConfiguration.dirName}")
        }
        conventionMapping(task).map("apkFile") {
            // only care about the first one. There shouldn't be more anyway.
            config.getFiles().iterator().next()
        }
        conventionMapping(task).map("manifestFile") {
            project.file(
                    "$project.buildDir/${FD_INTERMEDIATES}/${FD_GENERATED}/manifests/microapk/${variantData.variantConfiguration.dirName}/${FN_ANDROID_MANIFEST_XML}")
        }
        conventionMapping(task).map("mainPkgName") {
            variantData.variantConfiguration.getApplicationId()
        }

        conventionMapping(task).map("minSdkVersion") {
            variantData.variantConfiguration.getMinSdkVersion().apiLevel
        }

        conventionMapping(task).map("targetSdkVersion") {
            variantData.variantConfiguration.getTargetSdkVersion().apiLevel
        }

        task.dependsOn config

        // the merge res task will need to run after this one.
        variantData.resourceGenTask.dependsOn task
    }

    public void createNdkTasks(
            @NonNull BaseVariantData<? extends BaseVariantOutputData> variantData) {
        NdkCompile ndkCompile = project.tasks.create(
                "compile${variantData.variantConfiguration.fullName.capitalize()}Ndk",
                NdkCompile)

        ndkCompile.dependsOn variantData.preBuildTask

        ndkCompile.androidBuilder = androidBuilder
        ndkCompile.ndkDirectory = sdkHandler.getNdkFolder()
        variantData.ndkCompileTask = ndkCompile
        variantData.compileTask.dependsOn variantData.ndkCompileTask

        GradleVariantConfiguration variantConfig = variantData.variantConfiguration

        if (variantConfig.mergedFlavor.renderscriptNdkModeEnabled) {
            ndkCompile.ndkRenderScriptMode = true
            ndkCompile.dependsOn variantData.renderscriptCompileTask
        } else {
            ndkCompile.ndkRenderScriptMode = false
        }

        conventionMapping(ndkCompile).map("sourceFolders") {
            List<File> sourceList = variantConfig.jniSourceList
            if (variantConfig.mergedFlavor.renderscriptNdkModeEnabled) {
                sourceList.add(variantData.renderscriptCompileTask.sourceOutputDir)
            }

            return sourceList
        }

        conventionMapping(ndkCompile).map("generatedMakefile") {
            project.file(
                    "$project.buildDir/${FD_INTERMEDIATES}/ndk/${variantData.variantConfiguration.dirName}/Android.mk")
        }

        conventionMapping(ndkCompile).map("ndkConfig") { variantConfig.ndkConfig }

        conventionMapping(ndkCompile).map("debuggable") {
            variantConfig.buildType.jniDebuggable
        }

        conventionMapping(ndkCompile).map("objFolder") {
            project.file(
                    "$project.buildDir/${FD_INTERMEDIATES}/ndk/${variantData.variantConfiguration.dirName}/obj")
        }
        conventionMapping(ndkCompile).map("soFolder") {
            project.file(
                    "$project.buildDir/${FD_INTERMEDIATES}/ndk/${variantData.variantConfiguration.dirName}/lib")
        }
    }

    /**
     * Creates the tasks to build unit tests.
     *
     * @param variantData the test variant
     */
    void createUnitTestVariantTasks(
            @NonNull TaskFactory tasks,
            @NonNull TestVariantData variantData) {
        BaseVariantData testedVariantData = variantData.getTestedVariantData() as BaseVariantData
        variantData.assembleVariantTask.dependsOn createMockableJar

        createPreBuildTasks(variantData)
        createProcessJavaResTask(variantData)
        createCompileAnchorTask(variantData)
        createJavaCompileTask(variantData, testedVariantData)
        createJackAndUnitTestVerificationTask(variantData, testedVariantData)
        createUnitTestTask(tasks, variantData)

        // This hides the assemble unit test task from the task list.
        variantData.assembleVariantTask.group = null
    }

    /**
     * Creates the tasks to build android tests.
     *
     * @param variantData the test variant
     */
    public void createAndroidTestVariantTasks(
            @NonNull TaskFactory tasks,
            @NonNull TestVariantData variantData) {
        BaseVariantData<? extends BaseVariantOutputData> testedVariantData =
                variantData.
                        getTestedVariantData() as BaseVariantData<? extends BaseVariantOutputData>

        // get single output for now (though this may always be the case for tests).
        BaseVariantOutputData variantOutputData = variantData.outputs.get(0)
        BaseVariantOutputData testedVariantOutputData = testedVariantData.outputs.get(0)

        createAnchorTasks(variantData)

        // Add a task to process the manifest
        createProcessTestManifestTask(variantData, "manifests")

        // Add a task to create the res values
        createGenerateResValuesTask(variantData)

        // Add a task to compile renderscript files.
        createRenderscriptTask(variantData)

        // Add a task to merge the resource folders
        createMergeResourcesTask(variantData, true /*process9Patch*/)

        // Add a task to merge the assets folders
        createMergeAssetsTask(variantData, null /*default location*/, true /*includeDependencies*/)

        if (testedVariantData.variantConfiguration.type == VariantType.LIBRARY) {
            // in this case the tested library must be fully built before test can be built!
            if (testedVariantOutputData.assembleTask != null) {
                variantOutputData.manifestProcessorTask.dependsOn testedVariantOutputData.assembleTask
                variantData.mergeResourcesTask.dependsOn testedVariantOutputData.assembleTask
            }
        }

        // Add a task to create the BuildConfig class
        createBuildConfigTask(variantData)

        createPreprocessResourcesTask(variantData)

        // Add a task to generate resource source files
        createProcessResTask(variantData, true /*generateResourcePackage*/)

        // process java resources
        createProcessJavaResTask(variantData)

        createAidlTask(variantData, null /*parcelableDir*/)

        // Add NDK tasks
        if (isNdkTaskNeeded) {
            createNdkTasks(variantData)
        }

        // Add a task to compile the test application
        if (variantData.getVariantConfiguration().useJack) {
            createJackTask(variantData, testedVariantData);
        } else {
            createJavaCompileTask(variantData, testedVariantData)
            createPostCompilationTasks(variantData);
        }

        // Variant scope should be create at the function, but there is currently a dependencies
        // on the NdkCompile tasks, and the scope mechanism does not support lazy evaluation yet.
        VariantScope variantScope = createVariantScope(variantData);


        createPackagingTask(tasks, variantScope, false /*publishApk*/)

        tasks.named(ASSEMBLE_ANDROID_TEST) {
            it.dependsOn variantOutputData.assembleTask
        }

        createConnectedTestForVariantData(tasks, variantData, TestType.APPLICATION)
    }

    // TODO - should compile src/lint/java from src/lint/java and jar it into build/lint/lint.jar
    public void createLintCompileTask() {
        lintCompile = project.tasks.create("compileLint", Task)
        File outputDir = new File("$project.buildDir/${FD_INTERMEDIATES}/lint")

        lintCompile.doFirst {
            // create the directory for lint output if it does not exist.
            if (!outputDir.exists()) {
                boolean mkdirs = outputDir.mkdirs();
                if (!mkdirs) {
                    throw new GradleException("Unable to create lint output directory.")
                }
            }
        }
    }

    /** Is the given variant relevant for lint? */
    private static boolean isLintVariant(
            @NonNull BaseVariantData<? extends BaseVariantOutputData> baseVariantData) {
        // Only create lint targets for variants like debug and release, not debugTest
        VariantConfiguration config = baseVariantData.variantConfiguration
        // TODO: re-enable with Jack when possible
        return !config.getType().isForTesting() && !config.useJack;
    }

    // Add tasks for running lint on individual variants. We've already added a
    // lint task earlier which runs on all variants.
    public void createLintTasks(
            TaskFactory tasks,
            List<BaseVariantData<? extends BaseVariantOutputData>> variantDataList) {
        final Lint lint = project.tasks.create("lint", Lint)
        lint.description = "Runs lint on all variants."
        lint.group = JavaBasePlugin.VERIFICATION_GROUP
        lint.setLintOptions(getExtension().lintOptions)
        lint.setSdkHome(sdkHandler.getSdkFolder())
        lint.setToolingRegistry(toolingRegistry)
        tasks.named(JavaBasePlugin.CHECK_TASK_NAME) {
            it.dependsOn lint
        }
        lintAll = lint

        int count = variantDataList.size()
        for (int i = 0; i < count; i++) {
            final BaseVariantData<? extends BaseVariantOutputData> baseVariantData =
                    variantDataList.get(i)
            if (!isLintVariant(baseVariantData)) {
                continue;
            }

            // wire the main lint task dependency.
            lint.dependsOn lintCompile
            optionalDependsOn(lint, baseVariantData.javaCompileTask)

            String variantName = baseVariantData.variantConfiguration.fullName
            def capitalizedVariantName = variantName.capitalize()
            Lint variantLintCheck = project.tasks.create("lint" + capitalizedVariantName, Lint)
            variantLintCheck.dependsOn lintCompile
            optionalDependsOn(variantLintCheck, baseVariantData.javaCompileTask)

            // Note that we don't do "lint.dependsOn lintCheck"; the "lint" target will
            // on its own run through all variants (and compare results), it doesn't delegate
            // to the individual tasks (since it needs to coordinate data collection and
            // reporting)
            variantLintCheck.setLintOptions(getExtension().lintOptions)
            variantLintCheck.setSdkHome(sdkHandler.getSdkFolder())
            variantLintCheck.setVariantName(variantName)
            variantLintCheck.setToolingRegistry(toolingRegistry)
            variantLintCheck.description = "Runs lint on the " + capitalizedVariantName + " build."
            variantLintCheck.group = JavaBasePlugin.VERIFICATION_GROUP
        }
    }

    private void createLintVitalTask(@NonNull ApkVariantData variantData) {
        assert getExtension().lintOptions.checkReleaseBuilds
        // TODO: re-enable with Jack when possible
        if (!variantData.variantConfiguration.buildType.debuggable &&
                !variantData.variantConfiguration.useJack) {
            String variantName = variantData.variantConfiguration.fullName
            def capitalizedVariantName = variantName.capitalize()
            def taskName = "lintVital" + capitalizedVariantName
            Lint lintReleaseCheck = project.tasks.create(taskName, Lint)
            // TODO: Make this task depend on lintCompile too (resolve initialization order first)
            optionalDependsOn(lintReleaseCheck, variantData.javaCompileTask)
            lintReleaseCheck.setLintOptions(getExtension().lintOptions)
            lintReleaseCheck.setSdkHome(sdkHandler.getSdkFolder())
            lintReleaseCheck.setVariantName(variantName)
            lintReleaseCheck.setToolingRegistry(toolingRegistry)
            lintReleaseCheck.setFatalOnly(true)
            lintReleaseCheck.description = "Runs lint on just the fatal issues in the " +
                    capitalizedVariantName + " build."
            variantData.assembleVariantTask.dependsOn lintReleaseCheck

            // If lint is being run, we do not need to run lint vital.
            project.gradle.taskGraph.whenReady { TaskExecutionGraph taskGraph ->
                if (taskGraph.hasTask(lintAll)) {
                    lintReleaseCheck.setEnabled(false)
                }
            }
        }
    }

    private void createUnitTestTask(@NonNull TaskFactory tasks, @NonNull TestVariantData variantData) {
        BaseVariantData testedVariantData = variantData.testedVariantData as BaseVariantData

        Test runTestsTask = project.tasks.create(
                UNIT_TEST.prefix +
                        testedVariantData.variantConfiguration.fullName.capitalize(),
                Test)
        runTestsTask.group = JavaBasePlugin.VERIFICATION_GROUP
        runTestsTask.description = "Run unit tests for the " +
                "$testedVariantData.variantConfiguration.fullName build."

        fixTestTaskSources(runTestsTask)

        runTestsTask.dependsOn variantData.assembleVariantTask

        AbstractCompile testCompileTask = variantData.javaCompileTask
        runTestsTask.testClassesDir = testCompileTask.destinationDir

        conventionMapping(runTestsTask).map("classpath") {
            project.files(
                    testCompileTask.classpath,
                    testCompileTask.outputs.files,
                    variantData.processJavaResourcesTask.outputs,
                    testedVariantData.processJavaResourcesTask.outputs,
                    androidBuilder.bootClasspath.findAll {
                        it.name != SdkConstants.FN_FRAMEWORK_LIBRARY
                    },
                    // Mockable JAR is last, to make sure you can shadow the classes with
                    // dependencies.
                    createMockableJar.outputFile)
        }

        // Put the variant name in the report path, so that different testing tasks don't
        // overwrite each other's reports.
        TestTaskReports testTaskReports = runTestsTask.reports
        for (ConfigurableReport report in [testTaskReports.junitXml, testTaskReports.html]) {
            report.destination = new File(report.destination, testedVariantData.name)
        }

        tasks.named(JavaPlugin.TEST_TASK_NAME) { Task test ->
            test.dependsOn runTestsTask
        }

        extension.testOptions.unitTests.applyConfiguration(runTestsTask)
    }

    @CompileDynamic
    private static void fixTestTaskSources(@NonNull Test testTask) {
        // We are running in afterEvaluate, so the JavaBasePlugin has already added a
        // callback to add test classes to the list of source files of the newly created task.
        // The problem is that we haven't configured the test classes yet (JavaBasePlugin
        // assumes all Test tasks are fully configured at this point), so we have to remove the
        // "directory null" entry from source files and add the right value.
        //
        // This is an ugly hack, since we assume sourceFiles is an instance of
        // DefaultConfigurableFileCollection.
        testTask.inputs.sourceFiles.from.clear()
    }

    public void createTopLevelTestTasks(TaskFactory tasks, boolean hasFlavors) {
        List<String> reportTasks = Lists.newArrayListWithExpectedSize(2)

        List<DeviceProvider> providers = getExtension().deviceProviders

        String connectedRootName = "${CONNECTED}${ANDROID_TEST.suffix}"
        String defaultReportsDir = "$project.buildDir/$FD_REPORTS/$FD_ANDROID_TESTS"
        String defaultResultsDir = "$project.buildDir/${FD_OUTPUTS}/$FD_ANDROID_RESULTS"

        // If more than one flavor, create a report aggregator task and make this the parent
        // task for all new connected tasks.  Otherwise, create a top level connectedAndroidTest
        // DefaultTask.
        if (hasFlavors) {
            tasks.create(connectedRootName, AndroidReportTask) { AndroidReportTask mainConnectedTask ->
                mainConnectedTask.group = JavaBasePlugin.VERIFICATION_GROUP
                mainConnectedTask.description =
                        "Installs and runs instrumentation tests for all flavors on connected devices."
                mainConnectedTask.reportType = ReportType.MULTI_FLAVOR
                conventionMapping(mainConnectedTask).map("resultsDir") {
                    String rootLocation = extension.testOptions.resultsDir ?: defaultResultsDir
                    project.file("$rootLocation/connected/$FD_FLAVORS_ALL")
                }
                conventionMapping(mainConnectedTask).map("reportsDir") {
                    String rootLocation = extension.testOptions.reportDir ?: defaultReportsDir
                    project.file("$rootLocation/connected/$FD_FLAVORS_ALL")
                }

            }
            reportTasks.add(connectedRootName)
        } else {
            tasks.create(connectedRootName) { Task connectedTask ->
                connectedTask.group = JavaBasePlugin.VERIFICATION_GROUP
                connectedTask.description =
                        "Installs and runs instrumentation tests for all flavors on connected devices."
            }
        }
        tasks.named(CONNECTED_CHECK) {
            it.dependsOn connectedRootName
        }

        String mainProviderTaskName =  "${DEVICE}${ANDROID_TEST.suffix}"
        // if more than one provider tasks, either because of several flavors, or because of
        // more than one providers, then create an aggregate report tasks for all of them.
        if (providers.size() > 1 || hasFlavors) {
            tasks.create(mainProviderTaskName, AndroidReportTask) { AndroidReportTask mainProviderTask ->
                mainProviderTask.group = JavaBasePlugin.VERIFICATION_GROUP
                mainProviderTask.description =
                        "Installs and runs instrumentation tests using all Device Providers."
                mainProviderTask.reportType = ReportType.MULTI_FLAVOR

                conventionMapping(mainProviderTask).map("resultsDir") {
                    String rootLocation = extension.testOptions.resultsDir ?: defaultResultsDir

                    project.file("$rootLocation/devices/$FD_FLAVORS_ALL")
                }
                conventionMapping(mainProviderTask).map("reportsDir") {
                    String rootLocation = extension.testOptions.reportDir ?: defaultReportsDir
                    project.file("$rootLocation/devices/$FD_FLAVORS_ALL")
                }
            }
            reportTasks.add(mainProviderTaskName)
        } else {
            tasks.create(mainProviderTaskName) { Task providerTask ->
                providerTask.group = JavaBasePlugin.VERIFICATION_GROUP
                providerTask.description =
                        "Installs and runs instrumentation tests using all Device Providers."
            }
        }

        tasks.named(DEVICE_CHECK) {
            it.dependsOn mainProviderTaskName
        }

        // Create top level unit test tasks.
        tasks.create(JavaPlugin.TEST_TASK_NAME) { Task unitTestTask ->
            unitTestTask.group = JavaBasePlugin.VERIFICATION_GROUP
            unitTestTask.description = "Run unit tests for all variants."
        }
        tasks.named(JavaBasePlugin.CHECK_TASK_NAME) { Task check ->
            check.dependsOn JavaPlugin.TEST_TASK_NAME
        }

        // If gradle is launched with --continue, we want to run all tests and generate an
        // aggregate report (to help with the fact that we may have several build variants, or
        // or several device providers).
        // To do that, the report tasks must run even if one of their dependent tasks (flavor
        // or specific provider tasks) fails, when --continue is used, and the report task is
        // meant to run (== is in the task graph).
        // To do this, we make the children tasks ignore their errors (ie they won't fail and
        // stop the build).
        if (!reportTasks.isEmpty() && project.gradle.startParameter.continueOnFailure) {
            project.gradle.taskGraph.whenReady { TaskExecutionGraph taskGraph ->
                for (String reportTask : reportTasks) {
                    if (taskGraph.hasTask(reportTask)) {
                        tasks.named(reportTask) { AndroidReportTask task ->
                            task.setWillRun()
                        }
                    }
                }
            }
        }
    }

    public enum TestType {

        APPLICATION(DeviceProviderInstrumentTestTask.class),
        LIBRARY(DeviceProviderInstrumentTestLibraryTask.class),

        final private Class<? extends DeviceProviderInstrumentTestTask> taskType;

        TestType(Class<? extends DeviceProviderInstrumentTestTask> provider) {
            taskType = provider;
        }
    }

    protected void createConnectedTestForVariantData(
            TaskFactory tasks,
            final TestVariantData testVariantData,
            TestType testType) {
        BaseVariantData<? extends BaseVariantOutputData> baseVariantData =
                testVariantData.testedVariantData as BaseVariantData

        // get single output for now
        BaseVariantOutputData variantOutputData = baseVariantData.outputs.get(0)
        BaseVariantOutputData testVariantOutputData = testVariantData.outputs.get(0)

        String connectedRootName = "${CONNECTED}${ANDROID_TEST.suffix}"

        String connectedTaskName =
                "${connectedRootName}${baseVariantData.variantConfiguration.fullName.capitalize()}"

        TestData testData = new TestDataImpl(testVariantData)
        BaseVariantData<? extends BaseVariantOutputData> testedVariantData =
                baseVariantData as BaseVariantData
        // create the check tasks for this test
        // first the connected one.
        ImmutableList<Task> artifactsTasks = ImmutableList.of(
                testVariantData.outputs.get(0).assembleTask,
                testedVariantData.assembleVariantTask)

        DeviceProviderInstrumentTestTask connectedTask =
                createDeviceProviderInstrumentTestTask(
                        connectedTaskName,
                        "Installs and runs the tests for ${baseVariantData.description} on connected devices.",
                        testType.taskType,
                        testData,
                        artifactsTasks,
                        new ConnectedDeviceProvider(
                                sdkHandler.getSdkInfo().adb,
                                new LoggerWrapper(logger)),
                        CONNECTED
                )

        tasks.named(connectedRootName) {
            it.dependsOn connectedTask
        }
        testVariantData.connectedTestTask = connectedTask

        if (baseVariantData.variantConfiguration.buildType.isTestCoverageEnabled()) {
            def reportTask = project.tasks.create(
                    "create${baseVariantData.variantConfiguration.fullName.capitalize()}CoverageReport",
                    JacocoReportTask)
            reportTask.reportName = baseVariantData.variantConfiguration.fullName
            conventionMapping(reportTask).map("jacocoClasspath") {
                project.configurations[JacocoPlugin.ANT_CONFIGURATION_NAME]
            }
            conventionMapping(reportTask).map("coverageFile") {
                new File(connectedTask.getCoverageDir(),
                        SimpleTestCallable.FILE_COVERAGE_EC)
            }
            conventionMapping(reportTask).map("classDir") {
                return baseVariantData.javaCompileTask.destinationDir
            }
            conventionMapping(reportTask).
                    map("sourceDir") { baseVariantData.getJavaSourceFoldersForCoverage() }

            conventionMapping(reportTask).map("reportDir") {
                project.file(
                        "$project.buildDir/$FD_REPORTS/coverage/${baseVariantData.variantConfiguration.dirName}")
            }

            reportTask.dependsOn connectedTask
            tasks.named(connectedRootName) {
                it.dependsOn reportTask
            }
        }

        String mainProviderTaskName = "${DEVICE}${ANDROID_TEST.suffix}"

        List<DeviceProvider> providers = getExtension().deviceProviders

        boolean hasFlavors = baseVariantData.variantConfiguration.hasFlavors()

        // now the providers.
        for (DeviceProvider deviceProvider : providers) {
            DeviceProviderInstrumentTestTask providerTask =
                    createDeviceProviderInstrumentTestTask(
                            hasFlavors ?
                                    "${deviceProvider.name}${ANDROID_TEST.suffix}${baseVariantData.variantConfiguration.fullName.capitalize()}" :
                                    "${deviceProvider.name}${ANDROID_TEST.suffix}",
                            "Installs and runs the tests for Build '${baseVariantData.variantConfiguration.fullName}' using Provider '${deviceProvider.name.capitalize()}'.",
                            testType.taskType,
                            testData,
                            artifactsTasks,
                            deviceProvider,
                            "$DEVICE/$deviceProvider.name"
                    )

            tasks.named(mainProviderTaskName) {
                it.dependsOn providerTask
            }
            testVariantData.providerTestTaskList.add(providerTask)

            if (!deviceProvider.isConfigured()) {
                providerTask.enabled = false;
            }
        }

        // now the test servers
        // don't use an auto loop as it'll break the closure inside.
        List<TestServer> servers = getExtension().testServers
        for (TestServer testServer : servers) {
            def serverTask = project.tasks.create(
                    hasFlavors ?
                            "${testServer.name}${"upload".capitalize()}${baseVariantData.variantConfiguration.fullName}" :
                            "${testServer.name}${"upload".capitalize()}",
                    TestServerTask)

            serverTask.description =
                    "Uploads APKs for Build '${baseVariantData.variantConfiguration.fullName}' to Test Server '${testServer.name.capitalize()}'."
            serverTask.group = JavaBasePlugin.VERIFICATION_GROUP
            serverTask.dependsOn testVariantOutputData.assembleTask,
                    variantOutputData.assembleTask

            serverTask.testServer = testServer

            conventionMapping(serverTask).
                    map("testApk") { testVariantOutputData.outputFile }
            if (!(baseVariantData instanceof LibraryVariantData)) {
                conventionMapping(serverTask).
                        map("testedApk") { variantOutputData.outputFile }
            }

            conventionMapping(serverTask).
                    map("variantName") { baseVariantData.variantConfiguration.fullName }

            tasks.named(DEVICE_CHECK) {
                it.dependsOn serverTask
            }

            if (!testServer.isConfigured()) {
                serverTask.enabled = false;
            }
        }
    }

    protected DeviceProviderInstrumentTestTask createDeviceProviderInstrumentTestTask(
            @NonNull String taskName,
            @NonNull String description,
            @NonNull Class<? extends DeviceProviderInstrumentTestTask> taskClass,
            @NonNull TestData testData,
            @NonNull List<Task> artifactsTasks,
            @NonNull DeviceProvider deviceProvider,
            @NonNull String subFolder) {
        DeviceProviderInstrumentTestTask testTask = project.tasks.create(
                taskName,
                taskClass as Class<DeviceProviderInstrumentTestTask>)

        testTask.description = description
        testTask.group = JavaBasePlugin.VERIFICATION_GROUP

        for (Task task : artifactsTasks) {
            testTask.dependsOn task
        }

        testTask.androidBuilder = androidBuilder
        testTask.testData = testData
        testTask.flavorName = testData.getFlavorName()
        testTask.deviceProvider = deviceProvider
        testTask.installOptions = getExtension().getAdbOptions().getInstallOptions();

        conventionMapping(testTask).map("resultsDir") {
            String rootLocation = getExtension().testOptions.resultsDir != null ?
                    getExtension().testOptions.resultsDir :
                    "$project.buildDir/${FD_OUTPUTS}/$FD_ANDROID_RESULTS"

            String flavorFolder = testData.getFlavorName()
            if (!flavorFolder.isEmpty()) {
                flavorFolder = "$FD_FLAVORS/" + flavorFolder
            }

            project.file("$rootLocation/$subFolder/$flavorFolder")
        }

        conventionMapping(testTask).map("adbExec") {
            return sdkHandler.getSdkInfo().getAdb()
        }

        conventionMapping(testTask).map("splitSelectExec") {
            String path = androidBuilder.targetInfo?.buildTools?.getPath(
                    BuildToolInfo.PathId.SPLIT_SELECT)
            if (path != null) {
                File splitSelectExe = new File(path)
                return splitSelectExe.exists() ? splitSelectExe : null;
            } else {
                return null;
            }
        }
        testTask.processExecutor = androidBuilder.getProcessExecutor()


        conventionMapping(testTask).map("reportsDir") {
            String rootLocation = getExtension().testOptions.reportDir != null ?
                    getExtension().testOptions.reportDir :
                    "$project.buildDir/$FD_REPORTS/$FD_ANDROID_TESTS"

            String flavorFolder = testData.getFlavorName()
            if (!flavorFolder.isEmpty()) {
                flavorFolder = "$FD_FLAVORS/" + flavorFolder
            }

            project.file("$rootLocation/$subFolder/$flavorFolder")
        }
        conventionMapping(testTask).map("coverageDir") {
            String rootLocation = "$project.buildDir/${FD_OUTPUTS}/code-coverage"

            String flavorFolder = testData.getFlavorName()
            if (!flavorFolder.isEmpty()) {
                flavorFolder = "$FD_FLAVORS/" + flavorFolder
            }

            project.file("$rootLocation/$subFolder/$flavorFolder")
        }

        return testTask
    }

    /**
     * Class to hold data to setup the many optional
     * post-compilation steps.
     */
    public static class PostCompilationData {

        List<?> classGeneratingTask

        List<?> libraryGeneratingTask

        Closure<List<File>> inputFiles

        Closure<File> inputDir

        Closure<List<File>> inputLibraries
    }

    public void createJarTask(@NonNull BaseVariantData variantData) {

        GradleVariantConfiguration config = variantData.variantConfiguration
        AndroidJarTask jarTask = project.tasks.create(
                "jar${config.fullName.capitalize()}Classes",
                AndroidJarTask)

        jarTask.setArchiveName("classes.jar");
        jarTask.setDestinationDir(project.file(
                "$project.buildDir/${FD_INTERMEDIATES}/packaged/${config.dirName}/"))
        jarTask.from(variantData.javaCompileTask.destinationDir)
        jarTask.dependsOn variantData.javaCompileTask
        variantData.binayFileProviderTask = jarTask
    }

    /**
     * Creates the post-compilation tasks for the given Variant.
     *
     * These tasks create the dex file from the .class files, plus optional intermediary steps
     * like proguard and jacoco
     *
     * @param variantData the variant data.
     */
    public void createPostCompilationTasks(@NonNull ApkVariantData variantData) {
        GradleVariantConfiguration config = variantData.variantConfiguration

        boolean isTestForApp = config.type.isForTesting() &&
                (variantData as TestVariantData).testedVariantData.variantConfiguration.type ==
                DEFAULT

        boolean isMinifyEnabled = config.isMinifyEnabled()
        boolean isMultiDexEnabled = config.isMultiDexEnabled() && !isTestForApp
        boolean isLegacyMultiDexMode = config.isLegacyMultiDexMode()
        File multiDexKeepProguard = config.getMultiDexKeepProguard()
        File multiDexKeepFile = config.getMultiDexKeepFile()

        boolean isTestCoverageEnabled = config.buildType.isTestCoverageEnabled() &&
                !config.type.isForTesting()

        // common dex task configuration
        String dexTaskName = "dex${config.fullName.capitalize()}"
        Dex dexTask = project.tasks.create(dexTaskName, Dex)
        variantData.dexTask = dexTask
        dexTask.androidBuilder = androidBuilder
        conventionMapping(dexTask).map("outputFolder") {
            project.file("${project.buildDir}/${FD_INTERMEDIATES}/dex/${config.dirName}")
        }
        dexTask.tmpFolder =
                project.file("$project.buildDir/${FD_INTERMEDIATES}/tmp/dex/${config.dirName}")
        dexTask.dexOptions = getExtension().dexOptions
        dexTask.multiDexEnabled = isMultiDexEnabled
        dexTask.legacyMultiDexMode = isLegacyMultiDexMode
        // dx doesn't work with receving --no-optimize in debug so we disable it for now.
        dexTask.optimize = true //!variantData.variantConfiguration.buildType.debuggable


        // data holding dependencies and input for the dex. This gets updated as new
        // post-compilation steps are inserted between the compilation and dx.
        PostCompilationData pcData = new PostCompilationData()
        pcData.classGeneratingTask = [variantData.javaCompileTask]
        pcData.libraryGeneratingTask =
                [variantData.variantDependency.packageConfiguration.buildDependencies]
        pcData.inputFiles = {
            variantData.javaCompileTask.outputs.files.files as List
        }
        pcData.inputDir = {
            variantData.javaCompileTask.destinationDir
        }
        pcData.inputLibraries = {
            androidBuilder.getPackagedJars(config) as List
        }

        // ---- Code Coverage first -----
        if (isTestCoverageEnabled) {
            pcData = createJacocoTask(config, variantData, pcData)
        }

        // ----- Minify next ----
        BaseVariantData<? extends BaseVariantOutputData> testedVariantData =
                (variantData instanceof TestVariantData ? variantData.testedVariantData :
                        null) as BaseVariantData

        File outFile = maybeCreateProguardTasks(variantData, testedVariantData, pcData);
        if (outFile != null) {
            pcData.inputFiles = { [outFile] }
            pcData.inputLibraries = { [] }
        } else if ((getExtension().dexOptions.preDexLibraries && !isMultiDexEnabled) ||
                (isMultiDexEnabled && !isLegacyMultiDexMode)) {
            def preDexTaskName = "preDex${config.fullName.capitalize()}"
            PreDex preDexTask = project.tasks.create(preDexTaskName, PreDex)

            variantData.preDexTask = preDexTask
            preDexTask.androidBuilder = androidBuilder
            preDexTask.dexOptions = getExtension().dexOptions
            preDexTask.multiDex = isMultiDexEnabled

            conventionMapping(preDexTask).map("inputFiles", pcData.inputLibraries)
            conventionMapping(preDexTask).map("outputFolder") {
                project.file(
                        "${project.buildDir}/${FD_INTERMEDIATES}/pre-dexed/${config.dirName}")
            }

            // update dependency.
            optionalDependsOn(preDexTask, pcData.libraryGeneratingTask)
            pcData.libraryGeneratingTask = [preDexTask] as List<Object>

            // update inputs
            if (isMultiDexEnabled) {
                pcData.inputLibraries = { [] }

            } else {
                pcData.inputLibraries = {
                    project.fileTree(preDexTask.outputFolder).files as List
                }
            }
        }

        // ----- Multi-Dex support
        if (isMultiDexEnabled && isLegacyMultiDexMode) {
            if (!isMinifyEnabled) {
                // create a task that will convert the output of the compilation
                // into a jar. This is needed by the multi-dex input.
                JarMergingTask jarMergingTask = project.tasks.create(
                        "packageAll${config.fullName.capitalize()}ClassesForMultiDex",
                        JarMergingTask)
                conventionMapping(jarMergingTask).map("inputJars", pcData.inputLibraries)
                conventionMapping(jarMergingTask).map("inputDir", pcData.inputDir)

                jarMergingTask.jarFile = project.file(
                        "$project.buildDir/${FD_INTERMEDIATES}/multi-dex/${config.dirName}/allclasses.jar")

                // update dependencies
                optionalDependsOn(jarMergingTask, pcData.classGeneratingTask)
                optionalDependsOn(jarMergingTask, pcData.libraryGeneratingTask)
                pcData.libraryGeneratingTask = [jarMergingTask]
                pcData.classGeneratingTask = [jarMergingTask]

                // Update the inputs
                pcData.inputFiles = { [jarMergingTask.jarFile] }
                pcData.inputDir = null
                pcData.inputLibraries = { [] }
            }

            // ----------
            // Create a task to collect the list of manifest entry points which are
            // needed in the primary dex
            CreateManifestKeepList manifestKeepListTask = project.tasks.create(
                    "collect${config.fullName.capitalize()}MultiDexComponents",
                    CreateManifestKeepList)

            // since all the output have the same manifest, besides the versionCode,
            // we can take any of the output and use that.
            final BaseVariantOutputData output = variantData.outputs.get(0)
            manifestKeepListTask.dependsOn output.manifestProcessorTask
            conventionMapping(manifestKeepListTask).map("manifest") {
                output.manifestProcessorTask.getOutputFile()
            }

            manifestKeepListTask.proguardFile = multiDexKeepProguard
            manifestKeepListTask.outputFile = project.file(
                    "${project.buildDir}/${FD_INTERMEDIATES}/multi-dex/${config.dirName}/manifest_keep.txt")

            //variant.ext.collectMultiDexComponents = manifestKeepListTask

            // ----------
            // Create a proguard task to shrink the classes to manifest components
            ProGuardTask proguardComponentsTask = createShrinkingProGuardTask(project,
                    "shrink${config.fullName.capitalize()}MultiDexComponents")

            proguardComponentsTask.configuration(manifestKeepListTask.outputFile)

            proguardComponentsTask.libraryjars({
                checkNotNull(androidBuilder.getTargetInfo())
                File shrinkedAndroid = new File(androidBuilder.getTargetInfo().buildTools.location,
                        "lib${File.separatorChar}shrinkedAndroid.jar")

                // TODO remove in 1.0
                // STOPSHIP
                if (!shrinkedAndroid.isFile()) {
                    shrinkedAndroid = new File(androidBuilder.getTargetInfo().buildTools.location,
                            "multidex${File.separatorChar}shrinkedAndroid.jar")
                }
                return shrinkedAndroid
            })

            proguardComponentsTask.injars(pcData.inputFiles.call().iterator().next())

            File componentsJarFile = project.file(
                    "${project.buildDir}/${FD_INTERMEDIATES}/multi-dex/${config.dirName}/componentClasses.jar")
            proguardComponentsTask.outjars(componentsJarFile)

            proguardComponentsTask.printconfiguration(
                    "${project.buildDir}/${FD_INTERMEDIATES}/multi-dex/${config.dirName}/components.flags")

            // update dependencies
            proguardComponentsTask.dependsOn manifestKeepListTask
            optionalDependsOn(proguardComponentsTask, pcData.classGeneratingTask)
            optionalDependsOn(proguardComponentsTask, pcData.libraryGeneratingTask)

            // ----------
            // Compute the full list of classes for the main dex file
            CreateMainDexList createMainDexListTask = project.tasks.create(
                    "create${config.fullName.capitalize()}MainDexClassList",
                    CreateMainDexList)
            createMainDexListTask.androidBuilder = androidBuilder
            createMainDexListTask.dependsOn proguardComponentsTask
            //createMainDexListTask.dependsOn { proguardMainDexTask }

            def files = pcData.inputFiles
            createMainDexListTask.allClassesJarFile = files().first()
            conventionMapping(createMainDexListTask).map("componentsJarFile") { componentsJarFile }
            // conventionMapping(createMainDexListTask).map("includeInMainDexJarFile") { mainDexJarFile }
            createMainDexListTask.mainDexListFile = multiDexKeepFile
            createMainDexListTask.outputFile = project.file(
                    "${project.buildDir}/${FD_INTERMEDIATES}/multi-dex/${config.dirName}/maindexlist.txt")

            // update dependencies
            dexTask.dependsOn createMainDexListTask

            // ----------
            // If proguard is on create a de-obfuscated list to aid debugging.
            if (isMinifyEnabled) {
                RetraceMainDexList retraceTask = project.tasks.create(
                        "retrace${config.fullName.capitalize()}MainDexClassList",
                        RetraceMainDexList)
                retraceTask.dependsOn variantData.obfuscationTask, createMainDexListTask

                conventionMapping(retraceTask).
                        map("mainDexListFile") { createMainDexListTask.outputFile }
                conventionMapping(retraceTask).map("mappingFile") {
                    variantData.getMappingFile()
                }
                retraceTask.outputFile = project.file(
                        "${project.buildDir}/${FD_INTERMEDIATES}/multi-dex/${config.dirName}/maindexlist_deobfuscated.txt")
                dexTask.dependsOn retraceTask
            }

            // configure the dex task to receive the generated class list.
            conventionMapping(dexTask).map("mainDexListFile") { createMainDexListTask.outputFile }
        }

        // ----- Dex Task ----

        // dependencies, some of these could be null
        optionalDependsOn(dexTask, variantData.obfuscationTask)
        optionalDependsOn(dexTask, pcData.classGeneratingTask)
        optionalDependsOn(dexTask, pcData.libraryGeneratingTask,)

        // inputs
        if (pcData.inputDir != null) {
            conventionMapping(dexTask).map("inputDir", pcData.inputDir)
        }
        conventionMapping(dexTask).map("inputFiles", pcData.inputFiles)
        conventionMapping(dexTask).map("libraries", pcData.inputLibraries)
    }

    public PostCompilationData createJacocoTask(
            @NonNull GradleVariantConfiguration config,
            @NonNull BaseVariantData variantData,
            @NonNull final PostCompilationData pcData) {
        final JacocoInstrumentTask jacocoTask = project.tasks.create(
                "instrument${config.fullName.capitalize()}", JacocoInstrumentTask)
        conventionMapping(jacocoTask).map("jacocoClasspath") {
            project.configurations[JacocoPlugin.ANT_CONFIGURATION_NAME]
        }
        // can't directly use the existing inputFiles closure as we need the dir instead :\
        conventionMapping(jacocoTask).map("inputDir", pcData.inputDir)
        conventionMapping(jacocoTask).map("outputDir") {
            project.file(
                    "${project.buildDir}/${FD_INTERMEDIATES}/coverage-instrumented-classes/${config.dirName}")
        }
        variantData.jacocoInstrumentTask = jacocoTask

        Copy agentTask = getJacocoAgentTask()
        jacocoTask.dependsOn agentTask

        // update dependency.
        PostCompilationData pcData2 = new PostCompilationData()
        optionalDependsOn(jacocoTask, pcData.classGeneratingTask)
        pcData2.classGeneratingTask = [jacocoTask]
        pcData2.libraryGeneratingTask = [pcData.libraryGeneratingTask, agentTask]

        // update inputs
        pcData2.inputFiles = {
            project.files(jacocoTask.getOutputDir()).files as List
        }
        pcData2.inputDir = {
            jacocoTask.getOutputDir()
        }
        pcData2.inputLibraries = {
            [pcData.inputLibraries.call(), [new File(agentTask.destinationDir, FILE_JACOCO_AGENT)]].
                    flatten() as List
        }

        return pcData2
    }

    private static ProGuardTask createShrinkingProGuardTask(
            @NonNull Project project,
            @NonNull String name) {
        ProGuardTask task = project.tasks.create(name, ProGuardTask)

        task.dontobfuscate()
        task.dontoptimize()
        task.dontpreverify()
        task.dontwarn()
        task.forceprocessing()

        return task;
    }

    public void createJackTask(
            @NonNull BaseVariantData<? extends BaseVariantOutputData> variantData,
            @Nullable BaseVariantData<? extends BaseVariantOutputData> testedVariantData) {

        GradleVariantConfiguration config = variantData.variantConfiguration

        // ----- Create Jill tasks -----
        JillTask jillRuntimeTask = project.tasks.create(
                "jill${config.fullName.capitalize()}RuntimeLibraries",
                JillTask)

        jillRuntimeTask.androidBuilder = androidBuilder
        jillRuntimeTask.dexOptions = getExtension().dexOptions

        conventionMapping(jillRuntimeTask).map("inputLibs") {
            androidBuilder.getBootClasspath()
        }
        conventionMapping(jillRuntimeTask).map("outputFolder") {
            project.file(
                    "${project.buildDir}/${FD_INTERMEDIATES}/jill/${config.dirName}/runtime")
        }

        // ----

        JillTask jillPackagedTask = project.tasks.create(
                "jill${config.fullName.capitalize()}PackagedLibraries",
                JillTask)

        jillPackagedTask.dependsOn variantData.variantDependency.packageConfiguration.buildDependencies
        jillPackagedTask.androidBuilder = androidBuilder
        jillPackagedTask.dexOptions = getExtension().dexOptions

        conventionMapping(jillPackagedTask).map("inputLibs") {
            androidBuilder.getPackagedJars(config)
        }
        conventionMapping(jillPackagedTask).map("outputFolder") {
            project.file(
                    "${project.buildDir}/${FD_INTERMEDIATES}/jill/${config.dirName}/packaged")
        }

        // ----- Create Jack Task -----
        JackTask compileTask = project.tasks.create(
                "compile${config.fullName.capitalize()}JavaWithJack",
                JackTask)
        compileTask.isVerbose = isVerbose()
        compileTask.isDebugLog = isDebugLog()

        // Jack is compiling and also providing the binary and mapping files.
        variantData.javaCompileTask = compileTask
        variantData.mappingFileProviderTask = compileTask
        variantData.binayFileProviderTask = compileTask

        variantData.javaCompileTask.dependsOn variantData.sourceGenTask, jillRuntimeTask, jillPackagedTask
        variantData.compileTask.dependsOn variantData.javaCompileTask
        // TODO - dependency information for the compile classpath is being lost.
        // Add a temporary approximation
        compileTask.dependsOn variantData.variantDependency.compileConfiguration.buildDependencies

        compileTask.androidBuilder = androidBuilder
        conventionMapping(compileTask).
                map("javaMaxHeapSize") { getExtension().dexOptions.getJavaMaxHeapSize() }

        compileTask.source = variantData.getJavaSources()

        compileTask.multiDexEnabled = config.isMultiDexEnabled()
        compileTask.minSdkVersion = config.minSdkVersion.apiLevel

        // if the tested variant is an app, add its classpath. For the libraries,
        // it's done automatically since the classpath includes the library output as a normal
        // dependency.
        if (testedVariantData instanceof ApplicationVariantData) {
            JackTask jackTask = (JackTask) testedVariantData.javaCompileTask
            conventionMapping(compileTask).map("classpath") {
                project.fileTree(jillRuntimeTask.outputFolder) +
                        jackTask.classpath +
                        project.fileTree(jackTask.jackFile)
            }
        } else {
            conventionMapping(compileTask).map("classpath") {
                project.fileTree(jillRuntimeTask.outputFolder)
            }
        }

        conventionMapping(compileTask).map("packagedLibraries") {
            project.fileTree(jillPackagedTask.outputFolder).files
        }

        conventionMapping(compileTask).map("destinationDir") {
            project.file("$project.buildDir/${FD_INTERMEDIATES}/dex/${config.dirName}")
        }

        conventionMapping(compileTask).map("jackFile") {
            project.file(
                    "$project.buildDir/${FD_INTERMEDIATES}/packaged/${config.dirName}/classes.zip")
        }

        conventionMapping(compileTask).map("tempFolder") {
            project.file("$project.buildDir/${FD_INTERMEDIATES}/tmp/jack/${config.dirName}")
        }
        if (config.isMinifyEnabled()) {
            conventionMapping(compileTask).map("proguardFiles") {
                // since all the output use the same resources, we can use the first output
                // to query for a proguard file.
                BaseVariantOutputData variantOutputData = variantData.outputs.get(0)

                List<File> proguardFiles = config.getProguardFiles(true /*includeLibs*/,
                        [getExtension().getDefaultProguardFile(DEFAULT_PROGUARD_CONFIG_FILE)])
                File proguardResFile = variantOutputData.processResourcesTask.proguardOutputFile
                if (proguardResFile != null) {
                    proguardFiles.add(proguardResFile)
                }
                // for tested app, we only care about their aapt config since the base
                // configs are the same files anyway.
                if (testedVariantData != null) {
                    // use single output for now.
                    proguardResFile =
                            testedVariantData.outputs.get(0).processResourcesTask.proguardOutputFile
                    if (proguardResFile != null) {
                        proguardFiles.add(proguardResFile)
                    }
                }

                return proguardFiles
            }

            compileTask.mappingFile = project.file(
                    "${project.buildDir}/${FD_OUTPUTS}/mapping/${variantData.variantConfiguration.dirName}/mapping.txt")
        }

        configureLanguageLevel(compileTask)
    }

    /**
     * Configures the source and target language level of a compile task. If the user has set it
     * explicitly, we obey the setting. Otherwise we change the default language level based on the
     * compile SDK version.
     *
     * <p>This method modifies getExtension().compileOptions, to propagate the language level to Studio.
     */
    private void configureLanguageLevel(AbstractCompile compileTask) {
        def compileOptions = getExtension().compileOptions
        JavaVersion javaVersionToUse

        Integer compileSdkLevel =
                AndroidTargetHash.getVersionFromHash(getExtension().compileSdkVersion)?.apiLevel
        switch (compileSdkLevel) {
            case null:  // Default to 1.6 if we fail to parse compile SDK version.
            case 0..20:
                javaVersionToUse = JavaVersion.VERSION_1_6
                break
            default:
                javaVersionToUse = JavaVersion.VERSION_1_7
                break
        }

        def jdkVersion = JavaVersion.toVersion(System.getProperty("java.specification.version"))
        if (jdkVersion < javaVersionToUse) {
            logger.info(
                    "Default language level for 'compileSdkVersion $compileSdkLevel' is " +
                            "$javaVersionToUse, but the JDK used is $jdkVersion, so the JDK " +
                            "language level will be used.")
            javaVersionToUse = jdkVersion
        }

        compileOptions.defaultJavaVersion = javaVersionToUse

        conventionMapping(compileTask).map("sourceCompatibility") {
            compileOptions.sourceCompatibility.toString()
        }
        conventionMapping(compileTask).map("targetCompatibility") {
            compileOptions.targetCompatibility.toString()
        }
    }

    /**
     * Creates the final packaging task, and optionally the zipalign task (if the variant is signed)
     * @param variantData
     * @param assembleTask an optional assembleTask to be used. If null a new one is created. The
     *                assembleTask is always set in the Variant.
     * @param publishApk if true the generated APK gets published.
     */
    public void createPackagingTask(
            @NonNull TaskFactory tasks,
            @NonNull VariantScope variantScope,
            boolean publishApk) {
        ApkVariantData variantData = (ApkVariantData) variantScope.getVariantData()

        GradleVariantConfiguration config = variantData.variantConfiguration
        boolean signedApk = variantData.isSigned()
        // use a dynamic property invocation due to gradle issue.
        String defaultLocation = "$project.buildDir/${FD_OUTPUTS}/apk"
        String apkLocation = defaultLocation
        if (project.hasProperty(PROPERTY_APK_LOCATION)) {
            apkLocation = project.getProperties().get(PROPERTY_APK_LOCATION)
        }
        SigningConfig sc = (SigningConfig) config.signingConfig

        boolean multiOutput = variantData.outputs.size() > 1

        // loop on all outputs. The only difference will be the name of the task, and location
        // of the generated data.
        for (ApkVariantOutputData vod : variantData.outputs) {
            VariantOutputScope variantOutputScope = new VariantOutputScope(variantScope, vod);

            // create final var inside the loop to ensure the closures will work.
            final ApkVariantOutputData variantOutputData = vod

            String outputName = variantOutputData.fullName

            AndroidTask<PackageApplication> packageApp = androidTasks.create(
                    tasks,
                    new PackageApplication.ConfigAction(variantOutputScope));

            packageApp.dependsOn(tasks,
                    variantOutputData.processResourcesTask,
                    variantData.processJavaResourcesTask,
                    variantOutputScope.getVariantScope().getNdkBuildable());

            TaskManager.optionalDependsOn(
                    packageApp,
                    tasks,
                    variantData.dexTask,
                    variantData.javaCompileTask,
                    variantOutputData.packageSplitResourcesTask,
                    variantOutputData.packageSplitAbiTask);

            AndroidTask appTask = packageApp

            if (signedApk) {
                if (variantData.zipAlignEnabled) {
                    AndroidTask<ZipAlign> zipAlignTask = androidTasks.create(
                            tasks,
                            new ZipAlign.ConfigAction(variantOutputScope));
                    zipAlignTask.dependsOn(tasks, packageApp);
                    if (variantOutputData.splitZipAlign != null) {
                        zipAlignTask.dependsOn(tasks, variantOutputData.splitZipAlign)
                    }
                    appTask = zipAlignTask
                }
            }

            assert variantData.assembleVariantTask != null

            // Add an assemble task
            if (multiOutput) {
                // create a task for this output
                variantOutputData.assembleTask = createAssembleTask(variantOutputData)

                // variant assemble task depends on each output assemble task.
                variantData.assembleVariantTask.dependsOn variantOutputData.assembleTask
            } else {
                // single output
                variantOutputData.assembleTask = variantData.assembleVariantTask
            }

            if (!signedApk && variantOutputData.packageSplitResourcesTask != null) {
                // in case we are not signing the resulting APKs and we have some pure splits
                // we should manually copy them from the intermediate location to the final
                // apk location unmodified.
                Copy copyTask = project.tasks.create(
                        "copySplit${outputName.capitalize()}",
                        Copy)
                copyTask.destinationDir = new File(apkLocation as String);
                copyTask.from(variantOutputData.packageSplitResourcesTask.getOutputDirectory())
                variantOutputData.assembleTask.dependsOn(copyTask)
                copyTask.mustRunAfter(appTask.name)
            }

            variantOutputData.assembleTask.dependsOn appTask.name

            if (publishApk) {
                String projectBaseName = globalScope.projectBaseName;

                // if this variant is the default publish config or we also should publish non
                // defaults, proceed with declaring our artifacts.
                if (getExtension().defaultPublishConfig.equals(outputName)) {
                    appTask.configure(tasks) { FileSupplier packageTask ->
                        project.artifacts.add("default", new ApkPublishArtifact(
                                projectBaseName,
                                null,
                                packageTask))
                    }

                    for (FileSupplier outputFileProvider :
                            variantOutputData.getSplitOutputFileSuppliers()) {
                        project.artifacts.add("default", new ApkPublishArtifact(
                                projectBaseName,
                                null,
                                outputFileProvider))
                    }

                    if (variantOutputData.getMetadataFile() != null) {
                        project.artifacts.add("default-metadata",
                                new MetadataPublishArtifact(projectBaseName, null,
                                        variantOutputData.getMetadataFile()));
                    }

                    if (variantData.getMappingFileProvider() != null) {
                        project.artifacts.add("default-mapping",
                                new MappingPublishArtifact(projectBaseName,
                                        null,
                                        variantData.getMappingFileProvider()));
                    }
                }

                if (getExtension().publishNonDefault) {
                    appTask.configure(tasks) { FileSupplier packageTask ->
                        project.artifacts.add(
                                variantData.variantDependency.publishConfiguration.name,
                                new ApkPublishArtifact(
                                        projectBaseName,
                                        null,
                                        packageTask))
                    }

                    for (FileSupplier outputFileProvider :
                            variantOutputData.getSplitOutputFileSuppliers()) {
                        project.artifacts.add(
                                variantData.variantDependency.publishConfiguration.name,
                                new ApkPublishArtifact(
                                    projectBaseName,
                                    null,
                                    outputFileProvider))
                    }

                    if (variantOutputData.getMetadataFile() != null) {
                        project.artifacts.add(
                                variantData.variantDependency.metadataConfiguration.name,
                                new MetadataPublishArtifact(projectBaseName, null,
                                        variantOutputData.getMetadataFile()));
                    }

                    if (variantData.getMappingFileProvider() != null) {
                        project.artifacts.add(
                                variantData.variantDependency.mappingConfiguration.name,
                                new MappingPublishArtifact(projectBaseName,
                                        null,
                                        variantData.getMappingFileProvider()));
                    }

                    if (variantData.classesJarTask != null) {
                        project.artifacts.add(
                                variantData.variantDependency.classesConfiguration.name,
                                variantData.classesJarTask)
                    }
                }
            }
        }

        // create install task for the variant Data. This will deal with finding the
        // right output if there are more than one.
        // Add a task to install the application package
        if (signedApk) {
            InstallVariantTask installTask = project.tasks.
                    create("install${config.fullName.capitalize()}",
                            InstallVariantTask)
            installTask.description = "Installs the ${variantData.description}."
            installTask.group = INSTALL_GROUP
            installTask.projectName = project.name
            installTask.variantData = variantData
            installTask.timeOutInMs = getExtension().getAdbOptions().getTimeOutInMs()
            installTask.installOptions = getExtension().getAdbOptions().getInstallOptions()
            installTask.processExecutor = androidBuilder.getProcessExecutor()
            conventionMapping(installTask).map("adbExe") { sdkHandler.sdkInfo?.adb }
            conventionMapping(installTask).map("splitSelectExe") {
                String path = androidBuilder.targetInfo?.buildTools?.getPath(
                        BuildToolInfo.PathId.SPLIT_SELECT)
                if (path != null) {
                    File splitSelectExe = new File(path)
                    return splitSelectExe.exists() ? splitSelectExe : null;
                } else {
                    return null;
                }
            }
            installTask.dependsOn variantData.assembleVariantTask
            variantData.installTask = installTask
        }


        if (getExtension().lintOptions.checkReleaseBuilds) {
            createLintVitalTask(variantData)
        }

        // add an uninstall task
        def uninstallTask = project.tasks.create(
                "uninstall${variantData.variantConfiguration.fullName.capitalize()}",
                UninstallTask)
        uninstallTask.description = "Uninstalls the ${variantData.description}."
        uninstallTask.group = INSTALL_GROUP
        uninstallTask.variant = variantData
        uninstallTask.androidBuilder = androidBuilder
        uninstallTask.timeOutInMs = getExtension().getAdbOptions().getTimeOutInMs()

        variantData.uninstallTask = uninstallTask
        tasks.named(UNINSTALL_ALL) {
            it.dependsOn uninstallTask
        }
    }

    public Task createAssembleTask(
            @NonNull BaseVariantOutputData variantOutputData) {
        Task assembleTask = project.tasks.
                create("assemble${variantOutputData.fullName.capitalize()}")
        return assembleTask
    }

    public Task createAssembleTask(
            @NonNull BaseVariantData<? extends BaseVariantOutputData> variantData) {
        Task assembleTask = project.tasks.
                create("assemble${variantData.variantConfiguration.fullName.capitalize()}")
        assembleTask.description = "Assembles the ${variantData.description}."
        assembleTask.group = BUILD_GROUP
        return assembleTask
    }

    public Copy getJacocoAgentTask() {
        if (jacocoAgentTask == null) {
            jacocoAgentTask = project.tasks.create("unzipJacocoAgent", Copy)
            jacocoAgentTask.from {
                project.configurations.getByName(JacocoPlugin.AGENT_CONFIGURATION_NAME).
                        collect { project.zipTree(it) }
            }
            jacocoAgentTask.include FILE_JACOCO_AGENT
            jacocoAgentTask.into "$project.buildDir/${FD_INTERMEDIATES}/jacoco"
        }

        return jacocoAgentTask
    }

    /**
     * creates a zip align. This does not use convention mapping,
     * and is meant to let other plugin create zip align tasks.
     *
     * @param name the name of the task
     * @param inputFile the input file
     * @param outputFile the output file
     *
     * @return the task
     */
    @NonNull
    ZipAlign createZipAlignTask(
            @NonNull String name,
            @NonNull File inputFile,
            @NonNull File outputFile) {
        // Add a task to zip align application package
        def zipAlignTask = project.tasks.create(name, ZipAlign)

        zipAlignTask.inputFile = inputFile
        zipAlignTask.outputFile = outputFile
        conventionMapping(zipAlignTask).map("zipAlignExe") {
            String path = androidBuilder.targetInfo?.buildTools?.getPath(ZIP_ALIGN)
            if (path != null) {
                return new File(path)
            }

            return null
        }

        return zipAlignTask
    }

    /**
     * Creates the proguarding task for the given Variant if necessary.
     * @param variantData the variant data.
     * @param testedVariantData optional. variant data representing the tested variant, null if the
     *                          variant is not a test variant
     * @return null if the proguard task was not created, otherwise the expected outputFile.
     */
    @Nullable
    public File maybeCreateProguardTasks(
            final @NonNull BaseVariantData<? extends BaseVariantOutputData> variantData,
            final @Nullable BaseVariantData<? extends BaseVariantOutputData> testedVariantData,
            final @NonNull PostCompilationData pcData) {

        if (!variantData.getVariantConfiguration().isMinifyEnabled()) {
            return null;
        }

        final VariantConfiguration variantConfig = variantData.variantConfiguration

        // use single output for now.
        final BaseVariantOutputData variantOutputData = variantData.outputs.get(0)

        def proguardTask = project.tasks.create(
                "proguard${variantData.variantConfiguration.fullName.capitalize()}",
                AndroidProGuardTask)

        if (testedVariantData != null) {
            proguardTask.dependsOn testedVariantData.obfuscationTask
        }

        variantData.obfuscationTask = proguardTask
        variantData.mappingFileProviderTask = proguardTask

        // --- Output File ---

        final File outFile = variantData instanceof LibraryVariantData ?
            project.file(
                    "${project.buildDir}/${FD_INTERMEDIATES}/$DIR_BUNDLES/${variantData.variantConfiguration.dirName}/classes.jar") :
            project.file(
                    "${project.buildDir}/${FD_INTERMEDIATES}/classes-proguard/${variantData.variantConfiguration.dirName}/classes.jar")
        variantData.obfuscatedClassesJar = outFile

        // --- Proguard Config ---

        if (testedVariantData != null) {
            // Don't remove any code in tested app.
            proguardTask.dontshrink()
            proguardTask.dontoptimize()

            // We can't call dontobfuscate, since that would make ProGuard ignore the mapping file.
            proguardTask.keep("class * {*;}")
            proguardTask.keep("interface * {*;}")
            proguardTask.keep("enum * {*;}")

            // Input the mapping from the tested app so that we can deal with obfuscated code.
            proguardTask.applymapping(testedVariantData.mappingFile)

            // All -dontwarn rules for test dependencies should go in here:
            proguardTask.configuration(
                    testedVariantData.variantConfiguration.testProguardFiles)
        } else {
            if (variantConfig.isTestCoverageEnabled()) {
                // when collecting coverage, don't remove the JaCoCo runtime
                proguardTask.keep("class com.vladium.** {*;}")
                proguardTask.keep("class org.jacoco.** {*;}")
                proguardTask.keep("interface org.jacoco.** {*;}")
                proguardTask.dontwarn("org.jacoco.**")
            }

            proguardTask.configuration {
                List<File> proguardFiles = variantConfig.getProguardFiles(true /*includeLibs*/,
                        [extension.getDefaultProguardFile(DEFAULT_PROGUARD_CONFIG_FILE)])

                proguardFiles + [variantOutputData.processResourcesTask.proguardOutputFile]
            }
        }

        // --- InJars / LibraryJars ---

        if (variantData instanceof LibraryVariantData) {
            String packageName = variantConfig.getPackageFromManifest()
            if (packageName == null) {
                throw new BuildException("Failed to read manifest", null)
            }
            packageName = packageName.replace('.', '/');

            // injar: the compilation output
            // exclude R files and such from output
            String exclude = '!' + packageName + "/R.class"
            exclude += (', !' + packageName + "/R\$*.class")
            if (!((LibraryExtension) getExtension()).packageBuildConfig) {
                exclude += (', !' + packageName + "/Manifest.class")
                exclude += (', !' + packageName + "/Manifest\$*.class")
                exclude += (', !' + packageName + "/BuildConfig.class")
            }
            proguardTask.injars(pcData.inputDir, filter: exclude)

            // include R files and such for compilation
            String include = exclude.replace('!', '')
            proguardTask.libraryjars(pcData.inputDir, filter: include)

            // injar: the local dependencies
            Closure inJars = {
                DependencyManager.getPackagedLocalJarFileList(variantData.variantDependency)
            }

            proguardTask.injars(inJars, filter: '!META-INF/MANIFEST.MF')

            // libjar: the library dependencies. In this case we take all the compile-scope
            // dependencies
            Closure libJars = {
                // get all the compiled jar.
                Set<File> compiledJars = androidBuilder.getCompileClasspath(variantConfig)
                // and remove local jar that are also packaged
                List<File> localJars =
                        DependencyManager.getPackagedLocalJarFileList(variantData.variantDependency)

                compiledJars.findAll({ !localJars.contains(it) })
            }

            proguardTask.libraryjars(libJars, filter: '!META-INF/MANIFEST.MF')

            // ensure local jars keep their package names
            proguardTask.keeppackagenames()
        } else {
            // injar: the compilation output
            proguardTask.injars(pcData.inputDir)

            // injar: the packaged dependencies
            proguardTask.injars(pcData.inputLibraries, filter: '!META-INF/MANIFEST.MF')

            // the provided-only jars as libraries.
            Closure libJars = {
                variantData.variantConfiguration.providedOnlyJars
            }

            proguardTask.libraryjars(libJars)
        }

        // libraryJars: the runtime jars. Do this in doFirst since the boot classpath isn't
        // available until the SDK is loaded in the prebuild task
        proguardTask.doFirst {
            for (String runtimeJar : androidBuilder.getBootClasspathAsStrings()) {
                proguardTask.libraryjars(runtimeJar)
            }
        }

        if (testedVariantData != null) {
            // input the tested app as library
            proguardTask.libraryjars(testedVariantData.javaCompileTask.destinationDir)
            // including its dependencies
            Closure testedPackagedJars = {
                androidBuilder.getPackagedJars(testedVariantData.variantConfiguration)
            }

            proguardTask.libraryjars(testedPackagedJars, filter: '!META-INF/MANIFEST.MF')
        }

        // --- Out files ---

        proguardTask.outjars(outFile)

        final File proguardOut = project.file(
                "${project.buildDir}/${FD_OUTPUTS}/mapping/${variantData.variantConfiguration.dirName}")

        proguardTask.dump(new File(proguardOut, "dump.txt"))
        proguardTask.printseeds(new File(proguardOut, "seeds.txt"))
        proguardTask.printusage(new File(proguardOut, "usage.txt"))
        proguardTask.printmapping(new File(proguardOut, "mapping.txt"))

        // proguard doesn't verify that the seed/mapping/usage folders exist and will fail
        // if they don't so create them.
        proguardTask.doFirst {
            proguardOut.mkdirs()
        }

        // update dependency.
        optionalDependsOn(proguardTask, pcData.classGeneratingTask)
        optionalDependsOn(proguardTask, pcData.libraryGeneratingTask)
        pcData.libraryGeneratingTask = [proguardTask]
        pcData.classGeneratingTask = [proguardTask]

        // Update the inputs
        return outFile;
    }

    public void createReportTasks(
            List<BaseVariantData<? extends BaseVariantOutputData>> variantDataList) {
        def dependencyReportTask = project.tasks.create("androidDependencies", DependencyReportTask)
        dependencyReportTask.setDescription("Displays the Android dependencies of the project.")
        dependencyReportTask.setVariants(variantDataList)
        dependencyReportTask.setGroup(ANDROID_GROUP)

        def signingReportTask = project.tasks.create("signingReport", SigningReportTask)
        signingReportTask.setDescription("Displays the signing info for each variant.")
        signingReportTask.setVariants(variantDataList)
        signingReportTask.setGroup(ANDROID_GROUP)
    }

    public void createAnchorTasks(
            @NonNull BaseVariantData<? extends BaseVariantOutputData> variantData) {
        createPreBuildTasks(variantData)

        // also create sourceGenTask
        variantData.sourceGenTask = project.tasks.create(
                "generate${variantData.variantConfiguration.fullName.capitalize()}Sources")
        // and resGenTask
        variantData.resourceGenTask = project.tasks.create(
                "generate${variantData.variantConfiguration.fullName.capitalize()}Resources")
        variantData.assetGenTask = project.tasks.create(
                "generate${variantData.variantConfiguration.fullName.capitalize()}Assets")
        // and compile task
        createCompileAnchorTask(variantData)
    }

    private void createPreBuildTasks(BaseVariantData<? extends BaseVariantOutputData> variantData) {
        variantData.preBuildTask = project.tasks.create(
                "pre${variantData.variantConfiguration.fullName.capitalize()}Build")
        variantData.preBuildTask.dependsOn MAIN_PREBUILD

        def prepareDependenciesTask = project.tasks.create(
                "prepare${variantData.variantConfiguration.fullName.capitalize()}Dependencies",
                PrepareDependenciesTask)

        variantData.prepareDependenciesTask = prepareDependenciesTask
        prepareDependenciesTask.dependsOn variantData.preBuildTask

        prepareDependenciesTask.androidBuilder = androidBuilder
        prepareDependenciesTask.variant = variantData

        // for all libraries required by the configurations of this variant, make this task
        // depend on all the tasks preparing these libraries.
        VariantDependencies configurationDependencies = variantData.variantDependency
        prepareDependenciesTask.addChecker(configurationDependencies.checker)

        for (LibraryDependencyImpl lib : configurationDependencies.libraries) {
            dependencyManager.addDependencyToPrepareTask(variantData, prepareDependenciesTask, lib)
        }
    }

    private void createCompileAnchorTask(
            BaseVariantData<? extends BaseVariantOutputData> variantData) {
        variantData.compileTask = project.tasks.create(
                "compile${variantData.variantConfiguration.fullName.capitalize()}Sources")
        variantData.compileTask.group = BUILD_GROUP

        variantData.assembleVariantTask.dependsOn variantData.compileTask
    }

    public void createCheckManifestTask(
            @NonNull BaseVariantData<? extends BaseVariantOutputData> variantData) {
        String name = variantData.variantConfiguration.fullName
        variantData.checkManifestTask = project.tasks.create(
                "check${name.capitalize()}Manifest",
                CheckManifest)
        variantData.checkManifestTask.dependsOn variantData.preBuildTask

        variantData.prepareDependenciesTask.dependsOn variantData.checkManifestTask

        variantData.checkManifestTask.variantName = name
        conventionMapping(variantData.checkManifestTask).map("manifest") {
            variantData.variantConfiguration.getDefaultSourceSet().manifestFile
        }
    }

    public static void optionalDependsOn(@NonNull AndroidTask main, TaskFactory taskFactory, Task... dependencies) {
        for (Task dependency : dependencies) {
            if (dependency != null) {
                main.dependsOn(taskFactory, dependency)
            }
        }
    }

    public static void optionalDependsOn(@NonNull Task main, Task... dependencies) {
        for (Task dependency : dependencies) {
            if (dependency != null) {
                main.dependsOn dependency
            }
        }
    }

    public static void optionalDependsOn(@NonNull Task main, @NonNull List<?> dependencies) {
        for (Object dependency : dependencies) {
            if (dependency != null) {
                main.dependsOn dependency
            }
        }
    }

    @NonNull
    private List<ManifestDependencyImpl> getManifestDependencies(
            List<LibraryDependency> libraries) {

        List<ManifestDependencyImpl> list = Lists.newArrayListWithCapacity(libraries.size())

        for (LibraryDependency lib : libraries) {
            // get the dependencies
            List<ManifestDependencyImpl> children = getManifestDependencies(lib.dependencies)
            list.add(new ManifestDependencyImpl(lib.getName(), lib.manifest, children))
        }

        return list
    }

    @NonNull
    protected Logger getLogger() {
        return logger
    }

    @NonNull
    protected static List<SymbolFileProviderImpl> getTextSymbolDependencies(
            List<LibraryDependency> libraries) {

        List<SymbolFileProviderImpl> list = Lists.newArrayListWithCapacity(libraries.size())

        for (LibraryDependency lib : libraries) {
            list.add(new SymbolFileProviderImpl(lib.manifest, lib.symbolFile))
        }

        return list
    }

    protected VariantScope createVariantScope(BaseVariantData variantData) {
        return new VariantScope(
                globalScope,
                variantData,
                getNdkBuildable(variantData),
                getNdkOutputDirectories(variantData));
    }
}
