blob: 48e77465a613cfb4f4aa4ec1712f08872b7a2c5b [file] [log] [blame]
Colin Crossfb6d7812019-01-09 22:17:55 -08001// 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 "android/soong/android"
19 "android/soong/java/config"
20 "fmt"
21 "path/filepath"
Colin Cross98fd5742019-01-09 23:04:25 -080022 "sort"
Colin Crossfb6d7812019-01-09 22:17:55 -080023 "strconv"
24 "strings"
25)
26
Colin Cross98fd5742019-01-09 23:04:25 -080027func init() {
28 android.RegisterPreSingletonType("sdk", sdkSingletonFactory)
29}
30
Colin Cross571cccf2019-02-04 11:22:08 -080031var sdkSingletonKey = android.NewOnceKey("sdkSingletonKey")
Colin Cross98fd5742019-01-09 23:04:25 -080032
Colin Crossfb6d7812019-01-09 22:17:55 -080033type sdkContext interface {
34 // sdkVersion eturns the sdk_version property of the current module, or an empty string if it is not set.
35 sdkVersion() string
36 // minSdkVersion returns the min_sdk_version property of the current module, or sdkVersion() if it is not set.
37 minSdkVersion() string
38 // targetSdkVersion returns the target_sdk_version property of the current module, or sdkVersion() if it is not set.
39 targetSdkVersion() string
40}
41
42func sdkVersionOrDefault(ctx android.BaseContext, v string) string {
43 switch v {
44 case "", "current", "system_current", "test_current", "core_current":
45 return ctx.Config().DefaultAppTargetSdk()
46 default:
47 return v
48 }
49}
50
51// Returns a sdk version as a number. For modules targeting an unreleased SDK (meaning it does not yet have a number)
52// it returns android.FutureApiLevel (10000).
53func sdkVersionToNumber(ctx android.BaseContext, v string) (int, error) {
54 switch v {
55 case "", "current", "test_current", "system_current", "core_current":
56 return ctx.Config().DefaultAppTargetSdkInt(), nil
57 default:
58 n := android.GetNumericSdkVersion(v)
59 if i, err := strconv.Atoi(n); err != nil {
60 return -1, fmt.Errorf("invalid sdk version %q", n)
61 } else {
62 return i, nil
63 }
64 }
65}
66
67func sdkVersionToNumberAsString(ctx android.BaseContext, v string) (string, error) {
68 n, err := sdkVersionToNumber(ctx, v)
69 if err != nil {
70 return "", err
71 }
72 return strconv.Itoa(n), nil
73}
74
75func decodeSdkDep(ctx android.BaseContext, sdkContext sdkContext) sdkDep {
76 v := sdkContext.sdkVersion()
Colin Cross98fd5742019-01-09 23:04:25 -080077 // For PDK builds, use the latest SDK version instead of "current"
78 if ctx.Config().IsPdkBuild() && (v == "" || v == "current") {
79 sdkVersions := ctx.Config().Get(sdkSingletonKey).([]int)
80 latestSdkVersion := 0
81 if len(sdkVersions) > 0 {
82 latestSdkVersion = sdkVersions[len(sdkVersions)-1]
83 }
84 v = strconv.Itoa(latestSdkVersion)
85 }
86
Colin Crossff0daf42019-04-02 16:10:56 -070087 numericSdkVersion, err := sdkVersionToNumber(ctx, v)
Colin Crossfb6d7812019-01-09 22:17:55 -080088 if err != nil {
89 ctx.PropertyErrorf("sdk_version", "%s", err)
90 return sdkDep{}
91 }
92
Colin Crossfb6d7812019-01-09 22:17:55 -080093 toPrebuilt := func(sdk string) sdkDep {
94 var api, v string
95 if strings.Contains(sdk, "_") {
96 t := strings.Split(sdk, "_")
97 api = t[0]
98 v = t[1]
99 } else {
100 api = "public"
101 v = sdk
102 }
103 dir := filepath.Join("prebuilts", "sdk", v, api)
104 jar := filepath.Join(dir, "android.jar")
105 // There's no aidl for other SDKs yet.
106 // TODO(77525052): Add aidl files for other SDKs too.
107 public_dir := filepath.Join("prebuilts", "sdk", v, "public")
108 aidl := filepath.Join(public_dir, "framework.aidl")
109 jarPath := android.ExistentPathForSource(ctx, jar)
110 aidlPath := android.ExistentPathForSource(ctx, aidl)
111 lambdaStubsPath := android.PathForSource(ctx, config.SdkLambdaStubsPath)
112
113 if (!jarPath.Valid() || !aidlPath.Valid()) && ctx.Config().AllowMissingDependencies() {
114 return sdkDep{
115 invalidVersion: true,
116 modules: []string{fmt.Sprintf("sdk_%s_%s_android", api, v)},
117 }
118 }
119
120 if !jarPath.Valid() {
121 ctx.PropertyErrorf("sdk_version", "invalid sdk version %q, %q does not exist", v, jar)
122 return sdkDep{}
123 }
124
125 if !aidlPath.Valid() {
126 ctx.PropertyErrorf("sdk_version", "invalid sdk version %q, %q does not exist", v, aidl)
127 return sdkDep{}
128 }
129
130 return sdkDep{
131 useFiles: true,
132 jars: android.Paths{jarPath.Path(), lambdaStubsPath},
133 aidl: aidlPath.Path(),
134 }
135 }
136
137 toModule := func(m, r string) sdkDep {
138 ret := sdkDep{
139 useModule: true,
140 modules: []string{m, config.DefaultLambdaStubsLibrary},
141 systemModules: m + "_system_modules",
142 frameworkResModule: r,
143 }
144 if m == "core.current.stubs" {
145 ret.systemModules = "core-system-modules"
146 } else if m == "core.platform.api.stubs" {
147 ret.systemModules = "core-platform-api-stubs-system-modules"
148 }
149 return ret
150 }
151
Colin Cross98fd5742019-01-09 23:04:25 -0800152 // Ensures that the specificed system SDK version is one of BOARD_SYSTEMSDK_VERSIONS (for vendor apks)
153 // or PRODUCT_SYSTEMSDK_VERSIONS (for other apks or when BOARD_SYSTEMSDK_VERSIONS is not set)
Colin Crossff0daf42019-04-02 16:10:56 -0700154 if strings.HasPrefix(v, "system_") && numericSdkVersion != android.FutureApiLevel {
Colin Cross98fd5742019-01-09 23:04:25 -0800155 allowed_versions := ctx.DeviceConfig().PlatformSystemSdkVersions()
156 if ctx.DeviceSpecific() || ctx.SocSpecific() {
157 if len(ctx.DeviceConfig().SystemSdkVersions()) > 0 {
158 allowed_versions = ctx.DeviceConfig().SystemSdkVersions()
159 }
160 }
Colin Crossff0daf42019-04-02 16:10:56 -0700161 if len(allowed_versions) > 0 && !android.InList(strconv.Itoa(numericSdkVersion), allowed_versions) {
Colin Cross98fd5742019-01-09 23:04:25 -0800162 ctx.PropertyErrorf("sdk_version", "incompatible sdk version %q. System SDK version should be one of %q",
163 v, allowed_versions)
164 }
165 }
166
Colin Crossfb6d7812019-01-09 22:17:55 -0800167 if ctx.Config().UnbundledBuildPrebuiltSdks() && v != "" {
168 return toPrebuilt(v)
169 }
170
171 switch v {
172 case "":
173 return sdkDep{
174 useDefaultLibs: true,
175 frameworkResModule: "framework-res",
176 }
177 case "current":
178 return toModule("android_stubs_current", "framework-res")
179 case "system_current":
180 return toModule("android_system_stubs_current", "framework-res")
181 case "test_current":
182 return toModule("android_test_stubs_current", "framework-res")
183 case "core_current":
184 return toModule("core.current.stubs", "")
185 default:
186 return toPrebuilt(v)
187 }
188}
Colin Cross98fd5742019-01-09 23:04:25 -0800189
190func sdkSingletonFactory() android.Singleton {
191 return sdkSingleton{}
192}
193
194type sdkSingleton struct{}
195
196func (sdkSingleton) GenerateBuildActions(ctx android.SingletonContext) {
197 sdkJars, err := ctx.GlobWithDeps("prebuilts/sdk/*/public/android.jar", nil)
198 if err != nil {
199 ctx.Errorf("failed to glob prebuilts/sdk/*/public/android.jar: %s", err.Error())
200 }
201
202 var sdkVersions []int
203 for _, sdkJar := range sdkJars {
204 dir := filepath.Base(filepath.Dir(filepath.Dir(sdkJar)))
205 v, err := strconv.Atoi(dir)
206 if scerr, ok := err.(*strconv.NumError); ok && scerr.Err == strconv.ErrSyntax {
207 continue
208 } else if err != nil {
209 ctx.Errorf("invalid sdk jar %q, %s, %v", sdkJar, err.Error())
210 }
211 sdkVersions = append(sdkVersions, v)
212 }
213
214 sort.Ints(sdkVersions)
215
216 ctx.Config().Once(sdkSingletonKey, func() interface{} { return sdkVersions })
217}