1 /* 2 * Copyright (C) 2018 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 package com.android.launcher3.logging; 17 18 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.IGNORE; 19 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_CLOSE_DOWN; 20 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_OPEN_UP; 21 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_HOME_GESTURE; 22 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_OVERVIEW_GESTURE; 23 24 import android.content.Context; 25 26 import androidx.annotation.Nullable; 27 28 import com.android.launcher3.R; 29 import com.android.launcher3.logger.LauncherAtom.ContainerInfo; 30 import com.android.launcher3.logger.LauncherAtom.FromState; 31 import com.android.launcher3.logger.LauncherAtom.ToState; 32 import com.android.launcher3.model.data.ItemInfo; 33 import com.android.launcher3.userevent.LauncherLogProto; 34 import com.android.launcher3.util.ResourceBasedOverride; 35 36 import java.util.List; 37 38 /** 39 * Handles the user event logging in R+. 40 * 41 * <pre> 42 * All of the event ids are defined here. 43 * Most of the methods are dummy methods for Launcher3 44 * Actual call happens only for Launcher variant that implements QuickStep. 45 * </pre> 46 */ 47 public class StatsLogManager implements ResourceBasedOverride { 48 49 public static final int LAUNCHER_STATE_UNSPECIFIED = 0; 50 public static final int LAUNCHER_STATE_BACKGROUND = 1; 51 public static final int LAUNCHER_STATE_HOME = 2; 52 public static final int LAUNCHER_STATE_OVERVIEW = 3; 53 public static final int LAUNCHER_STATE_ALLAPPS = 4; 54 public static final int LAUNCHER_STATE_UNCHANGED = 5; 55 56 /** 57 * Returns proper launcher state enum for {@link StatsLogManager}(to be removed during 58 * UserEventDispatcher cleanup) 59 */ containerTypeToAtomState(int containerType)60 public static int containerTypeToAtomState(int containerType) { 61 switch (containerType) { 62 case LauncherLogProto.ContainerType.ALLAPPS_VALUE: 63 return LAUNCHER_STATE_ALLAPPS; 64 case LauncherLogProto.ContainerType.OVERVIEW_VALUE: 65 return LAUNCHER_STATE_OVERVIEW; 66 case LauncherLogProto.ContainerType.WORKSPACE_VALUE: 67 return LAUNCHER_STATE_HOME; 68 case LauncherLogProto.ContainerType.APP_VALUE: 69 return LAUNCHER_STATE_BACKGROUND; 70 } 71 return LAUNCHER_STATE_UNSPECIFIED; 72 } 73 74 /** 75 * Returns event enum based on the two {@link ContainerType} transition information when swipe 76 * gesture happens(to be removed during UserEventDispatcher cleanup). 77 */ getLauncherAtomEvent(int startContainerType, int targetContainerType, EventEnum fallbackEvent)78 public static EventEnum getLauncherAtomEvent(int startContainerType, 79 int targetContainerType, EventEnum fallbackEvent) { 80 if (startContainerType == LauncherLogProto.ContainerType.WORKSPACE.getNumber() 81 && targetContainerType == LauncherLogProto.ContainerType.WORKSPACE.getNumber()) { 82 return LAUNCHER_HOME_GESTURE; 83 } else if (startContainerType != LauncherLogProto.ContainerType.TASKSWITCHER.getNumber() 84 && targetContainerType == LauncherLogProto.ContainerType.TASKSWITCHER.getNumber()) { 85 return LAUNCHER_OVERVIEW_GESTURE; 86 } else if (startContainerType != LauncherLogProto.ContainerType.ALLAPPS.getNumber() 87 && targetContainerType == LauncherLogProto.ContainerType.ALLAPPS.getNumber()) { 88 return LAUNCHER_ALLAPPS_OPEN_UP; 89 } else if (startContainerType == LauncherLogProto.ContainerType.ALLAPPS.getNumber() 90 && targetContainerType != LauncherLogProto.ContainerType.ALLAPPS.getNumber()) { 91 return LAUNCHER_ALLAPPS_CLOSE_DOWN; 92 } 93 return fallbackEvent; // TODO fix 94 } 95 96 public interface EventEnum { getId()97 int getId(); 98 } 99 100 public enum LauncherEvent implements EventEnum { 101 /* Used to prevent double logging. */ 102 IGNORE(-1), 103 104 @UiEvent(doc = "App launched from workspace, hotseat or folder in launcher") 105 LAUNCHER_APP_LAUNCH_TAP(338), 106 107 @UiEvent(doc = "Task launched from overview using TAP") 108 LAUNCHER_TASK_LAUNCH_TAP(339), 109 110 @UiEvent(doc = "User tapped on notification inside popup context menu.") 111 LAUNCHER_NOTIFICATION_LAUNCH_TAP(516), 112 113 @UiEvent(doc = "Task launched from overview using SWIPE DOWN") 114 LAUNCHER_TASK_LAUNCH_SWIPE_DOWN(340), 115 116 @UiEvent(doc = "TASK dismissed from overview using SWIPE UP") 117 LAUNCHER_TASK_DISMISS_SWIPE_UP(341), 118 119 @UiEvent(doc = "User dragged a launcher item") 120 LAUNCHER_ITEM_DRAG_STARTED(383), 121 122 @UiEvent(doc = "A dragged launcher item is successfully dropped") 123 LAUNCHER_ITEM_DROP_COMPLETED(385), 124 125 @UiEvent(doc = "A dragged launcher item is successfully dropped on another item " 126 + "resulting in a new folder creation") 127 LAUNCHER_ITEM_DROP_FOLDER_CREATED(386), 128 129 @UiEvent(doc = "Folder's label is automatically assigned.") 130 LAUNCHER_FOLDER_AUTO_LABELED(591), 131 132 @UiEvent(doc = "Could not auto-label a folder because primary suggestion is null or empty.") 133 LAUNCHER_FOLDER_AUTO_LABELING_SKIPPED_EMPTY_PRIMARY(592), 134 135 @UiEvent(doc = "Could not auto-label a folder because no suggestions exist.") 136 LAUNCHER_FOLDER_AUTO_LABELING_SKIPPED_EMPTY_SUGGESTIONS(593), 137 138 @UiEvent(doc = "User manually updated the folder label.") 139 LAUNCHER_FOLDER_LABEL_UPDATED(460), 140 141 @UiEvent(doc = "User long pressed on the workspace empty space.") 142 LAUNCHER_WORKSPACE_LONGPRESS(461), 143 144 @UiEvent(doc = "User tapped or long pressed on a wallpaper icon inside launcher settings.") 145 LAUNCHER_WALLPAPER_BUTTON_TAP_OR_LONGPRESS(462), 146 147 @UiEvent(doc = "User tapped or long pressed on settings icon inside launcher settings.") 148 LAUNCHER_SETTINGS_BUTTON_TAP_OR_LONGPRESS(463), 149 150 @UiEvent(doc = "User tapped or long pressed on widget tray icon inside launcher settings.") 151 LAUNCHER_WIDGETSTRAY_BUTTON_TAP_OR_LONGPRESS(464), 152 153 @UiEvent(doc = "A dragged item is dropped on 'Remove' button in the target bar") 154 LAUNCHER_ITEM_DROPPED_ON_REMOVE(465), 155 156 @UiEvent(doc = "A dragged item is dropped on 'Cancel' button in the target bar") 157 LAUNCHER_ITEM_DROPPED_ON_CANCEL(466), 158 159 @UiEvent(doc = "A predicted item is dragged and dropped on 'Don't suggest app'" 160 + " button in the target bar") 161 LAUNCHER_ITEM_DROPPED_ON_DONT_SUGGEST(467), 162 163 @UiEvent(doc = "A dragged item is dropped on 'Uninstall' button in target bar") 164 LAUNCHER_ITEM_DROPPED_ON_UNINSTALL(468), 165 166 @UiEvent(doc = "User completed uninstalling the package after dropping on " 167 + "the icon onto 'Uninstall' button in the target bar") 168 LAUNCHER_ITEM_UNINSTALL_COMPLETED(469), 169 170 @UiEvent(doc = "User cancelled uninstalling the package after dropping on " 171 + "the icon onto 'Uninstall' button in the target bar") 172 LAUNCHER_ITEM_UNINSTALL_CANCELLED(470), 173 174 @UiEvent(doc = "User tapped or long pressed on the task icon(aka package icon) " 175 + "from overview to open task menu.") 176 LAUNCHER_TASK_ICON_TAP_OR_LONGPRESS(517), 177 178 @UiEvent(doc = "User opened package specific widgets list by tapping on widgets system " 179 + "shortcut inside popup context menu.") 180 LAUNCHER_SYSTEM_SHORTCUT_WIDGETS_TAP(514), 181 182 @UiEvent(doc = "User tapped on app info system shortcut.") 183 LAUNCHER_SYSTEM_SHORTCUT_APP_INFO_TAP(515), 184 185 @UiEvent(doc = "User tapped on split screen icon on a task menu.") 186 LAUNCHER_SYSTEM_SHORTCUT_SPLIT_SCREEN_TAP(518), 187 188 @UiEvent(doc = "User tapped on free form icon on a task menu.") 189 LAUNCHER_SYSTEM_SHORTCUT_FREE_FORM_TAP(519), 190 191 @UiEvent(doc = "User tapped on pause app system shortcut.") 192 LAUNCHER_SYSTEM_SHORTCUT_PAUSE_TAP(521), 193 194 @UiEvent(doc = "User tapped on pin system shortcut.") 195 LAUNCHER_SYSTEM_SHORTCUT_PIN_TAP(522), 196 197 @UiEvent(doc = "User is shown All Apps education view.") 198 LAUNCHER_ALL_APPS_EDU_SHOWN(523), 199 200 @UiEvent(doc = "User opened a folder.") 201 LAUNCHER_FOLDER_OPEN(551), 202 203 @UiEvent(doc = "Hotseat education half sheet seen") 204 LAUNCHER_HOTSEAT_EDU_SEEN(479), 205 206 @UiEvent(doc = "Hotseat migration accepted") 207 LAUNCHER_HOTSEAT_EDU_ACCEPT(480), 208 209 @UiEvent(doc = "Hotseat migration denied") 210 LAUNCHER_HOTSEAT_EDU_DENY(481), 211 212 @UiEvent(doc = "Hotseat education tip shown") 213 LAUNCHER_HOTSEAT_EDU_ONLY_TIP(482), 214 215 /** 216 * @deprecated LauncherUiChanged.rank field is repurposed to store all apps rank, so no 217 * separate event is required. 218 */ 219 @Deprecated 220 @UiEvent(doc = "App launch ranking logged for all apps predictions") 221 LAUNCHER_ALL_APPS_RANKED(552), 222 223 @UiEvent(doc = "App launch ranking logged for hotseat predictions)") 224 LAUNCHER_HOTSEAT_RANKED(553), 225 @UiEvent(doc = "Launcher is now in background. e.g., Screen off event") 226 LAUNCHER_ONSTOP(562), 227 228 @UiEvent(doc = "Launcher is now in foreground. e.g., Screen on event, back button") 229 LAUNCHER_ONRESUME(563), 230 231 @UiEvent(doc = "User swipes or fling in LEFT direction on workspace.") 232 LAUNCHER_SWIPELEFT(564), 233 234 @UiEvent(doc = "User swipes or fling in RIGHT direction on workspace.") 235 LAUNCHER_SWIPERIGHT(565), 236 237 @UiEvent(doc = "User swipes or fling in UP direction in unknown way.") 238 LAUNCHER_UNKNOWN_SWIPEUP(566), 239 240 @UiEvent(doc = "User swipes or fling in DOWN direction in unknown way.") 241 LAUNCHER_UNKNOWN_SWIPEDOWN(567), 242 243 @UiEvent(doc = "User swipes or fling in UP direction to open apps drawer.") 244 LAUNCHER_ALLAPPS_OPEN_UP(568), 245 246 @UiEvent(doc = "User swipes or fling in DOWN direction to close apps drawer.") 247 LAUNCHER_ALLAPPS_CLOSE_DOWN(569), 248 249 @UiEvent(doc = "User swipes or fling in UP direction and hold from the bottom bazel area") 250 LAUNCHER_OVERVIEW_GESTURE(570), 251 252 @UiEvent(doc = "User swipes or fling in LEFT direction on the bottom bazel area.") 253 LAUNCHER_QUICKSWITCH_LEFT(571), 254 255 @UiEvent(doc = "User swipes or fling in RIGHT direction on the bottom bazel area.") 256 LAUNCHER_QUICKSWITCH_RIGHT(572), 257 258 @UiEvent(doc = "User swipes or fling in DOWN direction on the bottom bazel area.") 259 LAUNCHER_SWIPEDOWN_NAVBAR(573), 260 261 @UiEvent(doc = "User swipes or fling in UP direction from bottom bazel area.") 262 LAUNCHER_HOME_GESTURE(574), 263 264 @UiEvent(doc = "User's workspace layout information is snapshot in the background.") 265 LAUNCHER_WORKSPACE_SNAPSHOT(579), 266 267 @UiEvent(doc = "User tapped on the screenshot button on overview)") 268 LAUNCHER_OVERVIEW_ACTIONS_SCREENSHOT(580), 269 270 @UiEvent(doc = "User tapped on the select button on overview)") 271 LAUNCHER_OVERVIEW_ACTIONS_SELECT(581), 272 273 @UiEvent(doc = "User tapped on the share button on overview") 274 LAUNCHER_OVERVIEW_ACTIONS_SHARE(582), 275 276 @UiEvent(doc = "User tapped on the close button in select mode") 277 LAUNCHER_SELECT_MODE_CLOSE(583), 278 279 @UiEvent(doc = "User tapped on the highlight items in select mode") 280 LAUNCHER_SELECT_MODE_ITEM(584), 281 282 @UiEvent(doc = "Notification dot on app icon enabled.") 283 LAUNCHER_NOTIFICATION_DOT_ENABLED(611), 284 285 @UiEvent(doc = "Notification dot on app icon disabled.") 286 LAUNCHER_NOTIFICATION_DOT_DISABLED(612), 287 288 @UiEvent(doc = "For new apps, add app icons to home screen enabled.") 289 LAUNCHER_ADD_NEW_APPS_TO_HOME_SCREEN_ENABLED(613), 290 291 @UiEvent(doc = "For new apps, add app icons to home screen disabled.") 292 LAUNCHER_ADD_NEW_APPS_TO_HOME_SCREEN_DISABLED(614), 293 294 @UiEvent(doc = "Home screen rotation is enabled when phone is rotated.") 295 LAUNCHER_HOME_SCREEN_ROTATION_ENABLED(615), 296 297 @UiEvent(doc = "Home screen rotation is disabled when phone is rotated.") 298 LAUNCHER_HOME_SCREEN_ROTATION_DISABLED(616), 299 300 @UiEvent(doc = "Suggestions in all apps list enabled.") 301 LAUNCHER_ALL_APPS_SUGGESTIONS_ENABLED(619), 302 303 @UiEvent(doc = "Suggestions in all apps list disabled.") 304 LAUNCHER_ALL_APPS_SUGGESTIONS_DISABLED(620), 305 306 @UiEvent(doc = "Suggestions on home screen is enabled.") 307 LAUNCHER_HOME_SCREEN_SUGGESTIONS_ENABLED(621), 308 309 @UiEvent(doc = "Suggestions on home screen is disabled.") 310 LAUNCHER_HOME_SCREEN_SUGGESTIONS_DISABLED(622), 311 312 @UiEvent(doc = "System navigation is 3 button mode.") 313 LAUNCHER_NAVIGATION_MODE_3_BUTTON(623), 314 315 @UiEvent(doc = "System navigation mode is 2 button mode.") 316 LAUNCHER_NAVIGATION_MODE_2_BUTTON(624), 317 318 @UiEvent(doc = "System navigation mode is 0 button mode/gesture navigation mode .") 319 LAUNCHER_NAVIGATION_MODE_GESTURE_BUTTON(625), 320 321 @UiEvent(doc = "User tapped on image content in Overview Select mode.") 322 LAUNCHER_SELECT_MODE_IMAGE(627), 323 324 @UiEvent(doc = "User swiped down on workspace (triggering noti shade to open).") 325 LAUNCHER_SWIPE_DOWN_WORKSPACE_NOTISHADE_OPEN(651); 326 // ADD MORE 327 328 private final int mId; 329 LauncherEvent(int id)330 LauncherEvent(int id) { 331 mId = id; 332 } 333 getId()334 public int getId() { 335 return mId; 336 } 337 } 338 339 /** 340 * Launcher specific ranking related events. 341 */ 342 public enum LauncherRankingEvent implements EventEnum { 343 344 UNKNOWN(0); 345 // ADD MORE 346 347 private final int mId; 348 LauncherRankingEvent(int id)349 LauncherRankingEvent(int id) { 350 mId = id; 351 } 352 getId()353 public int getId() { 354 return mId; 355 } 356 } 357 358 /** 359 * Helps to construct and write the log message. 360 */ 361 public interface StatsLogger { 362 363 /** 364 * Sets log fields from provided {@link ItemInfo}. 365 */ withItemInfo(ItemInfo itemInfo)366 default StatsLogger withItemInfo(ItemInfo itemInfo) { 367 return this; 368 } 369 370 371 /** 372 * Sets {@link InstanceId} of log message. 373 */ withInstanceId(InstanceId instanceId)374 default StatsLogger withInstanceId(InstanceId instanceId) { 375 return this; 376 } 377 378 /** 379 * Sets rank field of log message. 380 */ withRank(int rank)381 default StatsLogger withRank(int rank) { 382 return this; 383 } 384 385 /** 386 * Sets source launcher state field of log message. 387 */ withSrcState(int srcState)388 default StatsLogger withSrcState(int srcState) { 389 return this; 390 } 391 392 /** 393 * Sets destination launcher state field of log message. 394 */ withDstState(int dstState)395 default StatsLogger withDstState(int dstState) { 396 return this; 397 } 398 399 /** 400 * Sets FromState field of log message. 401 */ withFromState(FromState fromState)402 default StatsLogger withFromState(FromState fromState) { 403 return this; 404 } 405 406 /** 407 * Sets ToState field of log message. 408 */ withToState(ToState toState)409 default StatsLogger withToState(ToState toState) { 410 return this; 411 } 412 413 /** 414 * Sets editText field of log message. 415 */ withEditText(String editText)416 default StatsLogger withEditText(String editText) { 417 return this; 418 } 419 420 /** 421 * Sets the final value for container related fields of log message. 422 * 423 * By default container related fields are derived from {@link ItemInfo}, this method would 424 * override those values. 425 */ withContainerInfo(ContainerInfo containerInfo)426 default StatsLogger withContainerInfo(ContainerInfo containerInfo) { 427 return this; 428 } 429 430 /** 431 * Builds the final message and logs it as {@link EventEnum}. 432 */ log(EventEnum event)433 default void log(EventEnum event) { 434 } 435 } 436 437 /** 438 * Returns new logger object. 439 */ logger()440 public StatsLogger logger() { 441 return new StatsLogger() { 442 }; 443 } 444 445 /** 446 * Creates a new instance of {@link StatsLogManager} based on provided context. 447 */ newInstance(Context context)448 public static StatsLogManager newInstance(Context context) { 449 StatsLogManager mgr = Overrides.getObject(StatsLogManager.class, 450 context.getApplicationContext(), R.string.stats_log_manager_class); 451 return mgr; 452 } 453 454 /** 455 * Log an event with ranked-choice information along with package. Does nothing if event.getId() 456 * <= 0. 457 * 458 * @param rankingEvent an enum implementing EventEnum interface. 459 * @param instanceId An identifier obtained from an InstanceIdSequence. 460 * @param packageName the package name of the relevant app, if known (null otherwise). 461 * @param position the position picked. 462 */ log(EventEnum rankingEvent, InstanceId instanceId, @Nullable String packageName, int position)463 public void log(EventEnum rankingEvent, InstanceId instanceId, @Nullable String packageName, 464 int position) { 465 } 466 467 /** 468 * Logs impression of the current workspace with additional launcher events. 469 */ logSnapshot(List<EventEnum> additionalEvents)470 public void logSnapshot(List<EventEnum> additionalEvents) { 471 } 472 } 473