release-request-2c5efa61-1f02-4e74-bfeb-1ca3cd5028bd-for-git_pi-release-4301718 snap-temp-L56500000097146696

Change-Id: Ib1d42fc8a05a8c0e8eb373502f02e631e796df4b
diff --git a/bundletool/Android.mk b/bundletool/Android.mk
new file mode 100644
index 0000000..b6c20f8
--- /dev/null
+++ b/bundletool/Android.mk
@@ -0,0 +1,37 @@
+LOCAL_PATH:= $(call my-dir)
+
+## bundletool script
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := bundletool
+LOCAL_MODULE_TAG := optional
+LOCAL_MODULE_CLASS := EXECUTABLES
+LOCAL_IS_HOST_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(HOST_OUT_JAVA_LIBRARIES)/bundletool$(COMMON_JAVA_PACKAGE_SUFFIX)
+$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/etc/bundletool | $(ACP)
+	@echo "Copy: $(PRIVATE_MODULE) ($@)"
+	$(copy-file-to-new-target)
+	$(hide) chmod 755 $@
+
+## tool jar
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := bundletool
+
+LOCAL_SRC_FILES := $(call all-java-files-under, java)
+LOCAL_IS_HOST_MODULE := true
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_STATIC_JAVA_LIBRARIES := guavalib jsr305lib dagger2-auto-value-host error_prone_annotations-2.0.18
+
+LOCAL_ANNOTATION_PROCESSORS := dagger2-auto-value-host
+LOCAL_ANNOTATION_PROCESSOR_CLASSES := com.google.auto.value.processor.AutoValueProcessor
+
+LOCAL_JAR_MANIFEST := manifest.txt
+
+include $(BUILD_HOST_JAVA_LIBRARY)
diff --git a/bundletool/etc/bundletool b/bundletool/etc/bundletool
new file mode 100644
index 0000000..ac7cac3
--- /dev/null
+++ b/bundletool/etc/bundletool
@@ -0,0 +1,89 @@
+#!/bin/bash
+#
+# Copyright (C) 2017 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.
+
+# Set up prog to be the path of this script, including following symlinks,
+# and set up progdir to be the fully-qualified pathname of its directory.
+prog="$0"
+while [ -h "${prog}" ]; do
+    newProg=`/bin/ls -ld "${prog}"`
+    newProg=`expr "${newProg}" : ".* -> \(.*\)$"`
+    if expr "x${newProg}" : 'x/' >/dev/null; then
+        prog="${newProg}"
+    else
+        progdir=`dirname "${prog}"`
+        prog="${progdir}/${newProg}"
+    fi
+done
+oldwd=`pwd`
+progdir=`dirname "${prog}"`
+cd "${progdir}"
+progdir=`pwd`
+prog="${progdir}"/`basename "${prog}"`
+cd "${oldwd}"
+
+jarfile=bundletool.jar
+libdir="$progdir"
+
+if [ ! -r "$libdir/$jarfile" ]; then
+    # set bundletool.jar location for the SDK case
+    libdir="$libdir/lib"
+fi
+
+
+if [ ! -r "$libdir/$jarfile" ]; then
+    # set bundletool.jar location for the Android tree case
+    libdir=`dirname "$progdir"`/framework
+fi
+
+if [ ! -r "$libdir/$jarfile" ]; then
+    echo `basename "$prog"`": can't find $jarfile"
+    exit 1
+fi
+
+# By default, give bundletool a max heap size of 1 gig. This can be overridden
+# by using a "-J" option (see below).
+defaultMx="-Xmx1024M"
+
+# The following will extract any initial parameters of the form
+# "-J<stuff>" from the command line and pass them to the Java
+# invocation (instead of to bundletool). This makes it possible for you to add
+# a command-line parameter such as "-JXmx256M" in your scripts, for
+# example. "java" (with no args) and "java -X" give a summary of
+# available options.
+
+javaOpts=""
+
+while expr "x$1" : 'x-J' >/dev/null; do
+    opt=`expr "x$1" : 'x-J\(.*\)'`
+    javaOpts="${javaOpts} -${opt}"
+    if expr "x${opt}" : "xXmx[0-9]" >/dev/null; then
+        defaultMx="no"
+    fi
+    shift
+done
+
+if [ "${defaultMx}" != "no" ]; then
+    javaOpts="${javaOpts} ${defaultMx}"
+fi
+
+if [ "$OSTYPE" = "cygwin" ]; then
+    # For Cygwin, convert the jarfile path into native Windows style.
+    jarpath=`cygpath -w "$libdir/$jarfile"`
+else
+    jarpath="$libdir/$jarfile"
+fi
+
+exec java $javaOpts -jar "$jarpath" "$@"
diff --git a/bundletool/etc/bundletool.bat b/bundletool/etc/bundletool.bat
new file mode 100644
index 0000000..09a9d36
--- /dev/null
+++ b/bundletool/etc/bundletool.bat
@@ -0,0 +1,88 @@
+@echo off↵
+REM Copyright (C) 2017 The Android Open Source Project↵
+REM↵
+REM Licensed under the Apache License, Version 2.0 (the "License");↵
+REM you may not use this file except in compliance with the License.↵
+REM You may obtain a copy of the License at↵
+REM↵
+REM     http://www.apache.org/licenses/LICENSE-2.0↵
+REM↵
+REM Unless required by applicable law or agreed to in writing, software↵
+REM distributed under the License is distributed on an "AS IS" BASIS,↵
+REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.↵
+REM See the License for the specific language governing permissions and↵
+REM limitations under the License.↵
+↵
+REM don't modify the caller's environment↵
+setlocal↵
+↵
+REM Locate bundletool.jar in the directory where bundletool.bat was found and start it.↵
+↵
+REM Set up prog to be the path of this script, including following symlinks,↵
+REM and set up progdir to be the fully-qualified pathname of its directory.↵
+set prog=%~f0↵
+↵
+rem Check we have a valid Java.exe in the path.↵
+set java_exe=↵
+if exist    "%~dp0..\tools\lib\find_java.bat" call    "%~dp0..\tools\lib\find_java.bat"↵
+if exist "%~dp0..\..\tools\lib\find_java.bat" call "%~dp0..\..\tools\lib\find_java.bat"↵
+if not defined java_exe goto :EOF↵
+↵
+set jarfile=bundletool.jar↵
+set "frameworkdir=%~dp0"↵
+rem frameworkdir must not end with a dir sep.↵
+set "frameworkdir=%frameworkdir:~0,-1%"↵
+↵
+if exist "%frameworkdir%\%jarfile%" goto JarFileOk↵
+    set "frameworkdir=%~dp0lib"↵
+↵
+if exist "%frameworkdir%\%jarfile%" goto JarFileOk↵
+    set "frameworkdir=%~dp0..\framework"↵
+↵
+:JarFileOk↵
+↵
+set "jarpath=%frameworkdir%\%jarfile%"↵
+↵
+set javaOpts=↵
+set args=↵
+↵
+REM By default, give bundletool a max heap size of 1 gig and a stack size of 1meg.↵
+rem This can be overridden by using "-JXmx..." and "-JXss..." options below.↵
+set defaultXmx=-Xmx1024M↵
+set defaultXss=-Xss1m↵
+↵
+REM Capture all arguments that are not -J options.↵
+REM Note that when reading the input arguments with %1, the cmd.exe↵
+REM automagically converts --name=value arguments into 2 arguments "--name"↵
+REM followed by "value". Dx has been changed to know how to deal with that.↵
+set params=↵
+↵
+:firstArg↵
+if [%1]==[] goto endArgs↵
+set a=%~1↵
+↵
+    if [%defaultXmx%]==[] goto notXmx↵
+    if %a:~0,5% NEQ -JXmx goto notXmx↵
+        set defaultXmx=↵
+    :notXmx↵
+↵
+    if [%defaultXss%]==[] goto notXss↵
+    if %a:~0,5% NEQ -JXss goto notXss↵
+        set defaultXss=↵
+    :notXss↵
+↵
+    if %a:~0,2% NEQ -J goto notJ↵
+        set javaOpts=%javaOpts% -%a:~2%↵
+        shift /1↵
+        goto firstArg↵
+↵
+    :notJ↵
+    set params=%params% %1↵
+    shift /1↵
+    goto firstArg↵
+↵
+:endArgs↵
+↵
+set javaOpts=%javaOpts% %defaultXmx% %defaultXss%↵
+call "%java_exe%" %javaOpts% -Djava.ext.dirs="%frameworkdir%" -jar "%jarpath%" %params%↵
+↵
diff --git a/bundletool/javatests/com/android/tools/appbundle/bundletool/AllTests.java b/bundletool/javatests/com/android/tools/appbundle/bundletool/AllTests.java
deleted file mode 100644
index acfc60b..0000000
--- a/bundletool/javatests/com/android/tools/appbundle/bundletool/AllTests.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2017 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.tools.appbundle.bundletool;
-
-import org.junit.runner.JUnitCore;
-import org.junit.runner.RunWith;
-import org.junit.runners.Suite;
-
-@RunWith(Suite.class)
-@Suite.SuiteClasses({
-  AppBundleTest.class,
-  BuildModuleCommandTest.class,
-  BundleToolTest.class,
-  SplitModuleCommandTest.class,
-})
-public class AllTests {
-
-  public static void main(String[] args) throws Exception {
-    JUnitCore.main("com.android.tools.appbundle.bundletool.AllTests");
-  }
-}
diff --git a/bundletool/javatests/com/android/tools/appbundle/bundletool/AppBundleTest.java b/bundletool/javatests/com/android/tools/appbundle/bundletool/AppBundleTest.java
deleted file mode 100644
index d5a352b..0000000
--- a/bundletool/javatests/com/android/tools/appbundle/bundletool/AppBundleTest.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2017 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.tools.appbundle.bundletool;
-
-import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-
-import java.util.Vector;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipFile;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-/** Tests for the AppBundle class. */
-@RunWith(JUnit4.class)
-public class AppBundleTest {
-
-  private ZipFile bundleFile;
-  private Vector<ZipEntry> entries = new Vector<>();
-
-  @Before
-  public void setUp() {
-    bundleFile = mock(ZipFile.class);
-  }
-
-  @Test
-  public void testSingleModuleBundle() {
-    putEntry("/module1/classes.dex");
-    doReturn(entries.elements()).when(bundleFile).entries();
-
-    AppBundle appBundle = new AppBundle(bundleFile);
-    assertThat(appBundle.getModules().keySet()).containsExactly("module1");
-  }
-
-  @Test
-  public void testNoModulesWhenFilesAtRoot() {
-    putEntry("/deliverables.pb");
-    putEntry("variants.pb");
-    doReturn(entries.elements()).when(bundleFile).entries();
-
-    AppBundle appBundle = new AppBundle(bundleFile);
-    assertThat(appBundle.getModules().keySet()).isEmpty();
-  }
-
-  @Test
-  public void testMultipleModules() {
-    putEntry("base/AndroidManifest.flat");
-    putEntry("base/Format.flat");
-    putEntry("base/classes.dex");
-    putEntry("base/assets/textures.etc1");
-    putEntry("base/res/drawable-hdpi/title.jpg");
-    putEntry("detail/AndroidManifest.flat");
-    putEntry("detail/Format.flat");
-    doReturn(entries.elements()).when(bundleFile).entries();
-
-    AppBundle appBundle = new AppBundle(bundleFile);
-    assertThat(appBundle.getModules().keySet()).containsExactly("base", "detail");
-  }
-
-  private void putEntry(String fakeFile) {
-    entries.add(new ZipEntry(fakeFile));
-  }
-}
diff --git a/bundletool/javatests/com/android/tools/appbundle/bundletool/BuildModuleCommandTest.java b/bundletool/javatests/com/android/tools/appbundle/bundletool/BuildModuleCommandTest.java
deleted file mode 100644
index 7f6b107..0000000
--- a/bundletool/javatests/com/android/tools/appbundle/bundletool/BuildModuleCommandTest.java
+++ /dev/null
@@ -1,471 +0,0 @@
-/*
- * Copyright (C) 2017 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.tools.appbundle.bundletool;
-
-import static com.google.common.truth.Truth.assertThat;
-import static org.junit.Assert.assertThrows;
-import static org.junit.Assert.expectThrows;
-
-import com.android.tools.appbundle.bundletool.utils.FlagParser;
-import java.io.IOException;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-@RunWith(JUnit4.class)
-public class BuildModuleCommandTest {
-
-  @Rule public TemporaryFolder tmp = new TemporaryFolder();
-
-  private Path outputPath;
-  private Path manifestPath;
-  private Path manifestDirPath;
-  private Path dexPath;
-  private Path dexDirPath;
-  private Path resourcesDirPath;
-  private Path assetsDirPath;
-  private Path nativeDirPath;
-
-  private Path pathThatDoesNotExist;
-
-  @Before
-  public void setUp() throws IOException {
-    outputPath = Paths.get(tmp.getRoot().getPath(), "bundle");
-    manifestPath = tmp.newFile("AndroidManifest.flat").toPath();
-    manifestDirPath = tmp.newFolder("manifest").toPath();
-    dexPath = tmp.newFile("classes.dex").toPath();
-    dexDirPath = tmp.newFolder("dex").toPath();
-    resourcesDirPath = tmp.newFolder("resources").toPath();
-    assetsDirPath = tmp.newFolder("assets").toPath();
-    nativeDirPath = tmp.newFolder("native").toPath();
-
-    pathThatDoesNotExist = Paths.get(tmp.getRoot().getPath(), "path-that-does-not-exist");
-  }
-
-  @Test
-  public void validConfig_viaFlags() {
-    FlagParser flagParser =
-        new FlagParser()
-            .parse(
-                new String[] {
-                  "--output=" + outputPath,
-                  "--manifest=" + manifestPath,
-                  "--dexPath=" + dexPath,
-                  "--resourcesDirPath=" + resourcesDirPath,
-                  "--assetsDirPath=" + assetsDirPath,
-                  "--nativeDirPath=" + nativeDirPath,
-                });
-    BuildModuleCommand.fromFlags(flagParser).execute();
-  }
-
-  @Test
-  public void validConfig_viaBuilder() {
-    BuildModuleCommand.builder()
-        .setOutputPath(outputPath)
-        .setManifestPath(manifestPath)
-        .setDexPath(dexPath)
-        .setResourcesDirPath(resourcesDirPath)
-        .setAssetsDirPath(assetsDirPath)
-        .setNativeDirPath(nativeDirPath)
-        .build()
-        .execute();
-  }
-
-  @Test
-  public void outputPathNotSetThrowsException_viaFlags() {
-    FlagParser flagParser = new FlagParser().parse(new String[] {"--manifest=" + manifestPath});
-    IllegalArgumentException exception =
-        expectThrows(
-            IllegalArgumentException.class,
-            () -> BuildModuleCommand.fromFlags(flagParser).execute());
-
-    assertThat(exception).hasMessageThat().contains("--output");
-  }
-
-  @Test
-  public void outputPathNotSetThrowsException_viaBuilder() {
-    assertThrows(
-        IllegalStateException.class,
-        () -> BuildModuleCommand.builder().setManifestPath(manifestPath).build().execute());
-  }
-
-  @Test
-  public void manifestAndManifestDirNotSetThrowsException_viaFlags() {
-    FlagParser flagParser = new FlagParser().parse(new String[] {"--output=" + outputPath});
-    IllegalArgumentException exception =
-        expectThrows(
-            IllegalArgumentException.class,
-            () -> BuildModuleCommand.fromFlags(flagParser).execute());
-
-    assertThat(exception).hasMessageThat().contains("--manifest");
-  }
-
-  @Test
-  public void manifestAndManifestDirNotSetThrowsException_viaBuilder() {
-    IllegalArgumentException exception =
-        expectThrows(
-            IllegalArgumentException.class,
-            () -> BuildModuleCommand.builder().setOutputPath(outputPath).build().execute());
-
-    assertThat(exception).hasMessageThat().contains("--manifest");
-  }
-
-  @Test
-  public void manifestAndManifestDirBothSetThrowsException_viaFlags() {
-    FlagParser flagParser =
-        new FlagParser()
-            .parse(
-                new String[] {
-                  "--output=" + outputPath,
-                  "--manifest=" + manifestPath,
-                  "--manifest-dir=" + manifestDirPath
-                });
-    IllegalArgumentException exception =
-        expectThrows(
-            IllegalArgumentException.class,
-            () -> BuildModuleCommand.fromFlags(flagParser).execute());
-
-    assertThat(exception).hasMessageThat().contains("--manifest");
-  }
-
-  @Test
-  public void manifestAndManifestDirBothSetThrowsException_viaBuilder() {
-    IllegalArgumentException exception =
-        expectThrows(
-            IllegalArgumentException.class,
-            () ->
-                BuildModuleCommand.builder()
-                    .setOutputPath(outputPath)
-                    .setManifestPath(manifestPath)
-                    .setManifestDirPath(manifestDirPath)
-                    .build()
-                    .execute());
-
-    assertThat(exception).hasMessageThat().contains("--manifest");
-  }
-
-  @Test
-  public void dexAndDexDirBothSetThrowsException_viaFlags() {
-    FlagParser flagParser =
-        new FlagParser()
-            .parse(
-                new String[] {
-                  "--output=" + outputPath,
-                  "--manifest=" + manifestPath,
-                  "--dex=" + dexPath,
-                  "--dex-dir=" + dexDirPath
-                });
-    IllegalArgumentException exception =
-        expectThrows(
-            IllegalArgumentException.class,
-            () -> BuildModuleCommand.fromFlags(flagParser).execute());
-
-    assertThat(exception).hasMessageThat().contains("--dex");
-  }
-
-  @Test
-  public void dexAndDexDirBothSetThrowsException_viaBuilder() {
-    IllegalArgumentException exception =
-        expectThrows(
-            IllegalArgumentException.class,
-            () ->
-                BuildModuleCommand.builder()
-                    .setOutputPath(outputPath)
-                    .setManifestPath(manifestPath)
-                    .setDexPath(dexPath)
-                    .setDexDirPath(dexDirPath)
-                    .build()
-                    .execute());
-
-    assertThat(exception).hasMessageThat().contains("--dex");
-  }
-
-  @Test
-  public void outputExistsThrowsException_viaFlags() throws IOException {
-    outputPath = tmp.newFile("bundle").toPath();
-    FlagParser flagParser =
-        new FlagParser()
-            .parse(
-                new String[] {
-                  "--output=" + outputPath, "--manifest=" + manifestPath, "--dex=" + dexPath
-                });
-    IllegalArgumentException exception =
-        expectThrows(
-            IllegalArgumentException.class,
-            () -> BuildModuleCommand.fromFlags(flagParser).execute());
-
-    assertThat(exception).hasMessageThat().contains("already exists");
-  }
-
-  @Test
-  public void outputExistsThrowsException_viaBuilder() throws IOException {
-    outputPath = tmp.newFile("bundle").toPath();
-    IllegalArgumentException exception =
-        expectThrows(
-            IllegalArgumentException.class,
-            () ->
-                BuildModuleCommand.builder()
-                    .setOutputPath(outputPath)
-                    .setManifestPath(manifestPath)
-                    .setDexPath(dexPath)
-                    .build()
-                    .execute());
-
-    assertThat(exception).hasMessageThat().contains("already exists");
-  }
-
-  @Test
-  public void manifestDoesNotExistThrowsException_viaFlags() throws IOException {
-    FlagParser flagParser =
-        new FlagParser()
-            .parse(
-                new String[] {
-                  "--output=" + outputPath, "--manifest=" + pathThatDoesNotExist, "--dex=" + dexPath
-                });
-    IllegalArgumentException exception =
-        expectThrows(
-            IllegalArgumentException.class,
-            () -> BuildModuleCommand.fromFlags(flagParser).execute());
-
-    assertThat(exception).hasMessageThat().containsMatch("File '.*' was not found");
-  }
-
-  @Test
-  public void manifestDoesNotExistThrowsException_viaBuilder() throws IOException {
-    IllegalArgumentException exception =
-        expectThrows(
-            IllegalArgumentException.class,
-            () ->
-                BuildModuleCommand.builder()
-                    .setOutputPath(outputPath)
-                    .setManifestPath(pathThatDoesNotExist)
-                    .setDexPath(dexPath)
-                    .build()
-                    .execute());
-
-    assertThat(exception).hasMessageThat().containsMatch("File '.*' was not found");
-  }
-
-  @Test
-  public void manifestDirDoesNotExistThrowsException_viaFlags() throws IOException {
-    FlagParser flagParser =
-        new FlagParser()
-            .parse(
-                new String[] {
-                  "--output=" + outputPath,
-                  "--manifest-dir=" + pathThatDoesNotExist,
-                  "--dex=" + dexPath
-                });
-    IllegalArgumentException exception =
-        expectThrows(
-            IllegalArgumentException.class,
-            () -> BuildModuleCommand.fromFlags(flagParser).execute());
-
-    assertThat(exception).hasMessageThat().containsMatch("Directory '.*' was not found");
-  }
-
-  @Test
-  public void manifestDirDoesNotExistThrowsException_viaBuilder() throws IOException {
-    IllegalArgumentException exception =
-        expectThrows(
-            IllegalArgumentException.class,
-            () ->
-                BuildModuleCommand.builder()
-                    .setOutputPath(outputPath)
-                    .setManifestDirPath(pathThatDoesNotExist)
-                    .setDexPath(dexPath)
-                    .build()
-                    .execute());
-
-    assertThat(exception).hasMessageThat().containsMatch("Directory '.*' was not found");
-  }
-
-  @Test
-  public void dexDoesNotExistThrowsException_viaFlags() throws IOException {
-    FlagParser flagParser =
-        new FlagParser()
-            .parse(
-                new String[] {
-                  "--output=" + outputPath,
-                  "--manifest=" + manifestPath,
-                  "--dex=" + pathThatDoesNotExist
-                });
-    IllegalArgumentException exception =
-        expectThrows(
-            IllegalArgumentException.class,
-            () -> BuildModuleCommand.fromFlags(flagParser).execute());
-
-    assertThat(exception).hasMessageThat().containsMatch("File '.*' was not found");
-  }
-
-  @Test
-  public void dexDoesNotExistThrowsException_viaBuilder() throws IOException {
-    IllegalArgumentException exception =
-        expectThrows(
-            IllegalArgumentException.class,
-            () ->
-                BuildModuleCommand.builder()
-                    .setOutputPath(outputPath)
-                    .setManifestPath(manifestPath)
-                    .setDexPath(pathThatDoesNotExist)
-                    .build()
-                    .execute());
-
-    assertThat(exception).hasMessageThat().containsMatch("File '.*' was not found");
-  }
-
-  @Test
-  public void dexDirDoesNotExistThrowsException_viaFlags() throws IOException {
-    dexDirPath = Paths.get(tmp.getRoot().getPath(), "dir-that-does-not-exist");
-    FlagParser flagParser =
-        new FlagParser()
-            .parse(
-                new String[] {
-                  "--output=" + outputPath,
-                  "--manifest=" + manifestPath,
-                  "--dex-dir=" + pathThatDoesNotExist
-                });
-    IllegalArgumentException exception =
-        expectThrows(
-            IllegalArgumentException.class,
-            () -> BuildModuleCommand.fromFlags(flagParser).execute());
-
-    assertThat(exception).hasMessageThat().containsMatch("Directory '.*' was not found");
-  }
-
-  @Test
-  public void dexDirDoesNotExistThrowsException_viaBuilder() throws IOException {
-    IllegalArgumentException exception =
-        expectThrows(
-            IllegalArgumentException.class,
-            () ->
-                BuildModuleCommand.builder()
-                    .setOutputPath(outputPath)
-                    .setManifestPath(manifestPath)
-                    .setDexDirPath(pathThatDoesNotExist)
-                    .build()
-                    .execute());
-
-    assertThat(exception).hasMessageThat().containsMatch("Directory '.*' was not found");
-  }
-
-  @Test
-  public void resourcesDirDoesNotExistThrowsException_viaFlags() throws IOException {
-    FlagParser flagParser =
-        new FlagParser()
-            .parse(
-                new String[] {
-                  "--output=" + outputPath,
-                  "--manifest=" + manifestPath,
-                  "--resources-dir=" + pathThatDoesNotExist
-                });
-    IllegalArgumentException exception =
-        expectThrows(
-            IllegalArgumentException.class,
-            () -> BuildModuleCommand.fromFlags(flagParser).execute());
-
-    assertThat(exception).hasMessageThat().containsMatch("Directory '.*' was not found");
-  }
-
-  @Test
-  public void resourcesDirDoesNotExistThrowsException_viaBuilder() throws IOException {
-    IllegalArgumentException exception =
-        expectThrows(
-            IllegalArgumentException.class,
-            () ->
-                BuildModuleCommand.builder()
-                    .setOutputPath(outputPath)
-                    .setManifestPath(manifestPath)
-                    .setResourcesDirPath(pathThatDoesNotExist)
-                    .build()
-                    .execute());
-
-    assertThat(exception).hasMessageThat().containsMatch("Directory '.*' was not found");
-  }
-
-  @Test
-  public void assetsDirDoesNotExistThrowsException_viaFlags() throws IOException {
-    FlagParser flagParser =
-        new FlagParser()
-            .parse(
-                new String[] {
-                  "--output=" + outputPath,
-                  "--manifest=" + manifestPath,
-                  "--assets-dir=" + pathThatDoesNotExist
-                });
-    IllegalArgumentException exception =
-        expectThrows(
-            IllegalArgumentException.class,
-            () -> BuildModuleCommand.fromFlags(flagParser).execute());
-
-    assertThat(exception).hasMessageThat().containsMatch("Directory '.*' was not found");
-  }
-
-  @Test
-  public void assetsDirDoesNotExistThrowsException_viaBuilder() throws IOException {
-    IllegalArgumentException exception =
-        expectThrows(
-            IllegalArgumentException.class,
-            () ->
-                BuildModuleCommand.builder()
-                    .setOutputPath(outputPath)
-                    .setManifestPath(manifestPath)
-                    .setAssetsDirPath(pathThatDoesNotExist)
-                    .build()
-                    .execute());
-
-    assertThat(exception).hasMessageThat().containsMatch("Directory '.*' was not found");
-  }
-
-  @Test
-  public void nativeDirDoesNotExistThrowsException_viaFlags() throws IOException {
-    FlagParser flagParser =
-        new FlagParser()
-            .parse(
-                new String[] {
-                  "--output=" + outputPath,
-                  "--manifest=" + manifestPath,
-                  "--native-dir=" + pathThatDoesNotExist
-                });
-    IllegalArgumentException exception =
-        expectThrows(
-            IllegalArgumentException.class,
-            () -> BuildModuleCommand.fromFlags(flagParser).execute());
-
-    assertThat(exception).hasMessageThat().containsMatch("Directory '.*' was not found");
-  }
-
-  @Test
-  public void nativeDirDoesNotExistThrowsException_viaBuilder() throws IOException {
-    IllegalArgumentException exception =
-        expectThrows(
-            IllegalArgumentException.class,
-            () ->
-                BuildModuleCommand.builder()
-                    .setOutputPath(outputPath)
-                    .setManifestPath(manifestPath)
-                    .setNativeDirPath(pathThatDoesNotExist)
-                    .build()
-                    .execute());
-
-    assertThat(exception).hasMessageThat().containsMatch("Directory '.*' was not found");
-  }
-}
diff --git a/bundletool/javatests/com/android/tools/appbundle/bundletool/BundleToolTest.java b/bundletool/javatests/com/android/tools/appbundle/bundletool/BundleToolTest.java
deleted file mode 100644
index 2c69b01..0000000
--- a/bundletool/javatests/com/android/tools/appbundle/bundletool/BundleToolTest.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2017 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.tools.appbundle.bundletool;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-/**
- * Unit tests for Bundle tool.
- */
-@RunWith(JUnit4.class)
-public final class BundleToolTest {
-
-  @Test
-  public void dummyTest() {
-  }
-}
diff --git a/bundletool/javatests/com/android/tools/appbundle/bundletool/SplitModuleCommandTest.java b/bundletool/javatests/com/android/tools/appbundle/bundletool/SplitModuleCommandTest.java
deleted file mode 100644
index 0006cb0..0000000
--- a/bundletool/javatests/com/android/tools/appbundle/bundletool/SplitModuleCommandTest.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2017 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.tools.appbundle.bundletool;
-
-import static org.junit.Assert.assertThrows;
-
-import com.android.tools.appbundle.bundletool.Command.ExecutionException;
-import com.android.tools.appbundle.bundletool.utils.FlagParser;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-/** Tests for the SplitModuleCommand implementation. */
-@RunWith(JUnit4.class)
-public class SplitModuleCommandTest {
-
-  @Test
-  public void testMissingOutputFlag() throws Exception {
-    expectFlagException(new String[] {"--bundle=b.zip", "--module=m1"});
-  }
-
-  @Test
-  public void testMissingBundleFlag() throws Exception {
-    expectFlagException(new String[] {"--output=/some/dir", "--module=m1"});
-  }
-
-  @Test
-  public void testMissingModuleFlag() throws Exception {
-    expectFlagException(new String[] {"--output=/some/dir", "--bundle=b.zip"});
-  }
-
-  @Test
-  public void testMissingBundleFileFailsCommand() throws Exception {
-    FlagParser flagParser = new FlagParser();
-    flagParser.parse(new String[] {"--bundle=b.zip", "--output=/some/dir", "--module=m1"});
-    SplitModuleCommand command = new SplitModuleCommand(flagParser);
-    assertThrows(ExecutionException.class, () -> command.execute());
-  }
-
-  private void expectFlagException(String[] flags) throws Exception {
-    FlagParser flagParser = new FlagParser();
-    flagParser.parse(flags);
-    assertThrows(IllegalArgumentException.class, () -> new SplitModuleCommand(flagParser));
-  }
-}
diff --git a/bundletool/javatests/com/android/tools/appbundle/bundletool/utils/FlagParserTest.java b/bundletool/javatests/com/android/tools/appbundle/bundletool/utils/FlagParserTest.java
deleted file mode 100644
index f9fc6d5..0000000
--- a/bundletool/javatests/com/android/tools/appbundle/bundletool/utils/FlagParserTest.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright (C) 2017 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.tools.appbundle.bundletool.utils;
-
-import static com.google.common.truth.Truth.assertThat;
-import static junit.framework.TestCase.fail;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-/** Tests for the FlagParser class. */
-@RunWith(JUnit4.class)
-public class FlagParserTest {
-
-  @Test
-  public void testParsesSingleCommand() throws Exception {
-    String[] args = {"command1"};
-    FlagParser fp = new FlagParser();
-    fp.parse(args);
-    assertThat(fp.getCommands()).containsExactly("command1");
-  }
-
-  @Test
-  public void testEmptyCommandLine() throws Exception {
-    String[] args = {};
-    FlagParser fp = new FlagParser();
-    fp.parse(args);
-    assertThat(fp.getCommands()).isEmpty();
-  }
-
-  @Test
-  public void testParsesCommandLineFlags() throws Exception {
-    String[] args = {"command", "--flag1=value1", "--flag2=value2"};
-    FlagParser fp = new FlagParser();
-    fp.parse(args);
-    assertThat(fp.getCommands()).containsExactly("command");
-    assertThat(fp.getFlagValueOrDefault("flag1", "")).isEqualTo("value1");
-    assertThat(fp.getFlagValueOrDefault("flag2", "")).isEqualTo("value2");
-  }
-
-  @Test
-  public void testIncorrectCommandLineFlagsThrows() throws Exception {
-    String[] args = {"command", "--flag1=value1", "-flag2=value2"};
-    FlagParser fp = new FlagParser();
-    try {
-      fp.parse(args);
-      fail("Expected ParseException but nothing was thrown.");
-    } catch (FlagParser.ParseException e) {
-      assertThat(e.getMessage()).contains("-flag2=value2");
-    }
-  }
-
-  @Test
-  public void testFlagListValuesNotSet() throws Exception {
-    String[] args = {"command"};
-    FlagParser fp = new FlagParser();
-    fp.parse(args);
-    assertThat(fp.getCommands()).containsExactly("command");
-    assertThat(fp.getFlagListValue("flag1")).isEmpty();
-  }
-
-  @Test
-  public void testFlagListValuesSetWithDefault() throws Exception {
-    String[] args = {"command", "--flag1"};
-    FlagParser fp = new FlagParser();
-    fp.parse(args);
-    assertThat(fp.getCommands()).containsExactly("command");
-    assertThat(fp.getFlagListValue("flag1")).containsExactly("");
-  }
-
-  @Test
-  public void testFlagListValuesSingleValue() throws Exception {
-    String[] args = {"command", "--flag1=val1"};
-    FlagParser fp = new FlagParser();
-    fp.parse(args);
-    assertThat(fp.getFlagListValue("flag1")).containsExactly("val1");
-  }
-
-  @Test
-  public void testFlagListValuesMultiple() throws Exception {
-    String[] args = {"command", "--flag1=v1,v2,value3"};
-    FlagParser fp = new FlagParser();
-    fp.parse(args);
-    assertThat(fp.getCommands()).containsExactly("command");
-    assertThat(fp.getFlagValueOrDefault("flag1", "")).isEqualTo("v1,v2,value3");
-    assertThat(fp.getFlagListValue("flag1")).containsExactly("v1", "v2", "value3").inOrder();
-  }
-
-  @Test
-  public void testHandlingAbsentFlags() throws Exception {
-    String[] args = {"command", "--flag1=v1"};
-    FlagParser fp = new FlagParser();
-    fp.parse(args);
-    assertThat(fp.getCommands()).containsExactly("command");
-    assertThat(fp.getFlagValueOrDefault("flag2", "default")).isEqualTo("default");
-    assertThat(fp.getFlagListValue("flag2")).isEmpty();
-    assertThat(fp.isFlagSet("flag2")).isFalse();
-  }
-
-  @Test
-  public void testHandlingMultipleCommands() throws Exception {
-    String[] args = {"help", "command1"};
-    FlagParser fp = new FlagParser();
-    fp.parse(args);
-    assertThat(fp.getCommands()).containsExactly("help", "command1").inOrder();
-  }
-
-  @Test
-  public void testUsingFlagMoreThanOnceThrows() throws Exception {
-    String[] args = {"command", "--flag1=v1", "--flag1=v2"};
-    FlagParser fp = new FlagParser();
-    try {
-      fp.parse(args);
-      fail("Expected ParseException but nothing was thrown.");
-    } catch (FlagParser.ParseException e) {
-      assertThat(e.getMessage()).contains("flag1");
-    }
-  }
-}
diff --git a/bundletool/manifest.txt b/bundletool/manifest.txt
new file mode 100644
index 0000000..b8a4c92
--- /dev/null
+++ b/bundletool/manifest.txt
@@ -0,0 +1 @@
+Main-Class: com.android.tools.appbundle.bundletool.BundleToolMain