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/sysprop/sysprop_library.go b/sysprop/sysprop_library.go
new file mode 100644
index 0000000..4069e78
--- /dev/null
+++ b/sysprop/sysprop_library.go
@@ -0,0 +1,130 @@
+// 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 sysprop
+
+import (
+	"android/soong/android"
+	"android/soong/cc"
+	"android/soong/java"
+	"github.com/google/blueprint"
+	"github.com/google/blueprint/proptools"
+)
+
+type dependencyTag struct {
+	blueprint.BaseDependencyTag
+	name string
+}
+
+type syspropLibrary struct {
+	java.SdkLibrary
+
+	commonProperties         commonProperties
+	syspropLibraryProperties syspropLibraryProperties
+}
+
+type syspropLibraryProperties struct {
+	// Determine who owns this sysprop library. Possible values are
+	// "Platform", "Vendor", or "Odm"
+	Property_owner string
+	Api_packages   []string
+}
+
+type commonProperties struct {
+	Srcs             []string
+	Recovery         *bool
+	Vendor_available *bool
+}
+
+var (
+	Bool         = proptools.Bool
+	syspropCcTag = dependencyTag{name: "syspropCc"}
+)
+
+func init() {
+	android.RegisterModuleType("sysprop_library", syspropLibraryFactory)
+}
+
+func (m *syspropLibrary) CcModuleName() string {
+	return "lib" + m.Name()
+}
+
+func (m *syspropLibrary) SyspropJavaModule() *java.SdkLibrary {
+	return &m.SdkLibrary
+}
+
+func syspropLibraryFactory() android.Module {
+	m := &syspropLibrary{}
+
+	m.AddProperties(
+		&m.commonProperties,
+		&m.syspropLibraryProperties,
+	)
+	m.InitSdkLibraryProperties()
+	android.InitAndroidMultiTargetsArchModule(m, android.DeviceSupported, "common")
+	android.AddLoadHook(m, func(ctx android.LoadHookContext) { syspropLibraryHook(ctx, m) })
+
+	return m
+}
+
+func syspropLibraryHook(ctx android.LoadHookContext, m *syspropLibrary) {
+	if m.syspropLibraryProperties.Api_packages == nil {
+		ctx.PropertyErrorf("api_packages", "sysprop_library must specify api_packages")
+	}
+
+	socSpecific := ctx.SocSpecific()
+	deviceSpecific := ctx.DeviceSpecific()
+	productSpecific := ctx.ProductSpecific()
+
+	owner := m.syspropLibraryProperties.Property_owner
+
+	switch owner {
+	case "Platform":
+		// Every partition can access platform-defined properties
+		break
+	case "Vendor":
+		// System can't access vendor's properties
+		if !socSpecific && !deviceSpecific && !productSpecific {
+			ctx.ModuleErrorf("None of soc_specific, device_specific, product_specific is true. " +
+				"System can't access sysprop_library owned by Vendor")
+		}
+	case "Odm":
+		// Only vendor can access Odm-defined properties
+		if !socSpecific && !deviceSpecific {
+			ctx.ModuleErrorf("Neither soc_speicifc nor device_specific is true. " +
+				"Odm-defined properties should be accessed only in Vendor or Odm")
+		}
+	default:
+		ctx.PropertyErrorf("property_owner",
+			"Unknown value %s: must be one of Platform, Vendor or Odm", owner)
+	}
+
+	ccProps := struct {
+		Name             *string
+		Soc_specific     *bool
+		Device_specific  *bool
+		Product_specific *bool
+		Sysprop          struct {
+			Platform *bool
+		}
+	}{}
+
+	ccProps.Name = proptools.StringPtr(m.CcModuleName())
+	ccProps.Soc_specific = proptools.BoolPtr(socSpecific)
+	ccProps.Device_specific = proptools.BoolPtr(deviceSpecific)
+	ccProps.Product_specific = proptools.BoolPtr(productSpecific)
+	ccProps.Sysprop.Platform = proptools.BoolPtr(owner == "Platform")
+
+	ctx.CreateModule(android.ModuleFactoryAdaptor(cc.LibraryFactory), &m.commonProperties, &ccProps)
+}