Merge "Revert "Do not consider disabled prebuilt variants.""
diff --git a/apex/androidmk.go b/apex/androidmk.go
index 7595238..156906d 100644
--- a/apex/androidmk.go
+++ b/apex/androidmk.go
@@ -203,6 +203,7 @@
 				panic(fmt.Sprintf("Expected %s to be AndroidAppSet", fi.module))
 			}
 			fmt.Fprintln(w, "LOCAL_APK_SET_MASTER_FILE :=", as.MasterFile())
+			fmt.Fprintln(w, "LOCAL_APKCERTS_FILE :=", as.APKCertsFile().String())
 			fmt.Fprintln(w, "include $(BUILD_SYSTEM)/soong_android_app_set.mk")
 		case nativeSharedLib, nativeExecutable, nativeTest:
 			fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", fi.Stem())
diff --git a/apex/builder.go b/apex/builder.go
index 5fb9a5f..49e4642 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -390,7 +390,7 @@
 		} else {
 			if fi.class == appSet {
 				copyCommands = append(copyCommands,
-					fmt.Sprintf("unzip -q -d %s %s", destPathDir, fi.builtFile.String()))
+					fmt.Sprintf("unzip -qDD -d %s %s", destPathDir, fi.builtFile.String()))
 			} else {
 				copyCommands = append(copyCommands, "cp -f "+fi.builtFile.String()+" "+destPath)
 			}
diff --git a/cc/llndk_library.go b/cc/llndk_library.go
index 7ff20f4..71c9204 100644
--- a/cc/llndk_library.go
+++ b/cc/llndk_library.go
@@ -225,6 +225,8 @@
 func llndkHeadersFactory() android.Module {
 	module, library := NewLibrary(android.DeviceSupported)
 	library.HeaderOnly()
+	module.stl = nil
+	module.sanitize = nil
 
 	decorator := &llndkHeadersDecorator{
 		libraryDecorator: library,
diff --git a/cmd/soong_ui/main.go b/cmd/soong_ui/main.go
index d3802f9..e485c60 100644
--- a/cmd/soong_ui/main.go
+++ b/cmd/soong_ui/main.go
@@ -117,7 +117,7 @@
 // Command is the type of soong_ui execution. Only one type of
 // execution is specified. The args are specific to the command.
 func main() {
-	buildStartedMilli := time.Now().UnixNano() / int64(time.Millisecond)
+	buildStarted := time.Now()
 
 	c, args := getCommand(os.Args)
 	if c == nil {
@@ -138,6 +138,7 @@
 	defer trace.Close()
 
 	met := metrics.New()
+	met.SetBuildDateTime(buildStarted)
 
 	stat := &status.Status{}
 	defer stat.Finish()
@@ -171,7 +172,7 @@
 	buildErrorFile := filepath.Join(logsDir, c.logsPrefix+"build_error")
 	rbeMetricsFile := filepath.Join(logsDir, c.logsPrefix+"rbe_metrics.pb")
 	soongMetricsFile := filepath.Join(logsDir, c.logsPrefix+"soong_metrics")
-	defer build.UploadMetrics(buildCtx, config, c.forceDumbOutput, buildStartedMilli, buildErrorFile, rbeMetricsFile, soongMetricsFile)
+	defer build.UploadMetrics(buildCtx, config, c.forceDumbOutput, buildStarted, buildErrorFile, rbeMetricsFile, soongMetricsFile)
 
 	os.MkdirAll(logsDir, 0777)
 	log.SetOutput(filepath.Join(logsDir, c.logsPrefix+"soong.log"))
diff --git a/java/aar.go b/java/aar.go
index 500788f..ad9b5e7 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -641,7 +641,7 @@
 var unzipAAR = pctx.AndroidStaticRule("unzipAAR",
 	blueprint.RuleParams{
 		Command: `rm -rf $outDir && mkdir -p $outDir && ` +
-			`unzip -qo -d $outDir $in && rm -rf $outDir/res && touch $out`,
+			`unzip -qoDD -d $outDir $in && rm -rf $outDir/res && touch $out`,
 	},
 	"outDir")
 
diff --git a/java/app.go b/java/app.go
index 98bce94..4071c0a 100755
--- a/java/app.go
+++ b/java/app.go
@@ -106,6 +106,10 @@
 	return as.masterFile
 }
 
+func (as *AndroidAppSet) APKCertsFile() android.Path {
+	return as.apkcertsFile
+}
+
 var TargetCpuAbi = map[string]string{
 	"arm":    "ARMEABI_V7A",
 	"arm64":  "ARM64_V8A",
diff --git a/java/droiddoc.go b/java/droiddoc.go
index 99bfb6d..08865b6 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -112,13 +112,20 @@
 	// local files that are used within user customized droiddoc options.
 	Arg_files []string `android:"path"`
 
-	// user customized droiddoc args.
+	// user customized droiddoc args. Deprecated, use flags instead.
 	// Available variables for substitution:
 	//
 	//  $(location <label>): the path to the arg_files with name <label>
 	//  $$: a literal $
 	Args *string
 
+	// user customized droiddoc args. Not compatible with property args.
+	// Available variables for substitution:
+	//
+	//  $(location <label>): the path to the arg_files with name <label>
+	//  $$: a literal $
+	Flags []string
+
 	// names of the output files used in args that will be generated
 	Out []string
 
@@ -382,7 +389,7 @@
 	argFiles    android.Paths
 	implicits   android.Paths
 
-	args string
+	args []string
 
 	docZip      android.WritablePath
 	stubsSrcJar android.WritablePath
@@ -619,8 +626,8 @@
 	}
 	srcFiles = filterHtml(srcFiles)
 
-	flags := j.collectAidlFlags(ctx, deps)
-	srcFiles = j.genSources(ctx, srcFiles, flags)
+	aidlFlags := j.collectAidlFlags(ctx, deps)
+	srcFiles = j.genSources(ctx, srcFiles, aidlFlags)
 
 	// srcs may depend on some genrule output.
 	j.srcJars = srcFiles.FilterByExt(".srcjar")
@@ -649,24 +656,38 @@
 		}
 	}
 
-	var err error
-	j.args, err = android.Expand(String(j.properties.Args), func(name string) (string, error) {
-		if strings.HasPrefix(name, "location ") {
-			label := strings.TrimSpace(strings.TrimPrefix(name, "location "))
-			if paths, ok := argFilesMap[label]; ok {
-				return paths, nil
-			} else {
-				return "", fmt.Errorf("unknown location label %q, expecting one of %q",
-					label, strings.Join(argFileLabels, ", "))
-			}
-		} else if name == "genDir" {
-			return android.PathForModuleGen(ctx).String(), nil
-		}
-		return "", fmt.Errorf("unknown variable '$(%s)'", name)
-	})
+	var argsPropertyName string
+	flags := make([]string, 0)
+	if j.properties.Args != nil && j.properties.Flags != nil {
+		ctx.PropertyErrorf("args", "flags is set. Cannot set args")
+	} else if args := proptools.String(j.properties.Args); args != "" {
+		flags = append(flags, args)
+		argsPropertyName = "args"
+	} else {
+		flags = append(flags, j.properties.Flags...)
+		argsPropertyName = "flags"
+	}
 
-	if err != nil {
-		ctx.PropertyErrorf("args", "%s", err.Error())
+	for _, flag := range flags {
+		args, err := android.Expand(flag, func(name string) (string, error) {
+			if strings.HasPrefix(name, "location ") {
+				label := strings.TrimSpace(strings.TrimPrefix(name, "location "))
+				if paths, ok := argFilesMap[label]; ok {
+					return paths, nil
+				} else {
+					return "", fmt.Errorf("unknown location label %q, expecting one of %q",
+						label, strings.Join(argFileLabels, ", "))
+				}
+			} else if name == "genDir" {
+				return android.PathForModuleGen(ctx).String(), nil
+			}
+			return "", fmt.Errorf("unknown variable '$(%s)'", name)
+		})
+
+		if err != nil {
+			ctx.PropertyErrorf(argsPropertyName, "%s", err.Error())
+		}
+		j.args = append(j.args, args)
 	}
 
 	return deps
@@ -1010,7 +1031,7 @@
 
 	d.stubsFlags(ctx, cmd, stubsDir)
 
-	cmd.Flag(d.Javadoc.args).Implicits(d.Javadoc.argFiles)
+	cmd.Flag(strings.Join(d.Javadoc.args, " ")).Implicits(d.Javadoc.argFiles)
 
 	if d.properties.Compat_config != nil {
 		compatConfig := android.PathForModuleSrc(ctx, String(d.properties.Compat_config))
@@ -1327,7 +1348,7 @@
 		cmd.Flag("--include-annotations")
 
 		validatingNullability :=
-			strings.Contains(d.Javadoc.args, "--validate-nullability-from-merged-stubs") ||
+			android.InList("--validate-nullability-from-merged-stubs", d.Javadoc.args) ||
 				String(d.properties.Validate_nullability_from_list) != ""
 
 		migratingNullability := String(d.properties.Previous_api) != ""
@@ -1539,14 +1560,14 @@
 	d.apiLevelsAnnotationsFlags(ctx, cmd)
 	d.apiToXmlFlags(ctx, cmd)
 
-	if strings.Contains(d.Javadoc.args, "--generate-documentation") {
+	if android.InList("--generate-documentation", d.Javadoc.args) {
 		// Currently Metalava have the ability to invoke Javadoc in a seperate process.
 		// Pass "-nodocs" to suppress the Javadoc invocation when Metalava receives
 		// "--generate-documentation" arg. This is not needed when Metalava removes this feature.
-		d.Javadoc.args = d.Javadoc.args + " -nodocs "
+		d.Javadoc.args = append(d.Javadoc.args, "-nodocs")
 	}
 
-	cmd.Flag(d.Javadoc.args).Implicits(d.Javadoc.argFiles)
+	cmd.Flag(strings.Join(d.Javadoc.args, " ")).Implicits(d.Javadoc.argFiles)
 	for _, o := range d.Javadoc.properties.Out {
 		cmd.ImplicitOutput(android.PathForModuleGen(ctx, o))
 	}
diff --git a/java/hiddenapi.go b/java/hiddenapi.go
index 130b634..b5a0217 100644
--- a/java/hiddenapi.go
+++ b/java/hiddenapi.go
@@ -146,7 +146,7 @@
 
 var hiddenAPIEncodeDexRule = pctx.AndroidStaticRule("hiddenAPIEncodeDex", blueprint.RuleParams{
 	Command: `rm -rf $tmpDir && mkdir -p $tmpDir && mkdir $tmpDir/dex-input && mkdir $tmpDir/dex-output &&
-		unzip -o -q $in 'classes*.dex' -d $tmpDir/dex-input &&
+		unzip -qoDD $in 'classes*.dex' -d $tmpDir/dex-input &&
 		for INPUT_DEX in $$(find $tmpDir/dex-input -maxdepth 1 -name 'classes*.dex' | sort); do
 		  echo "--input-dex=$${INPUT_DEX}";
 		  echo "--output-dex=$tmpDir/dex-output/$$(basename $${INPUT_DEX})";
diff --git a/java/java_test.go b/java/java_test.go
index fb00361..db3f187 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -1097,7 +1097,7 @@
 		    ],
 		    proofread_file: "libcore-proofread.txt",
 		    todo_file: "libcore-docs-todo.html",
-		    args: "-offlinemode -title \"libcore\"",
+		    flags: ["-offlinemode -title \"libcore\""],
 		}
 		`,
 		map[string][]byte{
@@ -1124,6 +1124,42 @@
 	}
 }
 
+func TestDroiddocArgsAndFlagsCausesError(t *testing.T) {
+	testJavaError(t, "flags is set. Cannot set args", `
+		droiddoc_exported_dir {
+		    name: "droiddoc-templates-sdk",
+		    path: ".",
+		}
+		filegroup {
+		    name: "bar-doc-aidl-srcs",
+		    srcs: ["bar-doc/IBar.aidl"],
+		    path: "bar-doc",
+		}
+		droiddoc {
+		    name: "bar-doc",
+		    srcs: [
+		        "bar-doc/a.java",
+		        "bar-doc/IFoo.aidl",
+		        ":bar-doc-aidl-srcs",
+		    ],
+		    exclude_srcs: [
+		        "bar-doc/b.java"
+		    ],
+		    custom_template: "droiddoc-templates-sdk",
+		    hdf: [
+		        "android.whichdoc offline",
+		    ],
+		    knowntags: [
+		        "bar-doc/known_oj_tags.txt",
+		    ],
+		    proofread_file: "libcore-proofread.txt",
+		    todo_file: "libcore-docs-todo.html",
+		    flags: ["-offlinemode -title \"libcore\""],
+		    args: "-offlinemode -title \"libcore\"",
+		}
+		`)
+}
+
 func TestDroidstubsWithSystemModules(t *testing.T) {
 	ctx, _ := testJava(t, `
 		droidstubs {
diff --git a/java/lint.go b/java/lint.go
index b73d6a5..6fbef18 100644
--- a/java/lint.go
+++ b/java/lint.go
@@ -220,12 +220,21 @@
 	rule.Command().Text("rm -rf").Flag(cacheDir.String()).Flag(homeDir.String())
 	rule.Command().Text("mkdir -p").Flag(cacheDir.String()).Flag(homeDir.String())
 
+	var annotationsZipPath, apiVersionsXMLPath android.Path
+	if ctx.Config().UnbundledBuildUsePrebuiltSdks() {
+		annotationsZipPath = android.PathForSource(ctx, "prebuilts/sdk/current/public/data/annotations.zip")
+		apiVersionsXMLPath = android.PathForSource(ctx, "prebuilts/sdk/current/public/data/api-versions.xml")
+	} else {
+		annotationsZipPath = copiedAnnotationsZipPath(ctx)
+		apiVersionsXMLPath = copiedAPIVersionsXmlPath(ctx)
+	}
+
 	rule.Command().
 		Text("(").
 		Flag("JAVA_OPTS=-Xmx2048m").
 		FlagWithArg("ANDROID_SDK_HOME=", homeDir.String()).
-		FlagWithInput("SDK_ANNOTATIONS=", annotationsZipPath(ctx)).
-		FlagWithInput("LINT_OPTS=-DLINT_API_DATABASE=", apiVersionsXmlPath(ctx)).
+		FlagWithInput("SDK_ANNOTATIONS=", annotationsZipPath).
+		FlagWithInput("LINT_OPTS=-DLINT_API_DATABASE=", apiVersionsXMLPath).
 		Tool(android.PathForSource(ctx, "prebuilts/cmdline-tools/tools/bin/lint")).
 		Implicit(android.PathForSource(ctx, "prebuilts/cmdline-tools/tools/lib/lint-classpath.jar")).
 		Flag("--quiet").
@@ -271,7 +280,7 @@
 }
 
 func (l *lintSingleton) copyLintDependencies(ctx android.SingletonContext) {
-	if ctx.Config().UnbundledBuild() {
+	if ctx.Config().UnbundledBuildUsePrebuiltSdks() {
 		return
 	}
 
@@ -297,25 +306,29 @@
 	ctx.Build(pctx, android.BuildParams{
 		Rule:   android.Cp,
 		Input:  android.OutputFileForModule(ctx, frameworkDocStubs, ".annotations.zip"),
-		Output: annotationsZipPath(ctx),
+		Output: copiedAnnotationsZipPath(ctx),
 	})
 
 	ctx.Build(pctx, android.BuildParams{
 		Rule:   android.Cp,
 		Input:  android.OutputFileForModule(ctx, frameworkDocStubs, ".api_versions.xml"),
-		Output: apiVersionsXmlPath(ctx),
+		Output: copiedAPIVersionsXmlPath(ctx),
 	})
 }
 
-func annotationsZipPath(ctx android.PathContext) android.WritablePath {
+func copiedAnnotationsZipPath(ctx android.PathContext) android.WritablePath {
 	return android.PathForOutput(ctx, "lint", "annotations.zip")
 }
 
-func apiVersionsXmlPath(ctx android.PathContext) android.WritablePath {
+func copiedAPIVersionsXmlPath(ctx android.PathContext) android.WritablePath {
 	return android.PathForOutput(ctx, "lint", "api_versions.xml")
 }
 
 func (l *lintSingleton) generateLintReportZips(ctx android.SingletonContext) {
+	if ctx.Config().UnbundledBuild() {
+		return
+	}
+
 	var outputs []*lintOutputs
 	var dirs []string
 	ctx.VisitAllModules(func(m android.Module) {
@@ -370,7 +383,9 @@
 }
 
 func (l *lintSingleton) MakeVars(ctx android.MakeVarsContext) {
-	ctx.DistForGoal("lint-check", l.htmlZip, l.textZip, l.xmlZip)
+	if !ctx.Config().UnbundledBuild() {
+		ctx.DistForGoal("lint-check", l.htmlZip, l.textZip, l.xmlZip)
+	}
 }
 
 var _ android.SingletonMakeVarsProvider = (*lintSingleton)(nil)
diff --git a/java/prebuilt_apis.go b/java/prebuilt_apis.go
index 999c72f..b10e6c7 100644
--- a/java/prebuilt_apis.go
+++ b/java/prebuilt_apis.go
@@ -83,8 +83,7 @@
 	}{}
 	props.Name = proptools.StringPtr(prebuiltApiModuleName(mctx, module, scope, apiver))
 	props.Jars = append(props.Jars, path)
-	// TODO(hansson): change to scope after migration is done.
-	props.Sdk_version = proptools.StringPtr("current")
+	props.Sdk_version = proptools.StringPtr(scope)
 	props.Installable = proptools.BoolPtr(false)
 
 	mctx.CreateModule(ImportFactory, &props)
diff --git a/rust/binary.go b/rust/binary.go
index a1cd410..9fc52cd 100644
--- a/rust/binary.go
+++ b/rust/binary.go
@@ -106,7 +106,8 @@
 func (binary *binaryDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) android.Path {
 	fileName := binary.getStem(ctx) + ctx.toolchain().ExecutableSuffix()
 
-	srcPath := srcPathFromModuleSrcs(ctx, binary.baseCompiler.Properties.Srcs)
+	srcPath, paths := srcPathFromModuleSrcs(ctx, binary.baseCompiler.Properties.Srcs)
+	deps.SrcDeps = paths
 
 	outputFile := android.PathForModuleOut(ctx, fileName)
 	binary.unstrippedOutputFile = outputFile
diff --git a/rust/builder.go b/rust/builder.go
index 16d7306..7f94bb5 100644
--- a/rust/builder.go
+++ b/rust/builder.go
@@ -166,6 +166,7 @@
 	implicits = append(implicits, rustLibsToPaths(deps.ProcMacros)...)
 	implicits = append(implicits, deps.StaticLibs...)
 	implicits = append(implicits, deps.SharedLibs...)
+	implicits = append(implicits, deps.SrcDeps...)
 	if deps.CrtBegin.Valid() {
 		implicits = append(implicits, deps.CrtBegin.Path(), deps.CrtEnd.Path())
 	}
diff --git a/rust/compiler.go b/rust/compiler.go
index 92a3b07..c20179b 100644
--- a/rust/compiler.go
+++ b/rust/compiler.go
@@ -253,10 +253,24 @@
 	return String(compiler.Properties.Relative_install_path)
 }
 
-func srcPathFromModuleSrcs(ctx ModuleContext, srcs []string) android.Path {
-	srcPaths := android.PathsForModuleSrc(ctx, srcs)
-	if len(srcPaths) != 1 {
-		ctx.PropertyErrorf("srcs", "srcs can only contain one path for rust modules")
+func srcPathFromModuleSrcs(ctx ModuleContext, srcs []string) (android.Path, android.Paths) {
+	// The srcs can contain strings with prefix ":".
+	// They are dependent modules of this module, with android.SourceDepTag.
+	// They are not the main source file compiled by rustc.
+	numSrcs := 0
+	srcIndex := 0
+	for i, s := range srcs {
+		if android.SrcIsModule(s) == "" {
+			numSrcs++
+			srcIndex = i
+		}
 	}
-	return srcPaths[0]
+	if numSrcs != 1 {
+		ctx.PropertyErrorf("srcs", "srcs can only contain one path for a rust file")
+	}
+	if srcIndex != 0 {
+		ctx.PropertyErrorf("srcs", "main source file must be the first in srcs")
+	}
+	paths := android.PathsForModuleSrc(ctx, srcs)
+	return paths[srcIndex], paths
 }
diff --git a/rust/compiler_test.go b/rust/compiler_test.go
index bcde757..58ca52a 100644
--- a/rust/compiler_test.go
+++ b/rust/compiler_test.go
@@ -43,7 +43,7 @@
 // Test that we reject multiple source files.
 func TestEnforceSingleSourceFile(t *testing.T) {
 
-	singleSrcError := "srcs can only contain one path for rust modules"
+	singleSrcError := "srcs can only contain one path for a rust file"
 
 	// Test libraries
 	testRustError(t, singleSrcError, `
diff --git a/rust/library.go b/rust/library.go
index 8b8e797..d718eb8 100644
--- a/rust/library.go
+++ b/rust/library.go
@@ -368,7 +368,8 @@
 func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) android.Path {
 	var outputFile android.WritablePath
 
-	srcPath := srcPathFromModuleSrcs(ctx, library.baseCompiler.Properties.Srcs)
+	srcPath, paths := srcPathFromModuleSrcs(ctx, library.baseCompiler.Properties.Srcs)
+	deps.SrcDeps = paths
 
 	flags.RustFlags = append(flags.RustFlags, deps.depFlags...)
 
diff --git a/rust/prebuilt.go b/rust/prebuilt.go
index 67d649d..3b4f40a 100644
--- a/rust/prebuilt.go
+++ b/rust/prebuilt.go
@@ -95,7 +95,8 @@
 func (prebuilt *prebuiltLibraryDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) android.Path {
 	prebuilt.exportLinkDirs(android.PathsForModuleSrc(ctx, prebuilt.Properties.Link_dirs).Strings()...)
 
-	srcPath := srcPathFromModuleSrcs(ctx, prebuilt.prebuiltSrcs())
+	srcPath, paths := srcPathFromModuleSrcs(ctx, prebuilt.prebuiltSrcs())
+	deps.SrcDeps = paths
 
 	prebuilt.unstrippedOutputFile = srcPath
 
diff --git a/rust/proc_macro.go b/rust/proc_macro.go
index 2719161..49dbd8d 100644
--- a/rust/proc_macro.go
+++ b/rust/proc_macro.go
@@ -65,7 +65,8 @@
 	fileName := procMacro.getStem(ctx) + ctx.toolchain().ProcMacroSuffix()
 	outputFile := android.PathForModuleOut(ctx, fileName)
 
-	srcPath := srcPathFromModuleSrcs(ctx, procMacro.baseCompiler.Properties.Srcs)
+	srcPath, paths := srcPathFromModuleSrcs(ctx, procMacro.baseCompiler.Properties.Srcs)
+	deps.SrcDeps = paths
 
 	procMacro.unstrippedOutputFile = outputFile
 
diff --git a/rust/rust.go b/rust/rust.go
index 72301a7..7a98c64 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -239,6 +239,9 @@
 
 	CrtBegin android.OptionalPath
 	CrtEnd   android.OptionalPath
+
+	// Paths to generated source files
+	SrcDeps android.Paths
 }
 
 type RustLibraries []RustLibrary
@@ -843,6 +846,7 @@
 	// Dedup exported flags from dependencies
 	depPaths.linkDirs = android.FirstUniqueStrings(depPaths.linkDirs)
 	depPaths.depFlags = android.FirstUniqueStrings(depPaths.depFlags)
+	depPaths.SrcDeps = android.FirstUniquePaths(depPaths.SrcDeps)
 
 	return depPaths
 }
diff --git a/rust/rust_test.go b/rust/rust_test.go
index 08bc8ca..e803925 100644
--- a/rust/rust_test.go
+++ b/rust/rust_test.go
@@ -61,6 +61,7 @@
 		"foo.rs":     nil,
 		"foo.c":      nil,
 		"src/bar.rs": nil,
+		"src/any.h":  nil,
 		"liby.so":    nil,
 		"libz.so":    nil,
 	}
@@ -181,7 +182,7 @@
 		}
 		rust_library_host_rlib {
 			name: "librlib",
-			srcs: ["foo.rs"],
+			srcs: ["foo.rs", ":my_generator"],
 			crate_name: "rlib",
 		}
 		rust_proc_macro {
@@ -189,17 +190,38 @@
 			srcs: ["foo.rs"],
 			crate_name: "pm",
 		}
+		genrule {
+			name: "my_generator",
+			tools: ["any_rust_binary"],
+			cmd: "$(location) -o $(out) $(in)",
+			srcs: ["src/any.h"],
+			out: ["src/any.rs"],
+		}
 		rust_binary_host {
-			name: "fizz-buzz",
+			name: "fizz-buzz-dep",
 			dylibs: ["libdylib"],
 			rlibs: ["librlib"],
 			proc_macros: ["libpm"],
 			static_libs: ["libstatic"],
 			shared_libs: ["libshared"],
-			srcs: ["foo.rs"],
+			srcs: [
+				"foo.rs",
+				":my_generator",
+			],
 		}
 	`)
-	module := ctx.ModuleForTests("fizz-buzz", "linux_glibc_x86_64").Module().(*Module)
+	module := ctx.ModuleForTests("fizz-buzz-dep", "linux_glibc_x86_64").Module().(*Module)
+	rlibmodule := ctx.ModuleForTests("librlib", "linux_glibc_x86_64_rlib").Module().(*Module)
+
+	srcs := module.compiler.(*binaryDecorator).baseCompiler.Properties.Srcs
+	if len(srcs) != 2 || !android.InList(":my_generator", srcs) {
+		t.Errorf("missing module dependency in fizz-buzz)")
+	}
+
+	srcs = rlibmodule.compiler.(*libraryDecorator).baseCompiler.Properties.Srcs
+	if len(srcs) != 2 || !android.InList(":my_generator", srcs) {
+		t.Errorf("missing module dependency in rlib")
+	}
 
 	// Since dependencies are added to AndroidMk* properties, we can check these to see if they've been picked up.
 	if !android.InList("libdylib", module.Properties.AndroidMkDylibs) {
diff --git a/rust/testing.go b/rust/testing.go
index 3d583e1..430b40b 100644
--- a/rust/testing.go
+++ b/rust/testing.go
@@ -17,6 +17,7 @@
 import (
 	"android/soong/android"
 	"android/soong/cc"
+	"android/soong/genrule"
 )
 
 func GatherRequiredDepsForTest() string {
@@ -77,6 +78,7 @@
 func CreateTestContext() *android.TestContext {
 	ctx := android.NewTestArchContext()
 	cc.RegisterRequiredBuildComponentsForTest(ctx)
+	ctx.RegisterModuleType("genrule", genrule.GenRuleFactory)
 	ctx.RegisterModuleType("rust_binary", RustBinaryFactory)
 	ctx.RegisterModuleType("rust_binary_host", RustBinaryHostFactory)
 	ctx.RegisterModuleType("rust_test", RustTestFactory)
diff --git a/sdk/update.go b/sdk/update.go
index 8241151..cf25008 100644
--- a/sdk/update.go
+++ b/sdk/update.go
@@ -911,7 +911,7 @@
 
 	if commonVariants, ok := variantsByArchName["common"]; ok {
 		if len(osTypeVariants) != 1 {
-			panic("Expected to only have 1 variant when arch type is common but found " + string(len(osTypeVariants)))
+			panic(fmt.Errorf("Expected to only have 1 variant when arch type is common but found %d", len(osTypeVariants)))
 		}
 
 		// A common arch type only has one variant and its properties should be treated
diff --git a/ui/build/config.go b/ui/build/config.go
index e567e40..a60d70e 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -256,9 +256,6 @@
 		ret.buildDateTime = strconv.FormatInt(time.Now().Unix(), 10)
 	}
 
-	if ctx.Metrics != nil {
-		ctx.Metrics.SetBuildDateTime(ret.buildDateTime)
-	}
 	ret.environ.Set("BUILD_DATETIME_FILE", buildDateTimeFile)
 
 	return Config{ret}
diff --git a/ui/build/upload.go b/ui/build/upload.go
index 3a23a80..1cc2e94 100644
--- a/ui/build/upload.go
+++ b/ui/build/upload.go
@@ -44,7 +44,7 @@
 // environment variable. The metrics files are copied to a temporary directory
 // and the uploader is then executed in the background to allow the user to continue
 // working.
-func UploadMetrics(ctx Context, config Config, forceDumbOutput bool, buildStartedMilli int64, files ...string) {
+func UploadMetrics(ctx Context, config Config, forceDumbOutput bool, buildStarted time.Time, files ...string) {
 	ctx.BeginTrace(metrics.RunSetupTool, "upload_metrics")
 	defer ctx.EndTrace()
 
@@ -86,7 +86,7 @@
 	// For platform builds, the branch and target name is hardcoded to specific
 	// values for later extraction of the metrics in the data metrics pipeline.
 	data, err := proto.Marshal(&upload_proto.Upload{
-		CreationTimestampMs:   proto.Uint64(uint64(buildStartedMilli)),
+		CreationTimestampMs:   proto.Uint64(uint64(buildStarted.UnixNano() / int64(time.Millisecond))),
 		CompletionTimestampMs: proto.Uint64(uint64(time.Now().UnixNano() / int64(time.Millisecond))),
 		BranchName:            proto.String("developer-metrics"),
 		TargetName:            proto.String("platform-build-systems-metrics"),
diff --git a/ui/build/upload_test.go b/ui/build/upload_test.go
index c812730..dccf156 100644
--- a/ui/build/upload_test.go
+++ b/ui/build/upload_test.go
@@ -97,7 +97,7 @@
 				buildDateTime: strconv.FormatInt(time.Now().UnixNano()/int64(time.Millisecond), 10),
 			}}
 
-			UploadMetrics(ctx, config, false, 1591031903, metricsFiles...)
+			UploadMetrics(ctx, config, false, time.Now(), metricsFiles...)
 		})
 	}
 }
@@ -151,7 +151,7 @@
 					"OUT_DIR=/bad",
 				}}}
 
-			UploadMetrics(ctx, config, true, 1591031903, metricsFile)
+			UploadMetrics(ctx, config, true, time.Now(), metricsFile)
 			t.Errorf("got nil, expecting %q as a failure", tt.expectedErr)
 		})
 	}
diff --git a/ui/metrics/Android.bp b/ui/metrics/Android.bp
index 3596e10..8188a69 100644
--- a/ui/metrics/Android.bp
+++ b/ui/metrics/Android.bp
@@ -25,6 +25,9 @@
         "metrics.go",
         "time.go",
     ],
+    testSrcs: [
+        "time_test.go",
+    ],
 }
 
 bootstrap_go_package {
diff --git a/ui/metrics/metrics.go b/ui/metrics/metrics.go
index e055b76..2b5c4c3 100644
--- a/ui/metrics/metrics.go
+++ b/ui/metrics/metrics.go
@@ -17,7 +17,7 @@
 import (
 	"io/ioutil"
 	"os"
-	"strconv"
+	"time"
 
 	"github.com/golang/protobuf/proto"
 
@@ -131,14 +131,8 @@
 	}
 }
 
-func (m *Metrics) SetBuildDateTime(date_time string) {
-	if date_time != "" {
-		date_time_timestamp, err := strconv.ParseInt(date_time, 10, 64)
-		if err != nil {
-			panic(err)
-		}
-		m.metrics.BuildDateTimestamp = &date_time_timestamp
-	}
+func (m *Metrics) SetBuildDateTime(buildTimestamp time.Time) {
+	m.metrics.BuildDateTimestamp = proto.Int64(buildTimestamp.UnixNano() / int64(time.Second))
 }
 
 // exports the output to the file at outputPath
diff --git a/ui/metrics/time.go b/ui/metrics/time.go
index b8baf16..4016563 100644
--- a/ui/metrics/time.go
+++ b/ui/metrics/time.go
@@ -19,13 +19,18 @@
 
 	"android/soong/ui/metrics/metrics_proto"
 	"android/soong/ui/tracer"
+	"github.com/golang/protobuf/proto"
 )
 
+// for testing purpose only
+var _now = now
+
 type timeEvent struct {
 	desc string
 	name string
 
-	atNanos uint64 // timestamp measured in nanoseconds since the reference date
+	// the time that the event started to occur.
+	start time.Time
 }
 
 type TimeTracer interface {
@@ -39,33 +44,26 @@
 
 var _ TimeTracer = &timeTracerImpl{}
 
-func (t *timeTracerImpl) now() uint64 {
-	return uint64(time.Now().UnixNano())
+func now() time.Time {
+	return time.Now()
 }
 
-func (t *timeTracerImpl) Begin(name, desc string, thread tracer.Thread) {
-	t.beginAt(name, desc, t.now())
+func (t *timeTracerImpl) Begin(name, desc string, _ tracer.Thread) {
+	t.activeEvents = append(t.activeEvents, timeEvent{name: name, desc: desc, start: _now()})
 }
 
-func (t *timeTracerImpl) beginAt(name, desc string, atNanos uint64) {
-	t.activeEvents = append(t.activeEvents, timeEvent{name: name, desc: desc, atNanos: atNanos})
-}
-
-func (t *timeTracerImpl) End(thread tracer.Thread) soong_metrics_proto.PerfInfo {
-	return t.endAt(t.now())
-}
-
-func (t *timeTracerImpl) endAt(atNanos uint64) soong_metrics_proto.PerfInfo {
+func (t *timeTracerImpl) End(tracer.Thread) soong_metrics_proto.PerfInfo {
 	if len(t.activeEvents) < 1 {
 		panic("Internal error: No pending events for endAt to end!")
 	}
 	lastEvent := t.activeEvents[len(t.activeEvents)-1]
 	t.activeEvents = t.activeEvents[:len(t.activeEvents)-1]
-	realTime := atNanos - lastEvent.atNanos
+	realTime := uint64(_now().Sub(lastEvent.start).Nanoseconds())
 
 	return soong_metrics_proto.PerfInfo{
-		Desc:      &lastEvent.desc,
-		Name:      &lastEvent.name,
-		StartTime: &lastEvent.atNanos,
-		RealTime:  &realTime}
+		Desc:      proto.String(lastEvent.desc),
+		Name:      proto.String(lastEvent.name),
+		StartTime: proto.Uint64(uint64(lastEvent.start.UnixNano())),
+		RealTime:  proto.Uint64(realTime),
+	}
 }
diff --git a/ui/metrics/time_test.go b/ui/metrics/time_test.go
new file mode 100644
index 0000000..d73080a
--- /dev/null
+++ b/ui/metrics/time_test.go
@@ -0,0 +1,42 @@
+// 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 metrics
+
+import (
+	"testing"
+	"time"
+
+	"android/soong/ui/tracer"
+)
+
+func TestEnd(t *testing.T) {
+	startTime := time.Date(2020, time.July, 13, 13, 0, 0, 0, time.UTC)
+	dur := time.Nanosecond * 10
+	initialNow := _now
+	_now = func() time.Time { return startTime.Add(dur) }
+	defer func() { _now = initialNow }()
+
+	timeTracer := &timeTracerImpl{}
+	timeTracer.activeEvents = append(timeTracer.activeEvents, timeEvent{
+		desc:  "test",
+		name:  "test",
+		start: startTime,
+	})
+
+	perf := timeTracer.End(tracer.Thread(0))
+	if perf.GetRealTime() != uint64(dur.Nanoseconds()) {
+		t.Errorf("got %d, want %d nanoseconds for event duration", perf.GetRealTime(), dur.Nanoseconds())
+	}
+}