1 /* 2 * Copyright (C) 2017 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 android.view.textclassifier; 18 19 import android.annotation.IntDef; 20 import android.annotation.NonNull; 21 import android.annotation.Nullable; 22 import android.annotation.UserIdInt; 23 import android.os.Parcel; 24 import android.os.Parcelable; 25 import android.os.UserHandle; 26 import android.view.textclassifier.TextClassifier.EntityType; 27 import android.view.textclassifier.TextClassifier.WidgetType; 28 29 import com.android.internal.annotations.VisibleForTesting; 30 import com.android.internal.util.Preconditions; 31 32 import java.lang.annotation.Retention; 33 import java.lang.annotation.RetentionPolicy; 34 import java.util.Locale; 35 import java.util.Objects; 36 37 /** 38 * A selection event. 39 * Specify index parameters as word token indices. 40 */ 41 public final class SelectionEvent implements Parcelable { 42 43 /** @hide */ 44 @Retention(RetentionPolicy.SOURCE) 45 @IntDef({ACTION_OVERTYPE, ACTION_COPY, ACTION_PASTE, ACTION_CUT, 46 ACTION_SHARE, ACTION_SMART_SHARE, ACTION_DRAG, ACTION_ABANDON, 47 ACTION_OTHER, ACTION_SELECT_ALL, ACTION_RESET}) 48 // NOTE: ActionType values should not be lower than 100 to avoid colliding with the other 49 // EventTypes declared below. 50 public @interface ActionType { 51 /* 52 * Terminal event types range: [100,200). 53 * Non-terminal event types range: [200,300). 54 */ 55 } 56 57 /** User typed over the selection. */ 58 public static final int ACTION_OVERTYPE = 100; 59 /** User copied the selection. */ 60 public static final int ACTION_COPY = 101; 61 /** User pasted over the selection. */ 62 public static final int ACTION_PASTE = 102; 63 /** User cut the selection. */ 64 public static final int ACTION_CUT = 103; 65 /** User shared the selection. */ 66 public static final int ACTION_SHARE = 104; 67 /** User clicked the textAssist menu item. */ 68 public static final int ACTION_SMART_SHARE = 105; 69 /** User dragged+dropped the selection. */ 70 public static final int ACTION_DRAG = 106; 71 /** User abandoned the selection. */ 72 public static final int ACTION_ABANDON = 107; 73 /** User performed an action on the selection. */ 74 public static final int ACTION_OTHER = 108; 75 76 // Non-terminal actions. 77 /** User activated Select All */ 78 public static final int ACTION_SELECT_ALL = 200; 79 /** User reset the smart selection. */ 80 public static final int ACTION_RESET = 201; 81 82 /** @hide */ 83 @Retention(RetentionPolicy.SOURCE) 84 @IntDef({ACTION_OVERTYPE, ACTION_COPY, ACTION_PASTE, ACTION_CUT, 85 ACTION_SHARE, ACTION_SMART_SHARE, ACTION_DRAG, ACTION_ABANDON, 86 ACTION_OTHER, ACTION_SELECT_ALL, ACTION_RESET, 87 EVENT_SELECTION_STARTED, EVENT_SELECTION_MODIFIED, 88 EVENT_SMART_SELECTION_SINGLE, EVENT_SMART_SELECTION_MULTI, 89 EVENT_AUTO_SELECTION}) 90 // NOTE: EventTypes declared here must be less than 100 to avoid colliding with the 91 // ActionTypes declared above. 92 public @interface EventType { 93 /* 94 * Range: 1 -> 99. 95 */ 96 } 97 98 /** User started a new selection. */ 99 public static final int EVENT_SELECTION_STARTED = 1; 100 /** User modified an existing selection. */ 101 public static final int EVENT_SELECTION_MODIFIED = 2; 102 /** Smart selection triggered for a single token (word). */ 103 public static final int EVENT_SMART_SELECTION_SINGLE = 3; 104 /** Smart selection triggered spanning multiple tokens (words). */ 105 public static final int EVENT_SMART_SELECTION_MULTI = 4; 106 /** Something else other than User or the default TextClassifier triggered a selection. */ 107 public static final int EVENT_AUTO_SELECTION = 5; 108 109 /** @hide */ 110 @Retention(RetentionPolicy.SOURCE) 111 @IntDef({INVOCATION_MANUAL, INVOCATION_LINK, INVOCATION_UNKNOWN}) 112 public @interface InvocationMethod {} 113 114 /** Selection was invoked by the user long pressing, double tapping, or dragging to select. */ 115 public static final int INVOCATION_MANUAL = 1; 116 /** Selection was invoked by the user tapping on a link. */ 117 public static final int INVOCATION_LINK = 2; 118 /** Unknown invocation method */ 119 public static final int INVOCATION_UNKNOWN = 0; 120 121 static final String NO_SIGNATURE = ""; 122 123 private final int mAbsoluteStart; 124 private final int mAbsoluteEnd; 125 private final @EntityType String mEntityType; 126 127 private @EventType int mEventType; 128 private String mPackageName = ""; 129 private String mWidgetType = TextClassifier.WIDGET_TYPE_UNKNOWN; 130 private @InvocationMethod int mInvocationMethod; 131 @Nullable private String mWidgetVersion; 132 private @UserIdInt int mUserId = UserHandle.USER_NULL; 133 @Nullable private String mResultId; 134 private long mEventTime; 135 private long mDurationSinceSessionStart; 136 private long mDurationSincePreviousEvent; 137 private int mEventIndex; 138 @Nullable private TextClassificationSessionId mSessionId; 139 private int mStart; 140 private int mEnd; 141 private int mSmartStart; 142 private int mSmartEnd; 143 SelectionEvent( int start, int end, @EventType int eventType, @EntityType String entityType, @InvocationMethod int invocationMethod, @Nullable String resultId)144 SelectionEvent( 145 int start, int end, 146 @EventType int eventType, @EntityType String entityType, 147 @InvocationMethod int invocationMethod, @Nullable String resultId) { 148 Preconditions.checkArgument(end >= start, "end cannot be less than start"); 149 mAbsoluteStart = start; 150 mAbsoluteEnd = end; 151 mEventType = eventType; 152 mEntityType = Preconditions.checkNotNull(entityType); 153 mResultId = resultId; 154 mInvocationMethod = invocationMethod; 155 } 156 SelectionEvent(Parcel in)157 private SelectionEvent(Parcel in) { 158 mAbsoluteStart = in.readInt(); 159 mAbsoluteEnd = in.readInt(); 160 mEventType = in.readInt(); 161 mEntityType = in.readString(); 162 mWidgetVersion = in.readInt() > 0 ? in.readString() : null; 163 mPackageName = in.readString(); 164 mWidgetType = in.readString(); 165 mInvocationMethod = in.readInt(); 166 mResultId = in.readString(); 167 mEventTime = in.readLong(); 168 mDurationSinceSessionStart = in.readLong(); 169 mDurationSincePreviousEvent = in.readLong(); 170 mEventIndex = in.readInt(); 171 mSessionId = in.readInt() > 0 172 ? TextClassificationSessionId.CREATOR.createFromParcel(in) : null; 173 mStart = in.readInt(); 174 mEnd = in.readInt(); 175 mSmartStart = in.readInt(); 176 mSmartEnd = in.readInt(); 177 mUserId = in.readInt(); 178 } 179 180 @Override writeToParcel(Parcel dest, int flags)181 public void writeToParcel(Parcel dest, int flags) { 182 dest.writeInt(mAbsoluteStart); 183 dest.writeInt(mAbsoluteEnd); 184 dest.writeInt(mEventType); 185 dest.writeString(mEntityType); 186 dest.writeInt(mWidgetVersion != null ? 1 : 0); 187 if (mWidgetVersion != null) { 188 dest.writeString(mWidgetVersion); 189 } 190 dest.writeString(mPackageName); 191 dest.writeString(mWidgetType); 192 dest.writeInt(mInvocationMethod); 193 dest.writeString(mResultId); 194 dest.writeLong(mEventTime); 195 dest.writeLong(mDurationSinceSessionStart); 196 dest.writeLong(mDurationSincePreviousEvent); 197 dest.writeInt(mEventIndex); 198 dest.writeInt(mSessionId != null ? 1 : 0); 199 if (mSessionId != null) { 200 mSessionId.writeToParcel(dest, flags); 201 } 202 dest.writeInt(mStart); 203 dest.writeInt(mEnd); 204 dest.writeInt(mSmartStart); 205 dest.writeInt(mSmartEnd); 206 dest.writeInt(mUserId); 207 } 208 209 @Override describeContents()210 public int describeContents() { 211 return 0; 212 } 213 214 /** 215 * Creates a "selection started" event. 216 * 217 * @param invocationMethod the way the selection was triggered 218 * @param start the index of the selected text 219 */ 220 @NonNull createSelectionStartedEvent( @electionEvent.InvocationMethod int invocationMethod, int start)221 public static SelectionEvent createSelectionStartedEvent( 222 @SelectionEvent.InvocationMethod int invocationMethod, int start) { 223 return new SelectionEvent( 224 start, start + 1, SelectionEvent.EVENT_SELECTION_STARTED, 225 TextClassifier.TYPE_UNKNOWN, invocationMethod, NO_SIGNATURE); 226 } 227 228 /** 229 * Creates a "selection modified" event. 230 * Use when the user modifies the selection. 231 * 232 * @param start the start (inclusive) index of the selection 233 * @param end the end (exclusive) index of the selection 234 * 235 * @throws IllegalArgumentException if end is less than start 236 */ 237 @NonNull createSelectionModifiedEvent(int start, int end)238 public static SelectionEvent createSelectionModifiedEvent(int start, int end) { 239 Preconditions.checkArgument(end >= start, "end cannot be less than start"); 240 return new SelectionEvent( 241 start, end, SelectionEvent.EVENT_SELECTION_MODIFIED, 242 TextClassifier.TYPE_UNKNOWN, INVOCATION_UNKNOWN, NO_SIGNATURE); 243 } 244 245 /** 246 * Creates a "selection modified" event. 247 * Use when the user modifies the selection and the selection's entity type is known. 248 * 249 * @param start the start (inclusive) index of the selection 250 * @param end the end (exclusive) index of the selection 251 * @param classification the TextClassification object returned by the TextClassifier that 252 * classified the selected text 253 * 254 * @throws IllegalArgumentException if end is less than start 255 */ 256 @NonNull createSelectionModifiedEvent( int start, int end, @NonNull TextClassification classification)257 public static SelectionEvent createSelectionModifiedEvent( 258 int start, int end, @NonNull TextClassification classification) { 259 Preconditions.checkArgument(end >= start, "end cannot be less than start"); 260 Preconditions.checkNotNull(classification); 261 final String entityType = classification.getEntityCount() > 0 262 ? classification.getEntity(0) 263 : TextClassifier.TYPE_UNKNOWN; 264 return new SelectionEvent( 265 start, end, SelectionEvent.EVENT_SELECTION_MODIFIED, 266 entityType, INVOCATION_UNKNOWN, classification.getId()); 267 } 268 269 /** 270 * Creates a "selection modified" event. 271 * Use when a TextClassifier modifies the selection. 272 * 273 * @param start the start (inclusive) index of the selection 274 * @param end the end (exclusive) index of the selection 275 * @param selection the TextSelection object returned by the TextClassifier for the 276 * specified selection 277 * 278 * @throws IllegalArgumentException if end is less than start 279 */ 280 @NonNull createSelectionModifiedEvent( int start, int end, @NonNull TextSelection selection)281 public static SelectionEvent createSelectionModifiedEvent( 282 int start, int end, @NonNull TextSelection selection) { 283 Preconditions.checkArgument(end >= start, "end cannot be less than start"); 284 Preconditions.checkNotNull(selection); 285 final String entityType = selection.getEntityCount() > 0 286 ? selection.getEntity(0) 287 : TextClassifier.TYPE_UNKNOWN; 288 return new SelectionEvent( 289 start, end, SelectionEvent.EVENT_AUTO_SELECTION, 290 entityType, INVOCATION_UNKNOWN, selection.getId()); 291 } 292 293 /** 294 * Creates an event specifying an action taken on a selection. 295 * Use when the user clicks on an action to act on the selected text. 296 * 297 * @param start the start (inclusive) index of the selection 298 * @param end the end (exclusive) index of the selection 299 * @param actionType the action that was performed on the selection 300 * 301 * @throws IllegalArgumentException if end is less than start 302 */ 303 @NonNull createSelectionActionEvent( int start, int end, @SelectionEvent.ActionType int actionType)304 public static SelectionEvent createSelectionActionEvent( 305 int start, int end, @SelectionEvent.ActionType int actionType) { 306 Preconditions.checkArgument(end >= start, "end cannot be less than start"); 307 checkActionType(actionType); 308 return new SelectionEvent( 309 start, end, actionType, TextClassifier.TYPE_UNKNOWN, INVOCATION_UNKNOWN, 310 NO_SIGNATURE); 311 } 312 313 /** 314 * Creates an event specifying an action taken on a selection. 315 * Use when the user clicks on an action to act on the selected text and the selection's 316 * entity type is known. 317 * 318 * @param start the start (inclusive) index of the selection 319 * @param end the end (exclusive) index of the selection 320 * @param actionType the action that was performed on the selection 321 * @param classification the TextClassification object returned by the TextClassifier that 322 * classified the selected text 323 * 324 * @throws IllegalArgumentException if end is less than start 325 * @throws IllegalArgumentException If actionType is not a valid SelectionEvent actionType 326 */ 327 @NonNull createSelectionActionEvent( int start, int end, @SelectionEvent.ActionType int actionType, @NonNull TextClassification classification)328 public static SelectionEvent createSelectionActionEvent( 329 int start, int end, @SelectionEvent.ActionType int actionType, 330 @NonNull TextClassification classification) { 331 Preconditions.checkArgument(end >= start, "end cannot be less than start"); 332 Preconditions.checkNotNull(classification); 333 checkActionType(actionType); 334 final String entityType = classification.getEntityCount() > 0 335 ? classification.getEntity(0) 336 : TextClassifier.TYPE_UNKNOWN; 337 return new SelectionEvent(start, end, actionType, entityType, INVOCATION_UNKNOWN, 338 classification.getId()); 339 } 340 341 /** 342 * @throws IllegalArgumentException If eventType is not an {@link SelectionEvent.ActionType} 343 */ checkActionType(@electionEvent.EventType int eventType)344 private static void checkActionType(@SelectionEvent.EventType int eventType) 345 throws IllegalArgumentException { 346 switch (eventType) { 347 case SelectionEvent.ACTION_OVERTYPE: // fall through 348 case SelectionEvent.ACTION_COPY: // fall through 349 case SelectionEvent.ACTION_PASTE: // fall through 350 case SelectionEvent.ACTION_CUT: // fall through 351 case SelectionEvent.ACTION_SHARE: // fall through 352 case SelectionEvent.ACTION_SMART_SHARE: // fall through 353 case SelectionEvent.ACTION_DRAG: // fall through 354 case SelectionEvent.ACTION_ABANDON: // fall through 355 case SelectionEvent.ACTION_SELECT_ALL: // fall through 356 case SelectionEvent.ACTION_RESET: // fall through 357 case SelectionEvent.ACTION_OTHER: // fall through 358 return; 359 default: 360 throw new IllegalArgumentException( 361 String.format(Locale.US, "%d is not an eventType", eventType)); 362 } 363 } 364 getAbsoluteStart()365 int getAbsoluteStart() { 366 return mAbsoluteStart; 367 } 368 getAbsoluteEnd()369 int getAbsoluteEnd() { 370 return mAbsoluteEnd; 371 } 372 373 /** 374 * Returns the type of event that was triggered. e.g. {@link #ACTION_COPY}. 375 */ 376 @EventType getEventType()377 public int getEventType() { 378 return mEventType; 379 } 380 381 /** 382 * Sets the event type. 383 * @hide 384 */ 385 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) setEventType(@ventType int eventType)386 public void setEventType(@EventType int eventType) { 387 mEventType = eventType; 388 } 389 390 /** 391 * Returns the type of entity that is associated with this event. e.g. 392 * {@link android.view.textclassifier.TextClassifier#TYPE_EMAIL}. 393 */ 394 @EntityType 395 @NonNull getEntityType()396 public String getEntityType() { 397 return mEntityType; 398 } 399 400 /** 401 * Returns the package name of the app that this event originated in. 402 */ 403 @NonNull getPackageName()404 public String getPackageName() { 405 return mPackageName; 406 } 407 408 /** 409 * Sets the id of this event's user. 410 * <p> 411 * Package-private for SystemTextClassifier's use. 412 */ setUserId(@serIdInt int userId)413 void setUserId(@UserIdInt int userId) { 414 mUserId = userId; 415 } 416 417 /** 418 * Returns the id of this event's user. 419 * @hide 420 */ 421 @UserIdInt getUserId()422 public int getUserId() { 423 return mUserId; 424 } 425 426 /** 427 * Returns the type of widget that was involved in triggering this event. 428 */ 429 @WidgetType 430 @NonNull getWidgetType()431 public String getWidgetType() { 432 return mWidgetType; 433 } 434 435 /** 436 * Returns a string version info for the widget this event was triggered in. 437 */ 438 @Nullable getWidgetVersion()439 public String getWidgetVersion() { 440 return mWidgetVersion; 441 } 442 443 /** 444 * Sets the {@link TextClassificationContext} for this event. 445 * @hide 446 */ 447 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) setTextClassificationSessionContext(TextClassificationContext context)448 public void setTextClassificationSessionContext(TextClassificationContext context) { 449 mPackageName = context.getPackageName(); 450 mWidgetType = context.getWidgetType(); 451 mWidgetVersion = context.getWidgetVersion(); 452 mUserId = context.getUserId(); 453 } 454 455 /** 456 * Returns the way the selection mode was invoked. 457 */ getInvocationMethod()458 public @InvocationMethod int getInvocationMethod() { 459 return mInvocationMethod; 460 } 461 462 /** 463 * Sets the invocationMethod for this event. 464 * @hide 465 */ 466 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) setInvocationMethod(@nvocationMethod int invocationMethod)467 public void setInvocationMethod(@InvocationMethod int invocationMethod) { 468 mInvocationMethod = invocationMethod; 469 } 470 471 /** 472 * Returns the id of the text classifier result associated with this event. 473 */ 474 @Nullable getResultId()475 public String getResultId() { 476 return mResultId; 477 } 478 setResultId(@ullable String resultId)479 SelectionEvent setResultId(@Nullable String resultId) { 480 mResultId = resultId; 481 return this; 482 } 483 484 /** 485 * Returns the time this event was triggered. 486 */ getEventTime()487 public long getEventTime() { 488 return mEventTime; 489 } 490 setEventTime(long timeMs)491 SelectionEvent setEventTime(long timeMs) { 492 mEventTime = timeMs; 493 return this; 494 } 495 496 /** 497 * Returns the duration in ms between when this event was triggered and when the first event in 498 * the selection session was triggered. 499 */ getDurationSinceSessionStart()500 public long getDurationSinceSessionStart() { 501 return mDurationSinceSessionStart; 502 } 503 setDurationSinceSessionStart(long durationMs)504 SelectionEvent setDurationSinceSessionStart(long durationMs) { 505 mDurationSinceSessionStart = durationMs; 506 return this; 507 } 508 509 /** 510 * Returns the duration in ms between when this event was triggered and when the previous event 511 * in the selection session was triggered. 512 */ getDurationSincePreviousEvent()513 public long getDurationSincePreviousEvent() { 514 return mDurationSincePreviousEvent; 515 } 516 setDurationSincePreviousEvent(long durationMs)517 SelectionEvent setDurationSincePreviousEvent(long durationMs) { 518 this.mDurationSincePreviousEvent = durationMs; 519 return this; 520 } 521 522 /** 523 * Returns the index (e.g. 1st event, 2nd event, etc.) of this event in the selection session. 524 */ getEventIndex()525 public int getEventIndex() { 526 return mEventIndex; 527 } 528 529 /** @hide */ 530 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) setEventIndex(int index)531 public SelectionEvent setEventIndex(int index) { 532 mEventIndex = index; 533 return this; 534 } 535 536 /** 537 * Returns the selection session id. 538 */ 539 @Nullable getSessionId()540 public TextClassificationSessionId getSessionId() { 541 return mSessionId; 542 } 543 544 /** @hide */ 545 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) setSessionId(@ullable TextClassificationSessionId id)546 public SelectionEvent setSessionId(@Nullable TextClassificationSessionId id) { 547 mSessionId = id; 548 return this; 549 } 550 551 /** 552 * Returns the start index of this events relative to the index of the start selection 553 * event in the selection session. 554 */ getStart()555 public int getStart() { 556 return mStart; 557 } 558 559 /** @hide */ 560 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) setStart(int start)561 public SelectionEvent setStart(int start) { 562 mStart = start; 563 return this; 564 } 565 566 /** 567 * Returns the end index of this events relative to the index of the start selection 568 * event in the selection session. 569 */ getEnd()570 public int getEnd() { 571 return mEnd; 572 } 573 574 /** @hide */ 575 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) setEnd(int end)576 public SelectionEvent setEnd(int end) { 577 mEnd = end; 578 return this; 579 } 580 581 /** 582 * Returns the start index of this events relative to the index of the smart selection 583 * event in the selection session. 584 */ getSmartStart()585 public int getSmartStart() { 586 return mSmartStart; 587 } 588 589 /** @hide */ 590 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) setSmartStart(int start)591 public SelectionEvent setSmartStart(int start) { 592 this.mSmartStart = start; 593 return this; 594 } 595 596 /** 597 * Returns the end index of this events relative to the index of the smart selection 598 * event in the selection session. 599 */ getSmartEnd()600 public int getSmartEnd() { 601 return mSmartEnd; 602 } 603 604 /** @hide */ 605 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) setSmartEnd(int end)606 public SelectionEvent setSmartEnd(int end) { 607 mSmartEnd = end; 608 return this; 609 } 610 isTerminal()611 boolean isTerminal() { 612 return isTerminal(mEventType); 613 } 614 615 /** 616 * Returns true if the eventType is a terminal event type. Otherwise returns false. 617 * A terminal event is an event that ends a selection interaction. 618 */ isTerminal(@ventType int eventType)619 public static boolean isTerminal(@EventType int eventType) { 620 switch (eventType) { 621 case ACTION_OVERTYPE: // fall through 622 case ACTION_COPY: // fall through 623 case ACTION_PASTE: // fall through 624 case ACTION_CUT: // fall through 625 case ACTION_SHARE: // fall through 626 case ACTION_SMART_SHARE: // fall through 627 case ACTION_DRAG: // fall through 628 case ACTION_ABANDON: // fall through 629 case ACTION_OTHER: // fall through 630 return true; 631 default: 632 return false; 633 } 634 } 635 636 @Override hashCode()637 public int hashCode() { 638 return Objects.hash(mAbsoluteStart, mAbsoluteEnd, mEventType, mEntityType, 639 mWidgetVersion, mPackageName, mUserId, mWidgetType, mInvocationMethod, mResultId, 640 mEventTime, mDurationSinceSessionStart, mDurationSincePreviousEvent, 641 mEventIndex, mSessionId, mStart, mEnd, mSmartStart, mSmartEnd); 642 } 643 644 @Override equals(Object obj)645 public boolean equals(Object obj) { 646 if (this == obj) { 647 return true; 648 } 649 if (!(obj instanceof SelectionEvent)) { 650 return false; 651 } 652 653 final SelectionEvent other = (SelectionEvent) obj; 654 return mAbsoluteStart == other.mAbsoluteStart 655 && mAbsoluteEnd == other.mAbsoluteEnd 656 && mEventType == other.mEventType 657 && Objects.equals(mEntityType, other.mEntityType) 658 && Objects.equals(mWidgetVersion, other.mWidgetVersion) 659 && Objects.equals(mPackageName, other.mPackageName) 660 && mUserId == other.mUserId 661 && Objects.equals(mWidgetType, other.mWidgetType) 662 && mInvocationMethod == other.mInvocationMethod 663 && Objects.equals(mResultId, other.mResultId) 664 && mEventTime == other.mEventTime 665 && mDurationSinceSessionStart == other.mDurationSinceSessionStart 666 && mDurationSincePreviousEvent == other.mDurationSincePreviousEvent 667 && mEventIndex == other.mEventIndex 668 && Objects.equals(mSessionId, other.mSessionId) 669 && mStart == other.mStart 670 && mEnd == other.mEnd 671 && mSmartStart == other.mSmartStart 672 && mSmartEnd == other.mSmartEnd; 673 } 674 675 @Override toString()676 public String toString() { 677 return String.format(Locale.US, 678 "SelectionEvent {absoluteStart=%d, absoluteEnd=%d, eventType=%d, entityType=%s, " 679 + "widgetVersion=%s, packageName=%s, widgetType=%s, invocationMethod=%s, " 680 + "userId=%d, resultId=%s, eventTime=%d, durationSinceSessionStart=%d, " 681 + "durationSincePreviousEvent=%d, eventIndex=%d," 682 + "sessionId=%s, start=%d, end=%d, smartStart=%d, smartEnd=%d}", 683 mAbsoluteStart, mAbsoluteEnd, mEventType, mEntityType, 684 mWidgetVersion, mPackageName, mWidgetType, mInvocationMethod, 685 mUserId, mResultId, mEventTime, mDurationSinceSessionStart, 686 mDurationSincePreviousEvent, mEventIndex, 687 mSessionId, mStart, mEnd, mSmartStart, mSmartEnd); 688 } 689 690 public static final @android.annotation.NonNull Creator<SelectionEvent> CREATOR = new Creator<SelectionEvent>() { 691 @Override 692 public SelectionEvent createFromParcel(Parcel in) { 693 return new SelectionEvent(in); 694 } 695 696 @Override 697 public SelectionEvent[] newArray(int size) { 698 return new SelectionEvent[size]; 699 } 700 }; 701 } 702