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 java
16
17import (
18	"path/filepath"
19	"strings"
20
21	"android/soong/android"
22)
23
24func init() {
25	registerOverlayBuildComponents(android.InitRegistrationContext)
26}
27
28func registerOverlayBuildComponents(ctx android.RegistrationContext) {
29	ctx.RegisterPreSingletonType("overlay", OverlaySingletonFactory)
30}
31
32var androidResourceIgnoreFilenames = []string{
33	".svn",
34	".git",
35	".ds_store",
36	"*.scc",
37	".*",
38	"CVS",
39	"thumbs.db",
40	"picasa.ini",
41	"*~",
42}
43
44// androidResourceGlob returns the list of files in the given directory, using the standard
45// exclusion patterns for Android resources.
46func androidResourceGlob(ctx android.ModuleContext, dir android.Path) android.Paths {
47	return ctx.GlobFiles(filepath.Join(dir.String(), "**/*"), androidResourceIgnoreFilenames)
48}
49
50// androidResourceGlobList creates a rule to write the list of files in the given directory, using
51// the standard exclusion patterns for Android resources, to the given output file.
52func androidResourceGlobList(ctx android.ModuleContext, dir android.Path,
53	fileListFile android.WritablePath) {
54
55	android.GlobToListFileRule(ctx, filepath.Join(dir.String(), "**/*"),
56		androidResourceIgnoreFilenames, fileListFile)
57}
58
59type overlayType int
60
61const (
62	device overlayType = iota + 1
63	product
64)
65
66type rroDir struct {
67	path        android.Path
68	overlayType overlayType
69}
70
71type overlayGlobResult struct {
72	dir         string
73	paths       android.DirectorySortedPaths
74	overlayType overlayType
75}
76
77var overlayDataKey = android.NewOnceKey("overlayDataKey")
78
79type globbedResourceDir struct {
80	dir   android.Path
81	files android.Paths
82}
83
84func overlayResourceGlob(ctx android.ModuleContext, a *aapt, dir android.Path) (res []globbedResourceDir,
85	rroDirs []rroDir) {
86
87	overlayData := ctx.Config().Get(overlayDataKey).([]overlayGlobResult)
88
89	// Runtime resource overlays (RRO) may be turned on by the product config for some modules
90	rroEnabled := a.IsRROEnforced(ctx)
91
92	for _, data := range overlayData {
93		files := data.paths.PathsInDirectory(filepath.Join(data.dir, dir.String()))
94		if len(files) > 0 {
95			overlayModuleDir := android.PathForSource(ctx, data.dir, dir.String())
96
97			// If enforce RRO is enabled for this module and this overlay is not in the
98			// exclusion list, ignore the overlay.  The list of ignored overlays will be
99			// passed to Make to be turned into an RRO package.
100			if rroEnabled && !ctx.Config().EnforceRROExcludedOverlay(overlayModuleDir.String()) {
101				rroDirs = append(rroDirs, rroDir{overlayModuleDir, data.overlayType})
102			} else {
103				res = append(res, globbedResourceDir{
104					dir:   overlayModuleDir,
105					files: files,
106				})
107			}
108		}
109	}
110
111	return res, rroDirs
112}
113
114func OverlaySingletonFactory() android.Singleton {
115	return overlaySingleton{}
116}
117
118type overlaySingleton struct{}
119
120func (overlaySingleton) GenerateBuildActions(ctx android.SingletonContext) {
121	var overlayData []overlayGlobResult
122
123	appendOverlayData := func(overlayDirs []string, t overlayType) {
124		for i := range overlayDirs {
125			// Iterate backwards through the list of overlay directories so that the later, lower-priority
126			// directories in the list show up earlier in the command line to aapt2.
127			overlay := overlayDirs[len(overlayDirs)-1-i]
128			var result overlayGlobResult
129			result.dir = overlay
130			result.overlayType = t
131
132			files, err := ctx.GlobWithDeps(filepath.Join(overlay, "**/*"), androidResourceIgnoreFilenames)
133			if err != nil {
134				ctx.Errorf("failed to glob resource dir %q: %s", overlay, err.Error())
135				continue
136			}
137			var paths android.Paths
138			for _, f := range files {
139				if !strings.HasSuffix(f, "/") {
140					paths = append(paths, android.PathForSource(ctx, f))
141				}
142			}
143			result.paths = android.PathsToDirectorySortedPaths(paths)
144			overlayData = append(overlayData, result)
145		}
146	}
147
148	appendOverlayData(ctx.Config().DeviceResourceOverlays(), device)
149	appendOverlayData(ctx.Config().ProductResourceOverlays(), product)
150	ctx.Config().Once(overlayDataKey, func() interface{} {
151		return overlayData
152	})
153}
154