Skip to content

Commit

Permalink
v5.17.0
Browse files Browse the repository at this point in the history
  • Loading branch information
fractalwrench authored Dec 8, 2021
2 parents 8bb2eae + 3dc9d3b commit 9807e53
Show file tree
Hide file tree
Showing 27 changed files with 175 additions and 63 deletions.
21 changes: 20 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,27 @@
# Changelog

## 5.17.0 (2021-12-08)

### Enhancements

* Bump compileSdkVersion to apiLevel 31
[#1536](https://github.com/bugsnag/bugsnag-android/pull/1536)

### Bug fixes

* Flush in-memory sessions first
[#1538](https://github.com/bugsnag/bugsnag-android/pull/1538)

* Avoid unnecessary network connectivity change breadcrumb
[#1540](https://github.com/bugsnag/bugsnag-android/pull/1540)
[#1546](https://github.com/bugsnag/bugsnag-android/pull/1546)

* Clear native stacktrace memory in `bugsnag_notify_env` before attempting to unwind the stack
[#1543](https://github.com/bugsnag/bugsnag-android/pull/1543)

## 5.16.0 (2021-11-29)

## Bug fixes
### Bug fixes

* Increase resilience of NDK stackframe method capture
[#1484](https://github.com/bugsnag/bugsnag-android/pull/1484)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ import android.net.Network
import android.net.NetworkCapabilities
import android.os.Build
import androidx.annotation.RequiresApi
import androidx.annotation.VisibleForTesting
import com.bugsnag.android.UnknownConnectivity.retrieveNetworkAccessState
import java.util.concurrent.atomic.AtomicBoolean

internal typealias NetworkChangeCallback = (hasConnection: Boolean, networkState: String) -> Unit

Expand Down Expand Up @@ -89,10 +92,16 @@ internal class ConnectivityLegacy(
}
}

private inner class ConnectivityChangeReceiver(private val cb: NetworkChangeCallback?) :
BroadcastReceiver() {
private inner class ConnectivityChangeReceiver(
private val cb: NetworkChangeCallback?
) : BroadcastReceiver() {

private val receivedFirstCallback = AtomicBoolean(false)

override fun onReceive(context: Context, intent: Intent) {
cb?.invoke(hasNetworkConnection(), retrieveNetworkAccessState())
if (receivedFirstCallback.getAndSet(true)) {
cb?.invoke(hasNetworkConnection(), retrieveNetworkAccessState())
}
}
}
}
Expand Down Expand Up @@ -122,22 +131,38 @@ internal class ConnectivityApi24(
}
}

private inner class ConnectivityTrackerCallback(private val cb: NetworkChangeCallback?) :
ConnectivityManager.NetworkCallback() {
@VisibleForTesting
internal class ConnectivityTrackerCallback(
private val cb: NetworkChangeCallback?
) : ConnectivityManager.NetworkCallback() {

private val receivedFirstCallback = AtomicBoolean(false)

override fun onUnavailable() {
super.onUnavailable()
cb?.invoke(false, retrieveNetworkAccessState())
invokeNetworkCallback(false)
}

override fun onAvailable(network: Network) {
super.onAvailable(network)
cb?.invoke(true, retrieveNetworkAccessState())
invokeNetworkCallback(true)
}

/**
* Invokes the network callback, as long as the ConnectivityManager callback has been
* triggered at least once before (when setting a NetworkCallback Android always
* invokes the callback with the current network state).
*/
private fun invokeNetworkCallback(hasConnection: Boolean) {
if (receivedFirstCallback.getAndSet(true)) {
cb?.invoke(hasConnection, retrieveNetworkAccessState())
}
}
}
}

/**
* Connectivity used in cases where we cannot access the system ConnectivityManager.
* Connectivity used in cases where we cannot access the system ConnectivityManager.
* We assume that there is some sort of network and do not attempt to report any network changes.
*/
internal object UnknownConnectivity : Connectivity {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import java.io.IOException
*/
class Notifier @JvmOverloads constructor(
var name: String = "Android Bugsnag Notifier",
var version: String = "5.16.0",
var version: String = "5.17.0",
var url: String = "https://bugsnag.com"
) : JsonStream.Streamable {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,12 +181,10 @@ private boolean trackSessionIfNeeded(final Session session) {
if (deliverSession && session.isTracked().compareAndSet(false, true)) {
currentSession = session;
notifySessionStartObserver(session);
flushAsync();
flushInMemorySession(session);

flushAsync();
return true;
}

return false;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
@file:Suppress("DEPRECATION")

package com.bugsnag.android

import android.content.Context
Expand Down Expand Up @@ -31,15 +29,15 @@ class ConnectivityApi24Test {
lateinit var capabilities: NetworkCapabilities

@Test
fun connectivityLegacyHasConnection() {
fun connectivityApi24HasConnection() {
val conn = ConnectivityApi24(cm, null)
assertFalse(conn.hasNetworkConnection())
Mockito.`when`(cm.activeNetwork).thenReturn(info)
assertTrue(conn.hasNetworkConnection())
}

@Test
fun connectivityLegacyNetworkState() {
fun connectivityApi24NetworkState() {
val conn = ConnectivityApi24(cm, null)
Mockito.`when`(cm.activeNetwork).thenReturn(info)

Expand All @@ -50,4 +48,40 @@ class ConnectivityApi24Test {
Mockito.`when`(capabilities.hasTransport(0)).thenReturn(true)
assertEquals("cellular", conn.retrieveNetworkAccessState())
}

@Test
fun connectivityApi24OnAvailable() {
var count = 0
val tracker = ConnectivityApi24.ConnectivityTrackerCallback { _, _ ->
count++
}
assertEquals(0, count)

tracker.onAvailable(info)
assertEquals(0, count)

tracker.onAvailable(info)
assertEquals(1, count)

tracker.onAvailable(info)
assertEquals(2, count)
}

@Test
fun connectivityApi24OnUnvailable() {
var count = 0
val tracker = ConnectivityApi24.ConnectivityTrackerCallback { _, _ ->
count++
}
assertEquals(0, count)

tracker.onUnavailable()
assertEquals(0, count)

tracker.onUnavailable()
assertEquals(1, count)

tracker.onUnavailable()
assertEquals(2, count)
}
}
2 changes: 1 addition & 1 deletion bugsnag-benchmarks/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ plugins {
}

android {
compileSdkVersion 30
compileSdkVersion 31
buildToolsVersion "30.0.3"

compileOptions {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ internal class AnrPlugin : Plugin {
if (clz != null) {
val ndkPlugin = client.getPlugin(clz)
if (ndkPlugin != null) {
val method = ndkPlugin.javaClass.getMethod("getUnwindStackFunction")
val method = ndkPlugin.javaClass.getMethod("getSignalUnwindStackFunction")

@Suppress("UNCHECKED_CAST")
val function = method.invoke(ndkPlugin) as Long
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,10 @@ internal class NdkPlugin : Plugin {
}
}

fun getUnwindStackFunction(): Long {
fun getSignalUnwindStackFunction(): Long {
val bridge = nativeBridge
if (bridge != null) {
return bridge.getUnwindStackFunction()
return bridge.getSignalUnwindStackFunction()
}
return 0
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ class NativeBridge : StateObserver {
external fun updateUserId(newValue: String)
external fun updateUserEmail(newValue: String)
external fun updateUserName(newValue: String)
external fun getUnwindStackFunction(): Long
external fun getSignalUnwindStackFunction(): Long
external fun updateLowMemory(newValue: Boolean, memoryTrimLevelDescription: String)

override fun onStateChange(event: StateEvent) {
Expand Down
11 changes: 1 addition & 10 deletions bugsnag-plugin-android-ndk/src/main/jni/bugsnag.c
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ void bugsnag_notify_env(JNIEnv *env, const char *name, const char *message,
jbyteArray jmessage = NULL;

bugsnag_stackframe stacktrace[BUGSNAG_FRAMES_MAX];
memset(stacktrace, 0, sizeof(stacktrace));
ssize_t frame_count =
bsg_unwind_stack(bsg_configured_unwind_style(), stacktrace, NULL, NULL);

Expand Down Expand Up @@ -335,13 +336,3 @@ exit : {
bsg_safe_delete_local_ref(env, jtype);
bsg_safe_delete_local_ref(env, jmessage);
}

// Unwind the stack using the default unwind style.
// This function gets exposed via
// Java_com_bugsnag_android_ndk_NativeBridge_getUnwindStackFunction()
ssize_t
bsg_unwind_stack_default(bugsnag_stackframe stacktrace[BUGSNAG_FRAMES_MAX],
siginfo_t *info, void *user_context) __asyncsafe {
return bsg_unwind_stack(bsg_configured_unwind_style(), stacktrace, info,
user_context);
}
29 changes: 23 additions & 6 deletions bugsnag-plugin-android-ndk/src/main/jni/bugsnag_ndk.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,17 @@ bsg_unwinder bsg_configured_unwind_style() {
return BSG_CUSTOM_UNWIND;
}

/**
* Get the configured unwind style for async-safe environments such as signal
* handlers.
*/
bsg_unwinder bsg_configured_signal_unwind_style() {
if (bsg_global_env != NULL)
return bsg_global_env->signal_unwind_style;

return BSG_CUSTOM_UNWIND;
}

void bugsnag_add_on_error(bsg_on_error on_error) {
if (bsg_global_env != NULL) {
bsg_global_env->on_error = on_error;
Expand Down Expand Up @@ -698,14 +709,20 @@ JNIEXPORT void JNICALL Java_com_bugsnag_android_ndk_NativeBridge_updateMetadata(
bsg_release_env_write_lock();
}

ssize_t
bsg_unwind_stack_default(bugsnag_stackframe stacktrace[BUGSNAG_FRAMES_MAX],
siginfo_t *info, void *user_context) __asyncsafe;
// Unwind the stack using the configured unwind style for signal handlers.
// This function gets exposed via
// Java_com_bugsnag_android_ndk_NativeBridge_getSignalUnwindStackFunction()
static ssize_t
bsg_unwind_stack_signal(bugsnag_stackframe stacktrace[BUGSNAG_FRAMES_MAX],
siginfo_t *info, void *user_context) __asyncsafe {
return bsg_unwind_stack(bsg_configured_signal_unwind_style(), stacktrace,
info, user_context);
}

JNIEXPORT jlong JNICALL
Java_com_bugsnag_android_ndk_NativeBridge_getUnwindStackFunction(JNIEnv *env,
jobject thiz) {
return (jlong)bsg_unwind_stack_default;
Java_com_bugsnag_android_ndk_NativeBridge_getSignalUnwindStackFunction(
JNIEnv *env, jobject thiz) {
return (jlong)bsg_unwind_stack_signal;
}

#ifdef __cplusplus
Expand Down
4 changes: 4 additions & 0 deletions bugsnag-plugin-android-ndk/src/main/jni/bugsnag_ndk.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ typedef struct {
bsg_thread_send_policy send_threads;
} bsg_environment;

/**
* Get the configured unwind style for non-async-safe environments.
* DO NOT USE THIS IN A SIGNAL HANDLER!
*/
bsg_unwinder bsg_configured_unwind_style();

/**
Expand Down
2 changes: 1 addition & 1 deletion buildSrc/src/main/kotlin/com/bugsnag/android/Versions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import org.gradle.api.JavaVersion
object Versions {
// Note minSdkVersion must be >=21 for 64 bit architectures
val minSdkVersion = 14
val compileSdkVersion = 30
val compileSdkVersion = 31
val ndk = "17.2.4988734"
val java = JavaVersion.VERSION_1_7
val kotlin = "1.3.72"
Expand Down
2 changes: 1 addition & 1 deletion dockerfiles/Dockerfile.android-common
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ RUN rm $CMDLINE_TOOLS_NAME

# Install Android tools using sdkmanager
RUN yes | sdkmanager "platform-tools" > /dev/null
RUN yes | sdkmanager "platforms;android-30" > /dev/null
RUN yes | sdkmanager "platforms;android-31" > /dev/null
RUN yes | sdkmanager "ndk;17.2.4988734" > /dev/null
RUN yes | sdkmanager "cmake;3.6.4111459" > /dev/null
RUN yes | sdkmanager "cmake;3.10.2.4988404" > /dev/null
Expand Down
8 changes: 4 additions & 4 deletions examples/sdk-app-example/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ apply plugin: "com.android.application"
apply plugin: "kotlin-android"

android {
compileSdkVersion 30
compileSdkVersion 31
ndkVersion "17.2.4988734"

defaultConfig {
applicationId "com.example.bugsnag.android"
minSdkVersion 14
targetSdkVersion 30
targetSdkVersion 31
versionCode 1
versionName "1.0"
}
Expand Down Expand Up @@ -38,9 +38,9 @@ android {
}

dependencies {
implementation "com.bugsnag:bugsnag-android:5.12.0"
implementation "com.bugsnag:bugsnag-android:5.16.0"
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation "androidx.appcompat:appcompat:1.3.1"
implementation "androidx.appcompat:appcompat:1.4.0"
implementation "com.google.android.material:material:1.4.0"
}

Expand Down
3 changes: 2 additions & 1 deletion examples/sdk-app-example/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@

<activity
android:name=".ExampleActivity"
android:label="@string/app_name">
android:label="@string/app_name"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

Expand Down
4 changes: 2 additions & 2 deletions examples/sdk-app-example/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ buildscript {
mavenLocal()
}
dependencies {
classpath "com.android.tools.build:gradle:7.0.2"
classpath "com.android.tools.build:gradle:7.0.3"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "com.bugsnag:bugsnag-android-gradle-plugin:7.0.0"
classpath "com.bugsnag:bugsnag-android-gradle-plugin:7.1.0"
}
}

Expand Down
6 changes: 3 additions & 3 deletions features/fixtures/mazerunner/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ apply plugin: "io.gitlab.arturbosch.detekt"
apply plugin: "org.jlleitschuh.gradle.ktlint"

android {
compileSdkVersion 30
compileSdkVersion 31

defaultConfig {
minSdkVersion 14
targetSdkVersion 30
targetSdkVersion 31
versionCode 34
versionName "1.1.14"
manifestPlaceholders = [
Expand Down Expand Up @@ -55,7 +55,7 @@ android {
pickFirst "**/*.so"
}
lintOptions {
tasks.lint.enabled = false
abortOnError false
}

if (project.hasProperty("TEST_FIXTURE_NDK_VERSION")) {
Expand Down
Loading

0 comments on commit 9807e53

Please sign in to comment.