[Media TTT] Add analytics logs for the sender chip.

Bug: 216486003
Test: verified logs printed with `adb shell cmd stats print-logs && adb
logcat -s statsd:I | grep --line-buffered ' (90)'`
Test: media.taptotransfer tests

Change-Id: Id5de34611fcd06a9fa5510b710454b1e944c6b36
This commit is contained in:
Caitlin Cassidy
2022-03-03 20:15:30 +00:00
parent a3a5fc8bb2
commit 20e777a725
5 changed files with 192 additions and 3 deletions

View File

@@ -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 {

View File

@@ -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()

View File

@@ -0,0 +1,82 @@
/*
* 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
}

View File

@@ -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

View File

@@ -0,0 +1,46 @@
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)
}
}