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

Commit 4f9d750e authored by Jan Althaus's avatar Jan Althaus Committed by Android (Google) Code Review
Browse files

Merge "Remove legacy logger" into pi-dev

parents 739199f3 5a03094e
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -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;
+6 −4
Original line number Diff line number Diff line
@@ -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;
@@ -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;
@@ -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), "");
@@ -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()));
    }

+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);
        }
    }
}
+0 −14
Original line number Diff line number Diff line
@@ -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();
+33 −25
Original line number Diff line number Diff line
@@ -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;
@@ -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)
@@ -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);
    }
@@ -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));
    }

    /**
@@ -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);
@@ -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) {
@@ -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