Merge changes Ieb4ffa10,I9458cbc4

* changes:
  soong_ui: Do not clean the OutDir path multiple times.
  soong_ui: Construct the proper MODULES-IN-<dir name> for m* build commands.
diff --git a/ui/build/config.go b/ui/build/config.go
index 4de019c..20bb3d1 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -307,12 +307,10 @@
 		if topDir == dir {
 			break
 		}
-		// Find the build file from the directory where the build action was triggered by traversing up
-		// the source tree. If a blank build filename is returned, simply use the directory where the build
-		// action was invoked.
+
 		buildFile := findBuildFile(ctx, relDir)
 		if buildFile == "" {
-			buildFile = filepath.Join(relDir, "Android.mk")
+			ctx.Fatalf("Build file not found for %s directory", relDir)
 		}
 		buildFiles = []string{buildFile}
 		targets = []string{convertToTarget(filepath.Dir(buildFile), targetNamePrefix)}
@@ -360,19 +358,43 @@
 	return false
 }
 
-// findBuildFile finds a build file (makefile or blueprint file) by looking at dir first. If not
-// found, go up one level and repeat again until one is found and the path of that build file
-// relative to the root directory of the source tree is returned. The returned filename of build
-// file is "Android.mk". If one was not found, a blank string is returned.
+// findBuildFile finds a build file (makefile or blueprint file) by looking if there is a build file
+// in the current and any sub directory of dir. If a build file is not found, traverse the path
+// up by one directory and repeat again until either a build file is found or reached to the root
+// source tree. The returned filename of build file is "Android.mk". If one was not found, a blank
+// string is returned.
 func findBuildFile(ctx Context, dir string) string {
-	// If the string is empty, assume it is top directory of the source tree.
-	if dir == "" {
+	// If the string is empty or ".", assume it is top directory of the source tree.
+	if dir == "" || dir == "." {
 		return ""
 	}
 
-	for ; dir != "."; dir = filepath.Dir(dir) {
-		if hasBuildFile(ctx, dir) {
-			return filepath.Join(dir, "Android.mk")
+	found := false
+	for buildDir := dir; buildDir != "."; buildDir = filepath.Dir(buildDir) {
+		err := filepath.Walk(buildDir, func(path string, info os.FileInfo, err error) error {
+			if err != nil {
+				return err
+			}
+			if found {
+				return filepath.SkipDir
+			}
+			if info.IsDir() {
+				return nil
+			}
+			for _, buildFile := range buildFiles {
+				if info.Name() == buildFile {
+					found = true
+					return filepath.SkipDir
+				}
+			}
+			return nil
+		})
+		if err != nil {
+			ctx.Fatalf("Error finding Android build file: %v", err)
+		}
+
+		if found {
+			return filepath.Join(buildDir, "Android.mk")
 		}
 	}
 
@@ -616,7 +638,7 @@
 
 func (c *configImpl) OutDir() string {
 	if outDir, ok := c.environ.Get("OUT_DIR"); ok {
-		return filepath.Clean(outDir)
+		return outDir
 	}
 	return "out"
 }
diff --git a/ui/build/config_test.go b/ui/build/config_test.go
index 18dd151..463405a 100644
--- a/ui/build/config_test.go
+++ b/ui/build/config_test.go
@@ -545,8 +545,11 @@
 		// Array of build files to create in dir.
 		buildFiles []string
 
+		// Directories that exist in the source tree.
+		dirsInTrees []string
+
 		// ********* Action *********
-		// Directory to create, also the base directory is where findBuildFile is invoked.
+		// The base directory is where findBuildFile is invoked.
 		dir string
 
 		// ********* Validation *********
@@ -555,38 +558,63 @@
 	}{{
 		description:       "build file exists at leaf directory",
 		buildFiles:        []string{"1/2/3/Android.bp"},
+		dirsInTrees:       []string{"1/2/3"},
 		dir:               "1/2/3",
 		expectedBuildFile: "1/2/3/Android.mk",
 	}, {
 		description:       "build file exists in all directory paths",
 		buildFiles:        []string{"1/Android.mk", "1/2/Android.mk", "1/2/3/Android.mk"},
+		dirsInTrees:       []string{"1/2/3"},
 		dir:               "1/2/3",
 		expectedBuildFile: "1/2/3/Android.mk",
 	}, {
 		description:       "build file does not exist in all directory paths",
 		buildFiles:        []string{},
+		dirsInTrees:       []string{"1/2/3"},
 		dir:               "1/2/3",
 		expectedBuildFile: "",
 	}, {
 		description:       "build file exists only at top directory",
 		buildFiles:        []string{"Android.bp"},
+		dirsInTrees:       []string{"1/2/3"},
 		dir:               "1/2/3",
 		expectedBuildFile: "",
 	}, {
 		description:       "build file exist in a subdirectory",
 		buildFiles:        []string{"1/2/Android.bp"},
+		dirsInTrees:       []string{"1/2/3"},
 		dir:               "1/2/3",
 		expectedBuildFile: "1/2/Android.mk",
 	}, {
 		description:       "build file exists in a subdirectory",
 		buildFiles:        []string{"1/Android.mk"},
+		dirsInTrees:       []string{"1/2/3"},
 		dir:               "1/2/3",
 		expectedBuildFile: "1/Android.mk",
 	}, {
 		description:       "top directory",
 		buildFiles:        []string{"Android.bp"},
+		dirsInTrees:       []string{},
 		dir:               ".",
 		expectedBuildFile: "",
+	}, {
+		description:       "build file exists in subdirectory",
+		buildFiles:        []string{"1/2/3/Android.bp", "1/2/4/Android.bp"},
+		dirsInTrees:       []string{"1/2/3", "1/2/4"},
+		dir:               "1/2",
+		expectedBuildFile: "1/2/Android.mk",
+	}, {
+		description:       "build file exists in parent subdirectory",
+		buildFiles:        []string{"1/5/Android.bp"},
+		dirsInTrees:       []string{"1/2/3", "1/2/4", "1/5"},
+		dir:               "1/2",
+		expectedBuildFile: "1/Android.mk",
+	}, {
+		description:       "build file exists in deep parent's subdirectory.",
+		buildFiles:        []string{"1/5/6/Android.bp"},
+		dirsInTrees:       []string{"1/2/3", "1/2/4", "1/5/6", "1/5/7"},
+		dir:               "1/2",
+		expectedBuildFile: "1/Android.mk",
 	}}
 
 	for _, tt := range tests {
@@ -601,10 +629,7 @@
 			}
 			defer os.RemoveAll(topDir)
 
-			if tt.dir != "" {
-				createDirectories(t, topDir, []string{tt.dir})
-			}
-
+			createDirectories(t, topDir, tt.dirsInTrees)
 			createBuildFiles(t, topDir, tt.buildFiles)
 
 			curDir, err := os.Getwd()
@@ -709,11 +734,23 @@
 
 	// Expected environment variables to be set.
 	expectedEnvVars []envVar
+
+	// Expecting error from running test case.
+	expectedErrStr string
 }
 
 func testGetConfigArgs(t *testing.T, tt buildActionTestCase, action BuildAction, buildDependencies bool) {
 	ctx := testContext()
 
+	defer logger.Recover(func(err error) {
+		if tt.expectedErrStr == "" {
+			t.Fatalf("Got unexpected error: %v", err)
+		}
+		if tt.expectedErrStr != err.Error() {
+			t.Errorf("expected %s, got %s", tt.expectedErrStr, err.Error())
+		}
+	})
+
 	// Environment variables to set it to blank on every test case run.
 	resetEnvVars := []string{
 		"ONE_SHOT_MAKEFILE",
@@ -780,6 +817,11 @@
 			t.Errorf("expecting %s, got %s for environment variable %s", env.value, val, env.name)
 		}
 	}
+
+	// If the execution reached here and there was an expected error code, the unit test case failed.
+	if tt.expectedErrStr != "" {
+		t.Errorf("expecting error %s", tt.expectedErrStr)
+	}
 }
 
 func TestGetConfigArgsBuildModules(t *testing.T) {
@@ -875,6 +917,7 @@
 			envVar{
 				name:  "ONE_SHOT_MAKEFILE",
 				value: "0/1/2/Android.mk"}},
+		expectedErrStr: "Build file not found for 0/1/2 directory",
 	}, {
 		description:  "build action executed at root directory",
 		dirsInTrees:  []string{},
@@ -978,7 +1021,7 @@
 			expectedArgs:    []string{},
 			expectedEnvVars: []envVar{},
 		}, {
-			description:     "build file not found - no error is expected to return",
+			description:     "build file not found",
 			dirsInTrees:     []string{"0/1/2"},
 			buildFiles:      []string{},
 			args:            []string{},
@@ -986,6 +1029,7 @@
 			tidyOnly:        "",
 			expectedArgs:    []string{"MODULES-IN-0-1-2"},
 			expectedEnvVars: []envVar{},
+			expectedErrStr:  "Build file not found for 0/1/2 directory",
 		}, {
 			description:     "GET-INSTALL-PATH specified,",
 			dirsInTrees:     []string{"0/1/2"},