IRR: Fail gracefully on AndroidManifest-less apks

Test: ApkParserTest
Fixes: 177918178

Change-Id: Iecf2dc995372f0d2a87d1740abf320765695a559
diff --git a/deploy/deployer/src/main/java/com/android/tools/deployer/ApkParser.java b/deploy/deployer/src/main/java/com/android/tools/deployer/ApkParser.java
index 3922ee5..4f0c92b 100644
--- a/deploy/deployer/src/main/java/com/android/tools/deployer/ApkParser.java
+++ b/deploy/deployer/src/main/java/com/android/tools/deployer/ApkParser.java
@@ -37,6 +37,8 @@
     private static final byte[] SIGNATURE_BLOCK_MAGIC = "APK Sig Block 42".getBytes();
     private static final long USHRT_MAX = 65535;
     public static final int EOCD_SIZE = 22;
+    static final String NO_MANIFEST_MSG = "Missing AndroidManifest.xml entry";
+    private static final String NO_MANIFEST_MSG_DETAILS = "in '%s'";
 
     public static class ApkArchiveMap {
         public static final long UNINITIALIZED = -1;
@@ -87,13 +89,19 @@
         ApkDetails apkDetails;
         try (ZipFile zipFile = new ZipFile(path)) {
             ZipEntry manifestEntry = zipFile.getEntry("AndroidManifest.xml");
+            if (manifestEntry == null) {
+                StringBuilder msg = new StringBuilder(NO_MANIFEST_MSG);
+                msg.append(" ");
+                msg.append(String.format(Locale.US, NO_MANIFEST_MSG_DETAILS, path));
+                throw new IOException(msg.toString());
+            }
             InputStream stream = zipFile.getInputStream(manifestEntry);
             apkDetails = parseManifest(stream);
         }
         return apkDetails;
     }
 
-    private Apk parse(String apkPath) throws IOException, DeployerException {
+    Apk parse(String apkPath) throws IOException, DeployerException {
         File file = new File(apkPath);
         String absolutePath = file.getAbsolutePath();
         String digest;
diff --git a/deploy/deployer/src/test/java/com/android/tools/deployer/ApkParserTest.java b/deploy/deployer/src/test/java/com/android/tools/deployer/ApkParserTest.java
index ee33292..bc0c3b8 100644
--- a/deploy/deployer/src/test/java/com/android/tools/deployer/ApkParserTest.java
+++ b/deploy/deployer/src/test/java/com/android/tools/deployer/ApkParserTest.java
@@ -280,4 +280,20 @@
         }
         Assert.assertFalse("Short overflow thrown", exceptionCaught);
     }
+
+    @Test
+    public void testGracefulMissingManifest() throws IOException, DeployerException {
+        Path tempDirectory = Files.createTempDirectory("");
+        try {
+            Path zip = tempDirectory.resolve("testGracefulMissingManifest.zip");
+            int numFiles = 1;
+            int sizePerFile = 1;
+            createZip(numFiles, sizePerFile, zip.toFile());
+            ApkParser parser = new ApkParser();
+            parser.parse(zip.toString());
+            Assert.fail("No exception thrown in apk missing AndroidManifest.xml");
+        } catch (IOException e) {
+            Assert.assertTrue(e.getMessage().startsWith(ApkParser.NO_MANIFEST_MSG));
+        }
+    }
 }