Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 76fd89a9 authored by Chaohui Wang's avatar Chaohui Wang
Browse files

Catch crash for broadcastReceiverFlow

Because the flow can be cancelled before registerReceiver,
unregisterReceiver will throw IllegalArgumentException in this case.

Fix: 315727715
Test: unit test
Change-Id: I3889ca0991eb05899449d4b626c7e8f8c5f00572
parent df4a15fb
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -20,13 +20,17 @@ import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.util.Log
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.conflate
import kotlinx.coroutines.flow.flowOn

private const val TAG = "BroadcastReceiverFlow"

/**
 * A [BroadcastReceiver] flow for the given [intentFilter].
 */
@@ -39,4 +43,6 @@ fun Context.broadcastReceiverFlow(intentFilter: IntentFilter): Flow<Intent> = ca
    registerReceiver(broadcastReceiver, intentFilter, Context.RECEIVER_NOT_EXPORTED)

    awaitClose { unregisterReceiver(broadcastReceiver) }
}.catch { e ->
    Log.e(TAG, "Error while broadcastReceiverFlow", e)
}.conflate().flowOn(Dispatchers.Default)
+14 −0
Original line number Diff line number Diff line
@@ -31,8 +31,10 @@ import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.kotlin.any
import org.mockito.kotlin.doAnswer
import org.mockito.kotlin.doThrow
import org.mockito.kotlin.eq
import org.mockito.kotlin.mock
import org.mockito.kotlin.stub

@RunWith(AndroidJUnit4::class)
class BroadcastReceiverFlowTest {
@@ -74,6 +76,18 @@ class BroadcastReceiverFlowTest {
        assertThat(onReceiveIsCalled).isTrue()
    }

    @Test
    fun broadcastReceiverFlow_unregisterReceiverThrowException_noCrash() = runBlocking {
        context.stub {
            on { unregisterReceiver(any()) } doThrow IllegalArgumentException()
        }
        val flow = context.broadcastReceiverFlow(INTENT_FILTER)

        flow.firstWithTimeoutOrNull()

        assertThat(registeredBroadcastReceiver).isNotNull()
    }

    private companion object {
        val INTENT_FILTER = IntentFilter()
    }