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

Commit 4f2392c6 authored by Pablo Gamito's avatar Pablo Gamito
Browse files

Fallback to a NoOp ProtoLogImpl when viewer config is missing

Bug: 374125888
Flag: EXEMPT bug fix
Test: atest BubblePositionerTest
Test: atest com.android.internal.protolog.ProtoLogViewerConfigReaderTest#viewerConfigIsOnDevice
Change-Id: I4c4a9a3ac059a12591f8a57ecfa277a2b8180a35
parent 99853d95
Loading
Loading
Loading
Loading
+90 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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 com.android.internal.protolog;

import android.text.TextUtils;
import android.util.Log;

import com.android.internal.protolog.common.ILogger;
import com.android.internal.protolog.common.IProtoLog;
import com.android.internal.protolog.common.IProtoLogGroup;
import com.android.internal.protolog.common.LogLevel;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Class should only be used as a temporary solution to missing viewer config file on device.
 * In particular this class should only be initialized in Robolectric tests, if it's being used
 * otherwise please report it.
 *
 * @deprecated
 */
@Deprecated
public class NoViewerConfigProtoLogImpl implements IProtoLog {
    private static final String LOG_TAG = "ProtoLog";

    @Override
    public void log(LogLevel logLevel, IProtoLogGroup group, long messageHash, int paramsMask,
            Object[] args) {
        Log.w(LOG_TAG, "ProtoLogging is not available due to missing viewer config file...");
        logMessage(logLevel, group.getTag(), "PROTOLOG#" + messageHash + "("
                + Arrays.stream(args).map(Object::toString).collect(Collectors.joining()) + ")");
    }

    @Override
    public void log(LogLevel logLevel, IProtoLogGroup group, String messageString, Object... args) {
        logMessage(logLevel, group.getTag(), TextUtils.formatSimple(messageString, args));
    }

    @Override
    public boolean isProtoEnabled() {
        return false;
    }

    @Override
    public int startLoggingToLogcat(String[] groups, ILogger logger) {
        return 0;
    }

    @Override
    public int stopLoggingToLogcat(String[] groups, ILogger logger) {
        return 0;
    }

    @Override
    public boolean isEnabled(IProtoLogGroup group, LogLevel level) {
        return false;
    }

    @Override
    public List<IProtoLogGroup> getRegisteredGroups() {
        return List.of();
    }

    private void logMessage(LogLevel logLevel, String tag, String message) {
        switch (logLevel) {
            case VERBOSE -> Log.v(tag, message);
            case INFO -> Log.i(tag, message);
            case DEBUG -> Log.d(tag, message);
            case WARN -> Log.w(tag, message);
            case ERROR -> Log.e(tag, message);
            case WTF -> Log.wtf(tag, message);
        }
    }
}
+9 −9
Original line number Diff line number Diff line
@@ -106,7 +106,7 @@ public class ProtoLogImpl {

            final var groups = sLogGroups.values().toArray(new IProtoLogGroup[0]);
            if (android.tracing.Flags.perfettoProtologTracing()) {
                sServiceInstance = createPerfettoProtoLogImpl(groups);
                sServiceInstance = createProtoLogImpl(groups);
            } else {
                sServiceInstance = createLegacyProtoLogImpl(groups);
            }
@@ -116,18 +116,18 @@ public class ProtoLogImpl {
        return sServiceInstance;
    }

    private static PerfettoProtoLogImpl createPerfettoProtoLogImpl(IProtoLogGroup[] groups) {
    private static IProtoLog createProtoLogImpl(IProtoLogGroup[] groups) {
        try {
            File f = new File(sViewerConfigPath);
            if (!ProtoLog.REQUIRE_PROTOLOGTOOL && !f.exists()) {
            if (!f.exists()) {
                // TODO(b/353530422): Remove - temporary fix to unblock b/352290057
                // In some tests the viewer config file might not exist in which we don't
                // want to provide config path to the user
                Log.w(LOG_TAG, "Failed to find viewerConfigFile when setting up "
                        + ProtoLogImpl.class.getSimpleName() + ". "
                        + "Setting up without a viewer config instead...");
                // In robolectric tests the viewer config file isn't current available, so we cannot
                // use the ProcessedPerfettoProtoLogImpl.
                Log.e(LOG_TAG, "Failed to find viewer config file " + sViewerConfigPath
                        + " when setting up " + ProtoLogImpl.class.getSimpleName() + ". "
                        + "ProtoLog will not work here!");

                return new UnprocessedPerfettoProtoLogImpl(sCacheUpdater, groups);
                return new NoViewerConfigProtoLogImpl();
            } else {
                return new ProcessedPerfettoProtoLogImpl(sViewerConfigPath, sCacheUpdater, groups);
            }
+31 −0
Original line number Diff line number Diff line
@@ -19,8 +19,12 @@ package com.android.internal.protolog;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;

import android.os.Build;
import android.platform.test.annotations.Presubmit;

import com.google.common.truth.Truth;

import org.junit.Assume;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -28,6 +32,8 @@ import org.junit.runners.JUnit4;

import perfetto.protos.ProtologCommon;

import java.io.File;

@Presubmit
@RunWith(JUnit4.class)
public class ProtoLogViewerConfigReaderTest {
@@ -121,6 +127,31 @@ public class ProtoLogViewerConfigReaderTest {
        assertNull(mConfig.getViewerString(5));
    }

    @Test
    public void viewerConfigIsOnDevice() {
        Assume.assumeFalse(Build.FINGERPRINT.contains("robolectric"));

        final String[] viewerConfigPaths;
        if (android.tracing.Flags.perfettoProtologTracing()) {
            viewerConfigPaths = new String[] {
                    "/system_ext/etc/wmshell.protolog.pb",
                    "/system/etc/core.protolog.pb",
            };
        } else {
            viewerConfigPaths = new String[] {
                    "/system_ext/etc/wmshell.protolog.json.gz",
                    "/system/etc/protolog.conf.json.gz",
            };
        }

        for (final var viewerConfigPath : viewerConfigPaths) {
            File f = new File(viewerConfigPath);

            Truth.assertWithMessage(f.getAbsolutePath() + " exists").that(f.exists()).isTrue();
        }

    }

    @Test
    public void loadUnloadAndReloadViewerConfig() {
        loadViewerConfig();