sdk_version.go 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. // Copyright 2021 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. package android
  15. import (
  16. "fmt"
  17. "strconv"
  18. "strings"
  19. )
  20. type SdkContext interface {
  21. // SdkVersion returns SdkSpec that corresponds to the sdk_version property of the current module
  22. SdkVersion(ctx EarlyModuleContext) SdkSpec
  23. // SystemModules returns the system_modules property of the current module, or an empty string if it is not set.
  24. SystemModules() string
  25. // MinSdkVersion returns SdkSpec that corresponds to the min_sdk_version property of the current module,
  26. // or from sdk_version if it is not set.
  27. MinSdkVersion(ctx EarlyModuleContext) SdkSpec
  28. // ReplaceMaxSdkVersionPlaceholder returns SdkSpec to replace the maxSdkVersion property of permission and
  29. // uses-permission tags if it is set.
  30. ReplaceMaxSdkVersionPlaceholder(ctx EarlyModuleContext) SdkSpec
  31. // TargetSdkVersion returns the SdkSpec that corresponds to the target_sdk_version property of the current module,
  32. // or from sdk_version if it is not set.
  33. TargetSdkVersion(ctx EarlyModuleContext) SdkSpec
  34. }
  35. // SdkKind represents a particular category of an SDK spec like public, system, test, etc.
  36. type SdkKind int
  37. const (
  38. SdkInvalid SdkKind = iota
  39. SdkNone
  40. SdkCore
  41. SdkCorePlatform
  42. SdkIntraCore // API surface provided by one core module to another
  43. SdkPublic
  44. SdkSystem
  45. SdkTest
  46. SdkModule
  47. SdkSystemServer
  48. SdkPrivate
  49. )
  50. // String returns the string representation of this SdkKind
  51. func (k SdkKind) String() string {
  52. switch k {
  53. case SdkPrivate:
  54. return "private"
  55. case SdkNone:
  56. return "none"
  57. case SdkPublic:
  58. return "public"
  59. case SdkSystem:
  60. return "system"
  61. case SdkTest:
  62. return "test"
  63. case SdkCore:
  64. return "core"
  65. case SdkCorePlatform:
  66. return "core_platform"
  67. case SdkIntraCore:
  68. return "intracore"
  69. case SdkModule:
  70. return "module-lib"
  71. case SdkSystemServer:
  72. return "system-server"
  73. default:
  74. return "invalid"
  75. }
  76. }
  77. // SdkSpec represents the kind and the version of an SDK for a module to build against
  78. type SdkSpec struct {
  79. Kind SdkKind
  80. ApiLevel ApiLevel
  81. Raw string
  82. }
  83. func (s SdkSpec) String() string {
  84. return fmt.Sprintf("%s_%s", s.Kind, s.ApiLevel)
  85. }
  86. // Valid checks if this SdkSpec is well-formed. Note however that true doesn't mean that the
  87. // specified SDK actually exists.
  88. func (s SdkSpec) Valid() bool {
  89. return s.Kind != SdkInvalid
  90. }
  91. // Specified checks if this SdkSpec is well-formed and is not "".
  92. func (s SdkSpec) Specified() bool {
  93. return s.Valid() && s.Kind != SdkPrivate
  94. }
  95. // whether the API surface is managed and versioned, i.e. has .txt file that
  96. // get frozen on SDK freeze and changes get reviewed by API council.
  97. func (s SdkSpec) Stable() bool {
  98. if !s.Specified() {
  99. return false
  100. }
  101. switch s.Kind {
  102. case SdkNone:
  103. // there is nothing to manage and version in this case; de facto stable API.
  104. return true
  105. case SdkCore, SdkPublic, SdkSystem, SdkModule, SdkSystemServer:
  106. return true
  107. case SdkCorePlatform, SdkTest, SdkPrivate:
  108. return false
  109. default:
  110. panic(fmt.Errorf("unknown SdkKind=%v", s.Kind))
  111. }
  112. return false
  113. }
  114. // PrebuiltSdkAvailableForUnbundledBuild tells whether this SdkSpec can have a prebuilt SDK
  115. // that can be used for unbundled builds.
  116. func (s SdkSpec) PrebuiltSdkAvailableForUnbundledBuild() bool {
  117. // "", "none", and "core_platform" are not available for unbundled build
  118. // as we don't/can't have prebuilt stub for the versions
  119. return s.Kind != SdkPrivate && s.Kind != SdkNone && s.Kind != SdkCorePlatform
  120. }
  121. func (s SdkSpec) ForVendorPartition(ctx EarlyModuleContext) SdkSpec {
  122. // If BOARD_CURRENT_API_LEVEL_FOR_VENDOR_MODULES has a numeric value,
  123. // use it instead of "current" for the vendor partition.
  124. currentSdkVersion := ctx.DeviceConfig().CurrentApiLevelForVendorModules()
  125. if currentSdkVersion == "current" {
  126. return s
  127. }
  128. if s.Kind == SdkPublic || s.Kind == SdkSystem {
  129. if s.ApiLevel.IsCurrent() {
  130. if i, err := strconv.Atoi(currentSdkVersion); err == nil {
  131. apiLevel := uncheckedFinalApiLevel(i)
  132. return SdkSpec{s.Kind, apiLevel, s.Raw}
  133. }
  134. panic(fmt.Errorf("BOARD_CURRENT_API_LEVEL_FOR_VENDOR_MODULES must be either \"current\" or a number, but was %q", currentSdkVersion))
  135. }
  136. }
  137. return s
  138. }
  139. // UsePrebuilt determines whether prebuilt SDK should be used for this SdkSpec with the given context.
  140. func (s SdkSpec) UsePrebuilt(ctx EarlyModuleContext) bool {
  141. switch s {
  142. case SdkSpecNone, SdkSpecCorePlatform, SdkSpecPrivate:
  143. return false
  144. }
  145. if s.ApiLevel.IsCurrent() {
  146. // "current" can be built from source and be from prebuilt SDK
  147. return ctx.Config().AlwaysUsePrebuiltSdks()
  148. } else if !s.ApiLevel.IsPreview() {
  149. // validation check
  150. if s.Kind != SdkPublic && s.Kind != SdkSystem && s.Kind != SdkTest && s.Kind != SdkModule && s.Kind != SdkSystemServer {
  151. panic(fmt.Errorf("prebuilt SDK is not not available for SdkKind=%q", s.Kind))
  152. return false
  153. }
  154. // numbered SDKs are always from prebuilt
  155. return true
  156. }
  157. return false
  158. }
  159. // EffectiveVersion converts an SdkSpec into the concrete ApiLevel that the module should use. For
  160. // modules targeting an unreleased SDK (meaning it does not yet have a number) it returns
  161. // FutureApiLevel(10000).
  162. func (s SdkSpec) EffectiveVersion(ctx EarlyModuleContext) (ApiLevel, error) {
  163. if !s.Valid() {
  164. return s.ApiLevel, fmt.Errorf("invalid sdk version %q", s.Raw)
  165. }
  166. if ctx.DeviceSpecific() || ctx.SocSpecific() {
  167. s = s.ForVendorPartition(ctx)
  168. }
  169. if !s.ApiLevel.IsPreview() {
  170. return s.ApiLevel, nil
  171. }
  172. ret := ctx.Config().DefaultAppTargetSdk(ctx)
  173. if ret.IsPreview() {
  174. return FutureApiLevel, nil
  175. }
  176. return ret, nil
  177. }
  178. // EffectiveVersionString converts an SdkSpec into the concrete version string that the module
  179. // should use. For modules targeting an unreleased SDK (meaning it does not yet have a number)
  180. // it returns the codename (P, Q, R, etc.)
  181. func (s SdkSpec) EffectiveVersionString(ctx EarlyModuleContext) (string, error) {
  182. if !s.Valid() {
  183. return s.ApiLevel.String(), fmt.Errorf("invalid sdk version %q", s.Raw)
  184. }
  185. if ctx.DeviceSpecific() || ctx.SocSpecific() {
  186. s = s.ForVendorPartition(ctx)
  187. }
  188. if !s.ApiLevel.IsPreview() {
  189. return s.ApiLevel.String(), nil
  190. }
  191. return ctx.Config().DefaultAppTargetSdk(ctx).String(), nil
  192. }
  193. var (
  194. SdkSpecNone = SdkSpec{SdkNone, NoneApiLevel, "(no version)"}
  195. SdkSpecPrivate = SdkSpec{SdkPrivate, FutureApiLevel, ""}
  196. SdkSpecCorePlatform = SdkSpec{SdkCorePlatform, FutureApiLevel, "core_platform"}
  197. )
  198. func SdkSpecFrom(ctx EarlyModuleContext, str string) SdkSpec {
  199. return SdkSpecFromWithConfig(ctx.Config(), str)
  200. }
  201. func SdkSpecFromWithConfig(config Config, str string) SdkSpec {
  202. switch str {
  203. // special cases first
  204. case "":
  205. return SdkSpecPrivate
  206. case "none":
  207. return SdkSpecNone
  208. case "core_platform":
  209. return SdkSpecCorePlatform
  210. default:
  211. // the syntax is [kind_]version
  212. sep := strings.LastIndex(str, "_")
  213. var kindString string
  214. if sep == 0 {
  215. return SdkSpec{SdkInvalid, NoneApiLevel, str}
  216. } else if sep == -1 {
  217. kindString = ""
  218. } else {
  219. kindString = str[0:sep]
  220. }
  221. versionString := str[sep+1 : len(str)]
  222. var kind SdkKind
  223. switch kindString {
  224. case "":
  225. kind = SdkPublic
  226. case "core":
  227. kind = SdkCore
  228. case "system":
  229. kind = SdkSystem
  230. case "test":
  231. kind = SdkTest
  232. case "module":
  233. kind = SdkModule
  234. case "system_server":
  235. kind = SdkSystemServer
  236. default:
  237. return SdkSpec{SdkInvalid, NoneApiLevel, str}
  238. }
  239. apiLevel, err := ApiLevelFromUserWithConfig(config, versionString)
  240. if err != nil {
  241. return SdkSpec{SdkInvalid, apiLevel, str}
  242. }
  243. return SdkSpec{kind, apiLevel, str}
  244. }
  245. }
  246. func (s SdkSpec) ValidateSystemSdk(ctx EarlyModuleContext) bool {
  247. // Ensures that the specified system SDK version is one of BOARD_SYSTEMSDK_VERSIONS (for vendor/product Java module)
  248. // Assuming that BOARD_SYSTEMSDK_VERSIONS := 28 29,
  249. // sdk_version of the modules in vendor/product that use system sdk must be either system_28, system_29 or system_current
  250. if s.Kind != SdkSystem || s.ApiLevel.IsPreview() {
  251. return true
  252. }
  253. allowedVersions := ctx.DeviceConfig().PlatformSystemSdkVersions()
  254. if ctx.DeviceSpecific() || ctx.SocSpecific() || (ctx.ProductSpecific() && ctx.Config().EnforceProductPartitionInterface()) {
  255. systemSdkVersions := ctx.DeviceConfig().SystemSdkVersions()
  256. if len(systemSdkVersions) > 0 {
  257. allowedVersions = systemSdkVersions
  258. }
  259. }
  260. if len(allowedVersions) > 0 && !InList(s.ApiLevel.String(), allowedVersions) {
  261. ctx.PropertyErrorf("sdk_version", "incompatible sdk version %q. System SDK version should be one of %q",
  262. s.Raw, allowedVersions)
  263. return false
  264. }
  265. return true
  266. }