Skip to content

Commit b29f35c

Browse files
authored
Merge pull request #2642 from DataDog/nogorodnikov/catch-runtime-exception-during-power-battery-intent-processing
Catch exceptions during the Power or Battery broadcast intents processing
2 parents 4df0cde + bfb9889 commit b29f35c

File tree

2 files changed

+61
-18
lines changed

2 files changed

+61
-18
lines changed

dd-sdk-android-core/src/main/kotlin/com/datadog/android/core/internal/system/BroadcastReceiverSystemInfoProvider.kt

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -26,23 +26,34 @@ internal class BroadcastReceiverSystemInfoProvider(
2626
// region BroadcastReceiver
2727

2828
override fun onReceive(context: Context, intent: Intent?) {
29-
when (val action = intent?.action) {
30-
Intent.ACTION_BATTERY_CHANGED -> {
31-
handleBatteryIntent(intent)
32-
}
33-
PowerManager.ACTION_POWER_SAVE_MODE_CHANGED -> {
34-
handlePowerSaveIntent(context)
35-
}
36-
else -> {
37-
internalLogger.log(
38-
InternalLogger.Level.DEBUG,
39-
listOf(
40-
InternalLogger.Target.MAINTAINER,
41-
InternalLogger.Target.TELEMETRY
42-
),
43-
{ "Received unknown broadcast intent: [$action]" }
44-
)
29+
try {
30+
when (val action = intent?.action) {
31+
Intent.ACTION_BATTERY_CHANGED -> {
32+
handleBatteryIntent(intent)
33+
}
34+
35+
PowerManager.ACTION_POWER_SAVE_MODE_CHANGED -> {
36+
handlePowerSaveIntent(context)
37+
}
38+
39+
else -> {
40+
internalLogger.log(
41+
InternalLogger.Level.DEBUG,
42+
listOf(
43+
InternalLogger.Target.MAINTAINER,
44+
InternalLogger.Target.TELEMETRY
45+
),
46+
{ "Received unknown broadcast intent: [$action]" }
47+
)
48+
}
4549
}
50+
} catch (@Suppress("TooGenericExceptionCaught") e: RuntimeException) {
51+
internalLogger.log(
52+
level = InternalLogger.Level.ERROR,
53+
targets = listOf(InternalLogger.Target.USER, InternalLogger.Target.TELEMETRY),
54+
messageBuilder = { ERROR_HANDLING_BROADCAST_INTENT },
55+
throwable = e
56+
)
4657
}
4758
}
4859

@@ -111,6 +122,7 @@ internal class BroadcastReceiverSystemInfoProvider(
111122
private const val DEFAULT_BATTERY_SCALE = 100
112123
private const val BATTERY_UNPLUGGED = -1
113124
private const val BATTERY_LEVEL_UNKNOWN = -1
125+
private const val ERROR_HANDLING_BROADCAST_INTENT = "Error handling system info broadcast intent."
114126

115127
private val batteryFullOrChargingStatus = setOf(
116128
SystemInfo.BatteryStatus.CHARGING,

dd-sdk-android-core/src/test/kotlin/com/datadog/android/core/internal/system/BroadcastReceiverSystemInfoProviderTest.kt

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import android.os.PowerManager
1313
import com.datadog.android.api.InternalLogger
1414
import com.datadog.android.utils.assertj.SystemInfoAssert.Companion.assertThat
1515
import com.datadog.android.utils.forge.Configurator
16+
import fr.xgouchet.elmyr.Forge
1617
import fr.xgouchet.elmyr.annotation.BoolForgery
1718
import fr.xgouchet.elmyr.annotation.Forgery
1819
import fr.xgouchet.elmyr.annotation.IntForgery
@@ -22,6 +23,7 @@ import fr.xgouchet.elmyr.junit5.ForgeExtension
2223
import org.junit.jupiter.api.BeforeEach
2324
import org.junit.jupiter.api.RepeatedTest
2425
import org.junit.jupiter.api.Test
26+
import org.junit.jupiter.api.assertDoesNotThrow
2527
import org.junit.jupiter.api.extension.ExtendWith
2628
import org.junit.jupiter.api.extension.Extensions
2729
import org.junit.jupiter.params.ParameterizedTest
@@ -32,6 +34,7 @@ import org.mockito.junit.jupiter.MockitoSettings
3234
import org.mockito.kotlin.any
3335
import org.mockito.kotlin.doAnswer
3436
import org.mockito.kotlin.doReturn
37+
import org.mockito.kotlin.doThrow
3538
import org.mockito.kotlin.eq
3639
import org.mockito.kotlin.mock
3740
import org.mockito.kotlin.same
@@ -51,7 +54,7 @@ import kotlin.math.roundToInt
5154
@ForgeConfiguration(value = Configurator::class)
5255
internal class BroadcastReceiverSystemInfoProviderTest {
5356

54-
lateinit var testedProvider: BroadcastReceiverSystemInfoProvider
57+
private lateinit var testedProvider: BroadcastReceiverSystemInfoProvider
5558

5659
@Mock
5760
lateinit var mockContext: Context
@@ -442,11 +445,39 @@ internal class BroadcastReceiverSystemInfoProviderTest {
442445
assertThat(systemInfo).hasOnExternalPowerSource(false)
443446
}
444447

448+
@Test
449+
fun `M log error W onReceive { exception during intent processing }`(
450+
forge: Forge
451+
) {
452+
// Given
453+
val intent = mock<Intent>()
454+
val intentType = forge.anElementFrom(
455+
Intent.ACTION_BATTERY_CHANGED,
456+
PowerManager.ACTION_POWER_SAVE_MODE_CHANGED
457+
)
458+
whenever(intent.action) doReturn intentType
459+
when (intentType) {
460+
Intent.ACTION_BATTERY_CHANGED -> {
461+
whenever(intent.getIntExtra(any(), any())) doThrow RuntimeException()
462+
}
463+
PowerManager.ACTION_POWER_SAVE_MODE_CHANGED -> {
464+
val mockPowerManager = mock<PowerManager>()
465+
whenever(mockContext.getSystemService(Context.POWER_SERVICE)) doReturn mockPowerManager
466+
whenever(mockPowerManager.isPowerSaveMode) doThrow RuntimeException()
467+
}
468+
}
469+
470+
// When + Then
471+
assertDoesNotThrow {
472+
testedProvider.onReceive(mockContext, intent)
473+
}
474+
}
475+
445476
// endregion
446477

447478
// region Internal
448479

449-
fun SystemInfo.BatteryStatus.androidStatus(): Int {
480+
private fun SystemInfo.BatteryStatus.androidStatus(): Int {
450481
return when (this) {
451482
SystemInfo.BatteryStatus.UNKNOWN -> BatteryManager.BATTERY_STATUS_UNKNOWN
452483
SystemInfo.BatteryStatus.CHARGING -> BatteryManager.BATTERY_STATUS_CHARGING

0 commit comments

Comments
 (0)