|  | // 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. | 
|  |  | 
|  | // sysprop package defines a module named sysprop_library that can implement sysprop as API | 
|  | // See https://source.android.com/devices/architecture/sysprops-apis for details | 
|  | package sysprop | 
|  |  | 
|  | import ( | 
|  | "fmt" | 
|  | "io" | 
|  | "os" | 
|  | "path" | 
|  | "strings" | 
|  | "sync" | 
|  |  | 
|  | "github.com/google/blueprint" | 
|  | "github.com/google/blueprint/proptools" | 
|  |  | 
|  | "android/soong/android" | 
|  | "android/soong/cc" | 
|  | "android/soong/java" | 
|  | "android/soong/rust" | 
|  | ) | 
|  |  | 
|  | type dependencyTag struct { | 
|  | blueprint.BaseDependencyTag | 
|  | name string | 
|  | } | 
|  |  | 
|  | type syspropGenProperties struct { | 
|  | Srcs      []string `android:"path"` | 
|  | Scope     string | 
|  | Name      *string | 
|  | Check_api *string | 
|  | } | 
|  |  | 
|  | type syspropJavaGenRule struct { | 
|  | android.ModuleBase | 
|  |  | 
|  | properties syspropGenProperties | 
|  |  | 
|  | genSrcjars android.Paths | 
|  | } | 
|  |  | 
|  | type syspropRustGenRule struct { | 
|  | *rust.BaseSourceProvider | 
|  |  | 
|  | properties rustLibraryProperties | 
|  | } | 
|  |  | 
|  | var _ android.OutputFileProducer = (*syspropJavaGenRule)(nil) | 
|  | var _ rust.SourceProvider = (*syspropRustGenRule)(nil) | 
|  |  | 
|  | var ( | 
|  | syspropJava = pctx.AndroidStaticRule("syspropJava", | 
|  | blueprint.RuleParams{ | 
|  | Command: `rm -rf $out.tmp && mkdir -p $out.tmp && ` + | 
|  | `$syspropJavaCmd --scope $scope --java-output-dir $out.tmp $in && ` + | 
|  | `$soongZipCmd -jar -o $out -C $out.tmp -D $out.tmp && rm -rf $out.tmp`, | 
|  | CommandDeps: []string{ | 
|  | "$syspropJavaCmd", | 
|  | "$soongZipCmd", | 
|  | }, | 
|  | }, "scope") | 
|  | syspropRust = pctx.AndroidStaticRule("syspropRust", | 
|  | blueprint.RuleParams{ | 
|  | Command: `rm -rf $out_dir && mkdir -p $out_dir && ` + | 
|  | `$syspropRustCmd --scope $scope --rust-output-dir $out_dir $in`, | 
|  | CommandDeps: []string{ | 
|  | "$syspropRustCmd", | 
|  | }, | 
|  | }, "scope", "out_dir") | 
|  | ) | 
|  |  | 
|  | func init() { | 
|  | pctx.HostBinToolVariable("soongZipCmd", "soong_zip") | 
|  | pctx.HostBinToolVariable("syspropJavaCmd", "sysprop_java") | 
|  | pctx.HostBinToolVariable("syspropRustCmd", "sysprop_rust") | 
|  | } | 
|  |  | 
|  | // syspropJavaGenRule module generates srcjar containing generated java APIs. | 
|  | // It also depends on check api rule, so api check has to pass to use sysprop_library. | 
|  | func (g *syspropJavaGenRule) GenerateAndroidBuildActions(ctx android.ModuleContext) { | 
|  | var checkApiFileTimeStamp android.WritablePath | 
|  |  | 
|  | ctx.VisitDirectDeps(func(dep android.Module) { | 
|  | if m, ok := dep.(*syspropLibrary); ok { | 
|  | checkApiFileTimeStamp = m.checkApiFileTimeStamp | 
|  | } | 
|  | }) | 
|  |  | 
|  | for _, syspropFile := range android.PathsForModuleSrc(ctx, g.properties.Srcs) { | 
|  | srcJarFile := android.GenPathWithExt(ctx, "sysprop", syspropFile, "srcjar") | 
|  |  | 
|  | ctx.Build(pctx, android.BuildParams{ | 
|  | Rule:        syspropJava, | 
|  | Description: "sysprop_java " + syspropFile.Rel(), | 
|  | Output:      srcJarFile, | 
|  | Input:       syspropFile, | 
|  | Implicit:    checkApiFileTimeStamp, | 
|  | Args: map[string]string{ | 
|  | "scope": g.properties.Scope, | 
|  | }, | 
|  | }) | 
|  |  | 
|  | g.genSrcjars = append(g.genSrcjars, srcJarFile) | 
|  | } | 
|  | } | 
|  |  | 
|  | func (g *syspropJavaGenRule) DepsMutator(ctx android.BottomUpMutatorContext) { | 
|  | // Add a dependency from the stubs to sysprop library so that the generator rule can depend on | 
|  | // the check API rule of the sysprop library. | 
|  | ctx.AddFarVariationDependencies(nil, nil, proptools.String(g.properties.Check_api)) | 
|  | } | 
|  |  | 
|  | func (g *syspropJavaGenRule) OutputFiles(tag string) (android.Paths, error) { | 
|  | switch tag { | 
|  | case "": | 
|  | return g.genSrcjars, nil | 
|  | default: | 
|  | return nil, fmt.Errorf("unsupported module reference tag %q", tag) | 
|  | } | 
|  | } | 
|  |  | 
|  | func syspropJavaGenFactory() android.Module { | 
|  | g := &syspropJavaGenRule{} | 
|  | g.AddProperties(&g.properties) | 
|  | android.InitAndroidModule(g) | 
|  | return g | 
|  | } | 
|  |  | 
|  | // syspropRustGenRule module generates rust source files containing generated rust APIs. | 
|  | // It also depends on check api rule, so api check has to pass to use sysprop_library. | 
|  | func (g *syspropRustGenRule) GenerateSource(ctx rust.ModuleContext, deps rust.PathDeps) android.Path { | 
|  | var checkApiFileTimeStamp android.WritablePath | 
|  |  | 
|  | ctx.VisitDirectDeps(func(dep android.Module) { | 
|  | if m, ok := dep.(*syspropLibrary); ok { | 
|  | checkApiFileTimeStamp = m.checkApiFileTimeStamp | 
|  | } | 
|  | }) | 
|  |  | 
|  | outputDir := android.PathForModuleOut(ctx, "src") | 
|  | libFile := outputDir.Join(ctx, "lib.rs") | 
|  | g.BaseSourceProvider.OutputFiles = append(g.BaseSourceProvider.OutputFiles, libFile) | 
|  | libFileLines := []string{"//! Autogenerated system property accessors."} | 
|  |  | 
|  | for _, syspropFile := range android.PathsForModuleSrc(ctx, g.properties.Sysprop_srcs) { | 
|  | moduleName := syspropPathToRustModule(syspropFile) | 
|  | moduleDir := outputDir.Join(ctx, moduleName) | 
|  | modulePath := moduleDir.Join(ctx, "mod.rs") | 
|  |  | 
|  | ctx.Build(pctx, android.BuildParams{ | 
|  | Rule:        syspropRust, | 
|  | Description: "sysprop_rust " + syspropFile.Rel(), | 
|  | Output:      modulePath, | 
|  | Input:       syspropFile, | 
|  | Implicit:    checkApiFileTimeStamp, | 
|  | Args: map[string]string{ | 
|  | "scope":   g.properties.Scope, | 
|  | "out_dir": moduleDir.String(), | 
|  | }, | 
|  | }) | 
|  |  | 
|  | g.BaseSourceProvider.OutputFiles = append(g.BaseSourceProvider.OutputFiles, modulePath) | 
|  | libFileLines = append(libFileLines, fmt.Sprintf("pub mod %s;", moduleName)) | 
|  | } | 
|  |  | 
|  | libFileSource := strings.Join(libFileLines, "\n") | 
|  | android.WriteFileRule(ctx, libFile, libFileSource) | 
|  |  | 
|  | return libFile | 
|  | } | 
|  |  | 
|  | func (g *syspropRustGenRule) SourceProviderProps() []interface{} { | 
|  | return append(g.BaseSourceProvider.SourceProviderProps(), &g.Properties) | 
|  | } | 
|  |  | 
|  | // syspropPathToRustModule takes a path to a .sysprop file and returns the name to use for the | 
|  | // corresponding Rust module. | 
|  | func syspropPathToRustModule(syspropFilename android.Path) string { | 
|  | filenameBase := strings.TrimSuffix(syspropFilename.Base(), ".sysprop") | 
|  | return strings.ToLower(filenameBase) | 
|  | } | 
|  |  | 
|  | func (g *syspropRustGenRule) DepsMutator(ctx android.BottomUpMutatorContext) { | 
|  | // Add a dependency from the stubs to sysprop library so that the generator rule can depend on | 
|  | // the check API rule of the sysprop library. | 
|  | ctx.AddFarVariationDependencies(nil, nil, proptools.String(g.properties.Check_api)) | 
|  | } | 
|  |  | 
|  | func syspropRustGenFactory() android.Module { | 
|  | g := &syspropRustGenRule{ | 
|  | BaseSourceProvider: rust.NewSourceProvider(), | 
|  | } | 
|  | sourceProvider := rust.NewSourceProviderModule(android.DeviceSupported, g, false, false) | 
|  | sourceProvider.AddProperties(&g.properties) | 
|  | return sourceProvider.Init() | 
|  | } | 
|  |  | 
|  | type syspropLibrary struct { | 
|  | android.ModuleBase | 
|  | android.ApexModuleBase | 
|  |  | 
|  | properties syspropLibraryProperties | 
|  |  | 
|  | checkApiFileTimeStamp android.WritablePath | 
|  | latestApiFile         android.OptionalPath | 
|  | currentApiFile        android.OptionalPath | 
|  | dumpedApiFile         android.WritablePath | 
|  | } | 
|  |  | 
|  | type syspropLibraryProperties struct { | 
|  | // Determine who owns this sysprop library. Possible values are | 
|  | // "Platform", "Vendor", or "Odm" | 
|  | Property_owner string | 
|  |  | 
|  | // list of package names that will be documented and publicized as API | 
|  | Api_packages []string | 
|  |  | 
|  | // If set to true, allow this module to be dexed and installed on devices. | 
|  | Installable *bool | 
|  |  | 
|  | // Make this module available when building for ramdisk | 
|  | Ramdisk_available *bool | 
|  |  | 
|  | // Make this module available when building for recovery | 
|  | Recovery_available *bool | 
|  |  | 
|  | // Make this module available when building for vendor | 
|  | Vendor_available *bool | 
|  |  | 
|  | // Make this module available when building for product | 
|  | Product_available *bool | 
|  |  | 
|  | // list of .sysprop files which defines the properties. | 
|  | Srcs []string `android:"path"` | 
|  |  | 
|  | // If set to true, build a variant of the module for the host.  Defaults to false. | 
|  | Host_supported *bool | 
|  |  | 
|  | Cpp struct { | 
|  | // Minimum sdk version that the artifact should support when it runs as part of mainline modules(APEX). | 
|  | // Forwarded to cc_library.min_sdk_version | 
|  | Min_sdk_version *string | 
|  |  | 
|  | // C compiler flags used to build library | 
|  | Cflags []string | 
|  |  | 
|  | // Linker flags used to build binary | 
|  | Ldflags []string | 
|  | } | 
|  |  | 
|  | Java struct { | 
|  | // Minimum sdk version that the artifact should support when it runs as part of mainline modules(APEX). | 
|  | // Forwarded to java_library.min_sdk_version | 
|  | Min_sdk_version *string | 
|  | } | 
|  |  | 
|  | Rust struct { | 
|  | // Minimum sdk version that the artifact should support when it runs as part of mainline modules(APEX). | 
|  | // Forwarded to rust_library.min_sdk_version | 
|  | Min_sdk_version *string | 
|  | } | 
|  | } | 
|  |  | 
|  | var ( | 
|  | pctx         = android.NewPackageContext("android/soong/sysprop") | 
|  | syspropCcTag = dependencyTag{name: "syspropCc"} | 
|  |  | 
|  | syspropLibrariesKey  = android.NewOnceKey("syspropLibraries") | 
|  | syspropLibrariesLock sync.Mutex | 
|  | ) | 
|  |  | 
|  | // List of sysprop_library used by property_contexts to perform type check. | 
|  | func syspropLibraries(config android.Config) *[]string { | 
|  | return config.Once(syspropLibrariesKey, func() interface{} { | 
|  | return &[]string{} | 
|  | }).(*[]string) | 
|  | } | 
|  |  | 
|  | func SyspropLibraries(config android.Config) []string { | 
|  | return append([]string{}, *syspropLibraries(config)...) | 
|  | } | 
|  |  | 
|  | func init() { | 
|  | registerSyspropBuildComponents(android.InitRegistrationContext) | 
|  | } | 
|  |  | 
|  | func registerSyspropBuildComponents(ctx android.RegistrationContext) { | 
|  | ctx.RegisterModuleType("sysprop_library", syspropLibraryFactory) | 
|  | } | 
|  |  | 
|  | func (m *syspropLibrary) Name() string { | 
|  | return m.BaseModuleName() + "_sysprop_library" | 
|  | } | 
|  |  | 
|  | func (m *syspropLibrary) Owner() string { | 
|  | return m.properties.Property_owner | 
|  | } | 
|  |  | 
|  | func (m *syspropLibrary) CcImplementationModuleName() string { | 
|  | return "lib" + m.BaseModuleName() | 
|  | } | 
|  |  | 
|  | func (m *syspropLibrary) javaPublicStubName() string { | 
|  | return m.BaseModuleName() + "_public" | 
|  | } | 
|  |  | 
|  | func (m *syspropLibrary) javaGenModuleName() string { | 
|  | return m.BaseModuleName() + "_java_gen" | 
|  | } | 
|  |  | 
|  | func (m *syspropLibrary) javaGenPublicStubName() string { | 
|  | return m.BaseModuleName() + "_java_gen_public" | 
|  | } | 
|  |  | 
|  | func (m *syspropLibrary) rustGenStubName() string { | 
|  | return "lib" + m.rustCrateName() + "_rust" | 
|  | } | 
|  |  | 
|  | func (m *syspropLibrary) rustCrateName() string { | 
|  | moduleName := strings.ToLower(m.BaseModuleName()) | 
|  | moduleName = strings.ReplaceAll(moduleName, "-", "_") | 
|  | moduleName = strings.ReplaceAll(moduleName, ".", "_") | 
|  | return moduleName | 
|  | } | 
|  |  | 
|  | func (m *syspropLibrary) BaseModuleName() string { | 
|  | return m.ModuleBase.Name() | 
|  | } | 
|  |  | 
|  | func (m *syspropLibrary) CurrentSyspropApiFile() android.OptionalPath { | 
|  | return m.currentApiFile | 
|  | } | 
|  |  | 
|  | // GenerateAndroidBuildActions of sysprop_library handles API dump and API check. | 
|  | // generated java_library will depend on these API files. | 
|  | func (m *syspropLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) { | 
|  | baseModuleName := m.BaseModuleName() | 
|  | srcs := android.PathsForModuleSrc(ctx, m.properties.Srcs) | 
|  | for _, syspropFile := range srcs { | 
|  | if syspropFile.Ext() != ".sysprop" { | 
|  | ctx.PropertyErrorf("srcs", "srcs contains non-sysprop file %q", syspropFile.String()) | 
|  | } | 
|  | } | 
|  | android.SetProvider(ctx, blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: srcs.Strings()}) | 
|  |  | 
|  | if ctx.Failed() { | 
|  | return | 
|  | } | 
|  |  | 
|  | apiDirectoryPath := path.Join(ctx.ModuleDir(), "api") | 
|  | currentApiFilePath := path.Join(apiDirectoryPath, baseModuleName+"-current.txt") | 
|  | latestApiFilePath := path.Join(apiDirectoryPath, baseModuleName+"-latest.txt") | 
|  | m.currentApiFile = android.ExistentPathForSource(ctx, currentApiFilePath) | 
|  | m.latestApiFile = android.ExistentPathForSource(ctx, latestApiFilePath) | 
|  |  | 
|  | // dump API rule | 
|  | rule := android.NewRuleBuilder(pctx, ctx) | 
|  | m.dumpedApiFile = android.PathForModuleOut(ctx, "api-dump.txt") | 
|  | rule.Command(). | 
|  | BuiltTool("sysprop_api_dump"). | 
|  | Output(m.dumpedApiFile). | 
|  | Inputs(srcs) | 
|  | rule.Build(baseModuleName+"_api_dump", baseModuleName+" api dump") | 
|  |  | 
|  | // check API rule | 
|  | rule = android.NewRuleBuilder(pctx, ctx) | 
|  |  | 
|  | // We allow that the API txt files don't exist, when the sysprop_library only contains internal | 
|  | // properties. But we have to feed current api file and latest api file to the rule builder. | 
|  | // Currently we can't get android.Path representing the null device, so we add any existing API | 
|  | // txt files to implicits, and then directly feed string paths, rather than calling Input(Path) | 
|  | // method. | 
|  | var apiFileList android.Paths | 
|  | currentApiArgument := os.DevNull | 
|  | if m.currentApiFile.Valid() { | 
|  | apiFileList = append(apiFileList, m.currentApiFile.Path()) | 
|  | currentApiArgument = m.currentApiFile.String() | 
|  | } | 
|  |  | 
|  | latestApiArgument := os.DevNull | 
|  | if m.latestApiFile.Valid() { | 
|  | apiFileList = append(apiFileList, m.latestApiFile.Path()) | 
|  | latestApiArgument = m.latestApiFile.String() | 
|  | } | 
|  |  | 
|  | // 1. compares current.txt to api-dump.txt | 
|  | // current.txt should be identical to api-dump.txt. | 
|  | msg := fmt.Sprintf(`\n******************************\n`+ | 
|  | `API of sysprop_library %s doesn't match with current.txt\n`+ | 
|  | `Please update current.txt by:\n`+ | 
|  | `m %s-dump-api && mkdir -p %q && rm -rf %q && cp -f %q %q\n`+ | 
|  | `******************************\n`, baseModuleName, baseModuleName, | 
|  | apiDirectoryPath, currentApiFilePath, m.dumpedApiFile.String(), currentApiFilePath) | 
|  |  | 
|  | rule.Command(). | 
|  | Text("( cmp").Flag("-s"). | 
|  | Input(m.dumpedApiFile). | 
|  | Text(currentApiArgument). | 
|  | Text("|| ( echo").Flag("-e"). | 
|  | Flag(`"` + msg + `"`). | 
|  | Text("; exit 38) )") | 
|  |  | 
|  | // 2. compares current.txt to latest.txt (frozen API) | 
|  | // current.txt should be compatible with latest.txt | 
|  | msg = fmt.Sprintf(`\n******************************\n`+ | 
|  | `API of sysprop_library %s doesn't match with latest version\n`+ | 
|  | `Please fix the breakage and rebuild.\n`+ | 
|  | `******************************\n`, baseModuleName) | 
|  |  | 
|  | rule.Command(). | 
|  | Text("( "). | 
|  | BuiltTool("sysprop_api_checker"). | 
|  | Text(latestApiArgument). | 
|  | Text(currentApiArgument). | 
|  | Text(" || ( echo").Flag("-e"). | 
|  | Flag(`"` + msg + `"`). | 
|  | Text("; exit 38) )"). | 
|  | Implicits(apiFileList) | 
|  |  | 
|  | m.checkApiFileTimeStamp = android.PathForModuleOut(ctx, "check_api.timestamp") | 
|  |  | 
|  | rule.Command(). | 
|  | Text("touch"). | 
|  | Output(m.checkApiFileTimeStamp) | 
|  |  | 
|  | rule.Build(baseModuleName+"_check_api", baseModuleName+" check api") | 
|  | } | 
|  |  | 
|  | func (m *syspropLibrary) AndroidMk() android.AndroidMkData { | 
|  | return android.AndroidMkData{ | 
|  | Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) { | 
|  | // sysprop_library module itself is defined as a FAKE module to perform API check. | 
|  | // Actual implementation libraries are created on LoadHookMutator | 
|  | fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)", " # sysprop.syspropLibrary") | 
|  | fmt.Fprintln(w, "LOCAL_MODULE :=", m.Name()) | 
|  | fmt.Fprintf(w, "LOCAL_MODULE_CLASS := FAKE\n") | 
|  | fmt.Fprintf(w, "LOCAL_MODULE_TAGS := optional\n") | 
|  | // AconfigUpdateAndroidMkData may have added elements to Extra.  Process them here. | 
|  | for _, extra := range data.Extra { | 
|  | extra(w, nil) | 
|  | } | 
|  | fmt.Fprintf(w, "include $(BUILD_SYSTEM)/base_rules.mk\n\n") | 
|  | fmt.Fprintf(w, "$(LOCAL_BUILT_MODULE): %s\n", m.checkApiFileTimeStamp.String()) | 
|  | fmt.Fprintf(w, "\ttouch $@\n\n") | 
|  | fmt.Fprintf(w, ".PHONY: %s-check-api %s-dump-api\n\n", name, name) | 
|  |  | 
|  | // dump API rule | 
|  | fmt.Fprintf(w, "%s-dump-api: %s\n\n", name, m.dumpedApiFile.String()) | 
|  |  | 
|  | // check API rule | 
|  | fmt.Fprintf(w, "%s-check-api: %s\n\n", name, m.checkApiFileTimeStamp.String()) | 
|  | }} | 
|  | } | 
|  |  | 
|  | var _ android.ApexModule = (*syspropLibrary)(nil) | 
|  |  | 
|  | // Implements android.ApexModule | 
|  | func (m *syspropLibrary) ShouldSupportSdkVersion(ctx android.BaseModuleContext, | 
|  | sdkVersion android.ApiLevel) error { | 
|  | return fmt.Errorf("sysprop_library is not supposed to be part of apex modules") | 
|  | } | 
|  |  | 
|  | // sysprop_library creates schematized APIs from sysprop description files (.sysprop). | 
|  | // Both Java and C++ modules can link against sysprop_library, and API stability check | 
|  | // against latest APIs (see build/soong/scripts/freeze-sysprop-api-files.sh) | 
|  | // is performed. Note that the generated C++ module has its name prefixed with | 
|  | // `lib`, and it is this module that should be depended on from other C++ | 
|  | // modules; i.e., if the sysprop_library module is named `foo`, C++ modules | 
|  | // should depend on `libfoo`. | 
|  | func syspropLibraryFactory() android.Module { | 
|  | m := &syspropLibrary{} | 
|  |  | 
|  | m.AddProperties( | 
|  | &m.properties, | 
|  | ) | 
|  | android.InitAndroidModule(m) | 
|  | android.InitApexModule(m) | 
|  | android.AddLoadHook(m, func(ctx android.LoadHookContext) { syspropLibraryHook(ctx, m) }) | 
|  | return m | 
|  | } | 
|  |  | 
|  | type ccLibraryProperties struct { | 
|  | Name             *string | 
|  | Srcs             []string | 
|  | Soc_specific     *bool | 
|  | Device_specific  *bool | 
|  | Product_specific *bool | 
|  | Sysprop          struct { | 
|  | Platform *bool | 
|  | } | 
|  | Target struct { | 
|  | Android struct { | 
|  | Header_libs []string | 
|  | Shared_libs []string | 
|  | } | 
|  | Host struct { | 
|  | Static_libs []string | 
|  | } | 
|  | } | 
|  | Required           []string | 
|  | Recovery           *bool | 
|  | Recovery_available *bool | 
|  | Vendor_available   *bool | 
|  | Product_available  *bool | 
|  | Ramdisk_available  *bool | 
|  | Host_supported     *bool | 
|  | Apex_available     []string | 
|  | Min_sdk_version    *string | 
|  | Cflags             []string | 
|  | Ldflags            []string | 
|  | } | 
|  |  | 
|  | type javaLibraryProperties struct { | 
|  | Name              *string | 
|  | Srcs              []string | 
|  | Soc_specific      *bool | 
|  | Device_specific   *bool | 
|  | Product_specific  *bool | 
|  | Required          []string | 
|  | Sdk_version       *string | 
|  | Installable       *bool | 
|  | Libs              []string | 
|  | Stem              *string | 
|  | SyspropPublicStub string | 
|  | Apex_available    []string | 
|  | Min_sdk_version   *string | 
|  | } | 
|  |  | 
|  | type rustLibraryProperties struct { | 
|  | Name              *string | 
|  | Sysprop_srcs      []string `android:"path"` | 
|  | Scope             string | 
|  | Check_api         *string | 
|  | Srcs              []string | 
|  | Installable       *bool | 
|  | Crate_name        string | 
|  | Rustlibs          []string | 
|  | Vendor_available  *bool | 
|  | Product_available *bool | 
|  | Apex_available    []string | 
|  | Min_sdk_version   *string | 
|  | } | 
|  |  | 
|  | func syspropLibraryHook(ctx android.LoadHookContext, m *syspropLibrary) { | 
|  | if len(m.properties.Srcs) == 0 { | 
|  | ctx.PropertyErrorf("srcs", "sysprop_library must specify srcs") | 
|  | } | 
|  |  | 
|  | // ctx's Platform or Specific functions represent where this sysprop_library installed. | 
|  | installedInSystem := ctx.Platform() || ctx.SystemExtSpecific() | 
|  | installedInVendorOrOdm := ctx.SocSpecific() || ctx.DeviceSpecific() | 
|  | installedInProduct := ctx.ProductSpecific() | 
|  | isOwnerPlatform := false | 
|  | var javaSyspropStub string | 
|  |  | 
|  | // javaSyspropStub contains stub libraries used by generated APIs, instead of framework stub. | 
|  | // This is to make sysprop_library link against core_current. | 
|  | if installedInVendorOrOdm { | 
|  | javaSyspropStub = "sysprop-library-stub-vendor" | 
|  | } else if installedInProduct { | 
|  | javaSyspropStub = "sysprop-library-stub-product" | 
|  | } else { | 
|  | javaSyspropStub = "sysprop-library-stub-platform" | 
|  | } | 
|  |  | 
|  | switch m.Owner() { | 
|  | case "Platform": | 
|  | // Every partition can access platform-defined properties | 
|  | isOwnerPlatform = true | 
|  | case "Vendor": | 
|  | // System can't access vendor's properties | 
|  | if installedInSystem { | 
|  | 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 !installedInVendorOrOdm { | 
|  | 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", m.Owner()) | 
|  | } | 
|  |  | 
|  | // Generate a C++ implementation library. | 
|  | // cc_library can receive *.sysprop files as their srcs, generating sources itself. | 
|  | ccProps := ccLibraryProperties{} | 
|  | ccProps.Name = proptools.StringPtr(m.CcImplementationModuleName()) | 
|  | ccProps.Srcs = m.properties.Srcs | 
|  | ccProps.Soc_specific = proptools.BoolPtr(ctx.SocSpecific()) | 
|  | ccProps.Device_specific = proptools.BoolPtr(ctx.DeviceSpecific()) | 
|  | ccProps.Product_specific = proptools.BoolPtr(ctx.ProductSpecific()) | 
|  | ccProps.Sysprop.Platform = proptools.BoolPtr(isOwnerPlatform) | 
|  | ccProps.Target.Android.Header_libs = []string{"libbase_headers"} | 
|  | ccProps.Target.Android.Shared_libs = []string{"liblog"} | 
|  | ccProps.Target.Host.Static_libs = []string{"libbase", "liblog"} | 
|  | ccProps.Recovery_available = m.properties.Recovery_available | 
|  | ccProps.Vendor_available = m.properties.Vendor_available | 
|  | ccProps.Product_available = m.properties.Product_available | 
|  | ccProps.Ramdisk_available = m.properties.Ramdisk_available | 
|  | ccProps.Host_supported = m.properties.Host_supported | 
|  | ccProps.Apex_available = m.ApexProperties.Apex_available | 
|  | ccProps.Min_sdk_version = m.properties.Cpp.Min_sdk_version | 
|  | ccProps.Cflags = m.properties.Cpp.Cflags | 
|  | ccProps.Ldflags = m.properties.Cpp.Ldflags | 
|  | ctx.CreateModule(cc.LibraryFactory, &ccProps) | 
|  |  | 
|  | scope := "internal" | 
|  |  | 
|  | // We need to only use public version, if the partition where sysprop_library will be installed | 
|  | // is different from owner. | 
|  | if ctx.ProductSpecific() { | 
|  | // Currently product partition can't own any sysprop_library. So product always uses public. | 
|  | scope = "public" | 
|  | } else if isOwnerPlatform && installedInVendorOrOdm { | 
|  | // Vendor or Odm should use public version of Platform's sysprop_library. | 
|  | scope = "public" | 
|  | } | 
|  |  | 
|  | // Generate a Java implementation library. | 
|  | // Contrast to C++, syspropJavaGenRule module will generate srcjar and the srcjar will be fed | 
|  | // to Java implementation library. | 
|  | ctx.CreateModule(syspropJavaGenFactory, &syspropGenProperties{ | 
|  | Srcs:      m.properties.Srcs, | 
|  | Scope:     scope, | 
|  | Name:      proptools.StringPtr(m.javaGenModuleName()), | 
|  | Check_api: proptools.StringPtr(ctx.ModuleName()), | 
|  | }) | 
|  |  | 
|  | // if platform sysprop_library is installed in /system or /system-ext, we regard it as an API | 
|  | // and allow any modules (even from different partition) to link against the sysprop_library. | 
|  | // To do that, we create a public stub and expose it to modules with sdk_version: system_*. | 
|  | var publicStub string | 
|  | if isOwnerPlatform && installedInSystem { | 
|  | publicStub = m.javaPublicStubName() | 
|  | } | 
|  |  | 
|  | ctx.CreateModule(java.LibraryFactory, &javaLibraryProperties{ | 
|  | Name:              proptools.StringPtr(m.BaseModuleName()), | 
|  | Srcs:              []string{":" + m.javaGenModuleName()}, | 
|  | Soc_specific:      proptools.BoolPtr(ctx.SocSpecific()), | 
|  | Device_specific:   proptools.BoolPtr(ctx.DeviceSpecific()), | 
|  | Product_specific:  proptools.BoolPtr(ctx.ProductSpecific()), | 
|  | Installable:       m.properties.Installable, | 
|  | Sdk_version:       proptools.StringPtr("core_current"), | 
|  | Libs:              []string{javaSyspropStub}, | 
|  | SyspropPublicStub: publicStub, | 
|  | Apex_available:    m.ApexProperties.Apex_available, | 
|  | Min_sdk_version:   m.properties.Java.Min_sdk_version, | 
|  | }) | 
|  |  | 
|  | if publicStub != "" { | 
|  | ctx.CreateModule(syspropJavaGenFactory, &syspropGenProperties{ | 
|  | Srcs:      m.properties.Srcs, | 
|  | Scope:     "public", | 
|  | Name:      proptools.StringPtr(m.javaGenPublicStubName()), | 
|  | Check_api: proptools.StringPtr(ctx.ModuleName()), | 
|  | }) | 
|  |  | 
|  | ctx.CreateModule(java.LibraryFactory, &javaLibraryProperties{ | 
|  | Name:        proptools.StringPtr(publicStub), | 
|  | Srcs:        []string{":" + m.javaGenPublicStubName()}, | 
|  | Installable: proptools.BoolPtr(false), | 
|  | Sdk_version: proptools.StringPtr("core_current"), | 
|  | Libs:        []string{javaSyspropStub}, | 
|  | Stem:        proptools.StringPtr(m.BaseModuleName()), | 
|  | }) | 
|  | } | 
|  |  | 
|  | // Generate a Rust implementation library. | 
|  | rustProps := rustLibraryProperties{ | 
|  | Name:         proptools.StringPtr(m.rustGenStubName()), | 
|  | Sysprop_srcs: m.properties.Srcs, | 
|  | Scope:        scope, | 
|  | Check_api:    proptools.StringPtr(ctx.ModuleName()), | 
|  | Installable:  proptools.BoolPtr(false), | 
|  | Crate_name:   m.rustCrateName(), | 
|  | Rustlibs: []string{ | 
|  | "liblog_rust", | 
|  | "librustutils", | 
|  | }, | 
|  | Vendor_available:  m.properties.Vendor_available, | 
|  | Product_available: m.properties.Product_available, | 
|  | Apex_available:    m.ApexProperties.Apex_available, | 
|  | Min_sdk_version:   proptools.StringPtr("29"), | 
|  | } | 
|  | ctx.CreateModule(syspropRustGenFactory, &rustProps) | 
|  |  | 
|  | // syspropLibraries will be used by property_contexts to check types. | 
|  | // Record absolute paths of sysprop_library to prevent soong_namespace problem. | 
|  | if m.ExportedToMake() { | 
|  | syspropLibrariesLock.Lock() | 
|  | defer syspropLibrariesLock.Unlock() | 
|  |  | 
|  | libraries := syspropLibraries(ctx.Config()) | 
|  | *libraries = append(*libraries, "//"+ctx.ModuleDir()+":"+ctx.ModuleName()) | 
|  | } | 
|  | } |