1// Copyright 2020 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.
14package cc
15
16// This file contains image variant related things, including image mutator functions, utility
17// functions to determine where a module is installed, etc.
18
19import (
20	"strings"
21
22	"android/soong/android"
23
24	"github.com/google/blueprint/proptools"
25)
26
27var _ android.ImageInterface = (*Module)(nil)
28
29type ImageVariantType string
30
31const (
32	coreImageVariant          ImageVariantType = "core"
33	vendorImageVariant        ImageVariantType = "vendor"
34	productImageVariant       ImageVariantType = "product"
35	ramdiskImageVariant       ImageVariantType = "ramdisk"
36	vendorRamdiskImageVariant ImageVariantType = "vendor_ramdisk"
37	recoveryImageVariant      ImageVariantType = "recovery"
38	hostImageVariant          ImageVariantType = "host"
39)
40
41const (
42	// VendorVariation is the variant name used for /vendor code that does not
43	// compile against the VNDK.
44	VendorVariation = "vendor"
45
46	// VendorVariationPrefix is the variant prefix used for /vendor code that compiles
47	// against the VNDK.
48	VendorVariationPrefix = "vendor."
49
50	// ProductVariation is the variant name used for /product code that does not
51	// compile against the VNDK.
52	ProductVariation = "product"
53
54	// ProductVariationPrefix is the variant prefix used for /product code that compiles
55	// against the VNDK.
56	ProductVariationPrefix = "product."
57)
58
59func (ctx *moduleContextImpl) inProduct() bool {
60	return ctx.mod.InProduct()
61}
62
63func (ctx *moduleContextImpl) inVendor() bool {
64	return ctx.mod.InVendor()
65}
66
67func (ctx *moduleContextImpl) inRamdisk() bool {
68	return ctx.mod.InRamdisk()
69}
70
71func (ctx *moduleContextImpl) inVendorRamdisk() bool {
72	return ctx.mod.InVendorRamdisk()
73}
74
75func (ctx *moduleContextImpl) inRecovery() bool {
76	return ctx.mod.InRecovery()
77}
78
79func (c *Module) InstallInProduct() bool {
80	// Additionally check if this module is inProduct() that means it is a "product" variant of a
81	// module. As well as product specific modules, product variants must be installed to /product.
82	return c.InProduct()
83}
84
85func (c *Module) InstallInVendor() bool {
86	// Additionally check if this module is inVendor() that means it is a "vendor" variant of a
87	// module. As well as SoC specific modules, vendor variants must be installed to /vendor
88	// unless they have "odm_available: true".
89	return c.HasVendorVariant() && c.InVendor() && !c.VendorVariantToOdm()
90}
91
92func (c *Module) InstallInOdm() bool {
93	// Some vendor variants want to be installed to /odm by setting "odm_available: true".
94	return c.InVendor() && c.VendorVariantToOdm()
95}
96
97// Returns true when this module is configured to have core and vendor variants.
98func (c *Module) HasVendorVariant() bool {
99	return Bool(c.VendorProperties.Vendor_available) || Bool(c.VendorProperties.Odm_available)
100}
101
102// Returns true when this module creates a vendor variant and wants to install the vendor variant
103// to the odm partition.
104func (c *Module) VendorVariantToOdm() bool {
105	return Bool(c.VendorProperties.Odm_available)
106}
107
108// Returns true when this module is configured to have core and product variants.
109func (c *Module) HasProductVariant() bool {
110	return Bool(c.VendorProperties.Product_available)
111}
112
113// Returns true when this module is configured to have core and either product or vendor variants.
114func (c *Module) HasNonSystemVariants() bool {
115	return c.HasVendorVariant() || c.HasProductVariant()
116}
117
118// Returns true if the module is "product" variant. Usually these modules are installed in /product
119func (c *Module) InProduct() bool {
120	return c.Properties.ImageVariation == ProductVariation
121}
122
123// Returns true if the module is "vendor" variant. Usually these modules are installed in /vendor
124func (c *Module) InVendor() bool {
125	return c.Properties.ImageVariation == VendorVariation
126}
127
128// Returns true if the module is "vendor" or "product" variant. This replaces previous UseVndk usages
129// which were misused to check if the module variant is vendor or product.
130func (c *Module) InVendorOrProduct() bool {
131	return c.InVendor() || c.InProduct()
132}
133
134func (c *Module) InRamdisk() bool {
135	return c.ModuleBase.InRamdisk() || c.ModuleBase.InstallInRamdisk()
136}
137
138func (c *Module) InVendorRamdisk() bool {
139	return c.ModuleBase.InVendorRamdisk() || c.ModuleBase.InstallInVendorRamdisk()
140}
141
142func (c *Module) InRecovery() bool {
143	return c.ModuleBase.InRecovery() || c.ModuleBase.InstallInRecovery()
144}
145
146func (c *Module) OnlyInRamdisk() bool {
147	return c.ModuleBase.InstallInRamdisk()
148}
149
150func (c *Module) OnlyInVendorRamdisk() bool {
151	return c.ModuleBase.InstallInVendorRamdisk()
152}
153
154func (c *Module) OnlyInRecovery() bool {
155	return c.ModuleBase.InstallInRecovery()
156}
157
158// ImageMutatableModule provides a common image mutation interface for  LinkableInterface modules.
159type ImageMutatableModule interface {
160	android.Module
161	LinkableInterface
162
163	// AndroidModuleBase returns the android.ModuleBase for this module
164	AndroidModuleBase() *android.ModuleBase
165
166	// VendorAvailable returns true if this module is available on the vendor image.
167	VendorAvailable() bool
168
169	// OdmAvailable returns true if this module is available on the odm image.
170	OdmAvailable() bool
171
172	// ProductAvailable returns true if this module is available on the product image.
173	ProductAvailable() bool
174
175	// RamdiskAvailable returns true if this module is available on the ramdisk image.
176	RamdiskAvailable() bool
177
178	// RecoveryAvailable returns true if this module is available on the recovery image.
179	RecoveryAvailable() bool
180
181	// VendorRamdiskAvailable returns true if this module is available on the vendor ramdisk image.
182	VendorRamdiskAvailable() bool
183
184	// IsSnapshotPrebuilt returns true if this module is a snapshot prebuilt.
185	IsSnapshotPrebuilt() bool
186
187	// SnapshotVersion returns the snapshot version for this module.
188	SnapshotVersion(mctx android.BaseModuleContext) string
189
190	// SdkVersion returns the SDK version for this module.
191	SdkVersion() string
192
193	// ExtraVariants returns the list of extra variants this module requires.
194	ExtraVariants() []string
195
196	// AppendExtraVariant returns an extra variant to the list of extra variants this module requires.
197	AppendExtraVariant(extraVariant string)
198
199	// SetRamdiskVariantNeeded sets whether the Ramdisk Variant is needed.
200	SetRamdiskVariantNeeded(b bool)
201
202	// SetVendorRamdiskVariantNeeded sets whether the Vendor Ramdisk Variant is needed.
203	SetVendorRamdiskVariantNeeded(b bool)
204
205	// SetRecoveryVariantNeeded sets whether the Recovery Variant is needed.
206	SetRecoveryVariantNeeded(b bool)
207
208	// SetCoreVariantNeeded sets whether the Core Variant is needed.
209	SetCoreVariantNeeded(b bool)
210}
211
212var _ ImageMutatableModule = (*Module)(nil)
213
214func (m *Module) ImageMutatorBegin(mctx android.BaseModuleContext) {
215	MutateImage(mctx, m)
216}
217
218func (m *Module) VendorAvailable() bool {
219	return Bool(m.VendorProperties.Vendor_available)
220}
221
222func (m *Module) OdmAvailable() bool {
223	return Bool(m.VendorProperties.Odm_available)
224}
225
226func (m *Module) ProductAvailable() bool {
227	return Bool(m.VendorProperties.Product_available)
228}
229
230func (m *Module) RamdiskAvailable() bool {
231	return Bool(m.Properties.Ramdisk_available)
232}
233
234func (m *Module) VendorRamdiskAvailable() bool {
235	return Bool(m.Properties.Vendor_ramdisk_available)
236}
237
238func (m *Module) AndroidModuleBase() *android.ModuleBase {
239	return &m.ModuleBase
240}
241
242func (m *Module) RecoveryAvailable() bool {
243	return Bool(m.Properties.Recovery_available)
244}
245
246func (m *Module) ExtraVariants() []string {
247	return m.Properties.ExtraVersionedImageVariations
248}
249
250func (m *Module) AppendExtraVariant(extraVariant string) {
251	m.Properties.ExtraVersionedImageVariations = append(m.Properties.ExtraVersionedImageVariations, extraVariant)
252}
253
254func (m *Module) SetRamdiskVariantNeeded(b bool) {
255	m.Properties.RamdiskVariantNeeded = b
256}
257
258func (m *Module) SetVendorRamdiskVariantNeeded(b bool) {
259	m.Properties.VendorRamdiskVariantNeeded = b
260}
261
262func (m *Module) SetRecoveryVariantNeeded(b bool) {
263	m.Properties.RecoveryVariantNeeded = b
264}
265
266func (m *Module) SetCoreVariantNeeded(b bool) {
267	m.Properties.CoreVariantNeeded = b
268}
269
270func (m *Module) SnapshotVersion(mctx android.BaseModuleContext) string {
271	if snapshot, ok := m.linker.(SnapshotInterface); ok {
272		return snapshot.Version()
273	} else {
274		mctx.ModuleErrorf("version is unknown for snapshot prebuilt")
275		// Should we be panicking here instead?
276		return ""
277	}
278}
279
280func (m *Module) KernelHeadersDecorator() bool {
281	if _, ok := m.linker.(*kernelHeadersDecorator); ok {
282		return true
283	}
284	return false
285}
286
287// MutateImage handles common image mutations for ImageMutatableModule interfaces.
288func MutateImage(mctx android.BaseModuleContext, m ImageMutatableModule) {
289	// Validation check
290	vendorSpecific := mctx.SocSpecific() || mctx.DeviceSpecific()
291	productSpecific := mctx.ProductSpecific()
292
293	if m.VendorAvailable() {
294		if vendorSpecific {
295			mctx.PropertyErrorf("vendor_available",
296				"doesn't make sense at the same time as `vendor: true`, `proprietary: true`, or `device_specific: true`")
297		}
298		if m.OdmAvailable() {
299			mctx.PropertyErrorf("vendor_available",
300				"doesn't make sense at the same time as `odm_available: true`")
301		}
302	}
303
304	if m.OdmAvailable() {
305		if vendorSpecific {
306			mctx.PropertyErrorf("odm_available",
307				"doesn't make sense at the same time as `vendor: true`, `proprietary: true`, or `device_specific: true`")
308		}
309	}
310
311	if m.ProductAvailable() {
312		if productSpecific {
313			mctx.PropertyErrorf("product_available",
314				"doesn't make sense at the same time as `product_specific: true`")
315		}
316		if vendorSpecific {
317			mctx.PropertyErrorf("product_available",
318				"cannot provide product variant from a vendor module. Please use `product_specific: true` with `vendor_available: true`")
319		}
320	}
321
322	var coreVariantNeeded bool = false
323	var ramdiskVariantNeeded bool = false
324	var vendorRamdiskVariantNeeded bool = false
325	var recoveryVariantNeeded bool = false
326
327	var vendorVariants []string
328	var productVariants []string
329
330	needVndkVersionVendorVariantForLlndk := false
331
332	if m.NeedsLlndkVariants() {
333		// This is an LLNDK library.  The implementation of the library will be on /system,
334		// and vendor and product variants will be created with LLNDK stubs.
335		// The LLNDK libraries need vendor variants even if there is no VNDK.
336		coreVariantNeeded = true
337		vendorVariants = append(vendorVariants, "")
338		productVariants = append(productVariants, "")
339		// Generate vendor variants for boardVndkVersion only if the VNDK snapshot does not
340		// provide the LLNDK stub libraries.
341		if needVndkVersionVendorVariantForLlndk {
342			vendorVariants = append(vendorVariants, "")
343		}
344	} else if m.NeedsVendorPublicLibraryVariants() {
345		// A vendor public library has the implementation on /vendor, with stub variants
346		// for system and product.
347		coreVariantNeeded = true
348		vendorVariants = append(vendorVariants, "")
349		productVariants = append(productVariants, "")
350	} else if m.IsSnapshotPrebuilt() {
351		// Make vendor variants only for the versions in BOARD_VNDK_VERSION and
352		// PRODUCT_EXTRA_VNDK_VERSIONS.
353		if m.InstallInRecovery() {
354			recoveryVariantNeeded = true
355		} else {
356			vendorVariants = append(vendorVariants, m.SnapshotVersion(mctx))
357		}
358	} else if m.HasNonSystemVariants() {
359		// This will be available to /system unless it is product_specific
360		// which will be handled later.
361		coreVariantNeeded = true
362
363		// We assume that modules under proprietary paths are compatible for
364		// BOARD_VNDK_VERSION. The other modules are regarded as AOSP, or
365		// PLATFORM_VNDK_VERSION.
366		if m.HasVendorVariant() {
367			vendorVariants = append(vendorVariants, "")
368		}
369
370		// product_available modules are available to /product.
371		if m.HasProductVariant() {
372			productVariants = append(productVariants, "")
373		}
374	} else if vendorSpecific && m.SdkVersion() == "" {
375		// This will be available in /vendor (or /odm) only
376		vendorVariants = append(vendorVariants, "")
377	} else {
378		// This is either in /system (or similar: /data), or is a
379		// module built with the NDK. Modules built with the NDK
380		// will be restricted using the existing link type checks.
381		coreVariantNeeded = true
382	}
383
384	if coreVariantNeeded && productSpecific && m.SdkVersion() == "" {
385		// The module has "product_specific: true" that does not create core variant.
386		coreVariantNeeded = false
387		productVariants = append(productVariants, "")
388	}
389
390	if m.RamdiskAvailable() {
391		ramdiskVariantNeeded = true
392	}
393
394	if m.AndroidModuleBase().InstallInRamdisk() {
395		ramdiskVariantNeeded = true
396		coreVariantNeeded = false
397	}
398
399	if m.VendorRamdiskAvailable() {
400		vendorRamdiskVariantNeeded = true
401	}
402
403	if m.AndroidModuleBase().InstallInVendorRamdisk() {
404		vendorRamdiskVariantNeeded = true
405		coreVariantNeeded = false
406	}
407
408	if m.RecoveryAvailable() {
409		recoveryVariantNeeded = true
410	}
411
412	if m.AndroidModuleBase().InstallInRecovery() {
413		recoveryVariantNeeded = true
414		coreVariantNeeded = false
415	}
416
417	for _, variant := range android.FirstUniqueStrings(vendorVariants) {
418		if variant == "" {
419			m.AppendExtraVariant(VendorVariation)
420		} else {
421			m.AppendExtraVariant(VendorVariationPrefix + variant)
422		}
423	}
424
425	for _, variant := range android.FirstUniqueStrings(productVariants) {
426		if variant == "" {
427			m.AppendExtraVariant(ProductVariation)
428		} else {
429			m.AppendExtraVariant(ProductVariationPrefix + variant)
430		}
431	}
432
433	m.SetRamdiskVariantNeeded(ramdiskVariantNeeded)
434	m.SetVendorRamdiskVariantNeeded(vendorRamdiskVariantNeeded)
435	m.SetRecoveryVariantNeeded(recoveryVariantNeeded)
436	m.SetCoreVariantNeeded(coreVariantNeeded)
437
438	// Disable the module if no variants are needed.
439	if !ramdiskVariantNeeded &&
440		!recoveryVariantNeeded &&
441		!coreVariantNeeded &&
442		len(m.ExtraVariants()) == 0 {
443		m.Disable()
444	}
445}
446
447func (c *Module) CoreVariantNeeded(ctx android.BaseModuleContext) bool {
448	return c.Properties.CoreVariantNeeded
449}
450
451func (c *Module) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
452	return c.Properties.RamdiskVariantNeeded
453}
454
455func (c *Module) VendorRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
456	return c.Properties.VendorRamdiskVariantNeeded
457}
458
459func (c *Module) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
460	return false
461}
462
463func (c *Module) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool {
464	return c.Properties.RecoveryVariantNeeded
465}
466
467func (c *Module) ExtraImageVariations(ctx android.BaseModuleContext) []string {
468	return c.Properties.ExtraVersionedImageVariations
469}
470
471func squashVendorSrcs(m *Module) {
472	if lib, ok := m.compiler.(*libraryDecorator); ok {
473		lib.baseCompiler.Properties.Srcs = append(lib.baseCompiler.Properties.Srcs,
474			lib.baseCompiler.Properties.Target.Vendor.Srcs...)
475
476		lib.baseCompiler.Properties.Exclude_srcs = append(lib.baseCompiler.Properties.Exclude_srcs,
477			lib.baseCompiler.Properties.Target.Vendor.Exclude_srcs...)
478
479		lib.baseCompiler.Properties.Exclude_generated_sources = append(lib.baseCompiler.Properties.Exclude_generated_sources,
480			lib.baseCompiler.Properties.Target.Vendor.Exclude_generated_sources...)
481
482		if lib.Properties.Target.Vendor.No_stubs {
483			proptools.Clear(&lib.Properties.Stubs)
484		}
485	}
486}
487
488func squashProductSrcs(m *Module) {
489	if lib, ok := m.compiler.(*libraryDecorator); ok {
490		lib.baseCompiler.Properties.Srcs = append(lib.baseCompiler.Properties.Srcs,
491			lib.baseCompiler.Properties.Target.Product.Srcs...)
492
493		lib.baseCompiler.Properties.Exclude_srcs = append(lib.baseCompiler.Properties.Exclude_srcs,
494			lib.baseCompiler.Properties.Target.Product.Exclude_srcs...)
495
496		lib.baseCompiler.Properties.Exclude_generated_sources = append(lib.baseCompiler.Properties.Exclude_generated_sources,
497			lib.baseCompiler.Properties.Target.Product.Exclude_generated_sources...)
498
499		if lib.Properties.Target.Product.No_stubs {
500			proptools.Clear(&lib.Properties.Stubs)
501		}
502	}
503}
504
505func squashRecoverySrcs(m *Module) {
506	if lib, ok := m.compiler.(*libraryDecorator); ok {
507		lib.baseCompiler.Properties.Srcs = append(lib.baseCompiler.Properties.Srcs,
508			lib.baseCompiler.Properties.Target.Recovery.Srcs...)
509
510		lib.baseCompiler.Properties.Exclude_srcs = append(lib.baseCompiler.Properties.Exclude_srcs,
511			lib.baseCompiler.Properties.Target.Recovery.Exclude_srcs...)
512
513		lib.baseCompiler.Properties.Exclude_generated_sources = append(lib.baseCompiler.Properties.Exclude_generated_sources,
514			lib.baseCompiler.Properties.Target.Recovery.Exclude_generated_sources...)
515	}
516}
517
518func squashVendorRamdiskSrcs(m *Module) {
519	if lib, ok := m.compiler.(*libraryDecorator); ok {
520		lib.baseCompiler.Properties.Exclude_srcs = append(lib.baseCompiler.Properties.Exclude_srcs, lib.baseCompiler.Properties.Target.Vendor_ramdisk.Exclude_srcs...)
521	}
522}
523
524func squashRamdiskSrcs(m *Module) {
525	if lib, ok := m.compiler.(*libraryDecorator); ok {
526		lib.baseCompiler.Properties.Exclude_srcs = append(lib.baseCompiler.Properties.Exclude_srcs, lib.baseCompiler.Properties.Target.Ramdisk.Exclude_srcs...)
527	}
528}
529
530func (c *Module) SetImageVariation(ctx android.BaseModuleContext, variant string) {
531	if variant == android.RamdiskVariation {
532		c.MakeAsPlatform()
533		squashRamdiskSrcs(c)
534	} else if variant == android.VendorRamdiskVariation {
535		c.MakeAsPlatform()
536		squashVendorRamdiskSrcs(c)
537	} else if variant == android.RecoveryVariation {
538		c.MakeAsPlatform()
539		squashRecoverySrcs(c)
540	} else if strings.HasPrefix(variant, VendorVariation) {
541		c.Properties.ImageVariation = VendorVariation
542
543		if strings.HasPrefix(variant, VendorVariationPrefix) {
544			c.Properties.VndkVersion = strings.TrimPrefix(variant, VendorVariationPrefix)
545		}
546		squashVendorSrcs(c)
547	} else if strings.HasPrefix(variant, ProductVariation) {
548		c.Properties.ImageVariation = ProductVariation
549		if strings.HasPrefix(variant, ProductVariationPrefix) {
550			c.Properties.VndkVersion = strings.TrimPrefix(variant, ProductVariationPrefix)
551		}
552		squashProductSrcs(c)
553	}
554
555	if c.NeedsVendorPublicLibraryVariants() &&
556		(variant == android.CoreVariation || strings.HasPrefix(variant, ProductVariationPrefix)) {
557		c.VendorProperties.IsVendorPublicLibrary = true
558	}
559}
560