/* * 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.variant; import com.android.annotations.NonNull; import com.android.annotations.Nullable; import com.android.build.FilterData; import com.android.build.OutputFile; import com.android.build.gradle.BasePlugin; import com.android.build.gradle.api.BaseVariant; import com.android.build.gradle.api.BaseVariantOutput; import com.android.build.gradle.internal.BuildTypeData; import com.android.build.gradle.internal.ProductFlavorData; import com.android.build.gradle.internal.VariantModel; import com.android.build.gradle.internal.api.ReadOnlyObjectProvider; import com.android.build.gradle.internal.api.ApkVariantImpl; import com.android.build.gradle.internal.api.ApkVariantOutputImpl; import com.android.build.gradle.internal.api.ApplicationVariantImpl; import com.android.build.gradle.internal.core.GradleVariantConfiguration; import com.android.builder.core.VariantConfiguration; import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; import org.gradle.api.Task; import org.gradle.api.artifacts.Configuration; import java.io.File; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Set; /** */ public class ApplicationVariantFactory implements VariantFactory<ApplicationVariantData> { public static final String CONFIG_WEAR_APP = "wearApp"; @NonNull private final BasePlugin basePlugin; public ApplicationVariantFactory(@NonNull BasePlugin basePlugin) { this.basePlugin = basePlugin; } @Override @NonNull public ApplicationVariantData createVariantData( @NonNull GradleVariantConfiguration variantConfiguration, @NonNull Set<String> densities, @NonNull Set<String> abis, @NonNull Set<String> compatibleScreens) { ApplicationVariantData variant = new ApplicationVariantData(basePlugin, variantConfiguration); if (!densities.isEmpty()) { variant.setCompatibleScreens(compatibleScreens); } // create its outputs if (variant.getSplitHandlingPolicy() == BaseVariantData.SplitHandlingPolicy.PRE_21_POLICY) { // create its outputs for (String density : densities) { for (String abi : abis) { ImmutableList.Builder<FilterData> builder = ImmutableList.builder(); if (density != null) { builder.add(FilterData.Builder.build(OutputFile.DENSITY, density)); } if (abi != null) { builder.add(FilterData.Builder.build(OutputFile.ABI, abi)); } variant.createOutput( OutputFile.OutputType.FULL_SPLIT, builder.build()); } } } else { variant.createOutput(OutputFile.OutputType.MAIN, Collections.<FilterData>emptyList()); } return variant; } @Override @NonNull public BaseVariant createVariantApi( @NonNull BaseVariantData<? extends BaseVariantOutputData> variantData, @NonNull ReadOnlyObjectProvider readOnlyObjectProvider) { // create the base variant object. ApplicationVariantImpl variant = basePlugin.getInstantiator().newInstance( ApplicationVariantImpl.class, variantData, basePlugin, readOnlyObjectProvider); // now create the output objects createApkOutputApiObjects(basePlugin, variantData, variant); return variant; } public static void createApkOutputApiObjects( @NonNull BasePlugin basePlugin, @NonNull BaseVariantData<? extends BaseVariantOutputData> variantData, @NonNull ApkVariantImpl variant) { List<? extends BaseVariantOutputData> outputList = variantData.getOutputs(); List<BaseVariantOutput> apiOutputList = Lists.newArrayListWithCapacity(outputList.size()); for (BaseVariantOutputData variantOutputData : outputList) { ApkVariantOutputData apkOutput = (ApkVariantOutputData) variantOutputData; ApkVariantOutputImpl output = basePlugin.getInstantiator().newInstance( ApkVariantOutputImpl.class, apkOutput); apiOutputList.add(output); } variant.addOutputs(apiOutputList); } @NonNull @Override public VariantConfiguration.Type getVariantConfigurationType() { return VariantConfiguration.Type.DEFAULT; } @Override public boolean isLibrary() { return false; } /** * Creates the tasks for a given ApplicationVariantData. * @param variantData the non-null ApplicationVariantData. * @param assembleTask an optional assembleTask to be used. If null, a new one is created. */ @Override public void createTasks( @NonNull BaseVariantData<?> variantData, @Nullable Task assembleTask) { assert variantData instanceof ApplicationVariantData; ApplicationVariantData appVariantData = (ApplicationVariantData) variantData; basePlugin.createAnchorTasks(variantData); basePlugin.createCheckManifestTask(variantData); handleMicroApp(variantData); // Add a task to process the manifest(s) basePlugin.createMergeAppManifestsTask(variantData); // Add a task to create the res values basePlugin.createGenerateResValuesTask(variantData); // Add a task to compile renderscript files. basePlugin.createRenderscriptTask(variantData); // Add a task to merge the resource folders basePlugin.createMergeResourcesTask(variantData, true /*process9Patch*/); // Add a task to merge the asset folders basePlugin.createMergeAssetsTask(variantData, null /*default location*/, true /*includeDependencies*/); // Add a task to create the BuildConfig class basePlugin.createBuildConfigTask(variantData); // Add a task to process the Android Resources and generate source files basePlugin.createProcessResTask(variantData, true /*generateResourcePackage*/); // Add a task to process the java resources basePlugin.createProcessJavaResTask(variantData); basePlugin.createAidlTask(variantData, null /*parcelableDir*/); // Add a compile task if (variantData.getVariantConfiguration().getUseJack()) { basePlugin.createJackTask(appVariantData, null /*testedVariant*/); } else{ basePlugin.createCompileTask(variantData, null /*testedVariant*/); basePlugin.createPostCompilationTasks(appVariantData); } // Add NDK tasks if (!basePlugin.getExtension().getUseNewNativePlugin()) { basePlugin.createNdkTasks(variantData); } if (variantData.getSplitHandlingPolicy() == BaseVariantData.SplitHandlingPolicy.RELEASE_21_AND_AFTER_POLICY) { basePlugin.createPackageSplitResTask(appVariantData); } basePlugin.createPackagingTask(appVariantData, assembleTask, true /*publishApk*/); } @Override public void validateModel(VariantModel model){ // No additional checks for ApplicationVariantFactory, so just return. } private void handleMicroApp(@NonNull BaseVariantData<?> variantData) { Configuration config = basePlugin.getProject().getConfigurations().findByName( CONFIG_WEAR_APP); Set<File> file = config.getFiles(); int count = file.size(); if (count == 1) { if (variantData.getVariantConfiguration().getBuildType().isEmbedMicroApp()) { basePlugin.createGenerateMicroApkDataTask(variantData, config); } } else if (count > 1) { throw new RuntimeException( CONFIG_WEAR_APP + " configuration resolves to more than one apk."); } } }