Loading config/hiddenapi-light-greylist.txt +0 −1 Original line number Diff line number Diff line Loading @@ -2245,7 +2245,6 @@ Landroid/view/SurfaceView;->mRequestedFormat:I Landroid/view/SurfaceView;->mSurfaceHolder:Landroid/view/SurfaceHolder; Landroid/view/SurfaceView;->surfacePositionLost_uiRtSync(J)V Landroid/view/SurfaceView;->updateSurfacePosition_renderWorker(JIIII)V Landroid/view/textclassifier/Logger;->DISABLED:Landroid/view/textclassifier/Logger; Landroid/view/textclassifier/logging/SmartSelectionEventTracker;-><init>(Landroid/content/Context;I)V Landroid/view/textclassifier/logging/SmartSelectionEventTracker;->logEvent(Landroid/view/textclassifier/logging/SmartSelectionEventTracker$SelectionEvent;)V Landroid/view/textclassifier/logging/SmartSelectionEventTracker$SelectionEvent;->selectionAction(III)Landroid/view/textclassifier/logging/SmartSelectionEventTracker$SelectionEvent; Loading core/java/android/view/textclassifier/GenerateLinksLogger.java +6 −4 Original line number Diff line number Diff line Loading @@ -19,13 +19,13 @@ package android.view.textclassifier; import android.annotation.Nullable; import android.metrics.LogMaker; import android.util.ArrayMap; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.util.Preconditions; import java.util.Locale; import java.util.Map; import java.util.Objects; import java.util.Random; Loading @@ -39,6 +39,7 @@ import java.util.UUID; public final class GenerateLinksLogger { private static final String LOG_TAG = "GenerateLinksLogger"; private static final boolean DEBUG_LOG_ENABLED = false; private static final String ZERO = "0"; private final MetricsLogger mMetricsLogger; Loading Loading @@ -127,7 +128,7 @@ public final class GenerateLinksLogger { } private static void debugLog(LogMaker log) { if (!Logger.DEBUG_LOG_ENABLED) return; if (!DEBUG_LOG_ENABLED) return; final String callId = Objects.toString( log.getTaggedData(MetricsEvent.FIELD_LINKIFY_CALL_ID), ""); Loading @@ -142,7 +143,8 @@ public final class GenerateLinksLogger { final int latencyMs = Integer.parseInt( Objects.toString(log.getTaggedData(MetricsEvent.FIELD_LINKIFY_LATENCY), ZERO)); Log.d(LOG_TAG, String.format("%s:%s %d links (%d/%d chars) %dms %s", callId, entityType, Log.d(LOG_TAG, String.format(Locale.US, "%s:%s %d links (%d/%d chars) %dms %s", callId, entityType, numLinks, linkLength, textLength, latencyMs, log.getPackageName())); } Loading core/java/android/view/textclassifier/Logger.javadeleted 100644 → 0 +0 −397 Original line number Diff line number Diff line /* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.view.textclassifier; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; import com.android.internal.util.Preconditions; import java.text.BreakIterator; import java.util.Locale; import java.util.Objects; /** * A helper for logging TextClassifier related events. * @hide */ public abstract class Logger { private static final String LOG_TAG = "Logger"; /* package */ static final boolean DEBUG_LOG_ENABLED = true; private @SelectionEvent.InvocationMethod int mInvocationMethod; private SelectionEvent mPrevEvent; private SelectionEvent mSmartEvent; private SelectionEvent mStartEvent; /** * Logger that does not log anything. * @hide */ public static final Logger DISABLED = new Logger() { @Override public void writeEvent(SelectionEvent event) {} }; @Nullable private final Config mConfig; public Logger(Config config) { mConfig = Preconditions.checkNotNull(config); } private Logger() { mConfig = null; } /** * Writes the selection event to a log. */ public abstract void writeEvent(@NonNull SelectionEvent event); /** * Returns true if the resultId matches that of a smart selection event (i.e. * {@link SelectionEvent#EVENT_SMART_SELECTION_SINGLE} or * {@link SelectionEvent#EVENT_SMART_SELECTION_MULTI}). * Returns false otherwise. */ public boolean isSmartSelection(@NonNull String resultId) { return false; } /** * Returns a token iterator for tokenizing text for logging purposes. */ public BreakIterator getTokenIterator(@NonNull Locale locale) { return BreakIterator.getWordInstance(Preconditions.checkNotNull(locale)); } /** * 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( @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, mInvocationMethod, null, mConfig)); } /** * Logs a "selection modified" event. * Use when the user modifies the selection. * * @param start the start token (inclusive) index of the selection * @param end the end token (exclusive) index of the selection */ public final void logSelectionModifiedEvent(int start, int end) { Preconditions.checkArgument(end >= start, "end cannot be less than start"); if (mConfig == null) { return; } logEvent(new SelectionEvent( start, end, SelectionEvent.EVENT_SELECTION_MODIFIED, TextClassifier.TYPE_UNKNOWN, mInvocationMethod, null, mConfig)); } /** * Logs a "selection modified" event. * Use when the user modifies the selection and the selection's entity type is known. * * @param start the start token (inclusive) index of the selection * @param end the end token (exclusive) index of the selection * @param classification the TextClassification object returned by the TextClassifier that * classified the selected text */ public final void logSelectionModifiedEvent( int start, int end, @NonNull TextClassification classification) { Preconditions.checkArgument(end >= start, "end cannot be less than start"); Preconditions.checkNotNull(classification); if (mConfig == null) { return; } final String entityType = classification.getEntityCount() > 0 ? classification.getEntity(0) : TextClassifier.TYPE_UNKNOWN; logEvent(new SelectionEvent( start, end, SelectionEvent.EVENT_SELECTION_MODIFIED, entityType, mInvocationMethod, classification.getId(), mConfig)); } /** * Logs a "selection modified" event. * Use when a TextClassifier modifies the selection. * * @param start the start token (inclusive) index of the selection * @param end the end token (exclusive) index of the selection * @param selection the TextSelection object returned by the TextClassifier for the * specified selection */ public final void logSelectionModifiedEvent( int start, int end, @NonNull TextSelection selection) { Preconditions.checkArgument(end >= start, "end cannot be less than start"); Preconditions.checkNotNull(selection); if (mConfig == null) { return; } final int eventType; if (isSmartSelection(selection.getId())) { eventType = end - start > 1 ? SelectionEvent.EVENT_SMART_SELECTION_MULTI : SelectionEvent.EVENT_SMART_SELECTION_SINGLE; } else { eventType = SelectionEvent.EVENT_AUTO_SELECTION; } final String entityType = selection.getEntityCount() > 0 ? selection.getEntity(0) : TextClassifier.TYPE_UNKNOWN; logEvent(new SelectionEvent(start, end, eventType, entityType, mInvocationMethod, selection.getId(), mConfig)); } /** * Logs an event specifying an action taken on a selection. * Use when the user clicks on an action to act on the selected text. * * @param start the start token (inclusive) index of the selection * @param end the end token (exclusive) index of the selection * @param actionType the action that was performed on the selection */ public final void logSelectionActionEvent( int start, int end, @SelectionEvent.ActionType int actionType) { Preconditions.checkArgument(end >= start, "end cannot be less than start"); checkActionType(actionType); if (mConfig == null) { return; } logEvent(new SelectionEvent( start, end, actionType, TextClassifier.TYPE_UNKNOWN, mInvocationMethod, null, mConfig)); } /** * Logs an event specifying an action taken on a selection. * Use when the user clicks on an action to act on the selected text and the selection's * entity type is known. * * @param start the start token (inclusive) index of the selection * @param end the end token (exclusive) index of the selection * @param actionType the action that was performed on the selection * @param classification the TextClassification object returned by the TextClassifier that * classified the selected text * * @throws IllegalArgumentException If actionType is not a valid SelectionEvent actionType */ public final void logSelectionActionEvent( int start, int end, @SelectionEvent.ActionType int actionType, @NonNull TextClassification classification) { Preconditions.checkArgument(end >= start, "end cannot be less than start"); Preconditions.checkNotNull(classification); checkActionType(actionType); if (mConfig == null) { return; } final String entityType = classification.getEntityCount() > 0 ? classification.getEntity(0) : TextClassifier.TYPE_UNKNOWN; logEvent(new SelectionEvent(start, end, actionType, entityType, mInvocationMethod, classification.getId(), mConfig)); } private void logEvent(@NonNull SelectionEvent event) { Preconditions.checkNotNull(event); if (event.getEventType() != SelectionEvent.EVENT_SELECTION_STARTED && mStartEvent == null) { if (DEBUG_LOG_ENABLED) { Log.d(LOG_TAG, "Selection session not yet started. Ignoring event"); } return; } final long now = System.currentTimeMillis(); switch (event.getEventType()) { case SelectionEvent.EVENT_SELECTION_STARTED: Preconditions.checkArgument(event.getAbsoluteEnd() == event.getAbsoluteStart() + 1); event.setSessionId(startNewSession()); mStartEvent = event; break; case SelectionEvent.EVENT_SMART_SELECTION_SINGLE: // fall through case SelectionEvent.EVENT_SMART_SELECTION_MULTI: mSmartEvent = event; break; case SelectionEvent.EVENT_SELECTION_MODIFIED: // fall through case SelectionEvent.EVENT_AUTO_SELECTION: if (mPrevEvent != null && mPrevEvent.getAbsoluteStart() == event.getAbsoluteStart() && mPrevEvent.getAbsoluteEnd() == event.getAbsoluteEnd()) { // Selection did not change. Ignore event. return; } break; default: // do nothing. } event.setEventTime(now); if (mStartEvent != null) { event.setSessionId(mStartEvent.getSessionId()) .setDurationSinceSessionStart(now - mStartEvent.getEventTime()) .setStart(event.getAbsoluteStart() - mStartEvent.getAbsoluteStart()) .setEnd(event.getAbsoluteEnd() - mStartEvent.getAbsoluteStart()); } if (mSmartEvent != null) { event.setResultId(mSmartEvent.getResultId()) .setSmartStart(mSmartEvent.getAbsoluteStart() - mStartEvent.getAbsoluteStart()) .setSmartEnd(mSmartEvent.getAbsoluteEnd() - mStartEvent.getAbsoluteStart()); } if (mPrevEvent != null) { event.setDurationSincePreviousEvent(now - mPrevEvent.getEventTime()) .setEventIndex(mPrevEvent.getEventIndex() + 1); } writeEvent(event); mPrevEvent = event; if (event.isTerminal()) { endSession(); } } private TextClassificationSessionId startNewSession() { endSession(); return new TextClassificationSessionId(); } private void endSession() { mPrevEvent = null; mSmartEvent = null; mStartEvent = null; } /** * @throws IllegalArgumentException If eventType is not an {@link SelectionEvent.ActionType} */ private static void checkActionType(@SelectionEvent.EventType int eventType) throws IllegalArgumentException { switch (eventType) { case SelectionEvent.ACTION_OVERTYPE: // fall through case SelectionEvent.ACTION_COPY: // fall through case SelectionEvent.ACTION_PASTE: // fall through case SelectionEvent.ACTION_CUT: // fall through case SelectionEvent.ACTION_SHARE: // fall through case SelectionEvent.ACTION_SMART_SHARE: // fall through case SelectionEvent.ACTION_DRAG: // fall through case SelectionEvent.ACTION_ABANDON: // fall through case SelectionEvent.ACTION_SELECT_ALL: // fall through case SelectionEvent.ACTION_RESET: // fall through return; default: throw new IllegalArgumentException( String.format(Locale.US, "%d is not an eventType", eventType)); } } /** * A Logger config. */ public static final class Config { private final String mPackageName; private final String mWidgetType; @Nullable private final String mWidgetVersion; /** * @param context Context of the widget the logger logs for * @param widgetType a name for the widget being logged for. e.g. * {@link TextClassifier#WIDGET_TYPE_TEXTVIEW} * @param widgetVersion a string version info for the widget the logger logs for */ public Config( @NonNull Context context, @TextClassifier.WidgetType String widgetType, @Nullable String widgetVersion) { mPackageName = Preconditions.checkNotNull(context).getPackageName(); mWidgetType = widgetType; mWidgetVersion = widgetVersion; } /** * Returns the package name of the application the logger logs for. */ public String getPackageName() { return mPackageName; } /** * Returns the name for the widget being logged for. e.g. * {@link TextClassifier#WIDGET_TYPE_TEXTVIEW}. */ public String getWidgetType() { return mWidgetType; } /** * Returns string version info for the logger. This is specific to the text classifier. */ @Nullable public String getWidgetVersion() { return mWidgetVersion; } @Override public int hashCode() { return Objects.hash(mPackageName, mWidgetType, mWidgetVersion); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof Config)) { return false; } final Config other = (Config) obj; return Objects.equals(mPackageName, other.mPackageName) && Objects.equals(mWidgetType, other.mWidgetType) && Objects.equals(mWidgetVersion, other.mWidgetType); } } } core/java/android/view/textclassifier/SelectionEvent.java +0 −14 Original line number Diff line number Diff line Loading @@ -150,20 +150,6 @@ public final class SelectionEvent implements Parcelable { mInvocationMethod = invocationMethod; } SelectionEvent( int start, int end, @EventType int eventType, @EntityType String entityType, @InvocationMethod int invocationMethod, @Nullable String resultId, Logger.Config config) { this(start, end, eventType, entityType, invocationMethod, resultId); Preconditions.checkNotNull(config); setTextClassificationSessionContext( new TextClassificationContext.Builder( config.getPackageName(), config.getWidgetType()) .setWidgetVersion(config.getWidgetVersion()) .build()); } private SelectionEvent(Parcel in) { mAbsoluteStart = in.readInt(); mAbsoluteEnd = in.readInt(); Loading core/java/android/view/textclassifier/DefaultLogger.java→core/java/android/view/textclassifier/SelectionSessionLogger.java +33 −25 Original line number Diff line number Diff line Loading @@ -17,28 +17,29 @@ package android.view.textclassifier; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; import android.metrics.LogMaker; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.util.Preconditions; import java.text.BreakIterator; import java.util.List; import java.util.Locale; import java.util.Objects; import java.util.StringJoiner; /** * Default Logger. * Used internally by TextClassifierImpl. * A helper for logging selection session events. * @hide */ public final class DefaultLogger extends Logger { public final class SelectionSessionLogger { private static final String LOG_TAG = "DefaultLogger"; private static final String LOG_TAG = "SelectionSessionLogger"; private static final boolean DEBUG_LOG_ENABLED = false; static final String CLASSIFIER_ID = "androidtc"; private static final int START_EVENT_DELTA = MetricsEvent.FIELD_SELECTION_SINCE_START; Loading @@ -59,23 +60,16 @@ public final class DefaultLogger extends Logger { private final MetricsLogger mMetricsLogger; public DefaultLogger(@NonNull Config config) { super(config); public SelectionSessionLogger() { mMetricsLogger = new MetricsLogger(); } @VisibleForTesting public DefaultLogger(@NonNull Config config, @NonNull MetricsLogger metricsLogger) { super(config); public SelectionSessionLogger(@NonNull MetricsLogger metricsLogger) { mMetricsLogger = Preconditions.checkNotNull(metricsLogger); } @Override public boolean isSmartSelection(@NonNull String signature) { return CLASSIFIER_ID.equals(SignatureParser.getClassifierId(signature)); } @Override /** Emits a selection event to the logs. */ public void writeEvent(@NonNull SelectionEvent event) { Preconditions.checkNotNull(event); final LogMaker log = new LogMaker(MetricsEvent.TEXT_SELECTION_SESSION) Loading @@ -93,7 +87,7 @@ public final class DefaultLogger extends Logger { .addTaggedData(SMART_END, event.getSmartEnd()) .addTaggedData(EVENT_START, event.getStart()) .addTaggedData(EVENT_END, event.getEnd()) .addTaggedData(SESSION_ID, event.getSessionId()); .addTaggedData(SESSION_ID, event.getSessionId().flattenToString()); mMetricsLogger.write(log); debugLog(log); } Loading Loading @@ -225,9 +219,17 @@ 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/%s, range=%d,%d - smart_range=%d,%d (%s/%s)", index, type, subType, entity, eventStart, eventEnd, smartStart, smartEnd, widget, model)); Log.d(LOG_TAG, String.format(Locale.US, "%2d: %s/%s/%s, range=%d,%d - smart_range=%d,%d (%s/%s)", index, type, subType, entity, eventStart, eventEnd, smartStart, smartEnd, widget, model)); } /** * Returns a token iterator for tokenizing text for logging purposes. */ public static BreakIterator getTokenIterator(@NonNull Locale locale) { return BreakIterator.getWordInstance(Preconditions.checkNotNull(locale)); } /** Loading Loading @@ -260,8 +262,10 @@ public final class DefaultLogger extends Logger { return String.format(Locale.US, "%s|%s|%d", classifierId, modelName, hash); } static String getClassifierId(String signature) { Preconditions.checkNotNull(signature); static String getClassifierId(@Nullable String signature) { if (signature == null) { return ""; } final int end = signature.indexOf("|"); if (end >= 0) { return signature.substring(0, end); Loading @@ -269,8 +273,10 @@ public final class DefaultLogger extends Logger { return ""; } static String getModelName(String signature) { Preconditions.checkNotNull(signature); static String getModelName(@Nullable String signature) { if (signature == null) { return ""; } final int start = signature.indexOf("|") + 1; final int end = signature.indexOf("|", start); if (start >= 1 && end >= start) { Loading @@ -279,8 +285,10 @@ public final class DefaultLogger extends Logger { return ""; } static int getHash(String signature) { Preconditions.checkNotNull(signature); static int getHash(@Nullable String signature) { if (signature == null) { return 0; } final int index1 = signature.indexOf("|"); final int index2 = signature.indexOf("|", index1); if (index2 > 0) { Loading Loading
config/hiddenapi-light-greylist.txt +0 −1 Original line number Diff line number Diff line Loading @@ -2245,7 +2245,6 @@ Landroid/view/SurfaceView;->mRequestedFormat:I Landroid/view/SurfaceView;->mSurfaceHolder:Landroid/view/SurfaceHolder; Landroid/view/SurfaceView;->surfacePositionLost_uiRtSync(J)V Landroid/view/SurfaceView;->updateSurfacePosition_renderWorker(JIIII)V Landroid/view/textclassifier/Logger;->DISABLED:Landroid/view/textclassifier/Logger; Landroid/view/textclassifier/logging/SmartSelectionEventTracker;-><init>(Landroid/content/Context;I)V Landroid/view/textclassifier/logging/SmartSelectionEventTracker;->logEvent(Landroid/view/textclassifier/logging/SmartSelectionEventTracker$SelectionEvent;)V Landroid/view/textclassifier/logging/SmartSelectionEventTracker$SelectionEvent;->selectionAction(III)Landroid/view/textclassifier/logging/SmartSelectionEventTracker$SelectionEvent; Loading
core/java/android/view/textclassifier/GenerateLinksLogger.java +6 −4 Original line number Diff line number Diff line Loading @@ -19,13 +19,13 @@ package android.view.textclassifier; import android.annotation.Nullable; import android.metrics.LogMaker; import android.util.ArrayMap; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.util.Preconditions; import java.util.Locale; import java.util.Map; import java.util.Objects; import java.util.Random; Loading @@ -39,6 +39,7 @@ import java.util.UUID; public final class GenerateLinksLogger { private static final String LOG_TAG = "GenerateLinksLogger"; private static final boolean DEBUG_LOG_ENABLED = false; private static final String ZERO = "0"; private final MetricsLogger mMetricsLogger; Loading Loading @@ -127,7 +128,7 @@ public final class GenerateLinksLogger { } private static void debugLog(LogMaker log) { if (!Logger.DEBUG_LOG_ENABLED) return; if (!DEBUG_LOG_ENABLED) return; final String callId = Objects.toString( log.getTaggedData(MetricsEvent.FIELD_LINKIFY_CALL_ID), ""); Loading @@ -142,7 +143,8 @@ public final class GenerateLinksLogger { final int latencyMs = Integer.parseInt( Objects.toString(log.getTaggedData(MetricsEvent.FIELD_LINKIFY_LATENCY), ZERO)); Log.d(LOG_TAG, String.format("%s:%s %d links (%d/%d chars) %dms %s", callId, entityType, Log.d(LOG_TAG, String.format(Locale.US, "%s:%s %d links (%d/%d chars) %dms %s", callId, entityType, numLinks, linkLength, textLength, latencyMs, log.getPackageName())); } Loading
core/java/android/view/textclassifier/Logger.javadeleted 100644 → 0 +0 −397 Original line number Diff line number Diff line /* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.view.textclassifier; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; import com.android.internal.util.Preconditions; import java.text.BreakIterator; import java.util.Locale; import java.util.Objects; /** * A helper for logging TextClassifier related events. * @hide */ public abstract class Logger { private static final String LOG_TAG = "Logger"; /* package */ static final boolean DEBUG_LOG_ENABLED = true; private @SelectionEvent.InvocationMethod int mInvocationMethod; private SelectionEvent mPrevEvent; private SelectionEvent mSmartEvent; private SelectionEvent mStartEvent; /** * Logger that does not log anything. * @hide */ public static final Logger DISABLED = new Logger() { @Override public void writeEvent(SelectionEvent event) {} }; @Nullable private final Config mConfig; public Logger(Config config) { mConfig = Preconditions.checkNotNull(config); } private Logger() { mConfig = null; } /** * Writes the selection event to a log. */ public abstract void writeEvent(@NonNull SelectionEvent event); /** * Returns true if the resultId matches that of a smart selection event (i.e. * {@link SelectionEvent#EVENT_SMART_SELECTION_SINGLE} or * {@link SelectionEvent#EVENT_SMART_SELECTION_MULTI}). * Returns false otherwise. */ public boolean isSmartSelection(@NonNull String resultId) { return false; } /** * Returns a token iterator for tokenizing text for logging purposes. */ public BreakIterator getTokenIterator(@NonNull Locale locale) { return BreakIterator.getWordInstance(Preconditions.checkNotNull(locale)); } /** * 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( @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, mInvocationMethod, null, mConfig)); } /** * Logs a "selection modified" event. * Use when the user modifies the selection. * * @param start the start token (inclusive) index of the selection * @param end the end token (exclusive) index of the selection */ public final void logSelectionModifiedEvent(int start, int end) { Preconditions.checkArgument(end >= start, "end cannot be less than start"); if (mConfig == null) { return; } logEvent(new SelectionEvent( start, end, SelectionEvent.EVENT_SELECTION_MODIFIED, TextClassifier.TYPE_UNKNOWN, mInvocationMethod, null, mConfig)); } /** * Logs a "selection modified" event. * Use when the user modifies the selection and the selection's entity type is known. * * @param start the start token (inclusive) index of the selection * @param end the end token (exclusive) index of the selection * @param classification the TextClassification object returned by the TextClassifier that * classified the selected text */ public final void logSelectionModifiedEvent( int start, int end, @NonNull TextClassification classification) { Preconditions.checkArgument(end >= start, "end cannot be less than start"); Preconditions.checkNotNull(classification); if (mConfig == null) { return; } final String entityType = classification.getEntityCount() > 0 ? classification.getEntity(0) : TextClassifier.TYPE_UNKNOWN; logEvent(new SelectionEvent( start, end, SelectionEvent.EVENT_SELECTION_MODIFIED, entityType, mInvocationMethod, classification.getId(), mConfig)); } /** * Logs a "selection modified" event. * Use when a TextClassifier modifies the selection. * * @param start the start token (inclusive) index of the selection * @param end the end token (exclusive) index of the selection * @param selection the TextSelection object returned by the TextClassifier for the * specified selection */ public final void logSelectionModifiedEvent( int start, int end, @NonNull TextSelection selection) { Preconditions.checkArgument(end >= start, "end cannot be less than start"); Preconditions.checkNotNull(selection); if (mConfig == null) { return; } final int eventType; if (isSmartSelection(selection.getId())) { eventType = end - start > 1 ? SelectionEvent.EVENT_SMART_SELECTION_MULTI : SelectionEvent.EVENT_SMART_SELECTION_SINGLE; } else { eventType = SelectionEvent.EVENT_AUTO_SELECTION; } final String entityType = selection.getEntityCount() > 0 ? selection.getEntity(0) : TextClassifier.TYPE_UNKNOWN; logEvent(new SelectionEvent(start, end, eventType, entityType, mInvocationMethod, selection.getId(), mConfig)); } /** * Logs an event specifying an action taken on a selection. * Use when the user clicks on an action to act on the selected text. * * @param start the start token (inclusive) index of the selection * @param end the end token (exclusive) index of the selection * @param actionType the action that was performed on the selection */ public final void logSelectionActionEvent( int start, int end, @SelectionEvent.ActionType int actionType) { Preconditions.checkArgument(end >= start, "end cannot be less than start"); checkActionType(actionType); if (mConfig == null) { return; } logEvent(new SelectionEvent( start, end, actionType, TextClassifier.TYPE_UNKNOWN, mInvocationMethod, null, mConfig)); } /** * Logs an event specifying an action taken on a selection. * Use when the user clicks on an action to act on the selected text and the selection's * entity type is known. * * @param start the start token (inclusive) index of the selection * @param end the end token (exclusive) index of the selection * @param actionType the action that was performed on the selection * @param classification the TextClassification object returned by the TextClassifier that * classified the selected text * * @throws IllegalArgumentException If actionType is not a valid SelectionEvent actionType */ public final void logSelectionActionEvent( int start, int end, @SelectionEvent.ActionType int actionType, @NonNull TextClassification classification) { Preconditions.checkArgument(end >= start, "end cannot be less than start"); Preconditions.checkNotNull(classification); checkActionType(actionType); if (mConfig == null) { return; } final String entityType = classification.getEntityCount() > 0 ? classification.getEntity(0) : TextClassifier.TYPE_UNKNOWN; logEvent(new SelectionEvent(start, end, actionType, entityType, mInvocationMethod, classification.getId(), mConfig)); } private void logEvent(@NonNull SelectionEvent event) { Preconditions.checkNotNull(event); if (event.getEventType() != SelectionEvent.EVENT_SELECTION_STARTED && mStartEvent == null) { if (DEBUG_LOG_ENABLED) { Log.d(LOG_TAG, "Selection session not yet started. Ignoring event"); } return; } final long now = System.currentTimeMillis(); switch (event.getEventType()) { case SelectionEvent.EVENT_SELECTION_STARTED: Preconditions.checkArgument(event.getAbsoluteEnd() == event.getAbsoluteStart() + 1); event.setSessionId(startNewSession()); mStartEvent = event; break; case SelectionEvent.EVENT_SMART_SELECTION_SINGLE: // fall through case SelectionEvent.EVENT_SMART_SELECTION_MULTI: mSmartEvent = event; break; case SelectionEvent.EVENT_SELECTION_MODIFIED: // fall through case SelectionEvent.EVENT_AUTO_SELECTION: if (mPrevEvent != null && mPrevEvent.getAbsoluteStart() == event.getAbsoluteStart() && mPrevEvent.getAbsoluteEnd() == event.getAbsoluteEnd()) { // Selection did not change. Ignore event. return; } break; default: // do nothing. } event.setEventTime(now); if (mStartEvent != null) { event.setSessionId(mStartEvent.getSessionId()) .setDurationSinceSessionStart(now - mStartEvent.getEventTime()) .setStart(event.getAbsoluteStart() - mStartEvent.getAbsoluteStart()) .setEnd(event.getAbsoluteEnd() - mStartEvent.getAbsoluteStart()); } if (mSmartEvent != null) { event.setResultId(mSmartEvent.getResultId()) .setSmartStart(mSmartEvent.getAbsoluteStart() - mStartEvent.getAbsoluteStart()) .setSmartEnd(mSmartEvent.getAbsoluteEnd() - mStartEvent.getAbsoluteStart()); } if (mPrevEvent != null) { event.setDurationSincePreviousEvent(now - mPrevEvent.getEventTime()) .setEventIndex(mPrevEvent.getEventIndex() + 1); } writeEvent(event); mPrevEvent = event; if (event.isTerminal()) { endSession(); } } private TextClassificationSessionId startNewSession() { endSession(); return new TextClassificationSessionId(); } private void endSession() { mPrevEvent = null; mSmartEvent = null; mStartEvent = null; } /** * @throws IllegalArgumentException If eventType is not an {@link SelectionEvent.ActionType} */ private static void checkActionType(@SelectionEvent.EventType int eventType) throws IllegalArgumentException { switch (eventType) { case SelectionEvent.ACTION_OVERTYPE: // fall through case SelectionEvent.ACTION_COPY: // fall through case SelectionEvent.ACTION_PASTE: // fall through case SelectionEvent.ACTION_CUT: // fall through case SelectionEvent.ACTION_SHARE: // fall through case SelectionEvent.ACTION_SMART_SHARE: // fall through case SelectionEvent.ACTION_DRAG: // fall through case SelectionEvent.ACTION_ABANDON: // fall through case SelectionEvent.ACTION_SELECT_ALL: // fall through case SelectionEvent.ACTION_RESET: // fall through return; default: throw new IllegalArgumentException( String.format(Locale.US, "%d is not an eventType", eventType)); } } /** * A Logger config. */ public static final class Config { private final String mPackageName; private final String mWidgetType; @Nullable private final String mWidgetVersion; /** * @param context Context of the widget the logger logs for * @param widgetType a name for the widget being logged for. e.g. * {@link TextClassifier#WIDGET_TYPE_TEXTVIEW} * @param widgetVersion a string version info for the widget the logger logs for */ public Config( @NonNull Context context, @TextClassifier.WidgetType String widgetType, @Nullable String widgetVersion) { mPackageName = Preconditions.checkNotNull(context).getPackageName(); mWidgetType = widgetType; mWidgetVersion = widgetVersion; } /** * Returns the package name of the application the logger logs for. */ public String getPackageName() { return mPackageName; } /** * Returns the name for the widget being logged for. e.g. * {@link TextClassifier#WIDGET_TYPE_TEXTVIEW}. */ public String getWidgetType() { return mWidgetType; } /** * Returns string version info for the logger. This is specific to the text classifier. */ @Nullable public String getWidgetVersion() { return mWidgetVersion; } @Override public int hashCode() { return Objects.hash(mPackageName, mWidgetType, mWidgetVersion); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof Config)) { return false; } final Config other = (Config) obj; return Objects.equals(mPackageName, other.mPackageName) && Objects.equals(mWidgetType, other.mWidgetType) && Objects.equals(mWidgetVersion, other.mWidgetType); } } }
core/java/android/view/textclassifier/SelectionEvent.java +0 −14 Original line number Diff line number Diff line Loading @@ -150,20 +150,6 @@ public final class SelectionEvent implements Parcelable { mInvocationMethod = invocationMethod; } SelectionEvent( int start, int end, @EventType int eventType, @EntityType String entityType, @InvocationMethod int invocationMethod, @Nullable String resultId, Logger.Config config) { this(start, end, eventType, entityType, invocationMethod, resultId); Preconditions.checkNotNull(config); setTextClassificationSessionContext( new TextClassificationContext.Builder( config.getPackageName(), config.getWidgetType()) .setWidgetVersion(config.getWidgetVersion()) .build()); } private SelectionEvent(Parcel in) { mAbsoluteStart = in.readInt(); mAbsoluteEnd = in.readInt(); Loading
core/java/android/view/textclassifier/DefaultLogger.java→core/java/android/view/textclassifier/SelectionSessionLogger.java +33 −25 Original line number Diff line number Diff line Loading @@ -17,28 +17,29 @@ package android.view.textclassifier; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; import android.metrics.LogMaker; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.util.Preconditions; import java.text.BreakIterator; import java.util.List; import java.util.Locale; import java.util.Objects; import java.util.StringJoiner; /** * Default Logger. * Used internally by TextClassifierImpl. * A helper for logging selection session events. * @hide */ public final class DefaultLogger extends Logger { public final class SelectionSessionLogger { private static final String LOG_TAG = "DefaultLogger"; private static final String LOG_TAG = "SelectionSessionLogger"; private static final boolean DEBUG_LOG_ENABLED = false; static final String CLASSIFIER_ID = "androidtc"; private static final int START_EVENT_DELTA = MetricsEvent.FIELD_SELECTION_SINCE_START; Loading @@ -59,23 +60,16 @@ public final class DefaultLogger extends Logger { private final MetricsLogger mMetricsLogger; public DefaultLogger(@NonNull Config config) { super(config); public SelectionSessionLogger() { mMetricsLogger = new MetricsLogger(); } @VisibleForTesting public DefaultLogger(@NonNull Config config, @NonNull MetricsLogger metricsLogger) { super(config); public SelectionSessionLogger(@NonNull MetricsLogger metricsLogger) { mMetricsLogger = Preconditions.checkNotNull(metricsLogger); } @Override public boolean isSmartSelection(@NonNull String signature) { return CLASSIFIER_ID.equals(SignatureParser.getClassifierId(signature)); } @Override /** Emits a selection event to the logs. */ public void writeEvent(@NonNull SelectionEvent event) { Preconditions.checkNotNull(event); final LogMaker log = new LogMaker(MetricsEvent.TEXT_SELECTION_SESSION) Loading @@ -93,7 +87,7 @@ public final class DefaultLogger extends Logger { .addTaggedData(SMART_END, event.getSmartEnd()) .addTaggedData(EVENT_START, event.getStart()) .addTaggedData(EVENT_END, event.getEnd()) .addTaggedData(SESSION_ID, event.getSessionId()); .addTaggedData(SESSION_ID, event.getSessionId().flattenToString()); mMetricsLogger.write(log); debugLog(log); } Loading Loading @@ -225,9 +219,17 @@ 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/%s, range=%d,%d - smart_range=%d,%d (%s/%s)", index, type, subType, entity, eventStart, eventEnd, smartStart, smartEnd, widget, model)); Log.d(LOG_TAG, String.format(Locale.US, "%2d: %s/%s/%s, range=%d,%d - smart_range=%d,%d (%s/%s)", index, type, subType, entity, eventStart, eventEnd, smartStart, smartEnd, widget, model)); } /** * Returns a token iterator for tokenizing text for logging purposes. */ public static BreakIterator getTokenIterator(@NonNull Locale locale) { return BreakIterator.getWordInstance(Preconditions.checkNotNull(locale)); } /** Loading Loading @@ -260,8 +262,10 @@ public final class DefaultLogger extends Logger { return String.format(Locale.US, "%s|%s|%d", classifierId, modelName, hash); } static String getClassifierId(String signature) { Preconditions.checkNotNull(signature); static String getClassifierId(@Nullable String signature) { if (signature == null) { return ""; } final int end = signature.indexOf("|"); if (end >= 0) { return signature.substring(0, end); Loading @@ -269,8 +273,10 @@ public final class DefaultLogger extends Logger { return ""; } static String getModelName(String signature) { Preconditions.checkNotNull(signature); static String getModelName(@Nullable String signature) { if (signature == null) { return ""; } final int start = signature.indexOf("|") + 1; final int end = signature.indexOf("|", start); if (start >= 1 && end >= start) { Loading @@ -279,8 +285,10 @@ public final class DefaultLogger extends Logger { return ""; } static int getHash(String signature) { Preconditions.checkNotNull(signature); static int getHash(@Nullable String signature) { if (signature == null) { return 0; } final int index1 = signature.indexOf("|"); final int index2 = signature.indexOf("|", index1); if (index2 > 0) { Loading