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