diff --git a/animal-sniffer-signature/build.gradle.kts b/animal-sniffer-signature/build.gradle.kts new file mode 100644 index 000000000..f7aa8a158 --- /dev/null +++ b/animal-sniffer-signature/build.gradle.kts @@ -0,0 +1,70 @@ +import ru.vyarus.gradle.plugin.animalsniffer.info.SignatureInfoTask +import ru.vyarus.gradle.plugin.animalsniffer.signature.BuildSignatureTask + +plugins { + id("com.android.library") + id("ru.vyarus.animalsniffer") +} + +android { + namespace = "otel.animalsniffer.signature" + compileSdk = (property("android.compileSdk") as String).toInt() +} + +description = "Build tool to generate the Animal Sniffer Android signature" + +val signatureJar = + configurations.create("signatureJar") { + isCanBeConsumed = false + isCanBeResolved = false + } +val signatureJarClasspath = + configurations.create("signatureJarClasspath") { + isCanBeConsumed = false + isCanBeResolved = true + extendsFrom(signatureJar) + } +val generatedSignature = + configurations.create("generatedSignature") { + isCanBeConsumed = true + isCanBeResolved = false + } +configurations.add(signatureJar) +configurations.add(signatureJarClasspath) +configurations.add(generatedSignature) + +dependencies { + signature("com.toasttab.android:gummy-bears-api-${project.property("android.minSdk")}:0.9.0@signature") + signatureJar(libs.desugarJdkLibs) +} + +val signatureSimpleName = "android.signature" +val signatureBuilderTask = + tasks.register("buildSignature", BuildSignatureTask::class.java) { + files(signatureJarClasspath) // All the jar files here will be added to the signature file. + signatures(configurations.signature) // We'll extend from the existing signatures added to this config. + outputName = signatureSimpleName // Name for the generated signature file. + } + +// Exposing the "generatedSignature" consumable config to be used in other subprojects +artifacts { + add( + "generatedSignature", + project.provider { + File( + signatureBuilderTask + .get() + .outputs.files.singleFile, + signatureSimpleName, + ) + }, + ) { + builtBy(signatureBuilderTask) + } +} + +// Utility task to show what's in the signature file +tasks.register("printSignature", SignatureInfoTask::class.java) { + signature = signatureBuilderTask.get().outputFiles + depth = 1 +} diff --git a/buildSrc/src/main/kotlin/otel.android-library-conventions.gradle.kts b/buildSrc/src/main/kotlin/otel.android-library-conventions.gradle.kts index 6d96c85e2..92077949e 100644 --- a/buildSrc/src/main/kotlin/otel.android-library-conventions.gradle.kts +++ b/buildSrc/src/main/kotlin/otel.android-library-conventions.gradle.kts @@ -5,6 +5,7 @@ plugins { id("org.jetbrains.kotlin.android") id("otel.errorprone-conventions") id("kotlin-kapt") + id("otel.animalsniffer-conventions") } val javaVersion = rootProject.extra["java_version"] as JavaVersion @@ -44,6 +45,7 @@ tasks.withType { val libs = extensions.getByType().named("libs") dependencies { + implementation(libs.findLibrary("androidx-annotation").get()) implementation(libs.findLibrary("findbugs-jsr305").get()) implementation(libs.findLibrary("auto-service-annotations").get()) kapt(libs.findLibrary("auto-service-processor").get()) diff --git a/buildSrc/src/main/kotlin/otel.animalsniffer-conventions.gradle.kts b/buildSrc/src/main/kotlin/otel.animalsniffer-conventions.gradle.kts new file mode 100644 index 000000000..3abf01a21 --- /dev/null +++ b/buildSrc/src/main/kotlin/otel.animalsniffer-conventions.gradle.kts @@ -0,0 +1,34 @@ +import java.util.Locale +import ru.vyarus.gradle.plugin.animalsniffer.AnimalSniffer + +plugins { + id("com.android.library") + id("ru.vyarus.animalsniffer") +} + +dependencies { + signature(project(path = ":animal-sniffer-signature", configuration = "generatedSignature")) +} + +val capitalizedVariantNames = mutableListOf() +androidComponents.onVariants { variant -> + val capitalizedName = + variant.name.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() } + capitalizedVariantNames.add(capitalizedName) +} + +afterEvaluate { + capitalizedVariantNames.forEach { capitalizedName -> + tasks.named("pre${capitalizedName}Build").configure { + finalizedBy("animalsniffer$capitalizedName") + } + } +} + +// Any class, method or field annotated with this annotation will be ignored by animal sniffer. +animalsniffer.annotation = "androidx.annotation.RequiresApi" + +tasks.withType { + // always having declared output makes this task properly participate in tasks up-to-date checks + reports.text.required.set(true) +} diff --git a/buildSrc/src/main/kotlin/otel.java-library-conventions.gradle.kts b/buildSrc/src/main/kotlin/otel.java-library-conventions.gradle.kts deleted file mode 100644 index d0d167ff5..000000000 --- a/buildSrc/src/main/kotlin/otel.java-library-conventions.gradle.kts +++ /dev/null @@ -1,58 +0,0 @@ -import org.jetbrains.kotlin.gradle.dsl.JvmTarget -import org.jetbrains.kotlin.gradle.dsl.KotlinVersion -import ru.vyarus.gradle.plugin.animalsniffer.AnimalSniffer - -plugins { - id("java-library") - id("org.jetbrains.kotlin.jvm") - id("otel.errorprone-conventions") - id("ru.vyarus.animalsniffer") -} - -// Extension to configure android parameters for non-android projects. -interface OtelAndroidExtension { - val minSdk: Property -} - -val otelAndroidExtension = - project.extensions.create("otelAndroid", OtelAndroidExtension::class.java) -otelAndroidExtension.minSdk.convention((project.property("android.minSdk") as String).toInt()) - -val javaVersion = rootProject.extra["java_version"] as JavaVersion -val minKotlinVersion = rootProject.extra["kotlin_min_supported_version"] as KotlinVersion -java { - sourceCompatibility = javaVersion - targetCompatibility = javaVersion -} -kotlin { - compilerOptions { - jvmTarget.set(JvmTarget.fromTarget(javaVersion.toString())) - apiVersion.set(minKotlinVersion) - languageVersion.set(minKotlinVersion) - } -} - -val libs = extensions.getByType().named("libs") -dependencies { - implementation(libs.findLibrary("findbugs-jsr305").get()) -} - -animalsniffer { - sourceSets = listOf(java.sourceSets.main.get()) -} - -// Always having declared output makes this task properly participate in tasks up-to-date checks -tasks.withType { - reports.text.required.set(true) -} - -// Attaching animalsniffer check to the compilation process. -tasks.named("classes").configure { - finalizedBy("animalsnifferMain") -} - -afterEvaluate { - dependencies { - signature("com.toasttab.android:gummy-bears-api-${otelAndroidExtension.minSdk.get()}:0.5.1:coreLib@signature") - } -} \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index d124636ad..92b27d259 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -18,6 +18,7 @@ opentelemetry-platform-alpha = { module = "io.opentelemetry.instrumentation:open opentelemetry-platform = { module = "io.opentelemetry.instrumentation:opentelemetry-instrumentation-bom" } androidx-navigation-fragment = "androidx.navigation:navigation-fragment:2.7.7" androidx-core = "androidx.core:core:1.15.0" +androidx-annotation = "androidx.annotation:annotation:1.9.1" androidx-lifecycle-process = "androidx.lifecycle:lifecycle-process:2.8.7" findbugs-jsr305 = "com.google.code.findbugs:jsr305:3.0.2" byteBuddy = { module = "net.bytebuddy:byte-buddy", version.ref = "byteBuddy" } @@ -66,7 +67,7 @@ errorprone-javac = "com.google.errorprone:javac:9+181-r4173-1" spotless-plugin = { module = "com.diffplug.spotless:spotless-plugin-gradle", version.ref = "spotless" } errorprone-plugin = "net.ltgt.gradle:gradle-errorprone-plugin:4.1.0" nullaway-plugin = "net.ltgt.gradle:gradle-nullaway-plugin:2.2.0" -animalsniffer-plugin = "ru.vyarus:gradle-animalsniffer-plugin:1.7.2" +animalsniffer-plugin = "ru.vyarus:gradle-animalsniffer-plugin:2.0.0" android-plugin = { module = "com.android.tools.build:gradle", version.ref = "androidPlugin" } byteBuddy-plugin = { module = "net.bytebuddy:byte-buddy-gradle-plugin", version.ref = "byteBuddy" } kotlin-plugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" } diff --git a/instrumentation/httpurlconnection/library/src/main/java/io/opentelemetry/instrumentation/library/httpurlconnection/HttpUrlReplacements.java b/instrumentation/httpurlconnection/library/src/main/java/io/opentelemetry/instrumentation/library/httpurlconnection/HttpUrlReplacements.java index 77f9f6a39..8910ad57a 100644 --- a/instrumentation/httpurlconnection/library/src/main/java/io/opentelemetry/instrumentation/library/httpurlconnection/HttpUrlReplacements.java +++ b/instrumentation/httpurlconnection/library/src/main/java/io/opentelemetry/instrumentation/library/httpurlconnection/HttpUrlReplacements.java @@ -5,8 +5,9 @@ package io.opentelemetry.instrumentation.library.httpurlconnection; -import android.annotation.SuppressLint; +import android.os.Build; import android.os.SystemClock; +import androidx.annotation.RequiresApi; import io.opentelemetry.context.Context; import io.opentelemetry.instrumentation.library.httpurlconnection.internal.HttpUrlConnectionSingletons; import io.opentelemetry.instrumentation.library.httpurlconnection.internal.RequestPropertySetter; @@ -77,7 +78,15 @@ public static int replacementForContentLength(URLConnection connection) { } public static long replacementForContentLengthLong(URLConnection connection) { - return replace(connection, () -> connection.getContentLengthLong()); + return replace( + connection, + new ResultProvider() { + @RequiresApi(Build.VERSION_CODES.N) + @Override + public Long get() { + return connection.getContentLengthLong(); + } + }); } public static long replacementForExpiration(URLConnection connection) { @@ -105,10 +114,17 @@ public static int replacementForHeaderFieldInt( return replace(connection, () -> connection.getHeaderFieldInt(name, Default)); } - @SuppressLint("NewApi") public static long replacementForHeaderFieldLong( URLConnection connection, String name, long Default) { - return replace(connection, () -> connection.getHeaderFieldLong(name, Default)); + return replace( + connection, + new ResultProvider() { + @RequiresApi(Build.VERSION_CODES.N) + @Override + public Long get() { + return connection.getHeaderFieldLong(name, Default); + } + }); } public static long replacementForHeaderFieldDate( diff --git a/instrumentation/slowrendering/src/main/java/io/opentelemetry/android/instrumentation/slowrendering/SlowRenderListener.java b/instrumentation/slowrendering/src/main/java/io/opentelemetry/android/instrumentation/slowrendering/SlowRenderListener.java index 29cadd6f6..7141c6eb9 100644 --- a/instrumentation/slowrendering/src/main/java/io/opentelemetry/android/instrumentation/slowrendering/SlowRenderListener.java +++ b/instrumentation/slowrendering/src/main/java/io/opentelemetry/android/instrumentation/slowrendering/SlowRenderListener.java @@ -110,6 +110,7 @@ public void onActivityPaused(@NonNull Activity activity) { } } + @RequiresApi(api = Build.VERSION_CODES.N) static class PerActivityListener implements Window.OnFrameMetricsAvailableListener { private final Activity activity; diff --git a/services/src/main/java/io/opentelemetry/android/internal/services/network/CurrentNetworkProvider.java b/services/src/main/java/io/opentelemetry/android/internal/services/network/CurrentNetworkProvider.java index 4565d82c0..70b77f9b5 100644 --- a/services/src/main/java/io/opentelemetry/android/internal/services/network/CurrentNetworkProvider.java +++ b/services/src/main/java/io/opentelemetry/android/internal/services/network/CurrentNetworkProvider.java @@ -12,6 +12,7 @@ import android.os.Build; import android.util.Log; import androidx.annotation.NonNull; +import androidx.annotation.RequiresApi; import io.opentelemetry.android.common.RumConstants; import io.opentelemetry.android.common.internal.features.networkattributes.data.CurrentNetwork; import io.opentelemetry.android.common.internal.features.networkattributes.data.NetworkState; @@ -75,13 +76,18 @@ private void startMonitoring(Supplier createNetworkMonitoringReq private void registerNetworkCallbacks(Supplier createNetworkMonitoringRequest) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - connectivityManager.registerDefaultNetworkCallback(new ConnectionMonitor()); + registerNetworkCallbackApi24(); } else { NetworkRequest networkRequest = createNetworkMonitoringRequest.get(); connectivityManager.registerNetworkCallback(networkRequest, new ConnectionMonitor()); } } + @RequiresApi(Build.VERSION_CODES.N) + private void registerNetworkCallbackApi24() { + connectivityManager.registerDefaultNetworkCallback(new ConnectionMonitor()); + } + /** Returns up-to-date {@linkplain CurrentNetwork current network information}. */ public CurrentNetwork refreshNetworkStatus() { try { diff --git a/settings.gradle.kts b/settings.gradle.kts index 8a4ff64ad..6e91c438e 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -19,6 +19,7 @@ include(":instrumentation:httpurlconnection:agent") include(":instrumentation:httpurlconnection:library") include(":instrumentation:httpurlconnection:testing") include(":test-common") +include(":animal-sniffer-signature") include(":instrumentation:android-instrumentation") include(":common") include(":services")