|  | // Copyright 2020 The Android Open Source Project | 
|  | // | 
|  | // Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | // you may not use this file except in compliance with the License. | 
|  | // You may obtain a copy of the License at | 
|  | // | 
|  | //	http://www.apache.org/licenses/LICENSE-2.0 | 
|  | // | 
|  | // Unless required by applicable law or agreed to in writing, software | 
|  | // distributed under the License is distributed on an "AS IS" BASIS, | 
|  | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | // See the License for the specific language governing permissions and | 
|  | // limitations under the License. | 
|  | package cc | 
|  |  | 
|  | // This file contains image variant related things, including image mutator functions, utility | 
|  | // functions to determine where a module is installed, etc. | 
|  |  | 
|  | import ( | 
|  | "fmt" | 
|  | "reflect" | 
|  | "strings" | 
|  |  | 
|  | "android/soong/android" | 
|  | "android/soong/snapshot" | 
|  |  | 
|  | "github.com/google/blueprint/proptools" | 
|  | ) | 
|  |  | 
|  | var _ android.ImageInterface = (*Module)(nil) | 
|  |  | 
|  | type ImageVariantType string | 
|  |  | 
|  | const ( | 
|  | coreImageVariant          ImageVariantType = "core" | 
|  | vendorImageVariant        ImageVariantType = "vendor" | 
|  | productImageVariant       ImageVariantType = "product" | 
|  | ramdiskImageVariant       ImageVariantType = "ramdisk" | 
|  | vendorRamdiskImageVariant ImageVariantType = "vendor_ramdisk" | 
|  | recoveryImageVariant      ImageVariantType = "recovery" | 
|  | hostImageVariant          ImageVariantType = "host" | 
|  | ) | 
|  |  | 
|  | const ( | 
|  | // VendorVariationPrefix is the variant prefix used for /vendor code that compiles | 
|  | // against the VNDK. | 
|  | VendorVariationPrefix = "vendor." | 
|  |  | 
|  | // ProductVariationPrefix is the variant prefix used for /product code that compiles | 
|  | // against the VNDK. | 
|  | ProductVariationPrefix = "product." | 
|  | ) | 
|  |  | 
|  | func (ctx *moduleContext) ProductSpecific() bool { | 
|  | return ctx.ModuleContext.ProductSpecific() || ctx.mod.productSpecificModuleContext() | 
|  | } | 
|  |  | 
|  | func (ctx *moduleContext) SocSpecific() bool { | 
|  | return ctx.ModuleContext.SocSpecific() || ctx.mod.socSpecificModuleContext() | 
|  | } | 
|  |  | 
|  | func (ctx *moduleContext) DeviceSpecific() bool { | 
|  | return ctx.ModuleContext.DeviceSpecific() || ctx.mod.deviceSpecificModuleContext() | 
|  | } | 
|  |  | 
|  | func (ctx *moduleContextImpl) inProduct() bool { | 
|  | return ctx.mod.InProduct() | 
|  | } | 
|  |  | 
|  | func (ctx *moduleContextImpl) inVendor() bool { | 
|  | return ctx.mod.InVendor() | 
|  | } | 
|  |  | 
|  | func (ctx *moduleContextImpl) inRamdisk() bool { | 
|  | return ctx.mod.InRamdisk() | 
|  | } | 
|  |  | 
|  | func (ctx *moduleContextImpl) inVendorRamdisk() bool { | 
|  | return ctx.mod.InVendorRamdisk() | 
|  | } | 
|  |  | 
|  | func (ctx *moduleContextImpl) inRecovery() bool { | 
|  | return ctx.mod.InRecovery() | 
|  | } | 
|  |  | 
|  | func (c *Module) productSpecificModuleContext() bool { | 
|  | // Additionally check if this module is inProduct() that means it is a "product" variant of a | 
|  | // module. As well as product specific modules, product variants must be installed to /product. | 
|  | return c.InProduct() | 
|  | } | 
|  |  | 
|  | func (c *Module) socSpecificModuleContext() bool { | 
|  | // Additionally check if this module is inVendor() that means it is a "vendor" variant of a | 
|  | // module. As well as SoC specific modules, vendor variants must be installed to /vendor | 
|  | // unless they have "odm_available: true". | 
|  | return c.HasVendorVariant() && c.InVendor() && !c.VendorVariantToOdm() | 
|  | } | 
|  |  | 
|  | func (c *Module) deviceSpecificModuleContext() bool { | 
|  | // Some vendor variants want to be installed to /odm by setting "odm_available: true". | 
|  | return c.InVendor() && c.VendorVariantToOdm() | 
|  | } | 
|  |  | 
|  | // Returns true when this module is configured to have core and vendor variants. | 
|  | func (c *Module) HasVendorVariant() bool { | 
|  | return Bool(c.VendorProperties.Vendor_available) || Bool(c.VendorProperties.Odm_available) | 
|  | } | 
|  |  | 
|  | // Returns true when this module creates a vendor variant and wants to install the vendor variant | 
|  | // to the odm partition. | 
|  | func (c *Module) VendorVariantToOdm() bool { | 
|  | return Bool(c.VendorProperties.Odm_available) | 
|  | } | 
|  |  | 
|  | // Returns true when this module is configured to have core and product variants. | 
|  | func (c *Module) HasProductVariant() bool { | 
|  | return Bool(c.VendorProperties.Product_available) | 
|  | } | 
|  |  | 
|  | // Returns true when this module is configured to have core and either product or vendor variants. | 
|  | func (c *Module) HasNonSystemVariants() bool { | 
|  | return c.HasVendorVariant() || c.HasProductVariant() | 
|  | } | 
|  |  | 
|  | // Returns true if the module is "product" variant. Usually these modules are installed in /product | 
|  | func (c *Module) InProduct() bool { | 
|  | return c.Properties.ImageVariationPrefix == ProductVariationPrefix | 
|  | } | 
|  |  | 
|  | // Returns true if the module is "vendor" variant. Usually these modules are installed in /vendor | 
|  | func (c *Module) InVendor() bool { | 
|  | return c.Properties.ImageVariationPrefix == VendorVariationPrefix | 
|  | } | 
|  |  | 
|  | func (c *Module) InRamdisk() bool { | 
|  | return c.ModuleBase.InRamdisk() || c.ModuleBase.InstallInRamdisk() | 
|  | } | 
|  |  | 
|  | func (c *Module) InVendorRamdisk() bool { | 
|  | return c.ModuleBase.InVendorRamdisk() || c.ModuleBase.InstallInVendorRamdisk() | 
|  | } | 
|  |  | 
|  | func (c *Module) InRecovery() bool { | 
|  | return c.ModuleBase.InRecovery() || c.ModuleBase.InstallInRecovery() | 
|  | } | 
|  |  | 
|  | func (c *Module) OnlyInRamdisk() bool { | 
|  | return c.ModuleBase.InstallInRamdisk() | 
|  | } | 
|  |  | 
|  | func (c *Module) OnlyInVendorRamdisk() bool { | 
|  | return c.ModuleBase.InstallInVendorRamdisk() | 
|  | } | 
|  |  | 
|  | func (c *Module) OnlyInRecovery() bool { | 
|  | return c.ModuleBase.InstallInRecovery() | 
|  | } | 
|  |  | 
|  | func visitPropsAndCompareVendorAndProductProps(v reflect.Value) bool { | 
|  | if v.Kind() != reflect.Struct { | 
|  | return true | 
|  | } | 
|  | for i := 0; i < v.NumField(); i++ { | 
|  | prop := v.Field(i) | 
|  | if prop.Kind() == reflect.Struct && v.Type().Field(i).Name == "Target" { | 
|  | vendor_prop := prop.FieldByName("Vendor") | 
|  | product_prop := prop.FieldByName("Product") | 
|  | if vendor_prop.Kind() != reflect.Struct && product_prop.Kind() != reflect.Struct { | 
|  | // Neither Target.Vendor nor Target.Product is defined | 
|  | continue | 
|  | } | 
|  | if vendor_prop.Kind() != reflect.Struct || product_prop.Kind() != reflect.Struct || | 
|  | !reflect.DeepEqual(vendor_prop.Interface(), product_prop.Interface()) { | 
|  | // If only one of either Target.Vendor or Target.Product is | 
|  | // defined or they have different values, it fails the build | 
|  | // since VNDK must have the same properties for both vendor | 
|  | // and product variants. | 
|  | return false | 
|  | } | 
|  | } else if !visitPropsAndCompareVendorAndProductProps(prop) { | 
|  | // Visit the substructures to find Target.Vendor and Target.Product | 
|  | return false | 
|  | } | 
|  | } | 
|  | return true | 
|  | } | 
|  |  | 
|  | // In the case of VNDK, vendor and product variants must have the same properties. | 
|  | // VNDK installs only one file and shares it for both vendor and product modules on | 
|  | // runtime. We may not define different versions of a VNDK lib for each partition. | 
|  | // This function is used only for the VNDK modules that is available to both vendor | 
|  | // and product partitions. | 
|  | func (c *Module) compareVendorAndProductProps() bool { | 
|  | if !c.IsVndk() && !Bool(c.VendorProperties.Product_available) { | 
|  | panic(fmt.Errorf("This is only for product available VNDK libs. %q is not a VNDK library or not product available", c.Name())) | 
|  | } | 
|  | for _, properties := range c.GetProperties() { | 
|  | if !visitPropsAndCompareVendorAndProductProps(reflect.ValueOf(properties).Elem()) { | 
|  | return false | 
|  | } | 
|  | } | 
|  | return true | 
|  | } | 
|  |  | 
|  | // ImageMutatableModule provides a common image mutation interface for  LinkableInterface modules. | 
|  | type ImageMutatableModule interface { | 
|  | android.Module | 
|  | LinkableInterface | 
|  |  | 
|  | // AndroidModuleBase returns the android.ModuleBase for this module | 
|  | AndroidModuleBase() *android.ModuleBase | 
|  |  | 
|  | // VendorAvailable returns true if this module is available on the vendor image. | 
|  | VendorAvailable() bool | 
|  |  | 
|  | // OdmAvailable returns true if this module is available on the odm image. | 
|  | OdmAvailable() bool | 
|  |  | 
|  | // ProductAvailable returns true if this module is available on the product image. | 
|  | ProductAvailable() bool | 
|  |  | 
|  | // RamdiskAvailable returns true if this module is available on the ramdisk image. | 
|  | RamdiskAvailable() bool | 
|  |  | 
|  | // RecoveryAvailable returns true if this module is available on the recovery image. | 
|  | RecoveryAvailable() bool | 
|  |  | 
|  | // VendorRamdiskAvailable returns true if this module is available on the vendor ramdisk image. | 
|  | VendorRamdiskAvailable() bool | 
|  |  | 
|  | // IsSnapshotPrebuilt returns true if this module is a snapshot prebuilt. | 
|  | IsSnapshotPrebuilt() bool | 
|  |  | 
|  | // SnapshotVersion returns the snapshot version for this module. | 
|  | SnapshotVersion(mctx android.BaseModuleContext) string | 
|  |  | 
|  | // SdkVersion returns the SDK version for this module. | 
|  | SdkVersion() string | 
|  |  | 
|  | // ExtraVariants returns the list of extra variants this module requires. | 
|  | ExtraVariants() []string | 
|  |  | 
|  | // AppendExtraVariant returns an extra variant to the list of extra variants this module requires. | 
|  | AppendExtraVariant(extraVariant string) | 
|  |  | 
|  | // SetRamdiskVariantNeeded sets whether the Ramdisk Variant is needed. | 
|  | SetRamdiskVariantNeeded(b bool) | 
|  |  | 
|  | // SetVendorRamdiskVariantNeeded sets whether the Vendor Ramdisk Variant is needed. | 
|  | SetVendorRamdiskVariantNeeded(b bool) | 
|  |  | 
|  | // SetRecoveryVariantNeeded sets whether the Recovery Variant is needed. | 
|  | SetRecoveryVariantNeeded(b bool) | 
|  |  | 
|  | // SetCoreVariantNeeded sets whether the Core Variant is needed. | 
|  | SetCoreVariantNeeded(b bool) | 
|  | } | 
|  |  | 
|  | var _ ImageMutatableModule = (*Module)(nil) | 
|  |  | 
|  | func (m *Module) ImageMutatorBegin(mctx android.BaseModuleContext) { | 
|  | m.CheckVndkProperties(mctx) | 
|  | MutateImage(mctx, m) | 
|  | } | 
|  |  | 
|  | // CheckVndkProperties checks whether the VNDK-related properties are set correctly. | 
|  | // If properties are not set correctly, results in a module context property error. | 
|  | func (m *Module) CheckVndkProperties(mctx android.BaseModuleContext) { | 
|  | vendorSpecific := mctx.SocSpecific() || mctx.DeviceSpecific() | 
|  | productSpecific := mctx.ProductSpecific() | 
|  |  | 
|  | if vndkdep := m.vndkdep; vndkdep != nil { | 
|  | if vndkdep.isVndk() { | 
|  | if vendorSpecific || productSpecific { | 
|  | if !vndkdep.isVndkExt() { | 
|  | mctx.PropertyErrorf("vndk", | 
|  | "must set `extends: \"...\"` to vndk extension") | 
|  | } else if Bool(m.VendorProperties.Vendor_available) { | 
|  | mctx.PropertyErrorf("vendor_available", | 
|  | "must not set at the same time as `vndk: {extends: \"...\"}`") | 
|  | } else if Bool(m.VendorProperties.Product_available) { | 
|  | mctx.PropertyErrorf("product_available", | 
|  | "must not set at the same time as `vndk: {extends: \"...\"}`") | 
|  | } | 
|  | } else { | 
|  | if vndkdep.isVndkExt() { | 
|  | mctx.PropertyErrorf("vndk", | 
|  | "must set `vendor: true` or `product_specific: true` to set `extends: %q`", | 
|  | m.getVndkExtendsModuleName()) | 
|  | } | 
|  | if !Bool(m.VendorProperties.Vendor_available) { | 
|  | mctx.PropertyErrorf("vndk", | 
|  | "vendor_available must be set to true when `vndk: {enabled: true}`") | 
|  | } | 
|  | if Bool(m.VendorProperties.Product_available) { | 
|  | // If a VNDK module creates both product and vendor variants, they | 
|  | // must have the same properties since they share a single VNDK | 
|  | // library on runtime. | 
|  | if !m.compareVendorAndProductProps() { | 
|  | mctx.ModuleErrorf("product properties must have the same values with the vendor properties for VNDK modules") | 
|  | } | 
|  | } | 
|  | } | 
|  | } else { | 
|  | if vndkdep.isVndkSp() { | 
|  | mctx.PropertyErrorf("vndk", | 
|  | "must set `enabled: true` to set `support_system_process: true`") | 
|  | } | 
|  | if vndkdep.isVndkExt() { | 
|  | mctx.PropertyErrorf("vndk", | 
|  | "must set `enabled: true` to set `extends: %q`", | 
|  | m.getVndkExtendsModuleName()) | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | func (m *Module) VendorAvailable() bool { | 
|  | return Bool(m.VendorProperties.Vendor_available) | 
|  | } | 
|  |  | 
|  | func (m *Module) OdmAvailable() bool { | 
|  | return Bool(m.VendorProperties.Odm_available) | 
|  | } | 
|  |  | 
|  | func (m *Module) ProductAvailable() bool { | 
|  | return Bool(m.VendorProperties.Product_available) | 
|  | } | 
|  |  | 
|  | func (m *Module) RamdiskAvailable() bool { | 
|  | return Bool(m.Properties.Ramdisk_available) | 
|  | } | 
|  |  | 
|  | func (m *Module) VendorRamdiskAvailable() bool { | 
|  | return Bool(m.Properties.Vendor_ramdisk_available) | 
|  | } | 
|  |  | 
|  | func (m *Module) AndroidModuleBase() *android.ModuleBase { | 
|  | return &m.ModuleBase | 
|  | } | 
|  |  | 
|  | func (m *Module) RecoveryAvailable() bool { | 
|  | return Bool(m.Properties.Recovery_available) | 
|  | } | 
|  |  | 
|  | func (m *Module) ExtraVariants() []string { | 
|  | return m.Properties.ExtraVersionedImageVariations | 
|  | } | 
|  |  | 
|  | func (m *Module) AppendExtraVariant(extraVariant string) { | 
|  | m.Properties.ExtraVersionedImageVariations = append(m.Properties.ExtraVersionedImageVariations, extraVariant) | 
|  | } | 
|  |  | 
|  | func (m *Module) SetRamdiskVariantNeeded(b bool) { | 
|  | m.Properties.RamdiskVariantNeeded = b | 
|  | } | 
|  |  | 
|  | func (m *Module) SetVendorRamdiskVariantNeeded(b bool) { | 
|  | m.Properties.VendorRamdiskVariantNeeded = b | 
|  | } | 
|  |  | 
|  | func (m *Module) SetRecoveryVariantNeeded(b bool) { | 
|  | m.Properties.RecoveryVariantNeeded = b | 
|  | } | 
|  |  | 
|  | func (m *Module) SetCoreVariantNeeded(b bool) { | 
|  | m.Properties.CoreVariantNeeded = b | 
|  | } | 
|  |  | 
|  | func (m *Module) SnapshotVersion(mctx android.BaseModuleContext) string { | 
|  | if snapshot, ok := m.linker.(SnapshotInterface); ok { | 
|  | return snapshot.Version() | 
|  | } else { | 
|  | mctx.ModuleErrorf("version is unknown for snapshot prebuilt") | 
|  | // Should we be panicking here instead? | 
|  | return "" | 
|  | } | 
|  | } | 
|  |  | 
|  | func (m *Module) KernelHeadersDecorator() bool { | 
|  | if _, ok := m.linker.(*kernelHeadersDecorator); ok { | 
|  | return true | 
|  | } | 
|  | return false | 
|  | } | 
|  |  | 
|  | // MutateImage handles common image mutations for ImageMutatableModule interfaces. | 
|  | func MutateImage(mctx android.BaseModuleContext, m ImageMutatableModule) { | 
|  | // Validation check | 
|  | vendorSpecific := mctx.SocSpecific() || mctx.DeviceSpecific() | 
|  | productSpecific := mctx.ProductSpecific() | 
|  |  | 
|  | if m.VendorAvailable() { | 
|  | if vendorSpecific { | 
|  | mctx.PropertyErrorf("vendor_available", | 
|  | "doesn't make sense at the same time as `vendor: true`, `proprietary: true`, or `device_specific: true`") | 
|  | } | 
|  | if m.OdmAvailable() { | 
|  | mctx.PropertyErrorf("vendor_available", | 
|  | "doesn't make sense at the same time as `odm_available: true`") | 
|  | } | 
|  | } | 
|  |  | 
|  | if m.OdmAvailable() { | 
|  | if vendorSpecific { | 
|  | mctx.PropertyErrorf("odm_available", | 
|  | "doesn't make sense at the same time as `vendor: true`, `proprietary: true`, or `device_specific: true`") | 
|  | } | 
|  | } | 
|  |  | 
|  | if m.ProductAvailable() { | 
|  | if productSpecific { | 
|  | mctx.PropertyErrorf("product_available", | 
|  | "doesn't make sense at the same time as `product_specific: true`") | 
|  | } | 
|  | if vendorSpecific { | 
|  | mctx.PropertyErrorf("product_available", | 
|  | "cannot provide product variant from a vendor module. Please use `product_specific: true` with `vendor_available: true`") | 
|  | } | 
|  | } | 
|  |  | 
|  | var coreVariantNeeded bool = false | 
|  | var ramdiskVariantNeeded bool = false | 
|  | var vendorRamdiskVariantNeeded bool = false | 
|  | var recoveryVariantNeeded bool = false | 
|  |  | 
|  | var vendorVariants []string | 
|  | var productVariants []string | 
|  |  | 
|  | platformVndkVersion := mctx.DeviceConfig().PlatformVndkVersion() | 
|  | boardVndkVersion := mctx.DeviceConfig().VndkVersion() | 
|  | recoverySnapshotVersion := mctx.DeviceConfig().RecoverySnapshotVersion() | 
|  | usingRecoverySnapshot := recoverySnapshotVersion != "current" && | 
|  | recoverySnapshotVersion != "" | 
|  | needVndkVersionVendorVariantForLlndk := false | 
|  | if boardVndkVersion != "" { | 
|  | boardVndkApiLevel, err := android.ApiLevelFromUser(mctx, boardVndkVersion) | 
|  | if err == nil && !boardVndkApiLevel.IsPreview() { | 
|  | // VNDK snapshot newer than v30 has LLNDK stub libraries. | 
|  | // Only the VNDK version less than or equal to v30 requires generating the vendor | 
|  | // variant of the VNDK version from the source tree. | 
|  | needVndkVersionVendorVariantForLlndk = boardVndkApiLevel.LessThanOrEqualTo(android.ApiLevelOrPanic(mctx, "30")) | 
|  | } | 
|  | } | 
|  | if boardVndkVersion == "current" { | 
|  | boardVndkVersion = platformVndkVersion | 
|  | } | 
|  |  | 
|  | if m.NeedsLlndkVariants() { | 
|  | // This is an LLNDK library.  The implementation of the library will be on /system, | 
|  | // and vendor and product variants will be created with LLNDK stubs. | 
|  | // The LLNDK libraries need vendor variants even if there is no VNDK. | 
|  | coreVariantNeeded = true | 
|  | if platformVndkVersion != "" { | 
|  | vendorVariants = append(vendorVariants, platformVndkVersion) | 
|  | productVariants = append(productVariants, platformVndkVersion) | 
|  | } | 
|  | // Generate vendor variants for boardVndkVersion only if the VNDK snapshot does not | 
|  | // provide the LLNDK stub libraries. | 
|  | if needVndkVersionVendorVariantForLlndk { | 
|  | vendorVariants = append(vendorVariants, boardVndkVersion) | 
|  | } | 
|  | } else if m.NeedsVendorPublicLibraryVariants() { | 
|  | // A vendor public library has the implementation on /vendor, with stub variants | 
|  | // for system and product. | 
|  | coreVariantNeeded = true | 
|  | vendorVariants = append(vendorVariants, boardVndkVersion) | 
|  | if platformVndkVersion != "" { | 
|  | productVariants = append(productVariants, platformVndkVersion) | 
|  | } | 
|  | } else if boardVndkVersion == "" { | 
|  | // If the device isn't compiling against the VNDK, we always | 
|  | // use the core mode. | 
|  | coreVariantNeeded = true | 
|  | } else if m.IsSnapshotPrebuilt() { | 
|  | // Make vendor variants only for the versions in BOARD_VNDK_VERSION and | 
|  | // PRODUCT_EXTRA_VNDK_VERSIONS. | 
|  | if m.InstallInRecovery() { | 
|  | recoveryVariantNeeded = true | 
|  | } else { | 
|  | vendorVariants = append(vendorVariants, m.SnapshotVersion(mctx)) | 
|  | } | 
|  | } else if m.HasNonSystemVariants() && !m.IsVndkExt() { | 
|  | // This will be available to /system unless it is product_specific | 
|  | // which will be handled later. | 
|  | coreVariantNeeded = true | 
|  |  | 
|  | // We assume that modules under proprietary paths are compatible for | 
|  | // BOARD_VNDK_VERSION. The other modules are regarded as AOSP, or | 
|  | // PLATFORM_VNDK_VERSION. | 
|  | if m.HasVendorVariant() { | 
|  | if snapshot.IsVendorProprietaryModule(mctx) { | 
|  | vendorVariants = append(vendorVariants, boardVndkVersion) | 
|  | } else { | 
|  | vendorVariants = append(vendorVariants, platformVndkVersion) | 
|  | } | 
|  | } | 
|  |  | 
|  | // product_available modules are available to /product. | 
|  | if m.HasProductVariant() { | 
|  | productVariants = append(productVariants, platformVndkVersion) | 
|  | } | 
|  | } else if vendorSpecific && m.SdkVersion() == "" { | 
|  | // This will be available in /vendor (or /odm) only | 
|  |  | 
|  | // kernel_headers is a special module type whose exported headers | 
|  | // are coming from DeviceKernelHeaders() which is always vendor | 
|  | // dependent. They'll always have both vendor variants. | 
|  | // For other modules, we assume that modules under proprietary | 
|  | // paths are compatible for BOARD_VNDK_VERSION. The other modules | 
|  | // are regarded as AOSP, which is PLATFORM_VNDK_VERSION. | 
|  | if m.KernelHeadersDecorator() { | 
|  | vendorVariants = append(vendorVariants, | 
|  | platformVndkVersion, | 
|  | boardVndkVersion, | 
|  | ) | 
|  | } else if snapshot.IsVendorProprietaryModule(mctx) { | 
|  | vendorVariants = append(vendorVariants, boardVndkVersion) | 
|  | } else { | 
|  | vendorVariants = append(vendorVariants, platformVndkVersion) | 
|  | } | 
|  | } else { | 
|  | // This is either in /system (or similar: /data), or is a | 
|  | // module built with the NDK. Modules built with the NDK | 
|  | // will be restricted using the existing link type checks. | 
|  | coreVariantNeeded = true | 
|  | } | 
|  |  | 
|  | if coreVariantNeeded && productSpecific && m.SdkVersion() == "" { | 
|  | // The module has "product_specific: true" that does not create core variant. | 
|  | coreVariantNeeded = false | 
|  | productVariants = append(productVariants, platformVndkVersion) | 
|  | } | 
|  |  | 
|  | if m.RamdiskAvailable() { | 
|  | ramdiskVariantNeeded = true | 
|  | } | 
|  |  | 
|  | if m.AndroidModuleBase().InstallInRamdisk() { | 
|  | ramdiskVariantNeeded = true | 
|  | coreVariantNeeded = false | 
|  | } | 
|  |  | 
|  | if m.VendorRamdiskAvailable() { | 
|  | vendorRamdiskVariantNeeded = true | 
|  | } | 
|  |  | 
|  | if m.AndroidModuleBase().InstallInVendorRamdisk() { | 
|  | vendorRamdiskVariantNeeded = true | 
|  | coreVariantNeeded = false | 
|  | } | 
|  |  | 
|  | if m.RecoveryAvailable() { | 
|  | recoveryVariantNeeded = true | 
|  | } | 
|  |  | 
|  | if m.AndroidModuleBase().InstallInRecovery() { | 
|  | recoveryVariantNeeded = true | 
|  | coreVariantNeeded = false | 
|  | } | 
|  |  | 
|  | // If using a snapshot, the recovery variant under AOSP directories is not needed, | 
|  | // except for kernel headers, which needs all variants. | 
|  | if !m.KernelHeadersDecorator() && | 
|  | !m.IsSnapshotPrebuilt() && | 
|  | usingRecoverySnapshot && | 
|  | !snapshot.IsRecoveryProprietaryModule(mctx) { | 
|  | recoveryVariantNeeded = false | 
|  | } | 
|  |  | 
|  | for _, variant := range android.FirstUniqueStrings(vendorVariants) { | 
|  | m.AppendExtraVariant(VendorVariationPrefix + variant) | 
|  | } | 
|  |  | 
|  | for _, variant := range android.FirstUniqueStrings(productVariants) { | 
|  | m.AppendExtraVariant(ProductVariationPrefix + variant) | 
|  | } | 
|  |  | 
|  | m.SetRamdiskVariantNeeded(ramdiskVariantNeeded) | 
|  | m.SetVendorRamdiskVariantNeeded(vendorRamdiskVariantNeeded) | 
|  | m.SetRecoveryVariantNeeded(recoveryVariantNeeded) | 
|  | m.SetCoreVariantNeeded(coreVariantNeeded) | 
|  |  | 
|  | // Disable the module if no variants are needed. | 
|  | if !ramdiskVariantNeeded && | 
|  | !recoveryVariantNeeded && | 
|  | !coreVariantNeeded && | 
|  | len(m.ExtraVariants()) == 0 { | 
|  | m.Disable() | 
|  | } | 
|  | } | 
|  |  | 
|  | func (c *Module) CoreVariantNeeded(ctx android.BaseModuleContext) bool { | 
|  | return c.Properties.CoreVariantNeeded | 
|  | } | 
|  |  | 
|  | func (c *Module) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool { | 
|  | return c.Properties.RamdiskVariantNeeded | 
|  | } | 
|  |  | 
|  | func (c *Module) VendorRamdiskVariantNeeded(ctx android.BaseModuleContext) bool { | 
|  | return c.Properties.VendorRamdiskVariantNeeded | 
|  | } | 
|  |  | 
|  | func (c *Module) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool { | 
|  | return false | 
|  | } | 
|  |  | 
|  | func (c *Module) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool { | 
|  | return c.Properties.RecoveryVariantNeeded | 
|  | } | 
|  |  | 
|  | func (c *Module) ExtraImageVariations(ctx android.BaseModuleContext) []string { | 
|  | return c.Properties.ExtraVersionedImageVariations | 
|  | } | 
|  |  | 
|  | func squashVendorSrcs(m *Module) { | 
|  | if lib, ok := m.compiler.(*libraryDecorator); ok { | 
|  | lib.baseCompiler.Properties.Srcs = append(lib.baseCompiler.Properties.Srcs, | 
|  | lib.baseCompiler.Properties.Target.Vendor.Srcs...) | 
|  |  | 
|  | lib.baseCompiler.Properties.Exclude_srcs = append(lib.baseCompiler.Properties.Exclude_srcs, | 
|  | lib.baseCompiler.Properties.Target.Vendor.Exclude_srcs...) | 
|  |  | 
|  | lib.baseCompiler.Properties.Exclude_generated_sources = append(lib.baseCompiler.Properties.Exclude_generated_sources, | 
|  | lib.baseCompiler.Properties.Target.Vendor.Exclude_generated_sources...) | 
|  |  | 
|  | if lib.Properties.Target.Vendor.No_stubs { | 
|  | proptools.Clear(&lib.Properties.Stubs) | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | func squashProductSrcs(m *Module) { | 
|  | if lib, ok := m.compiler.(*libraryDecorator); ok { | 
|  | lib.baseCompiler.Properties.Srcs = append(lib.baseCompiler.Properties.Srcs, | 
|  | lib.baseCompiler.Properties.Target.Product.Srcs...) | 
|  |  | 
|  | lib.baseCompiler.Properties.Exclude_srcs = append(lib.baseCompiler.Properties.Exclude_srcs, | 
|  | lib.baseCompiler.Properties.Target.Product.Exclude_srcs...) | 
|  |  | 
|  | lib.baseCompiler.Properties.Exclude_generated_sources = append(lib.baseCompiler.Properties.Exclude_generated_sources, | 
|  | lib.baseCompiler.Properties.Target.Product.Exclude_generated_sources...) | 
|  |  | 
|  | if lib.Properties.Target.Product.No_stubs { | 
|  | proptools.Clear(&lib.Properties.Stubs) | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | func squashRecoverySrcs(m *Module) { | 
|  | if lib, ok := m.compiler.(*libraryDecorator); ok { | 
|  | lib.baseCompiler.Properties.Srcs = append(lib.baseCompiler.Properties.Srcs, | 
|  | lib.baseCompiler.Properties.Target.Recovery.Srcs...) | 
|  |  | 
|  | lib.baseCompiler.Properties.Exclude_srcs = append(lib.baseCompiler.Properties.Exclude_srcs, | 
|  | lib.baseCompiler.Properties.Target.Recovery.Exclude_srcs...) | 
|  |  | 
|  | lib.baseCompiler.Properties.Exclude_generated_sources = append(lib.baseCompiler.Properties.Exclude_generated_sources, | 
|  | lib.baseCompiler.Properties.Target.Recovery.Exclude_generated_sources...) | 
|  | } | 
|  | } | 
|  |  | 
|  | func squashVendorRamdiskSrcs(m *Module) { | 
|  | if lib, ok := m.compiler.(*libraryDecorator); ok { | 
|  | lib.baseCompiler.Properties.Exclude_srcs = append(lib.baseCompiler.Properties.Exclude_srcs, lib.baseCompiler.Properties.Target.Vendor_ramdisk.Exclude_srcs...) | 
|  | } | 
|  | } | 
|  |  | 
|  | func squashRamdiskSrcs(m *Module) { | 
|  | if lib, ok := m.compiler.(*libraryDecorator); ok { | 
|  | lib.baseCompiler.Properties.Exclude_srcs = append(lib.baseCompiler.Properties.Exclude_srcs, lib.baseCompiler.Properties.Target.Ramdisk.Exclude_srcs...) | 
|  | } | 
|  | } | 
|  |  | 
|  | func (c *Module) SetImageVariation(ctx android.BaseModuleContext, variant string, module android.Module) { | 
|  | m := module.(*Module) | 
|  | if variant == android.RamdiskVariation { | 
|  | m.MakeAsPlatform() | 
|  | squashRamdiskSrcs(m) | 
|  | } else if variant == android.VendorRamdiskVariation { | 
|  | m.MakeAsPlatform() | 
|  | squashVendorRamdiskSrcs(m) | 
|  | } else if variant == android.RecoveryVariation { | 
|  | m.MakeAsPlatform() | 
|  | squashRecoverySrcs(m) | 
|  | } else if strings.HasPrefix(variant, VendorVariationPrefix) { | 
|  | m.Properties.ImageVariationPrefix = VendorVariationPrefix | 
|  | m.Properties.VndkVersion = strings.TrimPrefix(variant, VendorVariationPrefix) | 
|  | squashVendorSrcs(m) | 
|  |  | 
|  | // Makefile shouldn't know vendor modules other than BOARD_VNDK_VERSION. | 
|  | // Hide other vendor variants to avoid collision. | 
|  | vndkVersion := ctx.DeviceConfig().VndkVersion() | 
|  | if vndkVersion != "current" && vndkVersion != "" && vndkVersion != m.Properties.VndkVersion { | 
|  | m.Properties.HideFromMake = true | 
|  | m.HideFromMake() | 
|  | } | 
|  | } else if strings.HasPrefix(variant, ProductVariationPrefix) { | 
|  | m.Properties.ImageVariationPrefix = ProductVariationPrefix | 
|  | m.Properties.VndkVersion = strings.TrimPrefix(variant, ProductVariationPrefix) | 
|  | squashProductSrcs(m) | 
|  | } | 
|  |  | 
|  | if c.NeedsVendorPublicLibraryVariants() && | 
|  | (variant == android.CoreVariation || strings.HasPrefix(variant, ProductVariationPrefix)) { | 
|  | c.VendorProperties.IsVendorPublicLibrary = true | 
|  | } | 
|  | } |