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

Commit d120ca75 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "[Media TTT] Add analytics logs for the sender chip." into tm-dev

parents bb1a04a5 20e777a7
Loading
Loading
Loading
Loading
+21 −1
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import android.content.Context
import android.media.MediaRoute2Info
import android.view.View
import androidx.annotation.StringRes
import com.android.internal.logging.UiEventLogger
import com.android.internal.statusbar.IUndoMediaTransferCallback
import com.android.systemui.R
import com.android.systemui.media.taptotransfer.common.DEFAULT_TIMEOUT_MILLIS
@@ -39,6 +40,7 @@ import com.android.systemui.media.taptotransfer.common.DEFAULT_TIMEOUT_MILLIS
 */
enum class ChipStateSender(
    @StatusBarManager.MediaTransferSenderState val stateInt: Int,
    val uiEvent: UiEventLogger.UiEventEnum,
    @StringRes val stringResId: Int?,
    val isMidTransfer: Boolean = false,
    val isTransferFailure: Boolean = false,
@@ -51,6 +53,7 @@ enum class ChipStateSender(
     */
    ALMOST_CLOSE_TO_START_CAST(
        StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_ALMOST_CLOSE_TO_START_CAST,
        MediaTttSenderUiEvents.MEDIA_TTT_SENDER_ALMOST_CLOSE_TO_START_CAST,
        R.string.media_move_closer_to_start_cast,
    ),

@@ -62,6 +65,7 @@ enum class ChipStateSender(
     */
    ALMOST_CLOSE_TO_END_CAST(
        StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_ALMOST_CLOSE_TO_END_CAST,
        MediaTttSenderUiEvents.MEDIA_TTT_SENDER_ALMOST_CLOSE_TO_END_CAST,
        R.string.media_move_closer_to_end_cast,
    ),

@@ -71,6 +75,7 @@ enum class ChipStateSender(
     */
    TRANSFER_TO_RECEIVER_TRIGGERED(
        StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_TRIGGERED,
        MediaTttSenderUiEvents.MEDIA_TTT_SENDER_TRANSFER_TO_RECEIVER_TRIGGERED,
        R.string.media_transfer_playing_different_device,
        isMidTransfer = true,
        timeout = TRANSFER_TRIGGERED_TIMEOUT_MILLIS
@@ -82,6 +87,7 @@ enum class ChipStateSender(
     */
    TRANSFER_TO_THIS_DEVICE_TRIGGERED(
        StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_TRIGGERED,
        MediaTttSenderUiEvents.MEDIA_TTT_SENDER_TRANSFER_TO_THIS_DEVICE_TRIGGERED,
        R.string.media_transfer_playing_this_device,
        isMidTransfer = true,
        timeout = TRANSFER_TRIGGERED_TIMEOUT_MILLIS
@@ -92,17 +98,22 @@ enum class ChipStateSender(
     */
    TRANSFER_TO_RECEIVER_SUCCEEDED(
        StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_SUCCEEDED,
        MediaTttSenderUiEvents.MEDIA_TTT_SENDER_TRANSFER_TO_RECEIVER_SUCCEEDED,
        R.string.media_transfer_playing_different_device
    ) {
        override fun undoClickListener(
            controllerSender: MediaTttChipControllerSender,
            routeInfo: MediaRoute2Info,
            undoCallback: IUndoMediaTransferCallback?,
            uiEventLogger: MediaTttSenderUiEventLogger
        ): View.OnClickListener? {
            if (undoCallback == null) {
                return null
            }
            return View.OnClickListener {
                uiEventLogger.logUndoClicked(
                    MediaTttSenderUiEvents.MEDIA_TTT_SENDER_UNDO_TRANSFER_TO_RECEIVER_CLICKED
                )
                undoCallback.onUndoTriggered()
                // The external service should eventually send us a TransferToThisDeviceTriggered
                // state, but that may take too long to go through the binder and the user may be
@@ -122,17 +133,22 @@ enum class ChipStateSender(
     */
    TRANSFER_TO_THIS_DEVICE_SUCCEEDED(
        StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_SUCCEEDED,
        MediaTttSenderUiEvents.MEDIA_TTT_SENDER_TRANSFER_TO_THIS_DEVICE_SUCCEEDED,
        R.string.media_transfer_playing_this_device
    ) {
        override fun undoClickListener(
            controllerSender: MediaTttChipControllerSender,
            routeInfo: MediaRoute2Info,
            undoCallback: IUndoMediaTransferCallback?,
            uiEventLogger: MediaTttSenderUiEventLogger
        ): View.OnClickListener? {
            if (undoCallback == null) {
                return null
            }
            return View.OnClickListener {
                uiEventLogger.logUndoClicked(
                    MediaTttSenderUiEvents.MEDIA_TTT_SENDER_UNDO_TRANSFER_TO_THIS_DEVICE_CLICKED
                )
                undoCallback.onUndoTriggered()
                // The external service should eventually send us a TransferToReceiverTriggered
                // state, but that may take too long to go through the binder and the user may be
@@ -150,6 +166,7 @@ enum class ChipStateSender(
    /** A state representing that a transfer to the receiver device has failed. */
    TRANSFER_TO_RECEIVER_FAILED(
        StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_FAILED,
        MediaTttSenderUiEvents.MEDIA_TTT_SENDER_TRANSFER_TO_RECEIVER_FAILED,
        R.string.media_transfer_failed,
        isTransferFailure = true
    ),
@@ -157,6 +174,7 @@ enum class ChipStateSender(
    /** A state representing that a transfer back to this device has failed. */
    TRANSFER_TO_THIS_DEVICE_FAILED(
        StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_FAILED,
        MediaTttSenderUiEvents.MEDIA_TTT_SENDER_TRANSFER_TO_THIS_DEVICE_FAILED,
        R.string.media_transfer_failed,
        isTransferFailure = true
    ),
@@ -164,6 +182,7 @@ enum class ChipStateSender(
    /** A state representing that this device is far away from any receiver device. */
    FAR_FROM_RECEIVER(
        StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_FAR_FROM_RECEIVER,
        MediaTttSenderUiEvents.MEDIA_TTT_SENDER_FAR_FROM_RECEIVER,
        stringResId = null
    );

@@ -191,7 +210,8 @@ enum class ChipStateSender(
    open fun undoClickListener(
        controllerSender: MediaTttChipControllerSender,
        routeInfo: MediaRoute2Info,
        undoCallback: IUndoMediaTransferCallback?
        undoCallback: IUndoMediaTransferCallback?,
        uiEventLogger: MediaTttSenderUiEventLogger
    ): View.OnClickListener? = null

    companion object {
+3 −1
Original line number Diff line number Diff line
@@ -51,6 +51,7 @@ class MediaTttChipControllerSender @Inject constructor(
    viewUtil: ViewUtil,
    @Main mainExecutor: DelayableExecutor,
    tapGestureDetector: TapGestureDetector,
    private val uiEventLogger: MediaTttSenderUiEventLogger
) : MediaTttChipControllerCommon<ChipSenderInfo>(
    context,
    logger,
@@ -91,6 +92,7 @@ class MediaTttChipControllerSender @Inject constructor(
            Log.e(SENDER_TAG, "Unhandled MediaTransferSenderState $displayState")
            return
        }
        uiEventLogger.logSenderStateChange(chipState)

        if (chipState == ChipStateSender.FAR_FROM_RECEIVER) {
            removeChip(removalReason = ChipStateSender.FAR_FROM_RECEIVER::class.simpleName!!)
@@ -123,7 +125,7 @@ class MediaTttChipControllerSender @Inject constructor(
        // Undo
        val undoView = currentChipView.requireViewById<View>(R.id.undo)
        val undoClickListener = chipState.undoClickListener(
                this, chipInfo.routeInfo, chipInfo.undoCallback
                this, chipInfo.routeInfo, chipInfo.undoCallback, uiEventLogger
        )
        undoView.setOnClickListener(undoClickListener)
        undoView.visibility = (undoClickListener != null).visibleIfTrue()
+82 −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.media.taptotransfer.sender

import android.util.Log
import com.android.internal.logging.UiEvent
import com.android.internal.logging.UiEventLogger
import com.android.systemui.dagger.SysUISingleton
import javax.inject.Inject

/** A class for analytics logging for the media tap-to-transfer chip on the sender device. */
@SysUISingleton
class MediaTttSenderUiEventLogger @Inject constructor(private val logger: UiEventLogger) {
    /** Logs that the sender chip has changed states. */
    fun logSenderStateChange(chipState: ChipStateSender) {
        logger.log(chipState.uiEvent)
    }

    /**
     * Logs that the undo button was clicked.
     *
     * @param undoUiEvent the uiEvent specific to which undo button was clicked.
     */
    fun logUndoClicked(undoUiEvent: UiEventLogger.UiEventEnum) {
        val isUndoEvent =
            undoUiEvent == MediaTttSenderUiEvents.MEDIA_TTT_SENDER_UNDO_TRANSFER_TO_RECEIVER_CLICKED
                    || undoUiEvent ==
                    MediaTttSenderUiEvents.MEDIA_TTT_SENDER_UNDO_TRANSFER_TO_THIS_DEVICE_CLICKED
        if (!isUndoEvent) {
            Log.w(
                MediaTttSenderUiEventLogger::class.simpleName!!,
            "Must pass an undo-specific UiEvent."
            )
            return
        }
        logger.log(undoUiEvent)
    }
}

enum class MediaTttSenderUiEvents(val metricId: Int) : UiEventLogger.UiEventEnum {
    @UiEvent(doc = "The undo button on the media ttt chip on the sender device was clicked " +
            "to undo the transfer to the receiver device")
    MEDIA_TTT_SENDER_UNDO_TRANSFER_TO_RECEIVER_CLICKED(971),
    @UiEvent(doc = "The undo button on the media ttt chip on the sender device was clicked " +
            "to undo the transfer back to this device")
    MEDIA_TTT_SENDER_UNDO_TRANSFER_TO_THIS_DEVICE_CLICKED(972),

    @UiEvent(doc = "See android.app.StatusBarManager.MEDIA_TRANSFER_SENDER_* docs")
    MEDIA_TTT_SENDER_ALMOST_CLOSE_TO_START_CAST(973),
    @UiEvent(doc = "See android.app.StatusBarManager.MEDIA_TRANSFER_SENDER_* docs")
    MEDIA_TTT_SENDER_ALMOST_CLOSE_TO_END_CAST(974),
    @UiEvent(doc = "See android.app.StatusBarManager.MEDIA_TRANSFER_SENDER_* docs")
    MEDIA_TTT_SENDER_TRANSFER_TO_RECEIVER_TRIGGERED(975),
    @UiEvent(doc = "See android.app.StatusBarManager.MEDIA_TRANSFER_SENDER_* docs")
    MEDIA_TTT_SENDER_TRANSFER_TO_THIS_DEVICE_TRIGGERED(976),
    @UiEvent(doc = "See android.app.StatusBarManager.MEDIA_TRANSFER_SENDER_* docs")
    MEDIA_TTT_SENDER_TRANSFER_TO_RECEIVER_SUCCEEDED(977),
    @UiEvent(doc = "See android.app.StatusBarManager.MEDIA_TRANSFER_SENDER_* docs")
    MEDIA_TTT_SENDER_TRANSFER_TO_THIS_DEVICE_SUCCEEDED(978),
    @UiEvent(doc = "See android.app.StatusBarManager.MEDIA_TRANSFER_SENDER_* docs")
    MEDIA_TTT_SENDER_TRANSFER_TO_RECEIVER_FAILED(979),
    @UiEvent(doc = "See android.app.StatusBarManager.MEDIA_TRANSFER_SENDER_* docs")
    MEDIA_TTT_SENDER_TRANSFER_TO_THIS_DEVICE_FAILED(980),
    @UiEvent(doc = "See android.app.StatusBarManager.MEDIA_TRANSFER_SENDER_* docs")
    MEDIA_TTT_SENDER_FAR_FROM_RECEIVER(981);

    override fun getId() = metricId
}
+40 −1
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import androidx.test.filters.SmallTest
import com.android.internal.logging.testing.UiEventLoggerFake
import com.android.internal.statusbar.IUndoMediaTransferCallback
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
@@ -74,6 +75,8 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
    private lateinit var fakeAppIconDrawable: Drawable
    private lateinit var fakeClock: FakeSystemClock
    private lateinit var fakeExecutor: FakeExecutor
    private lateinit var uiEventLoggerFake: UiEventLoggerFake
    private lateinit var senderUiEventLogger: MediaTttSenderUiEventLogger

    @Before
    fun setUp() {
@@ -89,6 +92,8 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {

        fakeClock = FakeSystemClock()
        fakeExecutor = FakeExecutor(fakeClock)
        uiEventLoggerFake = UiEventLoggerFake()
        senderUiEventLogger = MediaTttSenderUiEventLogger(uiEventLoggerFake)

        controllerSender = MediaTttChipControllerSender(
            commandQueue,
@@ -97,7 +102,8 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
            windowManager,
            viewUtil,
            fakeExecutor,
            TapGestureDetector(context)
            TapGestureDetector(context),
            senderUiEventLogger
        )

        val callbackCaptor = ArgumentCaptor.forClass(CommandQueue.Callbacks::class.java)
@@ -116,6 +122,9 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
        assertThat(getChipView().getChipText()).isEqualTo(
            almostCloseToStartCast().state.getChipTextString(context, OTHER_DEVICE_NAME)
        )
        assertThat(uiEventLoggerFake.eventId(0)).isEqualTo(
            MediaTttSenderUiEvents.MEDIA_TTT_SENDER_ALMOST_CLOSE_TO_START_CAST.id
        )
    }

    @Test
@@ -129,6 +138,9 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
        assertThat(getChipView().getChipText()).isEqualTo(
            almostCloseToEndCast().state.getChipTextString(context, OTHER_DEVICE_NAME)
        )
        assertThat(uiEventLoggerFake.eventId(0)).isEqualTo(
            MediaTttSenderUiEvents.MEDIA_TTT_SENDER_ALMOST_CLOSE_TO_END_CAST.id
        )
    }

    @Test
@@ -142,6 +154,9 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
        assertThat(getChipView().getChipText()).isEqualTo(
            transferToReceiverTriggered().state.getChipTextString(context, OTHER_DEVICE_NAME)
        )
        assertThat(uiEventLoggerFake.eventId(0)).isEqualTo(
            MediaTttSenderUiEvents.MEDIA_TTT_SENDER_TRANSFER_TO_RECEIVER_TRIGGERED.id
        )
    }

    @Test
@@ -155,6 +170,9 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
        assertThat(getChipView().getChipText()).isEqualTo(
            transferToThisDeviceTriggered().state.getChipTextString(context, OTHER_DEVICE_NAME)
        )
        assertThat(uiEventLoggerFake.eventId(0)).isEqualTo(
            MediaTttSenderUiEvents.MEDIA_TTT_SENDER_TRANSFER_TO_THIS_DEVICE_TRIGGERED.id
        )
    }

    @Test
@@ -168,6 +186,9 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
        assertThat(getChipView().getChipText()).isEqualTo(
            transferToReceiverSucceeded().state.getChipTextString(context, OTHER_DEVICE_NAME)
        )
        assertThat(uiEventLoggerFake.eventId(0)).isEqualTo(
            MediaTttSenderUiEvents.MEDIA_TTT_SENDER_TRANSFER_TO_RECEIVER_SUCCEEDED.id
        )
    }

    @Test
@@ -181,6 +202,9 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
        assertThat(getChipView().getChipText()).isEqualTo(
            transferToThisDeviceSucceeded().state.getChipTextString(context, OTHER_DEVICE_NAME)
        )
        assertThat(uiEventLoggerFake.eventId(0)).isEqualTo(
            MediaTttSenderUiEvents.MEDIA_TTT_SENDER_TRANSFER_TO_THIS_DEVICE_SUCCEEDED.id
        )
    }

    @Test
@@ -194,6 +218,9 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
        assertThat(getChipView().getChipText()).isEqualTo(
            transferToReceiverFailed().state.getChipTextString(context, OTHER_DEVICE_NAME)
        )
        assertThat(uiEventLoggerFake.eventId(0)).isEqualTo(
            MediaTttSenderUiEvents.MEDIA_TTT_SENDER_TRANSFER_TO_RECEIVER_FAILED.id
        )
    }

    @Test
@@ -207,6 +234,9 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
        assertThat(getChipView().getChipText()).isEqualTo(
            transferToThisDeviceFailed().state.getChipTextString(context, OTHER_DEVICE_NAME)
        )
        assertThat(uiEventLoggerFake.eventId(0)).isEqualTo(
            MediaTttSenderUiEvents.MEDIA_TTT_SENDER_TRANSFER_TO_THIS_DEVICE_FAILED.id
        )
    }

    @Test
@@ -218,6 +248,9 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
        )

        verify(windowManager, never()).addView(any(), any())
        assertThat(uiEventLoggerFake.eventId(0)).isEqualTo(
            MediaTttSenderUiEvents.MEDIA_TTT_SENDER_FAR_FROM_RECEIVER.id
        )
    }

    @Test
@@ -376,6 +409,9 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
        assertThat(getChipView().getChipText()).isEqualTo(
            transferToThisDeviceTriggered().state.getChipTextString(context, OTHER_DEVICE_NAME)
        )
        assertThat(uiEventLoggerFake.eventId(0)).isEqualTo(
            MediaTttSenderUiEvents.MEDIA_TTT_SENDER_UNDO_TRANSFER_TO_RECEIVER_CLICKED.id
        )
    }

    @Test
@@ -440,6 +476,9 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
        assertThat(getChipView().getChipText()).isEqualTo(
            transferToReceiverTriggered().state.getChipTextString(context, OTHER_DEVICE_NAME)
        )
        assertThat(uiEventLoggerFake.eventId(0)).isEqualTo(
            MediaTttSenderUiEvents.MEDIA_TTT_SENDER_UNDO_TRANSFER_TO_THIS_DEVICE_CLICKED.id
        )
    }

    @Test
+46 −0
Original line number Diff line number Diff line
package com.android.systemui.media.taptotransfer.sender

import androidx.test.filters.SmallTest
import com.android.internal.logging.testing.UiEventLoggerFake
import com.android.systemui.SysuiTestCase
import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Test

@SmallTest
class MediaTttSenderUiEventLoggerTest : SysuiTestCase() {
    private lateinit var uiEventLoggerFake: UiEventLoggerFake
    private lateinit var logger: MediaTttSenderUiEventLogger

    @Before
    fun setUp () {
        uiEventLoggerFake = UiEventLoggerFake()
        logger = MediaTttSenderUiEventLogger(uiEventLoggerFake)
    }

    @Test
    fun logSenderStateChange_eventAssociatedWithStateIsLogged() {
        val state = ChipStateSender.ALMOST_CLOSE_TO_END_CAST
        logger.logSenderStateChange(state)

        assertThat(uiEventLoggerFake.numLogs()).isEqualTo(1)
        assertThat(uiEventLoggerFake.eventId(0)).isEqualTo(state.uiEvent.id)
    }

    @Test
    fun logUndoClicked_undoEventLogged() {
        val undoEvent = MediaTttSenderUiEvents.MEDIA_TTT_SENDER_UNDO_TRANSFER_TO_THIS_DEVICE_CLICKED

        logger.logUndoClicked(undoEvent)

        assertThat(uiEventLoggerFake.numLogs()).isEqualTo(1)
        assertThat(uiEventLoggerFake.eventId(0)).isEqualTo(undoEvent.id)
    }

    @Test
    fun logUndoClicked_notUndoEvent_eventNotLogged() {
        logger.logUndoClicked(MediaTttSenderUiEvents.MEDIA_TTT_SENDER_TRANSFER_TO_RECEIVER_FAILED)

        assertThat(uiEventLoggerFake.numLogs()).isEqualTo(0)
    }
}