Merge "Logging for linkify selections"

This commit is contained in:
TreeHugger Robot
2018-02-12 14:44:35 +00:00
committed by Android (Google) Code Review
5 changed files with 80 additions and 18 deletions

View File

@@ -50372,7 +50372,7 @@ package android.view.textclassifier.logging {
method public final void logSelectionModifiedEvent(int, int);
method public final void logSelectionModifiedEvent(int, int, android.view.textclassifier.TextClassification);
method public final void logSelectionModifiedEvent(int, int, android.view.textclassifier.TextSelection);
method public final void logSelectionStartedEvent(int);
method public final void logSelectionStartedEvent(int, int);
method public abstract void writeEvent(android.view.textclassifier.logging.SelectionEvent);
field public static final int OUT_OF_BOUNDS = 2147483647; // 0x7fffffff
field public static final int OUT_OF_BOUNDS_NEGATIVE = -2147483648; // 0x80000000
@@ -50402,6 +50402,7 @@ package android.view.textclassifier.logging {
method public int getEventIndex();
method public long getEventTime();
method public int getEventType();
method public int getInvocationMethod();
method public java.lang.String getPackageName();
method public java.lang.String getSessionId();
method public java.lang.String getSignature();
@@ -50426,6 +50427,8 @@ package android.view.textclassifier.logging {
field public static final int EVENT_SELECTION_STARTED = 1; // 0x1
field public static final int EVENT_SMART_SELECTION_MULTI = 4; // 0x4
field public static final int EVENT_SMART_SELECTION_SINGLE = 3; // 0x3
field public static final int INVOCATION_LINK = 2; // 0x2
field public static final int INVOCATION_MANUAL = 1; // 0x1
}
}

View File

@@ -80,7 +80,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())
@@ -137,6 +137,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:
@@ -176,6 +187,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;
@@ -193,6 +215,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(
@@ -202,8 +225,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));
}
/**

View File

@@ -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) {

View File

@@ -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() {
@@ -179,6 +191,13 @@ public final class SelectionEvent {
return mWidgetVersion;
}
/**
* 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.
*/

View File

@@ -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);
@@ -487,7 +492,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();
@@ -496,7 +502,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);
}
/**
@@ -679,7 +686,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");
@@ -688,7 +697,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());