diff options
| author | Jan Althaus <jalt@google.com> | 2018-02-02 09:20:14 +0100 |
|---|---|---|
| committer | Jan Althaus <jalt@google.com> | 2018-02-05 16:56:52 +0100 |
| commit | 92c6decbb8e39f9b5ffae38528f47fcebabf7d44 (patch) | |
| tree | de8686b4182870fdc4fccf7ac0a8ec31800430c5 /core/java | |
| parent | fd673f32393aed9ee20a3ffe9cf882307198811d (diff) | |
Logging for linkify selections
Bug: 67629726, 70246800
Test: Manually validated, ran CTS tests, and framework tests
Change-Id: Icd41f1e171767bc466f47c87a6ab611185745fd4
Diffstat (limited to 'core/java')
4 files changed, 76 insertions, 17 deletions
diff --git a/core/java/android/view/textclassifier/logging/DefaultLogger.java b/core/java/android/view/textclassifier/logging/DefaultLogger.java index 6b848351cbf6..0fd4ab9a88f5 100644 --- a/core/java/android/view/textclassifier/logging/DefaultLogger.java +++ b/core/java/android/view/textclassifier/logging/DefaultLogger.java @@ -79,7 +79,7 @@ public final class DefaultLogger extends Logger { Preconditions.checkNotNull(event); final LogMaker log = new LogMaker(MetricsEvent.TEXT_SELECTION_SESSION) .setType(getLogType(event)) - .setSubtype(MetricsEvent.TEXT_SELECTION_INVOCATION_MANUAL) + .setSubtype(getLogSubType(event)) .setPackageName(event.getPackageName()) .addTaggedData(START_EVENT_DELTA, event.getDurationSinceSessionStart()) .addTaggedData(PREV_EVENT_DELTA, event.getDurationSincePreviousEvent()) @@ -136,6 +136,17 @@ public final class DefaultLogger extends Logger { } } + private static int getLogSubType(SelectionEvent event) { + switch (event.getInvocationMethod()) { + case SelectionEvent.INVOCATION_MANUAL: + return MetricsEvent.TEXT_SELECTION_INVOCATION_MANUAL; + case SelectionEvent.INVOCATION_LINK: + return MetricsEvent.TEXT_SELECTION_INVOCATION_LINK; + default: + return MetricsEvent.TEXT_SELECTION_INVOCATION_UNKNOWN; + } + } + private static String getLogTypeString(int logType) { switch (logType) { case MetricsEvent.ACTION_TEXT_SELECTION_OVERTYPE: @@ -175,6 +186,17 @@ public final class DefaultLogger extends Logger { } } + private static String getLogSubTypeString(int logSubType) { + switch (logSubType) { + case MetricsEvent.TEXT_SELECTION_INVOCATION_MANUAL: + return "MANUAL"; + case MetricsEvent.TEXT_SELECTION_INVOCATION_LINK: + return "LINK"; + default: + return UNKNOWN; + } + } + private static void debugLog(LogMaker log) { if (!DEBUG_LOG_ENABLED) return; @@ -192,6 +214,7 @@ public final class DefaultLogger extends Logger { final String model = Objects.toString(log.getTaggedData(MODEL_NAME), UNKNOWN); final String entity = Objects.toString(log.getTaggedData(ENTITY_TYPE), UNKNOWN); final String type = getLogTypeString(log.getType()); + final String subType = getLogSubTypeString(log.getSubtype()); final int smartStart = Integer.parseInt( Objects.toString(log.getTaggedData(SMART_START), ZERO)); final int smartEnd = Integer.parseInt( @@ -201,8 +224,9 @@ public final class DefaultLogger extends Logger { final int eventEnd = Integer.parseInt( Objects.toString(log.getTaggedData(EVENT_END), ZERO)); - Log.d(LOG_TAG, String.format("%2d: %s/%s, range=%d,%d - smart_range=%d,%d (%s/%s)", - index, type, entity, eventStart, eventEnd, smartStart, smartEnd, widget, model)); + Log.d(LOG_TAG, String.format("%2d: %s/%s/%s, range=%d,%d - smart_range=%d,%d (%s/%s)", + index, type, subType, entity, eventStart, eventEnd, smartStart, smartEnd, widget, + model)); } /** diff --git a/core/java/android/view/textclassifier/logging/Logger.java b/core/java/android/view/textclassifier/logging/Logger.java index 40e4d8ce1a77..4448b2b5b494 100644 --- a/core/java/android/view/textclassifier/logging/Logger.java +++ b/core/java/android/view/textclassifier/logging/Logger.java @@ -71,6 +71,7 @@ public abstract class Logger { public static final String WIDGET_CUSTOM_UNSELECTABLE_TEXTVIEW = "nosel-customview"; public static final String WIDGET_UNKNOWN = "unknown"; + private @SelectionEvent.InvocationMethod int mInvocationMethod; private SelectionEvent mPrevEvent; private SelectionEvent mSmartEvent; private SelectionEvent mStartEvent; @@ -124,16 +125,19 @@ public abstract class Logger { /** * Logs a "selection started" event. * + * @param invocationMethod the way the selection was triggered * @param start the token index of the selected token */ - public final void logSelectionStartedEvent(int start) { + public final void logSelectionStartedEvent( + @SelectionEvent.InvocationMethod int invocationMethod, int start) { if (mConfig == null) { return; } + mInvocationMethod = invocationMethod; logEvent(new SelectionEvent( start, start + 1, SelectionEvent.EVENT_SELECTION_STARTED, - TextClassifier.TYPE_UNKNOWN, NO_SIGNATURE, mConfig)); + TextClassifier.TYPE_UNKNOWN, mInvocationMethod, NO_SIGNATURE, mConfig)); } /** @@ -152,7 +156,7 @@ public abstract class Logger { logEvent(new SelectionEvent( start, end, SelectionEvent.EVENT_SELECTION_MODIFIED, - TextClassifier.TYPE_UNKNOWN, NO_SIGNATURE, mConfig)); + TextClassifier.TYPE_UNKNOWN, mInvocationMethod, NO_SIGNATURE, mConfig)); } /** @@ -179,7 +183,7 @@ public abstract class Logger { final String signature = classification.getSignature(); logEvent(new SelectionEvent( start, end, SelectionEvent.EVENT_SELECTION_MODIFIED, - entityType, signature, mConfig)); + entityType, mInvocationMethod, signature, mConfig)); } /** @@ -213,7 +217,8 @@ public abstract class Logger { ? selection.getEntity(0) : TextClassifier.TYPE_UNKNOWN; final String signature = selection.getSignature(); - logEvent(new SelectionEvent(start, end, eventType, entityType, signature, mConfig)); + logEvent(new SelectionEvent(start, end, eventType, entityType, mInvocationMethod, signature, + mConfig)); } /** @@ -234,7 +239,8 @@ public abstract class Logger { } logEvent(new SelectionEvent( - start, end, actionType, TextClassifier.TYPE_UNKNOWN, NO_SIGNATURE, mConfig)); + start, end, actionType, TextClassifier.TYPE_UNKNOWN, mInvocationMethod, + NO_SIGNATURE, mConfig)); } /** @@ -265,7 +271,8 @@ public abstract class Logger { ? classification.getEntity(0) : TextClassifier.TYPE_UNKNOWN; final String signature = classification.getSignature(); - logEvent(new SelectionEvent(start, end, actionType, entityType, signature, mConfig)); + logEvent(new SelectionEvent(start, end, actionType, entityType, mInvocationMethod, + signature, mConfig)); } private void logEvent(@NonNull SelectionEvent event) { diff --git a/core/java/android/view/textclassifier/logging/SelectionEvent.java b/core/java/android/view/textclassifier/logging/SelectionEvent.java index f40b65571142..a8de3088d8cc 100644 --- a/core/java/android/view/textclassifier/logging/SelectionEvent.java +++ b/core/java/android/view/textclassifier/logging/SelectionEvent.java @@ -98,6 +98,16 @@ public final class SelectionEvent { /** Something else other than User or the default TextClassifier triggered a selection. */ public static final int EVENT_AUTO_SELECTION = 5; + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef({INVOCATION_MANUAL, INVOCATION_LINK}) + public @interface InvocationMethod {} + + /** Selection was invoked by the user long pressing, double tapping, or dragging to select. */ + public static final int INVOCATION_MANUAL = 1; + /** Selection was invoked by the user tapping on a link. */ + public static final int INVOCATION_LINK = 2; + private final int mAbsoluteStart; private final int mAbsoluteEnd; private final @EventType int mEventType; @@ -105,6 +115,7 @@ public final class SelectionEvent { @Nullable private final String mWidgetVersion; private final String mPackageName; private final String mWidgetType; + private final @InvocationMethod int mInvocationMethod; // These fields should only be set by creator of a SelectionEvent. private String mSignature; @@ -121,7 +132,7 @@ public final class SelectionEvent { SelectionEvent( int start, int end, @EventType int eventType, @EntityType String entityType, - String signature, Logger.Config config) { + @InvocationMethod int invocationMethod, String signature, Logger.Config config) { Preconditions.checkArgument(end >= start, "end cannot be less than start"); mAbsoluteStart = start; mAbsoluteEnd = end; @@ -132,6 +143,7 @@ public final class SelectionEvent { mWidgetVersion = config.getWidgetVersion(); mPackageName = Preconditions.checkNotNull(config.getPackageName()); mWidgetType = Preconditions.checkNotNull(config.getWidgetType()); + mInvocationMethod = invocationMethod; } int getAbsoluteStart() { @@ -180,6 +192,13 @@ public final class SelectionEvent { } /** + * Returns the way the selection mode was invoked. + */ + public @InvocationMethod int getInvocationMethod() { + return mInvocationMethod; + } + + /** * Returns the signature of the text classifier result associated with this event. */ public String getSignature() { diff --git a/core/java/android/widget/SelectionActionModeHelper.java b/core/java/android/widget/SelectionActionModeHelper.java index 2e354c1eee1f..9ff5f5910677 100644 --- a/core/java/android/widget/SelectionActionModeHelper.java +++ b/core/java/android/widget/SelectionActionModeHelper.java @@ -111,7 +111,8 @@ public final class SelectionActionModeHelper { mSelectionTracker.onOriginalSelection( getText(mTextView), mTextView.getSelectionStart(), - mTextView.getSelectionEnd()); + mTextView.getSelectionEnd(), + false /*isLink*/); cancelAsyncTask(); if (skipTextClassification()) { startSelectionActionMode(null); @@ -134,7 +135,11 @@ public final class SelectionActionModeHelper { * Starts Link ActionMode. */ public void startLinkActionModeAsync(TextLinks.TextLink textLink) { - //TODO: tracking/logging + mSelectionTracker.onOriginalSelection( + getText(mTextView), + mTextView.getSelectionStart(), + mTextView.getSelectionEnd(), + true /*isLink*/); cancelAsyncTask(); if (skipTextClassification()) { startLinkActionMode(null); @@ -483,7 +488,8 @@ public final class SelectionActionModeHelper { /** * Called when the original selection happens, before smart selection is triggered. */ - public void onOriginalSelection(CharSequence text, int selectionStart, int selectionEnd) { + public void onOriginalSelection( + CharSequence text, int selectionStart, int selectionEnd, boolean isLink) { // If we abandoned a selection and created a new one very shortly after, we may still // have a pending request to log ABANDON, which we flush here. mDelayedLogAbandon.flush(); @@ -492,7 +498,8 @@ public final class SelectionActionModeHelper { mOriginalEnd = mSelectionEnd = selectionEnd; mAllowReset = false; maybeInvalidateLogger(); - mLogger.logSelectionStarted(text, selectionStart); + mLogger.logSelectionStarted(text, selectionStart, + isLink ? SelectionEvent.INVOCATION_LINK : SelectionEvent.INVOCATION_MANUAL); } /** @@ -675,7 +682,9 @@ public final class SelectionActionModeHelper { return Logger.WIDGET_UNSELECTABLE_TEXTVIEW; } - public void logSelectionStarted(CharSequence text, int index) { + public void logSelectionStarted( + CharSequence text, int index, + @SelectionEvent.InvocationMethod int invocationMethod) { try { Preconditions.checkNotNull(text); Preconditions.checkArgumentInRange(index, 0, text.length(), "index"); @@ -684,7 +693,7 @@ public final class SelectionActionModeHelper { } mTokenIterator.setText(mText); mStartIndex = index; - mLogger.logSelectionStartedEvent(0); + mLogger.logSelectionStartedEvent(invocationMethod, 0); } catch (Exception e) { // Avoid crashes due to logging. Log.d(LOG_TAG, e.getMessage()); |
