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 java
16
17import (
18	"fmt"
19	"io"
20
21	"android/soong/android"
22)
23
24type DeviceHostConverter struct {
25	android.ModuleBase
26	android.DefaultableModuleBase
27
28	properties DeviceHostConverterProperties
29
30	headerJars                    android.Paths
31	implementationJars            android.Paths
32	implementationAndResourceJars android.Paths
33	resourceJars                  android.Paths
34
35	srcJarArgs []string
36	srcJarDeps android.Paths
37
38	combinedHeaderJar         android.Path
39	combinedImplementationJar android.Path
40}
41
42type DeviceHostConverterProperties struct {
43	// List of modules whose contents will be visible to modules that depend on this module.
44	Libs []string
45}
46
47type DeviceForHost struct {
48	DeviceHostConverter
49}
50
51// java_device_for_host makes the classes.jar output of a device java_library module available to host
52// java_library modules.
53//
54// It is rarely necessary, and its usage is restricted to a few allowed projects.
55func DeviceForHostFactory() android.Module {
56	module := &DeviceForHost{}
57
58	module.AddProperties(&module.properties)
59
60	InitJavaModule(module, android.HostSupported)
61	return module
62}
63
64type HostForDevice struct {
65	DeviceHostConverter
66}
67
68// java_host_for_device makes the classes.jar output of a host java_library module available to device
69// java_library modules.
70//
71// It is rarely necessary, and its usage is restricted to a few allowed projects.
72func HostForDeviceFactory() android.Module {
73	module := &HostForDevice{}
74
75	module.AddProperties(&module.properties)
76
77	InitJavaModule(module, android.DeviceSupported)
78	return module
79}
80
81var deviceHostConverterDepTag = dependencyTag{name: "device_host_converter"}
82
83func (d *DeviceForHost) DepsMutator(ctx android.BottomUpMutatorContext) {
84	ctx.AddFarVariationDependencies(ctx.Config().AndroidCommonTarget.Variations(),
85		deviceHostConverterDepTag, d.properties.Libs...)
86}
87
88func (d *HostForDevice) DepsMutator(ctx android.BottomUpMutatorContext) {
89	ctx.AddFarVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(),
90		deviceHostConverterDepTag, d.properties.Libs...)
91}
92
93func (d *DeviceHostConverter) GenerateAndroidBuildActions(ctx android.ModuleContext) {
94	if len(d.properties.Libs) < 1 {
95		ctx.PropertyErrorf("libs", "at least one dependency is required")
96	}
97
98	ctx.VisitDirectDepsWithTag(deviceHostConverterDepTag, func(m android.Module) {
99		if dep, ok := m.(Dependency); ok {
100			d.headerJars = append(d.headerJars, dep.HeaderJars()...)
101			d.implementationJars = append(d.implementationJars, dep.ImplementationJars()...)
102			d.implementationAndResourceJars = append(d.implementationAndResourceJars, dep.ImplementationAndResourcesJars()...)
103			d.resourceJars = append(d.resourceJars, dep.ResourceJars()...)
104
105			srcJarArgs, srcJarDeps := dep.SrcJarArgs()
106			d.srcJarArgs = append(d.srcJarArgs, srcJarArgs...)
107			d.srcJarDeps = append(d.srcJarDeps, srcJarDeps...)
108		} else {
109			ctx.PropertyErrorf("libs", "module %q cannot be used as a dependency", ctx.OtherModuleName(m))
110		}
111	})
112
113	jarName := ctx.ModuleName() + ".jar"
114
115	if len(d.implementationAndResourceJars) > 1 {
116		outputFile := android.PathForModuleOut(ctx, "combined", jarName)
117		TransformJarsToJar(ctx, outputFile, "combine", d.implementationAndResourceJars,
118			android.OptionalPath{}, false, nil, nil)
119		d.combinedImplementationJar = outputFile
120	} else {
121		d.combinedImplementationJar = d.implementationAndResourceJars[0]
122	}
123
124	if len(d.headerJars) > 1 {
125		outputFile := android.PathForModuleOut(ctx, "turbine-combined", jarName)
126		TransformJarsToJar(ctx, outputFile, "turbine combine", d.headerJars,
127			android.OptionalPath{}, false, nil, []string{"META-INF/TRANSITIVE"})
128		d.combinedHeaderJar = outputFile
129	} else {
130		d.combinedHeaderJar = d.headerJars[0]
131	}
132
133}
134
135var _ Dependency = (*DeviceHostConverter)(nil)
136
137func (d *DeviceHostConverter) HeaderJars() android.Paths {
138	return d.headerJars
139}
140
141func (d *DeviceHostConverter) ImplementationJars() android.Paths {
142	return d.implementationJars
143}
144
145func (d *DeviceHostConverter) ResourceJars() android.Paths {
146	return d.resourceJars
147}
148
149func (d *DeviceHostConverter) ImplementationAndResourcesJars() android.Paths {
150	return d.implementationAndResourceJars
151}
152
153func (d *DeviceHostConverter) DexJarBuildPath() android.Path {
154	return nil
155}
156
157func (d *DeviceHostConverter) DexJarInstallPath() android.Path {
158	return nil
159}
160
161func (d *DeviceHostConverter) AidlIncludeDirs() android.Paths {
162	return nil
163}
164
165func (d *DeviceHostConverter) ExportedSdkLibs() []string {
166	return nil
167}
168
169func (d *DeviceHostConverter) ExportedPlugins() (android.Paths, []string) {
170	return nil, nil
171}
172
173func (d *DeviceHostConverter) SrcJarArgs() ([]string, android.Paths) {
174	return d.srcJarArgs, d.srcJarDeps
175}
176
177func (d *DeviceHostConverter) JacocoReportClassesFile() android.Path {
178	return nil
179}
180
181func (d *DeviceHostConverter) AndroidMk() android.AndroidMkData {
182	return android.AndroidMkData{
183		Class:      "JAVA_LIBRARIES",
184		OutputFile: android.OptionalPathForPath(d.combinedImplementationJar),
185		Include:    "$(BUILD_SYSTEM)/soong_java_prebuilt.mk",
186		Extra: []android.AndroidMkExtraFunc{
187			func(w io.Writer, outputFile android.Path) {
188				fmt.Fprintln(w, "LOCAL_UNINSTALLABLE_MODULE := true")
189				fmt.Fprintln(w, "LOCAL_SOONG_HEADER_JAR :=", d.combinedHeaderJar.String())
190				fmt.Fprintln(w, "LOCAL_SOONG_CLASSES_JAR :=", d.combinedImplementationJar.String())
191			},
192		},
193	}
194}
195