Do not exempt sourcepath from sandboxing.

This CL prevents the exemption of sourcepath from the sandbox if
enabled. It also bypasses violations when isDirectory or isFile are
used when traversing the sourcepath, and only reports violations
when files are read under sourcepath.

Test: built api-stubs-docs and framework-doc-stubs and verified there
are violations under the sourcepath.

Bug: b/156613606
Change-Id: I66fdf98d9a40b13754b2f613111bc6ff3794d83e
Merged-In: I66fdf98d9a40b13754b2f613111bc6ff3794d83e
diff --git a/src/main/java/com/android/tools/metalava/Driver.kt b/src/main/java/com/android/tools/metalava/Driver.kt
index 1241a16..2089215 100644
--- a/src/main/java/com/android/tools/metalava/Driver.kt
+++ b/src/main/java/com/android/tools/metalava/Driver.kt
@@ -1163,7 +1163,7 @@
     file: File,
     pkg: String
 ) {
-    if (file.isDirectory) {
+    if (FileReadSandbox.isDirectory(file)) {
         if (skippableDirectory(file)) {
             return
         }
@@ -1179,7 +1179,7 @@
         if (files != null) {
             for (child in files) {
                 var subPkg =
-                    if (child.isDirectory)
+                    if (FileReadSandbox.isDirectory(child))
                         if (pkg.isEmpty())
                             child.name
                         else pkg + "." + child.name
@@ -1194,7 +1194,7 @@
                 addHiddenPackages(packageToDoc, packageToOverview, hiddenPackages, child, subPkg)
             }
         }
-    } else if (file.isFile) {
+    } else if (FileReadSandbox.isFile(file)) {
         var javadoc = false
         val map = when {
             file.name == "package.html" -> {
diff --git a/src/main/java/com/android/tools/metalava/FileReadSandbox.kt b/src/main/java/com/android/tools/metalava/FileReadSandbox.kt
index a4ebb98..2c2443b 100644
--- a/src/main/java/com/android/tools/metalava/FileReadSandbox.kt
+++ b/src/main/java/com/android/tools/metalava/FileReadSandbox.kt
@@ -188,6 +188,24 @@
         return false
     }
 
+    fun isDirectory(file: File): Boolean {
+        try {
+            temporaryExempt.set(true)
+            return file.isDirectory()
+        } finally {
+            temporaryExempt.set(false)
+        }
+    }
+
+    fun isFile(file: File): Boolean {
+        try {
+            temporaryExempt.set(true)
+            return file.isFile()
+        } finally {
+            temporaryExempt.set(false)
+        }
+    }
+
     /** Used to skip all checks on any filesystem access made within the [check] method. */
     private val temporaryExempt = ThreadLocal<Boolean>()
 
diff --git a/src/main/java/com/android/tools/metalava/Options.kt b/src/main/java/com/android/tools/metalava/Options.kt
index 1636985..16917e3 100644
--- a/src/main/java/com/android/tools/metalava/Options.kt
+++ b/src/main/java/com/android/tools/metalava/Options.kt
@@ -787,7 +787,7 @@
                                 "$arg should point to a source root directory, not a source file ($path)"
                             )
                         }
-                        mutableSourcePath.addAll(stringToExistingDirsOrJars(path))
+                        mutableSourcePath.addAll(stringToExistingDirsOrJars(path, false))
                     }
                 }
 
@@ -1944,7 +1944,7 @@
         return FileReadSandbox.allowAccess(files)
     }
 
-    private fun stringToExistingDirsOrJars(value: String): List<File> {
+    private fun stringToExistingDirsOrJars(value: String, exempt: Boolean = true): List<File> {
         val files = mutableListOf<File>()
         for (path in value.split(File.pathSeparatorChar)) {
             val file = fileForPathInner(path)
@@ -1953,7 +1953,10 @@
             }
             files.add(file)
         }
-        return FileReadSandbox.allowAccess(files)
+        if (exempt) {
+            return FileReadSandbox.allowAccess(files)
+        }
+        return files
     }
 
     private fun stringToExistingDirsOrFiles(value: String): List<File> {
@@ -2156,7 +2159,10 @@
                 "@ followed by a path to a text file containing paths to the full set of files to parse.",
 
             "$ARG_SOURCE_PATH <paths>", "One or more directories (separated by `${File.pathSeparator}`) " +
-                "containing source files (within a package hierarchy)",
+                "containing source files (within a package hierarchy). If $ARG_STRICT_INPUT_FILES, " +
+                "$ARG_STRICT_INPUT_FILES_WARN, or $ARG_STRICT_INPUT_FILES_STACK are used, files accessed under " +
+                "$ARG_SOURCE_PATH that are not explicitly specified in $ARG_SOURCE_FILES are reported as " +
+                "violations.",
 
             "$ARG_CLASS_PATH <paths>", "One or more directories or jars (separated by " +
                 "`${File.pathSeparator}`) containing classes that should be on the classpath when parsing the " +
diff --git a/src/test/java/com/android/tools/metalava/OptionsTest.kt b/src/test/java/com/android/tools/metalava/OptionsTest.kt
index 33cfc7f..371106e 100644
--- a/src/test/java/com/android/tools/metalava/OptionsTest.kt
+++ b/src/test/java/com/android/tools/metalava/OptionsTest.kt
@@ -70,7 +70,10 @@
                                              parse.
 --source-path <paths>                        
                                              One or more directories (separated by `:`) containing source files (within
-                                             a package hierarchy)
+                                             a package hierarchy). If --strict-input-files, --strict-input-files:warn,
+                                             or --strict-input-files:stack are used, files accessed under --source-path
+                                             that are not explicitly specified in --source-files are reported as
+                                             violations.
 --classpath <paths>                          
                                              One or more directories or jars (separated by `:`) containing classes that
                                              should be on the classpath when parsing the source files