/*
 * Copyright 2012-present Facebook, Inc.
 *
 * 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.facebook.buck.android;

import static com.facebook.buck.rules.BuildableProperties.Kind.ANDROID;
import static com.facebook.buck.rules.BuildableProperties.Kind.PACKAGING;

import com.android.common.SdkConstants;
import com.facebook.buck.android.FilterResourcesStep.ResourceFilter;
import com.facebook.buck.dalvik.ZipSplitter;
import com.facebook.buck.java.Classpaths;
import com.facebook.buck.java.HasClasspathEntries;
import com.facebook.buck.java.JavaLibraryRule;
import com.facebook.buck.java.Keystore;
import com.facebook.buck.model.BuildTarget;
import com.facebook.buck.model.BuildTargetPattern;
import com.facebook.buck.rules.AbstractBuildRuleBuilder;
import com.facebook.buck.rules.AbstractBuildRuleBuilderParams;
import com.facebook.buck.rules.BuildContext;
import com.facebook.buck.rules.BuildRule;
import com.facebook.buck.rules.BuildRuleParams;
import com.facebook.buck.rules.BuildRuleResolver;
import com.facebook.buck.rules.BuildRuleType;
import com.facebook.buck.rules.Buildable;
import com.facebook.buck.rules.BuildableContext;
import com.facebook.buck.rules.BuildableProperties;
import com.facebook.buck.rules.DoNotUseAbstractBuildable;
import com.facebook.buck.rules.InstallableBuildRule;
import com.facebook.buck.rules.RuleKey;
import com.facebook.buck.rules.SourcePath;
import com.facebook.buck.rules.SourcePaths;
import com.facebook.buck.shell.AbstractGenruleStep;
import com.facebook.buck.shell.EchoStep;
import com.facebook.buck.shell.SymlinkFilesIntoDirectoryStep;
import com.facebook.buck.step.ExecutionContext;
import com.facebook.buck.step.Step;
import com.facebook.buck.step.fs.CopyStep;
import com.facebook.buck.step.fs.MakeCleanDirectoryStep;
import com.facebook.buck.step.fs.MkdirAndSymlinkFileStep;
import com.facebook.buck.step.fs.MkdirStep;
import com.facebook.buck.util.BuckConstant;
import com.facebook.buck.util.DefaultDirectoryTraverser;
import com.facebook.buck.util.DirectoryTraversal;
import com.facebook.buck.util.DirectoryTraverser;
import com.facebook.buck.util.HumanReadableException;
import com.facebook.buck.util.MorePaths;
import com.facebook.buck.util.Optionals;
import com.facebook.buck.zip.RepackZipEntriesStep;
import com.facebook.buck.zip.ZipDirectoryWithMaxDeflateStep;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicates;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableBiMap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSetMultimap;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Iterables;
import com.google.common.io.Files;

import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.EnumSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.Nullable;

/**
 * <pre>
 * android_binary(
 *   name = 'messenger',
 *   manifest = 'AndroidManifest.xml',
 *   target = 'Google Inc.:Google APIs:16',
 *   deps = [
 *     '//src/com/facebook/messenger:messenger_library',
 *   ],
 * )
 * </pre>
 */
public class AndroidBinaryRule extends DoNotUseAbstractBuildable implements
    HasAndroidPlatformTarget, HasClasspathEntries, InstallableBuildRule {

  private final static BuildableProperties PROPERTIES = new BuildableProperties(ANDROID, PACKAGING);

  /**
   * The largest file size Froyo will deflate.
   */
  private final long FROYO_DEFLATE_LIMIT_BYTES = 1 << 20;

  /**
   * This list of package types is taken from the set of targets that the default build.xml provides
   * for Android projects.
   * <p>
   * Note: not all package types are supported. If unsupported, will be treated as "DEBUG".
   */
  static enum PackageType {
    DEBUG,
    INSTRUMENTED,
    RELEASE,
    TEST,
    ;

    /**
     * @return true if ProGuard should be used to obfuscate the output
     */
    private final boolean isBuildWithObfuscation() {
      return this == RELEASE;
    }

    private final boolean isCrunchPngFiles() {
      return this == RELEASE;
    }
  }

  static enum TargetCpuType {
    ARM,
    ARMV7,
    X86,
    MIPS,
  }

  static enum ResourceCompressionMode {
    DISABLED(/* isCompressResources */ false, /* isStoreStringsAsAssets */ false),
    ENABLED(/* isCompressResources */ true, /* isStoreStringsAsAssets */ false),
    ENABLED_WITH_STRINGS_AS_ASSETS(
      /* isCompressResources */ true,
      /* isStoreStringsAsAssets */ true),
    ;

    private final boolean isCompressResources;
    private final boolean isStoreStringsAsAssets;

    private ResourceCompressionMode(boolean isCompressResources, boolean isStoreStringsAsAssets) {
      this.isCompressResources = isCompressResources;
      this.isStoreStringsAsAssets = isStoreStringsAsAssets;
    }

    public boolean isCompressResources() {
      return isCompressResources;
    }

    public boolean isStoreStringsAsAssets() {
      return isStoreStringsAsAssets;
    }
  }

  private final SourcePath manifest;
  private final String target;
  private final ImmutableSortedSet<BuildRule> classpathDeps;
  private final Keystore keystore;
  private final PackageType packageType;
  private final ImmutableSortedSet<BuildRule> buildRulesToExcludeFromDex;
  private DexSplitMode dexSplitMode;
  private final boolean useAndroidProguardConfigWithOptimizations;
  private final Optional<SourcePath> proguardConfig;
  private final ResourceCompressionMode resourceCompressionMode;
  private final ImmutableSet<String> primaryDexSubstrings;
  private final long linearAllocHardLimit;

  /**
   * File that whitelists the class files that should be in the primary dex.
   * <p>
   * Values in this file must match JAR entries exactly, so they should contain path separators.
   * For example:
   * <pre>
   * com/google/common/collect/ImmutableSet.class
   * </pre>
   */
  private final Optional<SourcePath> primaryDexClassesFile;

  private final FilterResourcesStep.ResourceFilter resourceFilter;
  private final ImmutableSet<TargetCpuType> cpuFilters;
  private final ImmutableSet<IntermediateDexRule> preDexDeps;
  private final ImmutableSortedSet<BuildRule> preprocessJavaClassesDeps;
  private final Optional<String> preprocessJavaClassesBash;
  private final AndroidTransitiveDependencyGraph transitiveDependencyGraph;

  /** This path is guaranteed to end with a slash. */
  private final String outputGenDirectory;

  /**
   * @param target the Android platform version to target, e.g., "Google Inc.:Google APIs:16". You
   *     can find the list of valid values on your system by running
   *     {@code android list targets --compact}.
   */
  protected AndroidBinaryRule(
      BuildRuleParams buildRuleParams,
      SourcePath manifest,
      String target,
      ImmutableSortedSet<BuildRule> classpathDeps,
      Keystore keystore,
      PackageType packageType,
      Set<BuildRule> buildRulesToExcludeFromDex,
      DexSplitMode dexSplitMode,
      boolean useAndroidProguardConfigWithOptimizations,
      Optional<SourcePath> proguardConfig,
      ResourceCompressionMode resourceCompressionMode,
      Set<String> primaryDexSubstrings,
      long linearAllocHardLimit,
      Optional<SourcePath> primaryDexClassesFile,
      FilterResourcesStep.ResourceFilter resourceFilter,
      Set<TargetCpuType> cpuFilters,
      Set<IntermediateDexRule> preDexDeps,
      Set<BuildRule> preprocessJavaClassesDeps,
      Optional<String> preprocessJavaClassesBash) {
    super(buildRuleParams);
    this.manifest = Preconditions.checkNotNull(manifest);
    this.target = Preconditions.checkNotNull(target);
    this.classpathDeps = ImmutableSortedSet.copyOf(classpathDeps);
    this.keystore = Preconditions.checkNotNull(keystore);
    this.packageType = Preconditions.checkNotNull(packageType);
    this.buildRulesToExcludeFromDex = ImmutableSortedSet.copyOf(buildRulesToExcludeFromDex);
    this.dexSplitMode = Preconditions.checkNotNull(dexSplitMode);
    this.useAndroidProguardConfigWithOptimizations = useAndroidProguardConfigWithOptimizations;
    this.proguardConfig = Preconditions.checkNotNull(proguardConfig);
    this.resourceCompressionMode = Preconditions.checkNotNull(resourceCompressionMode);
    this.primaryDexSubstrings = ImmutableSet.copyOf(primaryDexSubstrings);
    this.linearAllocHardLimit = linearAllocHardLimit;
    this.primaryDexClassesFile = Preconditions.checkNotNull(primaryDexClassesFile);
    this.outputGenDirectory = String.format("%s/%s",
        BuckConstant.GEN_DIR,
        getBuildTarget().getBasePathWithSlash());
    this.resourceFilter = Preconditions.checkNotNull(resourceFilter);
    this.cpuFilters = ImmutableSet.copyOf(cpuFilters);
    this.preDexDeps = ImmutableSet.copyOf(preDexDeps);
    this.preprocessJavaClassesDeps = ImmutableSortedSet.copyOf(preprocessJavaClassesDeps);
    this.preprocessJavaClassesBash = Preconditions.checkNotNull(preprocessJavaClassesBash);
    this.transitiveDependencyGraph = new AndroidTransitiveDependencyGraph(this);
  }

  @Override
  public BuildRuleType getType() {
    return BuildRuleType.ANDROID_BINARY;
  }

  @Override
  public BuildableProperties getProperties() {
    return PROPERTIES;
  }

  @Override
  public String getAndroidPlatformTarget() {
    return target;
  }

  @Override
  public RuleKey.Builder appendToRuleKey(RuleKey.Builder builder) throws IOException {
    super.appendToRuleKey(builder)
        .set("manifest", manifest.asReference())
        .set("target", target)
        .set("keystore", keystore.getBuildTarget().getFullyQualifiedName())
        .setRuleNames("classpathDeps", classpathDeps)
        .set("packageType", packageType.toString())
        .set("buildRulesToExcludeFromDex", buildRulesToExcludeFromDex)
        .set("useAndroidProguardConfigWithOptimizations", useAndroidProguardConfigWithOptimizations)
        .set("proguardConfig", proguardConfig.transform(SourcePath.TO_REFERENCE))
        .set("resourceCompressionMode", resourceCompressionMode.toString())
        .set("primaryDexSubstrings", primaryDexSubstrings)
        .set("linearAllocHardLimit", linearAllocHardLimit)
        .set("primaryDexClassesFile", primaryDexClassesFile.transform(SourcePath.TO_REFERENCE))
        .set("resourceFilter", resourceFilter.getDescription())
        .set("cpuFilters", ImmutableSortedSet.copyOf(cpuFilters).toString())
        .set("preprocessJavaClassesBash", preprocessJavaClassesBash)
        .set("preprocessJavaClassesDeps", preprocessJavaClassesDeps);
    return dexSplitMode.appendToRuleKey("dexSplitMode", builder);
  }

  public ImmutableSortedSet<BuildRule> getBuildRulesToExcludeFromDex() {
    return buildRulesToExcludeFromDex;
  }

  public AndroidTransitiveDependencyGraph getTransitiveDependencyGraph() {
    return transitiveDependencyGraph;
  }

  public Optional<SourcePath> getProguardConfig() {
    return proguardConfig;
  }

  public boolean isRelease() {
    return packageType == PackageType.RELEASE;
  }

  private boolean isCompressResources(){
    return resourceCompressionMode.isCompressResources();
  }

  private boolean isStoreStringsAsAssets() {
    return resourceCompressionMode.isStoreStringsAsAssets();
  }

  public ResourceCompressionMode getResourceCompressionMode() {
    return resourceCompressionMode;
  }

  public boolean requiresResourceFilter() {
    return resourceFilter.isEnabled() || isStoreStringsAsAssets();
  }

  public FilterResourcesStep.ResourceFilter getResourceFilter() {
    return this.resourceFilter;
  }

  public ImmutableSet<TargetCpuType> getCpuFilters() {
    return this.cpuFilters;
  }

  public ImmutableSet<IntermediateDexRule> getPreDexDeps() {
    return preDexDeps;
  }

  public ImmutableSortedSet<BuildRule> getPreprocessJavaClassesDeps() {
    return preprocessJavaClassesDeps;
  }

  public Optional<String> getPreprocessJavaClassesBash() {
    return preprocessJavaClassesBash;
  }

  /**
   * Native libraries compiled for different CPU architectures are placed in the
   * respective ABI subdirectories, such as 'armeabi', 'armeabi-v7a', 'x86' and 'mips'.
   * This looks at the cpu filter and returns the correct subdirectory. If cpu filter is
   * not present or not supported, returns Optional.absent();
   */
  private static Optional<String> getAbiDirectoryComponent(TargetCpuType cpuType) {
    String component = null;
    if (cpuType.equals(TargetCpuType.ARM)) {
      component = SdkConstants.ABI_ARMEABI;
    } else if (cpuType.equals(TargetCpuType.ARMV7)) {
      component = SdkConstants.ABI_ARMEABI_V7A;
    } else if (cpuType.equals(TargetCpuType.X86)) {
      component = SdkConstants.ABI_INTEL_ATOM;
    } else if (cpuType.equals(TargetCpuType.MIPS)) {
      component = SdkConstants.ABI_MIPS;
    }
    return Optional.fromNullable(component);

  }

  @VisibleForTesting
  void copyNativeLibrary(String sourceDir,
      String destinationDir,
      ImmutableList.Builder<Step> steps) {
    Path sourceDirPath = Paths.get(sourceDir);
    Path destinationDirPath = Paths.get(destinationDir);

    if (getCpuFilters().isEmpty()) {
      steps.add(new CopyStep(sourceDirPath, destinationDirPath, true));
    } else {
      for (TargetCpuType cpuType: getCpuFilters()) {
        Optional<String> abiDirectoryComponent = getAbiDirectoryComponent(cpuType);
        Preconditions.checkState(abiDirectoryComponent.isPresent());

        final Path libSourceDir = sourceDirPath.resolve(abiDirectoryComponent.get());
        Path libDestinationDir = destinationDirPath.resolve(abiDirectoryComponent.get());

        final MkdirStep mkDirStep = new MkdirStep(libDestinationDir);
        final CopyStep copyStep = new CopyStep(libSourceDir, libDestinationDir, true);
        steps.add(new Step() {
          @Override
          public int execute(ExecutionContext context) {
            if (!context.getProjectFilesystem().exists(libSourceDir.toString())) {
              return 0;
            }
            if (mkDirStep.execute(context) == 0 && copyStep.execute(context) == 0) {
              return 0;
            }
            return 1;
          }

          @Override
          public String getShortName() {
            return "copy_native_libraries";
          }

          @Override
          public String getDescription(ExecutionContext context) {
            ImmutableList.Builder<String> stringBuilder = ImmutableList.builder();
            stringBuilder.add(String.format("[ -d %s ]", libSourceDir.toString()));
            stringBuilder.add(mkDirStep.getDescription(context));
            stringBuilder.add(copyStep.getDescription(context));
            return Joiner.on(" && ").join(stringBuilder.build());
          }
        });
      }
    }
  }

  /** The APK at this path is the final one that points to an APK that a user should install. */
  @Override
  public String getApkPath() {
    return getUnsignedApkPath().replaceAll("\\.unsigned\\.apk$", ".apk");
  }

  @Override
  public String getPathToOutputFile() {
    return getApkPath();
  }

  @Override
  public List<String> getInputsToCompareToOutput() {
    ImmutableList.Builder<SourcePath> sourcePaths = ImmutableList.builder();
    sourcePaths.add(manifest);

    Optionals.addIfPresent(proguardConfig, sourcePaths);

    ImmutableList.Builder<String> inputs = ImmutableList.builder();
    inputs.addAll(SourcePaths.filterInputsToCompareToOutput(sourcePaths.build()));
    return inputs.build();
  }

  /**
   * Sets up filtering of resources, images/drawables and strings in particular, based on build
   * rule parameters {@link #resourceFilter} and {@link #isStoreStringsAsAssets}.
   *
   * {@link com.facebook.buck.android.FilterResourcesStep.ResourceFilter} {@code resourceFilter}
   * determines which drawables end up in the APK (based on density - mdpi, hdpi etc), and also
   * whether higher density drawables get scaled down to the specified density (if not present).
   *
   * {@code isStoreStringsAsAssets} determines whether non-english string resources are packaged
   * separately as assets (and not bundled together into the {@code resources.arsc} file).
   */
  @VisibleForTesting
  FilterResourcesStep createFilterResourcesStep(Set<String> resourceDirectories) {
    ImmutableBiMap.Builder<String, String> filteredResourcesDirMapBuilder = ImmutableBiMap.builder();
    String resDestinationBasePath = getBinPath("__filtered__%s__");
    int count = 0;
    for (String resDir : resourceDirectories) {
      filteredResourcesDirMapBuilder.put(resDir,
          Paths.get(resDestinationBasePath, String.valueOf(count++)).toString());
    }

    ImmutableBiMap<String, String> resSourceToDestDirMap = filteredResourcesDirMapBuilder.build();
    FilterResourcesStep.Builder filterResourcesStepBuilder = FilterResourcesStep.builder()
        .setInResToOutResDirMap(resSourceToDestDirMap)
        .setResourceFilter(resourceFilter);

    if (isStoreStringsAsAssets()) {
      filterResourcesStepBuilder.enableStringsFilter();
    }

    return filterResourcesStepBuilder.build();
  }

  @Override
  public List<Step> getBuildSteps(BuildContext context, BuildableContext buildableContext) {
    ImmutableList.Builder<Step> steps = ImmutableList.builder();

    // Symlink the manifest to a path named AndroidManifest.xml. Do this before running any other
    // commands to ensure that it is available at the desired path.
    steps.add(new MkdirAndSymlinkFileStep(getManifest().resolve(context).toString(),
        getAndroidManifestXml()));

    final AndroidTransitiveDependencies transitiveDependencies = findTransitiveDependencies();

    final AndroidDexTransitiveDependencies dexTransitiveDependencies =
        findDexTransitiveDependencies();

    // Add the steps for the aapt_package command. This method returns data that the ApkBuilder
    // needs to create a final, unsigned APK.
    ResourceDirectoriesFromAapt resourceDirectoriesFromAapt = addAaptPackageSteps(steps,
        transitiveDependencies,
        dexTransitiveDependencies);

    // Create the .dex files and create the unsigned APK using ApkBuilder.
    addDxAndApkBuilderSteps(context,
        steps,
        transitiveDependencies,
        dexTransitiveDependencies,
        resourceDirectoriesFromAapt.resDirectories,
        resourceDirectoriesFromAapt.nativeLibraryDirectories,
        getResourceApkPath(),
        getUnsignedApkPath());

    // Sign the APK.
    String signedApkPath = getSignedApkPath();
    SignApkStep signApkStep = new SignApkStep(
        keystore.getPathToStore(),
        keystore.getPathToPropertiesFile(),
        getUnsignedApkPath(),
        signedApkPath);
    steps.add(signApkStep);

    String apkToAlign;

    // Optionally, compress the resources file in the .apk.
    if (this.isCompressResources()) {
      String compressedApkPath = getCompressedResourcesApkPath();
      apkToAlign = compressedApkPath;
      RepackZipEntriesStep arscComp = new RepackZipEntriesStep(
          signedApkPath,
          compressedApkPath,
          ImmutableSet.of("resources.arsc"));
      steps.add(arscComp);
    } else {
      apkToAlign = signedApkPath;
    }

    String apkPath = getApkPath();
    ZipalignStep zipalign = new ZipalignStep(apkToAlign, apkPath);
    steps.add(zipalign);

    // Inform the user where the APK can be found.
    EchoStep success = new EchoStep(
        String.format("built APK for %s at %s", getFullyQualifiedName(), apkPath));
    steps.add(success);

    return steps.build();
  }

  private ResourceDirectoriesFromAapt addAaptPackageSteps(ImmutableList.Builder<Step> steps,
      final AndroidTransitiveDependencies transitiveDependencies,
      final AndroidDexTransitiveDependencies dexTransitiveDependencies) {
    final Set<String> rDotJavaPackages = transitiveDependencies.rDotJavaPackages;
    final FilterResourcesStep filterResourcesStep;
    final ImmutableSet<String> resDirectories;
    if (requiresResourceFilter()) {
      filterResourcesStep = createFilterResourcesStep(transitiveDependencies.resDirectories);
      resDirectories = filterResourcesStep.getOutputResourceDirs();
      steps.add(filterResourcesStep);
    } else {
      filterResourcesStep = null;
      resDirectories = transitiveDependencies.resDirectories;
    }

    // Extract the resources from third-party jars.
    // TODO(mbolin): The results of this should be cached between runs.
    String extractedResourcesDir = getBinPath("__resources__%s__");
    steps.add(new MakeCleanDirectoryStep(extractedResourcesDir));
    steps.add(new ExtractResourcesStep(dexTransitiveDependencies.pathsToThirdPartyJars,
        extractedResourcesDir));

    // Create the R.java files. Their compiled versions must be included in classes.dex.
    // TODO(mbolin): Skip this step if the transitive set of AndroidResourceRules is cached.
    if (!resDirectories.isEmpty()) {
      UberRDotJavaUtil.generateRDotJavaFiles(resDirectories,
          rDotJavaPackages,
          getBuildTarget(),
          steps);

      if (isStoreStringsAsAssets()) {
        Path tmpStringsDirPath = getPathForTmpStringAssetsDirectory();
        steps.add(new MakeCleanDirectoryStep(tmpStringsDirPath));
        steps.add(new CompileStringsStep(
            filterResourcesStep,
            Paths.get(UberRDotJavaUtil.getPathToGeneratedRDotJavaSrcFiles(getBuildTarget())),
            tmpStringsDirPath));
      }
    }

    // Copy the transitive closure of files in assets to a single directory, if any.
    Step collectAssets = new Step() {
      @Override
      public int execute(ExecutionContext context) {
        // This must be done in a Command because the files and directories that are specified may
        // not exist at the time this Command is created because the previous Commands have not run
        // yet.
        ImmutableList.Builder<Step> commands = ImmutableList.builder();
        try {
          createAllAssetsDirectory(
              transitiveDependencies.assetsDirectories,
              commands,
              new DefaultDirectoryTraverser());
        } catch (IOException e) {
          context.logError(e, "Error creating all assets directory in %s.", getBuildTarget());
          return 1;
        }

        for (Step command : commands.build()) {
          int exitCode = command.execute(context);
          if (exitCode != 0) {
            throw new HumanReadableException("Error running " + command.getDescription(context));
          }
        }

        return 0;
      }

      @Override
      public String getShortName() {
        return "symlink_assets";
      }

      @Override
      public String getDescription(ExecutionContext context) {
        return getShortName();
      }
    };
    steps.add(collectAssets);

    // Copy the transitive closure of files in native_libs to a single directory, if any.
    ImmutableSet<String> nativeLibraryDirectories;
    if (!transitiveDependencies.nativeLibsDirectories.isEmpty()) {
      ImmutableSet.Builder<String> nativeLibraryDirectoriesBuilder = ImmutableSet.builder();
      String pathForNativeLibs = getPathForNativeLibs();
      String libSubdirectory = pathForNativeLibs + "/lib";
      nativeLibraryDirectoriesBuilder.add(libSubdirectory);
      steps.add(new MakeCleanDirectoryStep(libSubdirectory));
      for (String nativeLibDir : transitiveDependencies.nativeLibsDirectories) {
        copyNativeLibrary(nativeLibDir, libSubdirectory, steps);
      }
      nativeLibraryDirectories = nativeLibraryDirectoriesBuilder.build();
    } else {
      nativeLibraryDirectories = ImmutableSet.of();
    }

    Optional<String> assetsDirectory;
    if (transitiveDependencies.assetsDirectories.isEmpty()
        && transitiveDependencies.nativeLibAssetsDirectories.isEmpty()
        && !isStoreStringsAsAssets()) {
      assetsDirectory = Optional.absent();
    } else {
      assetsDirectory = Optional.of(getPathToAllAssetsDirectory());
    }

    if (!transitiveDependencies.nativeLibAssetsDirectories.isEmpty()) {
      String nativeLibAssetsDir = assetsDirectory.get() + "/lib";
      steps.add(new MakeCleanDirectoryStep(nativeLibAssetsDir));
      for (String nativeLibDir : transitiveDependencies.nativeLibAssetsDirectories) {
        copyNativeLibrary(nativeLibDir, nativeLibAssetsDir, steps);
      }
    }

    if (isStoreStringsAsAssets()) {
      Path stringAssetsDir = Paths.get(assetsDirectory.get()).resolve("strings");
      steps.add(new MakeCleanDirectoryStep(stringAssetsDir));
      steps.add(new CopyStep(
          getPathForTmpStringAssetsDirectory(),
          stringAssetsDir,
          /* shouldRecurse */ true));
    }

    steps.add(new MkdirStep(outputGenDirectory));

    if (!canSkipAaptResourcePackaging()) {
      AaptStep aaptCommand = new AaptStep(
          getAndroidManifestXml(),
          resDirectories,
          assetsDirectory,
          getResourceApkPath(),
          ImmutableSet.of(extractedResourcesDir),
          packageType.isCrunchPngFiles());
      steps.add(aaptCommand);
    }

    ResourceDirectoriesFromAapt resourceDirectoriesFromAapt = new ResourceDirectoriesFromAapt(
        resDirectories,
        nativeLibraryDirectories);
    return resourceDirectoriesFromAapt;
  }

  private static class ResourceDirectoriesFromAapt {
    final ImmutableSet<String> resDirectories;
    final ImmutableSet<String> nativeLibraryDirectories;
    public ResourceDirectoriesFromAapt(ImmutableSet<String> resDirectories,
        ImmutableSet<String> nativeLibraryDirectories) {
      this.resDirectories = resDirectories;
      this.nativeLibraryDirectories = nativeLibraryDirectories;
    }
  }

  private void addDxAndApkBuilderSteps(BuildContext context,
      ImmutableList.Builder<Step> steps,
      final AndroidTransitiveDependencies transitiveDependencies,
      final AndroidDexTransitiveDependencies dexTransitiveDependencies,
      ImmutableSet<String> resDirectories,
      ImmutableSet<String> nativeLibraryDirectories,
      String resourceApkPath,
      String unsignedApkPath) {
    // Execute preprocess_java_classes_binary, if appropriate.
    ImmutableSet<String> classpathEntriesToDex;
    if (preprocessJavaClassesBash.isPresent()) {
      // Symlink everything in dexTransitiveDependencies.classpathEntriesToDex to the input
      // directory. Expect parallel outputs in the output directory and update classpathEntriesToDex
      // to reflect that.
      final String preprocessJavaClassesInDir = getBinPath("java_classes_preprocess_in_%s");
      final String preprocessJavaClassesOutDir = getBinPath("java_classes_preprocess_out_%s");
      steps.add(new MakeCleanDirectoryStep(preprocessJavaClassesInDir));
      steps.add(new MakeCleanDirectoryStep(preprocessJavaClassesOutDir));
      steps.add(new SymlinkFilesIntoDirectoryStep(
          Paths.get("."),
          dexTransitiveDependencies.classpathEntriesToDex,
          Paths.get(preprocessJavaClassesInDir)
          ));
      classpathEntriesToDex = FluentIterable.from(dexTransitiveDependencies.classpathEntriesToDex)
          .transform(new Function<String, String>() {
            @Override
            public String apply(String classpathEntry) {
              return Paths.get(preprocessJavaClassesOutDir, classpathEntry).toString();
            }
          })
          .toSet();

      AbstractGenruleStep.CommandString commandString = new AbstractGenruleStep.CommandString(
          /* cmd */ Optional.<String>absent(),
          /* bash */ preprocessJavaClassesBash,
          /* cmdExe */ Optional.<String>absent());
      steps.add(new AbstractGenruleStep(this, commandString, preprocessJavaClassesDeps) {

        @Override
        protected void addEnvironmentVariables(
            ExecutionContext context,
            ImmutableMap.Builder<String, String> environmentVariablesBuilder) {
          environmentVariablesBuilder.put("IN_JARS_DIR", preprocessJavaClassesInDir);
          environmentVariablesBuilder.put("OUT_JARS_DIR", preprocessJavaClassesOutDir);
        }

      });

    } else {
      classpathEntriesToDex = dexTransitiveDependencies.classpathEntriesToDex;
    }

    // Execute proguard if desired (transforms input classpaths).
    if (packageType.isBuildWithObfuscation()) {
      classpathEntriesToDex = addProguardCommands(
          context,
          classpathEntriesToDex,
          transitiveDependencies.proguardConfigs,
          steps,
          resDirectories);
    }

    // Create the final DEX (or set of DEX files in the case of split dex).
    // The APK building command needs to take a directory of raw files, so we create a directory
    // that can only contain .dex files from this build rule.
    String dexDir = getBinPath(".dex/%s");
    steps.add(new MkdirStep(dexDir));
    String dexFile = String.format("%s/classes.dex", dexDir);

    // Create dex artifacts.
    ImmutableSet.Builder<String> secondaryDexDirectoriesBuilder = ImmutableSet.builder();
    if (preDexDeps.isEmpty()) {
      addDexingSteps(
          classpathEntriesToDex,
          secondaryDexDirectoriesBuilder,
          steps,
          dexFile,
          context.getSourcePathResolver());
    } else {
      Iterable<Path> filesToDex = FluentIterable.from(preDexDeps)
          .transform(
              new Function<IntermediateDexRule, Path>() {
                  @Override
                  @Nullable
                  public Path apply(IntermediateDexRule preDexDep) {
                    DexProducedFromJavaLibraryThatContainsClassFiles preDex = preDexDep
                        .getBuildable();
                    if (preDex.hasOutput()) {
                      return preDex.getPathToDex();
                    } else {
                      return null;
                    }
                  }
              })
          .filter(Predicates.notNull());

      // If this APK has Android resources, then the generated R.class files also need to be dexed.
      if (dexTransitiveDependencies.pathToCompiledRDotJavaFiles.isPresent()) {
        Path pathToCompiledRDotJavaFilesDirectory =
            dexTransitiveDependencies.pathToCompiledRDotJavaFiles.get();
        filesToDex = Iterables.concat(filesToDex,
            Collections.singleton(pathToCompiledRDotJavaFilesDirectory));
      }

      // This will combine the pre-dexed files and the R.class files into a single classes.dex file.
      steps.add(new DxStep(dexFile,
          filesToDex,
          /* options */ EnumSet.of(DxStep.Option.USE_CUSTOM_DX_IF_AVAILABLE)));
    }
    ImmutableSet<String> secondaryDexDirectories = secondaryDexDirectoriesBuilder.build();


    // Due to limitations of Froyo, we need to ensure that all secondary zip files are STORED in
    // the final APK, not DEFLATED.  The only way to ensure this with ApkBuilder is to zip up the
    // the files properly and then add the zip files to the apk.
    ImmutableSet.Builder<String> secondaryDexZips = ImmutableSet.builder();
    for (String secondaryDexDirectory : secondaryDexDirectories) {
      // String the trailing slash from the directory name and add the zip extension.
      String zipFile = secondaryDexDirectory.replaceAll("/$", "") + ".zip";

      secondaryDexZips.add(zipFile);
      steps.add(new ZipDirectoryWithMaxDeflateStep(secondaryDexDirectory,
          zipFile,
          FROYO_DEFLATE_LIMIT_BYTES));
    }

    ApkBuilderStep apkBuilderCommand = new ApkBuilderStep(
        resourceApkPath,
        unsignedApkPath,
        dexFile,
        ImmutableSet.<String>of(),
        nativeLibraryDirectories,
        secondaryDexZips.build(),
        false);
    steps.add(apkBuilderCommand);
  }

  /**
   * Given a set of assets directories to include in the APK (which may be empty), return the path
   * to the directory that contains the union of all the assets. If any work needs to be done to
   * create such a directory, the appropriate commands should be added to the {@code commands}
   * list builder.
   * <p>
   * If there are no assets (i.e., {@code assetsDirectories} is empty), then the return value will
   * be an empty {@link Optional}.
   */
  @VisibleForTesting
  Optional<String> createAllAssetsDirectory(
      Set<String> assetsDirectories,
      ImmutableList.Builder<Step> steps,
      DirectoryTraverser traverser) throws IOException {
    if (assetsDirectories.isEmpty()) {
      return Optional.absent();
    }

    // Due to a limitation of aapt, only one assets directory can be specified, so if multiple are
    // specified in Buck, then all of the contents must be symlinked to a single directory.
    String destination = getPathToAllAssetsDirectory();
    steps.add(new MakeCleanDirectoryStep(destination));
    final ImmutableMap.Builder<String, File> allAssets = ImmutableMap.builder();

    File destinationDirectory = new File(destination);
    for (String assetsDirectory : assetsDirectories) {
      traverser.traverse(new DirectoryTraversal(new File(assetsDirectory)) {
        @Override
        public void visit(File file, String relativePath) {
          allAssets.put(relativePath, file);
        }
      });
    }

    for (Map.Entry<String, File> entry : allAssets.build().entrySet()) {
      steps.add(new MkdirAndSymlinkFileStep(
          MorePaths.newPathInstance(entry.getValue()).toString(),
          MorePaths.newPathInstance(destinationDirectory + "/" + entry.getKey()).toString()));
    }

    return Optional.of(destination);
  }

  public AndroidTransitiveDependencies findTransitiveDependencies() {
    return getTransitiveDependencyGraph().findDependencies(getAndroidResourceDepsInternal());
  }

  public AndroidDexTransitiveDependencies findDexTransitiveDependencies() {
    return getTransitiveDependencyGraph().findDexDependencies(
        getAndroidResourceDepsInternal(),
        buildRulesToExcludeFromDex);
  }

  /**
   * @return a list of {@link HasAndroidResourceDeps}s that should be passed, in order, to {@code aapt}
   *     when generating the {@code R.java} files for this APK.
   */
  protected ImmutableList<HasAndroidResourceDeps> getAndroidResourceDepsInternal() {
    return UberRDotJavaUtil.getAndroidResourceDeps(this);
  }

  private boolean canSkipAaptResourcePackaging() {
    // TODO(mbolin): Create a RuleKey for resources only and use it to determine the value of this
    // boolean. Whether the resources have not changed since the last build run is irrelevant
    // because this AndroidBinary may not have been written as part of the last build run.
    return false;
  }

  /**
   * This is the path to the directory for generated files related to ProGuard. Ultimately, it
   * should include:
   * <ul>
   *   <li>proguard.txt
   *   <li>dump.txt
   *   <li>seeds.txt
   *   <li>usage.txt
   *   <li>mapping.txt
   *   <li>obfuscated.jar
   * </ul>
   * @return path to directory (will not include trailing slash)
   */
  @VisibleForTesting
  Path getPathForProGuardDirectory() {
    return MorePaths.newPathInstance(
        String.format("%s/%s.proguard/%s",
        BuckConstant.GEN_DIR,
        getBuildTarget().getBasePathWithSlash(),
        getBuildTarget().getShortName()));
  }

  @VisibleForTesting
  String getPathToAllAssetsDirectory() {
    return getBinPath("__assets_%s__");
  }

  private Path getPathForTmpStringAssetsDirectory() {
    return Paths.get(getBinPath("__strings_%s__"));
  }

  /**
   * All native libs are copied to this directory before running aapt.
   */
  private String getPathForNativeLibs() {
    return getBinPath("__native_libs_%s__");
  }

  public Keystore getKeystore() {
    return keystore;
  }

  public String getResourceApkPath() {
    return String.format("%s%s.unsigned.ap_",
        outputGenDirectory,
        getBuildTarget().getShortName());
  }

  public String getUnsignedApkPath() {
    return String.format("%s%s.unsigned.apk",
        outputGenDirectory,
        getBuildTarget().getShortName());
  }

  /** The APK at this path will be signed, but not zipaligned. */
  private String getSignedApkPath() {
    return getUnsignedApkPath().replaceAll("\\.unsigned\\.apk$", ".signed.apk");
  }

  /** The APK at this path will have compressed resources, but will not be zipaligned. */
  private String getCompressedResourcesApkPath() {
    return getUnsignedApkPath().replaceAll("\\.unsigned\\.apk$", ".compressed.apk");
  }

  /**
   * Buck does not require the manifest to be named AndroidManifest.xml, but commands such as aapt
   * do. For this reason, we symlink the path to {@link #getManifest()} to the path returned by
   * this method, whose name is always "AndroidManifest.xml".
   * <p>
   * Therefore, commands created by this method should use this method instead of
   * {@link #getManifest()}.
   */
  private String getAndroidManifestXml() {
    return getBinPath("__manifest_%s__/AndroidManifest.xml");
  }

  /**
   * Return a path to a file in the buck-out/bin/ directory. {@code format} will be prepended with
   * the {@link BuckConstant#BIN_DIR} and the target base path, then formatted with the target
   * short name.
   * {@code format} should not start with a slash.
   */
  private String getBinPath(String format) {
    return String.format("%s/%s" + format,
        BuckConstant.BIN_DIR,
        getBuildTarget().getBasePathWithSlash(),
        getBuildTarget().getShortName());
  }

  @VisibleForTesting
  Path getProguardOutputFromInputClasspath(String classpathEntry) {
    // Hehe, this is so ridiculously fragile.
    Preconditions.checkArgument(classpathEntry.charAt(0) != '/',
        "Classpath entries should be relative rather than absolute paths: %s",
        classpathEntry);
    String obfuscatedName = Files.getNameWithoutExtension(classpathEntry) + "-obfuscated.jar";
    Path dirName = MorePaths.newPathInstance(new File(classpathEntry).getParent());
    Path outputJar = getPathForProGuardDirectory().resolve(dirName).resolve(obfuscatedName);
    return outputJar;
  }

  /**
   * @return the resulting set of ProGuarded classpath entries to dex.
   */
  @VisibleForTesting
  ImmutableSet<String> addProguardCommands(
      BuildContext context,
      Set<String> classpathEntriesToDex,
      Set<String> depsProguardConfigs,
      ImmutableList.Builder<Step> steps,
      Set<String> resDirectories) {
    final ImmutableSetMultimap<JavaLibraryRule, String> classpathEntriesMap =
        getTransitiveClasspathEntries();
    ImmutableSet.Builder<String> additionalLibraryJarsForProguardBuilder = ImmutableSet.builder();

    for (BuildRule buildRule : buildRulesToExcludeFromDex) {
      if (buildRule instanceof JavaLibraryRule) {
        additionalLibraryJarsForProguardBuilder.addAll(
            classpathEntriesMap.get((JavaLibraryRule)buildRule));
      }
    }

    // Clean out the directory for generated ProGuard files.
    Path proguardDirectory = getPathForProGuardDirectory();
    steps.add(new MakeCleanDirectoryStep(proguardDirectory));

    // Generate a file of ProGuard config options using aapt.
    String generatedProGuardConfig = proguardDirectory + "/proguard.txt";
    GenProGuardConfigStep genProGuardConfig = new GenProGuardConfigStep(
        getAndroidManifestXml(),
        resDirectories,
        generatedProGuardConfig);
    steps.add(genProGuardConfig);

    // Create list of proguard Configs for the app project and its dependencies
    ImmutableSet.Builder<String> proguardConfigsBuilder = ImmutableSet.builder();
    proguardConfigsBuilder.addAll(depsProguardConfigs);
    if (proguardConfig.isPresent()) {
      proguardConfigsBuilder.add(proguardConfig.get().resolve(context).toString());
    }

    // Transform our input classpath to a set of output locations for each input classpath.
    // TODO(devjasta): the output path we choose is the result of a slicing function against
    // input classpath. This is fragile and should be replaced with knowledge of the BuildTarget.
    final ImmutableMap<String, String> inputOutputEntries = FluentIterable
        .from(classpathEntriesToDex)
        .toMap(new Function<String, String>() {
          @Override
          public String apply(String classpathEntry) {
            return getProguardOutputFromInputClasspath(classpathEntry).toString();
          }
        });

    // Run ProGuard on the classpath entries.
    // TODO: ProGuardObfuscateStep's final argument should be a Path
    Step obfuscateCommand = ProGuardObfuscateStep.create(
        generatedProGuardConfig,
        proguardConfigsBuilder.build(),
        useAndroidProguardConfigWithOptimizations,
        inputOutputEntries,
        additionalLibraryJarsForProguardBuilder.build(),
        proguardDirectory.toString());
    steps.add(obfuscateCommand);

    // Apply the transformed inputs to the classpath (this will modify deps.classpathEntriesToDex
    // so that we're now dexing the proguarded artifacts).
    return ImmutableSet.copyOf(inputOutputEntries.values());
  }

  /**
   * Create dex artifacts for all of the individual directories of compiled .class files (or
   * the obfuscated jar files if proguard is used).  If split dex is used, multiple dex artifacts
   * will be produced.
   *
   * @param classpathEntriesToDex Full set of classpath entries that must make
   *     their way into the final APK structure (but not necessarily into the
   *     primary dex).
   * @param steps List of steps to add to.
   * @param primaryDexPath Output path for the primary dex file.
   */
  @VisibleForTesting
  void addDexingSteps(
      Set<String> classpathEntriesToDex,
      ImmutableSet.Builder<String> secondaryDexDirectories,
      ImmutableList.Builder<Step> steps,
      String primaryDexPath,
      Function<SourcePath, Path> sourcePathResolver) {
    final Set<String> primaryInputsToDex;
    final Optional<String> secondaryDexDir;
    final Optional<String> secondaryInputsDir;

    if (shouldSplitDex()) {
      Optional<Path> proguardMappingFile = Optional.absent();
      if (packageType.isBuildWithObfuscation()) {
        proguardMappingFile = Optional.of(getPathForProGuardDirectory().resolve("mapping.txt"));
      }

      // DexLibLoader expects that metadata.txt and secondary jar files are under this dir
      // in assets.
      String magicSecondaryDexSubdir = "assets/secondary-program-dex-jars";

      // Intermediate directory holding the primary split-zip jar.
      String splitZipDir = getBinPath("__%s_split_zip__");
      steps.add(new MakeCleanDirectoryStep(splitZipDir));
      String primaryJarPath = splitZipDir + "/primary.jar";

      String secondaryJarMetaDirParent = splitZipDir + "/secondary_meta/";
      String secondaryJarMetaDir = secondaryJarMetaDirParent + magicSecondaryDexSubdir;
      steps.add(new MakeCleanDirectoryStep(secondaryJarMetaDir));
      String secondaryJarMeta = secondaryJarMetaDir + "/metadata.txt";

      // Intermediate directory holding _ONLY_ the secondary split-zip jar files.  This is
      // important because SmartDexingCommand will try to dx every entry in this directory.  It
      // does this because it's impossible to know what outputs split-zip will generate until it
      // runs.
      String secondaryZipDir = getBinPath("__%s_secondary_zip__");
      steps.add(new MakeCleanDirectoryStep(secondaryZipDir));

      // Run the split-zip command which is responsible for dividing the large set of input
      // classpaths into a more compact set of jar files such that no one jar file when dexed will
      // yield a dex artifact too large for dexopt or the dx method limit to handle.
      String zipSplitReportDir = getBinPath("__%s_split_zip_report__");
      steps.add(new MakeCleanDirectoryStep(zipSplitReportDir));
      SplitZipStep splitZipCommand = new SplitZipStep(
          classpathEntriesToDex,
          secondaryJarMeta,
          primaryJarPath,
          secondaryZipDir,
          "secondary-%d.jar",
          proguardMappingFile,
          primaryDexSubstrings,
          primaryDexClassesFile.transform(sourcePathResolver),
          dexSplitMode.getDexSplitStrategy(),
          dexSplitMode.getDexStore(),
          zipSplitReportDir,
          dexSplitMode.useLinearAllocSplitDex(),
          linearAllocHardLimit);
      steps.add(splitZipCommand);

      // Add the secondary dex directory that has yet to be created, but will be by the
      // smart dexing command.  Smart dex will handle "cleaning" this directory properly.
      String secondaryDexParentDir = getBinPath("__%s_secondary_dex__/");
      secondaryDexDir = Optional.of(secondaryDexParentDir + magicSecondaryDexSubdir);
      steps.add(new MkdirStep(secondaryDexDir.get()));

      secondaryDexDirectories.add(secondaryJarMetaDirParent);
      secondaryDexDirectories.add(secondaryDexParentDir);

      // Adjust smart-dex inputs for the split-zip case.
      primaryInputsToDex = ImmutableSet.of(primaryJarPath);
      secondaryInputsDir = Optional.of(secondaryZipDir);
    } else {
      // Simple case where our inputs are the natural classpath directories and we don't have
      // to worry about secondary jar/dex files.
      primaryInputsToDex = classpathEntriesToDex;
      secondaryDexDir = Optional.absent();
      secondaryInputsDir = Optional.absent();
    }

    // Stores checksum information from each invocation to intelligently decide when dx needs
    // to be re-run.
    Path successDir = Paths.get(getBinPath("__%s_smart_dex__/.success"));
    steps.add(new MkdirStep(successDir));

    // Add the smart dexing tool that is capable of avoiding the external dx invocation(s) if
    // it can be shown that the inputs have not changed.  It also parallelizes dx invocations
    // where applicable.
    //
    // Note that by not specifying the number of threads this command will use it will select an
    // optimal default regardless of the value of --num-threads.  This decision was made with the
    // assumption that --num-threads specifies the threading of build rule execution and does not
    // directly apply to the internal threading/parallelization details of various build commands
    // being executed.  For example, aapt is internally threaded by default when preprocessing
    // images.
    SmartDexingStep smartDexingCommand = new SmartDexingStep(
        primaryDexPath,
        primaryInputsToDex,
        secondaryDexDir,
        secondaryInputsDir,
        successDir,
        Optional.<Integer>absent(),
        dexSplitMode.getDexStore(),
        /* optimize */ PackageType.RELEASE.equals(packageType));
    steps.add(smartDexingCommand);
  }

  /**
   * @return the path to the AndroidManifest.xml. Note that this file is not guaranteed to be named
   *     AndroidManifest.xml.
   */
  @Override
  public SourcePath getManifest() {
    return manifest;
  }

  String getTarget() {
    return target;
  }

  boolean shouldSplitDex() {
    return dexSplitMode.isShouldSplitDex();
  }

  boolean isUseAndroidProguardConfigWithOptimizations() {
    return useAndroidProguardConfigWithOptimizations;
  }

  ImmutableSet<String> getPrimaryDexSubstrings() {
    return primaryDexSubstrings;
  }

  long getLinearAllocHardLimit() {
    return linearAllocHardLimit;
  }

  Optional<SourcePath> getPrimaryDexClassesFile() {
    return primaryDexClassesFile;
  }

  public ImmutableSortedSet<BuildRule> getClasspathDeps() {
    return classpathDeps;
  }

  @Override
  public ImmutableSetMultimap<JavaLibraryRule, String> getTransitiveClasspathEntries() {
    // This is used primarily for buck audit classpath.
    return Classpaths.getClasspathEntries(classpathDeps);
  }

  public static Builder newAndroidBinaryRuleBuilder(AbstractBuildRuleBuilderParams params) {
    return new Builder(params);
  }

  public static class Builder extends AbstractBuildRuleBuilder<AndroidBinaryRule> {
    private static final PackageType DEFAULT_PACKAGE_TYPE = PackageType.DEBUG;

    private SourcePath manifest;
    private String target;

    /** This should always be a subset of {@link #getDeps()}. */
    private ImmutableSet.Builder<BuildTarget> classpathDeps = ImmutableSet.builder();

    private BuildTarget keystoreTarget;
    private PackageType packageType = DEFAULT_PACKAGE_TYPE;
    private ImmutableSet.Builder<BuildTarget> buildRulesToExcludeFromDexBuilder =
        ImmutableSet.builder();
    private boolean disablePreDex = false;
    private DexSplitMode dexSplitMode = new DexSplitMode(
        /* shouldSplitDex */ false,
        ZipSplitter.DexSplitStrategy.MAXIMIZE_PRIMARY_DEX_SIZE,
        DexStore.JAR,
        /* useLinearAllocSplitDex */ false);
    private boolean useAndroidProguardConfigWithOptimizations = false;
    private Optional<SourcePath> proguardConfig = Optional.absent();
    private ResourceCompressionMode resourceCompressionMode = ResourceCompressionMode.DISABLED;
    private ImmutableSet.Builder<String> primaryDexSubstrings = ImmutableSet.builder();
    private long linearAllocHardLimit = 0;
    private Optional<SourcePath> primaryDexClassesFile = Optional.absent();
    private FilterResourcesStep.ResourceFilter resourceFilter =
        new FilterResourcesStep.ResourceFilter(ImmutableList.<String>of());
    private ImmutableSet.Builder<TargetCpuType> cpuFilters = ImmutableSet.builder();
    private ImmutableSet.Builder<BuildTarget> preprocessJavaClassesDeps = ImmutableSet.builder();
    private Optional<String> preprocessJavaClassesBash = Optional.absent();

    private Builder(AbstractBuildRuleBuilderParams params) {
      super(params);
    }

    @Override
    public AndroidBinaryRule build(BuildRuleResolver ruleResolver) {
      // Make sure the "keystore" argument refers to a KeystoreRule.
      BuildRule rule = ruleResolver.get(keystoreTarget);

      Buildable keystore = rule.getBuildable();
      if (!(keystore instanceof Keystore)) {
        throw new HumanReadableException(
            "In %s, keystore='%s' must be a keystore() but was %s().",
            getBuildTarget(),
            rule.getFullyQualifiedName(),
            rule.getType().getName());
      }

      BuildRuleParams originalParams = createBuildRuleParams(ruleResolver);
      ImmutableSortedSet<BuildRule> originalDeps = originalParams.getDeps();
      ImmutableSet<IntermediateDexRule> preDexDeps;
      ImmutableSet<BuildTarget> buildRulesToExcludeFromDex =
          buildRulesToExcludeFromDexBuilder.build();
      if (!disablePreDex
          && PackageType.DEBUG.equals(packageType)
          && !dexSplitMode.isShouldSplitDex() // TODO(mbolin): Support predex for split dex.
          && !preprocessJavaClassesBash.isPresent() // TODO(mbolin): Support predex post-preprocess.
          ) {
        AndroidBinaryGraphEnhancer graphEnhancer = new AndroidBinaryGraphEnhancer(
            originalDeps,
            buildRulesToExcludeFromDex,
            originalParams.getPathRelativizer(),
            originalParams.getRuleKeyBuilderFactory());
        preDexDeps = graphEnhancer.createDepsForPreDexing(ruleResolver);
      } else {
        preDexDeps = ImmutableSet.of();
      }

      boolean allowNonExistentRule =
          false;

      // Must create a new BuildRuleParams to supersede the one built by
      // createBuildRuleParams(ruleResolver).
      ImmutableSortedSet<BuildRule> totalDeps = ImmutableSortedSet.<BuildRule>naturalOrder()
          .addAll(originalDeps)
          .addAll(preDexDeps)
          .build();
      BuildRuleParams finalParams = new BuildRuleParams(getBuildTarget(),
          totalDeps,
          originalParams.getVisibilityPatterns(),
          originalParams.getPathRelativizer(),
          originalParams.getRuleKeyBuilderFactory());

      return new AndroidBinaryRule(
          finalParams,
          manifest,
          target,
          getBuildTargetsAsBuildRules(ruleResolver, classpathDeps.build()),
          (Keystore)keystore,
          packageType,
          /* buildRulesToExcludeFromDex */ getBuildTargetsAsBuildRules(ruleResolver,
              buildRulesToExcludeFromDex,
              allowNonExistentRule),
          dexSplitMode,
          useAndroidProguardConfigWithOptimizations,
          proguardConfig,
          resourceCompressionMode,
          primaryDexSubstrings.build(),
          linearAllocHardLimit,
          primaryDexClassesFile,
          resourceFilter,
          cpuFilters.build(),
          preDexDeps,
          getBuildTargetsAsBuildRules(ruleResolver, preprocessJavaClassesDeps.build()),
          preprocessJavaClassesBash);
    }

    @Override
    public Builder setBuildTarget(BuildTarget buildTarget) {
      super.setBuildTarget(buildTarget);
      return this;
    }

    @Override
    public Builder addDep(BuildTarget dep) {
      super.addDep(dep);
      return this;
    }

    @Override
    public Builder addVisibilityPattern(BuildTargetPattern visibilityPattern) {
      super.addVisibilityPattern(visibilityPattern);
      return this;
    }

    public Builder setManifest(SourcePath manifest) {
      this.manifest = manifest;
      return this;
    }

    public Builder setTarget(String target) {
      this.target = target;
      return this;
    }

    public Builder addClasspathDep(BuildTarget classpathDep) {
      this.classpathDeps.add(classpathDep);
      addDep(classpathDep);
      return this;
    }

    public Builder setKeystore(BuildTarget keystoreTarget) {
      this.keystoreTarget = keystoreTarget;
      addDep(keystoreTarget);
      return this;
    }

    public Builder setPackageType(String packageType) {
      if (packageType == null) {
        this.packageType = DEFAULT_PACKAGE_TYPE;
      } else {
        this.packageType = PackageType.valueOf(packageType.toUpperCase());
      }
      return this;
    }

    public Builder addBuildRuleToExcludeFromDex(BuildTarget entry) {
      this.buildRulesToExcludeFromDexBuilder.add(entry);
      return this;
    }

    public Builder setDisablePreDex(boolean disablePreDex) {
      this.disablePreDex = disablePreDex;
      return this;
    }

    public Builder setDexSplitMode(DexSplitMode dexSplitMode) {
      this.dexSplitMode = dexSplitMode;
      return this;
    }

    public Builder setUseAndroidProguardConfigWithOptimizations(
        boolean useAndroidProguardConfigWithOptimizations) {
      this.useAndroidProguardConfigWithOptimizations = useAndroidProguardConfigWithOptimizations;
      return this;
    }

    public Builder setProguardConfig(Optional<SourcePath> proguardConfig) {
      this.proguardConfig = Preconditions.checkNotNull(proguardConfig);
      return this;
    }

    public Builder addPrimaryDexSubstrings(Iterable<String> primaryDexSubstrings) {
      this.primaryDexSubstrings.addAll(primaryDexSubstrings);
      return this;
    }

    public Builder setLinearAllocHardLimit(long linearAllocHardLimit) {
      this.linearAllocHardLimit = linearAllocHardLimit;
      return this;
    }

    public Builder setPrimaryDexClassesFile(Optional<SourcePath> primaryDexClassesFile) {
      this.primaryDexClassesFile = Preconditions.checkNotNull(primaryDexClassesFile);
      return this;
    }

    public Builder setResourceFilter(ResourceFilter resourceFilter) {
      this.resourceFilter = Preconditions.checkNotNull(resourceFilter);
      return this;
    }

    public Builder setResourceCompressionMode(String resourceCompressionMode) {
      Preconditions.checkNotNull(resourceCompressionMode);
      try {
        this.resourceCompressionMode = ResourceCompressionMode.valueOf(
            resourceCompressionMode.toUpperCase());
      } catch (IllegalArgumentException e) {
        throw new HumanReadableException(String.format(
            "In %s, android_binary() was passed an invalid resource compression mode: %s",
            buildTarget.getFullyQualifiedName(),
            resourceCompressionMode));
      }
      return this;
    }

    public Builder addCpuFilter(String cpuFilter) {
      if (cpuFilter != null) {
        try {
          this.cpuFilters.add(TargetCpuType.valueOf(cpuFilter.toUpperCase()));
        } catch (IllegalArgumentException e) {
          throw new HumanReadableException(
              "android_binary() was passed an invalid cpu filter: " + cpuFilter);
        }
      }
      return this;
    }

    public Builder addPreprocessJavaClassesDep(BuildTarget preprocessJavaClassesDep) {
      this.preprocessJavaClassesDeps.add(preprocessJavaClassesDep);
      this.addDep(preprocessJavaClassesDep);
      return this;
    }

    public Builder setPreprocessJavaClassesBash(
        Optional<String> preprocessJavaClassesBash) {
      this.preprocessJavaClassesBash = Preconditions.checkNotNull(preprocessJavaClassesBash);
      return this;
    }
  }
}
