1// Copyright 2019 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 android 16 17type ImageInterfaceContext interface { 18 ArchModuleContext 19 20 Module() Module 21 22 ModuleErrorf(fmt string, args ...interface{}) 23 PropertyErrorf(property, fmt string, args ...interface{}) 24 25 DeviceSpecific() bool 26 SocSpecific() bool 27 ProductSpecific() bool 28 SystemExtSpecific() bool 29 Platform() bool 30 31 Config() Config 32} 33 34// ImageInterface is implemented by modules that need to be split by the imageTransitionMutator. 35type ImageInterface interface { 36 // ImageMutatorBegin is called before any other method in the ImageInterface. 37 ImageMutatorBegin(ctx ImageInterfaceContext) 38 39 // VendorVariantNeeded should return true if the module needs a vendor variant (installed on the vendor image). 40 VendorVariantNeeded(ctx ImageInterfaceContext) bool 41 42 // ProductVariantNeeded should return true if the module needs a product variant (installed on the product image). 43 ProductVariantNeeded(ctx ImageInterfaceContext) bool 44 45 // CoreVariantNeeded should return true if the module needs a core variant (installed on the system image). 46 CoreVariantNeeded(ctx ImageInterfaceContext) bool 47 48 // RamdiskVariantNeeded should return true if the module needs a ramdisk variant (installed on the 49 // ramdisk partition). 50 RamdiskVariantNeeded(ctx ImageInterfaceContext) bool 51 52 // VendorRamdiskVariantNeeded should return true if the module needs a vendor ramdisk variant (installed on the 53 // vendor ramdisk partition). 54 VendorRamdiskVariantNeeded(ctx ImageInterfaceContext) bool 55 56 // DebugRamdiskVariantNeeded should return true if the module needs a debug ramdisk variant (installed on the 57 // debug ramdisk partition: $(PRODUCT_OUT)/debug_ramdisk). 58 DebugRamdiskVariantNeeded(ctx ImageInterfaceContext) bool 59 60 // RecoveryVariantNeeded should return true if the module needs a recovery variant (installed on the 61 // recovery partition). 62 RecoveryVariantNeeded(ctx ImageInterfaceContext) bool 63 64 // ExtraImageVariations should return a list of the additional variations needed for the module. After the 65 // variants are created the SetImageVariation method will be called on each newly created variant with the 66 // its variation. 67 ExtraImageVariations(ctx ImageInterfaceContext) []string 68 69 // SetImageVariation is called for each newly created image variant. The receiver is the original 70 // module, "variation" is the name of the newly created variant. "variation" is set on the receiver. 71 SetImageVariation(ctx ImageInterfaceContext, variation string) 72} 73 74const ( 75 // VendorVariation is the variant name used for /vendor code that does not 76 // compile against the VNDK. 77 VendorVariation string = "vendor" 78 79 // ProductVariation is the variant name used for /product code that does not 80 // compile against the VNDK. 81 ProductVariation string = "product" 82 83 // CoreVariation is the variant used for framework-private libraries, or 84 // SDK libraries. (which framework-private libraries can use), which 85 // will be installed to the system image. 86 CoreVariation string = "" 87 88 // RecoveryVariation means a module to be installed to recovery image. 89 RecoveryVariation string = "recovery" 90 91 // RamdiskVariation means a module to be installed to ramdisk image. 92 RamdiskVariation string = "ramdisk" 93 94 // VendorRamdiskVariation means a module to be installed to vendor ramdisk image. 95 VendorRamdiskVariation string = "vendor_ramdisk" 96 97 // DebugRamdiskVariation means a module to be installed to debug ramdisk image. 98 DebugRamdiskVariation string = "debug_ramdisk" 99) 100 101type imageInterfaceContextAdapter struct { 102 IncomingTransitionContext 103 kind moduleKind 104} 105 106var _ ImageInterfaceContext = (*imageInterfaceContextAdapter)(nil) 107 108func (e *imageInterfaceContextAdapter) Platform() bool { 109 return e.kind == platformModule 110} 111 112func (e *imageInterfaceContextAdapter) DeviceSpecific() bool { 113 return e.kind == deviceSpecificModule 114} 115 116func (e *imageInterfaceContextAdapter) SocSpecific() bool { 117 return e.kind == socSpecificModule 118} 119 120func (e *imageInterfaceContextAdapter) ProductSpecific() bool { 121 return e.kind == productSpecificModule 122} 123 124func (e *imageInterfaceContextAdapter) SystemExtSpecific() bool { 125 return e.kind == systemExtSpecificModule 126} 127 128// imageMutatorBeginMutator calls ImageMutatorBegin on all modules that may have image variants. 129// This happens right before the imageTransitionMutator runs. It's needed to initialize these 130// modules so that they return the correct results for all the other ImageInterface methods, 131// which the imageTransitionMutator will call. Transition mutators should also not mutate modules 132// (except in their Mutate() function), which this method does, so we run it in a separate mutator 133// first. 134func imageMutatorBeginMutator(ctx BottomUpMutatorContext) { 135 if m, ok := ctx.Module().(ImageInterface); ok && ctx.Os() == Android { 136 m.ImageMutatorBegin(ctx) 137 } 138} 139 140// imageTransitionMutator creates variants for modules that implement the ImageInterface that 141// allow them to build differently for each partition (recovery, core, vendor, etc.). 142type imageTransitionMutator struct{} 143 144func getImageVariations(ctx ImageInterfaceContext) []string { 145 var variations []string 146 147 if m, ok := ctx.Module().(ImageInterface); ctx.Os() == Android && ok { 148 if m.CoreVariantNeeded(ctx) { 149 variations = append(variations, CoreVariation) 150 } 151 if m.RamdiskVariantNeeded(ctx) { 152 variations = append(variations, RamdiskVariation) 153 } 154 if m.VendorRamdiskVariantNeeded(ctx) { 155 variations = append(variations, VendorRamdiskVariation) 156 } 157 if m.DebugRamdiskVariantNeeded(ctx) { 158 variations = append(variations, DebugRamdiskVariation) 159 } 160 if m.RecoveryVariantNeeded(ctx) { 161 variations = append(variations, RecoveryVariation) 162 } 163 if m.VendorVariantNeeded(ctx) { 164 variations = append(variations, VendorVariation) 165 } 166 if m.ProductVariantNeeded(ctx) { 167 variations = append(variations, ProductVariation) 168 } 169 170 extraVariations := m.ExtraImageVariations(ctx) 171 variations = append(variations, extraVariations...) 172 } 173 174 if len(variations) == 0 { 175 variations = append(variations, "") 176 } 177 178 return variations 179} 180 181func (imageTransitionMutator) Split(ctx BaseModuleContext) []string { 182 return getImageVariations(ctx) 183} 184 185func (imageTransitionMutator) OutgoingTransition(ctx OutgoingTransitionContext, sourceVariation string) string { 186 return sourceVariation 187} 188 189func (imageTransitionMutator) IncomingTransition(ctx IncomingTransitionContext, incomingVariation string) string { 190 if _, ok := ctx.Module().(ImageInterface); ctx.Os() != Android || !ok { 191 return CoreVariation 192 } 193 variations := getImageVariations(&imageInterfaceContextAdapter{ 194 IncomingTransitionContext: ctx, 195 kind: determineModuleKind(ctx.Module().base(), ctx), 196 }) 197 // If there's only 1 possible variation, use that. This is a holdover from when blueprint, 198 // when adding dependencies, would use the only variant of a module regardless of its variations 199 // if only 1 variant existed. 200 if len(variations) == 1 { 201 return variations[0] 202 } 203 return incomingVariation 204} 205 206func (imageTransitionMutator) Mutate(ctx BottomUpMutatorContext, variation string) { 207 ctx.Module().base().setImageVariation(variation) 208 if m, ok := ctx.Module().(ImageInterface); ok { 209 m.SetImageVariation(ctx, variation) 210 } 211} 212