Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v5.22.3 #1685

Merged
merged 24 commits into from
May 11, 2022
Merged

v5.22.3 #1685

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
34e0242
Stop polling once a command is received
twometresteve May 4, 2022
8ee07c7
Merge pull request #1672 from bugsnag/tms/stop-polling
joshedney May 4, 2022
0e26d8f
Merge pull request #1675 from bugsnag/master
lemnik May 5, 2022
9cd87c7
Move build steps to Macs
twometresteve Apr 8, 2022
7d7a705
Use general server pool
twometresteve May 4, 2022
e820449
Correct target
twometresteve May 4, 2022
dce1cca
Corrections
twometresteve May 4, 2022
410178a
Merge pull request #1674 from bugsnag/tms/mac-builds
twometresteve May 5, 2022
4a657c6
Do not symlink folders during a CI build
twometresteve May 6, 2022
807a5ca
Merge pull request #1678 from bugsnag/tms/do-not-ln
twometresteve May 6, 2022
8dedf92
Handle dirty folder and leave it clean
twometresteve May 6, 2022
9d54b03
Merge pull request #1681 from bugsnag/tms/fix-sizer
twometresteve May 9, 2022
a644e14
Allow retry for specific failure in MultiThreadedStartupScenario
twometresteve May 8, 2022
2fe95c0
Merge pull request #1682 from bugsnag/tms/threads-flake
twometresteve May 9, 2022
1d930a8
perf(DependencyModule): removed `future` and replaced it with `resolv…
lemnik May 6, 2022
93a224b
Merge pull request #1680 from bugsnag/PLAT-8334/optimise-resolve-depe…
lemnik May 10, 2022
59edeb5
Fixed concurrency bug that could be triggered via the React Native pl…
kstenerud May 6, 2022
04eb1fc
fix(locationStatus): use `LocationManager.isLocationEnabled` on Andro…
lemnik May 10, 2022
28359da
Merge pull request #1683 from bugsnag/PLAT-8430/fix-location-status
lemnik May 10, 2022
a29c9d4
Merge branch 'next' into PLAT-8390-concurrency
kstenerud May 11, 2022
9e1da59
Merge pull request #1679 from bugsnag/PLAT-8390-concurrency
kstenerud May 11, 2022
dc7af52
Improve test fixture logging
twometresteve May 11, 2022
650579e
Merge pull request #1684 from bugsnag/tms/fixture-logging
twometresteve May 11, 2022
c2bb12b
v5.22.3
lemnik May 11, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
220 changes: 98 additions & 122 deletions .buildkite/pipeline.full.yml

Large diffs are not rendered by default.

208 changes: 79 additions & 129 deletions .buildkite/pipeline.yml

Large diffs are not rendered by default.

11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
# Changelog

## 5.22.3 (2022-05-12)

### Bug fixes

* Fixed concurrency bug that could be triggered via the React Native plugin
[#1679](https://github.com/bugsnag/bugsnag-android/pull/1679)
* Correctly report `device.locationStatus` on Android 12 onwards using `LocationManager.isLocationEnabled`
[1683](https://github.com/bugsnag/bugsnag-android/pull/1683)
* Small performance improvements to `Bugnag.start`
[#1680](https://github.com/bugsnag/bugsnag-android/pull/1680)

## 5.22.2 (2022-05-04)

### Bug fixes
Expand Down
2 changes: 1 addition & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ source "https://rubygems.org"
#gem 'bugsnag-maze-runner', path: '../maze-runner'

# Or a specific release:
gem 'bugsnag-maze-runner', git: 'https://github.com/bugsnag/maze-runner', tag: 'v6.11.1'
gem 'bugsnag-maze-runner', git: 'https://github.com/bugsnag/maze-runner', tag: 'v6.15.0'

# Or follow master:
# gem 'bugsnag-maze-runner', git: 'https://github.com/bugsnag/maze-runner'
Expand Down
8 changes: 4 additions & 4 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
GIT
remote: https://github.com/bugsnag/maze-runner
revision: b7012344cc0c7081f54bfefe6d9356e3629d2b37
tag: v6.11.1
revision: d71ba8a1b770e86800b4e9f6782a63fef019a989
tag: v6.15.0
specs:
bugsnag-maze-runner (6.11.1)
bugsnag-maze-runner (6.15.0)
appium_lib (~> 11.2.0)
bugsnag (~> 6.24)
cucumber (~> 7.1)
Expand Down Expand Up @@ -81,7 +81,7 @@ GEM
mime-types-data (~> 3.2015)
mime-types-data (3.2022.0105)
multi_test (0.1.2)
nokogiri (1.13.4-x86_64-darwin)
nokogiri (1.13.6-x86_64-darwin)
racc (~> 1.4)
optimist (3.0.1)
os (1.0.1)
Expand Down
64 changes: 40 additions & 24 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -22,36 +22,52 @@ endif
INSTRUMENTATION_DEVICES='["Google Nexus 5-4.4", "Google Pixel-7.1", "Google Pixel 3-9.0"]' \
docker-compose up --build android-instrumentation-tests

BUILD_TASK ?= assembleRelease
MINIMAL_FIXTURE ?= false
TEST_FIXTURE_NDK_VERSION ?= 16.1.4479499
test-fixtures:
TEST_FIXTURE_NAME ?= fixture
USE_LEGACY_OKHTTP ?= false

notifier:
# Build the notifier
@./gradlew -PVERSION_NAME=9.9.9 assembleRelease publishToMavenLocal -x check

# Build the full test fixture
@./gradlew -PTEST_FIXTURE_NDK_VERSION=$(TEST_FIXTURE_NDK_VERSION) -p=features/fixtures/mazerunner/ assembleRelease -x check
@cp features/fixtures/mazerunner/app/build/outputs/apk/release/fixture.apk build/fixture.apk
# copy the unstripped scenarios libs (for stack unwinding validation)
# grabs the newest files as the likely just built ones
LIB_CXX_BUGSNAG_64=$$(dirname `ls -dt features/fixtures/mazerunner/cxx-scenarios-bugsnag/build/intermediates/cxx/RelWithDebInfo/*/obj/x86_64 | head -n 1`) && \
LIB_CXX_BUGSNAG_32=$$(dirname `ls -dt features/fixtures/mazerunner/cxx-scenarios-bugsnag/build/intermediates/cxx/RelWithDebInfo/*/obj/armeabi-v7a | head -n 1`) && \
LIB_CXX_64=$$(dirname `ls -dt features/fixtures/mazerunner/cxx-scenarios/build/intermediates/cxx/RelWithDebInfo/*/obj/x86_64 | head -n 1`) && \
LIB_CXX_32=$$(dirname `ls -dt features/fixtures/mazerunner/cxx-scenarios/build/intermediates/cxx/RelWithDebInfo/*/obj/armeabi-v7a | head -n 1`) && \
cp $$LIB_CXX_64/x86_64/libcxx-scenarios.so build/libcxx-scenarios-x86_64.so && \
cp $$LIB_CXX_32/x86/libcxx-scenarios.so build/libcxx-scenarios-x86.so && \
cp $$LIB_CXX_64/arm64-v8a/libcxx-scenarios.so build/libcxx-scenarios-arm64.so && \
cp $$LIB_CXX_32/armeabi-v7a/libcxx-scenarios.so build/libcxx-scenarios-arm32.so && \
cp $$LIB_CXX_BUGSNAG_64/x86_64/libcxx-scenarios-bugsnag.so build/libcxx-scenarios-bugsnag-x86_64.so && \
cp $$LIB_CXX_BUGSNAG_32/x86/libcxx-scenarios-bugsnag.so build/libcxx-scenarios-bugsnag-x86.so && \
cp $$LIB_CXX_BUGSNAG_64/arm64-v8a/libcxx-scenarios-bugsnag.so build/libcxx-scenarios-bugsnag-arm64.so && \
cp $$LIB_CXX_BUGSNAG_32/armeabi-v7a/libcxx-scenarios-bugsnag.so build/libcxx-scenarios-bugsnag-arm32.so
fixture-r16: notifier
# Build the r16 test fixture
@./gradlew -PTEST_FIXTURE_NDK_VERSION=16.1.4479499 \
-PTEST_FIXTURE_NAME=fixture-r16.apk \
-PUSE_LEGACY_OKHTTP=true \
-p=features/fixtures/mazerunner assembleRelease -x check
@scripts/copy-build-files.sh release fixture-r16

fixture-r19: notifier
# Build the r19 test fixture
@./gradlew -PTEST_FIXTURE_NDK_VERSION=19.2.5345600 \
-PTEST_FIXTURE_NAME=fixture-r19.apk \
-p=features/fixtures/mazerunner assembleRelease -x check
@scripts/copy-build-files.sh release fixture-r19

fixture-r21: notifier
# Build the minimal test fixture
@./gradlew -PTEST_FIXTURE_NDK_VERSION=21.4.7075529 \
-PTEST_FIXTURE_NAME=fixture-r21.apk \
-p=features/fixtures/mazerunner assembleRelease -x check
@scripts/copy-build-files.sh release fixture-r21

# And the minimal (no NDK or ANR plugin) test fixture
@./gradlew -PMINIMAL_FIXTURE=true -PTEST_FIXTURE_NAME=fixture-minimal.apk -p=features/fixtures/mazerunner/ assembleRelease -x check
@cp features/fixtures/mazerunner/app/build/outputs/apk/release/fixture-minimal.apk build/fixture-minimal.apk
fixture-minimal: notifier
# Build the minimal test fixture
@./gradlew -PMINIMAL_FIXTURE=true \
-PTEST_FIXTURE_NDK_VERSION=17.2.4988734 \
-PTEST_FIXTURE_NAME=fixture-minimal.apk \
-p=features/fixtures/mazerunner assembleRelease -x check
@scripts/copy-build-files.sh release fixture-minimal

# And the debug test fixture (full fixture - but a debug build)
@./gradlew -PTEST_FIXTURE_NDK_VERSION=$(TEST_FIXTURE_NDK_VERSION) -p=features/fixtures/mazerunner/ assembleDebug -x check
@cp features/fixtures/mazerunner/app/build/outputs/apk/debug/fixture.apk build/fixture-debug.apk
fixture-debug: notifier
# Build the minimal test fixture
@./gradlew -PTEST_FIXTURE_NDK_VERSION=17.2.4988734 \
-PTEST_FIXTURE_NAME=fixture-debug.apk \
-p=features/fixtures/mazerunner assembleDebug -x check
@scripts/copy-build-files.sh debug fixture-debug

bump:
ifneq ($(shell git diff --staged),)
Expand Down
3 changes: 2 additions & 1 deletion bugsnag-android-core/detekt-baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<ID>LongParameterList:AppDataCollector.kt$AppDataCollector$( appContext: Context, private val packageManager: PackageManager?, private val config: ImmutableConfig, private val sessionTracker: SessionTracker, private val activityManager: ActivityManager?, private val launchCrashTracker: LaunchCrashTracker, private val memoryTrimState: MemoryTrimState )</ID>
<ID>LongParameterList:AppWithState.kt$AppWithState$( binaryArch: String?, id: String?, releaseStage: String?, version: String?, codeBundleId: String?, buildUuid: String?, type: String?, versionCode: Number?, /** * The number of milliseconds the application was running before the event occurred */ var duration: Number?, /** * The number of milliseconds the application was running in the foreground before the * event occurred */ var durationInForeground: Number?, /** * Whether the application was in the foreground when the event occurred */ var inForeground: Boolean?, /** * Whether the application was launching when the event occurred */ var isLaunching: Boolean? )</ID>
<ID>LongParameterList:AppWithState.kt$AppWithState$( config: ImmutableConfig, binaryArch: String?, id: String?, releaseStage: String?, version: String?, codeBundleId: String?, duration: Number?, durationInForeground: Number?, inForeground: Boolean?, isLaunching: Boolean? )</ID>
<ID>LongParameterList:DataCollectionModule.kt$DataCollectionModule$( contextModule: ContextModule, configModule: ConfigModule, systemServiceModule: SystemServiceModule, trackerModule: TrackerModule, bgTaskService: BackgroundTaskService, connectivity: Connectivity, deviceId: String?, memoryTrimState: MemoryTrimState )</ID>
<ID>LongParameterList:DataCollectionModule.kt$DataCollectionModule$( contextModule: ContextModule, configModule: ConfigModule, systemServiceModule: SystemServiceModule, trackerModule: TrackerModule, private val bgTaskService: BackgroundTaskService, private val connectivity: Connectivity, private val deviceId: String?, memoryTrimState: MemoryTrimState )</ID>
<ID>LongParameterList:Device.kt$Device$( buildInfo: DeviceBuildInfo, /** * The Application Binary Interface used */ var cpuAbi: Array&lt;String>?, /** * Whether the device has been jailbroken */ var jailbroken: Boolean?, /** * A UUID generated by Bugsnag and used for the individual application on a device */ var id: String?, /** * The IETF language tag of the locale used */ var locale: String?, /** * The total number of bytes of memory on the device */ var totalMemory: Long?, /** * A collection of names and their versions of the primary languages, frameworks or * runtimes that the application is running on */ runtimeVersions: MutableMap&lt;String, Any>? )</ID>
<ID>LongParameterList:DeviceBuildInfo.kt$DeviceBuildInfo$( val manufacturer: String?, val model: String?, val osVersion: String?, val apiLevel: Int?, val osBuild: String?, val fingerprint: String?, val tags: String?, val brand: String?, val cpuAbis: Array&lt;String>? )</ID>
<ID>LongParameterList:DeviceDataCollector.kt$DeviceDataCollector$( private val connectivity: Connectivity, private val appContext: Context, resources: Resources, private val deviceId: String?, private val buildInfo: DeviceBuildInfo, private val dataDirectory: File, rootDetector: RootDetector, private val bgTaskService: BackgroundTaskService, private val logger: Logger )</ID>
Expand All @@ -34,6 +34,7 @@
<ID>SwallowedException:BugsnagEventMapper.kt$BugsnagEventMapper$catch (pe: IllegalArgumentException) { ndkDateFormatHolder.get()!!.parse(this) ?: throw IllegalArgumentException("cannot parse date $this") }</ID>
<ID>SwallowedException:ConnectivityCompat.kt$ConnectivityLegacy$catch (e: NullPointerException) { // in some rare cases we get a remote NullPointerException via Parcel.readException null }</ID>
<ID>SwallowedException:ContextExtensions.kt$catch (exc: RuntimeException) { null }</ID>
<ID>SwallowedException:DependencyModule.kt$DependencyModule$catch (exception: Exception) { // ignore failures }</ID>
<ID>SwallowedException:DeviceDataCollector.kt$DeviceDataCollector$catch (exc: Exception) { false }</ID>
<ID>SwallowedException:DeviceDataCollector.kt$DeviceDataCollector$catch (exception: Exception) { logger.w("Could not get battery status") }</ID>
<ID>SwallowedException:DeviceDataCollector.kt$DeviceDataCollector$catch (exception: Exception) { logger.w("Could not get locationStatus") }</ID>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package com.bugsnag.android

import android.content.Context
import android.content.res.Configuration
import android.content.res.Resources
import org.junit.Ignore
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mockito
import org.mockito.junit.MockitoJUnitRunner
import java.io.File
import kotlin.concurrent.thread

@RunWith(MockitoJUnitRunner::class)
class DataCollectorTest {

@Ignore("Disabled until we're able to mock final classes or auto-open classes")
@Test
fun testConcurretAccess() {
val res = Mockito.mock(Resources::class.java)
Mockito.`when`(res.configuration).thenReturn(Configuration())

val collector = DeviceDataCollector(
Mockito.mock(Connectivity::class.java),
Mockito.mock(Context::class.java),
res,
"fakeDevice",
Mockito.mock(DeviceBuildInfo::class.java),
File("/tmp/javatest"),
Mockito.mock(RootDetector::class.java),
Mockito.mock(BackgroundTaskService::class.java),
Mockito.mock(Logger::class.java)
)

repeat(10) { index ->
collector.addRuntimeVersionInfo("key" + index, "value" + index)
}

val count = 500

thread {
repeat(count) { index ->
collector.addRuntimeVersionInfo("key" + index, "value" + index)
}
}

repeat(count) {
collector.generateDevice()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.location.LocationManager
import android.net.ConnectivityManager
import android.os.RemoteException
import android.os.storage.StorageManager
Expand Down Expand Up @@ -69,3 +70,7 @@ internal fun Context.getConnectivityManager(): ConnectivityManager? =
@JvmName("getStorageManagerFrom")
internal fun Context.getStorageManager(): StorageManager? =
safeGetSystemService(Context.STORAGE_SERVICE)

@JvmName("getLocationManager")
internal fun Context.getLocationManager(): LocationManager? =
safeGetSystemService(Context.LOCATION_SERVICE)
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ internal class DataCollectionModule(
configModule: ConfigModule,
systemServiceModule: SystemServiceModule,
trackerModule: TrackerModule,
bgTaskService: BackgroundTaskService,
connectivity: Connectivity,
deviceId: String?,
private val bgTaskService: BackgroundTaskService,
private val connectivity: Connectivity,
private val deviceId: String?,
memoryTrimState: MemoryTrimState
) : DependencyModule() {

Expand All @@ -27,24 +27,25 @@ internal class DataCollectionModule(
private val deviceBuildInfo: DeviceBuildInfo = DeviceBuildInfo.defaultInfo()
private val dataDir = Environment.getDataDirectory()

val appDataCollector by future {
AppDataCollector(
ctx,
ctx.packageManager,
cfg,
trackerModule.sessionTracker,
systemServiceModule.activityManager,
trackerModule.launchCrashTracker,
memoryTrimState
)
}
val appDataCollector = AppDataCollector(
ctx,
ctx.packageManager,
cfg,
trackerModule.sessionTracker,
systemServiceModule.activityManager,
trackerModule.launchCrashTracker,
memoryTrimState
)

private val rootDetector by future {
RootDetector(logger = logger, deviceBuildInfo = deviceBuildInfo)
}
private lateinit var rootDetector: RootDetector
private lateinit var _deviceDataCollector: DeviceDataCollector

val deviceDataCollector: DeviceDataCollector
get() = resolvedValueOf { _deviceDataCollector }

val deviceDataCollector by future {
DeviceDataCollector(
override fun resolveDependencies() {
rootDetector = RootDetector(logger = logger, deviceBuildInfo = deviceBuildInfo)
_deviceDataCollector = DeviceDataCollector(
connectivity,
ctx,
ctx.resources,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import android.os.Build
import android.provider.Settings
import java.io.File
import java.util.Date
import java.util.HashMap
import java.util.Locale
import java.util.concurrent.Callable
import java.util.concurrent.Future
Expand Down Expand Up @@ -42,7 +41,7 @@ internal class DeviceDataCollector(
private val screenResolution = getScreenResolution()
private val locale = Locale.getDefault().toString()
private val cpuAbi = getCpuAbi()
private val runtimeVersions: MutableMap<String, Any>
private var runtimeVersions: MutableMap<String, Any>
private val rootedFuture: Future<Boolean>?
private val totalMemoryFuture: Future<Long?>? = retrieveTotalDeviceMemory()
private var orientation = AtomicInteger(resources.configuration.orientation)
Expand Down Expand Up @@ -163,19 +162,24 @@ internal class DeviceDataCollector(
*/
private fun getLocationStatus(): String? {
try {
val cr = appContext.contentResolver
@Suppress("DEPRECATION") val providersAllowed =
Settings.Secure.getString(cr, Settings.Secure.LOCATION_PROVIDERS_ALLOWED)
return when {
providersAllowed != null && providersAllowed.isNotEmpty() -> "allowed"
else -> "disallowed"
}
return if (isLocationEnabled()) "allowed" else "disallowed"
} catch (exception: Exception) {
logger.w("Could not get locationStatus")
}
return null
}

private fun isLocationEnabled() = when {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.S ->
appContext.getLocationManager()?.isLocationEnabled == true
else -> {
val cr = appContext.contentResolver
@Suppress("DEPRECATION") val providersAllowed =
Settings.Secure.getString(cr, Settings.Secure.LOCATION_PROVIDERS_ALLOWED)
providersAllowed != null && providersAllowed.isNotEmpty()
}
}

/**
* Get the current status of network access, eg "cellular"
*/
Expand Down Expand Up @@ -293,6 +297,9 @@ internal class DeviceDataCollector(
}

fun addRuntimeVersionInfo(key: String, value: String) {
runtimeVersions[key] = value
// Use copy-on-write to avoid a ConcurrentModificationException in generateDeviceWithState
val newRuntimeVersions = runtimeVersions.toMutableMap()
newRuntimeVersions[key] = value
runtimeVersions = newRuntimeVersions
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,24 @@ internal class EventStorageModule(

private val cfg = configModule.config

private val delegate by future {
InternalReportDelegate(
contextModule.ctx,
cfg.logger,
cfg,
systemServiceModule.storageManager,
dataCollectionModule.appDataCollector,
dataCollectionModule.deviceDataCollector,
trackerModule.sessionTracker,
notifier,
bgTaskService
)
}
private val delegate = InternalReportDelegate(
contextModule.ctx,
cfg.logger,
cfg,
systemServiceModule.storageManager,
dataCollectionModule.appDataCollector,
dataCollectionModule.deviceDataCollector,
trackerModule.sessionTracker,
notifier,
bgTaskService
)

val eventStore by future { EventStore(cfg, cfg.logger, notifier, bgTaskService, delegate, callbackState) }
val eventStore = EventStore(
cfg,
cfg.logger,
notifier,
bgTaskService,
delegate,
callbackState
)
}
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.22.2",
var version: String = "5.22.3",
var url: String = "https://bugsnag.com"
) : JsonStream.Streamable {

Expand Down
Loading