blob: 988610f5baf8ee39e13ea4381f1e76ffd0602f38 [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
31const sdkSingletonKey = "sdkSingletonKey"
32
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 Crossfb6d7812019-01-09 22:17:55 -080087 i, err := sdkVersionToNumber(ctx, v)
88 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)
154 if strings.HasPrefix(v, "system_") && i != android.FutureApiLevel {
155 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 }
161 version := strings.TrimPrefix(v, "system_")
162 if len(allowed_versions) > 0 && !android.InList(version, allowed_versions) {
163 ctx.PropertyErrorf("sdk_version", "incompatible sdk version %q. System SDK version should be one of %q",
164 v, allowed_versions)
165 }
166 }
167
Colin Crossfb6d7812019-01-09 22:17:55 -0800168 if ctx.Config().UnbundledBuildPrebuiltSdks() && v != "" {
169 return toPrebuilt(v)
170 }
171
172 switch v {
173 case "":
174 return sdkDep{
175 useDefaultLibs: true,
176 frameworkResModule: "framework-res",
177 }
178 case "current":
179 return toModule("android_stubs_current", "framework-res")
180 case "system_current":
181 return toModule("android_system_stubs_current", "framework-res")
182 case "test_current":
183 return toModule("android_test_stubs_current", "framework-res")
184 case "core_current":
185 return toModule("core.current.stubs", "")
186 default:
187 return toPrebuilt(v)
188 }
189}
Colin Cross98fd5742019-01-09 23:04:25 -0800190
191func sdkSingletonFactory() android.Singleton {
192 return sdkSingleton{}
193}
194
195type sdkSingleton struct{}
196
197func (sdkSingleton) GenerateBuildActions(ctx android.SingletonContext) {
198 sdkJars, err := ctx.GlobWithDeps("prebuilts/sdk/*/public/android.jar", nil)
199 if err != nil {
200 ctx.Errorf("failed to glob prebuilts/sdk/*/public/android.jar: %s", err.Error())
201 }
202
203 var sdkVersions []int
204 for _, sdkJar := range sdkJars {
205 dir := filepath.Base(filepath.Dir(filepath.Dir(sdkJar)))
206 v, err := strconv.Atoi(dir)
207 if scerr, ok := err.(*strconv.NumError); ok && scerr.Err == strconv.ErrSyntax {
208 continue
209 } else if err != nil {
210 ctx.Errorf("invalid sdk jar %q, %s, %v", sdkJar, err.Error())
211 }
212 sdkVersions = append(sdkVersions, v)
213 }
214
215 sort.Ints(sdkVersions)
216
217 ctx.Config().Once(sdkSingletonKey, func() interface{} { return sdkVersions })
218}