Add a categorization when the internal unzip fails

Test: presubmit
Bug: None
Change-Id: I11a2e1d16a1ad95c92b740b6ff6fc574adc99126
diff --git a/common_util/com/android/tradefed/error/HarnessIOException.java b/common_util/com/android/tradefed/error/HarnessIOException.java
new file mode 100644
index 0000000..3af2545
--- /dev/null
+++ b/common_util/com/android/tradefed/error/HarnessIOException.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2023 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.tradefed.error;
+
+import com.android.tradefed.result.error.ErrorIdentifier;
+
+import java.io.IOException;
+
+/** Harness exception that helps carrying file issues. */
+public class HarnessIOException extends IOException implements IHarnessException {
+
+    private ErrorIdentifier mErrorId;
+    private String mOrigin;
+
+    public HarnessIOException(Throwable cause, ErrorIdentifier errorId) {
+        super(cause);
+        mErrorId = errorId;
+        mOrigin =
+                StackWalker.getInstance(java.lang.StackWalker.Option.RETAIN_CLASS_REFERENCE)
+                        .getCallerClass()
+                        .getCanonicalName();
+    }
+
+    @Override
+    public ErrorIdentifier getErrorId() {
+        return mErrorId;
+    }
+
+    @Override
+    public String getOrigin() {
+        return mOrigin;
+    }
+}
diff --git a/common_util/com/android/tradefed/result/error/InfraErrorIdentifier.java b/common_util/com/android/tradefed/result/error/InfraErrorIdentifier.java
index d48e2e8..789f3c8 100644
--- a/common_util/com/android/tradefed/result/error/InfraErrorIdentifier.java
+++ b/common_util/com/android/tradefed/result/error/InfraErrorIdentifier.java
@@ -53,6 +53,7 @@
     ARTIFACT_DOWNLOAD_ERROR(500_503, FailureStatus.DEPENDENCY_ISSUE),
     GCS_ERROR(500_504, FailureStatus.DEPENDENCY_ISSUE),
     ANDROID_PARTNER_SERVER_ERROR(500_505, FailureStatus.DEPENDENCY_ISSUE),
+    ARTIFACT_INVALID(500_506, FailureStatus.DEPENDENCY_ISSUE),
 
     // 501_001 - 501_500: environment issues: For example: lab wifi
     WIFI_FAILED_CONNECT(501_001, FailureStatus.DEPENDENCY_ISSUE),
diff --git a/common_util/com/android/tradefed/util/FileUtil.java b/common_util/com/android/tradefed/util/FileUtil.java
index e0c33ba..8f6f0ca 100644
--- a/common_util/com/android/tradefed/util/FileUtil.java
+++ b/common_util/com/android/tradefed/util/FileUtil.java
@@ -17,12 +17,11 @@
 
 import com.android.tradefed.command.FatalHostError;
 import com.android.tradefed.config.Option;
-import com.android.tradefed.error.IHarnessException;
+import com.android.tradefed.error.HarnessIOException;
 import com.android.tradefed.invoker.logger.InvocationMetricLogger;
 import com.android.tradefed.invoker.logger.InvocationMetricLogger.InvocationMetricKey;
 import com.android.tradefed.log.LogUtil.CLog;
 import com.android.tradefed.result.LogDataType;
-import com.android.tradefed.result.error.ErrorIdentifier;
 import com.android.tradefed.result.error.InfraErrorIdentifier;
 import com.android.tradefed.testtype.IAbi;
 
@@ -123,32 +122,6 @@
 
     }
 
-    /** Harness exception that helps carrying file issues. */
-    public static class HarnessIOException extends IOException implements IHarnessException {
-
-        private ErrorIdentifier mErrorId;
-        private String mOrigin;
-
-        HarnessIOException(Throwable cause, ErrorIdentifier errorId) {
-            super(cause);
-            mErrorId = errorId;
-            mOrigin =
-                    StackWalker.getInstance(java.lang.StackWalker.Option.RETAIN_CLASS_REFERENCE)
-                            .getCallerClass()
-                            .getCanonicalName();
-        }
-
-        @Override
-        public ErrorIdentifier getErrorId() {
-            return mErrorId;
-        }
-
-        @Override
-        public String getOrigin() {
-            return mOrigin;
-        }
-    }
-
     /**
      * Method to create a chain of directories, and set them all group execute/read/writable as they
      * are created, by calling {@link #chmodGroupRWX(File)}.  Essentially a version of
diff --git a/common_util/com/android/tradefed/util/ZipUtil2.java b/common_util/com/android/tradefed/util/ZipUtil2.java
index c13f844..82ae42b 100644
--- a/common_util/com/android/tradefed/util/ZipUtil2.java
+++ b/common_util/com/android/tradefed/util/ZipUtil2.java
@@ -15,12 +15,15 @@
  */
 package com.android.tradefed.util;
 
+import com.android.tradefed.error.HarnessIOException;
 import com.android.tradefed.log.LogUtil.CLog;
+import com.android.tradefed.result.error.InfraErrorIdentifier;
 
 import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
 import org.apache.commons.compress.archivers.zip.ZipFile;
 
 import java.io.File;
+import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.nio.file.Files;
 import java.util.Enumeration;
@@ -112,6 +115,11 @@
         // Extract fast
         try (java.util.zip.ZipFile zipFile = new java.util.zip.ZipFile(toUnzip)) {
             ZipUtil.extractZip(zipFile, destDir);
+        } catch (IOException e) {
+            if (e instanceof FileNotFoundException) {
+                throw new HarnessIOException(e, InfraErrorIdentifier.ARTIFACT_INVALID);
+            }
+            throw e;
         }
         // Then restore permissions
         try (ZipFile zip = new ZipFile(toUnzip)) {