blob: 4daed7c0045154d1f787d0048dc6a216270af699 [file] [log] [blame]
Inseob Kime498dd92020-08-04 09:24:04 +09001// 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
25var _ android.ImageInterface = (*Module)(nil)
26
Inseob Kim74d25562020-08-04 00:41:38 +090027type imageVariantType string
28
29const (
30 coreImageVariant imageVariantType = "core"
31 vendorImageVariant imageVariantType = "vendor"
32 productImageVariant imageVariantType = "product"
33 ramdiskImageVariant imageVariantType = "ramdisk"
34 recoveryImageVariant imageVariantType = "recovery"
35 hostImageVariant imageVariantType = "host"
36)
37
38func (c *Module) getImageVariantType() imageVariantType {
39 if c.Host() {
40 return hostImageVariant
41 } else if c.inVendor() {
42 return vendorImageVariant
43 } else if c.inProduct() {
44 return productImageVariant
45 } else if c.InRamdisk() {
46 return ramdiskImageVariant
47 } else if c.InRecovery() {
48 return recoveryImageVariant
49 } else {
50 return coreImageVariant
51 }
52}
53
Inseob Kime498dd92020-08-04 09:24:04 +090054const (
55 // VendorVariationPrefix is the variant prefix used for /vendor code that compiles
56 // against the VNDK.
57 VendorVariationPrefix = "vendor."
58
59 // ProductVariationPrefix is the variant prefix used for /product code that compiles
60 // against the VNDK.
61 ProductVariationPrefix = "product."
62)
63
64func (ctx *moduleContext) ProductSpecific() bool {
65 return ctx.ModuleContext.ProductSpecific() ||
66 (ctx.mod.HasVendorVariant() && ctx.mod.inProduct() && !ctx.mod.IsVndk())
67}
68
69func (ctx *moduleContext) SocSpecific() bool {
70 return ctx.ModuleContext.SocSpecific() ||
71 (ctx.mod.HasVendorVariant() && ctx.mod.inVendor() && !ctx.mod.IsVndk())
72}
73
74func (ctx *moduleContextImpl) inProduct() bool {
75 return ctx.mod.inProduct()
76}
77
78func (ctx *moduleContextImpl) inVendor() bool {
79 return ctx.mod.inVendor()
80}
81
82func (ctx *moduleContextImpl) inRamdisk() bool {
83 return ctx.mod.InRamdisk()
84}
85
86func (ctx *moduleContextImpl) inRecovery() bool {
87 return ctx.mod.InRecovery()
88}
89
90// Returns true only when this module is configured to have core, product and vendor
91// variants.
92func (c *Module) HasVendorVariant() bool {
93 return c.IsVndk() || Bool(c.VendorProperties.Vendor_available)
94}
95
96// Returns true if the module is "product" variant. Usually these modules are installed in /product
97func (c *Module) inProduct() bool {
98 return c.Properties.ImageVariationPrefix == ProductVariationPrefix
99}
100
101// Returns true if the module is "vendor" variant. Usually these modules are installed in /vendor
102func (c *Module) inVendor() bool {
103 return c.Properties.ImageVariationPrefix == VendorVariationPrefix
104}
105
106func (c *Module) InRamdisk() bool {
107 return c.ModuleBase.InRamdisk() || c.ModuleBase.InstallInRamdisk()
108}
109
110func (c *Module) InRecovery() bool {
111 return c.ModuleBase.InRecovery() || c.ModuleBase.InstallInRecovery()
112}
113
114func (c *Module) OnlyInRamdisk() bool {
115 return c.ModuleBase.InstallInRamdisk()
116}
117
118func (c *Module) OnlyInRecovery() bool {
119 return c.ModuleBase.InstallInRecovery()
120}
121
122func (m *Module) ImageMutatorBegin(mctx android.BaseModuleContext) {
123 // Validation check
124 vendorSpecific := mctx.SocSpecific() || mctx.DeviceSpecific()
125 productSpecific := mctx.ProductSpecific()
126
127 if m.VendorProperties.Vendor_available != nil && vendorSpecific {
128 mctx.PropertyErrorf("vendor_available",
129 "doesn't make sense at the same time as `vendor: true`, `proprietary: true`, or `device_specific:true`")
130 }
131
132 if vndkdep := m.vndkdep; vndkdep != nil {
133 if vndkdep.isVndk() {
134 if vendorSpecific || productSpecific {
135 if !vndkdep.isVndkExt() {
136 mctx.PropertyErrorf("vndk",
137 "must set `extends: \"...\"` to vndk extension")
138 } else if m.VendorProperties.Vendor_available != nil {
139 mctx.PropertyErrorf("vendor_available",
140 "must not set at the same time as `vndk: {extends: \"...\"}`")
141 }
142 } else {
143 if vndkdep.isVndkExt() {
144 mctx.PropertyErrorf("vndk",
145 "must set `vendor: true` or `product_specific: true` to set `extends: %q`",
146 m.getVndkExtendsModuleName())
147 }
148 if m.VendorProperties.Vendor_available == nil {
149 mctx.PropertyErrorf("vndk",
150 "vendor_available must be set to either true or false when `vndk: {enabled: true}`")
151 }
152 }
153 } else {
154 if vndkdep.isVndkSp() {
155 mctx.PropertyErrorf("vndk",
156 "must set `enabled: true` to set `support_system_process: true`")
157 }
158 if vndkdep.isVndkExt() {
159 mctx.PropertyErrorf("vndk",
160 "must set `enabled: true` to set `extends: %q`",
161 m.getVndkExtendsModuleName())
162 }
163 }
164 }
165
166 var coreVariantNeeded bool = false
167 var ramdiskVariantNeeded bool = false
168 var recoveryVariantNeeded bool = false
169
170 var vendorVariants []string
171 var productVariants []string
172
173 platformVndkVersion := mctx.DeviceConfig().PlatformVndkVersion()
174 boardVndkVersion := mctx.DeviceConfig().VndkVersion()
175 productVndkVersion := mctx.DeviceConfig().ProductVndkVersion()
176 if boardVndkVersion == "current" {
177 boardVndkVersion = platformVndkVersion
178 }
179 if productVndkVersion == "current" {
180 productVndkVersion = platformVndkVersion
181 }
182
183 if boardVndkVersion == "" {
184 // If the device isn't compiling against the VNDK, we always
185 // use the core mode.
186 coreVariantNeeded = true
187 } else if _, ok := m.linker.(*llndkStubDecorator); ok {
188 // LL-NDK stubs only exist in the vendor and product variants,
189 // since the real libraries will be used in the core variant.
190 vendorVariants = append(vendorVariants,
191 platformVndkVersion,
192 boardVndkVersion,
193 )
194 productVariants = append(productVariants,
195 platformVndkVersion,
196 productVndkVersion,
197 )
198 } else if _, ok := m.linker.(*llndkHeadersDecorator); ok {
199 // ... and LL-NDK headers as well
200 vendorVariants = append(vendorVariants,
201 platformVndkVersion,
202 boardVndkVersion,
203 )
204 productVariants = append(productVariants,
205 platformVndkVersion,
206 productVndkVersion,
207 )
208 } else if m.isSnapshotPrebuilt() {
209 // Make vendor variants only for the versions in BOARD_VNDK_VERSION and
210 // PRODUCT_EXTRA_VNDK_VERSIONS.
211 if snapshot, ok := m.linker.(interface {
212 version() string
213 }); ok {
214 vendorVariants = append(vendorVariants, snapshot.version())
215 } else {
216 mctx.ModuleErrorf("version is unknown for snapshot prebuilt")
217 }
218 } else if m.HasVendorVariant() && !m.isVndkExt() {
219 // This will be available in /system, /vendor and /product
220 // or a /system directory that is available to vendor and product.
221 coreVariantNeeded = true
222
223 // We assume that modules under proprietary paths are compatible for
224 // BOARD_VNDK_VERSION. The other modules are regarded as AOSP, or
225 // PLATFORM_VNDK_VERSION.
226 if isVendorProprietaryPath(mctx.ModuleDir()) {
227 vendorVariants = append(vendorVariants, boardVndkVersion)
228 } else {
229 vendorVariants = append(vendorVariants, platformVndkVersion)
230 }
231
232 // vendor_available modules are also available to /product.
233 productVariants = append(productVariants, platformVndkVersion)
234 // VNDK is always PLATFORM_VNDK_VERSION
235 if !m.IsVndk() {
236 productVariants = append(productVariants, productVndkVersion)
237 }
238 } else if vendorSpecific && String(m.Properties.Sdk_version) == "" {
239 // This will be available in /vendor (or /odm) only
240
241 // kernel_headers is a special module type whose exported headers
242 // are coming from DeviceKernelHeaders() which is always vendor
243 // dependent. They'll always have both vendor variants.
244 // For other modules, we assume that modules under proprietary
245 // paths are compatible for BOARD_VNDK_VERSION. The other modules
246 // are regarded as AOSP, which is PLATFORM_VNDK_VERSION.
247 if _, ok := m.linker.(*kernelHeadersDecorator); ok {
248 vendorVariants = append(vendorVariants,
249 platformVndkVersion,
250 boardVndkVersion,
251 )
252 } else if isVendorProprietaryPath(mctx.ModuleDir()) {
253 vendorVariants = append(vendorVariants, boardVndkVersion)
254 } else {
255 vendorVariants = append(vendorVariants, platformVndkVersion)
256 }
257 } else {
258 // This is either in /system (or similar: /data), or is a
259 // modules built with the NDK. Modules built with the NDK
260 // will be restricted using the existing link type checks.
261 coreVariantNeeded = true
262 }
263
264 if boardVndkVersion != "" && productVndkVersion != "" {
265 if coreVariantNeeded && productSpecific && String(m.Properties.Sdk_version) == "" {
266 // The module has "product_specific: true" that does not create core variant.
267 coreVariantNeeded = false
268 productVariants = append(productVariants, productVndkVersion)
269 }
270 } else {
271 // Unless PRODUCT_PRODUCT_VNDK_VERSION is set, product partition has no
272 // restriction to use system libs.
273 // No product variants defined in this case.
274 productVariants = []string{}
275 }
276
277 if Bool(m.Properties.Ramdisk_available) {
278 ramdiskVariantNeeded = true
279 }
280
281 if m.ModuleBase.InstallInRamdisk() {
282 ramdiskVariantNeeded = true
283 coreVariantNeeded = false
284 }
285
286 if Bool(m.Properties.Recovery_available) {
287 recoveryVariantNeeded = true
288 }
289
290 if m.ModuleBase.InstallInRecovery() {
291 recoveryVariantNeeded = true
292 coreVariantNeeded = false
293 }
294
295 for _, variant := range android.FirstUniqueStrings(vendorVariants) {
296 m.Properties.ExtraVariants = append(m.Properties.ExtraVariants, VendorVariationPrefix+variant)
297 }
298
299 for _, variant := range android.FirstUniqueStrings(productVariants) {
300 m.Properties.ExtraVariants = append(m.Properties.ExtraVariants, ProductVariationPrefix+variant)
301 }
302
303 m.Properties.RamdiskVariantNeeded = ramdiskVariantNeeded
304 m.Properties.RecoveryVariantNeeded = recoveryVariantNeeded
305 m.Properties.CoreVariantNeeded = coreVariantNeeded
306}
307
308func (c *Module) CoreVariantNeeded(ctx android.BaseModuleContext) bool {
309 return c.Properties.CoreVariantNeeded
310}
311
312func (c *Module) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
313 return c.Properties.RamdiskVariantNeeded
314}
315
316func (c *Module) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool {
317 return c.Properties.RecoveryVariantNeeded
318}
319
320func (c *Module) ExtraImageVariations(ctx android.BaseModuleContext) []string {
321 return c.Properties.ExtraVariants
322}
323
324func (c *Module) SetImageVariation(ctx android.BaseModuleContext, variant string, module android.Module) {
325 m := module.(*Module)
326 if variant == android.RamdiskVariation {
327 m.MakeAsPlatform()
328 } else if variant == android.RecoveryVariation {
329 m.MakeAsPlatform()
330 squashRecoverySrcs(m)
331 } else if strings.HasPrefix(variant, VendorVariationPrefix) {
332 m.Properties.ImageVariationPrefix = VendorVariationPrefix
333 m.Properties.VndkVersion = strings.TrimPrefix(variant, VendorVariationPrefix)
334 squashVendorSrcs(m)
335
336 // Makefile shouldn't know vendor modules other than BOARD_VNDK_VERSION.
337 // Hide other vendor variants to avoid collision.
338 vndkVersion := ctx.DeviceConfig().VndkVersion()
339 if vndkVersion != "current" && vndkVersion != "" && vndkVersion != m.Properties.VndkVersion {
340 m.Properties.HideFromMake = true
341 m.SkipInstall()
342 }
343 } else if strings.HasPrefix(variant, ProductVariationPrefix) {
344 m.Properties.ImageVariationPrefix = ProductVariationPrefix
345 m.Properties.VndkVersion = strings.TrimPrefix(variant, ProductVariationPrefix)
346 squashVendorSrcs(m)
347 }
348}