| // Copyright 2019 Google Inc. All rights reserved. |
| // |
| // 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 android |
| |
| type ImageInterfaceContext interface { |
| ArchModuleContext |
| |
| Module() Module |
| |
| ModuleErrorf(fmt string, args ...interface{}) |
| PropertyErrorf(property, fmt string, args ...interface{}) |
| |
| DeviceSpecific() bool |
| SocSpecific() bool |
| ProductSpecific() bool |
| SystemExtSpecific() bool |
| Platform() bool |
| |
| Config() Config |
| } |
| |
| // ImageInterface is implemented by modules that need to be split by the imageTransitionMutator. |
| type ImageInterface interface { |
| // ImageMutatorBegin is called before any other method in the ImageInterface. |
| ImageMutatorBegin(ctx ImageInterfaceContext) |
| |
| // VendorVariantNeeded should return true if the module needs a vendor variant (installed on the vendor image). |
| VendorVariantNeeded(ctx ImageInterfaceContext) bool |
| |
| // ProductVariantNeeded should return true if the module needs a product variant (installed on the product image). |
| ProductVariantNeeded(ctx ImageInterfaceContext) bool |
| |
| // CoreVariantNeeded should return true if the module needs a core variant (installed on the system image). |
| CoreVariantNeeded(ctx ImageInterfaceContext) bool |
| |
| // RamdiskVariantNeeded should return true if the module needs a ramdisk variant (installed on the |
| // ramdisk partition). |
| RamdiskVariantNeeded(ctx ImageInterfaceContext) bool |
| |
| // VendorRamdiskVariantNeeded should return true if the module needs a vendor ramdisk variant (installed on the |
| // vendor ramdisk partition). |
| VendorRamdiskVariantNeeded(ctx ImageInterfaceContext) bool |
| |
| // DebugRamdiskVariantNeeded should return true if the module needs a debug ramdisk variant (installed on the |
| // debug ramdisk partition: $(PRODUCT_OUT)/debug_ramdisk). |
| DebugRamdiskVariantNeeded(ctx ImageInterfaceContext) bool |
| |
| // RecoveryVariantNeeded should return true if the module needs a recovery variant (installed on the |
| // recovery partition). |
| RecoveryVariantNeeded(ctx ImageInterfaceContext) bool |
| |
| // ExtraImageVariations should return a list of the additional variations needed for the module. After the |
| // variants are created the SetImageVariation method will be called on each newly created variant with the |
| // its variation. |
| ExtraImageVariations(ctx ImageInterfaceContext) []string |
| |
| // SetImageVariation is called for each newly created image variant. The receiver is the original |
| // module, "variation" is the name of the newly created variant. "variation" is set on the receiver. |
| SetImageVariation(ctx ImageInterfaceContext, variation string) |
| } |
| |
| const ( |
| // VendorVariation is the variant name used for /vendor code that does not |
| // compile against the VNDK. |
| VendorVariation string = "vendor" |
| |
| // ProductVariation is the variant name used for /product code that does not |
| // compile against the VNDK. |
| ProductVariation string = "product" |
| |
| // CoreVariation is the variant used for framework-private libraries, or |
| // SDK libraries. (which framework-private libraries can use), which |
| // will be installed to the system image. |
| CoreVariation string = "" |
| |
| // RecoveryVariation means a module to be installed to recovery image. |
| RecoveryVariation string = "recovery" |
| |
| // RamdiskVariation means a module to be installed to ramdisk image. |
| RamdiskVariation string = "ramdisk" |
| |
| // VendorRamdiskVariation means a module to be installed to vendor ramdisk image. |
| VendorRamdiskVariation string = "vendor_ramdisk" |
| |
| // DebugRamdiskVariation means a module to be installed to debug ramdisk image. |
| DebugRamdiskVariation string = "debug_ramdisk" |
| ) |
| |
| type imageInterfaceContextAdapter struct { |
| IncomingTransitionContext |
| kind moduleKind |
| } |
| |
| var _ ImageInterfaceContext = (*imageInterfaceContextAdapter)(nil) |
| |
| func (e *imageInterfaceContextAdapter) Platform() bool { |
| return e.kind == platformModule |
| } |
| |
| func (e *imageInterfaceContextAdapter) DeviceSpecific() bool { |
| return e.kind == deviceSpecificModule |
| } |
| |
| func (e *imageInterfaceContextAdapter) SocSpecific() bool { |
| return e.kind == socSpecificModule |
| } |
| |
| func (e *imageInterfaceContextAdapter) ProductSpecific() bool { |
| return e.kind == productSpecificModule |
| } |
| |
| func (e *imageInterfaceContextAdapter) SystemExtSpecific() bool { |
| return e.kind == systemExtSpecificModule |
| } |
| |
| // imageMutatorBeginMutator calls ImageMutatorBegin on all modules that may have image variants. |
| // This happens right before the imageTransitionMutator runs. It's needed to initialize these |
| // modules so that they return the correct results for all the other ImageInterface methods, |
| // which the imageTransitionMutator will call. Transition mutators should also not mutate modules |
| // (except in their Mutate() function), which this method does, so we run it in a separate mutator |
| // first. |
| func imageMutatorBeginMutator(ctx BottomUpMutatorContext) { |
| if m, ok := ctx.Module().(ImageInterface); ok && ctx.Os() == Android { |
| m.ImageMutatorBegin(ctx) |
| } |
| } |
| |
| // imageTransitionMutator creates variants for modules that implement the ImageInterface that |
| // allow them to build differently for each partition (recovery, core, vendor, etc.). |
| type imageTransitionMutator struct{} |
| |
| func getImageVariations(ctx ImageInterfaceContext) []string { |
| var variations []string |
| |
| if m, ok := ctx.Module().(ImageInterface); ctx.Os() == Android && ok { |
| if m.CoreVariantNeeded(ctx) { |
| variations = append(variations, CoreVariation) |
| } |
| if m.RamdiskVariantNeeded(ctx) { |
| variations = append(variations, RamdiskVariation) |
| } |
| if m.VendorRamdiskVariantNeeded(ctx) { |
| variations = append(variations, VendorRamdiskVariation) |
| } |
| if m.DebugRamdiskVariantNeeded(ctx) { |
| variations = append(variations, DebugRamdiskVariation) |
| } |
| if m.RecoveryVariantNeeded(ctx) { |
| variations = append(variations, RecoveryVariation) |
| } |
| if m.VendorVariantNeeded(ctx) { |
| variations = append(variations, VendorVariation) |
| } |
| if m.ProductVariantNeeded(ctx) { |
| variations = append(variations, ProductVariation) |
| } |
| |
| extraVariations := m.ExtraImageVariations(ctx) |
| variations = append(variations, extraVariations...) |
| } |
| |
| if len(variations) == 0 { |
| variations = append(variations, "") |
| } |
| |
| return variations |
| } |
| |
| func (imageTransitionMutator) Split(ctx BaseModuleContext) []string { |
| return getImageVariations(ctx) |
| } |
| |
| func (imageTransitionMutator) OutgoingTransition(ctx OutgoingTransitionContext, sourceVariation string) string { |
| return sourceVariation |
| } |
| |
| func (imageTransitionMutator) IncomingTransition(ctx IncomingTransitionContext, incomingVariation string) string { |
| if _, ok := ctx.Module().(ImageInterface); ctx.Os() != Android || !ok { |
| return CoreVariation |
| } |
| variations := getImageVariations(&imageInterfaceContextAdapter{ |
| IncomingTransitionContext: ctx, |
| kind: determineModuleKind(ctx.Module().base(), ctx), |
| }) |
| // If there's only 1 possible variation, use that. This is a holdover from when blueprint, |
| // when adding dependencies, would use the only variant of a module regardless of its variations |
| // if only 1 variant existed. |
| if len(variations) == 1 { |
| return variations[0] |
| } |
| return incomingVariation |
| } |
| |
| func (imageTransitionMutator) Mutate(ctx BottomUpMutatorContext, variation string) { |
| ctx.Module().base().setImageVariation(variation) |
| if m, ok := ctx.Module().(ImageInterface); ok { |
| m.SetImageVariation(ctx, variation) |
| } |
| } |