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