Merge changes I4ab7e1a3,Ib525b2f5,I2d4c54fb into rvc-dev

* changes:
  Generate combined deps-info for all updatable modules.
  Remove ApexBundleDepsInfo.MinSdkVersion()
  Add "updatable" property to ApexModule interface.
diff --git a/Android.bp b/Android.bp
index a81676f..d7c7dae 100644
--- a/Android.bp
+++ b/Android.bp
@@ -489,6 +489,7 @@
     srcs: [
         "apex/androidmk.go",
         "apex/apex.go",
+        "apex/apex_singleton.go",
         "apex/builder.go",
         "apex/key.go",
         "apex/prebuilt.go",
diff --git a/android/apex.go b/android/apex.go
index ede0965..30152db 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -33,6 +33,7 @@
 	ApexName string
 
 	MinSdkVersion int
+	Updatable     bool
 }
 
 // Extracted from ApexModule to make it easier to define custom subsets of the
@@ -116,6 +117,9 @@
 	// it returns 9 as string
 	ChooseSdkVersion(versionList []string, maxSdkVersion int) (string, error)
 
+	// Tests if the module comes from an updatable APEX.
+	Updatable() bool
+
 	// List of APEXes that this module tests. The module has access to
 	// the private part of the listed APEXes even when it is not included in the
 	// APEXes.
@@ -260,6 +264,10 @@
 	}
 }
 
+func (m *ApexModuleBase) Updatable() bool {
+	return m.ApexProperties.Info.Updatable
+}
+
 type byApexName []ApexInfo
 
 func (a byApexName) Len() int           { return len(a) }
@@ -413,21 +421,16 @@
 type DepNameToDepInfoMap map[string]ApexModuleDepInfo
 
 type ApexBundleDepsInfo struct {
-	minSdkVersion string
-	flatListPath  OutputPath
-	fullListPath  OutputPath
+	flatListPath OutputPath
+	fullListPath OutputPath
 }
 
-type ApexDepsInfoIntf interface {
-	MinSdkVersion() string
+type ApexBundleDepsInfoIntf interface {
+	Updatable() bool
 	FlatListPath() Path
 	FullListPath() Path
 }
 
-func (d *ApexBundleDepsInfo) MinSdkVersion() string {
-	return d.minSdkVersion
-}
-
 func (d *ApexBundleDepsInfo) FlatListPath() Path {
 	return d.flatListPath
 }
@@ -436,14 +439,10 @@
 	return d.fullListPath
 }
 
-var _ ApexDepsInfoIntf = (*ApexBundleDepsInfo)(nil)
-
 // Generate two module out files:
 // 1. FullList with transitive deps and their parents in the dep graph
 // 2. FlatList with a flat list of transitive deps
 func (d *ApexBundleDepsInfo) BuildDepsInfoLists(ctx ModuleContext, minSdkVersion string, depInfos DepNameToDepInfoMap) {
-	d.minSdkVersion = minSdkVersion
-
 	var fullContent strings.Builder
 	var flatContent strings.Builder
 
diff --git a/apex/apex.go b/apex/apex.go
index dbbfe78..05ba5c4 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -785,6 +785,7 @@
 		apexBundles = []android.ApexInfo{{
 			ApexName:      mctx.ModuleName(),
 			MinSdkVersion: a.minSdkVersion(mctx),
+			Updatable:     a.Updatable(),
 		}}
 		directDep = true
 	} else if am, ok := mctx.Module().(android.ApexModule); ok {
@@ -1828,6 +1829,12 @@
 	return tagString
 }
 
+func (a *apexBundle) Updatable() bool {
+	return proptools.Bool(a.properties.Updatable)
+}
+
+var _ android.ApexBundleDepsInfoIntf = (*apexBundle)(nil)
+
 // Ensures that the dependencies are marked as available for this APEX
 func (a *apexBundle) checkApexAvailability(ctx android.ModuleContext) {
 	// Let's be practical. Availability for test, host, and the VNDK apex isn't important
@@ -1876,7 +1883,7 @@
 }
 
 func (a *apexBundle) checkUpdatable(ctx android.ModuleContext) {
-	if proptools.Bool(a.properties.Updatable) {
+	if a.Updatable() {
 		if String(a.properties.Min_sdk_version) == "" {
 			ctx.PropertyErrorf("updatable", "updatable APEXes should set min_sdk_version as well")
 		}
@@ -2203,7 +2210,7 @@
 
 	// We don't need the optimization for updatable APEXes, as it might give false signal
 	// to the system health when the APEXes are still bundled (b/149805758)
-	if proptools.Bool(a.properties.Updatable) && a.properties.ApexType == imageApex {
+	if a.Updatable() && a.properties.ApexType == imageApex {
 		a.linkToSystemLib = false
 	}
 
diff --git a/apex/apex_singleton.go b/apex/apex_singleton.go
new file mode 100644
index 0000000..83a56a2
--- /dev/null
+++ b/apex/apex_singleton.go
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2020 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 apex
+
+import (
+	"github.com/google/blueprint"
+
+	"android/soong/android"
+)
+
+func init() {
+	android.RegisterSingletonType("apex_depsinfo_singleton", apexDepsInfoSingletonFactory)
+}
+
+type apexDepsInfoSingleton struct {
+	// Output file with all flatlists from updatable modules' deps-info combined
+	updatableFlatListsPath android.OutputPath
+}
+
+func apexDepsInfoSingletonFactory() android.Singleton {
+	return &apexDepsInfoSingleton{}
+}
+
+var combineFilesRule = pctx.AndroidStaticRule("combineFilesRule",
+	blueprint.RuleParams{
+		Command:        "cat $out.rsp | xargs cat > $out",
+		Rspfile:        "$out.rsp",
+		RspfileContent: "$in",
+	},
+)
+
+func (s *apexDepsInfoSingleton) GenerateBuildActions(ctx android.SingletonContext) {
+	updatableFlatLists := android.Paths{}
+	ctx.VisitAllModules(func(module android.Module) {
+		if binaryInfo, ok := module.(android.ApexBundleDepsInfoIntf); ok {
+			if path := binaryInfo.FlatListPath(); path != nil {
+				if binaryInfo.Updatable() {
+					updatableFlatLists = append(updatableFlatLists, path)
+				}
+			}
+		}
+	})
+
+	s.updatableFlatListsPath = android.PathForOutput(ctx, "apex", "depsinfo", "updatable-flatlists.txt")
+	ctx.Build(pctx, android.BuildParams{
+		Rule:        combineFilesRule,
+		Description: "Generate " + s.updatableFlatListsPath.String(),
+		Inputs:      updatableFlatLists,
+		Output:      s.updatableFlatListsPath,
+	})
+}
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 3979149..a2d7a97 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -4437,6 +4437,13 @@
 				"system/sepolicy/apex/some-updatable-apex-file_contexts",
 			],
 		}
+
+		filegroup {
+			name: "some-non-updatable-apex-file_contexts",
+			srcs: [
+				"system/sepolicy/apex/some-non-updatable-apex-file_contexts",
+			],
+		}
 	`
 	bp += cc.GatherRequiredDepsForTest(android.Android)
 	bp += java.GatherRequiredDepsForTest()
@@ -4449,6 +4456,7 @@
 		"apex_manifest.json":                 nil,
 		"AndroidManifest.xml":                nil,
 		"system/sepolicy/apex/some-updatable-apex-file_contexts":       nil,
+		"system/sepolicy/apex/some-non-updatable-apex-file_contexts":   nil,
 		"system/sepolicy/apex/com.android.art.something-file_contexts": nil,
 		"framework/aidl/a.aidl": nil,
 	}
@@ -4520,6 +4528,14 @@
 		}
 
 		java_library {
+			name: "some-non-updatable-apex-lib",
+			srcs: ["a.java"],
+			apex_available: [
+				"some-non-updatable-apex",
+			],
+		}
+
+		java_library {
 			name: "some-platform-lib",
 			srcs: ["a.java"],
 			sdk_version: "current",
@@ -4540,16 +4556,30 @@
 			name: "some-updatable-apex",
 			key: "some-updatable-apex.key",
 			java_libs: ["some-updatable-apex-lib"],
+			updatable: true,
+			min_sdk_version: "current",
+		}
+
+		apex {
+			name: "some-non-updatable-apex",
+			key: "some-non-updatable-apex.key",
+			java_libs: ["some-non-updatable-apex-lib"],
 		}
 
 		apex_key {
 			name: "some-updatable-apex.key",
 		}
 
+		apex_key {
+			name: "some-non-updatable-apex.key",
+		}
+
 		apex {
 			name: "com.android.art.something",
 			key: "com.android.art.something.key",
 			java_libs: ["some-art-lib"],
+			updatable: true,
+			min_sdk_version: "current",
 		}
 
 		apex_key {
@@ -4580,6 +4610,13 @@
 	}
 	testNoUpdatableJarsInBootImage(t, error, bp, transform)
 
+	// non-updatable jar from some other apex in the ART boot image => error
+	error = "module 'some-non-updatable-apex-lib' is not allowed in the ART boot image"
+	transform = func(config *dexpreopt.GlobalConfig) {
+		config.ArtApexJars = []string{"some-non-updatable-apex-lib"}
+	}
+	testNoUpdatableJarsInBootImage(t, error, bp, transform)
+
 	// updatable jar from some other apex in the framework boot image => error
 	error = "module 'some-updatable-apex-lib' from updatable apex 'some-updatable-apex' is not allowed in the framework boot image"
 	transform = func(config *dexpreopt.GlobalConfig) {
@@ -4587,6 +4624,12 @@
 	}
 	testNoUpdatableJarsInBootImage(t, error, bp, transform)
 
+	// non-updatable jar from some other apex in the framework boot image => ok
+	transform = func(config *dexpreopt.GlobalConfig) {
+		config.BootJars = []string{"some-non-updatable-apex-lib"}
+	}
+	testNoUpdatableJarsInBootImage(t, "", bp, transform)
+
 	// nonexistent jar in the ART boot image => error
 	error = "failed to find a dex jar path for module 'nonexistent'"
 	transform = func(config *dexpreopt.GlobalConfig) {
@@ -4602,7 +4645,7 @@
 	testNoUpdatableJarsInBootImage(t, error, bp, transform)
 
 	// platform jar in the ART boot image => error
-	error = "module 'some-platform-lib' is part of the platform and not allowed in the ART boot image"
+	error = "module 'some-platform-lib' is not allowed in the ART boot image"
 	transform = func(config *dexpreopt.GlobalConfig) {
 		config.ArtApexJars = []string{"some-platform-lib"}
 	}
diff --git a/java/app.go b/java/app.go
index 1fc18fb..e585dc8 100755
--- a/java/app.go
+++ b/java/app.go
@@ -414,7 +414,7 @@
 }
 
 func (a *AndroidApp) checkAppSdkVersions(ctx android.ModuleContext) {
-	if Bool(a.appProperties.Updatable) {
+	if a.Updatable() {
 		if !a.sdkVersion().stable() {
 			ctx.PropertyErrorf("sdk_version", "Updatable apps must use stable SDKs, found %v", a.sdkVersion())
 		}
@@ -880,6 +880,10 @@
 	a.ApexBundleDepsInfo.BuildDepsInfoLists(ctx, a.MinSdkVersion(), depsInfo)
 }
 
+func (a *AndroidApp) Updatable() bool {
+	return Bool(a.appProperties.Updatable) || a.ApexModuleBase.Updatable()
+}
+
 func (a *AndroidApp) getCertString(ctx android.BaseModuleContext) string {
 	certificate, overridden := ctx.DeviceConfig().OverrideCertificateFor(ctx.ModuleName())
 	if overridden {
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index 1b26667..b518e9c 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -264,27 +264,28 @@
 
 	// Check that this module satisfies constraints for a particular boot image.
 	apex, isApexModule := module.(android.ApexModule)
+	fromUpdatableApex := isApexModule && apex.Updatable()
 	if image.name == artBootImageName {
 		if isApexModule && strings.HasPrefix(apex.ApexName(), "com.android.art.") {
-			// ok, found the jar in the ART apex
-		} else if isApexModule && !apex.IsForPlatform() {
-			// this jar is part of an updatable apex other than ART, fail immediately
-			ctx.Errorf("module '%s' from updatable apex '%s' is not allowed in the ART boot image", name, apex.ApexName())
+			// ok: found the jar in the ART apex
 		} else if isApexModule && apex.IsForPlatform() && Bool(module.(*Library).deviceProperties.Hostdex) {
-			// this is a special "hostdex" variant, skip it and resume search
+			// exception (skip and continue): special "hostdex" platform variant
 			return -1, nil
 		} else if name == "jacocoagent" && ctx.Config().IsEnvTrue("EMMA_INSTRUMENT_FRAMEWORK") {
-			// this is Jacoco platform variant for a coverage build, skip it and resume search
+			// exception (skip and continue): Jacoco platform variant for a coverage build
 			return -1, nil
+		} else if fromUpdatableApex {
+			// error: this jar is part of an updatable apex other than ART
+			ctx.Errorf("module '%s' from updatable apex '%s' is not allowed in the ART boot image", name, apex.ApexName())
 		} else {
-			// this (installable) jar is part of the platform, fail immediately
-			ctx.Errorf("module '%s' is part of the platform and not allowed in the ART boot image", name)
+			// error: this jar is part of the platform or a non-updatable apex
+			ctx.Errorf("module '%s' is not allowed in the ART boot image", name)
 		}
 	} else if image.name == frameworkBootImageName {
-		if !isApexModule || apex.IsForPlatform() {
-			// ok, this jar is part of the platform
+		if !fromUpdatableApex {
+			// ok: this jar is part of the platform or a non-updatable apex
 		} else {
-			// this jar is part of an updatable apex, fail immediately
+			// error: this jar is part of an updatable apex
 			ctx.Errorf("module '%s' from updatable apex '%s' is not allowed in the framework boot image", name, apex.ApexName())
 		}
 	} else {