Merge "Reland "m <apex_name>-deps-info prints the internal/external deps of the APEX"""
diff --git a/Android.bp b/Android.bp
index 9403b26..0382ee2 100644
--- a/Android.bp
+++ b/Android.bp
@@ -69,6 +69,7 @@
         "android/proto.go",
         "android/register.go",
         "android/rule_builder.go",
+        "android/sandbox.go",
         "android/sdk.go",
         "android/sh_binary.go",
         "android/singleton.go",
diff --git a/android/androidmk.go b/android/androidmk.go
index f3c15e4..dbf3aa8 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -323,7 +323,7 @@
 		return
 	}
 
-	err := translateAndroidMk(ctx, transMk.String(), androidMkModulesList)
+	err := translateAndroidMk(ctx, absolutePath(transMk.String()), androidMkModulesList)
 	if err != nil {
 		ctx.Errorf(err.Error())
 	}
@@ -364,8 +364,8 @@
 	}
 
 	// Don't write to the file if it hasn't changed
-	if _, err := os.Stat(mkFile); !os.IsNotExist(err) {
-		if data, err := ioutil.ReadFile(mkFile); err == nil {
+	if _, err := os.Stat(absolutePath(mkFile)); !os.IsNotExist(err) {
+		if data, err := ioutil.ReadFile(absolutePath(mkFile)); err == nil {
 			matches := buf.Len() == len(data)
 
 			if matches {
@@ -383,7 +383,7 @@
 		}
 	}
 
-	return ioutil.WriteFile(mkFile, buf.Bytes(), 0666)
+	return ioutil.WriteFile(absolutePath(mkFile), buf.Bytes(), 0666)
 }
 
 func translateAndroidMkModule(ctx SingletonContext, w io.Writer, mod blueprint.Module) error {
diff --git a/android/config.go b/android/config.go
index 101f457..3c49c1a 100644
--- a/android/config.go
+++ b/android/config.go
@@ -135,12 +135,12 @@
 }
 
 func loadConfig(config *config) error {
-	err := loadFromConfigFile(&config.FileConfigurableOptions, config.ConfigFileName)
+	err := loadFromConfigFile(&config.FileConfigurableOptions, absolutePath(config.ConfigFileName))
 	if err != nil {
 		return err
 	}
 
-	return loadFromConfigFile(&config.productVariables, config.ProductVariablesFileName)
+	return loadFromConfigFile(&config.productVariables, absolutePath(config.ProductVariablesFileName))
 }
 
 // loads configuration options from a JSON file in the cwd.
@@ -204,6 +204,17 @@
 	return nil
 }
 
+// NullConfig returns a mostly empty Config for use by standalone tools like dexpreopt_gen that
+// use the android package.
+func NullConfig(buildDir string) Config {
+	return Config{
+		config: &config{
+			buildDir: buildDir,
+			fs:       pathtools.OsFs,
+		},
+	}
+}
+
 // TestConfig returns a Config object suitable for using for tests
 func TestConfig(buildDir string, env map[string]string, bp string, fs map[string][]byte) Config {
 	envCopy := make(map[string]string)
@@ -320,7 +331,7 @@
 		buildDir:          buildDir,
 		multilibConflicts: make(map[ArchType]bool),
 
-		fs: pathtools.OsFs,
+		fs: pathtools.NewOsFs(absSrcDir),
 	}
 
 	config.deviceConfig = &deviceConfig{
@@ -350,7 +361,7 @@
 	}
 
 	inMakeFile := filepath.Join(buildDir, ".soong.in_make")
-	if _, err := os.Stat(inMakeFile); err == nil {
+	if _, err := os.Stat(absolutePath(inMakeFile)); err == nil {
 		config.inMake = true
 	}
 
@@ -398,6 +409,8 @@
 	return Config{config}, nil
 }
 
+var TestConfigOsFs = map[string][]byte{}
+
 // mockFileSystem replaces all reads with accesses to the provided map of
 // filenames to contents stored as a byte slice.
 func (c *config) mockFileSystem(bp string, fs map[string][]byte) {
@@ -901,8 +914,13 @@
 	return c.productVariables.BootJars
 }
 
-func (c *config) DexpreoptGlobalConfig() string {
-	return String(c.productVariables.DexpreoptGlobalConfig)
+func (c *config) DexpreoptGlobalConfig(ctx PathContext) ([]byte, error) {
+	if c.productVariables.DexpreoptGlobalConfig == nil {
+		return nil, nil
+	}
+	path := absolutePath(*c.productVariables.DexpreoptGlobalConfig)
+	ctx.AddNinjaFileDeps(path)
+	return ioutil.ReadFile(path)
 }
 
 func (c *config) FrameworksBaseDirExists(ctx PathContext) bool {
diff --git a/android/env.go b/android/env.go
index d9f2db2..46bd3d6 100644
--- a/android/env.go
+++ b/android/env.go
@@ -52,6 +52,17 @@
 	os.Clearenv()
 }
 
+// getenv checks either os.Getenv or originalEnv so that it works before or after the init()
+// function above.  It doesn't add any dependencies on the environment variable, so it should
+// only be used for values that won't change.  For values that might change use ctx.Config().Getenv.
+func getenv(key string) string {
+	if originalEnv == nil {
+		return os.Getenv(key)
+	} else {
+		return originalEnv[key]
+	}
+}
+
 func EnvSingleton() Singleton {
 	return &envSingleton{}
 }
@@ -66,7 +77,12 @@
 		return
 	}
 
-	err := env.WriteEnvFile(envFile.String(), envDeps)
+	data, err := env.EnvFileContents(envDeps)
+	if err != nil {
+		ctx.Errorf(err.Error())
+	}
+
+	err = WriteFileToOutputDir(envFile, data, 0666)
 	if err != nil {
 		ctx.Errorf(err.Error())
 	}
diff --git a/android/makevars.go b/android/makevars.go
index 38a028c..aba4cce 100644
--- a/android/makevars.go
+++ b/android/makevars.go
@@ -23,7 +23,6 @@
 	"strings"
 
 	"github.com/google/blueprint"
-	"github.com/google/blueprint/pathtools"
 	"github.com/google/blueprint/proptools"
 )
 
@@ -41,7 +40,6 @@
 	Config() Config
 	DeviceConfig() DeviceConfig
 	AddNinjaFileDeps(deps ...string)
-	Fs() pathtools.FileSystem
 
 	ModuleName(module blueprint.Module) string
 	ModuleDir(module blueprint.Module) string
@@ -151,7 +149,8 @@
 		return
 	}
 
-	outFile := PathForOutput(ctx, "make_vars"+proptools.String(ctx.Config().productVariables.Make_suffix)+".mk").String()
+	outFile := absolutePath(PathForOutput(ctx,
+		"make_vars"+proptools.String(ctx.Config().productVariables.Make_suffix)+".mk").String())
 
 	if ctx.Failed() {
 		return
@@ -175,15 +174,15 @@
 
 	outBytes := s.writeVars(vars)
 
-	if _, err := os.Stat(outFile); err == nil {
-		if data, err := ioutil.ReadFile(outFile); err == nil {
+	if _, err := os.Stat(absolutePath(outFile)); err == nil {
+		if data, err := ioutil.ReadFile(absolutePath(outFile)); err == nil {
 			if bytes.Equal(data, outBytes) {
 				return
 			}
 		}
 	}
 
-	if err := ioutil.WriteFile(outFile, outBytes, 0666); err != nil {
+	if err := ioutil.WriteFile(absolutePath(outFile), outBytes, 0666); err != nil {
 		ctx.Errorf(err.Error())
 	}
 }
diff --git a/android/module.go b/android/module.go
index c998007..67d1f12 100644
--- a/android/module.go
+++ b/android/module.go
@@ -16,13 +16,13 @@
 
 import (
 	"fmt"
+	"os"
 	"path"
 	"path/filepath"
 	"strings"
 	"text/scanner"
 
 	"github.com/google/blueprint"
-	"github.com/google/blueprint/pathtools"
 	"github.com/google/blueprint/proptools"
 )
 
@@ -91,7 +91,8 @@
 
 	Glob(globPattern string, excludes []string) Paths
 	GlobFiles(globPattern string, excludes []string) Paths
-	Fs() pathtools.FileSystem
+	IsSymlink(path Path) bool
+	Readlink(path Path) string
 }
 
 // BaseModuleContext is the same as blueprint.BaseModuleContext except that Config() returns
@@ -1172,6 +1173,22 @@
 	return pathsForModuleSrcFromFullPath(e, ret, false)
 }
 
+func (b *earlyModuleContext) IsSymlink(path Path) bool {
+	fileInfo, err := b.config.fs.Lstat(path.String())
+	if err != nil {
+		b.ModuleErrorf("os.Lstat(%q) failed: %s", path.String(), err)
+	}
+	return fileInfo.Mode()&os.ModeSymlink == os.ModeSymlink
+}
+
+func (b *earlyModuleContext) Readlink(path Path) string {
+	dest, err := b.config.fs.Readlink(path.String())
+	if err != nil {
+		b.ModuleErrorf("os.Readlink(%q) failed: %s", path.String(), err)
+	}
+	return dest
+}
+
 func (e *earlyModuleContext) Module() Module {
 	module, _ := e.EarlyModuleContext.Module().(Module)
 	return module
diff --git a/android/override_module.go b/android/override_module.go
index 5bc787b..9f5127d 100644
--- a/android/override_module.go
+++ b/android/override_module.go
@@ -121,13 +121,13 @@
 	// override information is propagated and aggregated correctly.
 	overridesProperty *[]string
 
-	properties overridableModuleProperties
+	overridableModuleProperties overridableModuleProperties
 }
 
 func InitOverridableModule(m OverridableModule, overridesProperty *[]string) {
 	m.setOverridableProperties(m.(Module).GetProperties())
 	m.setOverridesProperty(overridesProperty)
-	m.AddProperties(&m.moduleBase().properties)
+	m.AddProperties(&m.moduleBase().overridableModuleProperties)
 }
 
 func (o *OverridableModuleBase) moduleBase() *OverridableModuleBase {
@@ -174,7 +174,7 @@
 	if b.overridesProperty != nil {
 		*b.overridesProperty = append(*b.overridesProperty, ctx.ModuleName())
 	}
-	b.properties.OverriddenBy = o.Name()
+	b.overridableModuleProperties.OverriddenBy = o.Name()
 }
 
 // GetOverriddenBy returns the name of the override module that has overridden this module.
@@ -182,7 +182,7 @@
 // of bar is created and its properties are overriden by foo. This method returns bar when called from
 // the new local variant. It returns "" when called from the original variant of bar.
 func (b *OverridableModuleBase) GetOverriddenBy() string {
-	return b.properties.OverriddenBy
+	return b.overridableModuleProperties.OverriddenBy
 }
 
 func (b *OverridableModuleBase) OverridablePropertiesDepsMutator(ctx BottomUpMutatorContext) {
diff --git a/android/package_ctx.go b/android/package_ctx.go
index d3527fa..a228910 100644
--- a/android/package_ctx.go
+++ b/android/package_ctx.go
@@ -19,7 +19,6 @@
 	"strings"
 
 	"github.com/google/blueprint"
-	"github.com/google/blueprint/pathtools"
 )
 
 // PackageContext is a wrapper for blueprint.PackageContext that adds
@@ -60,10 +59,6 @@
 	e.pctx.AddNinjaFileDeps(deps...)
 }
 
-func (e *configErrorWrapper) Fs() pathtools.FileSystem {
-	return nil
-}
-
 type PackageVarContext interface {
 	PathContext
 	errorfContext
diff --git a/android/paths.go b/android/paths.go
index a03fe17..02f56d0 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -16,6 +16,8 @@
 
 import (
 	"fmt"
+	"io/ioutil"
+	"os"
 	"path/filepath"
 	"reflect"
 	"sort"
@@ -25,10 +27,11 @@
 	"github.com/google/blueprint/pathtools"
 )
 
+var absSrcDir string
+
 // PathContext is the subset of a (Module|Singleton)Context required by the
 // Path methods.
 type PathContext interface {
-	Fs() pathtools.FileSystem
 	Config() Config
 	AddNinjaFileDeps(deps ...string)
 }
@@ -390,7 +393,7 @@
 		return PathsWithModuleSrcSubDir(ctx, paths, ""), nil
 	} else {
 		p := pathForModuleSrc(ctx, s)
-		if exists, _, err := ctx.Fs().Exists(p.String()); err != nil {
+		if exists, _, err := ctx.Config().fs.Exists(p.String()); err != nil {
 			reportPathErrorf(ctx, "%s: %s", p, err.Error())
 		} else if !exists {
 			reportPathErrorf(ctx, "module source path %q does not exist", p)
@@ -720,7 +723,7 @@
 		var deps []string
 		// We cannot add build statements in this context, so we fall back to
 		// AddNinjaFileDeps
-		files, deps, err = pathtools.Glob(path.String(), nil, pathtools.FollowSymlinks)
+		files, deps, err = ctx.Config().fs.Glob(path.String(), nil, pathtools.FollowSymlinks)
 		ctx.AddNinjaFileDeps(deps...)
 	}
 
@@ -752,7 +755,7 @@
 		if !exists {
 			modCtx.AddMissingDependencies([]string{path.String()})
 		}
-	} else if exists, _, err := ctx.Fs().Exists(path.String()); err != nil {
+	} else if exists, _, err := ctx.Config().fs.Exists(path.String()); err != nil {
 		reportPathErrorf(ctx, "%s: %s", path, err.Error())
 	} else if !exists {
 		reportPathErrorf(ctx, "source path %q does not exist", path)
@@ -1356,7 +1359,6 @@
 	config Config
 }
 
-func (x *testPathContext) Fs() pathtools.FileSystem   { return x.config.fs }
 func (x *testPathContext) Config() Config             { return x.config }
 func (x *testPathContext) AddNinjaFileDeps(...string) {}
 
@@ -1402,3 +1404,16 @@
 	}
 	return rel, true, nil
 }
+
+// Writes a file to the output directory.  Attempting to write directly to the output directory
+// will fail due to the sandbox of the soong_build process.
+func WriteFileToOutputDir(path WritablePath, data []byte, perm os.FileMode) error {
+	return ioutil.WriteFile(absolutePath(path.String()), data, perm)
+}
+
+func absolutePath(path string) string {
+	if filepath.IsAbs(path) {
+		return path
+	}
+	return filepath.Join(absSrcDir, path)
+}
diff --git a/android/paths_test.go b/android/paths_test.go
index ec5e598..46e3e1f 100644
--- a/android/paths_test.go
+++ b/android/paths_test.go
@@ -21,7 +21,6 @@
 	"strings"
 	"testing"
 
-	"github.com/google/blueprint/pathtools"
 	"github.com/google/blueprint/proptools"
 )
 
@@ -207,10 +206,6 @@
 	inRoot         bool
 }
 
-func (moduleInstallPathContextImpl) Fs() pathtools.FileSystem {
-	return pathtools.MockFs(nil)
-}
-
 func (m moduleInstallPathContextImpl) Config() Config {
 	return m.baseModuleContext.config
 }
diff --git a/android/register.go b/android/register.go
index b5defec..b48d3d1 100644
--- a/android/register.go
+++ b/android/register.go
@@ -84,7 +84,9 @@
 }
 
 func NewContext() *Context {
-	return &Context{blueprint.NewContext()}
+	ctx := &Context{blueprint.NewContext()}
+	ctx.SetSrcDir(absSrcDir)
+	return ctx
 }
 
 func (ctx *Context) Register() {
diff --git a/android/sandbox.go b/android/sandbox.go
new file mode 100644
index 0000000..ed022fb
--- /dev/null
+++ b/android/sandbox.go
@@ -0,0 +1,47 @@
+// Copyright 2020 Google Inc. All rights reserved.
+//
+// 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 android
+
+import (
+	"fmt"
+	"os"
+)
+
+func init() {
+	// Stash the working directory in a private variable and then change the working directory
+	// to "/", which will prevent untracked accesses to files by Go Soong plugins. The
+	// SOONG_SANDBOX_SOONG_BUILD environment variable is set by soong_ui, and is not
+	// overrideable on the command line.
+
+	orig, err := os.Getwd()
+	if err != nil {
+		panic(fmt.Errorf("failed to get working directory: %s", err))
+	}
+	absSrcDir = orig
+
+	if getenv("SOONG_SANDBOX_SOONG_BUILD") == "true" {
+		err = os.Chdir("/")
+		if err != nil {
+			panic(fmt.Errorf("failed to change working directory to '/': %s", err))
+		}
+	}
+}
+
+// DO NOT USE THIS FUNCTION IN NEW CODE.
+// Deprecated: This function will be removed as soon as the existing use cases that use it have been
+// replaced.
+func AbsSrcDirForExistingUseCases() string {
+	return absSrcDir
+}
diff --git a/android/singleton.go b/android/singleton.go
index 5519ca0..91268ad 100644
--- a/android/singleton.go
+++ b/android/singleton.go
@@ -16,7 +16,6 @@
 
 import (
 	"github.com/google/blueprint"
-	"github.com/google/blueprint/pathtools"
 )
 
 // SingletonContext
@@ -74,8 +73,6 @@
 	// builder whenever a file matching the pattern as added or removed, without rerunning if a
 	// file that does not match the pattern is added to a searched directory.
 	GlobWithDeps(pattern string, excludes []string) ([]string, error)
-
-	Fs() pathtools.FileSystem
 }
 
 type singletonAdaptor struct {
diff --git a/androidmk/Android.bp b/androidmk/Android.bp
index 4110073..70fc1f7 100644
--- a/androidmk/Android.bp
+++ b/androidmk/Android.bp
@@ -41,7 +41,6 @@
         "androidmk-parser",
         "blueprint-parser",
         "bpfix-lib",
-        "soong-android",
     ],
 }
 
diff --git a/androidmk/androidmk/android.go b/androidmk/androidmk/android.go
index 0082d8b..8860984 100644
--- a/androidmk/androidmk/android.go
+++ b/androidmk/androidmk/android.go
@@ -15,9 +15,9 @@
 package androidmk
 
 import (
-	"android/soong/android"
 	mkparser "android/soong/androidmk/parser"
 	"fmt"
+	"sort"
 	"strings"
 
 	bpparser "github.com/google/blueprint/parser"
@@ -350,7 +350,13 @@
 		return err
 	}
 
-	for _, nameClassification := range android.SortedStringKeys(namesByClassification) {
+	var classifications []string
+	for classification := range namesByClassification {
+		classifications = append(classifications, classification)
+	}
+	sort.Strings(classifications)
+
+	for _, nameClassification := range classifications {
 		name := namesByClassification[nameClassification]
 		if component, ok := lists[nameClassification]; ok && !emptyList(component) {
 			err = setVariable(ctx.file, ctx.append, ctx.prefix, name, component, true)
diff --git a/apex/androidmk.go b/apex/androidmk.go
index 5cdbcd6..b2fe8da 100644
--- a/apex/androidmk.go
+++ b/apex/androidmk.go
@@ -151,9 +151,19 @@
 			fmt.Fprintln(w, "include $(BUILD_SYSTEM)/soong_cc_prebuilt.mk")
 		} else {
 			fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", fi.builtFile.Base())
-			// For flattened apexes, compat symlinks are attached to apex_manifest.json which is guaranteed for every apex
-			if a.primaryApexType && fi.builtFile == a.manifestPbOut && len(a.compatSymlinks) > 0 {
-				fmt.Fprintln(w, "LOCAL_POST_INSTALL_CMD :=", strings.Join(a.compatSymlinks, " && "))
+			if a.primaryApexType && fi.builtFile == a.manifestPbOut {
+				// Make apex_manifest.pb module for this APEX to override all other
+				// modules in the APEXes being overridden by this APEX
+				var patterns []string
+				for _, o := range a.overridableProperties.Overrides {
+					patterns = append(patterns, "%."+o+a.suffix)
+				}
+				fmt.Fprintln(w, "LOCAL_OVERRIDES_MODULES :=", strings.Join(patterns, " "))
+
+				if len(a.compatSymlinks) > 0 {
+					// For flattened apexes, compat symlinks are attached to apex_manifest.json which is guaranteed for every apex
+					fmt.Fprintln(w, "LOCAL_POST_INSTALL_CMD :=", strings.Join(a.compatSymlinks, " && "))
+				}
 			}
 			fmt.Fprintln(w, "include $(BUILD_PREBUILT)")
 		}
diff --git a/cc/cc.go b/cc/cc.go
index 0bab41f..d1b97b4 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -2481,7 +2481,25 @@
 }
 
 func (c *Module) installable() bool {
-	return c.installer != nil && !c.Properties.PreventInstall && c.IsForPlatform() && c.outputFile.Valid()
+	ret := c.installer != nil && !c.Properties.PreventInstall && c.outputFile.Valid()
+
+	// The platform variant doesn't need further condition. Apex variants however might not
+	// be installable because it will likely to be included in the APEX and won't appear
+	// in the system partition.
+	if c.IsForPlatform() {
+		return ret
+	}
+
+	// Special case for modules that are configured to be installed to /data, which includes
+	// test modules. For these modules, both APEX and non-APEX variants are considered as
+	// installable. This is because even the APEX variants won't be included in the APEX, but
+	// will anyway be installed to /data/*.
+	// See b/146995717
+	if c.InstallInData() {
+		return ret
+	}
+
+	return false
 }
 
 func (c *Module) AllStaticDeps() []string {
diff --git a/cc/cmakelists.go b/cc/cmakelists.go
index 97d21f4..f7d9081 100644
--- a/cc/cmakelists.go
+++ b/cc/cmakelists.go
@@ -76,7 +76,7 @@
 	// Link all handmade CMakeLists.txt aggregate from
 	//     BASE/development/ide/clion to
 	// BASE/out/development/ide/clion.
-	dir := filepath.Join(getAndroidSrcRootDirectory(ctx), cLionAggregateProjectsDirectory)
+	dir := filepath.Join(android.AbsSrcDirForExistingUseCases(), cLionAggregateProjectsDirectory)
 	filepath.Walk(dir, linkAggregateCMakeListsFiles)
 
 	return
@@ -147,7 +147,7 @@
 	f.WriteString("# Tools > CMake > Change Project Root  \n\n")
 	f.WriteString(fmt.Sprintf("cmake_minimum_required(VERSION %s)\n", minimumCMakeVersionSupported))
 	f.WriteString(fmt.Sprintf("project(%s)\n", ccModule.ModuleBase.Name()))
-	f.WriteString(fmt.Sprintf("set(ANDROID_ROOT %s)\n\n", getAndroidSrcRootDirectory(ctx)))
+	f.WriteString(fmt.Sprintf("set(ANDROID_ROOT %s)\n\n", android.AbsSrcDirForExistingUseCases()))
 
 	pathToCC, _ := evalVariable(ctx, "${config.ClangBin}/")
 	f.WriteString(fmt.Sprintf("set(CMAKE_C_COMPILER \"%s%s\")\n", buildCMakePath(pathToCC), "clang"))
@@ -465,7 +465,7 @@
 }
 
 func getCMakeListsForModule(module *Module, ctx android.SingletonContext) string {
-	return filepath.Join(getAndroidSrcRootDirectory(ctx),
+	return filepath.Join(android.AbsSrcDirForExistingUseCases(),
 		cLionOutputProjectsDirectory,
 		path.Dir(ctx.BlueprintFile(module)),
 		module.ModuleBase.Name()+"-"+
@@ -473,8 +473,3 @@
 			module.ModuleBase.Os().Name,
 		cMakeListsFilename)
 }
-
-func getAndroidSrcRootDirectory(ctx android.SingletonContext) string {
-	srcPath, _ := filepath.Abs(android.PathForSource(ctx).String())
-	return srcPath
-}
diff --git a/cc/compdb.go b/cc/compdb.go
index dff14db..ea12443 100644
--- a/cc/compdb.go
+++ b/cc/compdb.go
@@ -79,9 +79,9 @@
 
 	// Create the output file.
 	dir := android.PathForOutput(ctx, compdbOutputProjectsDirectory)
-	os.MkdirAll(dir.String(), 0777)
+	os.MkdirAll(filepath.Join(android.AbsSrcDirForExistingUseCases(), dir.String()), 0777)
 	compDBFile := dir.Join(ctx, compdbFilename)
-	f, err := os.Create(compDBFile.String())
+	f, err := os.Create(filepath.Join(android.AbsSrcDirForExistingUseCases(), compDBFile.String()))
 	if err != nil {
 		log.Fatalf("Could not create file %s: %s", compDBFile, err)
 	}
@@ -103,8 +103,8 @@
 	}
 	f.Write(dat)
 
-	finalLinkPath := filepath.Join(ctx.Config().Getenv(envVariableCompdbLink), compdbFilename)
-	if finalLinkPath != "" {
+	if finalLinkDir := ctx.Config().Getenv(envVariableCompdbLink); finalLinkDir != "" {
+		finalLinkPath := filepath.Join(finalLinkDir, compdbFilename)
 		os.Remove(finalLinkPath)
 		if err := os.Symlink(compDBFile.String(), finalLinkPath); err != nil {
 			log.Fatalf("Unable to symlink %s to %s: %s", compDBFile, finalLinkPath, err)
@@ -174,18 +174,17 @@
 		return
 	}
 
-	rootDir := getCompdbAndroidSrcRootDirectory(ctx)
-	pathToCC, err := ctx.Eval(pctx, rootDir+"/${config.ClangBin}/")
+	pathToCC, err := ctx.Eval(pctx, "${config.ClangBin}")
 	ccPath := "/bin/false"
 	cxxPath := "/bin/false"
 	if err == nil {
-		ccPath = pathToCC + "clang"
-		cxxPath = pathToCC + "clang++"
+		ccPath = filepath.Join(pathToCC, "clang")
+		cxxPath = filepath.Join(pathToCC, "clang++")
 	}
 	for _, src := range srcs {
 		if _, ok := builds[src.String()]; !ok {
 			builds[src.String()] = compDbEntry{
-				Directory: rootDir,
+				Directory: android.AbsSrcDirForExistingUseCases(),
 				Arguments: getArguments(src, ctx, ccModule, ccPath, cxxPath),
 				File:      src.String(),
 			}
@@ -200,8 +199,3 @@
 	}
 	return []string{""}, err
 }
-
-func getCompdbAndroidSrcRootDirectory(ctx android.SingletonContext) string {
-	srcPath, _ := filepath.Abs(android.PathForSource(ctx).String())
-	return srcPath
-}
diff --git a/cc/ndk_headers.go b/cc/ndk_headers.go
index b8423be..5744bb2 100644
--- a/cc/ndk_headers.go
+++ b/cc/ndk_headers.go
@@ -16,7 +16,6 @@
 
 import (
 	"fmt"
-	"os"
 	"path/filepath"
 	"strings"
 
@@ -255,16 +254,8 @@
 	depsPath := android.PathForSource(ctx, "bionic/libc/versioner-dependencies")
 	depsGlob := ctx.Glob(filepath.Join(depsPath.String(), "**/*"), nil)
 	for i, path := range depsGlob {
-		fileInfo, err := os.Lstat(path.String())
-		if err != nil {
-			ctx.ModuleErrorf("os.Lstat(%q) failed: %s", path.String, err)
-		}
-		if fileInfo.Mode()&os.ModeSymlink == os.ModeSymlink {
-			dest, err := os.Readlink(path.String())
-			if err != nil {
-				ctx.ModuleErrorf("os.Readlink(%q) failed: %s",
-					path.String, err)
-			}
+		if ctx.IsSymlink(path) {
+			dest := ctx.Readlink(path)
 			// Additional .. to account for the symlink itself.
 			depsGlob[i] = android.PathForSource(
 				ctx, filepath.Clean(filepath.Join(path.String(), "..", dest)))
diff --git a/dexpreopt/config.go b/dexpreopt/config.go
index 0c79ccc..2a929c5 100644
--- a/dexpreopt/config.go
+++ b/dexpreopt/config.go
@@ -16,7 +16,6 @@
 
 import (
 	"encoding/json"
-	"io/ioutil"
 	"strings"
 
 	"android/soong/android"
@@ -185,7 +184,7 @@
 // soongConfig argument. LoadGlobalConfig is used directly in Soong and in
 // dexpreopt_gen called from Make to read the $OUT/dexpreopt.config written by
 // Make.
-func LoadGlobalConfig(ctx android.PathContext, path string, soongConfig GlobalSoongConfig) (GlobalConfig, []byte, error) {
+func LoadGlobalConfig(ctx android.PathContext, data []byte, soongConfig GlobalSoongConfig) (GlobalConfig, error) {
 	type GlobalJSONConfig struct {
 		GlobalConfig
 
@@ -196,9 +195,9 @@
 	}
 
 	config := GlobalJSONConfig{}
-	data, err := loadConfig(ctx, path, &config)
+	err := json.Unmarshal(data, &config)
 	if err != nil {
-		return config.GlobalConfig, nil, err
+		return config.GlobalConfig, err
 	}
 
 	// Construct paths that require a PathContext.
@@ -209,13 +208,13 @@
 	// either CreateGlobalSoongConfig or LoadGlobalSoongConfig).
 	config.GlobalConfig.SoongConfig = soongConfig
 
-	return config.GlobalConfig, data, nil
+	return config.GlobalConfig, nil
 }
 
 // LoadModuleConfig reads a per-module dexpreopt.config file into a ModuleConfig struct.  It is not used in Soong, which
 // receives a ModuleConfig struct directly from java/dexpreopt.go.  It is used in dexpreopt_gen called from oMake to
 // read the module dexpreopt.config written by Make.
-func LoadModuleConfig(ctx android.PathContext, path string) (ModuleConfig, error) {
+func LoadModuleConfig(ctx android.PathContext, data []byte) (ModuleConfig, error) {
 	type ModuleJSONConfig struct {
 		ModuleConfig
 
@@ -233,7 +232,7 @@
 
 	config := ModuleJSONConfig{}
 
-	_, err := loadConfig(ctx, path, &config)
+	err := json.Unmarshal(data, &config)
 	if err != nil {
 		return config.ModuleConfig, err
 	}
@@ -289,10 +288,10 @@
 
 // LoadGlobalSoongConfig reads the dexpreopt_soong.config file into a
 // GlobalSoongConfig struct. It is only used in dexpreopt_gen.
-func LoadGlobalSoongConfig(ctx android.PathContext, path string) (GlobalSoongConfig, error) {
+func LoadGlobalSoongConfig(ctx android.PathContext, data []byte) (GlobalSoongConfig, error) {
 	var jc globalJsonSoongConfig
 
-	_, err := loadConfig(ctx, path, &jc)
+	err := json.Unmarshal(data, &jc)
 	if err != nil {
 		return GlobalSoongConfig{}, err
 	}
@@ -352,26 +351,6 @@
 	}, " "))
 }
 
-func loadConfig(ctx android.PathContext, path string, config interface{}) ([]byte, error) {
-	r, err := ctx.Fs().Open(path)
-	if err != nil {
-		return nil, err
-	}
-	defer r.Close()
-
-	data, err := ioutil.ReadAll(r)
-	if err != nil {
-		return nil, err
-	}
-
-	err = json.Unmarshal(data, config)
-	if err != nil {
-		return nil, err
-	}
-
-	return data, nil
-}
-
 func GlobalConfigForTests(ctx android.PathContext) GlobalConfig {
 	return GlobalConfig{
 		DisablePreopt:                      false,
diff --git a/dexpreopt/dexpreopt_gen/dexpreopt_gen.go b/dexpreopt/dexpreopt_gen/dexpreopt_gen.go
index d2faa00..e2818bb 100644
--- a/dexpreopt/dexpreopt_gen/dexpreopt_gen.go
+++ b/dexpreopt/dexpreopt_gen/dexpreopt_gen.go
@@ -18,6 +18,7 @@
 	"bytes"
 	"flag"
 	"fmt"
+	"io/ioutil"
 	"os"
 	"path/filepath"
 	"runtime"
@@ -41,7 +42,6 @@
 	config android.Config
 }
 
-func (x *pathContext) Fs() pathtools.FileSystem   { return pathtools.OsFs }
 func (x *pathContext) Config() android.Config     { return x.config }
 func (x *pathContext) AddNinjaFileDeps(...string) {}
 
@@ -76,21 +76,39 @@
 		usage("--module configuration file is required")
 	}
 
-	ctx := &pathContext{android.TestConfig(*outDir, nil, "", nil)}
+	ctx := &pathContext{android.NullConfig(*outDir)}
 
-	globalSoongConfig, err := dexpreopt.LoadGlobalSoongConfig(ctx, *globalSoongConfigPath)
+	globalSoongConfigData, err := ioutil.ReadFile(*globalSoongConfigPath)
+	if err != nil {
+		fmt.Fprintf(os.Stderr, "error reading global config %q: %s\n", *globalSoongConfigPath, err)
+		os.Exit(2)
+	}
+
+	globalSoongConfig, err := dexpreopt.LoadGlobalSoongConfig(ctx, globalSoongConfigData)
 	if err != nil {
 		fmt.Fprintf(os.Stderr, "error loading global config %q: %s\n", *globalSoongConfigPath, err)
 		os.Exit(2)
 	}
 
-	globalConfig, _, err := dexpreopt.LoadGlobalConfig(ctx, *globalConfigPath, globalSoongConfig)
+	globalConfigData, err := ioutil.ReadFile(*globalConfigPath)
 	if err != nil {
-		fmt.Fprintf(os.Stderr, "error loading global config %q: %s\n", *globalConfigPath, err)
+		fmt.Fprintf(os.Stderr, "error reading global config %q: %s\n", *globalConfigPath, err)
 		os.Exit(2)
 	}
 
-	moduleConfig, err := dexpreopt.LoadModuleConfig(ctx, *moduleConfigPath)
+	globalConfig, err := dexpreopt.LoadGlobalConfig(ctx, globalConfigData, globalSoongConfig)
+	if err != nil {
+		fmt.Fprintf(os.Stderr, "error parse global config %q: %s\n", *globalConfigPath, err)
+		os.Exit(2)
+	}
+
+	moduleConfigData, err := ioutil.ReadFile(*moduleConfigPath)
+	if err != nil {
+		fmt.Fprintf(os.Stderr, "error reading module config %q: %s\n", *moduleConfigPath, err)
+		os.Exit(2)
+	}
+
+	moduleConfig, err := dexpreopt.LoadModuleConfig(ctx, moduleConfigData)
 	if err != nil {
 		fmt.Fprintf(os.Stderr, "error loading module config %q: %s\n", *moduleConfigPath, err)
 		os.Exit(2)
diff --git a/env/env.go b/env/env.go
index bf58a99..a98e1f6 100644
--- a/env/env.go
+++ b/env/env.go
@@ -27,7 +27,7 @@
 type envFileEntry struct{ Key, Value string }
 type envFileData []envFileEntry
 
-func WriteEnvFile(filename string, envDeps map[string]string) error {
+func EnvFileContents(envDeps map[string]string) ([]byte, error) {
 	contents := make(envFileData, 0, len(envDeps))
 	for key, value := range envDeps {
 		contents = append(contents, envFileEntry{key, value})
@@ -37,17 +37,12 @@
 
 	data, err := json.MarshalIndent(contents, "", "    ")
 	if err != nil {
-		return err
+		return nil, err
 	}
 
 	data = append(data, '\n')
 
-	err = ioutil.WriteFile(filename, data, 0664)
-	if err != nil {
-		return err
-	}
-
-	return nil
+	return data, nil
 }
 
 func StaleEnvFile(filename string) (bool, error) {
diff --git a/java/dexpreopt.go b/java/dexpreopt.go
index 479dec6..da68660 100644
--- a/java/dexpreopt.go
+++ b/java/dexpreopt.go
@@ -85,6 +85,11 @@
 		return true
 	}
 
+	// Don't preopt APEX variant module
+	if am, ok := ctx.Module().(android.ApexModule); ok && !am.IsForPlatform() {
+		return true
+	}
+
 	// TODO: contains no java code
 
 	return false
@@ -101,9 +106,8 @@
 
 	global := dexpreoptGlobalConfig(ctx)
 	bootImage := defaultBootImageConfig(ctx)
-	defaultBootImage := bootImage
 	if global.UseApexImage {
-		bootImage = apexBootImageConfig(ctx)
+		bootImage = frameworkJZBootImageConfig(ctx)
 	}
 
 	var archs []android.ArchType
@@ -174,11 +178,8 @@
 		DexPreoptImagesDeps:     imagesDeps,
 		DexPreoptImageLocations: bootImage.imageLocations,
 
-		// We use the dex paths and dex locations of the default boot image, as it
-		// contains the full dexpreopt boot classpath. Other images may just contain a subset of
-		// the dexpreopt boot classpath.
-		PreoptBootClassPathDexFiles:     defaultBootImage.dexPathsDeps.Paths(),
-		PreoptBootClassPathDexLocations: defaultBootImage.dexLocationsDeps,
+		PreoptBootClassPathDexFiles:     bootImage.dexPathsDeps.Paths(),
+		PreoptBootClassPathDexLocations: bootImage.dexLocationsDeps,
 
 		PreoptExtractedApk: false,
 
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index fe5bed5..66840b5 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -220,7 +220,8 @@
 	d.otherImages = append(d.otherImages, buildBootImage(ctx, artBootImageConfig(ctx)))
 	if global.GenerateApexImage {
 		// Create boot images for the JIT-zygote experiment.
-		d.otherImages = append(d.otherImages, buildBootImage(ctx, apexBootImageConfig(ctx)))
+		d.otherImages = append(d.otherImages, buildBootImage(ctx, artJZBootImageConfig(ctx)))
+		d.otherImages = append(d.otherImages, buildBootImage(ctx, frameworkJZBootImageConfig(ctx)))
 	}
 
 	dumpOatRules(ctx, d.defaultBootImage)
diff --git a/java/dexpreopt_bootjars_test.go b/java/dexpreopt_bootjars_test.go
index 8f29e9e..4ce30f6 100644
--- a/java/dexpreopt_bootjars_test.go
+++ b/java/dexpreopt_bootjars_test.go
@@ -48,7 +48,7 @@
 
 	pathCtx := android.PathContextForTesting(config)
 	dexpreoptConfig := dexpreopt.GlobalConfigForTests(pathCtx)
-	dexpreoptConfig.ArtApexJars = []string{"foo", "bar", "baz"}
+	dexpreoptConfig.BootJars = []string{"foo", "bar", "baz"}
 	setDexpreoptTestGlobalConfig(config, dexpreoptConfig)
 
 	ctx := testContext()
@@ -59,9 +59,10 @@
 
 	dexpreoptBootJars := ctx.SingletonForTests("dex_bootjars")
 
-	bootArt := dexpreoptBootJars.Output("boot.art")
+	bootArt := dexpreoptBootJars.Output("boot-foo.art")
 
 	expectedInputs := []string{
+		"dex_artjars/apex/com.android.art/javalib/arm64/boot.art",
 		"dex_bootjars_input/foo.jar",
 		"dex_bootjars_input/bar.jar",
 		"dex_bootjars_input/baz.jar",
@@ -82,19 +83,19 @@
 	expectedOutputs := []string{
 		"dex_bootjars/system/framework/arm64/boot.invocation",
 
-		"dex_bootjars/system/framework/arm64/boot.art",
+		"dex_bootjars/system/framework/arm64/boot-foo.art",
 		"dex_bootjars/system/framework/arm64/boot-bar.art",
 		"dex_bootjars/system/framework/arm64/boot-baz.art",
 
-		"dex_bootjars/system/framework/arm64/boot.oat",
+		"dex_bootjars/system/framework/arm64/boot-foo.oat",
 		"dex_bootjars/system/framework/arm64/boot-bar.oat",
 		"dex_bootjars/system/framework/arm64/boot-baz.oat",
 
-		"dex_bootjars/system/framework/arm64/boot.vdex",
+		"dex_bootjars/system/framework/arm64/boot-foo.vdex",
 		"dex_bootjars/system/framework/arm64/boot-bar.vdex",
 		"dex_bootjars/system/framework/arm64/boot-baz.vdex",
 
-		"dex_bootjars_unstripped/system/framework/arm64/boot.oat",
+		"dex_bootjars_unstripped/system/framework/arm64/boot-foo.oat",
 		"dex_bootjars_unstripped/system/framework/arm64/boot-bar.oat",
 		"dex_bootjars_unstripped/system/framework/arm64/boot-baz.oat",
 	}
diff --git a/java/dexpreopt_config.go b/java/dexpreopt_config.go
index 35748b8..31bec93 100644
--- a/java/dexpreopt_config.go
+++ b/java/dexpreopt_config.go
@@ -36,10 +36,11 @@
 
 func dexpreoptGlobalConfigRaw(ctx android.PathContext) globalConfigAndRaw {
 	return ctx.Config().Once(dexpreoptGlobalConfigKey, func() interface{} {
-		if f := ctx.Config().DexpreoptGlobalConfig(); f != "" {
+		if data, err := ctx.Config().DexpreoptGlobalConfig(ctx); err != nil {
+			panic(err)
+		} else if data != nil {
 			soongConfig := dexpreopt.CreateGlobalSoongConfig(ctx)
-			ctx.AddNinjaFileDeps(f)
-			globalConfig, data, err := dexpreopt.LoadGlobalConfig(ctx, f, soongConfig)
+			globalConfig, err := dexpreopt.LoadGlobalConfig(ctx, data, soongConfig)
 			if err != nil {
 				panic(err)
 			}
@@ -121,10 +122,11 @@
 }
 
 var (
-	bootImageConfigKey     = android.NewOnceKey("bootImageConfig")
-	artBootImageName       = "art"
-	frameworkBootImageName = "boot"
-	apexBootImageName      = "apex"
+	bootImageConfigKey       = android.NewOnceKey("bootImageConfig")
+	artBootImageName         = "art"
+	frameworkBootImageName   = "boot"
+	artJZBootImageName       = "jitzygote-art"
+	frameworkJZBootImageName = "jitzygote-boot"
 )
 
 // Construct the global boot image configs.
@@ -167,33 +169,44 @@
 		}
 
 		// Framework config for the boot image extension.
-		// It includes both the Core libraries and framework.
+		// It includes framework libraries and depends on the ART config.
 		frameworkCfg := bootImageConfig{
-			extension:        false,
+			extension:        true,
 			name:             frameworkBootImageName,
 			stem:             "boot",
 			installSubdir:    frameworkSubdir,
-			modules:          concat(artModules, frameworkModules),
-			dexLocations:     concat(artLocations, frameworkLocations),
-			dexLocationsDeps: concat(artLocations, frameworkLocations),
+			modules:          frameworkModules,
+			dexLocations:     frameworkLocations,
+			dexLocationsDeps: append(artLocations, frameworkLocations...),
 		}
 
-		// Apex config for the  boot image used in the JIT-zygote experiment.
-		// It includes both the Core libraries and framework.
-		apexCfg := bootImageConfig{
+		// ART config for JIT-zygote boot image.
+		artJZCfg := bootImageConfig{
 			extension:        false,
-			name:             apexBootImageName,
+			name:             artJZBootImageName,
+			stem:             "apex",
+			installSubdir:    artSubdir,
+			modules:          artModules,
+			dexLocations:     artLocations,
+			dexLocationsDeps: artLocations,
+		}
+
+		// Framework config for JIT-zygote boot image extension.
+		frameworkJZCfg := bootImageConfig{
+			extension:        true,
+			name:             frameworkJZBootImageName,
 			stem:             "apex",
 			installSubdir:    frameworkSubdir,
-			modules:          concat(artModules, frameworkModules),
-			dexLocations:     concat(artLocations, frameworkLocations),
-			dexLocationsDeps: concat(artLocations, frameworkLocations),
+			modules:          frameworkModules,
+			dexLocations:     frameworkLocations,
+			dexLocationsDeps: append(artLocations, frameworkLocations...),
 		}
 
 		configs := map[string]*bootImageConfig{
-			artBootImageName:       &artCfg,
-			frameworkBootImageName: &frameworkCfg,
-			apexBootImageName:      &apexCfg,
+			artBootImageName:         &artCfg,
+			frameworkBootImageName:   &frameworkCfg,
+			artJZBootImageName:       &artJZCfg,
+			frameworkJZBootImageName: &frameworkJZCfg,
 		}
 
 		// common to all configs
@@ -231,6 +244,14 @@
 			c.zip = c.dir.Join(ctx, c.name+".zip")
 		}
 
+		// specific to the framework config
+		frameworkCfg.dexPathsDeps = append(artCfg.dexPathsDeps, frameworkCfg.dexPathsDeps...)
+		frameworkCfg.imageLocations = append(artCfg.imageLocations, frameworkCfg.imageLocations...)
+
+		// specific to the jitzygote-framework config
+		frameworkJZCfg.dexPathsDeps = append(artJZCfg.dexPathsDeps, frameworkJZCfg.dexPathsDeps...)
+		frameworkJZCfg.imageLocations = append(artJZCfg.imageLocations, frameworkJZCfg.imageLocations...)
+
 		return configs
 	}).(map[string]*bootImageConfig)
 }
@@ -243,8 +264,12 @@
 	return *genBootImageConfigs(ctx)[frameworkBootImageName]
 }
 
-func apexBootImageConfig(ctx android.PathContext) bootImageConfig {
-	return *genBootImageConfigs(ctx)[apexBootImageName]
+func artJZBootImageConfig(ctx android.PathContext) bootImageConfig {
+	return *genBootImageConfigs(ctx)[artJZBootImageName]
+}
+
+func frameworkJZBootImageConfig(ctx android.PathContext) bootImageConfig {
+	return *genBootImageConfigs(ctx)[frameworkJZBootImageName]
 }
 
 func defaultBootclasspath(ctx android.PathContext) []string {
diff --git a/java/java.go b/java/java.go
index 50ffd65..5afdc2f 100644
--- a/java/java.go
+++ b/java/java.go
@@ -660,7 +660,14 @@
 		}
 	}
 
-	if j.shouldInstrumentStatic(ctx) {
+	// Framework libraries need special handling in static coverage builds: they should not have
+	// static dependency on jacoco, otherwise there would be multiple conflicting definitions of
+	// the same jacoco classes coming from different bootclasspath jars.
+	if inList(ctx.ModuleName(), config.InstrumentFrameworkModules) {
+		if ctx.Config().IsEnvTrue("EMMA_INSTRUMENT_FRAMEWORK") {
+			j.properties.Instrument = true
+		}
+	} else if j.shouldInstrumentStatic(ctx) {
 		ctx.AddVariationDependencies(nil, staticLibTag, "jacocoagent")
 	}
 }
@@ -1463,12 +1470,6 @@
 		j.headerJarFile = j.implementationJarFile
 	}
 
-	if ctx.Config().IsEnvTrue("EMMA_INSTRUMENT_FRAMEWORK") {
-		if inList(ctx.ModuleName(), config.InstrumentFrameworkModules) {
-			j.properties.Instrument = true
-		}
-	}
-
 	if j.shouldInstrument(ctx) {
 		outputFile = j.instrument(ctx, flags, outputFile, jarName)
 	}
diff --git a/java/jdeps.go b/java/jdeps.go
index fccc40f..49e3de3 100644
--- a/java/jdeps.go
+++ b/java/jdeps.go
@@ -17,7 +17,6 @@
 import (
 	"encoding/json"
 	"fmt"
-	"os"
 
 	"android/soong/android"
 )
@@ -92,23 +91,21 @@
 		moduleInfos[name] = dpInfo
 	})
 
-	jfpath := android.PathForOutput(ctx, jdepsJsonFileName).String()
+	jfpath := android.PathForOutput(ctx, jdepsJsonFileName)
 	err := createJsonFile(moduleInfos, jfpath)
 	if err != nil {
 		ctx.Errorf(err.Error())
 	}
 }
 
-func createJsonFile(moduleInfos map[string]android.IdeInfo, jfpath string) error {
-	file, err := os.Create(jfpath)
-	if err != nil {
-		return fmt.Errorf("Failed to create file: %s, relative: %v", jdepsJsonFileName, err)
-	}
-	defer file.Close()
+func createJsonFile(moduleInfos map[string]android.IdeInfo, jfpath android.WritablePath) error {
 	buf, err := json.MarshalIndent(moduleInfos, "", "\t")
 	if err != nil {
-		return fmt.Errorf("Write file failed: %s, relative: %v", jdepsJsonFileName, err)
+		return fmt.Errorf("JSON marshal of java deps failed: %s", err)
 	}
-	fmt.Fprintf(file, string(buf))
+	err = android.WriteFileToOutputDir(jfpath, buf, 0666)
+	if err != nil {
+		return fmt.Errorf("Writing java deps to %s failed: %s", jfpath.String(), err)
+	}
 	return nil
 }
diff --git a/rust/config/global.go b/rust/config/global.go
index ad8eb3a..fb9b14b 100644
--- a/rust/config/global.go
+++ b/rust/config/global.go
@@ -29,7 +29,6 @@
 	DefaultEdition     = "2018"
 	Stdlibs            = []string{
 		"libstd",
-		"libterm",
 		"libtest",
 	}
 
diff --git a/ui/build/ninja.go b/ui/build/ninja.go
index 8c6ebb8..0b56b67 100644
--- a/ui/build/ninja.go
+++ b/ui/build/ninja.go
@@ -127,6 +127,7 @@
 			"GOMA_USE_LOCAL",
 
 			// RBE client
+			"FLAG_compare",
 			"FLAG_exec_root",
 			"FLAG_exec_strategy",
 			"FLAG_invocation_id",
diff --git a/ui/build/paths/config.go b/ui/build/paths/config.go
index 711a9c7..ee6e9dc 100644
--- a/ui/build/paths/config.go
+++ b/ui/build/paths/config.go
@@ -82,8 +82,6 @@
 	"fuser":    Allowed,
 	"getopt":   Allowed,
 	"git":      Allowed,
-	"gzcat":    Allowed,
-	"gzip":     Allowed,
 	"hexdump":  Allowed,
 	"jar":      Allowed,
 	"java":     Allowed,
diff --git a/ui/build/soong.go b/ui/build/soong.go
index 3388417..afbc073 100644
--- a/ui/build/soong.go
+++ b/ui/build/soong.go
@@ -119,6 +119,7 @@
 			"-j", strconv.Itoa(config.Parallel()),
 			"--frontend_file", fifo,
 			"-f", filepath.Join(config.SoongOutDir(), file))
+		cmd.Environment.Set("SOONG_SANDBOX_SOONG_BUILD", "true")
 		cmd.Sandbox = soongSandbox
 		cmd.RunAndStreamOrFatal()
 	}