Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ae5eb83a authored by Jan Althaus's avatar Jan Althaus
Browse files

Update smart select metrics for new system event fields

We are now adding new system UI event fields specifically for smart select.
This CL adds corresponding new metric field values and changes the log
event building accordingly.

Bug: 67674199
Test: Manually tested that the logs are correct.
Change-Id: I5b90c8b194de2d46d7d6be1f1c314be9a2239298
parent 3bba3511
Loading
Loading
Loading
Loading
+49 −90
Original line number Diff line number Diff line
@@ -48,9 +48,13 @@ public final class SmartSelectionEventTracker {
    private static final int START_EVENT_DELTA = MetricsEvent.FIELD_SELECTION_SINCE_START;
    private static final int PREV_EVENT_DELTA = MetricsEvent.FIELD_SELECTION_SINCE_PREVIOUS;
    private static final int INDEX = MetricsEvent.FIELD_SELECTION_SESSION_INDEX;
    private static final int VERSION_TAG = MetricsEvent.FIELD_SELECTION_VERSION_TAG;
    private static final int SMART_INDICES = MetricsEvent.FIELD_SELECTION_SMART_RANGE;
    private static final int EVENT_INDICES = MetricsEvent.FIELD_SELECTION_RANGE;
    private static final int WIDGET_TYPE = MetricsEvent.FIELD_SELECTION_WIDGET_TYPE;
    private static final int MODEL_NAME = MetricsEvent.FIELD_TEXTCLASSIFIER_MODEL;
    private static final int ENTITY_TYPE = MetricsEvent.FIELD_SELECTION_ENTITY_TYPE;
    private static final int SMART_START = MetricsEvent.FIELD_SELECTION_SMART_RANGE_START;
    private static final int SMART_END = MetricsEvent.FIELD_SELECTION_SMART_RANGE_END;
    private static final int EVENT_START = MetricsEvent.FIELD_SELECTION_RANGE_START;
    private static final int EVENT_END = MetricsEvent.FIELD_SELECTION_RANGE_END;
    private static final int SESSION_ID = MetricsEvent.FIELD_SELECTION_SESSION_ID;

    private static final String ZERO = "0";
@@ -83,7 +87,7 @@ public final class SmartSelectionEventTracker {
    private long mSessionStartTime;
    private long mLastEventTime;
    private boolean mSmartSelectionTriggered;
    private String mVersionTag;
    private String mModelName;

    public SmartSelectionEventTracker(@NonNull Context context, @WidgetType int widgetType) {
        mWidgetType = widgetType;
@@ -115,7 +119,7 @@ public final class SmartSelectionEventTracker {
            case SelectionEvent.EventType.SMART_SELECTION_SINGLE:  // fall through
            case SelectionEvent.EventType.SMART_SELECTION_MULTI:
                mSmartSelectionTriggered = true;
                mVersionTag = getVersionTag(event);
                mModelName = getModelName(event);
                mSmartIndices[0] = event.mStart;
                mSmartIndices[1] = event.mEnd;
                break;
@@ -137,14 +141,18 @@ public final class SmartSelectionEventTracker {
        final long prevEventDelta = mLastEventTime == 0 ? 0 : now - mLastEventTime;
        final LogMaker log = new LogMaker(MetricsEvent.TEXT_SELECTION_SESSION)
                .setType(getLogType(event))
                .setSubtype(getLogSubType(event))
                .setSubtype(MetricsEvent.TEXT_SELECTION_INVOCATION_MANUAL)
                .setPackageName(mContext.getPackageName())
                .addTaggedData(START_EVENT_DELTA, now - mSessionStartTime)
                .addTaggedData(PREV_EVENT_DELTA, prevEventDelta)
                .addTaggedData(INDEX, mIndex)
                .addTaggedData(VERSION_TAG, mVersionTag)
                .addTaggedData(SMART_INDICES, getSmartDelta())
                .addTaggedData(EVENT_INDICES, getEventDelta(event))
                .addTaggedData(WIDGET_TYPE, getWidgetTypeName())
                .addTaggedData(MODEL_NAME, mModelName)
                .addTaggedData(ENTITY_TYPE, event.mEntityType)
                .addTaggedData(SMART_START, getSmartRangeDelta(mSmartIndices[0]))
                .addTaggedData(SMART_END, getSmartRangeDelta(mSmartIndices[1]))
                .addTaggedData(EVENT_START, getRangeDelta(event.mStart))
                .addTaggedData(EVENT_END, getRangeDelta(event.mEnd))
                .addTaggedData(SESSION_ID, mSessionId);
        mMetricsLogger.write(log);
        debugLog(log);
@@ -169,7 +177,7 @@ public final class SmartSelectionEventTracker {
        mSessionStartTime = 0;
        mLastEventTime = 0;
        mSmartSelectionTriggered = false;
        mVersionTag = getVersionTag(null);
        mModelName = getModelName(null);
        mSessionId = null;
    }

@@ -251,113 +259,64 @@ public final class SmartSelectionEventTracker {
        }
    }

    private static int getLogSubType(SelectionEvent event) {
        switch (event.mEntityType) {
            case TextClassifier.TYPE_OTHER:
                return MetricsEvent.TEXT_CLASSIFIER_TYPE_OTHER;
            case TextClassifier.TYPE_EMAIL:
                return MetricsEvent.TEXT_CLASSIFIER_TYPE_EMAIL;
            case TextClassifier.TYPE_PHONE:
                return MetricsEvent.TEXT_CLASSIFIER_TYPE_PHONE;
            case TextClassifier.TYPE_ADDRESS:
                return MetricsEvent.TEXT_CLASSIFIER_TYPE_ADDRESS;
            case TextClassifier.TYPE_URL:
                return MetricsEvent.TEXT_CLASSIFIER_TYPE_URL;
            default:
                return MetricsEvent.TEXT_CLASSIFIER_TYPE_UNKNOWN;
        }
    }

    private static String getLogSubTypeString(int logSubType) {
        switch (logSubType) {
            case MetricsEvent.TEXT_CLASSIFIER_TYPE_OTHER:
                return TextClassifier.TYPE_OTHER;
            case MetricsEvent.TEXT_CLASSIFIER_TYPE_EMAIL:
                return TextClassifier.TYPE_EMAIL;
            case MetricsEvent.TEXT_CLASSIFIER_TYPE_PHONE:
                return TextClassifier.TYPE_PHONE;
            case MetricsEvent.TEXT_CLASSIFIER_TYPE_ADDRESS:
                return TextClassifier.TYPE_ADDRESS;
            case MetricsEvent.TEXT_CLASSIFIER_TYPE_URL:
                return TextClassifier.TYPE_URL;
            default:
                return TextClassifier.TYPE_UNKNOWN;
        }
    private int getRangeDelta(int offset) {
        return offset - mOrigStart;
    }

    private int getSmartDelta() {
        if (mSmartSelectionTriggered) {
            return (clamp(mSmartIndices[0] - mOrigStart) << 16)
                    | (clamp(mSmartIndices[1] - mOrigStart) & 0xffff);
        }
        // If the smart selection model was not run, return invalid selection indices [0,0]. This
        // allows us to tell from the terminal event alone whether the model was run.
        return 0;
    private int getSmartRangeDelta(int offset) {
        return mSmartSelectionTriggered ? getRangeDelta(offset) : 0;
    }

    private int getEventDelta(SelectionEvent event) {
        return (clamp(event.mStart - mOrigStart) << 16)
                | (clamp(event.mEnd - mOrigStart) & 0xffff);
    }

    private String getVersionTag(@Nullable SelectionEvent event) {
        final String widgetType;
    private String getWidgetTypeName() {
        switch (mWidgetType) {
            case WidgetType.TEXTVIEW:
                widgetType = TEXTVIEW;
                break;
                return TEXTVIEW;
            case WidgetType.WEBVIEW:
                widgetType = WEBVIEW;
                break;
                return WEBVIEW;
            case WidgetType.EDITTEXT:
                widgetType = EDITTEXT;
                break;
                return EDITTEXT;
            case WidgetType.EDIT_WEBVIEW:
                widgetType = EDIT_WEBVIEW;
                break;
                return EDIT_WEBVIEW;
            default:
                widgetType = UNKNOWN;
                return UNKNOWN;
        }
        final String version = event == null
    }

    private String getModelName(@Nullable SelectionEvent event) {
        return event == null
                ? SelectionEvent.NO_VERSION_TAG
                : Objects.toString(event.mVersionTag, SelectionEvent.NO_VERSION_TAG);
        return String.format("%s/%s", widgetType, version);
    }

    private static String createSessionId() {
        return UUID.randomUUID().toString();
    }

    private static int clamp(int val) {
        return Math.max(Math.min(val, Short.MAX_VALUE), Short.MIN_VALUE);
    }

    private static void debugLog(LogMaker log) {
        if (!DEBUG_LOG_ENABLED) return;

        final String tag = Objects.toString(log.getTaggedData(VERSION_TAG), "tag");
        final String widget = Objects.toString(log.getTaggedData(WIDGET_TYPE), UNKNOWN);
        final int index = Integer.parseInt(Objects.toString(log.getTaggedData(INDEX), ZERO));
        if (log.getType() == MetricsEvent.ACTION_TEXT_SELECTION_START) {
            String sessionId = Objects.toString(log.getTaggedData(SESSION_ID), "");
            sessionId = sessionId.substring(sessionId.lastIndexOf("-") + 1);
            Log.d(LOG_TAG, String.format("New selection session: %s(%s)", tag, sessionId));
            Log.d(LOG_TAG, String.format("New selection session: %s (%s)", widget, sessionId));
        }

        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 smartIndices = Integer.parseInt(
                Objects.toString(log.getTaggedData(SMART_INDICES), ZERO));
        final int smartStart = (short) ((smartIndices & 0xffff0000) >> 16);
        final int smartEnd = (short) (smartIndices & 0xffff);

        final int eventIndices = Integer.parseInt(
                Objects.toString(log.getTaggedData(EVENT_INDICES), ZERO));
        final int eventStart = (short) ((eventIndices & 0xffff0000) >> 16);
        final int eventEnd = (short) (eventIndices & 0xffff);
        final int smartStart = Integer.parseInt(
                Objects.toString(log.getTaggedData(SMART_START), ZERO));
        final int smartEnd = Integer.parseInt(
                Objects.toString(log.getTaggedData(SMART_END), ZERO));
        final int eventStart = Integer.parseInt(
                Objects.toString(log.getTaggedData(EVENT_START), ZERO));
        final int eventEnd = Integer.parseInt(
                Objects.toString(log.getTaggedData(EVENT_END), ZERO));

        Log.d(LOG_TAG, String.format("%2d: %s/%s, context=%d,%d - old=%d,%d (%s)",
                index, type, subType, eventStart, eventEnd, smartStart, smartEnd, tag));
        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));
    }

    /**
@@ -369,12 +328,12 @@ public final class SmartSelectionEventTracker {
        /**
         * Use this to specify an indeterminate positive index.
         */
        public static final int OUT_OF_BOUNDS = Short.MAX_VALUE;
        public static final int OUT_OF_BOUNDS = Integer.MAX_VALUE;

        /**
         * Use this to specify an indeterminate negative index.
         */
        public static final int OUT_OF_BOUNDS_NEGATIVE = Short.MIN_VALUE;
        public static final int OUT_OF_BOUNDS_NEGATIVE = Integer.MIN_VALUE;

        private static final String NO_VERSION_TAG = "";

+43 −0
Original line number Diff line number Diff line
@@ -171,6 +171,12 @@ message MetricsEvent {
    TEXT_CLASSIFIER_TYPE_URL = 6;
  }

  // Selection invocation methods. Used as sub-type for TEXT_SELECTION_SESSION events.
  enum TextSelectionInvocationMethod {
    TEXT_SELECTION_INVOCATION_MANUAL = 1;
    TEXT_SELECTION_INVOCATION_LINK = 2;
  }

  // Known visual elements: views or controls.
  enum View {
    // Unknown view
@@ -4690,6 +4696,43 @@ message MetricsEvent {
    // OS: P
    ACTION_PRIVATE_DNS_MODE = 1249;

    // FIELD: text select start offset in words (as defined by the ICU BreakIterator).
    // CATEGORY: TEXT_SELECTION_SESSION
    // OS: P
    FIELD_SELECTION_RANGE_START = 1250;

    // FIELD: text select end offset in words (as defined by the ICU BreakIterator).
    // CATEGORY: TEXT_SELECTION_SESSION
    // OS: P
    FIELD_SELECTION_RANGE_END = 1251;

    // FIELD: smart text selection start offset in words (as defined by the ICU BreakIterator),
    //        stored as two packed 16bit integers. (start in MSBs, end in LSBs)
    // CATEGORY: TEXT_SELECTION_SESSION
    // OS: P
    FIELD_SELECTION_SMART_RANGE_START = 1252;

    // FIELD: smart text selection end offset in words (as defined by the ICU BreakIterator),
    //        stored as two packed 16bit integers. (start in MSBs, end in LSBs)
    // CATEGORY: TEXT_SELECTION_SESSION
    // OS: P
    FIELD_SELECTION_SMART_RANGE_END = 1253;

    // FIELD: the entity type of the text currently selected.
    // CATEGORY: TEXT_SELECTION_SESSION
    // OS: P
    FIELD_SELECTION_ENTITY_TYPE = 1254;

    // FIELD: the type of widget the selection was made in.
    // CATEGORY: TEXT_SELECTION_SESSION
    // OS: P
    FIELD_SELECTION_WIDGET_TYPE = 1255;

    // FIELD: the name of the text classifier model used.
    // CATEGORY: TEXT_SELECTION_SESSION
    // OS: P
    FIELD_TEXTCLASSIFIER_MODEL = 1256;

    // Add new aosp constants above this line.
    // END OF AOSP CONSTANTS
  }