Remove BroadcastReceiver ref on unregister

There were unremoved references in a map in UserBroadcastDispatcher that
were not being removed on unregister, leaking objects.

Test: atest UserBroadcastDispatcherTest
Test: hprof
Fixes: 144937054
Change-Id: Icc33a28711eadcd0d566c468f34e76a3913700f3
This commit is contained in:
Fabian Kozynski
2019-11-21 15:47:23 -05:00
parent b7213a25b1
commit e68fa407ff
2 changed files with 50 additions and 24 deletions

View File

@@ -28,6 +28,7 @@ import android.util.ArrayMap
import android.util.ArraySet
import android.util.Log
import androidx.annotation.MainThread
import androidx.annotation.VisibleForTesting
import com.android.internal.util.Preconditions
import com.android.systemui.Dumpable
import java.io.FileDescriptor
@@ -78,6 +79,14 @@ class UserBroadcastDispatcher(
private val actionsToReceivers = ArrayMap<String, MutableSet<ReceiverData>>()
private val receiverToReceiverData = ArrayMap<BroadcastReceiver, MutableSet<ReceiverData>>()
@VisibleForTesting
internal fun isReceiverReferenceHeld(receiver: BroadcastReceiver): Boolean {
return receiverToReceiverData.contains(receiver) ||
actionsToReceivers.any {
it.value.any { it.receiver == receiver }
}
}
// Only call on BG thread as it reads from the maps
private fun createFilter(): IntentFilter {
Preconditions.checkState(bgHandler.looper.isCurrentThread,
@@ -142,7 +151,7 @@ class UserBroadcastDispatcher(
if (DEBUG) Log.w(TAG, "Unregister receiver: $receiver")
val actions = receiverToReceiverData.getOrElse(receiver) { return }
.flatMap { it.filter.actionsIterator().asSequence().asIterable() }.toSet()
receiverToReceiverData.get(receiver)?.clear()
receiverToReceiverData.remove(receiver)?.clear()
var changed = false
actions.forEach { action ->
actionsToReceivers.get(action)?.removeIf { it.receiver == receiver }

View File

@@ -77,7 +77,7 @@ class UserBroadcastDispatcherTest : SysuiTestCase() {
private lateinit var argumentCaptor: ArgumentCaptor<IntentFilter>
private lateinit var testableLooper: TestableLooper
private lateinit var universalBroadcastReceiver: UserBroadcastDispatcher
private lateinit var userBroadcastDispatcher: UserBroadcastDispatcher
private lateinit var intentFilter: IntentFilter
private lateinit var intentFilterOther: IntentFilter
private lateinit var handler: Handler
@@ -88,9 +88,9 @@ class UserBroadcastDispatcherTest : SysuiTestCase() {
testableLooper = TestableLooper.get(this)
handler = Handler(testableLooper.looper)
universalBroadcastReceiver = UserBroadcastDispatcher(
userBroadcastDispatcher = UserBroadcastDispatcher(
mockContext, USER_ID, handler, testableLooper.looper)
universalBroadcastReceiver.pendingResult = mPendingResult
userBroadcastDispatcher.pendingResult = mPendingResult
}
@Test
@@ -107,11 +107,11 @@ class UserBroadcastDispatcherTest : SysuiTestCase() {
fun testSingleReceiverRegistered() {
intentFilter = IntentFilter(ACTION_1)
universalBroadcastReceiver.registerReceiver(
userBroadcastDispatcher.registerReceiver(
ReceiverData(broadcastReceiver, intentFilter, mockHandler, USER_HANDLE))
testableLooper.processAllMessages()
assertTrue(universalBroadcastReceiver.isRegistered())
assertTrue(userBroadcastDispatcher.isRegistered())
verify(mockContext).registerReceiverAsUser(
any(),
eq(USER_HANDLE),
@@ -127,19 +127,19 @@ class UserBroadcastDispatcherTest : SysuiTestCase() {
fun testSingleReceiverUnregistered() {
intentFilter = IntentFilter(ACTION_1)
universalBroadcastReceiver.registerReceiver(
userBroadcastDispatcher.registerReceiver(
ReceiverData(broadcastReceiver, intentFilter, mockHandler, USER_HANDLE))
testableLooper.processAllMessages()
reset(mockContext)
assertTrue(universalBroadcastReceiver.isRegistered())
assertTrue(userBroadcastDispatcher.isRegistered())
universalBroadcastReceiver.unregisterReceiver(broadcastReceiver)
userBroadcastDispatcher.unregisterReceiver(broadcastReceiver)
testableLooper.processAllMessages()
verify(mockContext, atLeastOnce()).unregisterReceiver(any())
verify(mockContext, never()).registerReceiverAsUser(any(), any(), any(), any(), any())
assertFalse(universalBroadcastReceiver.isRegistered())
assertFalse(userBroadcastDispatcher.isRegistered())
}
@Test
@@ -150,13 +150,13 @@ class UserBroadcastDispatcherTest : SysuiTestCase() {
addCategory(CATEGORY_2)
}
universalBroadcastReceiver.registerReceiver(
userBroadcastDispatcher.registerReceiver(
ReceiverData(broadcastReceiver, intentFilter, mockHandler, USER_HANDLE))
universalBroadcastReceiver.registerReceiver(
userBroadcastDispatcher.registerReceiver(
ReceiverData(broadcastReceiverOther, intentFilterOther, mockHandler, USER_HANDLE))
testableLooper.processAllMessages()
assertTrue(universalBroadcastReceiver.isRegistered())
assertTrue(userBroadcastDispatcher.isRegistered())
verify(mockContext, times(2)).registerReceiverAsUser(
any(),
@@ -178,14 +178,14 @@ class UserBroadcastDispatcherTest : SysuiTestCase() {
intentFilter = IntentFilter(ACTION_1)
intentFilterOther = IntentFilter(ACTION_2)
universalBroadcastReceiver.registerReceiver(
userBroadcastDispatcher.registerReceiver(
ReceiverData(broadcastReceiver, intentFilter, handler, USER_HANDLE))
universalBroadcastReceiver.registerReceiver(
userBroadcastDispatcher.registerReceiver(
ReceiverData(broadcastReceiverOther, intentFilterOther, handler, USER_HANDLE))
val intent = Intent(ACTION_2)
universalBroadcastReceiver.onReceive(mockContext, intent)
userBroadcastDispatcher.onReceive(mockContext, intent)
testableLooper.processAllMessages()
verify(broadcastReceiver, never()).onReceive(any(), any())
@@ -197,14 +197,14 @@ class UserBroadcastDispatcherTest : SysuiTestCase() {
intentFilter = IntentFilter(ACTION_1)
intentFilterOther = IntentFilter(ACTION_2)
universalBroadcastReceiver.registerReceiver(
userBroadcastDispatcher.registerReceiver(
ReceiverData(broadcastReceiver, intentFilter, handler, USER_HANDLE))
universalBroadcastReceiver.registerReceiver(
userBroadcastDispatcher.registerReceiver(
ReceiverData(broadcastReceiver, intentFilterOther, handler, USER_HANDLE))
val intent = Intent(ACTION_2)
universalBroadcastReceiver.onReceive(mockContext, intent)
userBroadcastDispatcher.onReceive(mockContext, intent)
testableLooper.processAllMessages()
verify(broadcastReceiver).onReceive(mockContext, intent)
@@ -217,14 +217,14 @@ class UserBroadcastDispatcherTest : SysuiTestCase() {
intentFilterOther = IntentFilter(ACTION_1)
intentFilterOther.addCategory(CATEGORY_2)
universalBroadcastReceiver.registerReceiver(
userBroadcastDispatcher.registerReceiver(
ReceiverData(broadcastReceiver, intentFilter, handler, USER_HANDLE))
universalBroadcastReceiver.registerReceiver(
userBroadcastDispatcher.registerReceiver(
ReceiverData(broadcastReceiverOther, intentFilterOther, handler, USER_HANDLE))
val intent = Intent(ACTION_1)
universalBroadcastReceiver.onReceive(mockContext, intent)
userBroadcastDispatcher.onReceive(mockContext, intent)
testableLooper.processAllMessages()
verify(broadcastReceiver).onReceive(mockContext, intent)
@@ -234,15 +234,32 @@ class UserBroadcastDispatcherTest : SysuiTestCase() {
@Test
fun testPendingResult() {
intentFilter = IntentFilter(ACTION_1)
universalBroadcastReceiver.registerReceiver(
userBroadcastDispatcher.registerReceiver(
ReceiverData(broadcastReceiver, intentFilter, handler, USER_HANDLE))
val intent = Intent(ACTION_1)
universalBroadcastReceiver.onReceive(mockContext, intent)
userBroadcastDispatcher.onReceive(mockContext, intent)
testableLooper.processAllMessages()
verify(broadcastReceiver).onReceive(mockContext, intent)
verify(broadcastReceiver).pendingResult = mPendingResult
}
@Test
fun testRemoveReceiverReferences() {
intentFilter = IntentFilter(ACTION_1)
userBroadcastDispatcher.registerReceiver(
ReceiverData(broadcastReceiver, intentFilter, handler, USER_HANDLE))
intentFilterOther = IntentFilter(ACTION_1)
intentFilterOther.addAction(ACTION_2)
userBroadcastDispatcher.registerReceiver(
ReceiverData(broadcastReceiverOther, intentFilterOther, handler, USER_HANDLE))
userBroadcastDispatcher.unregisterReceiver(broadcastReceiver)
testableLooper.processAllMessages()
assertFalse(userBroadcastDispatcher.isReceiverReferenceHeld(broadcastReceiver))
}
}