1 /* 2 * Copyright (C) 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.systemui.media.controls.util 18 19 import com.android.internal.logging.InstanceId 20 import com.android.internal.logging.InstanceIdSequence 21 import com.android.internal.logging.UiEvent 22 import com.android.internal.logging.UiEventLogger 23 import com.android.systemui.dagger.SysUISingleton 24 import com.android.systemui.media.controls.shared.model.MediaData 25 import com.android.systemui.media.controls.ui.controller.MediaHierarchyManager 26 import com.android.systemui.media.controls.ui.controller.MediaLocation 27 import com.android.systemui.res.R 28 import java.lang.IllegalArgumentException 29 import javax.inject.Inject 30 31 private const val INSTANCE_ID_MAX = 1 shl 20 32 33 /** A helper class to log events related to the media controls */ 34 @SysUISingleton 35 class MediaUiEventLogger @Inject constructor(private val logger: UiEventLogger) { 36 37 private val instanceIdSequence = InstanceIdSequence(INSTANCE_ID_MAX) 38 39 /** Get a new instance ID for a new media control */ getNewInstanceIdnull40 fun getNewInstanceId(): InstanceId { 41 return instanceIdSequence.newInstanceId() 42 } 43 logActiveMediaAddednull44 fun logActiveMediaAdded( 45 uid: Int, 46 packageName: String, 47 instanceId: InstanceId, 48 playbackLocation: Int 49 ) { 50 val event = 51 when (playbackLocation) { 52 MediaData.PLAYBACK_LOCAL -> MediaUiEvent.LOCAL_MEDIA_ADDED 53 MediaData.PLAYBACK_CAST_LOCAL -> MediaUiEvent.CAST_MEDIA_ADDED 54 MediaData.PLAYBACK_CAST_REMOTE -> MediaUiEvent.REMOTE_MEDIA_ADDED 55 else -> throw IllegalArgumentException("Unknown playback location") 56 } 57 logger.logWithInstanceId(event, uid, packageName, instanceId) 58 } 59 logPlaybackLocationChangenull60 fun logPlaybackLocationChange( 61 uid: Int, 62 packageName: String, 63 instanceId: InstanceId, 64 playbackLocation: Int 65 ) { 66 val event = 67 when (playbackLocation) { 68 MediaData.PLAYBACK_LOCAL -> MediaUiEvent.TRANSFER_TO_LOCAL 69 MediaData.PLAYBACK_CAST_LOCAL -> MediaUiEvent.TRANSFER_TO_CAST 70 MediaData.PLAYBACK_CAST_REMOTE -> MediaUiEvent.TRANSFER_TO_REMOTE 71 else -> throw IllegalArgumentException("Unknown playback location") 72 } 73 logger.logWithInstanceId(event, uid, packageName, instanceId) 74 } 75 logResumeMediaAddednull76 fun logResumeMediaAdded(uid: Int, packageName: String, instanceId: InstanceId) { 77 logger.logWithInstanceId(MediaUiEvent.RESUME_MEDIA_ADDED, uid, packageName, instanceId) 78 } 79 logActiveConvertedToResumenull80 fun logActiveConvertedToResume(uid: Int, packageName: String, instanceId: InstanceId) { 81 logger.logWithInstanceId(MediaUiEvent.ACTIVE_TO_RESUME, uid, packageName, instanceId) 82 } 83 logMediaTimeoutnull84 fun logMediaTimeout(uid: Int, packageName: String, instanceId: InstanceId) { 85 logger.logWithInstanceId(MediaUiEvent.MEDIA_TIMEOUT, uid, packageName, instanceId) 86 } 87 logMediaRemovednull88 fun logMediaRemoved(uid: Int, packageName: String, instanceId: InstanceId) { 89 logger.logWithInstanceId(MediaUiEvent.MEDIA_REMOVED, uid, packageName, instanceId) 90 } 91 logMediaCarouselPagenull92 fun logMediaCarouselPage(position: Int) { 93 // Since this operation is on the carousel, we don't include package information 94 logger.logWithPosition(MediaUiEvent.CAROUSEL_PAGE, 0, null, position) 95 } 96 logSwipeDismissnull97 fun logSwipeDismiss() { 98 // Since this operation is on the carousel, we don't include package information 99 logger.log(MediaUiEvent.DISMISS_SWIPE) 100 } 101 logLongPressOpennull102 fun logLongPressOpen(uid: Int, packageName: String, instanceId: InstanceId?) { 103 logger.logWithInstanceId(MediaUiEvent.OPEN_LONG_PRESS, uid, packageName, instanceId) 104 } 105 logLongPressDismissnull106 fun logLongPressDismiss(uid: Int, packageName: String, instanceId: InstanceId?) { 107 logger.logWithInstanceId(MediaUiEvent.DISMISS_LONG_PRESS, uid, packageName, instanceId) 108 } 109 logLongPressSettingsnull110 fun logLongPressSettings(uid: Int, packageName: String, instanceId: InstanceId?) { 111 logger.logWithInstanceId( 112 MediaUiEvent.OPEN_SETTINGS_LONG_PRESS, 113 uid, 114 packageName, 115 instanceId 116 ) 117 } 118 logCarouselSettingsnull119 fun logCarouselSettings() { 120 // Since this operation is on the carousel, we don't include package information 121 logger.log(MediaUiEvent.OPEN_SETTINGS_CAROUSEL) 122 } 123 logTapActionnull124 fun logTapAction(buttonId: Int, uid: Int, packageName: String, instanceId: InstanceId) { 125 val event = 126 when (buttonId) { 127 R.id.actionPlayPause -> MediaUiEvent.TAP_ACTION_PLAY_PAUSE 128 R.id.actionPrev -> MediaUiEvent.TAP_ACTION_PREV 129 R.id.actionNext -> MediaUiEvent.TAP_ACTION_NEXT 130 else -> MediaUiEvent.TAP_ACTION_OTHER 131 } 132 133 logger.logWithInstanceId(event, uid, packageName, instanceId) 134 } 135 logSeeknull136 fun logSeek(uid: Int, packageName: String, instanceId: InstanceId) { 137 logger.logWithInstanceId(MediaUiEvent.ACTION_SEEK, uid, packageName, instanceId) 138 } 139 logOpenOutputSwitchernull140 fun logOpenOutputSwitcher(uid: Int, packageName: String, instanceId: InstanceId) { 141 logger.logWithInstanceId(MediaUiEvent.OPEN_OUTPUT_SWITCHER, uid, packageName, instanceId) 142 } 143 logTapContentViewnull144 fun logTapContentView(uid: Int, packageName: String, instanceId: InstanceId) { 145 logger.logWithInstanceId(MediaUiEvent.MEDIA_TAP_CONTENT_VIEW, uid, packageName, instanceId) 146 } 147 logCarouselPositionnull148 fun logCarouselPosition(@MediaLocation location: Int) { 149 val event = 150 when (location) { 151 MediaHierarchyManager.LOCATION_QQS -> MediaUiEvent.MEDIA_CAROUSEL_LOCATION_QQS 152 MediaHierarchyManager.LOCATION_QS -> MediaUiEvent.MEDIA_CAROUSEL_LOCATION_QS 153 MediaHierarchyManager.LOCATION_LOCKSCREEN -> 154 MediaUiEvent.MEDIA_CAROUSEL_LOCATION_LOCKSCREEN 155 MediaHierarchyManager.LOCATION_DREAM_OVERLAY -> 156 MediaUiEvent.MEDIA_CAROUSEL_LOCATION_DREAM 157 MediaHierarchyManager.LOCATION_COMMUNAL_HUB -> 158 MediaUiEvent.MEDIA_CAROUSEL_LOCATION_COMMUNAL 159 else -> throw IllegalArgumentException("Unknown media carousel location $location") 160 } 161 logger.log(event) 162 } 163 logRecommendationAddednull164 fun logRecommendationAdded(packageName: String, instanceId: InstanceId?) { 165 logger.logWithInstanceId( 166 MediaUiEvent.MEDIA_RECOMMENDATION_ADDED, 167 0, 168 packageName, 169 instanceId 170 ) 171 } 172 logRecommendationRemovednull173 fun logRecommendationRemoved(packageName: String, instanceId: InstanceId?) { 174 logger.logWithInstanceId( 175 MediaUiEvent.MEDIA_RECOMMENDATION_REMOVED, 176 0, 177 packageName, 178 instanceId 179 ) 180 } 181 logRecommendationActivatednull182 fun logRecommendationActivated(uid: Int, packageName: String, instanceId: InstanceId) { 183 logger.logWithInstanceId( 184 MediaUiEvent.MEDIA_RECOMMENDATION_ACTIVATED, 185 uid, 186 packageName, 187 instanceId 188 ) 189 } 190 logRecommendationItemTapnull191 fun logRecommendationItemTap(packageName: String, instanceId: InstanceId?, position: Int) { 192 logger.logWithInstanceIdAndPosition( 193 MediaUiEvent.MEDIA_RECOMMENDATION_ITEM_TAP, 194 0, 195 packageName, 196 instanceId, 197 position 198 ) 199 } 200 logRecommendationCardTapnull201 fun logRecommendationCardTap(packageName: String, instanceId: InstanceId?) { 202 logger.logWithInstanceId( 203 MediaUiEvent.MEDIA_RECOMMENDATION_CARD_TAP, 204 0, 205 packageName, 206 instanceId 207 ) 208 } 209 logOpenBroadcastDialognull210 fun logOpenBroadcastDialog(uid: Int, packageName: String, instanceId: InstanceId) { 211 logger.logWithInstanceId( 212 MediaUiEvent.MEDIA_OPEN_BROADCAST_DIALOG, 213 uid, 214 packageName, 215 instanceId 216 ) 217 } 218 logSingleMediaPlayerInCarouselnull219 fun logSingleMediaPlayerInCarousel(uid: Int, packageName: String, instanceId: InstanceId) { 220 logger.logWithInstanceId( 221 MediaUiEvent.MEDIA_CAROUSEL_SINGLE_PLAYER, 222 uid, 223 packageName, 224 instanceId 225 ) 226 } 227 logMultipleMediaPlayersInCarouselnull228 fun logMultipleMediaPlayersInCarousel(uid: Int, packageName: String, instanceId: InstanceId) { 229 logger.logWithInstanceId( 230 MediaUiEvent.MEDIA_CAROUSEL_MULTIPLE_PLAYERS, 231 uid, 232 packageName, 233 instanceId 234 ) 235 } 236 } 237 238 enum class MediaUiEvent(val metricId: Int) : UiEventLogger.UiEventEnum { 239 @UiEvent(doc = "A new media control was added for media playing locally on the device") 240 LOCAL_MEDIA_ADDED(1029), 241 @UiEvent(doc = "A new media control was added for media cast from the device") 242 CAST_MEDIA_ADDED(1030), 243 @UiEvent(doc = "A new media control was added for media playing remotely") 244 REMOTE_MEDIA_ADDED(1031), 245 @UiEvent(doc = "The media for an existing control was transferred to local playback") 246 TRANSFER_TO_LOCAL(1032), 247 @UiEvent(doc = "The media for an existing control was transferred to a cast device") 248 TRANSFER_TO_CAST(1033), 249 @UiEvent(doc = "The media for an existing control was transferred to a remote device") 250 TRANSFER_TO_REMOTE(1034), 251 @UiEvent(doc = "A new resumable media control was added") RESUME_MEDIA_ADDED(1013), 252 @UiEvent(doc = "An existing active media control was converted into resumable media") 253 ACTIVE_TO_RESUME(1014), 254 @UiEvent(doc = "A media control timed out") MEDIA_TIMEOUT(1015), 255 @UiEvent(doc = "A media control was removed from the carousel") MEDIA_REMOVED(1016), 256 @UiEvent(doc = "User swiped to another control within the media carousel") CAROUSEL_PAGE(1017), 257 @UiEvent(doc = "The user swiped away the media carousel") DISMISS_SWIPE(1018), 258 @UiEvent(doc = "The user long pressed on a media control") OPEN_LONG_PRESS(1019), 259 @UiEvent(doc = "The user dismissed a media control via its long press menu") 260 DISMISS_LONG_PRESS(1020), 261 @UiEvent(doc = "The user opened media settings from a media control's long press menu") 262 OPEN_SETTINGS_LONG_PRESS(1021), 263 @UiEvent(doc = "The user opened media settings from the media carousel") 264 OPEN_SETTINGS_CAROUSEL(1022), 265 @UiEvent(doc = "The play/pause button on a media control was tapped") 266 TAP_ACTION_PLAY_PAUSE(1023), 267 @UiEvent(doc = "The previous button on a media control was tapped") TAP_ACTION_PREV(1024), 268 @UiEvent(doc = "The next button on a media control was tapped") TAP_ACTION_NEXT(1025), 269 @UiEvent(doc = "A custom or generic action button on a media control was tapped") 270 TAP_ACTION_OTHER(1026), 271 @UiEvent(doc = "The user seeked on a media control using the seekbar") ACTION_SEEK(1027), 272 @UiEvent(doc = "The user opened the output switcher from a media control") 273 OPEN_OUTPUT_SWITCHER(1028), 274 @UiEvent(doc = "The user tapped on a media control view") MEDIA_TAP_CONTENT_VIEW(1036), 275 @UiEvent(doc = "The media carousel moved to QQS") MEDIA_CAROUSEL_LOCATION_QQS(1037), 276 @UiEvent(doc = "THe media carousel moved to QS") MEDIA_CAROUSEL_LOCATION_QS(1038), 277 @UiEvent(doc = "The media carousel moved to the lockscreen") 278 MEDIA_CAROUSEL_LOCATION_LOCKSCREEN(1039), 279 @UiEvent(doc = "The media carousel moved to the dream state") 280 MEDIA_CAROUSEL_LOCATION_DREAM(1040), 281 @UiEvent(doc = "The media carousel moved to the communal hub UI") 282 MEDIA_CAROUSEL_LOCATION_COMMUNAL(1520), 283 @UiEvent(doc = "A media recommendation card was added to the media carousel") 284 MEDIA_RECOMMENDATION_ADDED(1041), 285 @UiEvent(doc = "A media recommendation card was removed from the media carousel") 286 MEDIA_RECOMMENDATION_REMOVED(1042), 287 @UiEvent(doc = "An existing media control was made active as a recommendation") 288 MEDIA_RECOMMENDATION_ACTIVATED(1043), 289 @UiEvent(doc = "User tapped on an item in a media recommendation card") 290 MEDIA_RECOMMENDATION_ITEM_TAP(1044), 291 @UiEvent(doc = "User tapped on a media recommendation card") 292 MEDIA_RECOMMENDATION_CARD_TAP(1045), 293 @UiEvent(doc = "User opened the broadcast dialog from a media control") 294 MEDIA_OPEN_BROADCAST_DIALOG(1079), 295 @UiEvent(doc = "The media carousel contains one media player card") 296 MEDIA_CAROUSEL_SINGLE_PLAYER(1244), 297 @UiEvent(doc = "The media carousel contains multiple media player cards") 298 MEDIA_CAROUSEL_MULTIPLE_PLAYERS(1245); 299 getIdnull300 override fun getId() = metricId 301 } 302