Logging for linkify selections
Bug: 67629726, 70246800 Test: Manually validated, ran CTS tests, and framework tests Change-Id: Icd41f1e171767bc466f47c87a6ab611185745fd4
This commit is contained in:
@@ -50292,7 +50292,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
|
||||
@@ -50322,6 +50322,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();
|
||||
@@ -50346,6 +50347,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
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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());
|
||||
|
||||
Reference in New Issue
Block a user