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

Commit 1f94d22a authored by Caitlin Cassidy's avatar Caitlin Cassidy
Browse files

[Media] Add logging for NearbyMediaDevicesManager.

Fixes: 219767651
Test: atest NearbyMediaDevicesManagerTest
Change-Id: I3d1952ae30e5d4c3fa0f234f00883dc4b9bc233a
parent 61aa8665
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -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
+33 −0
Original line number Diff line number Diff line
/*
 * 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 {
}
+51 −0
Original line number Diff line number Diff line
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"
+8 −4
Original line number Diff line number Diff line
@@ -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
                }
            }
+101 −3
Original line number Diff line number Diff line
@@ -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
        }
    }
}