• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright (C) 2019 The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15// sysprop package defines a module named sysprop_library that can implement sysprop as API
16// See https://source.android.com/devices/architecture/sysprops-apis for details
17package sysprop
18
19import (
20	"fmt"
21	"io"
22	"os"
23	"path"
24	"strings"
25	"sync"
26
27	"github.com/google/blueprint"
28	"github.com/google/blueprint/proptools"
29
30	"android/soong/android"
31	"android/soong/cc"
32	"android/soong/java"
33	"android/soong/rust"
34)
35
36type dependencyTag struct {
37	blueprint.BaseDependencyTag
38	name string
39}
40
41type syspropGenProperties struct {
42	Srcs      []string `android:"path"`
43	Scope     string
44	Name      *string
45	Check_api *string
46}
47
48type syspropJavaGenRule struct {
49	android.ModuleBase
50
51	properties syspropGenProperties
52}
53
54type syspropRustGenRule struct {
55	*rust.BaseSourceProvider
56
57	properties rustLibraryProperties
58}
59
60var _ rust.SourceProvider = (*syspropRustGenRule)(nil)
61
62var (
63	syspropJava = pctx.AndroidStaticRule("syspropJava",
64		blueprint.RuleParams{
65			Command: `rm -rf $out.tmp && mkdir -p $out.tmp && ` +
66				`$syspropJavaCmd --scope $scope --java-output-dir $out.tmp $in && ` +
67				`$soongZipCmd -jar -o $out -C $out.tmp -D $out.tmp && rm -rf $out.tmp`,
68			CommandDeps: []string{
69				"$syspropJavaCmd",
70				"$soongZipCmd",
71			},
72		}, "scope")
73	syspropRust = pctx.AndroidStaticRule("syspropRust",
74		blueprint.RuleParams{
75			Command: `rm -rf $out_dir && mkdir -p $out_dir && ` +
76				`$syspropRustCmd --scope $scope --rust-output-dir $out_dir $in`,
77			CommandDeps: []string{
78				"$syspropRustCmd",
79			},
80		}, "scope", "out_dir")
81)
82
83func init() {
84	pctx.HostBinToolVariable("soongZipCmd", "soong_zip")
85	pctx.HostBinToolVariable("syspropJavaCmd", "sysprop_java")
86	pctx.HostBinToolVariable("syspropRustCmd", "sysprop_rust")
87}
88
89// syspropJavaGenRule module generates srcjar containing generated java APIs.
90// It also depends on check api rule, so api check has to pass to use sysprop_library.
91func (g *syspropJavaGenRule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
92	var checkApiFileTimeStamp android.WritablePath
93
94	ctx.VisitDirectDeps(func(dep android.Module) {
95		if m, ok := dep.(*syspropLibrary); ok {
96			checkApiFileTimeStamp = m.checkApiFileTimeStamp
97		}
98	})
99
100	var genSrcjars android.Paths
101	for _, syspropFile := range android.PathsForModuleSrc(ctx, g.properties.Srcs) {
102		srcJarFile := android.GenPathWithExt(ctx, "sysprop", syspropFile, "srcjar")
103
104		ctx.Build(pctx, android.BuildParams{
105			Rule:        syspropJava,
106			Description: "sysprop_java " + syspropFile.Rel(),
107			Output:      srcJarFile,
108			Input:       syspropFile,
109			Implicit:    checkApiFileTimeStamp,
110			Args: map[string]string{
111				"scope": g.properties.Scope,
112			},
113		})
114
115		genSrcjars = append(genSrcjars, srcJarFile)
116	}
117
118	ctx.SetOutputFiles(genSrcjars, "")
119}
120
121func (g *syspropJavaGenRule) DepsMutator(ctx android.BottomUpMutatorContext) {
122	// Add a dependency from the stubs to sysprop library so that the generator rule can depend on
123	// the check API rule of the sysprop library.
124	ctx.AddFarVariationDependencies(nil, nil, proptools.String(g.properties.Check_api))
125}
126
127func syspropJavaGenFactory() android.Module {
128	g := &syspropJavaGenRule{}
129	g.AddProperties(&g.properties)
130	android.InitAndroidModule(g)
131	return g
132}
133
134// syspropRustGenRule module generates rust source files containing generated rust APIs.
135// It also depends on check api rule, so api check has to pass to use sysprop_library.
136func (g *syspropRustGenRule) GenerateSource(ctx rust.ModuleContext, deps rust.PathDeps) android.Path {
137	var checkApiFileTimeStamp android.WritablePath
138
139	ctx.VisitDirectDeps(func(dep android.Module) {
140		if m, ok := dep.(*syspropLibrary); ok {
141			checkApiFileTimeStamp = m.checkApiFileTimeStamp
142		}
143	})
144
145	outputDir := android.PathForModuleOut(ctx, "src")
146	libFile := outputDir.Join(ctx, "lib.rs")
147	g.BaseSourceProvider.OutputFiles = append(g.BaseSourceProvider.OutputFiles, libFile)
148	libFileLines := []string{"//! Autogenerated system property accessors."}
149
150	for _, syspropFile := range android.PathsForModuleSrc(ctx, g.properties.Sysprop_srcs) {
151		moduleName := syspropPathToRustModule(syspropFile)
152		moduleDir := outputDir.Join(ctx, moduleName)
153		modulePath := moduleDir.Join(ctx, "mod.rs")
154
155		ctx.Build(pctx, android.BuildParams{
156			Rule:        syspropRust,
157			Description: "sysprop_rust " + syspropFile.Rel(),
158			Output:      modulePath,
159			Input:       syspropFile,
160			Implicit:    checkApiFileTimeStamp,
161			Args: map[string]string{
162				"scope":   g.properties.Scope,
163				"out_dir": moduleDir.String(),
164			},
165		})
166
167		g.BaseSourceProvider.OutputFiles = append(g.BaseSourceProvider.OutputFiles, modulePath)
168		libFileLines = append(libFileLines, fmt.Sprintf("pub mod %s;", moduleName))
169	}
170
171	libFileSource := strings.Join(libFileLines, "\n")
172	android.WriteFileRule(ctx, libFile, libFileSource)
173
174	return libFile
175}
176
177func (g *syspropRustGenRule) SourceProviderProps() []interface{} {
178	return append(g.BaseSourceProvider.SourceProviderProps(), &g.Properties)
179}
180
181// syspropPathToRustModule takes a path to a .sysprop file and returns the name to use for the
182// corresponding Rust module.
183func syspropPathToRustModule(syspropFilename android.Path) string {
184	filenameBase := strings.TrimSuffix(syspropFilename.Base(), ".sysprop")
185	return strings.ToLower(filenameBase)
186}
187
188func (g *syspropRustGenRule) DepsMutator(ctx android.BottomUpMutatorContext) {
189	// Add a dependency from the stubs to sysprop library so that the generator rule can depend on
190	// the check API rule of the sysprop library.
191	ctx.AddFarVariationDependencies(nil, nil, proptools.String(g.properties.Check_api))
192}
193
194func syspropRustGenFactory() android.Module {
195	g := &syspropRustGenRule{
196		BaseSourceProvider: rust.NewSourceProvider(),
197	}
198	sourceProvider := rust.NewSourceProviderModule(android.DeviceSupported, g, false, false)
199	sourceProvider.AddProperties(&g.properties)
200	return sourceProvider.Init()
201}
202
203type syspropLibrary struct {
204	android.ModuleBase
205	android.ApexModuleBase
206
207	properties syspropLibraryProperties
208
209	checkApiFileTimeStamp android.WritablePath
210	latestApiFile         android.OptionalPath
211	currentApiFile        android.OptionalPath
212	dumpedApiFile         android.WritablePath
213}
214
215type syspropLibraryProperties struct {
216	// Determine who owns this sysprop library. Possible values are
217	// "Platform", "Vendor", or "Odm"
218	Property_owner string
219
220	// list of package names that will be documented and publicized as API
221	Api_packages []string
222
223	// If set to true, allow this module to be dexed and installed on devices.
224	Installable *bool
225
226	// Make this module available when building for ramdisk
227	Ramdisk_available *bool
228
229	// Make this module available when building for vendor ramdisk
230	Vendor_ramdisk_available *bool
231
232	// Make this module available when building for recovery
233	Recovery_available *bool
234
235	// Make this module available when building for vendor
236	Vendor_available *bool
237
238	// Make this module available when building for product
239	Product_available *bool
240
241	// list of .sysprop files which defines the properties.
242	Srcs []string `android:"path"`
243
244	// If set to true, build a variant of the module for the host.  Defaults to false.
245	Host_supported *bool
246
247	Cpp struct {
248		// Minimum sdk version that the artifact should support when it runs as part of mainline modules(APEX).
249		// Forwarded to cc_library.min_sdk_version
250		Min_sdk_version *string
251
252		// C compiler flags used to build library
253		Cflags []string
254
255		// Linker flags used to build binary
256		Ldflags []string
257	}
258
259	Java struct {
260		// Minimum sdk version that the artifact should support when it runs as part of mainline modules(APEX).
261		// Forwarded to java_library.min_sdk_version
262		Min_sdk_version *string
263	}
264
265	Rust struct {
266		// Minimum sdk version that the artifact should support when it runs as part of mainline modules(APEX).
267		// Forwarded to rust_library.min_sdk_version
268		Min_sdk_version *string
269	}
270}
271
272var (
273	pctx         = android.NewPackageContext("android/soong/sysprop")
274	syspropCcTag = dependencyTag{name: "syspropCc"}
275
276	syspropLibrariesKey  = android.NewOnceKey("syspropLibraries")
277	syspropLibrariesLock sync.Mutex
278)
279
280// List of sysprop_library used by property_contexts to perform type check.
281func syspropLibraries(config android.Config) *[]string {
282	return config.Once(syspropLibrariesKey, func() interface{} {
283		return &[]string{}
284	}).(*[]string)
285}
286
287func SyspropLibraries(config android.Config) []string {
288	return append([]string{}, *syspropLibraries(config)...)
289}
290
291func init() {
292	registerSyspropBuildComponents(android.InitRegistrationContext)
293}
294
295func registerSyspropBuildComponents(ctx android.RegistrationContext) {
296	ctx.RegisterModuleType("sysprop_library", syspropLibraryFactory)
297}
298
299func (m *syspropLibrary) Name() string {
300	return m.BaseModuleName() + "_sysprop_library"
301}
302
303func (m *syspropLibrary) Owner() string {
304	return m.properties.Property_owner
305}
306
307func (m *syspropLibrary) CcImplementationModuleName() string {
308	return "lib" + m.BaseModuleName()
309}
310
311func (m *syspropLibrary) javaPublicStubName() string {
312	return m.BaseModuleName() + "_public"
313}
314
315func (m *syspropLibrary) javaGenModuleName() string {
316	return m.BaseModuleName() + "_java_gen"
317}
318
319func (m *syspropLibrary) javaGenPublicStubName() string {
320	return m.BaseModuleName() + "_java_gen_public"
321}
322
323func (m *syspropLibrary) rustGenStubName() string {
324	return "lib" + m.rustCrateName() + "_rust"
325}
326
327func (m *syspropLibrary) rustCrateName() string {
328	moduleName := strings.ToLower(m.BaseModuleName())
329	moduleName = strings.ReplaceAll(moduleName, "-", "_")
330	moduleName = strings.ReplaceAll(moduleName, ".", "_")
331	return moduleName
332}
333
334func (m *syspropLibrary) BaseModuleName() string {
335	return m.ModuleBase.Name()
336}
337
338func (m *syspropLibrary) CurrentSyspropApiFile() android.OptionalPath {
339	return m.currentApiFile
340}
341
342// GenerateAndroidBuildActions of sysprop_library handles API dump and API check.
343// generated java_library will depend on these API files.
344func (m *syspropLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
345	baseModuleName := m.BaseModuleName()
346	srcs := android.PathsForModuleSrc(ctx, m.properties.Srcs)
347	for _, syspropFile := range srcs {
348		if syspropFile.Ext() != ".sysprop" {
349			ctx.PropertyErrorf("srcs", "srcs contains non-sysprop file %q", syspropFile.String())
350		}
351	}
352
353	if ctx.Failed() {
354		return
355	}
356
357	apiDirectoryPath := path.Join(ctx.ModuleDir(), "api")
358	currentApiFilePath := path.Join(apiDirectoryPath, baseModuleName+"-current.txt")
359	latestApiFilePath := path.Join(apiDirectoryPath, baseModuleName+"-latest.txt")
360	m.currentApiFile = android.ExistentPathForSource(ctx, currentApiFilePath)
361	m.latestApiFile = android.ExistentPathForSource(ctx, latestApiFilePath)
362
363	// dump API rule
364	rule := android.NewRuleBuilder(pctx, ctx)
365	m.dumpedApiFile = android.PathForModuleOut(ctx, "api-dump.txt")
366	rule.Command().
367		BuiltTool("sysprop_api_dump").
368		Output(m.dumpedApiFile).
369		Inputs(srcs)
370	rule.Build(baseModuleName+"_api_dump", baseModuleName+" api dump")
371
372	// check API rule
373	rule = android.NewRuleBuilder(pctx, ctx)
374
375	// We allow that the API txt files don't exist, when the sysprop_library only contains internal
376	// properties. But we have to feed current api file and latest api file to the rule builder.
377	// Currently we can't get android.Path representing the null device, so we add any existing API
378	// txt files to implicits, and then directly feed string paths, rather than calling Input(Path)
379	// method.
380	var apiFileList android.Paths
381	currentApiArgument := os.DevNull
382	if m.currentApiFile.Valid() {
383		apiFileList = append(apiFileList, m.currentApiFile.Path())
384		currentApiArgument = m.currentApiFile.String()
385	}
386
387	latestApiArgument := os.DevNull
388	if m.latestApiFile.Valid() {
389		apiFileList = append(apiFileList, m.latestApiFile.Path())
390		latestApiArgument = m.latestApiFile.String()
391	}
392
393	// 1. compares current.txt to api-dump.txt
394	// current.txt should be identical to api-dump.txt.
395	msg := fmt.Sprintf(`\n******************************\n`+
396		`API of sysprop_library %s doesn't match with current.txt\n`+
397		`Please update current.txt by:\n`+
398		`m %s-dump-api && mkdir -p %q && rm -rf %q && cp -f %q %q\n`+
399		`******************************\n`, baseModuleName, baseModuleName,
400		apiDirectoryPath, currentApiFilePath, m.dumpedApiFile.String(), currentApiFilePath)
401
402	rule.Command().
403		Text("( cmp").Flag("-s").
404		Input(m.dumpedApiFile).
405		Text(currentApiArgument).
406		Text("|| ( echo").Flag("-e").
407		Flag(`"` + msg + `"`).
408		Text("; exit 38) )")
409
410	// 2. compares current.txt to latest.txt (frozen API)
411	// current.txt should be compatible with latest.txt
412	msg = fmt.Sprintf(`\n******************************\n`+
413		`API of sysprop_library %s doesn't match with latest version\n`+
414		`Please fix the breakage and rebuild.\n`+
415		`******************************\n`, baseModuleName)
416
417	rule.Command().
418		Text("( ").
419		BuiltTool("sysprop_api_checker").
420		Text(latestApiArgument).
421		Text(currentApiArgument).
422		Text(" || ( echo").Flag("-e").
423		Flag(`"` + msg + `"`).
424		Text("; exit 38) )").
425		Implicits(apiFileList)
426
427	m.checkApiFileTimeStamp = android.PathForModuleOut(ctx, "check_api.timestamp")
428
429	rule.Command().
430		Text("touch").
431		Output(m.checkApiFileTimeStamp)
432
433	rule.Build(baseModuleName+"_check_api", baseModuleName+" check api")
434}
435
436func (m *syspropLibrary) AndroidMk() android.AndroidMkData {
437	return android.AndroidMkData{
438		Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
439			// sysprop_library module itself is defined as a FAKE module to perform API check.
440			// Actual implementation libraries are created on LoadHookMutator
441			fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)", " # sysprop.syspropLibrary")
442			fmt.Fprintln(w, "LOCAL_MODULE :=", m.Name())
443			fmt.Fprintf(w, "LOCAL_MODULE_CLASS := FAKE\n")
444			fmt.Fprintf(w, "LOCAL_MODULE_TAGS := optional\n")
445			// AconfigUpdateAndroidMkData may have added elements to Extra.  Process them here.
446			for _, extra := range data.Extra {
447				extra(w, nil)
448			}
449			fmt.Fprintf(w, "include $(BUILD_SYSTEM)/base_rules.mk\n\n")
450			fmt.Fprintf(w, "$(LOCAL_BUILT_MODULE): %s\n", m.checkApiFileTimeStamp.String())
451			fmt.Fprintf(w, "\ttouch $@\n\n")
452			fmt.Fprintf(w, ".PHONY: %s-check-api %s-dump-api\n\n", name, name)
453
454			// dump API rule
455			fmt.Fprintf(w, "%s-dump-api: %s\n\n", name, m.dumpedApiFile.String())
456
457			// check API rule
458			fmt.Fprintf(w, "%s-check-api: %s\n\n", name, m.checkApiFileTimeStamp.String())
459		}}
460}
461
462var _ android.ApexModule = (*syspropLibrary)(nil)
463
464// Implements android.ApexModule
465func (m *syspropLibrary) MinSdkVersionSupported(ctx android.BaseModuleContext) android.ApiLevel {
466	return android.MinApiLevel
467}
468
469// sysprop_library creates schematized APIs from sysprop description files (.sysprop).
470// Both Java and C++ modules can link against sysprop_library, and API stability check
471// against latest APIs (see build/soong/scripts/freeze-sysprop-api-files.sh)
472// is performed. Note that the generated C++ module has its name prefixed with
473// `lib`, and it is this module that should be depended on from other C++
474// modules; i.e., if the sysprop_library module is named `foo`, C++ modules
475// should depend on `libfoo`.
476func syspropLibraryFactory() android.Module {
477	m := &syspropLibrary{}
478
479	m.AddProperties(
480		&m.properties,
481	)
482	android.InitAndroidModule(m)
483	android.InitApexModule(m)
484	android.AddLoadHook(m, func(ctx android.LoadHookContext) { syspropLibraryHook(ctx, m) })
485	return m
486}
487
488type ccLibraryProperties struct {
489	Name             *string
490	Srcs             []string
491	Soc_specific     *bool
492	Device_specific  *bool
493	Product_specific *bool
494	Sysprop          struct {
495		Platform *bool
496	}
497	Target struct {
498		Android struct {
499			Header_libs []string
500			Shared_libs []string
501		}
502		Host struct {
503			Static_libs []string
504		}
505	}
506	Required                 []string
507	Recovery                 *bool
508	Recovery_available       *bool
509	Vendor_available         *bool
510	Product_available        *bool
511	Ramdisk_available        *bool
512	Vendor_ramdisk_available *bool
513	Host_supported           *bool
514	Apex_available           []string
515	Min_sdk_version          *string
516	Cflags                   []string
517	Ldflags                  []string
518}
519
520type javaLibraryProperties struct {
521	Name              *string
522	Srcs              []string
523	Soc_specific      *bool
524	Device_specific   *bool
525	Product_specific  *bool
526	Required          []string
527	Sdk_version       *string
528	Installable       *bool
529	Libs              []string
530	Stem              *string
531	SyspropPublicStub string
532	Apex_available    []string
533	Min_sdk_version   *string
534}
535
536type rustLibraryProperties struct {
537	Name              *string
538	Sysprop_srcs      []string `android:"path"`
539	Scope             string
540	Check_api         *string
541	Srcs              []string
542	Installable       *bool
543	Crate_name        string
544	Rustlibs          []string
545	Vendor_available  *bool
546	Product_available *bool
547	Apex_available    []string
548	Min_sdk_version   *string
549}
550
551func syspropLibraryHook(ctx android.LoadHookContext, m *syspropLibrary) {
552	if len(m.properties.Srcs) == 0 {
553		ctx.PropertyErrorf("srcs", "sysprop_library must specify srcs")
554	}
555
556	// ctx's Platform or Specific functions represent where this sysprop_library installed.
557	installedInSystem := ctx.Platform() || ctx.SystemExtSpecific()
558	installedInVendorOrOdm := ctx.SocSpecific() || ctx.DeviceSpecific()
559	installedInProduct := ctx.ProductSpecific()
560	isOwnerPlatform := false
561	var javaSyspropStub string
562
563	// javaSyspropStub contains stub libraries used by generated APIs, instead of framework stub.
564	// This is to make sysprop_library link against core_current.
565	if installedInVendorOrOdm {
566		javaSyspropStub = "sysprop-library-stub-vendor"
567	} else if installedInProduct {
568		javaSyspropStub = "sysprop-library-stub-product"
569	} else {
570		javaSyspropStub = "sysprop-library-stub-platform"
571	}
572
573	switch m.Owner() {
574	case "Platform":
575		// Every partition can access platform-defined properties
576		isOwnerPlatform = true
577	case "Vendor":
578		// System can't access vendor's properties
579		if installedInSystem {
580			ctx.ModuleErrorf("None of soc_specific, device_specific, product_specific is true. " +
581				"System can't access sysprop_library owned by Vendor")
582		}
583	case "Odm":
584		// Only vendor can access Odm-defined properties
585		if !installedInVendorOrOdm {
586			ctx.ModuleErrorf("Neither soc_speicifc nor device_specific is true. " +
587				"Odm-defined properties should be accessed only in Vendor or Odm")
588		}
589	default:
590		ctx.PropertyErrorf("property_owner",
591			"Unknown value %s: must be one of Platform, Vendor or Odm", m.Owner())
592	}
593
594	// Generate a C++ implementation library.
595	// cc_library can receive *.sysprop files as their srcs, generating sources itself.
596	ccProps := ccLibraryProperties{}
597	ccProps.Name = proptools.StringPtr(m.CcImplementationModuleName())
598	ccProps.Srcs = m.properties.Srcs
599	ccProps.Soc_specific = proptools.BoolPtr(ctx.SocSpecific())
600	ccProps.Device_specific = proptools.BoolPtr(ctx.DeviceSpecific())
601	ccProps.Product_specific = proptools.BoolPtr(ctx.ProductSpecific())
602	ccProps.Sysprop.Platform = proptools.BoolPtr(isOwnerPlatform)
603	ccProps.Target.Android.Header_libs = []string{"libbase_headers"}
604	ccProps.Target.Android.Shared_libs = []string{"liblog"}
605	ccProps.Target.Host.Static_libs = []string{"libbase", "liblog"}
606	ccProps.Recovery_available = m.properties.Recovery_available
607	ccProps.Vendor_available = m.properties.Vendor_available
608	ccProps.Product_available = m.properties.Product_available
609	ccProps.Ramdisk_available = m.properties.Ramdisk_available
610	ccProps.Vendor_ramdisk_available = m.properties.Vendor_ramdisk_available
611	ccProps.Host_supported = m.properties.Host_supported
612	ccProps.Apex_available = m.ApexProperties.Apex_available
613	ccProps.Min_sdk_version = m.properties.Cpp.Min_sdk_version
614	ccProps.Cflags = m.properties.Cpp.Cflags
615	ccProps.Ldflags = m.properties.Cpp.Ldflags
616	ctx.CreateModule(cc.LibraryFactory, &ccProps)
617
618	scope := "internal"
619
620	// We need to only use public version, if the partition where sysprop_library will be installed
621	// is different from owner.
622	if ctx.ProductSpecific() {
623		// Currently product partition can't own any sysprop_library. So product always uses public.
624		scope = "public"
625	} else if isOwnerPlatform && installedInVendorOrOdm {
626		// Vendor or Odm should use public version of Platform's sysprop_library.
627		scope = "public"
628	}
629
630	// Generate a Java implementation library.
631	// Contrast to C++, syspropJavaGenRule module will generate srcjar and the srcjar will be fed
632	// to Java implementation library.
633	ctx.CreateModule(syspropJavaGenFactory, &syspropGenProperties{
634		Srcs:      m.properties.Srcs,
635		Scope:     scope,
636		Name:      proptools.StringPtr(m.javaGenModuleName()),
637		Check_api: proptools.StringPtr(ctx.ModuleName()),
638	})
639
640	// if platform sysprop_library is installed in /system or /system-ext, we regard it as an API
641	// and allow any modules (even from different partition) to link against the sysprop_library.
642	// To do that, we create a public stub and expose it to modules with sdk_version: system_*.
643	var publicStub string
644	if isOwnerPlatform && installedInSystem {
645		publicStub = m.javaPublicStubName()
646	}
647
648	ctx.CreateModule(java.LibraryFactory, &javaLibraryProperties{
649		Name:              proptools.StringPtr(m.BaseModuleName()),
650		Srcs:              []string{":" + m.javaGenModuleName()},
651		Soc_specific:      proptools.BoolPtr(ctx.SocSpecific()),
652		Device_specific:   proptools.BoolPtr(ctx.DeviceSpecific()),
653		Product_specific:  proptools.BoolPtr(ctx.ProductSpecific()),
654		Installable:       m.properties.Installable,
655		Sdk_version:       proptools.StringPtr("core_current"),
656		Libs:              []string{javaSyspropStub},
657		SyspropPublicStub: publicStub,
658		Apex_available:    m.ApexProperties.Apex_available,
659		Min_sdk_version:   m.properties.Java.Min_sdk_version,
660	})
661
662	if publicStub != "" {
663		ctx.CreateModule(syspropJavaGenFactory, &syspropGenProperties{
664			Srcs:      m.properties.Srcs,
665			Scope:     "public",
666			Name:      proptools.StringPtr(m.javaGenPublicStubName()),
667			Check_api: proptools.StringPtr(ctx.ModuleName()),
668		})
669
670		ctx.CreateModule(java.LibraryFactory, &javaLibraryProperties{
671			Name:        proptools.StringPtr(publicStub),
672			Srcs:        []string{":" + m.javaGenPublicStubName()},
673			Installable: proptools.BoolPtr(false),
674			Sdk_version: proptools.StringPtr("core_current"),
675			Libs:        []string{javaSyspropStub},
676			Stem:        proptools.StringPtr(m.BaseModuleName()),
677		})
678	}
679
680	// Generate a Rust implementation library.
681	rustProps := rustLibraryProperties{
682		Name:         proptools.StringPtr(m.rustGenStubName()),
683		Sysprop_srcs: m.properties.Srcs,
684		Scope:        scope,
685		Check_api:    proptools.StringPtr(ctx.ModuleName()),
686		Installable:  m.properties.Installable,
687		Crate_name:   m.rustCrateName(),
688		Rustlibs: []string{
689			"liblog_rust",
690			"librustutils",
691		},
692		Vendor_available:  m.properties.Vendor_available,
693		Product_available: m.properties.Product_available,
694		Apex_available:    m.ApexProperties.Apex_available,
695		Min_sdk_version:   proptools.StringPtr("29"),
696	}
697	ctx.CreateModule(syspropRustGenFactory, &rustProps)
698
699	// syspropLibraries will be used by property_contexts to check types.
700	// Record absolute paths of sysprop_library to prevent soong_namespace problem.
701	if m.ExportedToMake() {
702		syspropLibrariesLock.Lock()
703		defer syspropLibrariesLock.Unlock()
704
705		libraries := syspropLibraries(ctx.Config())
706		*libraries = append(*libraries, "//"+ctx.ModuleDir()+":"+ctx.ModuleName())
707	}
708}
709