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