From b35a8198341a3f83df98562b1a7e9bcc318acbba Mon Sep 17 00:00:00 2001 From: Jiyong Park Date: Mon, 10 Aug 2020 15:59:36 +0900 Subject: [PATCH 1/2] __ANDROID_API__ tracks min_sdk_version Previously, for cc_* modules, __ANDROID_API__ tracked the sdk_version property. This however has caused a few number of problems: 1. It's confusing. __ANDROID_API__ has meant minSdkVersion. Therefore the sdk_version property should mean minSdkVersion (since the macro tracks the property). However, the introduction of the new min_sdk_version property (which is currently for APEX) made this very confusing. Also, this is not consistent with the java_* modules where sdk_version means compileSdkVersion. 2. This is preventing go/android-future-symbols. The plan is to make the APIs that are above the minSdkVersion available as weak symbols. Previously those APIs had to be accessed via dlsym because they are hidden behind the __ANDROID_API__ macro at build-time. To use make the APIs visible at build-time, the module authors had to __ANDROID_API__ beyond their minSdkVersion. This is against the definition of __ANDROID_API__. To solve above problems, __ANDROID_API__ now correctly tracks min_sdk_version. In addition, min_sdk_version now defaults to sdk_version. Therefore, most of the modules that don't set min_sdk_version aren't affected by this change. Bug: 163288375 Test: m Change-Id: I645e6bb1234c27ae0a69b7b87a59206cfd350744 --- cc/cc.go | 47 ++++++++++++++++++++++++++++++++++++++++++++--- cc/compiler.go | 7 ++++++- 2 files changed, 50 insertions(+), 4 deletions(-) diff --git a/cc/cc.go b/cc/cc.go index ca2bd4fd4..e69cff52f 100644 --- a/cc/cc.go +++ b/cc/cc.go @@ -256,11 +256,27 @@ type BaseProperties struct { // Deprecated. true is the default, false is invalid. Clang *bool `android:"arch_variant"` - // Minimum sdk version supported when compiling against the ndk. Setting this property causes - // two variants to be built, one for the platform and one for apps. + // The API level that this module is built against. The APIs of this API level will be + // visible at build time, but use of any APIs newer than min_sdk_version will render the + // module unloadable on older devices. In the future it will be possible to weakly-link new + // APIs, making the behavior match Java: such modules will load on older devices, but + // calling new APIs on devices that do not support them will result in a crash. + // + // This property has the same behavior as sdk_version does for Java modules. For those + // familiar with Android Gradle, the property behaves similarly to how compileSdkVersion + // does for Java code. + // + // In addition, setting this property causes two variants to be built, one for the platform + // and one for apps. Sdk_version *string - // Minimum sdk version that the artifact should support when it runs as part of mainline modules(APEX). + // Minimum OS API level supported by this C or C++ module. This property becomes the value + // of the __ANDROID_API__ macro. When the C or C++ module is included in an APEX or an APK, + // this property is also used to ensure that the min_sdk_version of the containing module is + // not older (i.e. less) than this module's min_sdk_version. When not set, this property + // defaults to the value of sdk_version. When this is set to "apex_inherit", this tracks + // min_sdk_version of the containing APEX. When the module + // is not built for an APEX, "apex_inherit" defaults to sdk_version. Min_sdk_version *string // If true, always create an sdk variant and don't create a platform variant. @@ -428,6 +444,8 @@ type ModuleContextIntf interface { canUseSdk() bool useSdk() bool sdkVersion() string + minSdkVersion() string + isSdkVariant() bool useVndk() bool isNdk(config android.Config) bool IsLlndk() bool @@ -1300,6 +1318,29 @@ func (ctx *moduleContextImpl) sdkVersion() string { return "" } +func (ctx *moduleContextImpl) minSdkVersion() string { + ver := ctx.mod.MinSdkVersion() + if ver == "apex_inherit" && !ctx.isForPlatform() { + ver = ctx.apexSdkVersion().String() + } + if ver == "apex_inherit" || ver == "" { + ver = ctx.sdkVersion() + } + // Also make sure that minSdkVersion is not greater than sdkVersion, if they are both numbers + sdkVersionInt, err := strconv.Atoi(ctx.sdkVersion()) + minSdkVersionInt, err2 := strconv.Atoi(ver) + if err == nil && err2 == nil { + if sdkVersionInt < minSdkVersionInt { + return strconv.Itoa(sdkVersionInt) + } + } + return ver +} + +func (ctx *moduleContextImpl) isSdkVariant() bool { + return ctx.mod.IsSdkVariant() +} + func (ctx *moduleContextImpl) useVndk() bool { return ctx.mod.UseVndk() } diff --git a/cc/compiler.go b/cc/compiler.go index eb2b5666a..5f30d3d6e 100644 --- a/cc/compiler.go +++ b/cc/compiler.go @@ -404,7 +404,12 @@ func (compiler *baseCompiler) compilerFlags(ctx ModuleContext, flags Flags, deps target := "-target " + tc.ClangTriple() if ctx.Os().Class == android.Device { - version := ctx.sdkVersion() + // When built for the non-updateble part of platform, minSdkVersion doesn't matter. + // It matters only when building we are building for modules that can be unbundled. + version := "current" + if !ctx.isForPlatform() || ctx.isSdkVariant() { + version = ctx.minSdkVersion() + } if version == "" || version == "current" { target += strconv.Itoa(android.FutureApiLevelInt) } else { From 423e37873b2fbec728ac615985ac2b7edbff482c Mon Sep 17 00:00:00 2001 From: Jiyong Park Date: Tue, 11 Aug 2020 09:35:08 +0900 Subject: [PATCH 2/2] API availability should be checked using __builtin_available This change turns -Wunguarded-availability option which enforces calls to APIs which are introduced after the min_sdk_version of the compliation unit to be guarded with __builtin_available check. For example, let's assume that we have foo() which was introduced with API level 30. void foo() __INTRODUCED_IN(30); Then if foo() is called for a module whose min_sdk_version is less than 30, say 26, it should be called as below: if (__builtin_available(android 30, *)) { foo(); } else { // fallback impl } For modules whose min_sdk_version is >=30, the guard is not required. Bug: 150860940 Bug: 134795810 Test: m Change-Id: I084148b9a051350626a37cb394daa4398b7332d5 --- cc/config/clang.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/cc/config/clang.go b/cc/config/clang.go index 328295896..35dd10f2c 100644 --- a/cc/config/clang.go +++ b/cc/config/clang.go @@ -141,6 +141,13 @@ func init() { // Warnings from clang-10 // Nested and array designated initialization is nice to have. "-Wno-c99-designator", + + // Calls to the APIs that are newer than the min sdk version of the caller should be + // guarded with __builtin_available. + "-Wunguarded-availability", + // This macro allows the bionic versioning.h to indirectly determine whether the + // option -Wunguarded-availability is on or not. + "-D__ANDROID_UNGUARDED_AVAILABILITY__", }, " ")) pctx.StaticVariable("ClangExtraCppflags", strings.Join([]string{