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	"fmt"
21	"reflect"
22	"strings"
23
24	"android/soong/android"
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	// VendorVariationPrefix is the variant prefix used for /vendor code that compiles
43	// against the VNDK.
44	VendorVariationPrefix = "vendor."
45
46	// ProductVariationPrefix is the variant prefix used for /product code that compiles
47	// against the VNDK.
48	ProductVariationPrefix = "product."
49)
50
51func (ctx *moduleContext) ProductSpecific() bool {
52	return ctx.ModuleContext.ProductSpecific() || ctx.mod.productSpecificModuleContext()
53}
54
55func (ctx *moduleContext) SocSpecific() bool {
56	return ctx.ModuleContext.SocSpecific() || ctx.mod.socSpecificModuleContext()
57}
58
59func (ctx *moduleContext) DeviceSpecific() bool {
60	return ctx.ModuleContext.DeviceSpecific() || ctx.mod.deviceSpecificModuleContext()
61}
62
63func (ctx *moduleContextImpl) inProduct() bool {
64	return ctx.mod.InProduct()
65}
66
67func (ctx *moduleContextImpl) inVendor() bool {
68	return ctx.mod.InVendor()
69}
70
71func (ctx *moduleContextImpl) inRamdisk() bool {
72	return ctx.mod.InRamdisk()
73}
74
75func (ctx *moduleContextImpl) inVendorRamdisk() bool {
76	return ctx.mod.InVendorRamdisk()
77}
78
79func (ctx *moduleContextImpl) inRecovery() bool {
80	return ctx.mod.InRecovery()
81}
82
83func (c *Module) productSpecificModuleContext() bool {
84	// Additionally check if this module is inProduct() that means it is a "product" variant of a
85	// module. As well as product specific modules, product variants must be installed to /product.
86	return c.InProduct()
87}
88
89func (c *Module) socSpecificModuleContext() bool {
90	// Additionally check if this module is inVendor() that means it is a "vendor" variant of a
91	// module. As well as SoC specific modules, vendor variants must be installed to /vendor
92	// unless they have "odm_available: true".
93	return c.HasVendorVariant() && c.InVendor() && !c.VendorVariantToOdm()
94}
95
96func (c *Module) deviceSpecificModuleContext() bool {
97	// Some vendor variants want to be installed to /odm by setting "odm_available: true".
98	return c.InVendor() && c.VendorVariantToOdm()
99}
100
101// Returns true when this module is configured to have core and vendor variants.
102func (c *Module) HasVendorVariant() bool {
103	return Bool(c.VendorProperties.Vendor_available) || Bool(c.VendorProperties.Odm_available)
104}
105
106// Returns true when this module creates a vendor variant and wants to install the vendor variant
107// to the odm partition.
108func (c *Module) VendorVariantToOdm() bool {
109	return Bool(c.VendorProperties.Odm_available)
110}
111
112// Returns true when this module is configured to have core and product variants.
113func (c *Module) HasProductVariant() bool {
114	return Bool(c.VendorProperties.Product_available)
115}
116
117// Returns true when this module is configured to have core and either product or vendor variants.
118func (c *Module) HasNonSystemVariants() bool {
119	return c.HasVendorVariant() || c.HasProductVariant()
120}
121
122// Returns true if the module is "product" variant. Usually these modules are installed in /product
123func (c *Module) InProduct() bool {
124	return c.Properties.ImageVariationPrefix == ProductVariationPrefix
125}
126
127// Returns true if the module is "vendor" variant. Usually these modules are installed in /vendor
128func (c *Module) InVendor() bool {
129	return c.Properties.ImageVariationPrefix == VendorVariationPrefix
130}
131
132func (c *Module) InRamdisk() bool {
133	return c.ModuleBase.InRamdisk() || c.ModuleBase.InstallInRamdisk()
134}
135
136func (c *Module) InVendorRamdisk() bool {
137	return c.ModuleBase.InVendorRamdisk() || c.ModuleBase.InstallInVendorRamdisk()
138}
139
140func (c *Module) InRecovery() bool {
141	return c.ModuleBase.InRecovery() || c.ModuleBase.InstallInRecovery()
142}
143
144func (c *Module) OnlyInRamdisk() bool {
145	return c.ModuleBase.InstallInRamdisk()
146}
147
148func (c *Module) OnlyInVendorRamdisk() bool {
149	return c.ModuleBase.InstallInVendorRamdisk()
150}
151
152func (c *Module) OnlyInRecovery() bool {
153	return c.ModuleBase.InstallInRecovery()
154}
155
156func visitPropsAndCompareVendorAndProductProps(v reflect.Value) bool {
157	if v.Kind() != reflect.Struct {
158		return true
159	}
160	for i := 0; i < v.NumField(); i++ {
161		prop := v.Field(i)
162		if prop.Kind() == reflect.Struct && v.Type().Field(i).Name == "Target" {
163			vendor_prop := prop.FieldByName("Vendor")
164			product_prop := prop.FieldByName("Product")
165			if vendor_prop.Kind() != reflect.Struct && product_prop.Kind() != reflect.Struct {
166				// Neither Target.Vendor nor Target.Product is defined
167				continue
168			}
169			if vendor_prop.Kind() != reflect.Struct || product_prop.Kind() != reflect.Struct ||
170				!reflect.DeepEqual(vendor_prop.Interface(), product_prop.Interface()) {
171				// If only one of either Target.Vendor or Target.Product is
172				// defined or they have different values, it fails the build
173				// since VNDK must have the same properties for both vendor
174				// and product variants.
175				return false
176			}
177		} else if !visitPropsAndCompareVendorAndProductProps(prop) {
178			// Visit the substructures to find Target.Vendor and Target.Product
179			return false
180		}
181	}
182	return true
183}
184
185// In the case of VNDK, vendor and product variants must have the same properties.
186// VNDK installs only one file and shares it for both vendor and product modules on
187// runtime. We may not define different versions of a VNDK lib for each partition.
188// This function is used only for the VNDK modules that is available to both vendor
189// and product partitions.
190func (c *Module) compareVendorAndProductProps() bool {
191	if !c.IsVndk() && !Bool(c.VendorProperties.Product_available) {
192		panic(fmt.Errorf("This is only for product available VNDK libs. %q is not a VNDK library or not product available", c.Name()))
193	}
194	for _, properties := range c.GetProperties() {
195		if !visitPropsAndCompareVendorAndProductProps(reflect.ValueOf(properties).Elem()) {
196			return false
197		}
198	}
199	return true
200}
201
202// ImageMutatableModule provides a common image mutation interface for  LinkableInterface modules.
203type ImageMutatableModule interface {
204	android.Module
205	LinkableInterface
206
207	// AndroidModuleBase returns the android.ModuleBase for this module
208	AndroidModuleBase() *android.ModuleBase
209
210	// VendorAvailable returns true if this module is available on the vendor image.
211	VendorAvailable() bool
212
213	// OdmAvailable returns true if this module is available on the odm image.
214	OdmAvailable() bool
215
216	// ProductAvailable returns true if this module is available on the product image.
217	ProductAvailable() bool
218
219	// RamdiskAvailable returns true if this module is available on the ramdisk image.
220	RamdiskAvailable() bool
221
222	// RecoveryAvailable returns true if this module is available on the recovery image.
223	RecoveryAvailable() bool
224
225	// VendorRamdiskAvailable returns true if this module is available on the vendor ramdisk image.
226	VendorRamdiskAvailable() bool
227
228	// IsSnapshotPrebuilt returns true if this module is a snapshot prebuilt.
229	IsSnapshotPrebuilt() bool
230
231	// SnapshotVersion returns the snapshot version for this module.
232	SnapshotVersion(mctx android.BaseModuleContext) string
233
234	// SdkVersion returns the SDK version for this module.
235	SdkVersion() string
236
237	// ExtraVariants returns the list of extra variants this module requires.
238	ExtraVariants() []string
239
240	// AppendExtraVariant returns an extra variant to the list of extra variants this module requires.
241	AppendExtraVariant(extraVariant string)
242
243	// SetRamdiskVariantNeeded sets whether the Ramdisk Variant is needed.
244	SetRamdiskVariantNeeded(b bool)
245
246	// SetVendorRamdiskVariantNeeded sets whether the Vendor Ramdisk Variant is needed.
247	SetVendorRamdiskVariantNeeded(b bool)
248
249	// SetRecoveryVariantNeeded sets whether the Recovery Variant is needed.
250	SetRecoveryVariantNeeded(b bool)
251
252	// SetCoreVariantNeeded sets whether the Core Variant is needed.
253	SetCoreVariantNeeded(b bool)
254}
255
256var _ ImageMutatableModule = (*Module)(nil)
257
258func (m *Module) ImageMutatorBegin(mctx android.BaseModuleContext) {
259	m.CheckVndkProperties(mctx)
260	MutateImage(mctx, m)
261}
262
263// CheckVndkProperties checks whether the VNDK-related properties are set correctly.
264// If properties are not set correctly, results in a module context property error.
265func (m *Module) CheckVndkProperties(mctx android.BaseModuleContext) {
266	vendorSpecific := mctx.SocSpecific() || mctx.DeviceSpecific()
267	productSpecific := mctx.ProductSpecific()
268
269	if vndkdep := m.vndkdep; vndkdep != nil {
270		if vndkdep.isVndk() {
271			if vendorSpecific || productSpecific {
272				if !vndkdep.isVndkExt() {
273					mctx.PropertyErrorf("vndk",
274						"must set `extends: \"...\"` to vndk extension")
275				} else if Bool(m.VendorProperties.Vendor_available) {
276					mctx.PropertyErrorf("vendor_available",
277						"must not set at the same time as `vndk: {extends: \"...\"}`")
278				} else if Bool(m.VendorProperties.Product_available) {
279					mctx.PropertyErrorf("product_available",
280						"must not set at the same time as `vndk: {extends: \"...\"}`")
281				}
282			} else {
283				if vndkdep.isVndkExt() {
284					mctx.PropertyErrorf("vndk",
285						"must set `vendor: true` or `product_specific: true` to set `extends: %q`",
286						m.getVndkExtendsModuleName())
287				}
288				if !Bool(m.VendorProperties.Vendor_available) {
289					mctx.PropertyErrorf("vndk",
290						"vendor_available must be set to true when `vndk: {enabled: true}`")
291				}
292				if Bool(m.VendorProperties.Product_available) {
293					// If a VNDK module creates both product and vendor variants, they
294					// must have the same properties since they share a single VNDK
295					// library on runtime.
296					if !m.compareVendorAndProductProps() {
297						mctx.ModuleErrorf("product properties must have the same values with the vendor properties for VNDK modules")
298					}
299				}
300			}
301		} else {
302			if vndkdep.isVndkSp() {
303				mctx.PropertyErrorf("vndk",
304					"must set `enabled: true` to set `support_system_process: true`")
305			}
306			if vndkdep.isVndkExt() {
307				mctx.PropertyErrorf("vndk",
308					"must set `enabled: true` to set `extends: %q`",
309					m.getVndkExtendsModuleName())
310			}
311		}
312	}
313}
314
315func (m *Module) VendorAvailable() bool {
316	return Bool(m.VendorProperties.Vendor_available)
317}
318
319func (m *Module) OdmAvailable() bool {
320	return Bool(m.VendorProperties.Odm_available)
321}
322
323func (m *Module) ProductAvailable() bool {
324	return Bool(m.VendorProperties.Product_available)
325}
326
327func (m *Module) RamdiskAvailable() bool {
328	return Bool(m.Properties.Ramdisk_available)
329}
330
331func (m *Module) VendorRamdiskAvailable() bool {
332	return Bool(m.Properties.Vendor_ramdisk_available)
333}
334
335func (m *Module) AndroidModuleBase() *android.ModuleBase {
336	return &m.ModuleBase
337}
338
339func (m *Module) RecoveryAvailable() bool {
340	return Bool(m.Properties.Recovery_available)
341}
342
343func (m *Module) ExtraVariants() []string {
344	return m.Properties.ExtraVariants
345}
346
347func (m *Module) AppendExtraVariant(extraVariant string) {
348	m.Properties.ExtraVariants = append(m.Properties.ExtraVariants, extraVariant)
349}
350
351func (m *Module) SetRamdiskVariantNeeded(b bool) {
352	m.Properties.RamdiskVariantNeeded = b
353}
354
355func (m *Module) SetVendorRamdiskVariantNeeded(b bool) {
356	m.Properties.VendorRamdiskVariantNeeded = b
357}
358
359func (m *Module) SetRecoveryVariantNeeded(b bool) {
360	m.Properties.RecoveryVariantNeeded = b
361}
362
363func (m *Module) SetCoreVariantNeeded(b bool) {
364	m.Properties.CoreVariantNeeded = b
365}
366
367func (m *Module) SnapshotVersion(mctx android.BaseModuleContext) string {
368	if snapshot, ok := m.linker.(snapshotInterface); ok {
369		return snapshot.version()
370	} else {
371		mctx.ModuleErrorf("version is unknown for snapshot prebuilt")
372		// Should we be panicking here instead?
373		return ""
374	}
375}
376
377func (m *Module) KernelHeadersDecorator() bool {
378	if _, ok := m.linker.(*kernelHeadersDecorator); ok {
379		return true
380	}
381	return false
382}
383
384// MutateImage handles common image mutations for ImageMutatableModule interfaces.
385func MutateImage(mctx android.BaseModuleContext, m ImageMutatableModule) {
386	// Validation check
387	vendorSpecific := mctx.SocSpecific() || mctx.DeviceSpecific()
388	productSpecific := mctx.ProductSpecific()
389
390	if m.VendorAvailable() {
391		if vendorSpecific {
392			mctx.PropertyErrorf("vendor_available",
393				"doesn't make sense at the same time as `vendor: true`, `proprietary: true`, or `device_specific: true`")
394		}
395		if m.OdmAvailable() {
396			mctx.PropertyErrorf("vendor_available",
397				"doesn't make sense at the same time as `odm_available: true`")
398		}
399	}
400
401	if m.OdmAvailable() {
402		if vendorSpecific {
403			mctx.PropertyErrorf("odm_available",
404				"doesn't make sense at the same time as `vendor: true`, `proprietary: true`, or `device_specific: true`")
405		}
406	}
407
408	if m.ProductAvailable() {
409		if productSpecific {
410			mctx.PropertyErrorf("product_available",
411				"doesn't make sense at the same time as `product_specific: true`")
412		}
413		if vendorSpecific {
414			mctx.PropertyErrorf("product_available",
415				"cannot provide product variant from a vendor module. Please use `product_specific: true` with `vendor_available: true`")
416		}
417	}
418
419	var coreVariantNeeded bool = false
420	var ramdiskVariantNeeded bool = false
421	var vendorRamdiskVariantNeeded bool = false
422	var recoveryVariantNeeded bool = false
423
424	var vendorVariants []string
425	var productVariants []string
426
427	platformVndkVersion := mctx.DeviceConfig().PlatformVndkVersion()
428	boardVndkVersion := mctx.DeviceConfig().VndkVersion()
429	productVndkVersion := mctx.DeviceConfig().ProductVndkVersion()
430	recoverySnapshotVersion := mctx.DeviceConfig().RecoverySnapshotVersion()
431	usingRecoverySnapshot := recoverySnapshotVersion != "current" &&
432		recoverySnapshotVersion != ""
433	needVndkVersionVendorVariantForLlndk := false
434	if boardVndkVersion != "" {
435		boardVndkApiLevel, err := android.ApiLevelFromUser(mctx, boardVndkVersion)
436		if err == nil && !boardVndkApiLevel.IsPreview() {
437			// VNDK snapshot newer than v30 has LLNDK stub libraries.
438			// Only the VNDK version less than or equal to v30 requires generating the vendor
439			// variant of the VNDK version from the source tree.
440			needVndkVersionVendorVariantForLlndk = boardVndkApiLevel.LessThanOrEqualTo(android.ApiLevelOrPanic(mctx, "30"))
441		}
442	}
443	if boardVndkVersion == "current" {
444		boardVndkVersion = platformVndkVersion
445	}
446	if productVndkVersion == "current" {
447		productVndkVersion = platformVndkVersion
448	}
449
450	if m.NeedsLlndkVariants() {
451		// This is an LLNDK library.  The implementation of the library will be on /system,
452		// and vendor and product variants will be created with LLNDK stubs.
453		// The LLNDK libraries need vendor variants even if there is no VNDK.
454		coreVariantNeeded = true
455		if platformVndkVersion != "" {
456			vendorVariants = append(vendorVariants, platformVndkVersion)
457			productVariants = append(productVariants, platformVndkVersion)
458		}
459		// Generate vendor variants for boardVndkVersion only if the VNDK snapshot does not
460		// provide the LLNDK stub libraries.
461		if needVndkVersionVendorVariantForLlndk {
462			vendorVariants = append(vendorVariants, boardVndkVersion)
463		}
464		if productVndkVersion != "" {
465			productVariants = append(productVariants, productVndkVersion)
466		}
467	} else if m.NeedsVendorPublicLibraryVariants() {
468		// A vendor public library has the implementation on /vendor, with stub variants
469		// for system and product.
470		coreVariantNeeded = true
471		vendorVariants = append(vendorVariants, boardVndkVersion)
472		if platformVndkVersion != "" {
473			productVariants = append(productVariants, platformVndkVersion)
474		}
475		if productVndkVersion != "" {
476			productVariants = append(productVariants, productVndkVersion)
477		}
478	} else if boardVndkVersion == "" {
479		// If the device isn't compiling against the VNDK, we always
480		// use the core mode.
481		coreVariantNeeded = true
482	} else if m.IsSnapshotPrebuilt() {
483		// Make vendor variants only for the versions in BOARD_VNDK_VERSION and
484		// PRODUCT_EXTRA_VNDK_VERSIONS.
485		if m.InstallInRecovery() {
486			recoveryVariantNeeded = true
487		} else {
488			vendorVariants = append(vendorVariants, m.SnapshotVersion(mctx))
489		}
490	} else if m.HasNonSystemVariants() && !m.IsVndkExt() {
491		// This will be available to /system unless it is product_specific
492		// which will be handled later.
493		coreVariantNeeded = true
494
495		// We assume that modules under proprietary paths are compatible for
496		// BOARD_VNDK_VERSION. The other modules are regarded as AOSP, or
497		// PLATFORM_VNDK_VERSION.
498		if m.HasVendorVariant() {
499			if isVendorProprietaryModule(mctx) {
500				vendorVariants = append(vendorVariants, boardVndkVersion)
501			} else {
502				vendorVariants = append(vendorVariants, platformVndkVersion)
503			}
504		}
505
506		// product_available modules are available to /product.
507		if m.HasProductVariant() {
508			productVariants = append(productVariants, platformVndkVersion)
509			// VNDK is always PLATFORM_VNDK_VERSION
510			if !m.IsVndk() {
511				productVariants = append(productVariants, productVndkVersion)
512			}
513		}
514	} else if vendorSpecific && m.SdkVersion() == "" {
515		// This will be available in /vendor (or /odm) only
516
517		// kernel_headers is a special module type whose exported headers
518		// are coming from DeviceKernelHeaders() which is always vendor
519		// dependent. They'll always have both vendor variants.
520		// For other modules, we assume that modules under proprietary
521		// paths are compatible for BOARD_VNDK_VERSION. The other modules
522		// are regarded as AOSP, which is PLATFORM_VNDK_VERSION.
523		if m.KernelHeadersDecorator() {
524			vendorVariants = append(vendorVariants,
525				platformVndkVersion,
526				boardVndkVersion,
527			)
528		} else if isVendorProprietaryModule(mctx) {
529			vendorVariants = append(vendorVariants, boardVndkVersion)
530		} else {
531			vendorVariants = append(vendorVariants, platformVndkVersion)
532		}
533	} else {
534		// This is either in /system (or similar: /data), or is a
535		// modules built with the NDK. Modules built with the NDK
536		// will be restricted using the existing link type checks.
537		coreVariantNeeded = true
538	}
539
540	if boardVndkVersion != "" && productVndkVersion != "" {
541		if coreVariantNeeded && productSpecific && m.SdkVersion() == "" {
542			// The module has "product_specific: true" that does not create core variant.
543			coreVariantNeeded = false
544			productVariants = append(productVariants, productVndkVersion)
545		}
546	} else {
547		// Unless PRODUCT_PRODUCT_VNDK_VERSION is set, product partition has no
548		// restriction to use system libs.
549		// No product variants defined in this case.
550		productVariants = []string{}
551	}
552
553	if m.RamdiskAvailable() {
554		ramdiskVariantNeeded = true
555	}
556
557	if m.AndroidModuleBase().InstallInRamdisk() {
558		ramdiskVariantNeeded = true
559		coreVariantNeeded = false
560	}
561
562	if m.VendorRamdiskAvailable() {
563		vendorRamdiskVariantNeeded = true
564	}
565
566	if m.AndroidModuleBase().InstallInVendorRamdisk() {
567		vendorRamdiskVariantNeeded = true
568		coreVariantNeeded = false
569	}
570
571	if m.RecoveryAvailable() {
572		recoveryVariantNeeded = true
573	}
574
575	if m.AndroidModuleBase().InstallInRecovery() {
576		recoveryVariantNeeded = true
577		coreVariantNeeded = false
578	}
579
580	// If using a snapshot, the recovery variant under AOSP directories is not needed,
581	// except for kernel headers, which needs all variants.
582	if m.KernelHeadersDecorator() &&
583		!m.IsSnapshotPrebuilt() &&
584		usingRecoverySnapshot &&
585		!isRecoveryProprietaryModule(mctx) {
586		recoveryVariantNeeded = false
587	}
588
589	for _, variant := range android.FirstUniqueStrings(vendorVariants) {
590		m.AppendExtraVariant(VendorVariationPrefix + variant)
591	}
592
593	for _, variant := range android.FirstUniqueStrings(productVariants) {
594		m.AppendExtraVariant(ProductVariationPrefix + variant)
595	}
596
597	m.SetRamdiskVariantNeeded(ramdiskVariantNeeded)
598	m.SetVendorRamdiskVariantNeeded(vendorRamdiskVariantNeeded)
599	m.SetRecoveryVariantNeeded(recoveryVariantNeeded)
600	m.SetCoreVariantNeeded(coreVariantNeeded)
601
602	// Disable the module if no variants are needed.
603	if !ramdiskVariantNeeded &&
604		!recoveryVariantNeeded &&
605		!coreVariantNeeded &&
606		len(m.ExtraVariants()) == 0 {
607		m.Disable()
608	}
609}
610
611func (c *Module) CoreVariantNeeded(ctx android.BaseModuleContext) bool {
612	return c.Properties.CoreVariantNeeded
613}
614
615func (c *Module) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
616	return c.Properties.RamdiskVariantNeeded
617}
618
619func (c *Module) VendorRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
620	return c.Properties.VendorRamdiskVariantNeeded
621}
622
623func (c *Module) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
624	return false
625}
626
627func (c *Module) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool {
628	return c.Properties.RecoveryVariantNeeded
629}
630
631func (c *Module) ExtraImageVariations(ctx android.BaseModuleContext) []string {
632	return c.Properties.ExtraVariants
633}
634
635func squashVendorSrcs(m *Module) {
636	if lib, ok := m.compiler.(*libraryDecorator); ok {
637		lib.baseCompiler.Properties.Srcs = append(lib.baseCompiler.Properties.Srcs,
638			lib.baseCompiler.Properties.Target.Vendor.Srcs...)
639
640		lib.baseCompiler.Properties.Exclude_srcs = append(lib.baseCompiler.Properties.Exclude_srcs,
641			lib.baseCompiler.Properties.Target.Vendor.Exclude_srcs...)
642
643		lib.baseCompiler.Properties.Exclude_generated_sources = append(lib.baseCompiler.Properties.Exclude_generated_sources,
644			lib.baseCompiler.Properties.Target.Vendor.Exclude_generated_sources...)
645	}
646}
647
648func squashProductSrcs(m *Module) {
649	if lib, ok := m.compiler.(*libraryDecorator); ok {
650		lib.baseCompiler.Properties.Srcs = append(lib.baseCompiler.Properties.Srcs,
651			lib.baseCompiler.Properties.Target.Product.Srcs...)
652
653		lib.baseCompiler.Properties.Exclude_srcs = append(lib.baseCompiler.Properties.Exclude_srcs,
654			lib.baseCompiler.Properties.Target.Product.Exclude_srcs...)
655
656		lib.baseCompiler.Properties.Exclude_generated_sources = append(lib.baseCompiler.Properties.Exclude_generated_sources,
657			lib.baseCompiler.Properties.Target.Product.Exclude_generated_sources...)
658	}
659}
660
661func squashRecoverySrcs(m *Module) {
662	if lib, ok := m.compiler.(*libraryDecorator); ok {
663		lib.baseCompiler.Properties.Srcs = append(lib.baseCompiler.Properties.Srcs,
664			lib.baseCompiler.Properties.Target.Recovery.Srcs...)
665
666		lib.baseCompiler.Properties.Exclude_srcs = append(lib.baseCompiler.Properties.Exclude_srcs,
667			lib.baseCompiler.Properties.Target.Recovery.Exclude_srcs...)
668
669		lib.baseCompiler.Properties.Exclude_generated_sources = append(lib.baseCompiler.Properties.Exclude_generated_sources,
670			lib.baseCompiler.Properties.Target.Recovery.Exclude_generated_sources...)
671	}
672}
673
674func squashVendorRamdiskSrcs(m *Module) {
675	if lib, ok := m.compiler.(*libraryDecorator); ok {
676		lib.baseCompiler.Properties.Exclude_srcs = append(lib.baseCompiler.Properties.Exclude_srcs, lib.baseCompiler.Properties.Target.Vendor_ramdisk.Exclude_srcs...)
677	}
678}
679
680func (c *Module) SetImageVariation(ctx android.BaseModuleContext, variant string, module android.Module) {
681	m := module.(*Module)
682	if variant == android.RamdiskVariation {
683		m.MakeAsPlatform()
684	} else if variant == android.VendorRamdiskVariation {
685		m.MakeAsPlatform()
686		squashVendorRamdiskSrcs(m)
687	} else if variant == android.RecoveryVariation {
688		m.MakeAsPlatform()
689		squashRecoverySrcs(m)
690	} else if strings.HasPrefix(variant, VendorVariationPrefix) {
691		m.Properties.ImageVariationPrefix = VendorVariationPrefix
692		m.Properties.VndkVersion = strings.TrimPrefix(variant, VendorVariationPrefix)
693		squashVendorSrcs(m)
694
695		// Makefile shouldn't know vendor modules other than BOARD_VNDK_VERSION.
696		// Hide other vendor variants to avoid collision.
697		vndkVersion := ctx.DeviceConfig().VndkVersion()
698		if vndkVersion != "current" && vndkVersion != "" && vndkVersion != m.Properties.VndkVersion {
699			m.Properties.HideFromMake = true
700			m.HideFromMake()
701		}
702	} else if strings.HasPrefix(variant, ProductVariationPrefix) {
703		m.Properties.ImageVariationPrefix = ProductVariationPrefix
704		m.Properties.VndkVersion = strings.TrimPrefix(variant, ProductVariationPrefix)
705		squashProductSrcs(m)
706	}
707
708	if c.NeedsVendorPublicLibraryVariants() &&
709		(variant == android.CoreVariation || strings.HasPrefix(variant, ProductVariationPrefix)) {
710		c.VendorProperties.IsVendorPublicLibrary = true
711	}
712}
713