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

Commit f7157470 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Statsd -> Perfetto integration"

parents 18fb2fe4 e4d44919
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -781,6 +781,7 @@ LOCAL_PROTOC_FLAGS := \
LOCAL_SOURCE_FILES_ALL_GENERATED := true
LOCAL_SRC_FILES := \
    cmds/am/proto/instrumentation_data.proto \
    cmds/statsd/src/perfetto/perfetto_config.proto \
    $(call all-proto-files-under, core/proto) \
    $(call all-proto-files-under, libs/incident/proto) \
    $(call all-proto-files-under, cmds/statsd/src)
+3 −0
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ statsd_common_src := \
    src/config/ConfigKey.cpp \
    src/config/ConfigListener.cpp \
    src/config/ConfigManager.cpp \
    src/external/Perfetto.cpp \
    src/external/StatsPuller.cpp \
    src/external/StatsCompanionServicePuller.cpp \
    src/external/SubsystemSleepStatePuller.cpp \
@@ -57,6 +58,7 @@ statsd_common_src := \
    src/metrics/MetricsManager.cpp \
    src/metrics/metrics_manager_util.cpp \
    src/packages/UidMap.cpp \
    src/perfetto/perfetto_config.proto \
    src/storage/StorageManager.cpp \
    src/StatsLogProcessor.cpp \
    src/StatsService.cpp \
@@ -209,6 +211,7 @@ LOCAL_MODULE := statsdprotolite
LOCAL_SRC_FILES := \
    src/stats_log.proto \
    src/statsd_config.proto \
    src/perfetto/perfetto_config.proto \
    src/atoms.proto

LOCAL_PROTOC_OPTIMIZE_TYPE := lite
+2 −1
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
#include "Log.h"

#include "AnomalyTracker.h"
#include "external/Perfetto.h"
#include "guardrail/StatsdStats.h"

#include <android/os/IIncidentManager.h>
@@ -239,7 +240,7 @@ void AnomalyTracker::informSubscribers(const HashableDimensionKey& key) {
                }
                break;
            case Subscription::SubscriberInformationCase::kPerfettoDetails:
                ALOGW("Perfetto reports not implemented.");
                CollectPerfettoTraceAndUploadToDropbox(subscription.perfetto_details());
                break;
            default:
                break;
+111 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 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.
 */

#include "Log.h"

#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"  // Alert

#include <android-base/unique_fd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

#include <string>

namespace {
const char kDropboxTag[] = "perfetto";
}

namespace android {
namespace os {
namespace statsd {

bool CollectPerfettoTraceAndUploadToDropbox(const PerfettoDetails& config) {
    ALOGD("Starting trace collection through perfetto");

    if (!config.has_trace_config()) {
        ALOGE("The perfetto trace config is empty, aborting");
        return false;
    }

    android::base::unique_fd readPipe;
    android::base::unique_fd writePipe;
    if (!android::base::Pipe(&readPipe, &writePipe)) {
        ALOGE("pipe() failed while calling the Perfetto client: %s", strerror(errno));
        return false;
    }

    pid_t pid = fork();
    if (pid < 0) {
        ALOGE("fork() failed while calling the Perfetto client: %s", strerror(errno));
        return false;
    }

    if (pid == 0) {
        // Child process.

        // No malloc calls or library calls after this point. Remember that even
        // ALOGx (aka android_printLog()) can use dynamic memory for vsprintf().

        writePipe.reset();  // Close the write end (owned by the main process).

        // Replace stdin with |readPipe| so the main process can write into it.
        if (dup2(readPipe.get(), STDIN_FILENO) < 0) _exit(1);
        execl("/system/bin/perfetto", "perfetto", "--background", "--config", "-", "--dropbox",
              kDropboxTag, nullptr);

        // execl() doesn't return in case of success, if we get here something failed.
        _exit(1);
    }

    // Main process.

    readPipe.reset();  // Close the read end (owned by the child process).

    // Using fopen() because fwrite() has the right logic to chunking write()
    // over a pipe (see __sfvwrite()).
    FILE* writePipeStream = fdopen(writePipe.get(), "wb");
    if (!writePipeStream) {
        ALOGE("fdopen() failed while calling the Perfetto client: %s", strerror(errno));
        return false;
    }

    std::string cfgProto = config.trace_config().SerializeAsString();
    size_t bytesWritten = fwrite(cfgProto.data(), 1, cfgProto.size(), writePipeStream);
    fclose(writePipeStream);
    if (bytesWritten != cfgProto.size() || cfgProto.size() == 0) {
        ALOGE("fwrite() failed (ret: %zd) while calling the Perfetto client: %s", bytesWritten,
              strerror(errno));
        return false;
    }

    // This does NOT wait for the full duration of the trace. It just waits until the process
    // has read the config from stdin and detached.
    int childStatus = 0;
    waitpid(pid, &childStatus, 0);
    if (!WIFEXITED(childStatus) || WEXITSTATUS(childStatus) != 0) {
        ALOGE("Child process failed (0x%x) while calling the Perfetto client", childStatus);
        return false;
    }

    ALOGD("CollectPerfettoTraceAndUploadToDropbox() succeeded");
    return true;
}

}  // namespace statsd
}  // namespace os
}  // namespace android
+35 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 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.
 */

#pragma once

using android::os::StatsLogEventWrapper;

namespace android {
namespace os {
namespace statsd {

class PerfettoDetails;  // Declared in statsd_config.pb.h

// Starts the collection of a Perfetto trace with the given |config|.
// The trace is uploaded to Dropbox by the perfetto cmdline util once done.
// This method returns immediately after passing the config and does NOT wait
// for the full duration of the trace.
bool CollectPerfettoTraceAndUploadToDropbox(const PerfettoDetails& config);

}  // namespace statsd
}  // namespace os
}  // namespace android
Loading