/* * Copyright (C) 2012 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.builder.core; import com.android.annotations.NonNull; import com.android.annotations.Nullable; import com.android.builder.internal.BaseConfigImpl; import com.android.builder.model.ApiVersion; import com.android.builder.model.ProductFlavor; import com.android.builder.model.SigningConfig; import com.google.common.base.Objects; import com.google.common.collect.Sets; import java.util.Arrays; import java.util.Collection; import java.util.Set; /** * The configuration of a product flavor. * * This is also used to describe the default configuration of all builds, even those that * do not contain any flavors. */ public class DefaultProductFlavor extends BaseConfigImpl implements ProductFlavor { private static final long serialVersionUID = 1L; private final String mName; private ApiVersion mMinSdkVersion; private ApiVersion mTargetSdkVersion; private Integer mMaxSdkVersion; private Integer mRenderscriptTargetApi; private Boolean mRenderscriptSupportModeEnabled; private Boolean mRenderscriptNdkModeEnabled; private Integer mVersionCode; private String mVersionName; private String mApplicationId; private String mTestApplicationId; private String mTestInstrumentationRunner; private Boolean mTestHandleProfiling; private Boolean mTestFunctionalTest; private SigningConfig mSigningConfig; private Set<String> mResourceConfiguration; /** * Creates a ProductFlavor with a given name. * * Names can be important when dealing with flavor groups. * @param name the name of the flavor. * * @see BuilderConstants#MAIN */ public DefaultProductFlavor(@NonNull String name) { mName = name; } @Override @NonNull public String getName() { return mName; } /** * Sets the application id. * * @param applicationId the application id * @return the flavor object */ @NonNull public ProductFlavor setApplicationId(String applicationId) { mApplicationId = applicationId; return this; } @Override @Nullable public String getApplicationId() { return mApplicationId; } /** * Sets the version code. If the value is -1, it is considered not set. * * @param versionCode the version code * @return the flavor object */ @NonNull public ProductFlavor setVersionCode(Integer versionCode) { mVersionCode = versionCode; return this; } @Override @Nullable public Integer getVersionCode() { return mVersionCode; } /** * Sets the version name. * * @param versionName the version name * @return the flavor object */ @NonNull public ProductFlavor setVersionName(String versionName) { mVersionName = versionName; return this; } @Override @Nullable public String getVersionName() { return mVersionName; } /** Sets the minSdkVersion to the given value. */ @NonNull public ProductFlavor setMinSdkVersion(ApiVersion minSdkVersion) { mMinSdkVersion = minSdkVersion; return this; } @Override public ApiVersion getMinSdkVersion() { return mMinSdkVersion; } /** Sets the targetSdkVersion to the given value. */ @NonNull public ProductFlavor setTargetSdkVersion(ApiVersion targetSdkVersion) { mTargetSdkVersion = targetSdkVersion; return this; } @Override public ApiVersion getTargetSdkVersion() { return mTargetSdkVersion; } @NonNull public ProductFlavor setMaxSdkVersion(Integer maxSdkVersion) { mMaxSdkVersion = maxSdkVersion; return this; } @Override public Integer getMaxSdkVersion() { return mMaxSdkVersion; } @Override @Nullable public Integer getRenderscriptTargetApi() { return mRenderscriptTargetApi; } /** Sets the renderscript target API to the given value. */ public void setRenderscriptTargetApi(Integer renderscriptTargetApi) { mRenderscriptTargetApi = renderscriptTargetApi; } @Override @Nullable public Boolean getRenderscriptSupportModeEnabled() { return mRenderscriptSupportModeEnabled; } /** * Sets whether the renderscript code should be compiled in support mode to make it compatible * with older versions of Android. */ public ProductFlavor setRenderscriptSupportModeEnabled(Boolean renderscriptSupportMode) { mRenderscriptSupportModeEnabled = renderscriptSupportMode; return this; } @Override @Nullable public Boolean getRenderscriptNdkModeEnabled() { return mRenderscriptNdkModeEnabled; } /** Sets whether the renderscript code should be compiled to generate C/C++ bindings. */ public ProductFlavor setRenderscriptNdkModeEnabled(Boolean renderscriptNdkMode) { mRenderscriptNdkModeEnabled = renderscriptNdkMode; return this; } /** Sets the test package name. */ @NonNull public ProductFlavor setTestApplicationId(String applicationId) { mTestApplicationId = applicationId; return this; } @Override @Nullable public String getTestApplicationId() { return mTestApplicationId; } /** Sets the test instrumentation runner to the given value. */ @NonNull public ProductFlavor setTestInstrumentationRunner(String testInstrumentationRunner) { mTestInstrumentationRunner = testInstrumentationRunner; return this; } @Override @Nullable public String getTestInstrumentationRunner() { return mTestInstrumentationRunner; } @Override @Nullable public Boolean getTestHandleProfiling() { return mTestHandleProfiling; } @NonNull public ProductFlavor setTestHandleProfiling(boolean handleProfiling) { mTestHandleProfiling = handleProfiling; return this; } @Override @Nullable public Boolean getTestFunctionalTest() { return mTestFunctionalTest; } @NonNull public ProductFlavor setTestFunctionalTest(boolean functionalTest) { mTestFunctionalTest = functionalTest; return this; } @Override @Nullable public SigningConfig getSigningConfig() { return mSigningConfig; } /** Sets the signing configuration. e.g.: {@code signingConfig signingConfigs.myConfig} */ @NonNull public ProductFlavor setSigningConfig(SigningConfig signingConfig) { mSigningConfig = signingConfig; return this; } public void addResourceConfiguration(@NonNull String configuration) { if (mResourceConfiguration == null) { mResourceConfiguration = Sets.newHashSet(); } mResourceConfiguration.add(configuration); } public void addResourceConfigurations(@NonNull String... configurations) { if (mResourceConfiguration == null) { mResourceConfiguration = Sets.newHashSet(); } mResourceConfiguration.addAll(Arrays.asList(configurations)); } public void addResourceConfigurations(@NonNull Collection<String> configurations) { if (mResourceConfiguration == null) { mResourceConfiguration = Sets.newHashSet(); } mResourceConfiguration.addAll(configurations); } @NonNull @Override public Collection<String> getResourceConfigurations() { if (mResourceConfiguration == null) { mResourceConfiguration = Sets.newHashSet(); } return mResourceConfiguration; } /** * Merges two flavors on top of one another and returns a new object with the result. * * The behavior is that if a value is present in the overlay, then it is used, otherwise * we use the value from the base. * * @param base the flavor to merge on top of * @param overlay the flavor to apply on top of the base. * * @return a new ProductFlavor that represents the merge. */ @NonNull static ProductFlavor mergeFlavors(@NonNull ProductFlavor base, @NonNull ProductFlavor overlay) { DefaultProductFlavor flavor = new DefaultProductFlavor(""); flavor.mMinSdkVersion = chooseNotNull( overlay.getMinSdkVersion(), base.getMinSdkVersion()); flavor.mTargetSdkVersion = chooseNotNull( overlay.getTargetSdkVersion(), base.getTargetSdkVersion()); flavor.mMaxSdkVersion = chooseNotNull( overlay.getMaxSdkVersion(), base.getMaxSdkVersion()); flavor.mRenderscriptTargetApi = chooseNotNull( overlay.getRenderscriptTargetApi(), base.getRenderscriptTargetApi()); flavor.mRenderscriptSupportModeEnabled = chooseNotNull( overlay.getRenderscriptSupportModeEnabled(), base.getRenderscriptSupportModeEnabled()); flavor.mRenderscriptNdkModeEnabled = chooseNotNull( overlay.getRenderscriptNdkModeEnabled(), base.getRenderscriptNdkModeEnabled()); flavor.mVersionCode = chooseNotNull(overlay.getVersionCode(), base.getVersionCode()); flavor.mVersionName = chooseNotNull(overlay.getVersionName(), base.getVersionName()); flavor.mApplicationId = chooseNotNull(overlay.getApplicationId(), base.getApplicationId()); flavor.mTestApplicationId = chooseNotNull( overlay.getTestApplicationId(), base.getTestApplicationId()); flavor.mTestInstrumentationRunner = chooseNotNull( overlay.getTestInstrumentationRunner(), base.getTestInstrumentationRunner()); flavor.mTestHandleProfiling = chooseNotNull( overlay.getTestHandleProfiling(), base.getTestHandleProfiling()); flavor.mTestFunctionalTest = chooseNotNull( overlay.getTestFunctionalTest(), base.getTestFunctionalTest()); flavor.mSigningConfig = chooseNotNull( overlay.getSigningConfig(), base.getSigningConfig()); flavor.addResourceConfigurations(base.getResourceConfigurations()); flavor.addResourceConfigurations(overlay.getResourceConfigurations()); flavor.addManifestPlaceHolders(base.getManifestPlaceholders()); flavor.addManifestPlaceHolders(overlay.getManifestPlaceholders()); flavor.addResValues(base.getResValues()); flavor.addResValues(overlay.getResValues()); flavor.addBuildConfigFields(base.getBuildConfigFields()); flavor.addBuildConfigFields(overlay.getBuildConfigFields()); flavor.setMultiDexEnabled(chooseNotNull( overlay.getMultiDexEnabled(), base.getMultiDexEnabled())); flavor.setMultiDexKeepFile(chooseNotNull( overlay.getMultiDexKeepFile(), base.getMultiDexKeepFile())); flavor.setMultiDexKeepProguard(chooseNotNull( overlay.getMultiDexKeepProguard(), base.getMultiDexKeepProguard())); return flavor; } /** * Clone a given product flavor. * * @param productFlavor the flavor to clone. * * @return a new instance that is a clone of the flavor. */ @NonNull static ProductFlavor clone(@NonNull ProductFlavor productFlavor) { DefaultProductFlavor flavor = new DefaultProductFlavor(productFlavor.getName()); flavor._initWith(productFlavor); flavor.mMinSdkVersion = productFlavor.getMinSdkVersion(); flavor.mTargetSdkVersion = productFlavor.getTargetSdkVersion(); flavor.mMaxSdkVersion = productFlavor.getMaxSdkVersion(); flavor.mRenderscriptTargetApi = productFlavor.getRenderscriptTargetApi(); flavor.mRenderscriptSupportModeEnabled = productFlavor.getRenderscriptSupportModeEnabled(); flavor.mRenderscriptNdkModeEnabled = productFlavor.getRenderscriptNdkModeEnabled(); flavor.mVersionCode = productFlavor.getVersionCode(); flavor.mVersionName = productFlavor.getVersionName(); flavor.mApplicationId = productFlavor.getApplicationId(); flavor.mTestApplicationId = productFlavor.getTestApplicationId(); flavor.mTestInstrumentationRunner = productFlavor.getTestInstrumentationRunner(); flavor.mTestHandleProfiling = productFlavor.getTestHandleProfiling(); flavor.mTestFunctionalTest = productFlavor.getTestFunctionalTest(); flavor.mSigningConfig = productFlavor.getSigningConfig(); flavor.addResourceConfigurations(productFlavor.getResourceConfigurations()); flavor.addManifestPlaceHolders(productFlavor.getManifestPlaceholders()); flavor.addResValues(productFlavor.getResValues()); flavor.addBuildConfigFields(productFlavor.getBuildConfigFields()); flavor.setMultiDexEnabled(productFlavor.getMultiDexEnabled()); flavor.setMultiDexKeepFile(productFlavor.getMultiDexKeepFile()); flavor.setMultiDexKeepProguard(productFlavor.getMultiDexKeepProguard()); return flavor; } private static <T> T chooseNotNull(T overlay, T base) { return overlay != null ? overlay : base; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } if (!super.equals(o)) { return false; } DefaultProductFlavor that = (DefaultProductFlavor) o; if (mApplicationId != null ? !mApplicationId.equals(that.mApplicationId) : that.mApplicationId != null) { return false; } if (mMaxSdkVersion != null ? !mMaxSdkVersion.equals(that.mMaxSdkVersion) : that.mMaxSdkVersion != null) { return false; } if (mMinSdkVersion != null ? !mMinSdkVersion.equals(that.mMinSdkVersion) : that.mMinSdkVersion != null) { return false; } if (!mName.equals(that.mName)) { return false; } if (mRenderscriptNdkModeEnabled != null ? !mRenderscriptNdkModeEnabled .equals(that.mRenderscriptNdkModeEnabled) : that.mRenderscriptNdkModeEnabled != null) { return false; } if (mRenderscriptSupportModeEnabled != null ? !mRenderscriptSupportModeEnabled .equals(that.mRenderscriptSupportModeEnabled) : that.mRenderscriptSupportModeEnabled != null) { return false; } if (mRenderscriptTargetApi != null ? !mRenderscriptTargetApi .equals(that.mRenderscriptTargetApi) : that.mRenderscriptTargetApi != null) { return false; } if (mResourceConfiguration != null ? !mResourceConfiguration .equals(that.mResourceConfiguration) : that.mResourceConfiguration != null) { return false; } if (mSigningConfig != null ? !mSigningConfig.equals(that.mSigningConfig) : that.mSigningConfig != null) { return false; } if (mTargetSdkVersion != null ? !mTargetSdkVersion.equals(that.mTargetSdkVersion) : that.mTargetSdkVersion != null) { return false; } if (mTestApplicationId != null ? !mTestApplicationId.equals(that.mTestApplicationId) : that.mTestApplicationId != null) { return false; } if (mTestFunctionalTest != null ? !mTestFunctionalTest.equals(that.mTestFunctionalTest) : that.mTestFunctionalTest != null) { return false; } if (mTestHandleProfiling != null ? !mTestHandleProfiling.equals(that.mTestHandleProfiling) : that.mTestHandleProfiling != null) { return false; } if (mTestInstrumentationRunner != null ? !mTestInstrumentationRunner .equals(that.mTestInstrumentationRunner) : that.mTestInstrumentationRunner != null) { return false; } if (mVersionCode != null ? !mVersionCode.equals(that.mVersionCode) : that.mVersionCode != null) { return false; } if (mVersionName != null ? !mVersionName.equals(that.mVersionName) : that.mVersionName != null) { return false; } return true; } @Override public int hashCode() { int result = super.hashCode(); result = 31 * result + mName.hashCode(); result = 31 * result + (mMinSdkVersion != null ? mMinSdkVersion.hashCode() : 0); result = 31 * result + (mTargetSdkVersion != null ? mTargetSdkVersion.hashCode() : 0); result = 31 * result + (mMaxSdkVersion != null ? mMaxSdkVersion.hashCode() : 0); result = 31 * result + (mRenderscriptTargetApi != null ? mRenderscriptTargetApi.hashCode() : 0); result = 31 * result + (mRenderscriptSupportModeEnabled != null ? mRenderscriptSupportModeEnabled .hashCode() : 0); result = 31 * result + (mRenderscriptNdkModeEnabled != null ? mRenderscriptNdkModeEnabled.hashCode() : 0); result = 31 * result + (mVersionCode != null ? mVersionCode.hashCode() : 0); result = 31 * result + (mVersionName != null ? mVersionName.hashCode() : 0); result = 31 * result + (mApplicationId != null ? mApplicationId.hashCode() : 0); result = 31 * result + (mTestApplicationId != null ? mTestApplicationId.hashCode() : 0); result = 31 * result + (mTestInstrumentationRunner != null ? mTestInstrumentationRunner .hashCode() : 0); result = 31 * result + (mTestHandleProfiling != null ? mTestHandleProfiling.hashCode() : 0); result = 31 * result + (mTestFunctionalTest != null ? mTestFunctionalTest.hashCode() : 0); result = 31 * result + (mSigningConfig != null ? mSigningConfig.hashCode() : 0); result = 31 * result + (mResourceConfiguration != null ? mResourceConfiguration.hashCode() : 0); return result; } @Override @NonNull public String toString() { return Objects.toStringHelper(this) .add("name", mName) .add("minSdkVersion", mMinSdkVersion) .add("targetSdkVersion", mTargetSdkVersion) .add("renderscriptTargetApi", mRenderscriptTargetApi) .add("renderscriptSupportModeEnabled", mRenderscriptSupportModeEnabled) .add("renderscriptNdkModeEnabled", mRenderscriptNdkModeEnabled) .add("versionCode", mVersionCode) .add("versionName", mVersionName) .add("applicationId", mApplicationId) .add("testApplicationId", mTestApplicationId) .add("testInstrumentationRunner", mTestInstrumentationRunner) .add("testHandleProfiling", mTestHandleProfiling) .add("testFunctionalTest", mTestFunctionalTest) .add("signingConfig", mSigningConfig) .add("resConfig", mResourceConfiguration) .add("mBuildConfigFields", getBuildConfigFields()) .add("mResValues", getResValues()) .add("mProguardFiles", getProguardFiles()) .add("mConsumerProguardFiles", getConsumerProguardFiles()) .add("mManifestPlaceholders", getManifestPlaceholders()) .toString(); } }