Skip to content
Snippets Groups Projects
Unverified Commit 1c863658 authored by Matthias Urhahn's avatar Matthias Urhahn Committed by GitHub
Browse files

Fix potential crash on network check (DEV) (#3066)


```
java.lang.IllegalArgumentException:
  at com.android.internal.util.Preconditions.checkArgument (Preconditions.java:52)
  at android.net.ConnectivityManager.unregisterNetworkCallback (ConnectivityManager.java:4750)
  at de.rki.coronawarnapp.util.network.NetworkStateProvider$networkState$1$2.invoke (NetworkStateProvider.kt:4)
```

Co-authored-by: default avatarharambasicluka <64483219+harambasicluka@users.noreply.github.com>
parent bb93699a
No related branches found
No related tags found
No related merge requests found
...@@ -40,23 +40,26 @@ class NetworkStateProvider @Inject constructor( ...@@ -40,23 +40,26 @@ class NetworkStateProvider @Inject constructor(
val networkState: Flow<State> = callbackFlow { val networkState: Flow<State> = callbackFlow {
send(currentState) send(currentState)
val callback = object : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) {
Timber.tag(TAG).v("onAvailable(network=%s)", network)
appScope.launch { send(currentState) }
}
override fun onUnavailable() {
Timber.tag(TAG).v("onUnavailable()")
appScope.launch { send(currentState) }
}
}
val request = networkRequestBuilderProvider.get() val request = networkRequestBuilderProvider.get()
.addCapability(NET_CAPABILITY_INTERNET) .addCapability(NET_CAPABILITY_INTERNET)
.build() .build()
var registeredCallback: ConnectivityManager.NetworkCallback? = null
try { try {
val callback = object : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) {
Timber.tag(TAG).v("onAvailable(network=%s)", network)
appScope.launch { send(currentState) }
}
override fun onUnavailable() {
Timber.tag(TAG).v("onUnavailable()")
appScope.launch { send(currentState) }
}
}
/** /**
* This may throw java.lang.SecurityException on Samsung devices * This may throw java.lang.SecurityException on Samsung devices
* java.lang.SecurityException: * java.lang.SecurityException:
...@@ -64,6 +67,7 @@ class NetworkStateProvider @Inject constructor( ...@@ -64,6 +67,7 @@ class NetworkStateProvider @Inject constructor(
* at android.net.ConnectivityManager.registerNetworkCallback (ConnectivityManager.java:4564) * at android.net.ConnectivityManager.registerNetworkCallback (ConnectivityManager.java:4564)
*/ */
manager.registerNetworkCallback(request, callback) manager.registerNetworkCallback(request, callback)
registeredCallback = callback
} catch (e: SecurityException) { } catch (e: SecurityException) {
Timber.e(e, "registerNetworkCallback() threw an undocumented SecurityException, Just Samsung Things™️") Timber.e(e, "registerNetworkCallback() threw an undocumented SecurityException, Just Samsung Things™️")
State( State(
...@@ -82,8 +86,8 @@ class NetworkStateProvider @Inject constructor( ...@@ -82,8 +86,8 @@ class NetworkStateProvider @Inject constructor(
} }
awaitClose { awaitClose {
Timber.tag(TAG).v("unregisterNetworkCallback()") Timber.tag(TAG).v("unregisterNetworkCallback(%s)", registeredCallback)
manager.unregisterNetworkCallback(callback) registeredCallback?.let { manager.unregisterNetworkCallback(it) }
fakeConnectionSubscriber.cancel() fakeConnectionSubscriber.cancel()
} }
} }
......
...@@ -237,4 +237,33 @@ class NetworkStateProviderTest : BaseTest() { ...@@ -237,4 +237,33 @@ class NetworkStateProviderTest : BaseTest() {
linkProperties = null linkProperties = null
).isMeteredConnection shouldBe true ).isMeteredConnection shouldBe true
} }
@Test
fun `if we fail to register the callback, we do not attempt to unregister it`() =
runBlockingTest2(ignoreActive = true) {
every {
conMan.registerNetworkCallback(
any(),
any<ConnectivityManager.NetworkCallback>()
)
} throws SecurityException()
val instance = createInstance(this)
instance.networkState.first() shouldBe NetworkStateProvider.State(
activeNetwork = null,
capabilities = null,
linkProperties = null
)
advanceUntilIdle()
verifySequence {
conMan.activeNetwork
conMan.getNetworkCapabilities(network)
conMan.getLinkProperties(network)
conMan.registerNetworkCallback(networkRequest, any<ConnectivityManager.NetworkCallback>())
}
verify(exactly = 0) { conMan.unregisterNetworkCallback(any<ConnectivityManager.NetworkCallback>()) }
}
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment