• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2018 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
17import (
18	"sort"
19	"sync"
20
21	"github.com/google/blueprint"
22)
23
24// ApexModule is the interface that a module type is expected to implement if
25// the module has to be built differently depending on whether the module
26// is destined for an apex or not (installed to one of the regular partitions).
27//
28// Native shared libraries are one such module type; when it is built for an
29// APEX, it should depend only on stable interfaces such as NDK, stable AIDL,
30// or C APIs from other APEXs.
31//
32// A module implementing this interface will be mutated into multiple
33// variations by apex.apexMutator if it is directly or indirectly included
34// in one or more APEXs. Specifically, if a module is included in apex.foo and
35// apex.bar then three apex variants are created: platform, apex.foo and
36// apex.bar. The platform variant is for the regular partitions
37// (e.g., /system or /vendor, etc.) while the other two are for the APEXs,
38// respectively.
39type ApexModule interface {
40	Module
41	apexModuleBase() *ApexModuleBase
42
43	// Marks that this module should be built for the APEX of the specified name.
44	// Call this before apex.apexMutator is run.
45	BuildForApex(apexName string)
46
47	// Returns the name of APEX that this module will be built for. Empty string
48	// is returned when 'IsForPlatform() == true'. Note that a module can be
49	// included in multiple APEXes, in which case, the module is mutated into
50	// multiple modules each of which for an APEX. This method returns the
51	// name of the APEX that a variant module is for.
52	// Call this after apex.apexMutator is run.
53	ApexName() string
54
55	// Tests whether this module will be built for the platform or not.
56	// This is a shortcut for ApexName() == ""
57	IsForPlatform() bool
58
59	// Tests if this module could have APEX variants. APEX variants are
60	// created only for the modules that returns true here. This is useful
61	// for not creating APEX variants for certain types of shared libraries
62	// such as NDK stubs.
63	CanHaveApexVariants() bool
64
65	// Tests if this module can be installed to APEX as a file. For example,
66	// this would return true for shared libs while return false for static
67	// libs.
68	IsInstallableToApex() bool
69
70	// Mutate this module into one or more variants each of which is built
71	// for an APEX marked via BuildForApex().
72	CreateApexVariations(mctx BottomUpMutatorContext) []blueprint.Module
73
74	// Sets the name of the apex variant of this module. Called inside
75	// CreateApexVariations.
76	setApexName(apexName string)
77}
78
79type ApexProperties struct {
80	// Name of the apex variant that this module is mutated into
81	ApexName string `blueprint:"mutated"`
82}
83
84// Provides default implementation for the ApexModule interface. APEX-aware
85// modules are expected to include this struct and call InitApexModule().
86type ApexModuleBase struct {
87	ApexProperties ApexProperties
88
89	canHaveApexVariants bool
90
91	apexVariationsLock sync.Mutex // protects apexVariations during parallel apexDepsMutator
92	apexVariations     []string
93}
94
95func (m *ApexModuleBase) apexModuleBase() *ApexModuleBase {
96	return m
97}
98
99func (m *ApexModuleBase) BuildForApex(apexName string) {
100	m.apexVariationsLock.Lock()
101	defer m.apexVariationsLock.Unlock()
102	if !InList(apexName, m.apexVariations) {
103		m.apexVariations = append(m.apexVariations, apexName)
104	}
105}
106
107func (m *ApexModuleBase) ApexName() string {
108	return m.ApexProperties.ApexName
109}
110
111func (m *ApexModuleBase) IsForPlatform() bool {
112	return m.ApexProperties.ApexName == ""
113}
114
115func (m *ApexModuleBase) setApexName(apexName string) {
116	m.ApexProperties.ApexName = apexName
117}
118
119func (m *ApexModuleBase) CanHaveApexVariants() bool {
120	return m.canHaveApexVariants
121}
122
123func (m *ApexModuleBase) IsInstallableToApex() bool {
124	// should be overriden if needed
125	return false
126}
127
128func (m *ApexModuleBase) CreateApexVariations(mctx BottomUpMutatorContext) []blueprint.Module {
129	if len(m.apexVariations) > 0 {
130		sort.Strings(m.apexVariations)
131		variations := []string{""} // Original variation for platform
132		variations = append(variations, m.apexVariations...)
133
134		modules := mctx.CreateVariations(variations...)
135		for i, m := range modules {
136			if i == 0 {
137				continue
138			}
139			m.(ApexModule).setApexName(variations[i])
140		}
141		return modules
142	}
143	return nil
144}
145
146var apexData OncePer
147var apexNamesMapMutex sync.Mutex
148var apexNamesKey = NewOnceKey("apexNames")
149
150// This structure maintains the global mapping in between modules and APEXes.
151// Examples:
152//
153// apexNamesMap()["foo"]["bar"] == true: module foo is directly depended on by APEX bar
154// apexNamesMap()["foo"]["bar"] == false: module foo is indirectly depended on by APEX bar
155// apexNamesMap()["foo"]["bar"] doesn't exist: foo is not built for APEX bar
156func apexNamesMap() map[string]map[string]bool {
157	return apexData.Once(apexNamesKey, func() interface{} {
158		return make(map[string]map[string]bool)
159	}).(map[string]map[string]bool)
160}
161
162// Update the map to mark that a module named moduleName is directly or indirectly
163// depended on by an APEX named apexName. Directly depending means that a module
164// is explicitly listed in the build definition of the APEX via properties like
165// native_shared_libs, java_libs, etc.
166func UpdateApexDependency(apexName string, moduleName string, directDep bool) {
167	apexNamesMapMutex.Lock()
168	defer apexNamesMapMutex.Unlock()
169	apexNames, ok := apexNamesMap()[moduleName]
170	if !ok {
171		apexNames = make(map[string]bool)
172		apexNamesMap()[moduleName] = apexNames
173	}
174	apexNames[apexName] = apexNames[apexName] || directDep
175}
176
177// Tests whether a module named moduleName is directly depended on by an APEX
178// named apexName.
179func DirectlyInApex(apexName string, moduleName string) bool {
180	apexNamesMapMutex.Lock()
181	defer apexNamesMapMutex.Unlock()
182	if apexNames, ok := apexNamesMap()[moduleName]; ok {
183		return apexNames[apexName]
184	}
185	return false
186}
187
188type hostContext interface {
189	Host() bool
190}
191
192// Tests whether a module named moduleName is directly depended on by any APEX.
193func DirectlyInAnyApex(ctx hostContext, moduleName string) bool {
194	if ctx.Host() {
195		// Host has no APEX.
196		return false
197	}
198	apexNamesMapMutex.Lock()
199	defer apexNamesMapMutex.Unlock()
200	if apexNames, ok := apexNamesMap()[moduleName]; ok {
201		for an := range apexNames {
202			if apexNames[an] {
203				return true
204			}
205		}
206	}
207	return false
208}
209
210// Tests whether a module named module is depended on (including both
211// direct and indirect dependencies) by any APEX.
212func InAnyApex(moduleName string) bool {
213	apexNamesMapMutex.Lock()
214	defer apexNamesMapMutex.Unlock()
215	apexNames, ok := apexNamesMap()[moduleName]
216	return ok && len(apexNames) > 0
217}
218
219func GetApexesForModule(moduleName string) []string {
220	ret := []string{}
221	apexNamesMapMutex.Lock()
222	defer apexNamesMapMutex.Unlock()
223	if apexNames, ok := apexNamesMap()[moduleName]; ok {
224		for an := range apexNames {
225			ret = append(ret, an)
226		}
227	}
228	return ret
229}
230
231func InitApexModule(m ApexModule) {
232	base := m.apexModuleBase()
233	base.canHaveApexVariants = true
234
235	m.AddProperties(&base.ApexProperties)
236}
237