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

Commit a45e68c6 authored by Pablo Gamito's avatar Pablo Gamito Committed by Android (Google) Code Review
Browse files

Merge changes from topic "protolog-if-wrapper" into main

* changes:
  Update usages of isEnabled protolog API
  Improve performance of ProtoLog
parents 78bfc6b6 274035a5
Loading
Loading
Loading
Loading
+15 −4
Original line number Diff line number Diff line
@@ -66,6 +66,7 @@ public class LegacyProtoLogImpl implements IProtoLog {
    private final TraceBuffer mBuffer;
    private final LegacyProtoLogViewerConfigReader mViewerConfig;
    private final TreeMap<String, IProtoLogGroup> mLogGroups;
    private final Runnable mCacheUpdater;
    private final int mPerChunkSize;

    private boolean mProtoLogEnabled;
@@ -73,20 +74,21 @@ public class LegacyProtoLogImpl implements IProtoLog {
    private final Object mProtoLogEnabledLock = new Object();

    public LegacyProtoLogImpl(String outputFile, String viewerConfigFilename,
            TreeMap<String, IProtoLogGroup> logGroups) {
            TreeMap<String, IProtoLogGroup> logGroups, Runnable cacheUpdater) {
        this(new File(outputFile), viewerConfigFilename, BUFFER_CAPACITY,
                new LegacyProtoLogViewerConfigReader(), PER_CHUNK_SIZE, logGroups);
                new LegacyProtoLogViewerConfigReader(), PER_CHUNK_SIZE, logGroups, cacheUpdater);
    }

    public LegacyProtoLogImpl(File file, String viewerConfigFilename, int bufferCapacity,
            LegacyProtoLogViewerConfigReader viewerConfig, int perChunkSize,
            TreeMap<String, IProtoLogGroup> logGroups) {
            TreeMap<String, IProtoLogGroup> logGroups, Runnable cacheUpdater) {
        mLogFile = file;
        mBuffer = new TraceBuffer(bufferCapacity);
        mLegacyViewerConfigFilename = viewerConfigFilename;
        mViewerConfig = viewerConfig;
        mPerChunkSize = perChunkSize;
        this.mLogGroups = logGroups;
        mLogGroups = logGroups;
        mCacheUpdater = cacheUpdater;
    }

    /**
@@ -285,6 +287,8 @@ public class LegacyProtoLogImpl implements IProtoLog {
                return -1;
            }
        }

        mCacheUpdater.run();
        return 0;
    }

@@ -399,5 +403,12 @@ public class LegacyProtoLogImpl implements IProtoLog {
    public int stopLoggingToLogcat(String[] groups, ILogger logger) {
        return setLogging(true /* setTextLogging */, false, logger, groups);
    }

    @Override
    public boolean isEnabled(IProtoLogGroup group, LogLevel level) {
        // In legacy logging we just enable an entire group at a time without more granular control,
        // so we ignore the level argument to this function.
        return group.isLogToLogcat() || (group.isLogToProto() && isProtoEnabled());
    }
}
+97 −7
Original line number Diff line number Diff line
@@ -52,6 +52,7 @@ import android.tracing.perfetto.DataSourceParams;
import android.tracing.perfetto.InitArguments;
import android.tracing.perfetto.Producer;
import android.tracing.perfetto.TracingContext;
import android.util.ArrayMap;
import android.util.LongArray;
import android.util.Slog;
import android.util.proto.ProtoInputStream;
@@ -70,6 +71,7 @@ import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@@ -83,18 +85,22 @@ public class PerfettoProtoLogImpl implements IProtoLog {
    private final AtomicInteger mTracingInstances = new AtomicInteger();

    private final ProtoLogDataSource mDataSource = new ProtoLogDataSource(
            this.mTracingInstances::incrementAndGet,
            this::onTracingInstanceStart,
            this::dumpTransitionTraceConfig,
            this.mTracingInstances::decrementAndGet
            this::onTracingInstanceStop
    );
    private final ProtoLogViewerConfigReader mViewerConfigReader;
    private final ViewerConfigInputStreamProvider mViewerConfigInputStreamProvider;
    private final TreeMap<String, IProtoLogGroup> mLogGroups;
    private final Runnable mCacheUpdater;

    private final Map<LogLevel, Integer> mDefaultLogLevelCounts = new ArrayMap<>();
    private final Map<IProtoLogGroup, Map<LogLevel, Integer>> mLogLevelCounts = new ArrayMap<>();

    private final ExecutorService mBackgroundLoggingService = Executors.newCachedThreadPool();

    public PerfettoProtoLogImpl(String viewerConfigFilePath,
            TreeMap<String, IProtoLogGroup> logGroups) {
            TreeMap<String, IProtoLogGroup> logGroups, Runnable cacheUpdater) {
        this(() -> {
            try {
                return new ProtoInputStream(new FileInputStream(viewerConfigFilePath));
@@ -102,28 +108,32 @@ public class PerfettoProtoLogImpl implements IProtoLog {
                Slog.w(LOG_TAG, "Failed to load viewer config file " + viewerConfigFilePath, e);
                return null;
            }
        }, logGroups);
        }, logGroups, cacheUpdater);
    }

    public PerfettoProtoLogImpl(
            ViewerConfigInputStreamProvider viewerConfigInputStreamProvider,
            TreeMap<String, IProtoLogGroup> logGroups
            TreeMap<String, IProtoLogGroup> logGroups,
            Runnable cacheUpdater
    ) {
        this(viewerConfigInputStreamProvider,
                new ProtoLogViewerConfigReader(viewerConfigInputStreamProvider), logGroups);
                new ProtoLogViewerConfigReader(viewerConfigInputStreamProvider), logGroups,
                cacheUpdater);
    }

    @VisibleForTesting
    public PerfettoProtoLogImpl(
            ViewerConfigInputStreamProvider viewerConfigInputStreamProvider,
            ProtoLogViewerConfigReader viewerConfigReader,
            TreeMap<String, IProtoLogGroup> logGroups
            TreeMap<String, IProtoLogGroup> logGroups,
            Runnable cacheUpdater
    ) {
        Producer.init(InitArguments.DEFAULTS);
        mDataSource.register(DataSourceParams.DEFAULTS);
        this.mViewerConfigInputStreamProvider = viewerConfigInputStreamProvider;
        this.mViewerConfigReader = viewerConfigReader;
        this.mLogGroups = logGroups;
        this.mCacheUpdater = cacheUpdater;
    }

    /**
@@ -494,6 +504,29 @@ public class PerfettoProtoLogImpl implements IProtoLog {
        return setTextLogging(false, logger, groups);
    }

    @Override
    public boolean isEnabled(IProtoLogGroup group, LogLevel level) {
        return group.isLogToLogcat() || getLogFromLevel(group).ordinal() <= level.ordinal();
    }

    private LogLevel getLogFromLevel(IProtoLogGroup group) {
        if (mLogLevelCounts.containsKey(group)) {
            for (LogLevel logLevel : LogLevel.values()) {
                if (mLogLevelCounts.get(group).getOrDefault(logLevel, 0) > 0) {
                    return logLevel;
                }
            }
        } else {
            for (LogLevel logLevel : LogLevel.values()) {
                if (mDefaultLogLevelCounts.getOrDefault(logLevel, 0) > 0) {
                    return logLevel;
                }
            }
        }

        return LogLevel.WTF;
    }

    /**
     * Start logging the stack trace of the when the log message happened for target groups
     * @return status code
@@ -521,6 +554,8 @@ public class PerfettoProtoLogImpl implements IProtoLog {
                return -1;
            }
        }

        mCacheUpdater.run();
        return 0;
    }

@@ -567,6 +602,61 @@ public class PerfettoProtoLogImpl implements IProtoLog {
        return -1;
    }

    private synchronized void onTracingInstanceStart(ProtoLogDataSource.ProtoLogConfig config) {
        this.mTracingInstances.incrementAndGet();

        final LogLevel defaultLogFrom = config.getDefaultGroupConfig().logFrom;
        mDefaultLogLevelCounts.put(defaultLogFrom,
                mDefaultLogLevelCounts.getOrDefault(defaultLogFrom, 0) + 1);

        final Set<String> overriddenGroupTags = config.getGroupTagsWithOverriddenConfigs();

        for (String overriddenGroupTag : overriddenGroupTags) {
            IProtoLogGroup group = mLogGroups.get(overriddenGroupTag);

            mLogLevelCounts.putIfAbsent(group, new ArrayMap<>());
            final Map<LogLevel, Integer> logLevelsCountsForGroup = mLogLevelCounts.get(group);

            final LogLevel logFromLevel = config.getConfigFor(overriddenGroupTag).logFrom;
            logLevelsCountsForGroup.put(logFromLevel,
                    logLevelsCountsForGroup.getOrDefault(logFromLevel, 0) + 1);
        }

        mCacheUpdater.run();
    }

    private synchronized void onTracingInstanceStop(ProtoLogDataSource.ProtoLogConfig config) {
        this.mTracingInstances.decrementAndGet();

        final LogLevel defaultLogFrom = config.getDefaultGroupConfig().logFrom;
        mDefaultLogLevelCounts.put(defaultLogFrom,
                mDefaultLogLevelCounts.get(defaultLogFrom) - 1);
        if (mDefaultLogLevelCounts.get(defaultLogFrom) <= 0) {
            mDefaultLogLevelCounts.remove(defaultLogFrom);
        }

        final Set<String> overriddenGroupTags = config.getGroupTagsWithOverriddenConfigs();

        for (String overriddenGroupTag : overriddenGroupTags) {
            IProtoLogGroup group = mLogGroups.get(overriddenGroupTag);

            mLogLevelCounts.putIfAbsent(group, new ArrayMap<>());
            final Map<LogLevel, Integer> logLevelsCountsForGroup = mLogLevelCounts.get(group);

            final LogLevel logFromLevel = config.getConfigFor(overriddenGroupTag).logFrom;
            logLevelsCountsForGroup.put(logFromLevel,
                    logLevelsCountsForGroup.get(logFromLevel) - 1);
            if (logLevelsCountsForGroup.get(logFromLevel) <= 0) {
                logLevelsCountsForGroup.remove(logFromLevel);
            }
            if (logLevelsCountsForGroup.isEmpty()) {
                mLogLevelCounts.remove(group);
            }
        }

        mCacheUpdater.run();
    }

    static void logAndPrintln(@Nullable PrintWriter pw, String msg) {
        Slog.i(LOG_TAG, msg);
        if (pw != null) {
+19 −12
Original line number Diff line number Diff line
@@ -39,16 +39,19 @@ import com.android.internal.protolog.common.LogLevel;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;

public class ProtoLogDataSource extends DataSource<ProtoLogDataSource.Instance,
        ProtoLogDataSource.TlsState,
        ProtoLogDataSource.IncrementalState> {

    private final Runnable mOnStart;
    private final Consumer<ProtoLogConfig> mOnStart;
    private final Runnable mOnFlush;
    private final Runnable mOnStop;
    private final Consumer<ProtoLogConfig> mOnStop;

    public ProtoLogDataSource(Runnable onStart, Runnable onFlush, Runnable onStop) {
    public ProtoLogDataSource(Consumer<ProtoLogConfig> onStart, Runnable onFlush,
            Consumer<ProtoLogConfig> onStop) {
        super("android.protolog");
        this.mOnStart = onStart;
        this.mOnFlush = onFlush;
@@ -138,7 +141,7 @@ public class ProtoLogDataSource extends DataSource<ProtoLogDataSource.Instance,
        public boolean clearReported = false;
    }

    private static class ProtoLogConfig {
    public static class ProtoLogConfig {
        private final LogLevel mDefaultLogFromLevel;
        private final Map<String, GroupConfig> mGroupConfigs;

@@ -151,13 +154,17 @@ public class ProtoLogDataSource extends DataSource<ProtoLogDataSource.Instance,
            this.mGroupConfigs = groupConfigs;
        }

        private GroupConfig getConfigFor(String groupTag) {
        public GroupConfig getConfigFor(String groupTag) {
            return mGroupConfigs.getOrDefault(groupTag, getDefaultGroupConfig());
        }

        private GroupConfig getDefaultGroupConfig() {
        public GroupConfig getDefaultGroupConfig() {
            return new GroupConfig(mDefaultLogFromLevel, false);
        }

        public Set<String> getGroupTagsWithOverriddenConfigs() {
            return mGroupConfigs.keySet();
        }
    }

    public static class GroupConfig {
@@ -255,18 +262,18 @@ public class ProtoLogDataSource extends DataSource<ProtoLogDataSource.Instance,

    public static class Instance extends DataSourceInstance {

        private final Runnable mOnStart;
        private final Consumer<ProtoLogConfig> mOnStart;
        private final Runnable mOnFlush;
        private final Runnable mOnStop;
        private final Consumer<ProtoLogConfig> mOnStop;
        private final ProtoLogConfig mConfig;

        public Instance(
                DataSource<Instance, TlsState, IncrementalState> dataSource,
                int instanceIdx,
                ProtoLogConfig config,
                Runnable onStart,
                Consumer<ProtoLogConfig> onStart,
                Runnable onFlush,
                Runnable onStop
                Consumer<ProtoLogConfig> onStop
        ) {
            super(dataSource, instanceIdx);
            this.mOnStart = onStart;
@@ -277,7 +284,7 @@ public class ProtoLogDataSource extends DataSource<ProtoLogDataSource.Instance,

        @Override
        public void onStart(StartCallbackArguments args) {
            this.mOnStart.run();
            this.mOnStart.accept(this.mConfig);
        }

        @Override
@@ -287,7 +294,7 @@ public class ProtoLogDataSource extends DataSource<ProtoLogDataSource.Instance,

        @Override
        public void onStop(StopCallbackArguments args) {
            this.mOnStop.run();
            this.mOnStop.accept(this.mConfig);
        }
    }
}
+15 −5
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.internal.protolog;

import static com.android.internal.protolog.common.ProtoLogToolInjected.Value.CACHE_UPDATER;
import static com.android.internal.protolog.common.ProtoLogToolInjected.Value.LEGACY_OUTPUT_FILE_PATH;
import static com.android.internal.protolog.common.ProtoLogToolInjected.Value.LEGACY_VIEWER_CONFIG_PATH;
import static com.android.internal.protolog.common.ProtoLogToolInjected.Value.LOG_GROUPS;
@@ -49,6 +50,9 @@ public class ProtoLogImpl {
    @ProtoLogToolInjected(LOG_GROUPS)
    private static TreeMap<String, IProtoLogGroup> sLogGroups;

    @ProtoLogToolInjected(CACHE_UPDATER)
    private static Runnable sCacheUpdater;

    /** Used by the ProtoLogTool, do not call directly - use {@code ProtoLog} class instead. */
    public static void d(IProtoLogGroup group, long messageHash, int paramsMask,
            @Nullable String messageString,
@@ -94,9 +98,12 @@ public class ProtoLogImpl {
        getSingleInstance().log(LogLevel.WTF, group, messageHash, paramsMask, messageString, args);
    }

    public static boolean isEnabled(IProtoLogGroup group) {
        // TODO: Implement for performance reasons, with optional level parameter?
        return true;
    /**
     * Should return true iff we should be logging to either protolog or logcat for this group
     * and log level.
     */
    public static boolean isEnabled(IProtoLogGroup group, LogLevel level) {
        return getSingleInstance().isEnabled(group, level);
    }

    /**
@@ -105,11 +112,14 @@ public class ProtoLogImpl {
    public static synchronized IProtoLog getSingleInstance() {
        if (sServiceInstance == null) {
            if (android.tracing.Flags.perfettoProtologTracing()) {
                sServiceInstance = new PerfettoProtoLogImpl(sViewerConfigPath, sLogGroups);
                sServiceInstance = new PerfettoProtoLogImpl(
                        sViewerConfigPath, sLogGroups, sCacheUpdater);
            } else {
                sServiceInstance = new LegacyProtoLogImpl(
                        sLegacyOutputFilePath, sLegacyViewerConfigPath, sLogGroups);
                        sLegacyOutputFilePath, sLegacyViewerConfigPath, sLogGroups, sCacheUpdater);
            }

            sCacheUpdater.run();
        }
        return sServiceInstance;
    }
+8 −0
Original line number Diff line number Diff line
@@ -52,4 +52,12 @@ public interface IProtoLog {
     * @return status code
     */
    int stopLoggingToLogcat(String[] groups, ILogger logger);

    /**
     * Should return true iff logging is enabled to ProtoLog or to Logcat for this group and level.
     * @param group ProtoLog group to check for.
     * @param level ProtoLog level to check for.
     * @return If we need to log this group and level to either ProtoLog or Logcat.
     */
    boolean isEnabled(IProtoLogGroup group, LogLevel level);
}
Loading