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

Commit 34088642 authored by Android Build Coastguard Worker's avatar Android Build Coastguard Worker
Browse files

Snap for 13473899 from 70bc1d3f to 25Q3-release

Change-Id: I16f7122e58112d30aacaf606078c687848c616c1
parents 96e507b1 70bc1d3f
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -1286,6 +1286,18 @@ java_aconfig_library {
    visibility: [":__subpackages__"],
}

java_aconfig_library {
    name: "android.net.platform.flags-aconfig-java-export",
    aconfig_declarations: "android.net.platform.flags-aconfig",
    mode: "exported",
    min_sdk_version: "30",
    defaults: ["framework-minus-apex-aconfig-java-defaults"],
    apex_available: [
        "//apex_available:platform",
        "com.android.tethering",
    ],
}

java_aconfig_library {
    name: "com.android.net.thread.platform.flags-aconfig-java",
    aconfig_declarations: "com.android.net.thread.platform.flags-aconfig",
+18 −4
Original line number Diff line number Diff line
@@ -12,24 +12,38 @@
// See the License for the specific language governing permissions and
// limitations under the License.

filegroup {
    name: "ui-tracing-metric-specs",
    srcs: [
        "metric_specs/*",
    ],
}

android_test {
    name: "UiTracingPerfTests",
    team: "trendy_team_windowing_tools",
    srcs: ["src/**/*.java"],
    srcs: [
        "src/**/*.java",
        "src/**/*.kt",
    ],
    static_libs: [
        "androidx.test.rules",
        "androidx.annotation_annotation",
        "androidx.test.rules",
        "apct-perftests-utils",
        "collector-device-lib",
        "collector-device-lib-platform",
        "platform-test-annotations",
        "flickerlib-parsers",
        "perfetto_trace_java_protos",
        "platform-test-annotations",
    ],
    test_suites: [
        "device-tests",
        "performance-tests",
    ],
    data: [":perfetto_artifacts"],
    data: [
        ":perfetto_artifacts",
        ":ui-tracing-metric-specs",
    ],
    platform_apis: true,
    certificate: "platform",
}
+11 −45
Original line number Diff line number Diff line
@@ -84,54 +84,20 @@
        <option name="collect-on-run-ended-only" value="false"/>
    </metrics_collector>

    <!-- Post processors run in the reverse order to that in xml, so the order is:
        1. PerfettoTracePostProcessor runs the trace_processor to produce a metric proto
        2. PerfettoGenericPostProcessor parses the proto to produce metrics as key-value pairs
        3. MetricFilePostProcessor writes the metrics to a file -->
    <metric_post_processor class="com.android.tradefed.postprocessor.MetricFilePostProcessor"/>
    <metrics_collector class="com.android.tradefed.device.metric.PerfettoPullerMetricCollector">
        <option name="trace-processor-binary" value="trace_processor_shell"/>
        <option name="perfetto-v1-metrics" value="false"/>
        <option name="perfetto-v2-metrics" value="true"/>
        <option name="perfetto-v2-metrics-ids" value="avg_runtime_per_uitracing_slice" />
        <option name="summary-spec-file-name" value="avg_runtime_per_uitracing_slice.textproto" />
        <option name="trace-processor-timeout" value="120000"/>
        <option name="pull-pattern-keys" value="perfetto_file_path"/>
        <option name="clean-up" value="false"/>
        <option name="collect-on-run-ended-only" value="false"/>
    </metrics_collector>

    <metric_post_processor class="com.android.tradefed.postprocessor.PerfettoGenericPostProcessor">
        <option name="perfetto-proto-file-prefix" value="metric_perfetto"/>
        <option name="perfetto-proto-file-prefix" value="metric_v2_perfetto"/>

        <!-- Memory related metrics -->
        <option name="perfetto-prefix-key-field" value="perfetto.protos.AndroidGpuMetric.Process.name"/>
        <option name="perfetto-metric-filter-regex" value="android_mem-process_metrics-process_name-.*-total_counters-.*"/>
        <option name="perfetto-metric-replace-prefix" key="android_mem-process_metrics-process_name" value="android_mem"/>

        <!-- PnP related metrics. -->
        <option name="perfetto-metric-filter-regex" value="android_batt-battery_aggregates-avg_power_mw"/>
        <option name="perfetto-metric-filter-regex" value="android_frame_timeline_metric-(total_frames|missed_app_frames)"/>

        <!-- Metric for wattson energy/power consumption -->
        <option name="perfetto-metric-filter-regex" value="wattson_atrace_apps_rails-period_info-period_name-*.*-cpu_subsystem-estimated_mw\b"/>
        <option name="perfetto-metric-filter-regex" value="wattson_atrace_apps_rails-period_info-period_name-*.*-cpu_subsystem-estimated_mws"/>
        <option name="perfetto-metric-replace-prefix" key="wattson_atrace_apps_rails-period_info-period_name" value="wattson_apps_rails-name"/>

        <!-- Metric for android anomaly detection-->
        <option name="perfetto-metric-filter-regex" value="android_anomaly-binder-max_outgoing_process_count_per_second-process_name-system_server-value"/>
        <option name="perfetto-metric-filter-regex" value="android_anomaly-binder-max_incoming_process_count_per_second-process_name-system_server-value"/>
        <option name="perfetto-metric-filter-regex" value="android_anomaly-binder-max_outgoing_process_count_per_second-process_name-/system/bin/servicemanager-value"/>
        <option name="perfetto-metric-filter-regex" value="android_anomaly-binder-max_incoming_process_count_per_second-process_name-/system/bin/servicemanager-value"/>
        <option name="perfetto-metric-filter-regex" value="android_anomaly-binder-max_outgoing_process_count_per_second-process_name-com.google.android.apps.nexuslauncher-value"/>
        <option name="perfetto-metric-filter-regex" value="android_anomaly-binder-max_incoming_process_count_per_second-process_name-com.google.android.apps.nexuslauncher-value"/>
        <option name="perfetto-metric-filter-regex" value="android_anomaly-binder-max_outgoing_process_count_per_second-process_name-com.android.systemui-value"/>
        <option name="perfetto-metric-filter-regex" value="android_anomaly-binder-max_incoming_process_count_per_second-process_name-com.android.systemui-value"/>
        <option name="perfetto-prefix-key-field"  value="perfetto.protos.AndroidAnomalyMetric.ProcessAnomaly.process_name"/>

        <option name="perfetto-metric-replace-prefix" key="android_anomaly-binder-max_outgoing_process_count_per_second-process_name-system_server-value" value="android_anomaly-max_outgoing_process_name-system_server"/>
        <option name="perfetto-metric-replace-prefix" key="android_anomaly-binder-max_incoming_process_count_per_second-process_name-system_server-value" value="android_anomaly-max_incoming_process_name-system_server"/>
        <option name="perfetto-metric-replace-prefix" key="android_anomaly-binder-max_outgoing_process_count_per_second-process_name-/system/bin/servicemanager-value" value="android_anomaly-max_outgoing_process_name-/system/bin/servicemanager"/>
        <option name="perfetto-metric-replace-prefix" key="android_anomaly-binder-max_incoming_process_count_per_second-process_name-/system/bin/servicemanager-value" value="android_anomaly-max_incoming_process_name-/system/bin/servicemanager"/>
        <option name="perfetto-metric-replace-prefix" key="android_anomaly-binder-max_outgoing_process_count_per_second-process_name-com.android.systemui-value" value="android_anomaly-max_outgoing_process_name-com.android.systemui"/>
        <option name="perfetto-metric-replace-prefix" key="android_anomaly-binder-max_incoming_process_count_per_second-process_name-com.android.systemui-value" value="android_anomaly-max_incoming_process_name-com.android.systemui"/>
        <option name="perfetto-metric-replace-prefix" key="android_anomaly-binder-max_outgoing_process_count_per_second-process_name-com.google.android.apps.nexuslauncher-value" value="android_anomaly-max_outgoing_process_name-com.google.android.apps.nexuslauncher"/>
        <option name="perfetto-metric-replace-prefix" key="android_anomaly-binder-max_incoming_process_count_per_second-process_name-com.google.android.apps.nexuslauncher-value" value="android_anomaly-max_incoming_process_name-com.google.android.apps.nexuslauncher"/>
    </metric_post_processor>

    <metric_post_processor class="com.android.tradefed.postprocessor.PerfettoTracePostProcessor">
        <!-- V1 metrics -->
        <option name="trace-processor-run-metrics" value="android_batt,android_frame_timeline_metric,android_mem,android_gpu,android_ion,android_dma_heap"/>
    </metric_post_processor>

    <metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector">
+40 −0
Original line number Diff line number Diff line
# Copyright (C) 2025 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.

metric_spec: {
  id: "avg_runtime_per_uitracing_slice"
  dimensions: "slice_name"
  value: "avg_runtime"
  query: {
    id: "duration_per_process"
    inner_query: {
      simple_slices: {
         slice_name_glob: "UiTracing::*"
      }
      select_columns: { column_name: "dur" }
      select_columns: { column_name: "slice_name" }
    }
    group_by: {
      column_names: "slice_name"
      aggregates: {
        column_name: "dur"
        # TODO (b/416488773): Change this to MEDIAN to be more robust against outliers
        op: MEAN
        result_column_name: "avg_runtime"
      }
    }
    select_columns: { column_name: "slice_name" }
    select_columns: { column_name: "avg_runtime" }
  }
}
+0 −275
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.app.Activity;
import android.os.Bundle;
import android.os.ServiceManager.ServiceNotFoundException;
import android.perftests.utils.Stats;
import android.platform.test.annotations.Postsubmit;
import android.tracing.perfetto.DataSourceParams;
import android.tracing.perfetto.InitArguments;
import android.tracing.perfetto.Producer;

import androidx.test.InstrumentationRegistry;

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

import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

import perfetto.protos.ProtologCommon;

import java.util.ArrayList;
import java.util.Collection;

@RunWith(Parameterized.class)
@Postsubmit
public class ProtoLogPerfTest {
    private final boolean mLogToProto;
    private final boolean mLogToLogcat;

    /**
     * Generates the parameters used for this test class
     */
    @Parameters(name = "LOG_TO_{0}")
    public static Collection<Object[]> params() {
        var params = new ArrayList<Object[]>();

        for (LogTo logTo : LogTo.values()) {
            params.add(new Object[] { logTo });
        }

        return params;
    }

    public ProtoLogPerfTest(LogTo logTo) {
        mLogToProto = switch (logTo) {
            case ALL, PROTO_ONLY -> true;
            case LOGCAT_ONLY, NONE -> false;
        };

        mLogToLogcat = switch (logTo) {
            case ALL, LOGCAT_ONLY -> true;
            case PROTO_ONLY, NONE -> false;
        };
    }

    private IProtoLog mProcessedProtoLogger;
    private static ProtoLogDataSource sTestDataSource;
    private static final String TEST_PROTOLOG_DATASOURCE_NAME = "test.android.protolog";
    private static final String MOCK_TEST_FILE_PATH = "mock/file/path";
    private static final perfetto.protos.Protolog.ProtoLogViewerConfig VIEWER_CONFIG =
            perfetto.protos.Protolog.ProtoLogViewerConfig.newBuilder()
                .addGroups(
                        perfetto.protos.Protolog.ProtoLogViewerConfig.Group.newBuilder()
                                .setId(1)
                                .setName(TestProtoLogGroup.TEST_GROUP.toString())
                                .setTag(TestProtoLogGroup.TEST_GROUP.getTag())
                ).addMessages(
                        perfetto.protos.Protolog.ProtoLogViewerConfig.MessageData.newBuilder()
                                .setMessageId(123)
                                .setMessage("My Test Debug Log Message %b")
                                .setLevel(ProtologCommon.ProtoLogLevel.PROTOLOG_LEVEL_DEBUG)
                                .setGroupId(1)
                                .setLocation("com/test/MyTestClass.java:123")
                ).build();

    @BeforeClass
    public static void init() {
        Producer.init(InitArguments.DEFAULTS);

        sTestDataSource = new ProtoLogDataSource(TEST_PROTOLOG_DATASOURCE_NAME);
        DataSourceParams params =
                new DataSourceParams.Builder()
                        .setBufferExhaustedPolicy(
                                DataSourceParams
                                        .PERFETTO_DS_BUFFER_EXHAUSTED_POLICY_DROP)
                        .build();
        sTestDataSource.register(params);

        ProtoLog.init(TestProtoLogGroup.values());
    }

    @Before
    public void setUp() throws ServiceNotFoundException {
        TestProtoLogGroup.TEST_GROUP.setLogToProto(mLogToProto);
        TestProtoLogGroup.TEST_GROUP.setLogToLogcat(mLogToLogcat);

        mProcessedProtoLogger = new ProcessedPerfettoProtoLogImpl(
                sTestDataSource,
                MOCK_TEST_FILE_PATH,
                () -> new AutoClosableProtoInputStream(VIEWER_CONFIG.toByteArray()),
                (instance) -> {},
                TestProtoLogGroup.values()
        );
    }

    @Test
    public void log_Processed_NoArgs() {
        final var perfMonitor = new PerfMonitor();

        while (perfMonitor.keepRunning()) {
            mProcessedProtoLogger.log(
                    LogLevel.INFO, TestProtoLogGroup.TEST_GROUP, 123,
                    0, (Object[]) null);
        }
    }

    @Test
    public void log_Processed_WithArgs() {
        final var perfMonitor = new PerfMonitor();

        while (perfMonitor.keepRunning()) {
            mProcessedProtoLogger.log(
                    LogLevel.INFO, TestProtoLogGroup.TEST_GROUP, 123,
                    0b1110101001010100,
                    new Object[]{"test", 1, 2, 3, 0.4, 0.5, 0.6, true});
        }
    }

    @Test
    public void log_Unprocessed_NoArgs() {
        final var perfMonitor = new PerfMonitor();

        while (perfMonitor.keepRunning()) {
            ProtoLog.d(TestProtoLogGroup.TEST_GROUP, "Test message");
        }
    }

    @Test
    public void log_Unprocessed_WithArgs() {
        final var perfMonitor = new PerfMonitor();

        while (perfMonitor.keepRunning()) {
            ProtoLog.d(TestProtoLogGroup.TEST_GROUP, "Test message %s, %d, %b", "arg1", 2, true);
        }
    }

    private class PerfMonitor {
        private int mIteration = 0;

        private static final int WARM_UP_ITERATIONS = 10;
        private static final int ITERATIONS = 1000;

        private final ArrayList<Long> mResults = new ArrayList<>();

        private long mStartTimeNs;

        public boolean keepRunning() {
            final long currentTime = System.nanoTime();

            mIteration++;

            if (mIteration > ITERATIONS) {
                reportResults();
                return false;
            }

            if (mIteration > WARM_UP_ITERATIONS) {
                mResults.add(currentTime - mStartTimeNs);
            }

            mStartTimeNs = System.nanoTime();
            return true;
        }

        public void reportResults() {
            final var stats = new Stats(mResults);

            Bundle status = new Bundle();
            status.putLong("protologging_time_mean_ns", (long) stats.getMean());
            status.putLong("protologging_time_median_ns", (long) stats.getMedian());
            InstrumentationRegistry.getInstrumentation().sendStatus(Activity.RESULT_OK, status);
        }
    }

    private enum TestProtoLogGroup implements IProtoLogGroup {
        TEST_GROUP(true, true, false, "WindowManagetProtoLogTest");

        private final boolean mEnabled;
        private volatile boolean mLogToProto;
        private volatile boolean mLogToLogcat;
        private final String mTag;

        /**
         * @param enabled set to false to exclude all log statements for this group from
         *     compilation, they will not be available in runtime.
         * @param logToProto enable binary logging for the group
         * @param logToLogcat enable text logging for the group
         * @param tag name of the source of the logged message
         */
        TestProtoLogGroup(boolean enabled, boolean logToProto, boolean logToLogcat, String tag) {
            this.mEnabled = enabled;
            this.mLogToProto = logToProto;
            this.mLogToLogcat = logToLogcat;
            this.mTag = tag;
        }

        @Override
        public boolean isEnabled() {
            return mEnabled;
        }

        @Override
        public boolean isLogToProto() {
            return mLogToProto;
        }

        @Override
        public boolean isLogToLogcat() {
            return mLogToLogcat;
        }

        @Override
        public boolean isLogToAny() {
            return mLogToLogcat || mLogToProto;
        }

        @Override
        public String getTag() {
            return mTag;
        }

        @Override
        public void setLogToProto(boolean logToProto) {
            this.mLogToProto = logToProto;
        }

        @Override
        public void setLogToLogcat(boolean logToLogcat) {
            this.mLogToLogcat = logToLogcat;
        }

        @Override
        public int getId() {
            return ordinal();
        }
    }

    private enum LogTo {
        PROTO_ONLY,
        LOGCAT_ONLY,
        ALL,
        NONE,
    }
}
Loading