[Media] Add logging for NearbyMediaDevicesManager.

Fixes: 219767651
Test: atest NearbyMediaDevicesManagerTest
Change-Id: I3d1952ae30e5d4c3fa0f234f00883dc4b9bc233a
This commit is contained in:
Caitlin Cassidy
2022-04-18 15:23:49 +00:00
parent 61aa866570
commit 1f94d22ad8
5 changed files with 204 additions and 7 deletions

View File

@@ -188,6 +188,17 @@ public class LogModule {
return factory.create("MediaMuteAwaitLog", 20);
}
/**
* Provides a logging buffer for logs related to the media mute-await connections. See
* {@link com.android.systemui.media.nearby.NearbyMediaDevicesManager}.
*/
@Provides
@SysUISingleton
@NearbyMediaDevicesLog
public static LogBuffer provideNearbyMediaDevicesLogBuffer(LogBufferFactory factory) {
return factory.create("NearbyMediaDevicesLog", 20);
}
/** Allows logging buffers to be tweaked via adb on debug builds but not on prod builds. */
@Provides
@SysUISingleton

View File

@@ -0,0 +1,33 @@
/*
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.systemui.log.dagger;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import com.android.systemui.log.LogBuffer;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import javax.inject.Qualifier;
/** A {@link LogBuffer} for {@link com.android.systemui.media.nearby.NearbyMediaDevicesManager}. */
@Qualifier
@Documented
@Retention(RUNTIME)
public @interface NearbyMediaDevicesLog {
}

View File

@@ -0,0 +1,51 @@
package com.android.systemui.media.nearby
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.log.LogBuffer
import com.android.systemui.log.LogLevel
import com.android.systemui.log.dagger.NearbyMediaDevicesLog
import javax.inject.Inject
/** Log messages for [NearbyMediaDevicesManager]. */
@SysUISingleton
class NearbyMediaDevicesLogger @Inject constructor(
@NearbyMediaDevicesLog private val buffer: LogBuffer
) {
/**
* Log that a new provider was registered.
*
* @param numProviders the total number of providers that are currently registered.
*/
fun logProviderRegistered(numProviders: Int) = buffer.log(
TAG,
LogLevel.DEBUG,
{ int1 = numProviders },
{ "Provider registered; total providers = $int1" }
)
/**
* Log that a new provider was unregistered.
*
* @param numProviders the total number of providers that are currently registered.
*/
fun logProviderUnregistered(numProviders: Int) = buffer.log(
TAG,
LogLevel.DEBUG,
{ int1 = numProviders },
{ "Provider unregistered; total providers = $int1" }
)
/**
* Log that a provider's binder has died.
*
* @param numProviders the total number of providers that are currently registered.
*/
fun logProviderBinderDied(numProviders: Int) = buffer.log(
TAG,
LogLevel.DEBUG,
{ int1 = numProviders },
{ "Provider binder died; total providers = $int1" }
)
}
private const val TAG = "NearbyMediaDevices"

View File

@@ -27,12 +27,11 @@ import javax.inject.Inject
* A service that acts as a bridge between (1) external clients that have data on nearby devices
* that are able to play media and (2) internal clients (like media Output Switcher) that need data
* on these nearby devices.
*
* TODO(b/216313420): Add logging to this class.
*/
@SysUISingleton
class NearbyMediaDevicesManager @Inject constructor(
commandQueue: CommandQueue
commandQueue: CommandQueue,
private val logger: NearbyMediaDevicesLogger
) {
private var providers: MutableList<INearbyMediaDevicesProvider> = mutableListOf()
private var activeCallbacks: MutableList<INearbyMediaDevicesUpdateCallback> = mutableListOf()
@@ -46,13 +45,17 @@ class NearbyMediaDevicesManager @Inject constructor(
newProvider.registerNearbyDevicesCallback(it)
}
providers.add(newProvider)
logger.logProviderRegistered(providers.size)
newProvider.asBinder().linkToDeath(deathRecipient, /* flags= */ 0)
}
override fun unregisterNearbyMediaDevicesProvider(
newProvider: INearbyMediaDevicesProvider
) {
providers.remove(newProvider)
val isRemoved = providers.remove(newProvider)
if (isRemoved) {
logger.logProviderUnregistered(providers.size)
}
}
}
@@ -99,6 +102,7 @@ class NearbyMediaDevicesManager @Inject constructor(
for (i in providers.size - 1 downTo 0) {
if (providers[i].asBinder() == who) {
providers.removeAt(i)
logger.logProviderBinderDied(providers.size)
break
}
}

View File

@@ -5,13 +5,18 @@ import android.media.INearbyMediaDevicesUpdateCallback
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import android.media.NearbyDevice
import android.os.IBinder
import com.android.systemui.statusbar.CommandQueue
import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Test
import org.mockito.ArgumentCaptor
import org.mockito.Mock
import org.mockito.Mockito
import org.mockito.Mockito.anyInt
import org.mockito.Mockito.never
import org.mockito.Mockito.reset
import org.mockito.Mockito.times
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
@SmallTest
@@ -19,16 +24,18 @@ class NearbyMediaDevicesManagerTest : SysuiTestCase() {
private lateinit var manager: NearbyMediaDevicesManager
@Mock
private lateinit var logger: NearbyMediaDevicesLogger
@Mock
private lateinit var commandQueue: CommandQueue
private lateinit var commandQueueCallbacks: CommandQueue.Callbacks
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
manager = NearbyMediaDevicesManager(commandQueue)
manager = NearbyMediaDevicesManager(commandQueue, logger)
val callbackCaptor = ArgumentCaptor.forClass(CommandQueue.Callbacks::class.java)
Mockito.verify(commandQueue).addCallback(callbackCaptor.capture())
verify(commandQueue).addCallback(callbackCaptor.capture())
commandQueueCallbacks = callbackCaptor.value!!
}
@@ -128,9 +135,92 @@ class NearbyMediaDevicesManagerTest : SysuiTestCase() {
assertThat(provider2.lastRegisteredCallback).isEqualTo(callback)
}
@Test
fun providerUnregistered_doesNotReceiveNewCallback() {
val provider = TestProvider()
commandQueueCallbacks.registerNearbyMediaDevicesProvider(provider)
commandQueueCallbacks.unregisterNearbyMediaDevicesProvider(provider)
val callback = object : INearbyMediaDevicesUpdateCallback.Stub() {
override fun onDevicesUpdated(nearbyDevices: List<NearbyDevice>) {}
}
manager.registerNearbyDevicesCallback(callback)
assertThat(provider.lastRegisteredCallback).isEqualTo(null)
}
@Test
fun providerRegistered_isLogged() {
commandQueueCallbacks.registerNearbyMediaDevicesProvider(TestProvider())
verify(logger).logProviderRegistered(numProviders = 1)
}
@Test
fun providerRegisteredTwice_onlyLoggedOnce() {
val provider = TestProvider()
commandQueueCallbacks.registerNearbyMediaDevicesProvider(provider)
commandQueueCallbacks.registerNearbyMediaDevicesProvider(provider)
verify(logger, times(1)).logProviderRegistered(numProviders = 1)
}
@Test
fun multipleProvidersRegistered_isLogged() {
commandQueueCallbacks.registerNearbyMediaDevicesProvider(TestProvider())
commandQueueCallbacks.registerNearbyMediaDevicesProvider(TestProvider())
reset(logger)
commandQueueCallbacks.registerNearbyMediaDevicesProvider(TestProvider())
verify(logger).logProviderRegistered(numProviders = 3)
}
@Test
fun providerUnregistered_isLogged() {
val provider = TestProvider()
commandQueueCallbacks.registerNearbyMediaDevicesProvider(provider)
commandQueueCallbacks.unregisterNearbyMediaDevicesProvider(provider)
verify(logger).logProviderUnregistered(numProviders = 0)
}
@Test
fun multipleProvidersRegisteredThenUnregistered_isLogged() {
val provider = TestProvider()
commandQueueCallbacks.registerNearbyMediaDevicesProvider(provider)
commandQueueCallbacks.registerNearbyMediaDevicesProvider(TestProvider())
commandQueueCallbacks.registerNearbyMediaDevicesProvider(TestProvider())
commandQueueCallbacks.unregisterNearbyMediaDevicesProvider(provider)
verify(logger).logProviderUnregistered(numProviders = 2)
}
@Test
fun providerUnregisteredButNeverRegistered_notLogged() {
commandQueueCallbacks.unregisterNearbyMediaDevicesProvider(TestProvider())
verify(logger, never()).logProviderRegistered(anyInt())
}
@Test
fun providerBinderDied_isLogged() {
val provider = TestProvider()
commandQueueCallbacks.registerNearbyMediaDevicesProvider(provider)
provider.deathRecipient!!.binderDied(provider)
verify(logger).logProviderBinderDied(numProviders = 0)
}
private class TestProvider : INearbyMediaDevicesProvider.Stub() {
var lastRegisteredCallback: INearbyMediaDevicesUpdateCallback? = null
var lastUnregisteredCallback: INearbyMediaDevicesUpdateCallback? = null
var deathRecipient: IBinder.DeathRecipient? = null
override fun registerNearbyDevicesCallback(
callback: INearbyMediaDevicesUpdateCallback
) {
@@ -142,5 +232,13 @@ class NearbyMediaDevicesManagerTest : SysuiTestCase() {
) {
lastUnregisteredCallback = callback
}
override fun asBinder(): IBinder {
return this
}
override fun linkToDeath(recipient: IBinder.DeathRecipient, flags: Int) {
deathRecipient = recipient
}
}
}