Create sysprop_library soong module

A newly introduced sysprop_library soong module will generate a
java_sdk_library and a cc_library from .sysprop description files.
Both Java modules and C++ modules can link against sysprop_library
module, thus giving consistency for using generated sysprop API.

As Java controls accessibility of Internal / System properties with
@hide and @SystemApi, 2 different header files will be created. And
build system will selectively expose depending on the property owner
and the place where the client libraries go into.

Bug: 80125326
Bug: 122170616
Test: 1) Create sysprop_library module.
Test: 2) Create empty txt files under prebuilts/sdk.
Test: 3) Create api directory, make update-api, and see changes.
Test: 4) Try to link against sysprop_library with various clients.
Test: 5) Soc_specific, Device_specific, Product_specific, recovery flags
work as intended.
Change-Id: I78dc5780ccfbb4b69e5c61dec26b94e92d43c333
diff --git a/cc/cc.go b/cc/cc.go
index 01577bc..081da12 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -41,6 +41,7 @@
 		ctx.BottomUp("test_per_src", testPerSrcMutator).Parallel()
 		ctx.BottomUp("version", VersionMutator).Parallel()
 		ctx.BottomUp("begin", BeginMutator).Parallel()
+		ctx.BottomUp("sysprop", SyspropMutator).Parallel()
 	})
 
 	android.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
@@ -1211,11 +1212,18 @@
 		{Mutator: "link", Variation: "static"},
 	}, wholeStaticDepTag, deps.WholeStaticLibs...)
 
+	syspropImplLibraries := syspropImplLibraries(actx.Config())
+
 	for _, lib := range deps.StaticLibs {
 		depTag := staticDepTag
 		if inList(lib, deps.ReexportStaticLibHeaders) {
 			depTag = staticExportDepTag
 		}
+
+		if impl, ok := syspropImplLibraries[lib]; ok {
+			lib = impl
+		}
+
 		actx.AddVariationDependencies([]blueprint.Variation{
 			{Mutator: "link", Variation: "static"},
 		}, depTag, lib)
@@ -1253,12 +1261,18 @@
 	var sharedLibNames []string
 
 	for _, lib := range deps.SharedLibs {
-		name, version := stubsLibNameAndVersion(lib)
-		sharedLibNames = append(sharedLibNames, name)
 		depTag := sharedDepTag
 		if inList(lib, deps.ReexportSharedLibHeaders) {
 			depTag = sharedExportDepTag
 		}
+
+		if impl, ok := syspropImplLibraries[lib]; ok {
+			lib = impl
+		}
+
+		name, version := stubsLibNameAndVersion(lib)
+		sharedLibNames = append(sharedLibNames, name)
+
 		addSharedLibDependencies(depTag, name, version)
 	}
 
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 9d370c1..22ac0d9 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -51,165 +51,6 @@
 	os.Exit(run())
 }
 
-func gatherRequiredDeps(os android.OsType) string {
-	ret := `
-		toolchain_library {
-			name: "libatomic",
-			vendor_available: true,
-			recovery_available: true,
-			src: "",
-		}
-
-		toolchain_library {
-			name: "libcompiler_rt-extras",
-			vendor_available: true,
-			recovery_available: true,
-			src: "",
-		}
-
-		toolchain_library {
-			name: "libclang_rt.builtins-arm-android",
-			vendor_available: true,
-			recovery_available: true,
-			src: "",
-		}
-
-		toolchain_library {
-			name: "libclang_rt.builtins-aarch64-android",
-			vendor_available: true,
-			recovery_available: true,
-			src: "",
-		}
-
-		toolchain_library {
-			name: "libclang_rt.builtins-i686-android",
-			vendor_available: true,
-			recovery_available: true,
-			src: "",
-		}
-
-		toolchain_library {
-			name: "libclang_rt.builtins-x86_64-android",
-			vendor_available: true,
-			recovery_available: true,
-			src: "",
-		}
-
-		toolchain_library {
-			name: "libgcc",
-			vendor_available: true,
-			recovery_available: true,
-			src: "",
-		}
-
-		cc_library {
-			name: "libc",
-			no_libgcc: true,
-			nocrt: true,
-			system_shared_libs: [],
-			recovery_available: true,
-		}
-		llndk_library {
-			name: "libc",
-			symbol_file: "",
-		}
-		cc_library {
-			name: "libm",
-			no_libgcc: true,
-			nocrt: true,
-			system_shared_libs: [],
-			recovery_available: true,
-		}
-		llndk_library {
-			name: "libm",
-			symbol_file: "",
-		}
-		cc_library {
-			name: "libdl",
-			no_libgcc: true,
-			nocrt: true,
-			system_shared_libs: [],
-			recovery_available: true,
-		}
-		llndk_library {
-			name: "libdl",
-			symbol_file: "",
-		}
-		cc_library {
-			name: "libc++_static",
-			no_libgcc: true,
-			nocrt: true,
-			system_shared_libs: [],
-			stl: "none",
-			vendor_available: true,
-			recovery_available: true,
-		}
-		cc_library {
-			name: "libc++",
-			no_libgcc: true,
-			nocrt: true,
-			system_shared_libs: [],
-			stl: "none",
-			vendor_available: true,
-			recovery_available: true,
-			vndk: {
-				enabled: true,
-				support_system_process: true,
-			},
-		}
-		cc_library {
-			name: "libunwind_llvm",
-			no_libgcc: true,
-			nocrt: true,
-			system_shared_libs: [],
-			stl: "none",
-			vendor_available: true,
-			recovery_available: true,
-		}
-
-		cc_object {
-			name: "crtbegin_so",
-			recovery_available: true,
-			vendor_available: true,
-		}
-
-		cc_object {
-			name: "crtbegin_static",
-			recovery_available: true,
-			vendor_available: true,
-		}
-
-		cc_object {
-			name: "crtend_so",
-			recovery_available: true,
-			vendor_available: true,
-		}
-
-		cc_object {
-			name: "crtend_android",
-			recovery_available: true,
-			vendor_available: true,
-		}
-
-		cc_library {
-			name: "libprotobuf-cpp-lite",
-		}
-		`
-	if os == android.Fuchsia {
-		ret += `
-		cc_library {
-			name: "libbioniccompat",
-			stl: "none",
-		}
-		cc_library {
-			name: "libcompiler_rt",
-			stl: "none",
-		}
-		`
-	}
-	return ret
-}
-
 func createTestContext(t *testing.T, config android.Config, bp string, os android.OsType) *android.TestContext {
 	ctx := android.NewTestArchContext()
 	ctx.RegisterModuleType("cc_binary", android.ModuleFactoryAdaptor(BinaryFactory))
@@ -233,7 +74,7 @@
 	ctx.Register()
 
 	// add some modules that are required by the compiler and/or linker
-	bp = bp + gatherRequiredDeps(os)
+	bp = bp + GatherRequiredDepsForTest(os)
 
 	ctx.MockFileSystem(map[string][]byte{
 		"Android.bp":  []byte(bp),
diff --git a/cc/gen.go b/cc/gen.go
index c3088f4..0c3d089 100644
--- a/cc/gen.go
+++ b/cc/gen.go
@@ -56,10 +56,11 @@
 
 	sysprop = pctx.AndroidStaticRule("sysprop",
 		blueprint.RuleParams{
-			Command:     "$syspropCmd --header-output-dir=$headerOutDir --source-output-dir=$srcOutDir --include-name=$includeName $in",
+			Command: "$syspropCmd --header-dir=$headerOutDir --system-header-dir=$systemOutDir " +
+				"--source-dir=$srcOutDir --include-name=$includeName $in",
 			CommandDeps: []string{"$syspropCmd"},
 		},
-		"headerOutDir", "srcOutDir", "includeName")
+		"headerOutDir", "systemOutDir", "srcOutDir", "includeName")
 
 	windmc = pctx.AndroidStaticRule("windmc",
 		blueprint.RuleParams{
@@ -114,6 +115,7 @@
 
 func genSysprop(ctx android.ModuleContext, syspropFile android.Path) (android.Path, android.Path) {
 	headerFile := android.PathForModuleGen(ctx, "sysprop", "include", syspropFile.Rel()+".h")
+	systemHeaderFile := android.PathForModuleGen(ctx, "sysprop/system", "include", syspropFile.Rel()+".h")
 	cppFile := android.PathForModuleGen(ctx, "sysprop", syspropFile.Rel()+".cpp")
 
 	ctx.Build(pctx, android.BuildParams{
@@ -124,6 +126,7 @@
 		Input:          syspropFile,
 		Args: map[string]string{
 			"headerOutDir": filepath.Dir(headerFile.String()),
+			"systemOutDir": filepath.Dir(systemHeaderFile.String()),
 			"srcOutDir":    filepath.Dir(cppFile.String()),
 			"includeName":  syspropFile.Rel() + ".h",
 		},
diff --git a/cc/library.go b/cc/library.go
index a6c7bc8..a48b45d 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -67,6 +67,11 @@
 		Export_proto_headers *bool
 	}
 
+	Sysprop struct {
+		// Whether platform owns this sysprop library.
+		Platform *bool
+	}
+
 	Static_ndk_lib *bool
 
 	Stubs struct {
@@ -836,9 +841,27 @@
 	}
 
 	if library.baseCompiler.hasSrcExt(".sysprop") {
-		flags := []string{
+		internalFlags := []string{
 			"-I" + android.PathForModuleGen(ctx, "sysprop", "include").String(),
 		}
+		systemFlags := []string{
+			"-I" + android.PathForModuleGen(ctx, "sysprop/system", "include").String(),
+		}
+
+		flags := internalFlags
+
+		if library.Properties.Sysprop.Platform != nil {
+			isProduct := ctx.ProductSpecific() && !ctx.useVndk()
+			isVendor := ctx.useVndk()
+			isOwnerPlatform := Bool(library.Properties.Sysprop.Platform)
+
+			useSystem := isProduct || (isOwnerPlatform == isVendor)
+
+			if useSystem {
+				flags = systemFlags
+			}
+		}
+
 		library.reexportFlags(flags)
 		library.reexportDeps(library.baseCompiler.pathDeps)
 		library.reuseExportedFlags = append(library.reuseExportedFlags, flags...)
diff --git a/cc/sysprop.go b/cc/sysprop.go
new file mode 100644
index 0000000..656f79f
--- /dev/null
+++ b/cc/sysprop.go
@@ -0,0 +1,47 @@
+// Copyright (C) 2019 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 cc
+
+import (
+	"sync"
+
+	"android/soong/android"
+)
+
+type syspropLibraryInterface interface {
+	CcModuleName() string
+}
+
+var (
+	syspropImplLibrariesKey  = android.NewOnceKey("syspropImplLibirares")
+	syspropImplLibrariesLock sync.Mutex
+)
+
+func syspropImplLibraries(config android.Config) map[string]string {
+	return config.Once(syspropImplLibrariesKey, func() interface{} {
+		return make(map[string]string)
+	}).(map[string]string)
+}
+
+// gather list of sysprop libraries
+func SyspropMutator(mctx android.BottomUpMutatorContext) {
+	if m, ok := mctx.Module().(syspropLibraryInterface); ok {
+		syspropImplLibraries := syspropImplLibraries(mctx.Config())
+		syspropImplLibrariesLock.Lock()
+		defer syspropImplLibrariesLock.Unlock()
+
+		syspropImplLibraries[mctx.ModuleName()] = m.CcModuleName()
+	}
+}
diff --git a/cc/testing.go b/cc/testing.go
new file mode 100644
index 0000000..b3b2756
--- /dev/null
+++ b/cc/testing.go
@@ -0,0 +1,188 @@
+// Copyright (C) 2019 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 cc
+
+import (
+	"android/soong/android"
+)
+
+func GatherRequiredDepsForTest(os android.OsType) string {
+	ret := `
+		toolchain_library {
+			name: "libatomic",
+			vendor_available: true,
+			recovery_available: true,
+			src: "",
+		}
+
+		toolchain_library {
+			name: "libcompiler_rt-extras",
+			vendor_available: true,
+			recovery_available: true,
+			src: "",
+		}
+
+		toolchain_library {
+			name: "libclang_rt.builtins-arm-android",
+			vendor_available: true,
+			recovery_available: true,
+			src: "",
+		}
+
+		toolchain_library {
+			name: "libclang_rt.builtins-aarch64-android",
+			vendor_available: true,
+			recovery_available: true,
+			src: "",
+		}
+
+		toolchain_library {
+			name: "libclang_rt.builtins-i686-android",
+			vendor_available: true,
+			recovery_available: true,
+			src: "",
+		}
+
+		toolchain_library {
+			name: "libclang_rt.builtins-x86_64-android",
+			vendor_available: true,
+			recovery_available: true,
+			src: "",
+		}
+
+		toolchain_library {
+			name: "libgcc",
+			vendor_available: true,
+			recovery_available: true,
+			src: "",
+		}
+
+		cc_library {
+			name: "libbase",
+			no_libgcc: true,
+			nocrt: true,
+			vendor_available: true,
+			vndk: {
+				enabled: true,
+				support_system_process: true,
+			}
+		}
+		cc_library {
+			name: "libc",
+			no_libgcc: true,
+			nocrt: true,
+			system_shared_libs: [],
+			recovery_available: true,
+		}
+		llndk_library {
+			name: "libc",
+			symbol_file: "",
+		}
+		cc_library {
+			name: "libm",
+			no_libgcc: true,
+			nocrt: true,
+			system_shared_libs: [],
+			recovery_available: true,
+		}
+		llndk_library {
+			name: "libm",
+			symbol_file: "",
+		}
+		cc_library {
+			name: "libdl",
+			no_libgcc: true,
+			nocrt: true,
+			system_shared_libs: [],
+			recovery_available: true,
+		}
+		llndk_library {
+			name: "libdl",
+			symbol_file: "",
+		}
+		cc_library {
+			name: "libc++_static",
+			no_libgcc: true,
+			nocrt: true,
+			system_shared_libs: [],
+			stl: "none",
+			vendor_available: true,
+			recovery_available: true,
+		}
+		cc_library {
+			name: "libc++",
+			no_libgcc: true,
+			nocrt: true,
+			system_shared_libs: [],
+			stl: "none",
+			vendor_available: true,
+			recovery_available: true,
+			vndk: {
+				enabled: true,
+				support_system_process: true,
+			},
+		}
+		cc_library {
+			name: "libunwind_llvm",
+			no_libgcc: true,
+			nocrt: true,
+			system_shared_libs: [],
+			stl: "none",
+			vendor_available: true,
+			recovery_available: true,
+		}
+
+		cc_object {
+			name: "crtbegin_so",
+			recovery_available: true,
+			vendor_available: true,
+		}
+
+		cc_object {
+			name: "crtbegin_static",
+			recovery_available: true,
+			vendor_available: true,
+		}
+
+		cc_object {
+			name: "crtend_so",
+			recovery_available: true,
+			vendor_available: true,
+		}
+
+		cc_object {
+			name: "crtend_android",
+			recovery_available: true,
+			vendor_available: true,
+		}
+
+		cc_library {
+			name: "libprotobuf-cpp-lite",
+		}
+		`
+	if os == android.Fuchsia {
+		ret += `
+		cc_library {
+			name: "libbioniccompat",
+			stl: "none",
+		}
+		cc_library {
+			name: "libcompiler_rt",
+			stl: "none",
+		}
+		`
+	}
+	return ret
+}