• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2016 Google Inc. All rights reserved.
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
15package etc
16
17// This file implements module types that install prebuilt artifacts.
18//
19// There exist two classes of prebuilt modules in the Android tree. The first class are the ones
20// based on `android.Prebuilt`, such as `cc_prebuilt_library` and `java_import`. This kind of
21// modules may exist both as prebuilts and source at the same time, though only one would be
22// installed and the other would be marked disabled. The `prebuilt_postdeps` mutator would select
23// the actual modules to be installed. More details in android/prebuilt.go.
24//
25// The second class is described in this file. Unlike `android.Prebuilt` based module types,
26// `prebuilt_etc` exist only as prebuilts and cannot have a same-named source module counterpart.
27// This makes the logic of `prebuilt_etc` to be much simpler as they don't need to go through the
28// various `prebuilt_*` mutators.
29
30import (
31	"encoding/json"
32	"fmt"
33	"path/filepath"
34	"reflect"
35	"strings"
36
37	"github.com/google/blueprint/proptools"
38
39	"android/soong/android"
40	"android/soong/bazel"
41	"android/soong/snapshot"
42)
43
44var pctx = android.NewPackageContext("android/soong/etc")
45
46// TODO(jungw): Now that it handles more than the ones in etc/, consider renaming this file.
47
48func init() {
49	pctx.Import("android/soong/android")
50	RegisterPrebuiltEtcBuildComponents(android.InitRegistrationContext)
51	snapshot.RegisterSnapshotAction(generatePrebuiltSnapshot)
52}
53
54func RegisterPrebuiltEtcBuildComponents(ctx android.RegistrationContext) {
55	ctx.RegisterModuleType("prebuilt_etc", PrebuiltEtcFactory)
56	ctx.RegisterModuleType("prebuilt_etc_host", PrebuiltEtcHostFactory)
57	ctx.RegisterModuleType("prebuilt_etc_cacerts", PrebuiltEtcCaCertsFactory)
58	ctx.RegisterModuleType("prebuilt_root", PrebuiltRootFactory)
59	ctx.RegisterModuleType("prebuilt_root_host", PrebuiltRootHostFactory)
60	ctx.RegisterModuleType("prebuilt_usr_share", PrebuiltUserShareFactory)
61	ctx.RegisterModuleType("prebuilt_usr_share_host", PrebuiltUserShareHostFactory)
62	ctx.RegisterModuleType("prebuilt_font", PrebuiltFontFactory)
63	ctx.RegisterModuleType("prebuilt_firmware", PrebuiltFirmwareFactory)
64	ctx.RegisterModuleType("prebuilt_dsp", PrebuiltDSPFactory)
65	ctx.RegisterModuleType("prebuilt_rfsa", PrebuiltRFSAFactory)
66
67	ctx.RegisterModuleType("prebuilt_defaults", defaultsFactory)
68
69}
70
71var PrepareForTestWithPrebuiltEtc = android.FixtureRegisterWithContext(RegisterPrebuiltEtcBuildComponents)
72
73type prebuiltEtcProperties struct {
74	// Source file of this prebuilt. Can reference a genrule type module with the ":module" syntax.
75	Src *string `android:"path,arch_variant"`
76
77	// Optional name for the installed file. If unspecified, name of the module is used as the file
78	// name.
79	Filename *string `android:"arch_variant"`
80
81	// When set to true, and filename property is not set, the name for the installed file
82	// is the same as the file name of the source file.
83	Filename_from_src *bool `android:"arch_variant"`
84
85	// Make this module available when building for ramdisk.
86	// On device without a dedicated recovery partition, the module is only
87	// available after switching root into
88	// /first_stage_ramdisk. To expose the module before switching root, install
89	// the recovery variant instead.
90	Ramdisk_available *bool
91
92	// Make this module available when building for vendor ramdisk.
93	// On device without a dedicated recovery partition, the module is only
94	// available after switching root into
95	// /first_stage_ramdisk. To expose the module before switching root, install
96	// the recovery variant instead.
97	Vendor_ramdisk_available *bool
98
99	// Make this module available when building for debug ramdisk.
100	Debug_ramdisk_available *bool
101
102	// Make this module available when building for recovery.
103	Recovery_available *bool
104
105	// Whether this module is directly installable to one of the partitions. Default: true.
106	Installable *bool
107
108	// Install symlinks to the installed file.
109	Symlinks []string `android:"arch_variant"`
110}
111
112type prebuiltSubdirProperties struct {
113	// Optional subdirectory under which this file is installed into, cannot be specified with
114	// relative_install_path, prefer relative_install_path.
115	Sub_dir *string `android:"arch_variant"`
116
117	// Optional subdirectory under which this file is installed into, cannot be specified with
118	// sub_dir.
119	Relative_install_path *string `android:"arch_variant"`
120}
121
122type PrebuiltEtcModule interface {
123	android.Module
124
125	// Returns the base install directory, such as "etc", "usr/share".
126	BaseDir() string
127
128	// Returns the sub install directory relative to BaseDir().
129	SubDir() string
130
131	// Returns an android.OutputPath to the intermeidate file, which is the renamed prebuilt source
132	// file.
133	OutputFile() android.OutputPath
134}
135
136type PrebuiltEtc struct {
137	android.ModuleBase
138	android.DefaultableModuleBase
139	android.BazelModuleBase
140
141	snapshot.VendorSnapshotModuleInterface
142	snapshot.RecoverySnapshotModuleInterface
143
144	properties       prebuiltEtcProperties
145	subdirProperties prebuiltSubdirProperties
146
147	sourceFilePath android.Path
148	outputFilePath android.OutputPath
149	// The base install location, e.g. "etc" for prebuilt_etc, "usr/share" for prebuilt_usr_share.
150	installDirBase string
151	// The base install location when soc_specific property is set to true, e.g. "firmware" for
152	// prebuilt_firmware.
153	socInstallDirBase      string
154	installDirPath         android.InstallPath
155	additionalDependencies *android.Paths
156}
157
158type Defaults struct {
159	android.ModuleBase
160	android.DefaultsModuleBase
161}
162
163func (p *PrebuiltEtc) inRamdisk() bool {
164	return p.ModuleBase.InRamdisk() || p.ModuleBase.InstallInRamdisk()
165}
166
167func (p *PrebuiltEtc) onlyInRamdisk() bool {
168	return p.ModuleBase.InstallInRamdisk()
169}
170
171func (p *PrebuiltEtc) InstallInRamdisk() bool {
172	return p.inRamdisk()
173}
174
175func (p *PrebuiltEtc) inVendorRamdisk() bool {
176	return p.ModuleBase.InVendorRamdisk() || p.ModuleBase.InstallInVendorRamdisk()
177}
178
179func (p *PrebuiltEtc) onlyInVendorRamdisk() bool {
180	return p.ModuleBase.InstallInVendorRamdisk()
181}
182
183func (p *PrebuiltEtc) InstallInVendorRamdisk() bool {
184	return p.inVendorRamdisk()
185}
186
187func (p *PrebuiltEtc) inDebugRamdisk() bool {
188	return p.ModuleBase.InDebugRamdisk() || p.ModuleBase.InstallInDebugRamdisk()
189}
190
191func (p *PrebuiltEtc) onlyInDebugRamdisk() bool {
192	return p.ModuleBase.InstallInDebugRamdisk()
193}
194
195func (p *PrebuiltEtc) InstallInDebugRamdisk() bool {
196	return p.inDebugRamdisk()
197}
198
199func (p *PrebuiltEtc) InRecovery() bool {
200	return p.ModuleBase.InRecovery() || p.ModuleBase.InstallInRecovery()
201}
202
203func (p *PrebuiltEtc) onlyInRecovery() bool {
204	return p.ModuleBase.InstallInRecovery()
205}
206
207func (p *PrebuiltEtc) InstallInRecovery() bool {
208	return p.InRecovery()
209}
210
211var _ android.ImageInterface = (*PrebuiltEtc)(nil)
212
213func (p *PrebuiltEtc) ImageMutatorBegin(ctx android.BaseModuleContext) {}
214
215func (p *PrebuiltEtc) CoreVariantNeeded(ctx android.BaseModuleContext) bool {
216	return !p.ModuleBase.InstallInRecovery() && !p.ModuleBase.InstallInRamdisk() &&
217		!p.ModuleBase.InstallInVendorRamdisk() && !p.ModuleBase.InstallInDebugRamdisk()
218}
219
220func (p *PrebuiltEtc) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
221	return proptools.Bool(p.properties.Ramdisk_available) || p.ModuleBase.InstallInRamdisk()
222}
223
224func (p *PrebuiltEtc) VendorRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
225	return proptools.Bool(p.properties.Vendor_ramdisk_available) || p.ModuleBase.InstallInVendorRamdisk()
226}
227
228func (p *PrebuiltEtc) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
229	return proptools.Bool(p.properties.Debug_ramdisk_available) || p.ModuleBase.InstallInDebugRamdisk()
230}
231
232func (p *PrebuiltEtc) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool {
233	return proptools.Bool(p.properties.Recovery_available) || p.ModuleBase.InstallInRecovery()
234}
235
236func (p *PrebuiltEtc) ExtraImageVariations(ctx android.BaseModuleContext) []string {
237	return nil
238}
239
240func (p *PrebuiltEtc) SetImageVariation(ctx android.BaseModuleContext, variation string, module android.Module) {
241}
242
243func (p *PrebuiltEtc) SourceFilePath(ctx android.ModuleContext) android.Path {
244	return android.PathForModuleSrc(ctx, proptools.String(p.properties.Src))
245}
246
247func (p *PrebuiltEtc) InstallDirPath() android.InstallPath {
248	return p.installDirPath
249}
250
251// This allows other derivative modules (e.g. prebuilt_etc_xml) to perform
252// additional steps (like validating the src) before the file is installed.
253func (p *PrebuiltEtc) SetAdditionalDependencies(paths android.Paths) {
254	p.additionalDependencies = &paths
255}
256
257func (p *PrebuiltEtc) OutputFile() android.OutputPath {
258	return p.outputFilePath
259}
260
261var _ android.OutputFileProducer = (*PrebuiltEtc)(nil)
262
263func (p *PrebuiltEtc) OutputFiles(tag string) (android.Paths, error) {
264	switch tag {
265	case "":
266		return android.Paths{p.outputFilePath}, nil
267	default:
268		return nil, fmt.Errorf("unsupported module reference tag %q", tag)
269	}
270}
271
272func (p *PrebuiltEtc) SubDir() string {
273	if subDir := proptools.String(p.subdirProperties.Sub_dir); subDir != "" {
274		return subDir
275	}
276	return proptools.String(p.subdirProperties.Relative_install_path)
277}
278
279func (p *PrebuiltEtc) BaseDir() string {
280	return p.installDirBase
281}
282
283func (p *PrebuiltEtc) Installable() bool {
284	return p.properties.Installable == nil || proptools.Bool(p.properties.Installable)
285}
286
287func (p *PrebuiltEtc) InVendor() bool {
288	return p.ModuleBase.InstallInVendor()
289}
290
291func (p *PrebuiltEtc) ExcludeFromVendorSnapshot() bool {
292	return false
293}
294
295func (p *PrebuiltEtc) ExcludeFromRecoverySnapshot() bool {
296	return false
297}
298
299func (p *PrebuiltEtc) GenerateAndroidBuildActions(ctx android.ModuleContext) {
300	filename := proptools.String(p.properties.Filename)
301	filenameFromSrc := proptools.Bool(p.properties.Filename_from_src)
302	if p.properties.Src != nil {
303		p.sourceFilePath = android.PathForModuleSrc(ctx, proptools.String(p.properties.Src))
304
305		// Determine the output file basename.
306		// If Filename is set, use the name specified by the property.
307		// If Filename_from_src is set, use the source file name.
308		// Otherwise use the module name.
309		if filename != "" {
310			if filenameFromSrc {
311				ctx.PropertyErrorf("filename_from_src", "filename is set. filename_from_src can't be true")
312				return
313			}
314		} else if filenameFromSrc {
315			filename = p.sourceFilePath.Base()
316		} else {
317			filename = ctx.ModuleName()
318		}
319	} else if ctx.Config().AllowMissingDependencies() {
320		// If no srcs was set and AllowMissingDependencies is enabled then
321		// mark the module as missing dependencies and set a fake source path
322		// and file name.
323		ctx.AddMissingDependencies([]string{"MISSING_PREBUILT_SRC_FILE"})
324		p.sourceFilePath = android.PathForModuleSrc(ctx)
325		if filename == "" {
326			filename = ctx.ModuleName()
327		}
328	} else {
329		ctx.PropertyErrorf("src", "missing prebuilt source file")
330		return
331	}
332	p.outputFilePath = android.PathForModuleOut(ctx, filename).OutputPath
333
334	if strings.Contains(filename, "/") {
335		ctx.PropertyErrorf("filename", "filename cannot contain separator '/'")
336		return
337	}
338
339	// Check that `sub_dir` and `relative_install_path` are not set at the same time.
340	if p.subdirProperties.Sub_dir != nil && p.subdirProperties.Relative_install_path != nil {
341		ctx.PropertyErrorf("sub_dir", "relative_install_path is set. Cannot set sub_dir")
342	}
343
344	// If soc install dir was specified and SOC specific is set, set the installDirPath to the
345	// specified socInstallDirBase.
346	installBaseDir := p.installDirBase
347	if p.SocSpecific() && p.socInstallDirBase != "" {
348		installBaseDir = p.socInstallDirBase
349	}
350	p.installDirPath = android.PathForModuleInstall(ctx, installBaseDir, p.SubDir())
351
352	// This ensures that outputFilePath has the correct name for others to
353	// use, as the source file may have a different name.
354	ctx.Build(pctx, android.BuildParams{
355		Rule:   android.Cp,
356		Output: p.outputFilePath,
357		Input:  p.sourceFilePath,
358	})
359
360	if !p.Installable() {
361		p.SkipInstall()
362	}
363
364	// Call InstallFile even when uninstallable to make the module included in the package
365	installPath := ctx.InstallFile(p.installDirPath, p.outputFilePath.Base(), p.outputFilePath)
366	for _, sl := range p.properties.Symlinks {
367		ctx.InstallSymlink(p.installDirPath, sl, installPath)
368	}
369}
370
371func (p *PrebuiltEtc) AndroidMkEntries() []android.AndroidMkEntries {
372	nameSuffix := ""
373	if p.inRamdisk() && !p.onlyInRamdisk() {
374		nameSuffix = ".ramdisk"
375	}
376	if p.inVendorRamdisk() && !p.onlyInVendorRamdisk() {
377		nameSuffix = ".vendor_ramdisk"
378	}
379	if p.inDebugRamdisk() && !p.onlyInDebugRamdisk() {
380		nameSuffix = ".debug_ramdisk"
381	}
382	if p.InRecovery() && !p.onlyInRecovery() {
383		nameSuffix = ".recovery"
384	}
385	return []android.AndroidMkEntries{android.AndroidMkEntries{
386		Class:      "ETC",
387		SubName:    nameSuffix,
388		OutputFile: android.OptionalPathForPath(p.outputFilePath),
389		ExtraEntries: []android.AndroidMkExtraEntriesFunc{
390			func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
391				entries.SetString("LOCAL_MODULE_TAGS", "optional")
392				entries.SetString("LOCAL_MODULE_PATH", p.installDirPath.String())
393				entries.SetString("LOCAL_INSTALLED_MODULE_STEM", p.outputFilePath.Base())
394				if len(p.properties.Symlinks) > 0 {
395					entries.AddStrings("LOCAL_MODULE_SYMLINKS", p.properties.Symlinks...)
396				}
397				entries.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", !p.Installable())
398				if p.additionalDependencies != nil {
399					entries.AddStrings("LOCAL_ADDITIONAL_DEPENDENCIES", p.additionalDependencies.Strings()...)
400				}
401			},
402		},
403	}}
404}
405
406func InitPrebuiltEtcModule(p *PrebuiltEtc, dirBase string) {
407	p.installDirBase = dirBase
408	p.AddProperties(&p.properties)
409	p.AddProperties(&p.subdirProperties)
410}
411
412func InitPrebuiltRootModule(p *PrebuiltEtc) {
413	p.installDirBase = "."
414	p.AddProperties(&p.properties)
415}
416
417// prebuilt_etc is for a prebuilt artifact that is installed in
418// <partition>/etc/<sub_dir> directory.
419func PrebuiltEtcFactory() android.Module {
420	module := &PrebuiltEtc{}
421	InitPrebuiltEtcModule(module, "etc")
422	// This module is device-only
423	android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
424	android.InitDefaultableModule(module)
425	android.InitBazelModule(module)
426	return module
427}
428
429func defaultsFactory() android.Module {
430	return DefaultsFactory()
431}
432
433func DefaultsFactory(props ...interface{}) android.Module {
434	module := &Defaults{}
435
436	module.AddProperties(props...)
437	module.AddProperties(
438		&prebuiltEtcProperties{},
439		&prebuiltSubdirProperties{},
440	)
441
442	android.InitDefaultsModule(module)
443
444	return module
445}
446
447// prebuilt_etc_host is for a host prebuilt artifact that is installed in
448// $(HOST_OUT)/etc/<sub_dir> directory.
449func PrebuiltEtcHostFactory() android.Module {
450	module := &PrebuiltEtc{}
451	InitPrebuiltEtcModule(module, "etc")
452	// This module is host-only
453	android.InitAndroidArchModule(module, android.HostSupported, android.MultilibCommon)
454	android.InitDefaultableModule(module)
455	android.InitBazelModule(module)
456	return module
457}
458
459// prebuilt_etc_host is for a host prebuilt artifact that is installed in
460// <partition>/etc/<sub_dir> directory.
461func PrebuiltEtcCaCertsFactory() android.Module {
462	module := &PrebuiltEtc{}
463	InitPrebuiltEtcModule(module, "cacerts")
464	// This module is device-only
465	android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
466	android.InitBazelModule(module)
467	return module
468}
469
470// prebuilt_root is for a prebuilt artifact that is installed in
471// <partition>/ directory. Can't have any sub directories.
472func PrebuiltRootFactory() android.Module {
473	module := &PrebuiltEtc{}
474	InitPrebuiltRootModule(module)
475	// This module is device-only
476	android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
477	android.InitDefaultableModule(module)
478	return module
479}
480
481// prebuilt_root_host is for a host prebuilt artifact that is installed in $(HOST_OUT)/<sub_dir>
482// directory.
483func PrebuiltRootHostFactory() android.Module {
484	module := &PrebuiltEtc{}
485	InitPrebuiltEtcModule(module, ".")
486	// This module is host-only
487	android.InitAndroidArchModule(module, android.HostSupported, android.MultilibCommon)
488	android.InitDefaultableModule(module)
489	return module
490}
491
492// prebuilt_usr_share is for a prebuilt artifact that is installed in
493// <partition>/usr/share/<sub_dir> directory.
494func PrebuiltUserShareFactory() android.Module {
495	module := &PrebuiltEtc{}
496	InitPrebuiltEtcModule(module, "usr/share")
497	// This module is device-only
498	android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
499	android.InitDefaultableModule(module)
500	android.InitBazelModule(module)
501	return module
502}
503
504// prebuild_usr_share_host is for a host prebuilt artifact that is installed in
505// $(HOST_OUT)/usr/share/<sub_dir> directory.
506func PrebuiltUserShareHostFactory() android.Module {
507	module := &PrebuiltEtc{}
508	InitPrebuiltEtcModule(module, "usr/share")
509	// This module is host-only
510	android.InitAndroidArchModule(module, android.HostSupported, android.MultilibCommon)
511	android.InitDefaultableModule(module)
512	return module
513}
514
515// prebuilt_font installs a font in <partition>/fonts directory.
516func PrebuiltFontFactory() android.Module {
517	module := &PrebuiltEtc{}
518	InitPrebuiltEtcModule(module, "fonts")
519	// This module is device-only
520	android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
521	android.InitDefaultableModule(module)
522	return module
523}
524
525// prebuilt_firmware installs a firmware file to <partition>/etc/firmware directory for system
526// image.
527// If soc_specific property is set to true, the firmware file is installed to the
528// vendor <partition>/firmware directory for vendor image.
529func PrebuiltFirmwareFactory() android.Module {
530	module := &PrebuiltEtc{}
531	module.socInstallDirBase = "firmware"
532	InitPrebuiltEtcModule(module, "etc/firmware")
533	// This module is device-only
534	android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
535	android.InitDefaultableModule(module)
536	return module
537}
538
539// prebuilt_dsp installs a DSP related file to <partition>/etc/dsp directory for system image.
540// If soc_specific property is set to true, the DSP related file is installed to the
541// vendor <partition>/dsp directory for vendor image.
542func PrebuiltDSPFactory() android.Module {
543	module := &PrebuiltEtc{}
544	module.socInstallDirBase = "dsp"
545	InitPrebuiltEtcModule(module, "etc/dsp")
546	// This module is device-only
547	android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
548	android.InitDefaultableModule(module)
549	return module
550}
551
552// prebuilt_rfsa installs a firmware file that will be available through Qualcomm's RFSA
553// to the <partition>/lib/rfsa directory.
554func PrebuiltRFSAFactory() android.Module {
555	module := &PrebuiltEtc{}
556	// Ideally these would go in /vendor/dsp, but the /vendor/lib/rfsa paths are hardcoded in too
557	// many places outside of the application processor.  They could be moved to /vendor/dsp once
558	// that is cleaned up.
559	InitPrebuiltEtcModule(module, "lib/rfsa")
560	// This module is device-only
561	android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
562	android.InitDefaultableModule(module)
563	return module
564}
565
566// Copy file into the snapshot
567func copyFile(ctx android.SingletonContext, path android.Path, out string, fake bool) android.OutputPath {
568	if fake {
569		// Create empty file instead for the fake snapshot
570		return snapshot.WriteStringToFileRule(ctx, "", out)
571	} else {
572		return snapshot.CopyFileRule(pctx, ctx, path, out)
573	}
574}
575
576// Check if the module is target of the snapshot
577func isSnapshotAware(ctx android.SingletonContext, m *PrebuiltEtc, image snapshot.SnapshotImage) bool {
578	if !m.Enabled() {
579		return false
580	}
581
582	// Skip if the module is not included in the image
583	if !image.InImage(m)() {
584		return false
585	}
586
587	// When android/prebuilt.go selects between source and prebuilt, it sets
588	// HideFromMake on the other one to avoid duplicate install rules in make.
589	if m.IsHideFromMake() {
590		return false
591	}
592
593	// There are some prebuilt_etc module with multiple definition of same name.
594	// Check if the target would be included from the build
595	if !m.ExportedToMake() {
596		return false
597	}
598
599	// Skip if the module is in the predefined path list to skip
600	if image.IsProprietaryPath(ctx.ModuleDir(m), ctx.DeviceConfig()) {
601		return false
602	}
603
604	// Skip if the module should be excluded
605	if image.ExcludeFromSnapshot(m) || image.ExcludeFromDirectedSnapshot(ctx.DeviceConfig(), m.BaseModuleName()) {
606		return false
607	}
608
609	// Skip from other exceptional cases
610	if m.Target().Os.Class != android.Device {
611		return false
612	}
613	if m.Target().NativeBridge == android.NativeBridgeEnabled {
614		return false
615	}
616
617	return true
618}
619
620func generatePrebuiltSnapshot(s snapshot.SnapshotSingleton, ctx android.SingletonContext, snapshotArchDir string) snapshot.SnapshotPaths {
621	/*
622		Snapshot zipped artifacts directory structure for etc modules:
623		{SNAPSHOT_ARCH}/
624			arch-{TARGET_ARCH}-{TARGET_ARCH_VARIANT}/
625				etc/
626					(prebuilt etc files)
627			arch-{TARGET_2ND_ARCH}-{TARGET_2ND_ARCH_VARIANT}/
628				etc/
629					(prebuilt etc files)
630			NOTICE_FILES/
631				(notice files)
632	*/
633	var snapshotOutputs android.Paths
634	var snapshotNotices android.Paths
635	installedNotices := make(map[string]bool)
636
637	ctx.VisitAllModules(func(module android.Module) {
638		m, ok := module.(*PrebuiltEtc)
639		if !ok {
640			return
641		}
642
643		if !isSnapshotAware(ctx, m, s.Image) {
644			return
645		}
646
647		targetArch := "arch-" + m.Target().Arch.ArchType.String()
648
649		snapshotLibOut := filepath.Join(snapshotArchDir, targetArch, "etc", m.BaseModuleName())
650		snapshotOutputs = append(snapshotOutputs, copyFile(ctx, m.OutputFile(), snapshotLibOut, s.Fake))
651
652		prop := snapshot.SnapshotJsonFlags{}
653		propOut := snapshotLibOut + ".json"
654		prop.InitBaseSnapshotProps(m)
655		prop.RelativeInstallPath = m.SubDir()
656
657		if m.properties.Filename != nil {
658			prop.Filename = *m.properties.Filename
659		}
660
661		j, err := json.Marshal(prop)
662		if err != nil {
663			ctx.Errorf("json marshal to %q failed: %#v", propOut, err)
664			return
665		}
666		snapshotOutputs = append(snapshotOutputs, snapshot.WriteStringToFileRule(ctx, string(j), propOut))
667
668		for _, notice := range m.EffectiveLicenseFiles() {
669			if _, ok := installedNotices[notice.String()]; !ok {
670				installedNotices[notice.String()] = true
671				snapshotNotices = append(snapshotNotices, notice)
672			}
673		}
674
675	})
676
677	return snapshot.SnapshotPaths{OutputFiles: snapshotOutputs, NoticeFiles: snapshotNotices}
678}
679
680// For Bazel / bp2build
681
682type bazelPrebuiltFileAttributes struct {
683	Src               bazel.LabelAttribute
684	Filename          bazel.LabelAttribute
685	Dir               string
686	Installable       bazel.BoolAttribute
687	Filename_from_src bazel.BoolAttribute
688}
689
690// Bp2buildHelper returns a bazelPrebuiltFileAttributes used for the conversion
691// of prebuilt_*  modules. bazelPrebuiltFileAttributes has the common attributes
692// used by both prebuilt_etc_xml and other prebuilt_* moodules
693func (module *PrebuiltEtc) Bp2buildHelper(ctx android.TopDownMutatorContext) *bazelPrebuiltFileAttributes {
694	var src bazel.LabelAttribute
695	for axis, configToProps := range module.GetArchVariantProperties(ctx, &prebuiltEtcProperties{}) {
696		for config, p := range configToProps {
697			props, ok := p.(*prebuiltEtcProperties)
698			if !ok {
699				continue
700			}
701			if props.Src != nil {
702				label := android.BazelLabelForModuleSrcSingle(ctx, *props.Src)
703				src.SetSelectValue(axis, config, label)
704			}
705		}
706
707		for propName, productConfigProps := range android.ProductVariableProperties(ctx, ctx.Module()) {
708			for configProp, propVal := range productConfigProps {
709				if propName == "Src" {
710					props, ok := propVal.(*string)
711					if !ok {
712						ctx.PropertyErrorf(" Expected Property to have type string, but was %s\n", reflect.TypeOf(propVal).String())
713						continue
714					}
715					if props != nil {
716						label := android.BazelLabelForModuleSrcSingle(ctx, *props)
717						src.SetSelectValue(configProp.ConfigurationAxis(), configProp.SelectKey(), label)
718					}
719				}
720			}
721		}
722	}
723
724	var filename string
725	var filenameFromSrc bool
726	moduleProps := module.properties
727
728	if moduleProps.Filename != nil && *moduleProps.Filename != "" {
729		filename = *moduleProps.Filename
730	} else if moduleProps.Filename_from_src != nil && *moduleProps.Filename_from_src {
731		if moduleProps.Src != nil {
732			filename = *moduleProps.Src
733		}
734		filenameFromSrc = true
735	} else {
736		filename = ctx.ModuleName()
737	}
738
739	var dir = module.installDirBase
740	if subDir := module.subdirProperties.Sub_dir; subDir != nil {
741		dir = dir + "/" + *subDir
742	}
743
744	var installable bazel.BoolAttribute
745	if install := module.properties.Installable; install != nil {
746		installable.Value = install
747	}
748
749	attrs := &bazelPrebuiltFileAttributes{
750		Src:         src,
751		Dir:         dir,
752		Installable: installable,
753	}
754
755	if filename != "" {
756		attrs.Filename = bazel.LabelAttribute{Value: &bazel.Label{Label: filename}}
757	} else if filenameFromSrc {
758		attrs.Filename_from_src = bazel.BoolAttribute{Value: moduleProps.Filename_from_src}
759	}
760
761	return attrs
762
763}
764
765// ConvertWithBp2build performs bp2build conversion of PrebuiltEtc
766// prebuilt_* modules (except prebuilt_etc_xml) are PrebuiltEtc,
767// which we treat as *PrebuiltFile*
768func (module *PrebuiltEtc) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
769	var dir = module.installDirBase
770	// prebuilt_file supports only `etc` or `usr/share`
771	if !(dir == "etc" || dir == "usr/share") {
772		return
773	}
774
775	attrs := module.Bp2buildHelper(ctx)
776
777	props := bazel.BazelTargetModuleProperties{
778		Rule_class:        "prebuilt_file",
779		Bzl_load_location: "//build/bazel/rules:prebuilt_file.bzl",
780	}
781
782	ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: module.Name()}, attrs)
783}
784