Merge "Throw exception if IntentFilter is not valid"

This commit is contained in:
Fabian Kozynski
2019-10-30 14:20:00 +00:00
committed by Android (Google) Code Review
2 changed files with 67 additions and 2 deletions

View File

@@ -23,6 +23,7 @@ import android.os.Handler
import android.os.Looper
import android.os.Message
import android.os.UserHandle
import android.text.TextUtils
import android.util.Log
import android.util.SparseArray
import com.android.internal.annotations.VisibleForTesting
@@ -55,7 +56,8 @@ private const val DEBUG = false
* a given broadcast.
*
* Use only for IntentFilters with actions and optionally categories. It does not support,
* permissions, schemes or data types. Cannot be used for getting sticky broadcasts.
* permissions, schemes, data types or data authorities.
* Cannot be used for getting sticky broadcasts.
*/
@Singleton
open class BroadcastDispatcher @Inject constructor (
@@ -72,11 +74,14 @@ open class BroadcastDispatcher @Inject constructor (
*
* @param receiver A receiver to dispatch the [Intent]
* @param filter A filter to determine what broadcasts should be dispatched to this receiver.
* It will only take into account actions and categories for filtering.
* It will only take into account actions and categories for filtering. It must
* have at least one action.
* @param handler A handler to dispatch [BroadcastReceiver.onReceive]. By default, it is the
* main handler. Pass `null` to use the default.
* @param user A user handle to determine which broadcast should be dispatched to this receiver.
* By default, it is the current user.
* @throws IllegalArgumentException if the filter has other constraints that are not actions or
* categories or the filter has no actions.
*/
@JvmOverloads
fun registerReceiver(
@@ -85,12 +90,23 @@ open class BroadcastDispatcher @Inject constructor (
handler: Handler? = mainHandler,
user: UserHandle = context.user
) {
checkFilter(filter)
this.handler
.obtainMessage(MSG_ADD_RECEIVER,
ReceiverData(receiver, filter, handler ?: mainHandler, user))
.sendToTarget()
}
private fun checkFilter(filter: IntentFilter) {
val sb = StringBuilder()
if (filter.countActions() == 0) sb.append("Filter must contain at least one action. ")
if (filter.countDataAuthorities() != 0) sb.append("Filter cannot contain DataAuthorities. ")
if (filter.countDataPaths() != 0) sb.append("Filter cannot contain DataPaths. ")
if (filter.countDataSchemes() != 0) sb.append("Filter cannot contain DataSchemes. ")
if (filter.countDataTypes() != 0) sb.append("Filter cannot contain DataTypes. ")
if (!TextUtils.isEmpty(sb)) throw IllegalArgumentException(sb.toString())
}
/**
* Unregister receiver for all users.
* <br>

View File

@@ -21,6 +21,7 @@ import android.content.Context
import android.content.IntentFilter
import android.os.Handler
import android.os.Looper
import android.os.PatternMatcher
import android.os.UserHandle
import android.test.suitebuilder.annotation.SmallTest
import android.testing.AndroidTestingRunner
@@ -33,6 +34,7 @@ import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor
import org.mockito.Captor
import org.mockito.Mock
import org.mockito.Mockito.`when`
import org.mockito.Mockito.mock
import org.mockito.Mockito.never
import org.mockito.Mockito.verify
@@ -48,6 +50,10 @@ class BroadcastDispatcherTest : SysuiTestCase() {
val user1 = UserHandle.of(1)
fun <T> capture(argumentCaptor: ArgumentCaptor<T>): T = argumentCaptor.capture()
const val TEST_ACTION = "TEST_ACTION"
const val TEST_SCHEME = "TEST_SCHEME"
const val TEST_PATH = "TEST_PATH"
const val TEST_TYPE = "test/type"
}
@Mock
@@ -83,6 +89,11 @@ class BroadcastDispatcherTest : SysuiTestCase() {
Handler(testableLooper.looper),
testableLooper.looper,
mapOf(0 to mockUBRUser0, 1 to mockUBRUser1))
// These should be valid filters
`when`(intentFilter.countActions()).thenReturn(1)
`when`(intentFilterOther.countActions()).thenReturn(1)
`when`(mockContext.user).thenReturn(user0)
}
@Test
@@ -129,6 +140,44 @@ class BroadcastDispatcherTest : SysuiTestCase() {
verify(mockUBRUser1, never()).unregisterReceiver(broadcastReceiver)
}
@Test(expected = IllegalArgumentException::class)
fun testFilterMustContainActions() {
val testFilter = IntentFilter()
broadcastDispatcher.registerReceiver(broadcastReceiver, testFilter)
}
@Test(expected = IllegalArgumentException::class)
fun testFilterMustNotContainDataScheme() {
val testFilter = IntentFilter(TEST_ACTION).apply {
addDataScheme(TEST_SCHEME)
}
broadcastDispatcher.registerReceiver(broadcastReceiver, testFilter)
}
@Test(expected = IllegalArgumentException::class)
fun testFilterMustNotContainDataAuthority() {
val testFilter = IntentFilter(TEST_ACTION).apply {
addDataAuthority(mock(IntentFilter.AuthorityEntry::class.java))
}
broadcastDispatcher.registerReceiver(broadcastReceiver, testFilter)
}
@Test(expected = IllegalArgumentException::class)
fun testFilterMustNotContainDataPath() {
val testFilter = IntentFilter(TEST_ACTION).apply {
addDataPath(TEST_PATH, PatternMatcher.PATTERN_LITERAL)
}
broadcastDispatcher.registerReceiver(broadcastReceiver, testFilter)
}
@Test(expected = IllegalArgumentException::class)
fun testFilterMustNotContainDataType() {
val testFilter = IntentFilter(TEST_ACTION).apply {
addDataType(TEST_TYPE)
}
broadcastDispatcher.registerReceiver(broadcastReceiver, testFilter)
}
private class TestBroadcastDispatcher(
context: Context,
mainHandler: Handler,