Merge "Fix zygote energy-aware scheduler tuning bug"
diff --git a/base/include/android-base/logging.h b/base/include/android-base/logging.h
index c626fc3..39f4689 100644
--- a/base/include/android-base/logging.h
+++ b/base/include/android-base/logging.h
@@ -51,12 +51,15 @@
SYSTEM,
};
-typedef std::function<void(LogId, LogSeverity, const char*, const char*,
- unsigned int, const char*)> LogFunction;
+using LogFunction = std::function<void(LogId, LogSeverity, const char*, const char*,
+ unsigned int, const char*)>;
+using AbortFunction = std::function<void(const char*)>;
void KernelLogger(LogId, LogSeverity, const char*, const char*, unsigned int, const char*);
void StderrLogger(LogId, LogSeverity, const char*, const char*, unsigned int, const char*);
+void DefaultAborter(const char* abort_message);
+
#ifdef __ANDROID__
// We expose this even though it is the default because a user that wants to
// override the default log buffer will have to construct this themselves.
@@ -80,15 +83,22 @@
// The tag (or '*' for the global level) comes first, followed by a colon and a
// letter indicating the minimum priority level we're expected to log. This can
// be used to reveal or conceal logs with specific tags.
-void InitLogging(char* argv[], LogFunction&& logger);
-
-// Configures logging using the default logger (logd for the device, stderr for
-// the host).
-void InitLogging(char* argv[]);
+#ifdef __ANDROID__
+#define INIT_LOGGING_DEFAULT_LOGGER LogdLogger()
+#else
+#define INIT_LOGGING_DEFAULT_LOGGER StderrLogger
+#endif
+void InitLogging(char* argv[],
+ LogFunction&& logger = INIT_LOGGING_DEFAULT_LOGGER,
+ AbortFunction&& aborter = DefaultAborter);
+#undef INIT_LOGGING_DEFAULT_LOGGER
// Replace the current logger.
void SetLogger(LogFunction&& logger);
+// Replace the current aborter.
+void SetAborter(AbortFunction&& aborter);
+
class ErrnoRestorer {
public:
ErrnoRestorer()
diff --git a/base/logging.cpp b/base/logging.cpp
index 86d3b4d..6e1dd9c 100644
--- a/base/logging.cpp
+++ b/base/logging.cpp
@@ -173,6 +173,8 @@
static auto& gLogger = *new LogFunction(StderrLogger);
#endif
+static auto& gAborter = *new AbortFunction(DefaultAborter);
+
static bool gInitialized = false;
static LogSeverity gMinimumLogSeverity = INFO;
static auto& gProgramInvocationName = *new std::unique_ptr<std::string>();
@@ -247,6 +249,15 @@
severity_char, timestamp, getpid(), GetThreadId(), file, line, message);
}
+void DefaultAborter(const char* abort_message) {
+#ifdef __ANDROID__
+ android_set_abort_message(abort_message);
+#else
+ UNUSED(abort_message);
+#endif
+ abort();
+}
+
#ifdef __ANDROID__
LogdLogger::LogdLogger(LogId default_log_id) : default_log_id_(default_log_id) {
@@ -284,12 +295,10 @@
}
#endif
-void InitLogging(char* argv[], LogFunction&& logger) {
+void InitLogging(char* argv[], LogFunction&& logger, AbortFunction&& aborter) {
SetLogger(std::forward<LogFunction>(logger));
- InitLogging(argv);
-}
+ SetAborter(std::forward<AbortFunction>(aborter));
-void InitLogging(char* argv[]) {
if (gInitialized) {
return;
}
@@ -349,6 +358,11 @@
gLogger = std::move(logger);
}
+void SetAborter(AbortFunction&& aborter) {
+ lock_guard<mutex> lock(logging_lock);
+ gAborter = std::move(aborter);
+}
+
static const char* GetFileBasename(const char* file) {
// We can't use basename(3) even on Unix because the Mac doesn't
// have a non-modifying basename.
@@ -450,10 +464,7 @@
// Abort if necessary.
if (data_->GetSeverity() == FATAL) {
-#ifdef __ANDROID__
- android_set_abort_message(msg.c_str());
-#endif
- abort();
+ gAborter(msg.c_str());
}
}
diff --git a/base/logging_test.cpp b/base/logging_test.cpp
index 3fde302..02a9198 100644
--- a/base/logging_test.cpp
+++ b/base/logging_test.cpp
@@ -330,3 +330,23 @@
UNIMPLEMENTED(ERROR);
CheckMessage(cap, android::base::ERROR, expected.c_str());
}
+
+static void NoopAborter(const char* msg ATTRIBUTE_UNUSED) {
+ LOG(ERROR) << "called noop";
+}
+
+TEST(logging, LOG_FATAL_NOOP_ABORTER) {
+ {
+ android::base::SetAborter(NoopAborter);
+
+ android::base::ScopedLogSeverity sls(android::base::ERROR);
+ CapturedStderr cap;
+ LOG(FATAL) << "foobar";
+ CheckMessage(cap, android::base::FATAL, "foobar");
+ CheckMessage(cap, android::base::ERROR, "called noop");
+
+ android::base::SetAborter(android::base::DefaultAborter);
+ }
+
+ ASSERT_DEATH({SuppressAbortUI(); LOG(FATAL) << "foobar";}, "foobar");
+}
diff --git a/crash_reporter/.project_alias b/crash_reporter/.project_alias
deleted file mode 100644
index 0bc3798..0000000
--- a/crash_reporter/.project_alias
+++ /dev/null
@@ -1 +0,0 @@
-crash
diff --git a/crash_reporter/99-crash-reporter.rules b/crash_reporter/99-crash-reporter.rules
deleted file mode 100644
index aea5b1c..0000000
--- a/crash_reporter/99-crash-reporter.rules
+++ /dev/null
@@ -1,6 +0,0 @@
-ACTION=="change", SUBSYSTEM=="drm", KERNEL=="card0", ENV{ERROR}=="1", RUN+="/sbin/crash_reporter --udev=KERNEL=card0:SUBSYSTEM=drm:ACTION=change"
-# For detecting cypress trackpad issue. Passing into crash_reporter SUBSYSTEM=i2c-cyapa since crash_reporter does not handle DRIVER string.
-ACTION=="change", SUBSYSTEM=="i2c", DRIVER=="cyapa", ENV{ERROR}=="1", RUN+="/sbin/crash_reporter --udev=SUBSYSTEM=i2c-cyapa:ACTION=change"
-# For detecting Atmel trackpad/touchscreen issue. Passing into crash_reporter SUBSYSTEM=i2c-atmel_mxt_ts since crash_reporter does not handle DRIVER string.
-ACTION=="change", SUBSYSTEM=="i2c", DRIVER=="atmel_mxt_ts", ENV{ERROR}=="1", RUN+="/sbin/crash_reporter --udev=SUBSYSTEM=i2c-atmel_mxt_ts:ACTION=change"
-ACTION=="add", SUBSYSTEM=="devcoredump", RUN+="/sbin/crash_reporter --udev=SUBSYSTEM=devcoredump:ACTION=add:KERNEL_NUMBER=%n"
diff --git a/crash_reporter/Android.mk b/crash_reporter/Android.mk
deleted file mode 100644
index 4feb72a..0000000
--- a/crash_reporter/Android.mk
+++ /dev/null
@@ -1,144 +0,0 @@
-# Copyright (C) 2015 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.
-
-LOCAL_PATH := $(call my-dir)
-
-crash_reporter_cpp_extension := .cc
-
-crash_reporter_src := crash_collector.cc \
- kernel_collector.cc \
- kernel_warning_collector.cc \
- unclean_shutdown_collector.cc \
- user_collector.cc
-
-crash_reporter_includes := external/gtest/include
-
-crash_reporter_test_src := crash_collector_test.cc \
- crash_reporter_logs_test.cc \
- kernel_collector_test.cc \
- testrunner.cc \
- unclean_shutdown_collector_test.cc \
- user_collector_test.cc
-
-warn_collector_src := warn_collector.l
-
-# Crash reporter static library.
-# ========================================================
-include $(CLEAR_VARS)
-LOCAL_MODULE := libcrash
-LOCAL_CPP_EXTENSION := $(crash_reporter_cpp_extension)
-LOCAL_C_INCLUDES := $(crash_reporter_includes)
-LOCAL_SHARED_LIBRARIES := libchrome \
- libbinder \
- libbrillo \
- libcutils \
- libmetrics \
- libpcrecpp
-LOCAL_STATIC_LIBRARIES := libmetricscollectorservice
-LOCAL_SRC_FILES := $(crash_reporter_src)
-include $(BUILD_STATIC_LIBRARY)
-
-# Crash reporter client.
-# ========================================================
-include $(CLEAR_VARS)
-LOCAL_MODULE := crash_reporter
-LOCAL_CPP_EXTENSION := $(crash_reporter_cpp_extension)
-LOCAL_C_INCLUDES := $(crash_reporter_includes)
-LOCAL_REQUIRED_MODULES := core2md \
- crash_reporter_logs.conf \
- crash_sender \
- crash_server
-LOCAL_INIT_RC := crash_reporter.rc
-LOCAL_SHARED_LIBRARIES := libchrome \
- libbinder \
- libbrillo \
- libcutils \
- libmetrics \
- libpcrecpp \
- libutils
-LOCAL_SRC_FILES := crash_reporter.cc
-LOCAL_STATIC_LIBRARIES := libcrash \
- libmetricscollectorservice
-include $(BUILD_EXECUTABLE)
-
-# Crash sender script.
-# ========================================================
-include $(CLEAR_VARS)
-LOCAL_MODULE := crash_sender
-LOCAL_MODULE_CLASS := EXECUTABLES
-LOCAL_MODULE_PATH := $(TARGET_OUT_EXECUTABLES)
-LOCAL_REQUIRED_MODULES := curl grep periodic_scheduler
-LOCAL_SRC_FILES := crash_sender
-include $(BUILD_PREBUILT)
-
-# Warn collector client.
-# ========================================================
-include $(CLEAR_VARS)
-LOCAL_MODULE := warn_collector
-LOCAL_CPP_EXTENSION := $(crash_reporter_cpp_extension)
-LOCAL_SHARED_LIBRARIES := libmetrics
-LOCAL_SRC_FILES := $(warn_collector_src)
-include $(BUILD_EXECUTABLE)
-
-# /etc/os-release.d/crash_server configuration file.
-# ========================================================
-ifdef OSRELEASED_DIRECTORY
-include $(CLEAR_VARS)
-LOCAL_MODULE := crash_server
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/$(OSRELEASED_DIRECTORY)
-include $(BUILD_SYSTEM)/base_rules.mk
-
-# Optionally populate the BRILLO_CRASH_SERVER variable from a product
-# configuration file: brillo/crash_server.
-LOADED_BRILLO_CRASH_SERVER := $(call cfgtree-get-if-exists,brillo/crash_server)
-
-# If the crash server isn't set, use a blank value. crash_sender
-# will log it as a configuration error.
-$(LOCAL_BUILT_MODULE): BRILLO_CRASH_SERVER ?= "$(LOADED_BRILLO_CRASH_SERVER)"
-$(LOCAL_BUILT_MODULE):
- $(hide)mkdir -p $(dir $@)
- echo $(BRILLO_CRASH_SERVER) > $@
-endif
-
-# Crash reporter logs conf file.
-# ========================================================
-include $(CLEAR_VARS)
-LOCAL_MODULE := crash_reporter_logs.conf
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(PRODUCT_OUT)/system/etc
-LOCAL_SRC_FILES := crash_reporter_logs.conf
-include $(BUILD_PREBUILT)
-
-# Periodic Scheduler.
-# ========================================================
-include $(CLEAR_VARS)
-LOCAL_MODULE := periodic_scheduler
-LOCAL_MODULE_CLASS := EXECUTABLES
-LOCAL_MODULE_PATH := $(TARGET_OUT_EXECUTABLES)
-LOCAL_SRC_FILES := periodic_scheduler
-include $(BUILD_PREBUILT)
-
-# Crash reporter tests.
-# ========================================================
-include $(CLEAR_VARS)
-LOCAL_MODULE := crash_reporter_tests
-LOCAL_CPP_EXTENSION := $(crash_reporter_cpp_extension)
-LOCAL_SHARED_LIBRARIES := libchrome \
- libbrillo \
- libcutils \
- libpcrecpp
-LOCAL_SRC_FILES := $(crash_reporter_test_src)
-LOCAL_STATIC_LIBRARIES := libcrash libgmock
-include $(BUILD_NATIVE_TEST)
diff --git a/crash_reporter/OWNERS b/crash_reporter/OWNERS
deleted file mode 100644
index 96ea5b2..0000000
--- a/crash_reporter/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-set noparent
-vapier@chromium.org
diff --git a/crash_reporter/README.md b/crash_reporter/README.md
deleted file mode 100644
index 9ac0a86..0000000
--- a/crash_reporter/README.md
+++ /dev/null
@@ -1,61 +0,0 @@
-# crash_reporter
-
-`crash_reporter` is a deamon running on the device that saves the call stack of
-crashing programs. It makes use of the
-[Breakpad](https://chromium.googlesource.com/breakpad/breakpad/) library.
-
-During a build, Breakpad symbol files are generated for all binaries. They are
-packaged into a zip file when running `m dist`, so that a developer can upload
-them to the crash server.
-
-On a device, if the user has opted in to metrics and crash reporting, a
-Breakpad minidump is generated when an executable crashes, which is then
-uploaded to the crash server.
-
-On the crash server, it compares the minidump's signature to the symbol files
-that the developer has uploaded, and extracts and symbolizes the stack trace
-from the minidump.
-
-## SELinux policies
-
-In order to correctly generate a minidump, `crash_reporter` needs to be given
-the proper SELinux permissions for accessing the domain of the crashing
-executable. By default, `crash_reporter` has only been given access to a select
-number of system domains, such as `metricsd`, `weave`, and `update_engine`. If
-a developer wants their executable's crashes to be caught by `crash_reporter`,
-they will have to set their SELinux policies in their .te file to allow
-`crash_reporter` access to their domain. This can be done through a simple
-[macro](https://android.googlesource.com/device/generic/brillo/+/master/sepolicy/te_macros):
-
- allow_crash_reporter(domain_name)
-
-Replace *domain_name* with whatever domain is assigned to the executable in
-the `file_contexts` file.
-
-## Configuration
-
-`crash_reporter` has a few different configuration options that have to be set.
-
-- Crashes are only handled and uploaded if analytics reporting is enabled,
- either via the weave call to set `_metrics.enableAnalyticsReporting` or by
- manually creating the file `/data/misc/metrics/enabled` (for testing only).
-- The `BRILLO_CRASH_SERVER` make variable should be set in the `product.mk`
- file to the URL of the crash server. For Brillo builds, it is set
- automatically through the product configuration. Setting this variable will
- populate the `/etc/os-release.d/crash_server` file on the device, which is
- read by `crash_sender`.
-- The `BRILLO_PRODUCT_ID` make variable should be set in the `product.mk` file
- to the product's ID. For Brillo builds, it is set automatically through the
- product configuration. Setting this variable will populate the
- `/etc/os-release.d/product_id`, which is read by `crash_sender`.
-
-## Uploading crash reports in *eng* builds
-
-By default, crash reports are only uploaded to the server for production
-*user* and *userdebug* images. In *eng* builds, with crash reporting enabled
-the device will generate minidumps for any crashing executables but will not
-send them to the crash server. If a developer does want to force an upload,
-they can do so by issuing the command `SECONDS_SEND_SPREAD=5 FORCE_OFFICIAL=1
-crash_sender` from an ADB shell. This will send the report to the server, with
-the *image_type* field set to *force-official* so that these reports can be
-differentiated from normal reports.
diff --git a/crash_reporter/TEST_WARNING b/crash_reporter/TEST_WARNING
deleted file mode 100644
index 64ad2e9..0000000
--- a/crash_reporter/TEST_WARNING
+++ /dev/null
@@ -1,31 +0,0 @@
-Apr 31 25:25:25 localhost kernel: [117959.226729] [<ffffffff810e16bf>] do_vfs_ioctl+0x469/0x4b3
-Apr 31 25:25:25 localhost kernel: [117959.226738] [<ffffffff810d3117>] ? fsnotify_access+0x58/0x60
-Apr 31 25:25:25 localhost kernel: [117959.226747] [<ffffffff810d3791>] ? vfs_read+0xad/0xd7
-Apr 31 25:25:25 localhost kernel: [117959.226756] [<ffffffff810e175f>] sys_ioctl+0x56/0x7b
-Apr 31 25:25:25 localhost kernel: [117959.226765] [<ffffffff810d37fe>] ? sys_read+0x43/0x73
-Apr 31 25:25:25 localhost kernel: [117959.226774] [<ffffffff8146b7d2>] system_call_fastpath+0x16/0x1b
-Apr 31 25:25:25 localhost kernel: [117959.226782] ---[ end trace f16822cad7406cec ]---
-Apr 31 25:25:25 localhost kernel: [117959.231085] ------------[ cut here ]------------
-Apr 31 25:25:25 localhost kernel: [117959.231100] WARNING: at /mnt/host/source/src/third_party/kernel/files/drivers/gpu/drm/i915/intel_dp.c:351 intel_dp_check_edp+0x6b/0xb9()
-Apr 31 25:25:25 localhost kernel: [117959.231113] Hardware name: Link
-Apr 31 25:25:25 localhost kernel: [117959.231117] eDP powered off while attempting aux channel communication.
-Apr 31 25:25:25 localhost kernel: [117959.231240] Pid: 10508, comm: X Tainted: G WC 3.4.0 #1
-Apr 31 25:25:25 localhost kernel: [117959.231247] Call Trace:
-Apr 31 25:25:25 localhost kernel: [117959.231393] [<ffffffff810d3117>] ? fsnotify_access+0x58/0x60
-Apr 31 25:25:25 localhost kernel: [117959.231402] [<ffffffff810d3791>] ? vfs_read+0xad/0xd7
-Apr 31 25:25:25 localhost kernel: [117959.231411] [<ffffffff810e175f>] sys_ioctl+0x56/0x7b
-Apr 31 25:25:25 localhost kernel: [117959.231420] [<ffffffff810d37fe>] ? sys_read+0x43/0x73
-Apr 31 25:25:25 localhost kernel: [117959.231431] [<ffffffff8146b7d2>] system_call_fastpath+0x16/0x1b
-Apr 31 25:25:25 localhost kernel: [117959.231439] ---[ end trace f16822cad7406ced ]---
-Apr 31 25:25:25 localhost kernel: [117959.231450] ------------[ cut here ]------------
-Apr 31 25:25:25 localhost kernel: [117959.231458] BARNING: at /mnt/host/source/src/third_party/kernel/files/drivers/gpu/drm/i915/intel_dp.c:351 intel_dp_check_edp+0x6b/0xb9()
-Apr 31 25:25:25 localhost kernel: [117959.231458] ("BARNING" above is intentional)
-Apr 31 25:25:25 localhost kernel: [117959.231471] Hardware name: Link
-Apr 31 25:25:25 localhost kernel: [117959.231475] eDP powered off while attempting aux channel communication.
-Apr 31 25:25:25 localhost kernel: [117959.231482] Modules linked in: nls_iso8859_1 nls_cp437 vfat fat rfcomm i2c_dev ath9k_btcoex snd_hda_codec_hdmi snd_hda_codec_ca0132 mac80211 snd_hda_intel ath9k_common_btcoex snd_hda_codec ath9k_hw_btcoex aesni_intel cryptd snd_hwdep ath snd_pcm aes_x86_64 isl29018(C) memconsole snd_timer snd_page_alloc industrialio(C) cfg80211 rtc_cmos nm10_gpio zram(C) zsmalloc(C) lzo_decompress lzo_compress fuse nf_conntrack_ipv6 nf_defrag_ipv6 ip6table_filter ip6_tables xt_mark option usb_wwan cdc_ether usbnet ath3k btusb bluetooth uvcvideo videobuf2_core videodev videobuf2_vmalloc videobuf2_memops joydev
-Apr 31 25:25:25 localhost kernel: [117959.231588] Pid: 10508, comm: X Tainted: G WC 3.4.0 #1
-Apr 31 25:25:25 localhost kernel: [117959.231595] Call Trace:
-Apr 31 25:25:25 localhost kernel: [117959.231601] [<ffffffff8102a931>] warn_slowpath_common+0x83/0x9c
-Apr 31 25:25:25 localhost kernel: [117959.231610] [<ffffffff8102a9ed>] warn_slowpath_fmt+0x46/0x48
-Apr 31 25:25:25 localhost kernel: [117959.231620] [<ffffffff812af495>] intel_dp_check_edp+0x6b/0xb9
-Apr 31 25:25:25 localhost kernel: [117959.231629] [<ffffffff8102a9ed>] ? warn_slowpath_fmt+
diff --git a/crash_reporter/crash_collector.cc b/crash_reporter/crash_collector.cc
deleted file mode 100644
index 6e81c51..0000000
--- a/crash_reporter/crash_collector.cc
+++ /dev/null
@@ -1,454 +0,0 @@
-/*
- * Copyright (C) 2012 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 "crash_collector.h"
-
-#include <dirent.h>
-#include <fcntl.h> // For file creation modes.
-#include <inttypes.h>
-#include <linux/limits.h> // PATH_MAX
-#include <pwd.h> // For struct passwd.
-#include <sys/types.h> // for mode_t.
-#include <sys/wait.h> // For waitpid.
-#include <unistd.h> // For execv and fork.
-
-#include <set>
-#include <utility>
-#include <vector>
-
-#include <base/files/file_util.h>
-#include <base/logging.h>
-#include <base/posix/eintr_wrapper.h>
-#include <base/strings/string_split.h>
-#include <base/strings/string_util.h>
-#include <base/strings/stringprintf.h>
-#include <brillo/key_value_store.h>
-#include <brillo/osrelease_reader.h>
-#include <brillo/process.h>
-
-namespace {
-
-const char kCollectChromeFile[] =
- "/mnt/stateful_partition/etc/collect_chrome_crashes";
-const char kCrashTestInProgressPath[] =
- "/data/misc/crash_reporter/tmp/crash-test-in-progress";
-const char kDefaultLogConfig[] = "/etc/crash_reporter_logs.conf";
-const char kDefaultUserName[] = "chronos";
-const char kLeaveCoreFile[] = "/data/misc/crash_reporter/.leave_core";
-const char kShellPath[] = "/system/bin/sh";
-const char kSystemCrashPath[] = "/data/misc/crash_reporter/crash";
-const char kUploadVarPrefix[] = "upload_var_";
-const char kUploadFilePrefix[] = "upload_file_";
-
-// Product information keys in the /etc/os-release.d folder.
-static const char kBdkVersionKey[] = "bdk_version";
-static const char kProductIDKey[] = "product_id";
-static const char kProductVersionKey[] = "product_version";
-
-// Normally this path is not used. Unfortunately, there are a few edge cases
-// where we need this. Any process that runs as kDefaultUserName that crashes
-// is consider a "user crash". That includes the initial Chrome browser that
-// runs the login screen. If that blows up, there is no logged in user yet,
-// so there is no per-user dir for us to stash things in. Instead we fallback
-// to this path as it is at least encrypted on a per-system basis.
-//
-// This also comes up when running autotests. The GUI is sitting at the login
-// screen while tests are sshing in, changing users, and triggering crashes as
-// the user (purposefully).
-const char kFallbackUserCrashPath[] = "/home/chronos/crash";
-
-// Directory mode of the user crash spool directory.
-const mode_t kUserCrashPathMode = 0755;
-
-// Directory mode of the system crash spool directory.
-const mode_t kSystemCrashPathMode = 01755;
-
-const uid_t kRootOwner = 0;
-const uid_t kRootGroup = 0;
-
-} // namespace
-
-// Maximum crash reports per crash spool directory. Note that this is
-// a separate maximum from the maximum rate at which we upload these
-// diagnostics. The higher this rate is, the more space we allow for
-// core files, minidumps, and kcrash logs, and equivalently the more
-// processor and I/O bandwidth we dedicate to handling these crashes when
-// many occur at once. Also note that if core files are configured to
-// be left on the file system, we stop adding crashes when either the
-// number of core files or minidumps reaches this number.
-const int CrashCollector::kMaxCrashDirectorySize = 32;
-
-using base::FilePath;
-using base::StringPrintf;
-
-CrashCollector::CrashCollector()
- : log_config_path_(kDefaultLogConfig) {
-}
-
-CrashCollector::~CrashCollector() {
-}
-
-void CrashCollector::Initialize(
- CrashCollector::CountCrashFunction count_crash_function,
- CrashCollector::IsFeedbackAllowedFunction is_feedback_allowed_function) {
- CHECK(count_crash_function);
- CHECK(is_feedback_allowed_function);
-
- count_crash_function_ = count_crash_function;
- is_feedback_allowed_function_ = is_feedback_allowed_function;
-}
-
-int CrashCollector::WriteNewFile(const FilePath &filename,
- const char *data,
- int size) {
- int fd = HANDLE_EINTR(open(filename.value().c_str(),
- O_CREAT | O_WRONLY | O_TRUNC | O_EXCL, 0666));
- if (fd < 0) {
- return -1;
- }
-
- int rv = base::WriteFileDescriptor(fd, data, size) ? size : -1;
- IGNORE_EINTR(close(fd));
- return rv;
-}
-
-std::string CrashCollector::Sanitize(const std::string &name) {
- // Make sure the sanitized name does not include any periods.
- // The logic in crash_sender relies on this.
- std::string result = name;
- for (size_t i = 0; i < name.size(); ++i) {
- if (!isalnum(result[i]) && result[i] != '_')
- result[i] = '_';
- }
- return result;
-}
-
-std::string CrashCollector::FormatDumpBasename(const std::string &exec_name,
- time_t timestamp,
- pid_t pid) {
- struct tm tm;
- localtime_r(×tamp, &tm);
- std::string sanitized_exec_name = Sanitize(exec_name);
- return StringPrintf("%s.%04d%02d%02d.%02d%02d%02d.%d",
- sanitized_exec_name.c_str(),
- tm.tm_year + 1900,
- tm.tm_mon + 1,
- tm.tm_mday,
- tm.tm_hour,
- tm.tm_min,
- tm.tm_sec,
- pid);
-}
-
-FilePath CrashCollector::GetCrashPath(const FilePath &crash_directory,
- const std::string &basename,
- const std::string &extension) {
- return crash_directory.Append(StringPrintf("%s.%s",
- basename.c_str(),
- extension.c_str()));
-}
-
-FilePath CrashCollector::GetCrashDirectoryInfo(
- mode_t *mode,
- uid_t *directory_owner,
- gid_t *directory_group) {
- *mode = kSystemCrashPathMode;
- *directory_owner = kRootOwner;
- *directory_group = kRootGroup;
- return FilePath(kSystemCrashPath);
-}
-
-bool CrashCollector::GetUserInfoFromName(const std::string &name,
- uid_t *uid,
- gid_t *gid) {
- char storage[256];
- struct passwd passwd_storage;
- struct passwd *passwd_result = nullptr;
-
- if (getpwnam_r(name.c_str(), &passwd_storage, storage, sizeof(storage),
- &passwd_result) != 0 || passwd_result == nullptr) {
- LOG(ERROR) << "Cannot find user named " << name;
- return false;
- }
-
- *uid = passwd_result->pw_uid;
- *gid = passwd_result->pw_gid;
- return true;
-}
-
-bool CrashCollector::GetCreatedCrashDirectoryByEuid(uid_t euid __unused,
- FilePath *crash_directory,
- bool *out_of_capacity) {
- if (out_of_capacity) *out_of_capacity = false;
-
- // For testing.
- if (!forced_crash_directory_.empty()) {
- *crash_directory = forced_crash_directory_;
- return true;
- }
-
- mode_t directory_mode;
- uid_t directory_owner;
- gid_t directory_group;
- *crash_directory =
- GetCrashDirectoryInfo(&directory_mode,
- &directory_owner,
- &directory_group);
-
- if (!base::PathExists(*crash_directory)) {
- // Create the spool directory with the appropriate mode (regardless of
- // umask) and ownership.
- mode_t old_mask = umask(0);
- if (mkdir(crash_directory->value().c_str(), directory_mode) < 0 ||
- chown(crash_directory->value().c_str(),
- directory_owner,
- directory_group) < 0) {
- LOG(ERROR) << "Unable to create appropriate crash directory";
- return false;
- }
- umask(old_mask);
- }
-
- if (!base::PathExists(*crash_directory)) {
- LOG(ERROR) << "Unable to create crash directory "
- << crash_directory->value().c_str();
- return false;
- }
-
- if (!CheckHasCapacity(*crash_directory)) {
- if (out_of_capacity) *out_of_capacity = true;
- LOG(ERROR) << "Directory " << crash_directory->value()
- << " is out of capacity.";
- return false;
- }
-
- return true;
-}
-
-FilePath CrashCollector::GetProcessPath(pid_t pid) {
- return FilePath(StringPrintf("/proc/%d", pid));
-}
-
-bool CrashCollector::GetSymlinkTarget(const FilePath &symlink,
- FilePath *target) {
- ssize_t max_size = 64;
- std::vector<char> buffer;
-
- while (true) {
- buffer.resize(max_size + 1);
- ssize_t size = readlink(symlink.value().c_str(), buffer.data(), max_size);
- if (size < 0) {
- int saved_errno = errno;
- LOG(ERROR) << "Readlink failed on " << symlink.value() << " with "
- << saved_errno;
- return false;
- }
-
- buffer[size] = 0;
- if (size == max_size) {
- max_size *= 2;
- if (max_size > PATH_MAX) {
- return false;
- }
- continue;
- }
- break;
- }
-
- *target = FilePath(buffer.data());
- return true;
-}
-
-bool CrashCollector::GetExecutableBaseNameFromPid(pid_t pid,
- std::string *base_name) {
- FilePath target;
- FilePath process_path = GetProcessPath(pid);
- FilePath exe_path = process_path.Append("exe");
- if (!GetSymlinkTarget(exe_path, &target)) {
- LOG(INFO) << "GetSymlinkTarget failed - Path " << process_path.value()
- << " DirectoryExists: "
- << base::DirectoryExists(process_path);
- // Try to further diagnose exe readlink failure cause.
- struct stat buf;
- int stat_result = stat(exe_path.value().c_str(), &buf);
- int saved_errno = errno;
- if (stat_result < 0) {
- LOG(INFO) << "stat " << exe_path.value() << " failed: " << stat_result
- << " " << saved_errno;
- } else {
- LOG(INFO) << "stat " << exe_path.value() << " succeeded: st_mode="
- << buf.st_mode;
- }
- return false;
- }
- *base_name = target.BaseName().value();
- return true;
-}
-
-// Return true if the given crash directory has not already reached
-// maximum capacity.
-bool CrashCollector::CheckHasCapacity(const FilePath &crash_directory) {
- DIR* dir = opendir(crash_directory.value().c_str());
- if (!dir) {
- LOG(WARNING) << "Unable to open crash directory "
- << crash_directory.value();
- return false;
- }
- struct dirent ent_buf;
- struct dirent* ent;
- bool full = false;
- std::set<std::string> basenames;
- while (readdir_r(dir, &ent_buf, &ent) == 0 && ent) {
- if ((strcmp(ent->d_name, ".") == 0) ||
- (strcmp(ent->d_name, "..") == 0))
- continue;
-
- std::string filename(ent->d_name);
- size_t last_dot = filename.rfind('.');
- std::string basename;
- // If there is a valid looking extension, use the base part of the
- // name. If the only dot is the first byte (aka a dot file), treat
- // it as unique to avoid allowing a directory full of dot files
- // from accumulating.
- if (last_dot != std::string::npos && last_dot != 0)
- basename = filename.substr(0, last_dot);
- else
- basename = filename;
- basenames.insert(basename);
-
- if (basenames.size() >= static_cast<size_t>(kMaxCrashDirectorySize)) {
- LOG(WARNING) << "Crash directory " << crash_directory.value()
- << " already full with " << kMaxCrashDirectorySize
- << " pending reports";
- full = true;
- break;
- }
- }
- closedir(dir);
- return !full;
-}
-
-bool CrashCollector::GetLogContents(const FilePath &config_path,
- const std::string &exec_name,
- const FilePath &output_file) {
- brillo::KeyValueStore store;
- if (!store.Load(config_path)) {
- LOG(INFO) << "Unable to read log configuration file "
- << config_path.value();
- return false;
- }
-
- std::string command;
- if (!store.GetString(exec_name, &command))
- return false;
-
- brillo::ProcessImpl diag_process;
- diag_process.AddArg(kShellPath);
- diag_process.AddStringOption("-c", command);
- diag_process.RedirectOutput(output_file.value());
-
- const int result = diag_process.Run();
- if (result != 0) {
- LOG(INFO) << "Log command \"" << command << "\" exited with " << result;
- return false;
- }
- return true;
-}
-
-void CrashCollector::AddCrashMetaData(const std::string &key,
- const std::string &value) {
- extra_metadata_.append(StringPrintf("%s=%s\n", key.c_str(), value.c_str()));
-}
-
-void CrashCollector::AddCrashMetaUploadFile(const std::string &key,
- const std::string &path) {
- if (!path.empty())
- AddCrashMetaData(kUploadFilePrefix + key, path);
-}
-
-void CrashCollector::AddCrashMetaUploadData(const std::string &key,
- const std::string &value) {
- if (!value.empty())
- AddCrashMetaData(kUploadVarPrefix + key, value);
-}
-
-void CrashCollector::WriteCrashMetaData(const FilePath &meta_path,
- const std::string &exec_name,
- const std::string &payload_path) {
- int64_t payload_size = -1;
- base::GetFileSize(FilePath(payload_path), &payload_size);
-
- brillo::OsReleaseReader reader;
- if (!forced_osreleased_directory_.empty()) {
- reader.LoadTestingOnly(forced_osreleased_directory_);
- } else {
- reader.Load();
- }
- std::string bdk_version = "undefined";
- std::string product_id = "undefined";
- std::string product_version = "undefined";
-
- if (!reader.GetString(kBdkVersionKey, &bdk_version)) {
- LOG(ERROR) << "Could not read " << kBdkVersionKey
- << " from /etc/os-release.d/";
- }
-
- if (!reader.GetString(kProductIDKey, &product_id)) {
- LOG(ERROR) << "Could not read " << kProductIDKey
- << " from /etc/os-release.d/";
- }
-
- if (!reader.GetString(kProductVersionKey, &product_version)) {
- LOG(ERROR) << "Could not read " << kProductVersionKey
- << " from /etc/os-release.d/";
- }
-
- std::string meta_data = StringPrintf("%sexec_name=%s\n"
- "payload=%s\n"
- "payload_size=%" PRId64 "\n"
- "%s=%s\n"
- "%s=%s\n"
- "%s=%s\n"
- "done=1\n",
- extra_metadata_.c_str(),
- exec_name.c_str(),
- payload_path.c_str(),
- payload_size,
- kBdkVersionKey,
- bdk_version.c_str(),
- kProductIDKey,
- product_id.c_str(),
- kProductVersionKey,
- product_version.c_str());
- // We must use WriteNewFile instead of base::WriteFile as we
- // do not want to write with root access to a symlink that an attacker
- // might have created.
- if (WriteNewFile(meta_path, meta_data.c_str(), meta_data.size()) < 0) {
- LOG(ERROR) << "Unable to write " << meta_path.value();
- }
-}
-
-bool CrashCollector::IsCrashTestInProgress() {
- return base::PathExists(FilePath(kCrashTestInProgressPath));
-}
-
-bool CrashCollector::IsDeveloperImage() {
- // If we're testing crash reporter itself, we don't want to special-case
- // for developer images.
- if (IsCrashTestInProgress())
- return false;
- return base::PathExists(FilePath(kLeaveCoreFile));
-}
diff --git a/crash_reporter/crash_collector.h b/crash_reporter/crash_collector.h
deleted file mode 100644
index 21b9198..0000000
--- a/crash_reporter/crash_collector.h
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Copyright (C) 2012 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.
- */
-
-#ifndef CRASH_REPORTER_CRASH_COLLECTOR_H_
-#define CRASH_REPORTER_CRASH_COLLECTOR_H_
-
-#include <sys/stat.h>
-
-#include <map>
-#include <string>
-
-#include <base/files/file_path.h>
-#include <base/macros.h>
-#include <gtest/gtest_prod.h> // for FRIEND_TEST
-
-// User crash collector.
-class CrashCollector {
- public:
- typedef void (*CountCrashFunction)();
- typedef bool (*IsFeedbackAllowedFunction)();
-
- CrashCollector();
-
- virtual ~CrashCollector();
-
- // Initialize the crash collector for detection of crashes, given a
- // crash counting function, and metrics collection enabled oracle.
- void Initialize(CountCrashFunction count_crash,
- IsFeedbackAllowedFunction is_metrics_allowed);
-
- protected:
- friend class CrashCollectorTest;
- FRIEND_TEST(ChromeCollectorTest, HandleCrash);
- FRIEND_TEST(CrashCollectorTest, CheckHasCapacityCorrectBasename);
- FRIEND_TEST(CrashCollectorTest, CheckHasCapacityStrangeNames);
- FRIEND_TEST(CrashCollectorTest, CheckHasCapacityUsual);
- FRIEND_TEST(CrashCollectorTest, GetCrashDirectoryInfo);
- FRIEND_TEST(CrashCollectorTest, GetCrashPath);
- FRIEND_TEST(CrashCollectorTest, GetLogContents);
- FRIEND_TEST(CrashCollectorTest, ForkExecAndPipe);
- FRIEND_TEST(CrashCollectorTest, FormatDumpBasename);
- FRIEND_TEST(CrashCollectorTest, Initialize);
- FRIEND_TEST(CrashCollectorTest, MetaData);
- FRIEND_TEST(CrashCollectorTest, Sanitize);
- FRIEND_TEST(CrashCollectorTest, WriteNewFile);
- FRIEND_TEST(ForkExecAndPipeTest, Basic);
- FRIEND_TEST(ForkExecAndPipeTest, NonZeroReturnValue);
- FRIEND_TEST(ForkExecAndPipeTest, BadOutputFile);
- FRIEND_TEST(ForkExecAndPipeTest, ExistingOutputFile);
- FRIEND_TEST(ForkExecAndPipeTest, BadExecutable);
- FRIEND_TEST(ForkExecAndPipeTest, StderrCaptured);
- FRIEND_TEST(ForkExecAndPipeTest, NULLParam);
- FRIEND_TEST(ForkExecAndPipeTest, NoParams);
- FRIEND_TEST(ForkExecAndPipeTest, SegFaultHandling);
-
- // Set maximum enqueued crashes in a crash directory.
- static const int kMaxCrashDirectorySize;
-
- // Writes |data| of |size| to |filename|, which must be a new file.
- // If the file already exists or writing fails, return a negative value.
- // Otherwise returns the number of bytes written.
- int WriteNewFile(const base::FilePath &filename, const char *data, int size);
-
- // Return a filename that has only [a-z0-1_] characters by mapping
- // all others into '_'.
- std::string Sanitize(const std::string &name);
-
- // For testing, set the directory always returned by
- // GetCreatedCrashDirectoryByEuid.
- void ForceCrashDirectory(const base::FilePath &forced_directory) {
- forced_crash_directory_ = forced_directory;
- }
-
- // For testing, set the root directory to read etc/os-release.d properties
- // from.
- void ForceOsReleaseDDirectory(const base::FilePath &forced_directory) {
- forced_osreleased_directory_ = forced_directory;
- }
-
- base::FilePath GetCrashDirectoryInfo(mode_t *mode,
- uid_t *directory_owner,
- gid_t *directory_group);
- bool GetUserInfoFromName(const std::string &name,
- uid_t *uid,
- gid_t *gid);
-
- // Determines the crash directory for given euid, and creates the
- // directory if necessary with appropriate permissions. If
- // |out_of_capacity| is not nullptr, it is set to indicate if the call
- // failed due to not having capacity in the crash directory. Returns
- // true whether or not directory needed to be created, false on any
- // failure. If the crash directory is at capacity, returns false.
- bool GetCreatedCrashDirectoryByEuid(uid_t euid,
- base::FilePath *crash_file_path,
- bool *out_of_capacity);
-
- // Format crash name based on components.
- std::string FormatDumpBasename(const std::string &exec_name,
- time_t timestamp,
- pid_t pid);
-
- // Create a file path to a file in |crash_directory| with the given
- // |basename| and |extension|.
- base::FilePath GetCrashPath(const base::FilePath &crash_directory,
- const std::string &basename,
- const std::string &extension);
-
- base::FilePath GetProcessPath(pid_t pid);
- bool GetSymlinkTarget(const base::FilePath &symlink,
- base::FilePath *target);
- bool GetExecutableBaseNameFromPid(pid_t pid,
- std::string *base_name);
-
- // Check given crash directory still has remaining capacity for another
- // crash.
- bool CheckHasCapacity(const base::FilePath &crash_directory);
-
- // Write a log applicable to |exec_name| to |output_file| based on the
- // log configuration file at |config_path|.
- bool GetLogContents(const base::FilePath &config_path,
- const std::string &exec_name,
- const base::FilePath &output_file);
-
- // Add non-standard meta data to the crash metadata file. Call
- // before calling WriteCrashMetaData. Key must not contain "=" or
- // "\n" characters. Value must not contain "\n" characters.
- void AddCrashMetaData(const std::string &key, const std::string &value);
-
- // Add a file to be uploaded to the crash reporter server. The file must
- // persist until the crash report is sent; ideally it should live in the same
- // place as the .meta file, so it can be cleaned up automatically.
- void AddCrashMetaUploadFile(const std::string &key, const std::string &path);
-
- // Add non-standard meta data to the crash metadata file.
- // Data added though this call will be uploaded to the crash reporter server,
- // appearing as a form field.
- void AddCrashMetaUploadData(const std::string &key, const std::string &value);
-
- // Write a file of metadata about crash.
- void WriteCrashMetaData(const base::FilePath &meta_path,
- const std::string &exec_name,
- const std::string &payload_path);
-
- // Returns true if the a crash test is currently running.
- bool IsCrashTestInProgress();
- // Returns true if we should consider ourselves to be running on a
- // developer image.
- bool IsDeveloperImage();
-
- CountCrashFunction count_crash_function_;
- IsFeedbackAllowedFunction is_feedback_allowed_function_;
- std::string extra_metadata_;
- base::FilePath forced_crash_directory_;
- base::FilePath forced_osreleased_directory_;
- base::FilePath log_config_path_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(CrashCollector);
-};
-
-#endif // CRASH_REPORTER_CRASH_COLLECTOR_H_
diff --git a/crash_reporter/crash_collector_test.cc b/crash_reporter/crash_collector_test.cc
deleted file mode 100644
index a386cd1..0000000
--- a/crash_reporter/crash_collector_test.cc
+++ /dev/null
@@ -1,269 +0,0 @@
-/*
- * Copyright (C) 2012 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 "crash_collector_test.h"
-
-#include <unistd.h>
-#include <utility>
-
-#include <base/files/file_util.h>
-#include <base/files/scoped_temp_dir.h>
-#include <base/strings/string_util.h>
-#include <base/strings/stringprintf.h>
-#include <brillo/syslog_logging.h>
-#include <gtest/gtest.h>
-
-#include "crash_collector.h"
-
-using base::FilePath;
-using base::StringPrintf;
-using brillo::FindLog;
-using ::testing::Invoke;
-using ::testing::Return;
-
-namespace {
-
-void CountCrash() {
- ADD_FAILURE();
-}
-
-bool IsMetrics() {
- ADD_FAILURE();
- return false;
-}
-
-} // namespace
-
-class CrashCollectorTest : public ::testing::Test {
- public:
- void SetUp() {
- EXPECT_CALL(collector_, SetUpDBus()).WillRepeatedly(Return());
-
- collector_.Initialize(CountCrash, IsMetrics);
- EXPECT_TRUE(test_dir_.CreateUniqueTempDir());
- brillo::ClearLog();
- }
-
- bool CheckHasCapacity();
-
- protected:
- CrashCollectorMock collector_;
-
- // Temporary directory used for tests.
- base::ScopedTempDir test_dir_;
-};
-
-TEST_F(CrashCollectorTest, Initialize) {
- ASSERT_TRUE(CountCrash == collector_.count_crash_function_);
- ASSERT_TRUE(IsMetrics == collector_.is_feedback_allowed_function_);
-}
-
-TEST_F(CrashCollectorTest, WriteNewFile) {
- FilePath test_file = test_dir_.path().Append("test_new");
- const char kBuffer[] = "buffer";
- unsigned int numBytesWritten = collector_.WriteNewFile(
- test_file,
- kBuffer,
- strlen(kBuffer));
- EXPECT_EQ(strlen(kBuffer), numBytesWritten);
- EXPECT_LT(collector_.WriteNewFile(test_file,
- kBuffer,
- strlen(kBuffer)), 0);
-}
-
-TEST_F(CrashCollectorTest, Sanitize) {
- EXPECT_EQ("chrome", collector_.Sanitize("chrome"));
- EXPECT_EQ("CHROME", collector_.Sanitize("CHROME"));
- EXPECT_EQ("1chrome2", collector_.Sanitize("1chrome2"));
- EXPECT_EQ("chrome__deleted_", collector_.Sanitize("chrome (deleted)"));
- EXPECT_EQ("foo_bar", collector_.Sanitize("foo.bar"));
- EXPECT_EQ("", collector_.Sanitize(""));
- EXPECT_EQ("_", collector_.Sanitize(" "));
-}
-
-TEST_F(CrashCollectorTest, FormatDumpBasename) {
- struct tm tm = {};
- tm.tm_sec = 15;
- tm.tm_min = 50;
- tm.tm_hour = 13;
- tm.tm_mday = 23;
- tm.tm_mon = 4;
- tm.tm_year = 110;
- tm.tm_isdst = -1;
- std::string basename =
- collector_.FormatDumpBasename("foo", mktime(&tm), 100);
- ASSERT_EQ("foo.20100523.135015.100", basename);
-}
-
-TEST_F(CrashCollectorTest, GetCrashPath) {
- EXPECT_EQ("/var/spool/crash/myprog.20100101.1200.1234.core",
- collector_.GetCrashPath(FilePath("/var/spool/crash"),
- "myprog.20100101.1200.1234",
- "core").value());
- EXPECT_EQ("/home/chronos/user/crash/chrome.20100101.1200.1234.dmp",
- collector_.GetCrashPath(FilePath("/home/chronos/user/crash"),
- "chrome.20100101.1200.1234",
- "dmp").value());
-}
-
-
-bool CrashCollectorTest::CheckHasCapacity() {
- const char* kFullMessage =
- StringPrintf("Crash directory %s already full",
- test_dir_.path().value().c_str()).c_str();
- bool has_capacity = collector_.CheckHasCapacity(test_dir_.path());
- bool has_message = FindLog(kFullMessage);
- EXPECT_EQ(has_message, !has_capacity);
- return has_capacity;
-}
-
-TEST_F(CrashCollectorTest, CheckHasCapacityUsual) {
- // Test kMaxCrashDirectorySize - 1 non-meta files can be added.
- for (int i = 0; i < CrashCollector::kMaxCrashDirectorySize - 1; ++i) {
- base::WriteFile(test_dir_.path().Append(StringPrintf("file%d.core", i)),
- "", 0);
- EXPECT_TRUE(CheckHasCapacity());
- }
-
- // Test an additional kMaxCrashDirectorySize - 1 meta files fit.
- for (int i = 0; i < CrashCollector::kMaxCrashDirectorySize - 1; ++i) {
- base::WriteFile(test_dir_.path().Append(StringPrintf("file%d.meta", i)),
- "", 0);
- EXPECT_TRUE(CheckHasCapacity());
- }
-
- // Test an additional kMaxCrashDirectorySize meta files don't fit.
- for (int i = 0; i < CrashCollector::kMaxCrashDirectorySize; ++i) {
- base::WriteFile(test_dir_.path().Append(StringPrintf("overage%d.meta", i)),
- "", 0);
- EXPECT_FALSE(CheckHasCapacity());
- }
-}
-
-TEST_F(CrashCollectorTest, CheckHasCapacityCorrectBasename) {
- // Test kMaxCrashDirectorySize - 1 files can be added.
- for (int i = 0; i < CrashCollector::kMaxCrashDirectorySize - 1; ++i) {
- base::WriteFile(test_dir_.path().Append(StringPrintf("file.%d.core", i)),
- "", 0);
- EXPECT_TRUE(CheckHasCapacity());
- }
- base::WriteFile(test_dir_.path().Append("file.last.core"), "", 0);
- EXPECT_FALSE(CheckHasCapacity());
-}
-
-TEST_F(CrashCollectorTest, CheckHasCapacityStrangeNames) {
- // Test many files with different extensions and same base fit.
- for (int i = 0; i < 5 * CrashCollector::kMaxCrashDirectorySize; ++i) {
- base::WriteFile(test_dir_.path().Append(StringPrintf("a.%d", i)), "", 0);
- EXPECT_TRUE(CheckHasCapacity());
- }
- // Test dot files are treated as individual files.
- for (int i = 0; i < CrashCollector::kMaxCrashDirectorySize - 2; ++i) {
- base::WriteFile(test_dir_.path().Append(StringPrintf(".file%d", i)), "", 0);
- EXPECT_TRUE(CheckHasCapacity());
- }
- base::WriteFile(test_dir_.path().Append("normal.meta"), "", 0);
- EXPECT_FALSE(CheckHasCapacity());
-}
-
-TEST_F(CrashCollectorTest, MetaData) {
- const char kMetaFileBasename[] = "generated.meta";
- FilePath meta_file = test_dir_.path().Append(kMetaFileBasename);
- FilePath payload_file = test_dir_.path().Append("payload-file");
- FilePath osreleased_directory =
- test_dir_.path().Append("etc").Append("os-release.d");
- ASSERT_TRUE(base::CreateDirectory(osreleased_directory));
- collector_.ForceOsReleaseDDirectory(test_dir_.path());
-
- std::string contents;
- const char kPayload[] = "foo";
- ASSERT_TRUE(base::WriteFile(payload_file, kPayload, strlen(kPayload)));
- const char kBdkVersion[] = "1";
- ASSERT_TRUE(base::WriteFile(osreleased_directory.Append("bdk_version"),
- kBdkVersion,
- strlen(kBdkVersion)));
- const char kProductId[] = "baz";
- ASSERT_TRUE(base::WriteFile(osreleased_directory.Append("product_id"),
- kProductId,
- strlen(kProductId)));
- const char kProductVersion[] = "1.2.3.4";
- ASSERT_TRUE(base::WriteFile(osreleased_directory.Append("product_version"),
- kProductVersion,
- strlen(kProductVersion)));
- collector_.AddCrashMetaData("foo", "bar");
- collector_.WriteCrashMetaData(meta_file, "kernel", payload_file.value());
- EXPECT_TRUE(base::ReadFileToString(meta_file, &contents));
- const std::string kExpectedMeta =
- StringPrintf("foo=bar\n"
- "exec_name=kernel\n"
- "payload=%s\n"
- "payload_size=3\n"
- "bdk_version=1\n"
- "product_id=baz\n"
- "product_version=1.2.3.4\n"
- "done=1\n",
- test_dir_.path().Append("payload-file").value().c_str());
- EXPECT_EQ(kExpectedMeta, contents);
-
- // Test target of symlink is not overwritten.
- payload_file = test_dir_.path().Append("payload2-file");
- ASSERT_TRUE(base::WriteFile(payload_file, kPayload, strlen(kPayload)));
- FilePath meta_symlink_path = test_dir_.path().Append("symlink.meta");
- ASSERT_EQ(0,
- symlink(kMetaFileBasename,
- meta_symlink_path.value().c_str()));
- ASSERT_TRUE(base::PathExists(meta_symlink_path));
- brillo::ClearLog();
- collector_.WriteCrashMetaData(meta_symlink_path,
- "kernel",
- payload_file.value());
- // Target metadata contents should have stayed the same.
- contents.clear();
- EXPECT_TRUE(base::ReadFileToString(meta_file, &contents));
- EXPECT_EQ(kExpectedMeta, contents);
- EXPECT_TRUE(FindLog("Unable to write"));
-
- // Test target of dangling symlink is not created.
- base::DeleteFile(meta_file, false);
- ASSERT_FALSE(base::PathExists(meta_file));
- brillo::ClearLog();
- collector_.WriteCrashMetaData(meta_symlink_path, "kernel",
- payload_file.value());
- EXPECT_FALSE(base::PathExists(meta_file));
- EXPECT_TRUE(FindLog("Unable to write"));
-}
-
-TEST_F(CrashCollectorTest, GetLogContents) {
- FilePath config_file = test_dir_.path().Append("crash_config");
- FilePath output_file = test_dir_.path().Append("crash_log");
- const char kConfigContents[] =
- "foobar=echo hello there | \\\n sed -e \"s/there/world/\"";
- ASSERT_TRUE(
- base::WriteFile(config_file, kConfigContents, strlen(kConfigContents)));
- base::DeleteFile(FilePath(output_file), false);
- EXPECT_FALSE(collector_.GetLogContents(config_file,
- "barfoo",
- output_file));
- EXPECT_FALSE(base::PathExists(output_file));
- base::DeleteFile(FilePath(output_file), false);
- EXPECT_TRUE(collector_.GetLogContents(config_file,
- "foobar",
- output_file));
- ASSERT_TRUE(base::PathExists(output_file));
- std::string contents;
- EXPECT_TRUE(base::ReadFileToString(output_file, &contents));
- EXPECT_EQ("hello world\n", contents);
-}
diff --git a/crash_reporter/crash_collector_test.h b/crash_reporter/crash_collector_test.h
deleted file mode 100644
index cfbb97b..0000000
--- a/crash_reporter/crash_collector_test.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-
-#ifndef CRASH_REPORTER_CRASH_COLLECTOR_TEST_H_
-#define CRASH_REPORTER_CRASH_COLLECTOR_TEST_H_
-
-#include "crash_collector.h"
-
-#include <map>
-#include <string>
-
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-
-class CrashCollectorMock : public CrashCollector {
- public:
- MOCK_METHOD0(SetUpDBus, void());
- MOCK_METHOD1(GetActiveUserSessions,
- bool(std::map<std::string, std::string> *sessions));
-};
-
-#endif // CRASH_REPORTER_CRASH_COLLECTOR_TEST_H_
diff --git a/crash_reporter/crash_reporter.cc b/crash_reporter/crash_reporter.cc
deleted file mode 100644
index 16e70d8..0000000
--- a/crash_reporter/crash_reporter.cc
+++ /dev/null
@@ -1,331 +0,0 @@
-/*
- * Copyright (C) 2012 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 <fcntl.h> // for open
-
-#include <string>
-#include <vector>
-
-#include <base/files/file_util.h>
-#include <base/guid.h>
-#include <base/logging.h>
-#include <base/strings/string_split.h>
-#include <base/strings/string_util.h>
-#include <base/strings/stringprintf.h>
-#include <binder/IServiceManager.h>
-#include <brillo/flag_helper.h>
-#include <brillo/syslog_logging.h>
-#include <metrics/metrics_collector_service_client.h>
-#include <metrics/metrics_library.h>
-#include <utils/String16.h>
-
-
-#include "kernel_collector.h"
-#include "kernel_warning_collector.h"
-#include "unclean_shutdown_collector.h"
-#include "user_collector.h"
-
-#if !defined(__ANDROID__)
-#include "udev_collector.h"
-#endif
-
-static const char kCrashCounterHistogram[] = "Logging.CrashCounter";
-static const char kKernelCrashDetected[] =
- "/data/misc/crash_reporter/run/kernel-crash-detected";
-static const char kUncleanShutdownDetected[] =
- "/var/run/unclean-shutdown-detected";
-static const char kGUIDFileName[] = "/data/misc/crash_reporter/guid";
-
-// Enumeration of kinds of crashes to be used in the CrashCounter histogram.
-enum CrashKinds {
- kCrashKindUncleanShutdown = 1,
- kCrashKindUser = 2,
- kCrashKindKernel = 3,
- kCrashKindUdev = 4,
- kCrashKindKernelWarning = 5,
- kCrashKindMax
-};
-
-static MetricsLibrary s_metrics_lib;
-
-using android::brillo::metrics::IMetricsCollectorService;
-using base::FilePath;
-using base::StringPrintf;
-
-static bool IsFeedbackAllowed() {
- return s_metrics_lib.AreMetricsEnabled();
-}
-
-static bool TouchFile(const FilePath &file_path) {
- return base::WriteFile(file_path, "", 0) == 0;
-}
-
-static void SendCrashMetrics(CrashKinds type, const char* name) {
- // TODO(kmixter): We can remove this histogram as part of
- // crosbug.com/11163.
- s_metrics_lib.SendEnumToUMA(kCrashCounterHistogram, type, kCrashKindMax);
- s_metrics_lib.SendCrashToUMA(name);
-}
-
-static void CountKernelCrash() {
- SendCrashMetrics(kCrashKindKernel, "kernel");
-}
-
-static void CountUdevCrash() {
- SendCrashMetrics(kCrashKindUdev, "udevcrash");
-}
-
-static void CountUncleanShutdown() {
- SendCrashMetrics(kCrashKindUncleanShutdown, "uncleanshutdown");
-}
-
-static void CountUserCrash() {
- SendCrashMetrics(kCrashKindUser, "user");
- // Tell the metrics collector about the user crash, in order to log active
- // use time between crashes.
- MetricsCollectorServiceClient metrics_collector_service;
-
- if (metrics_collector_service.Init())
- metrics_collector_service.notifyUserCrash();
- else
- LOG(ERROR) << "Failed to send user crash notification to metrics_collector";
-}
-
-
-static int Initialize(KernelCollector *kernel_collector,
- UserCollector *user_collector,
- UncleanShutdownCollector *unclean_shutdown_collector,
- const bool unclean_check,
- const bool clean_shutdown) {
- CHECK(!clean_shutdown) << "Incompatible options";
-
- // Try to read the GUID from kGUIDFileName. If the file doesn't exist, is
- // blank, or the read fails, generate a new GUID and write it to the file.
- std::string guid;
- base::FilePath filepath(kGUIDFileName);
- if (!base::ReadFileToString(filepath, &guid) || guid.empty()) {
- guid = base::GenerateGUID();
- // If we can't read or write the file, log an error. However it is not
- // a fatal error, as the crash server will assign a random GUID based
- // on a hash of the IP address if one is not provided in the report.
- if (base::WriteFile(filepath, guid.c_str(), guid.size()) <= 0) {
- LOG(ERROR) << "Could not write guid " << guid << " to file "
- << filepath.value();
- }
- }
-
- bool was_kernel_crash = false;
- bool was_unclean_shutdown = false;
- kernel_collector->Enable();
- if (kernel_collector->is_enabled()) {
- was_kernel_crash = kernel_collector->Collect();
- }
-
- if (unclean_check) {
- was_unclean_shutdown = unclean_shutdown_collector->Collect();
- }
-
- // Touch a file to notify the metrics daemon that a kernel
- // crash has been detected so that it can log the time since
- // the last kernel crash.
- if (IsFeedbackAllowed()) {
- if (was_kernel_crash) {
- TouchFile(FilePath(kKernelCrashDetected));
- } else if (was_unclean_shutdown) {
- // We only count an unclean shutdown if it did not come with
- // an associated kernel crash.
- TouchFile(FilePath(kUncleanShutdownDetected));
- }
- }
-
- // Must enable the unclean shutdown collector *after* collecting.
- unclean_shutdown_collector->Enable();
- user_collector->Enable();
-
- return 0;
-}
-
-static int HandleUserCrash(UserCollector *user_collector,
- const std::string& user, const bool crash_test) {
- // Handle a specific user space crash.
- CHECK(!user.empty()) << "--user= must be set";
-
- // Make it possible to test what happens when we crash while
- // handling a crash.
- if (crash_test) {
- *(volatile char *)0 = 0;
- return 0;
- }
-
- // Accumulate logs to help in diagnosing failures during user collection.
- brillo::LogToString(true);
- // Handle the crash, get the name of the process from procfs.
- bool handled = user_collector->HandleCrash(user, nullptr);
- brillo::LogToString(false);
- if (!handled)
- return 1;
- return 0;
-}
-
-#if !defined(__ANDROID__)
-static int HandleUdevCrash(UdevCollector *udev_collector,
- const std::string& udev_event) {
- // Handle a crash indicated by a udev event.
- CHECK(!udev_event.empty()) << "--udev= must be set";
-
- // Accumulate logs to help in diagnosing failures during user collection.
- brillo::LogToString(true);
- bool handled = udev_collector->HandleCrash(udev_event);
- brillo::LogToString(false);
- if (!handled)
- return 1;
- return 0;
-}
-#endif
-
-static int HandleKernelWarning(KernelWarningCollector
- *kernel_warning_collector) {
- // Accumulate logs to help in diagnosing failures during collection.
- brillo::LogToString(true);
- bool handled = kernel_warning_collector->Collect();
- brillo::LogToString(false);
- if (!handled)
- return 1;
- return 0;
-}
-
-// Interactive/diagnostics mode for generating kernel crash signatures.
-static int GenerateKernelSignature(KernelCollector *kernel_collector,
- const std::string& kernel_signature_file) {
- std::string kcrash_contents;
- std::string signature;
- if (!base::ReadFileToString(FilePath(kernel_signature_file),
- &kcrash_contents)) {
- fprintf(stderr, "Could not read file.\n");
- return 1;
- }
- if (!kernel_collector->ComputeKernelStackSignature(
- kcrash_contents,
- &signature,
- true)) {
- fprintf(stderr, "Signature could not be generated.\n");
- return 1;
- }
- printf("Kernel crash signature is \"%s\".\n", signature.c_str());
- return 0;
-}
-
-// Ensure stdout, stdin, and stderr are open file descriptors. If
-// they are not, any code which writes to stderr/stdout may write out
-// to files opened during execution. In particular, when
-// crash_reporter is run by the kernel coredump pipe handler (via
-// kthread_create/kernel_execve), it will not have file table entries
-// 1 and 2 (stdout and stderr) populated. We populate them here.
-static void OpenStandardFileDescriptors() {
- int new_fd = -1;
- // We open /dev/null to fill in any of the standard [0, 2] file
- // descriptors. We leave these open for the duration of the
- // process. This works because open returns the lowest numbered
- // invalid fd.
- do {
- new_fd = open("/dev/null", 0);
- CHECK_GE(new_fd, 0) << "Unable to open /dev/null";
- } while (new_fd >= 0 && new_fd <= 2);
- close(new_fd);
-}
-
-int main(int argc, char *argv[]) {
- DEFINE_bool(init, false, "Initialize crash logging");
- DEFINE_bool(clean_shutdown, false, "Signal clean shutdown");
- DEFINE_string(generate_kernel_signature, "",
- "Generate signature from given kcrash file");
- DEFINE_bool(crash_test, false, "Crash test");
- DEFINE_string(user, "", "User crash info (pid:signal:exec_name)");
- DEFINE_bool(unclean_check, true, "Check for unclean shutdown");
-
-#if !defined(__ANDROID__)
- DEFINE_string(udev, "", "Udev event description (type:device:subsystem)");
-#endif
-
- DEFINE_bool(kernel_warning, false, "Report collected kernel warning");
- DEFINE_string(pid, "", "PID of crashing process");
- DEFINE_string(uid, "", "UID of crashing process");
- DEFINE_string(exe, "", "Executable name of crashing process");
- DEFINE_bool(core2md_failure, false, "Core2md failure test");
- DEFINE_bool(directory_failure, false, "Spool directory failure test");
- DEFINE_string(filter_in, "",
- "Ignore all crashes but this for testing");
-
- OpenStandardFileDescriptors();
- FilePath my_path = base::MakeAbsoluteFilePath(FilePath(argv[0]));
- s_metrics_lib.Init();
- brillo::FlagHelper::Init(argc, argv, "Chromium OS Crash Reporter");
- brillo::OpenLog(my_path.BaseName().value().c_str(), true);
- brillo::InitLog(brillo::kLogToSyslog);
-
- KernelCollector kernel_collector;
- kernel_collector.Initialize(CountKernelCrash, IsFeedbackAllowed);
- UserCollector user_collector;
- user_collector.Initialize(CountUserCrash,
- my_path.value(),
- IsFeedbackAllowed,
- true, // generate_diagnostics
- FLAGS_core2md_failure,
- FLAGS_directory_failure,
- FLAGS_filter_in);
- UncleanShutdownCollector unclean_shutdown_collector;
- unclean_shutdown_collector.Initialize(CountUncleanShutdown,
- IsFeedbackAllowed);
-
-#if !defined(__ANDROID__)
- UdevCollector udev_collector;
- udev_collector.Initialize(CountUdevCrash, IsFeedbackAllowed);
-#endif
-
- KernelWarningCollector kernel_warning_collector;
- kernel_warning_collector.Initialize(CountUdevCrash, IsFeedbackAllowed);
-
- if (FLAGS_init) {
- return Initialize(&kernel_collector,
- &user_collector,
- &unclean_shutdown_collector,
- FLAGS_unclean_check,
- FLAGS_clean_shutdown);
- }
-
- if (FLAGS_clean_shutdown) {
- unclean_shutdown_collector.Disable();
- user_collector.Disable();
- return 0;
- }
-
- if (!FLAGS_generate_kernel_signature.empty()) {
- return GenerateKernelSignature(&kernel_collector,
- FLAGS_generate_kernel_signature);
- }
-
-#if !defined(__ANDROID__)
- if (!FLAGS_udev.empty()) {
- return HandleUdevCrash(&udev_collector, FLAGS_udev);
- }
-#endif
-
- if (FLAGS_kernel_warning) {
- return HandleKernelWarning(&kernel_warning_collector);
- }
-
- return HandleUserCrash(&user_collector, FLAGS_user, FLAGS_crash_test);
-}
diff --git a/crash_reporter/crash_reporter.rc b/crash_reporter/crash_reporter.rc
deleted file mode 100644
index e6d1ec5..0000000
--- a/crash_reporter/crash_reporter.rc
+++ /dev/null
@@ -1,37 +0,0 @@
-on property:crash_reporter.coredump.enabled=1
- write /proc/sys/kernel/core_pattern \
- "|/system/bin/crash_reporter --user=%P:%s:%u:%g:%e"
-
-on property:crash_reporter.coredump.enabled=0
- write /proc/sys/kernel/core_pattern "core"
-
-on post-fs-data
- # Allow catching multiple unrelated concurrent crashes, but use a finite
- # number to prevent infinitely recursing on crash handling.
- write /proc/sys/kernel/core_pipe_limit 4
-
- # Remove any previous orphaned locks.
- rmdir /data/misc/crash_reporter/lock/crash_sender
-
- # Remove any previous run files.
- rm /data/misc/crash_reporter/run/kernel-crash-detected
- rmdir /data/misc/crash_reporter/run
-
- # Create crash directories.
- # These directories are group-writable by root so that crash_reporter can
- # still access them when it switches users.
- mkdir /data/misc/crash_reporter 0770 root root
- mkdir /data/misc/crash_reporter/crash 0770 root root
- mkdir /data/misc/crash_reporter/lock 0700 root root
- mkdir /data/misc/crash_reporter/log 0700 root root
- mkdir /data/misc/crash_reporter/run 0700 root root
- mkdir /data/misc/crash_reporter/tmp 0770 root root
-
-service crash_reporter /system/bin/crash_reporter --init
- class late_start
- oneshot
-
-service crash_sender /system/bin/periodic_scheduler 3600 14400 crash_sender \
- /system/bin/crash_sender
- class late_start
- group system
diff --git a/crash_reporter/crash_reporter_logs.conf b/crash_reporter/crash_reporter_logs.conf
deleted file mode 100644
index 7db308c..0000000
--- a/crash_reporter/crash_reporter_logs.conf
+++ /dev/null
@@ -1,122 +0,0 @@
-# Copyright (C) 2012 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.
-
-# This file is parsed by chromeos::KeyValueStore. It has the format:
-#
-# <basename>=<shell command>\n
-#
-# Commands may be split across multiple lines using trailing backslashes.
-#
-# When an executable named <basename> crashes, the corresponding command is
-# executed and its standard output and standard error are attached to the crash
-# report.
-#
-# Use caution in modifying this file. Only run common Unix commands here, as
-# these commands will be run when a crash has recently occurred and we should
-# avoid running anything that might cause another crash. Similarly, these
-# commands block notification of the crash to parent processes, so commands
-# should execute quickly.
-
-update_engine=cat $(ls -1tr /var/log/update_engine | tail -5 | \
- sed s.^./var/log/update_engine/.) | tail -c 50000
-
-# The cros_installer output is logged into the update engine log file,
-# so it is handled in the same way as update_engine.
-cros_installer=cat $(ls -1tr /var/log/update_engine | tail -5 | \
- sed s.^./var/log/update_engine/.) | tail -c 50000
-
-# Dump the last 20 lines of the last two files in Chrome's system and user log
-# directories, along with the last 20 messages from the session manager.
-chrome=\
- for f in $(ls -1rt /var/log/chrome/chrome_[0-9]* | tail -2) \
- $(ls -1rt /home/chronos/u-*/log/chrome_[0-9]* 2>/dev/null | tail -2); do \
- echo "===$f (tail)==="; \
- tail -20 $f; \
- echo EOF; \
- echo; \
- done; \
- echo "===session_manager (tail)==="; \
- awk '$3 ~ "^session_manager\[" { print }' /var/log/messages | tail -20; \
- echo EOF
-
-# The following rule is used for generating additional diagnostics when
-# collection of user crashes fails. This output should not be too large
-# as it is stored in memory. The output format specified for 'ps' is the
-# same as with the "u" ("user-oriented") option, except it doesn't show
-# the commands' arguments (i.e. "comm" instead of "command").
-crash_reporter-user-collection=\
- echo "===ps output==="; \
- ps axw -o user,pid,%cpu,%mem,vsz,rss,tname,stat,start_time,bsdtime,comm | \
- tail -c 25000; \
- echo "===meminfo==="; \
- cat /proc/meminfo
-
-# This rule is similar to the crash_reporter-user-collection rule, except it is
-# run for kernel errors reported through udev events.
-crash_reporter-udev-collection-change-card0-drm=\
- for dri in /sys/kernel/debug/dri/*; do \
- echo "===$dri/i915_error_state==="; \
- cat $dri/i915_error_state; \
- done
-
-# When trackpad driver cyapa detects some abnormal behavior, we collect
-# additional logs from kernel messages.
-crash_reporter-udev-collection-change--i2c-cyapa=\
- /usr/sbin/kernel_log_collector.sh cyapa 30
-# When trackpad/touchscreen driver atmel_mxt_ts detects some abnormal behavior,
-# we collect additional logs from kernel messages.
-crash_reporter-udev-collection-change--i2c-atmel_mxt_ts=\
- /usr/sbin/kernel_log_collector.sh atmel 30
-# When touch device noise are detected, we collect relevant logs.
-# (crosbug.com/p/16788)
-crash_reporter-udev-collection---TouchNoise=cat /var/log/touch_noise.log
-# Periodically collect touch event log for debugging (crosbug.com/p/17244)
-crash_reporter-udev-collection---TouchEvent=cat /var/log/touch_event.log
-
-# Collect the last 50 lines of /var/log/messages and /var/log/net.log for
-# intel wifi driver (iwlwifi) for debugging purpose.
-crash_reporter-udev-collection-devcoredump-iwlwifi=\
- echo "===/var/log/messages==="; \
- tail -n 50 /var/log/messages; \
- echo "===/var/log/net.log==="; \
- tail -n 50 /var/log/net.log; \
- echo EOF
-
-# Dump the last 50 lines of the last two powerd log files -- if the job has
-# already restarted, we want to see the end of the previous instance's logs.
-powerd=\
- for f in $(ls -1tr /var/log/power_manager/powerd.[0-9]* | tail -2); do \
- echo "===$(basename $f) (tail)==="; \
- tail -50 $f; \
- echo EOF; \
- done
-# If power_supply_info aborts (due to e.g. a bad battery), its failure message
-# could end up in various places depending on which process was running it.
-# Attach the end of powerd's log since it might've also logged the underlying
-# problem.
-power_supply_info=\
- echo "===powerd.LATEST (tail)==="; \
- tail -50 /var/log/power_manager/powerd.LATEST; \
- echo EOF
-# powerd_setuid_helper gets run by powerd, so its stdout/stderr will be mixed in
-# with powerd's stdout/stderr.
-powerd_setuid_helper=\
- echo "===powerd.OUT (tail)==="; \
- tail -50 /var/log/powerd.out; \
- echo EOF
-
-# The following rules are only for testing purposes.
-crash_log_test=echo hello world
-crash_log_recursion_test=sleep 1 && \
- /usr/local/autotest/tests/crash_log_recursion_test
diff --git a/crash_reporter/crash_reporter_logs_test.cc b/crash_reporter/crash_reporter_logs_test.cc
deleted file mode 100644
index 77f5a7f..0000000
--- a/crash_reporter/crash_reporter_logs_test.cc
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2015 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 <string>
-
-#include <base/files/file_path.h>
-#include <brillo/key_value_store.h>
-#include <gtest/gtest.h>
-
-namespace {
-
-// Name of the checked-in configuration file containing log-collection commands.
-const char kConfigFile[] = "/system/etc/crash_reporter_logs.conf";
-
-// Signature name for crash_reporter user collection.
-// kConfigFile is expected to contain this entry.
-const char kUserCollectorSignature[] = "crash_reporter-user-collection";
-
-} // namespace
-
-// Tests that the config file is parsable and that Chrome is listed.
-TEST(CrashReporterLogsTest, ReadConfig) {
- brillo::KeyValueStore store;
- ASSERT_TRUE(store.Load(base::FilePath(kConfigFile)));
- std::string command;
- EXPECT_TRUE(store.GetString(kUserCollectorSignature, &command));
- EXPECT_FALSE(command.empty());
-}
diff --git a/crash_reporter/crash_sender b/crash_reporter/crash_sender
deleted file mode 100755
index a430ab5..0000000
--- a/crash_reporter/crash_sender
+++ /dev/null
@@ -1,719 +0,0 @@
-#!/system/bin/sh
-
-# Copyright (C) 2010 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.
-
-set -e
-
-# Default product ID in crash report (used if GOOGLE_CRASH_* is undefined).
-BRILLO_PRODUCT=Brillo
-
-# Base directory that contains any crash reporter state files.
-CRASH_STATE_DIR="/data/misc/crash_reporter"
-
-# File containing crash_reporter's anonymized guid.
-GUID_FILE="${CRASH_STATE_DIR}/guid"
-
-# Crash sender lock in case the sender is already running.
-CRASH_SENDER_LOCK="${CRASH_STATE_DIR}/lock/crash_sender"
-
-# Path to file that indicates a crash test is currently running.
-CRASH_TEST_IN_PROGRESS_FILE="${CRASH_STATE_DIR}/tmp/crash-test-in-progress"
-
-# Set this to 1 in the environment to allow uploading crash reports
-# for unofficial versions.
-FORCE_OFFICIAL=${FORCE_OFFICIAL:-0}
-
-# Path to hardware class description.
-HWCLASS_PATH="/sys/devices/platform/chromeos_acpi/HWID"
-
-# Path to file that indicates this is a developer image.
-LEAVE_CORE_FILE="${CRASH_STATE_DIR}/.leave_core"
-
-# Path to list_proxies.
-LIST_PROXIES="list_proxies"
-
-# Maximum crashes to send per day.
-MAX_CRASH_RATE=${MAX_CRASH_RATE:-32}
-
-# File whose existence mocks crash sending. If empty we pretend the
-# crash sending was successful, otherwise unsuccessful.
-MOCK_CRASH_SENDING="${CRASH_STATE_DIR}/tmp/mock-crash-sending"
-
-# Set this to 1 in the environment to pretend to have booted in developer
-# mode. This is used by autotests.
-MOCK_DEVELOPER_MODE=${MOCK_DEVELOPER_MODE:-0}
-
-# Ignore PAUSE_CRASH_SENDING file if set.
-OVERRIDE_PAUSE_SENDING=${OVERRIDE_PAUSE_SENDING:-0}
-
-# File whose existence causes crash sending to be delayed (for testing).
-# Must be stateful to enable testing kernel crashes.
-PAUSE_CRASH_SENDING="${CRASH_STATE_DIR}/lock/crash_sender_paused"
-
-# Path to a directory of restricted certificates which includes
-# a certificate for the crash server.
-RESTRICTED_CERTIFICATES_PATH="/system/etc/security/cacerts"
-RESTRICTED_CERTIFICATES_PATH_GOOGLE="/system/etc/security/cacerts_google"
-
-# File whose existence implies we're running and not to start again.
-RUN_FILE="${CRASH_STATE_DIR}/run/crash_sender.pid"
-
-# Maximum time to sleep between sends.
-SECONDS_SEND_SPREAD=${SECONDS_SEND_SPREAD:-600}
-
-# Set this to 1 to allow uploading of device coredumps.
-DEVCOREDUMP_UPLOAD_FLAG_FILE="${CRASH_STATE_DIR}/device_coredump_upload_allowed"
-
-# The weave configuration file.
-WEAVE_CONF_FILE="/etc/weaved/weaved.conf"
-
-# The os-release.d folder.
-OSRELEASED_FOLDER="/etc/os-release.d"
-
-# The syslog tag for all logging we emit.
-TAG="$(basename $0)[$$]"
-
-# Directory to store timestamp files indicating the uploads in the past 24
-# hours.
-TIMESTAMPS_DIR="${CRASH_STATE_DIR}/crash_sender"
-
-# Temp directory for this process.
-TMP_DIR=""
-
-# Crash report log file.
-CRASH_LOG="${CRASH_STATE_DIR}/log/uploads.log"
-
-lecho() {
- log -t "${TAG}" "$@"
-}
-
-lwarn() {
- lecho -psyslog.warn "$@"
-}
-
-# Returns true if mock is enabled.
-is_mock() {
- [ -f "${MOCK_CRASH_SENDING}" ] && return 0
- return 1
-}
-
-is_mock_successful() {
- local mock_in=$(cat "${MOCK_CRASH_SENDING}")
- [ "${mock_in}" = "" ] && return 0 # empty file means success
- return 1
-}
-
-cleanup() {
- if [ -n "${TMP_DIR}" ]; then
- rm -rf "${TMP_DIR}"
- fi
- rm -f "${RUN_FILE}"
- if [ -n "${CRASH_SENDER_LOCK}" ]; then
- rm -rf "${CRASH_SENDER_LOCK}"
- fi
- crash_done
-}
-
-crash_done() {
- if is_mock; then
- # For testing purposes, emit a message to log so that we
- # know when the test has received all the messages from this run.
- lecho "crash_sender done."
- fi
-}
-
-is_official_image() {
- [ ${FORCE_OFFICIAL} -ne 0 ] && return 0
- if [ "$(getprop ro.secure)" = "1" ]; then
- return 0
- else
- return 1
- fi
-}
-
-# Returns 0 if the a crash test is currently running. NOTE: Mirrors
-# crash_collector.cc:CrashCollector::IsCrashTestInProgress().
-is_crash_test_in_progress() {
- [ -f "${CRASH_TEST_IN_PROGRESS_FILE}" ] && return 0
- return 1
-}
-
-# Returns 0 if we should consider ourselves to be running on a developer
-# image. NOTE: Mirrors crash_collector.cc:CrashCollector::IsDeveloperImage().
-is_developer_image() {
- # If we're testing crash reporter itself, we don't want to special-case
- # for developer images.
- is_crash_test_in_progress && return 1
- [ -f "${LEAVE_CORE_FILE}" ] && return 0
- return 1
-}
-
-# Returns 0 if we should consider ourselves to be running on a test image.
-is_test_image() {
- # If we're testing crash reporter itself, we don't want to special-case
- # for test images.
- is_crash_test_in_progress && return 1
- case $(get_channel) in
- test*) return 0;;
- esac
- return 1
-}
-
-# Returns 0 if the machine booted up in developer mode.
-is_developer_mode() {
- [ ${MOCK_DEVELOPER_MODE} -ne 0 ] && return 0
- # If we're testing crash reporter itself, we don't want to special-case
- # for developer mode.
- is_crash_test_in_progress && return 1
- if [ "$(getprop ro.debuggable)" = "1" ]; then
- return 0
- else
- return 1
- fi
-}
-
-# Returns the path of the certificates directory to be used when sending
-# reports to the crash server.
-# If crash_reporter.full_certs=1, return the full certificates path.
-# Otherwise return the Google-specific certificates path.
-get_certificates_path() {
- if [ "$(getprop crash_reporter.full_certs)" = "1" ]; then
- echo "${RESTRICTED_CERTIFICATES_PATH}"
- else
- echo "${RESTRICTED_CERTIFICATES_PATH_GOOGLE}"
- fi
-}
-
-# Return 0 if the uploading of device coredumps is allowed.
-is_device_coredump_upload_allowed() {
- [ -f "${DEVCOREDUMP_UPLOAD_FLAG_FILE}" ] && return 0
- return 1
-}
-
-# Generate a uniform random number in 0..max-1.
-# POSIX arithmetic expansion requires support of at least signed long integers.
-# On 32-bit systems, that may mean 32-bit signed integers, in which case the
-# 32-bit random number read from /dev/urandom may be interpreted as negative
-# when used inside an arithmetic expansion (since the high bit might be set).
-# mksh at least is known to behave this way.
-# For this case, simply take the absolute value, which will still give a
-# roughly uniform random distribution for the modulo (as we are merely ignoring
-# the high/sign bit).
-# See corresponding Arithmetic Expansion and Arithmetic Expression sections:
-# POSIX: http://pubs.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_06_04
-# mksh: http://linux.die.net/man/1/mksh
-generate_uniform_random() {
- local max=$1
- local random="$(od -An -N4 -tu /dev/urandom)"
- echo $(((random < 0 ? -random : random) % max))
-}
-
-# Check if sending a crash now does not exceed the maximum 24hr rate and
-# commit to doing so, if not.
-check_rate() {
- mkdir -p ${TIMESTAMPS_DIR}
- # Only consider minidumps written in the past 24 hours by removing all older.
- find "${TIMESTAMPS_DIR}" -mindepth 1 -mtime +1 \
- -exec rm -- '{}' ';'
- local sends_in_24hrs=$(echo "${TIMESTAMPS_DIR}"/* | wc -w)
- lecho "Current send rate: ${sends_in_24hrs}sends/24hrs"
- if [ ${sends_in_24hrs} -ge ${MAX_CRASH_RATE} ]; then
- lecho "Cannot send more crashes:"
- lecho " current ${sends_in_24hrs}send/24hrs >= " \
- "max ${MAX_CRASH_RATE}send/24hrs"
- return 1
- fi
- mktemp "${TIMESTAMPS_DIR}"/XXXXXX > /dev/null
- return 0
-}
-
-# Gets the base part of a crash report file, such as name.01234.5678.9012 from
-# name.01234.5678.9012.meta or name.01234.5678.9012.log.tar.xz. We make sure
-# "name" is sanitized in CrashCollector::Sanitize to not include any periods.
-get_base() {
- echo "$1" | cut -d. -f-4
-}
-
-get_extension() {
- local extension="${1##*.}"
- local filename="${1%.*}"
- # For gzipped file, we ignore .gz and get the real extension
- if [ "${extension}" = "gz" ]; then
- echo "${filename##*.}"
- else
- echo "${extension}"
- fi
-}
-
-# Return which kind of report the given metadata file relates to
-get_kind() {
- local payload="$(get_key_value "$1" "payload")"
- if [ ! -r "${payload}" ]; then
- lecho "Missing payload: ${payload}"
- echo "undefined"
- return
- fi
- local kind="$(get_extension "${payload}")"
- if [ "${kind}" = "dmp" ]; then
- echo "minidump"
- return
- fi
- echo "${kind}"
-}
-
-get_key_value() {
- local file="$1" key="$2" value
-
- if [ -f "${file}/${key}" ]; then
- # Get the value from a folder where each key is its own file. The key
- # file's entire contents is the value.
- value=$(cat "${file}/${key}")
- elif [ -f "${file}" ]; then
- # Get the value from a file that has multiple key=value combinations.
- # Return the first entry. There shouldn't be more than one anyways.
- # Substr at length($1) + 2 skips past the key and following = sign (awk
- # uses 1-based indexes), but preserves embedded = characters.
- value=$(sed -n "/^${key}[[:space:]]*=/{s:^[^=]*=::p;q}" "${file}")
- fi
-
- echo "${value:-undefined}"
-}
-
-get_keys() {
- local file="$1" regex="$2"
-
- cut -d '=' -f1 "${file}" | grep --color=never "${regex}"
-}
-
-# Return the channel name (sans "-channel" suffix).
-get_channel() {
- getprop ro.product.channel | sed 's:-channel$::'
-}
-
-# Return the hardware class or "undefined".
-get_hardware_class() {
- if [ -r "${HWCLASS_PATH}" ]; then
- cat "${HWCLASS_PATH}"
- else
- echo "undefined"
- fi
-}
-
-# Return the log string filtered with only JSON-safe white-listed characters.
-filter_log_string() {
- echo "$1" | tr -cd '[:alnum:]_.\-:;'
-}
-
-send_crash() {
- local meta_path="$1"
- local report_payload="$(get_key_value "${meta_path}" "payload")"
- local kind="$(get_kind "${meta_path}")"
- local exec_name="$(get_key_value "${meta_path}" "exec_name")"
- local url="$(get_key_value "${OSRELEASED_FOLDER}" "crash_server")"
- local bdk_version="$(get_key_value "${meta_path}" "bdk_version")"
- local hwclass="$(get_hardware_class)"
- local write_payload_size="$(get_key_value "${meta_path}" "payload_size")"
- local log="$(get_key_value "${meta_path}" "log")"
- local sig="$(get_key_value "${meta_path}" "sig")"
- local send_payload_size="$(stat -c "%s" "${report_payload}" 2>/dev/null)"
- local product="$(get_key_value "${meta_path}" "product_id")"
- local version="$(get_key_value "${meta_path}" "product_version")"
- local upload_prefix="$(get_key_value "${meta_path}" "upload_prefix")"
- local guid
- local model_manifest_id="$(get_key_value "${WEAVE_CONF_FILE}" "model_id")"
-
- # If crash_reporter.server is not set return with an error.
- if [ -z "${url}" ]; then
- lecho "Configuration error: crash_reporter.server not set."
- return 1
- fi
-
- set -- \
- -F "write_payload_size=${write_payload_size}" \
- -F "send_payload_size=${send_payload_size}"
- if [ "${sig}" != "undefined" ]; then
- set -- "$@" \
- -F "sig=${sig}" \
- -F "sig2=${sig}"
- fi
- if [ -r "${report_payload}" ]; then
- set -- "$@" \
- -F "upload_file_${kind}=@${report_payload}"
- fi
- if [ "${log}" != "undefined" -a -r "${log}" ]; then
- set -- "$@" \
- -F "log=@${log}"
- fi
-
- if [ "${upload_prefix}" = "undefined" ]; then
- upload_prefix=""
- fi
-
- # Grab any variable that begins with upload_.
- local v
- for k in $(get_keys "${meta_path}" "^upload_"); do
- v="$(get_key_value "${meta_path}" "${k}")"
- case ${k} in
- # Product & version are handled separately.
- upload_var_prod) ;;
- upload_var_ver) ;;
- upload_var_*)
- set -- "$@" -F "${upload_prefix}${k#upload_var_}=${v}"
- ;;
- upload_file_*)
- if [ -r "${v}" ]; then
- set -- "$@" -F "${upload_prefix}${k#upload_file_}=@${v}"
- fi
- ;;
- esac
- done
-
- # If ID or VERSION_ID is undefined, we use the default product name
- # and bdk_version from /etc/os-release.d.
- if [ "${product}" = "undefined" ]; then
- product="${BRILLO_PRODUCT}"
- fi
- if [ "${version}" = "undefined" ]; then
- version="${bdk_version}"
- fi
-
- local image_type
- if is_test_image; then
- image_type="test"
- elif is_developer_image; then
- image_type="dev"
- elif [ ${FORCE_OFFICIAL} -ne 0 ]; then
- image_type="force-official"
- elif is_mock && ! is_mock_successful; then
- image_type="mock-fail"
- fi
-
- local boot_mode
- if is_developer_mode; then
- boot_mode="dev"
- fi
-
- # Need to strip dashes ourselves as Chrome preserves it in the file
- # nowadays. This is also what the Chrome breakpad client does.
- guid=$(tr -d '-' < "${GUID_FILE}")
-
- local error_type="$(get_key_value "${meta_path}" "error_type")"
- [ "${error_type}" = "undefined" ] && error_type=
-
- lecho "Sending crash:"
- if [ "${product}" != "${BRILLO_PRODUCT}" ]; then
- lecho " Sending crash report on behalf of ${product}"
- fi
- lecho " Metadata: ${meta_path} (${kind})"
- lecho " Payload: ${report_payload}"
- lecho " Version: ${version}"
- lecho " Bdk Version: ${bdk_version}"
- [ -n "${image_type}" ] && lecho " Image type: ${image_type}"
- [ -n "${boot_mode}" ] && lecho " Boot mode: ${boot_mode}"
- if is_mock; then
- lecho " Product: ${product}"
- lecho " URL: ${url}"
- lecho " HWClass: ${hwclass}"
- lecho " write_payload_size: ${write_payload_size}"
- lecho " send_payload_size: ${send_payload_size}"
- if [ "${log}" != "undefined" ]; then
- lecho " log: @${log}"
- fi
- if [ "${sig}" != "undefined" ]; then
- lecho " sig: ${sig}"
- fi
- fi
- lecho " Exec name: ${exec_name}"
- [ -n "${error_type}" ] && lecho " Error type: ${error_type}"
- if is_mock; then
- if ! is_mock_successful; then
- lecho "Mocking unsuccessful send"
- return 1
- fi
- lecho "Mocking successful send"
- return 0
- fi
-
- # Read in the first proxy, if any, for a given URL. NOTE: The
- # double-quotes are necessary due to a bug in dash with the "local"
- # builtin command and values that have spaces in them (see
- # "https://bugs.launchpad.net/ubuntu/+source/dash/+bug/139097").
- if [ -f "${LIST_PROXIES}" ]; then
- local proxy ret
- proxy=$("${LIST_PROXIES}" --quiet "${url}")
- ret=$?
- if [ ${ret} -ne 0 ]; then
- proxy=''
- lwarn "Listing proxies failed with exit code ${ret}"
- else
- proxy=$(echo "${proxy}" | head -1)
- fi
- fi
- # if a direct connection should be used, unset the proxy variable.
- [ "${proxy}" = "direct://" ] && proxy=
- local report_id="${TMP_DIR}/report_id"
- local curl_stderr="${TMP_DIR}/curl_stderr"
-
- set +e
- curl "${url}" -f -v ${proxy:+--proxy "$proxy"} \
- --capath "$(get_certificates_path)" --ciphers HIGH \
- -F "prod=${product}" \
- -F "ver=${version}" \
- -F "bdk_version=${bdk_version}" \
- -F "hwclass=${hwclass}" \
- -F "exec_name=${exec_name}" \
- -F "model_manifest_id=${model_manifest_id}" \
- ${image_type:+-F "image_type=${image_type}"} \
- ${boot_mode:+-F "boot_mode=${boot_mode}"} \
- ${error_type:+-F "error_type=${error_type}"} \
- -F "guid=${guid}" \
- -o "${report_id}" \
- "$@" \
- 2>"${curl_stderr}"
- curl_result=$?
- set -e
-
- if [ ${curl_result} -eq 0 ]; then
- local id="$(cat "${report_id}")"
- local timestamp="$(date +%s)"
- local filter_prod="$(filter_log_string "${product}")"
- local filter_exec="$(filter_log_string "${exec_name}")"
- if [ "${filter_prod}" != "${product}" ]; then
- lwarn "Product name filtered to: ${filter_prod}."
- fi
- if [ "${filter_exec}" != "${exec_name}" ]; then
- lwarn "Exec name filtered to: ${filter_exec}."
- fi
- printf "{'time':%s,'id':'%s','product':'%s','exec_name':'%s'}\n" \
- "${timestamp}" "${id}" "${filter_prod}" "${filter_exec}" >> "${CRASH_LOG}"
- lecho "Crash report receipt ID ${id}"
- else
- lecho "Crash sending failed with exit code ${curl_result}: " \
- "$(cat "${curl_stderr}")"
- fi
-
- rm -f "${report_id}"
-
- return ${curl_result}
-}
-
-# *.meta files always end with done=1 so we can tell if they are complete.
-is_complete_metadata() {
- grep -q "done=1" "$1"
-}
-
-# Remove the given report path.
-remove_report() {
- local base="${1%.*}"
- rm -f -- "${base}".*
-}
-
-# Send all crashes from the given directory. This applies even when we're on a
-# 3G connection (see crosbug.com/3304 for discussion).
-send_crashes() {
- local dir="$1"
- lecho "Sending crashes for ${dir}"
-
- if [ ! -d "${dir}" ]; then
- return
- fi
-
- # Consider any old files which still have no corresponding meta file
- # as orphaned, and remove them.
- for old_file in $(find "${dir}" -mindepth 1 \
- -mtime +1 -type f); do
- if [ ! -e "$(get_base "${old_file}").meta" ]; then
- lecho "Removing old orphaned file: ${old_file}."
- rm -f -- "${old_file}"
- fi
- done
-
- # Look through all metadata (*.meta) files, oldest first. That way, the rate
- # limit does not stall old crashes if there's a high amount of new crashes
- # coming in.
- # For each crash report, first evaluate conditions that might lead to its
- # removal to honor user choice and to free disk space as soon as possible,
- # then decide whether it should be sent right now or kept for later sending.
- for meta_path in $(ls -1tr "${dir}"/*.meta 2>/dev/null); do
- lecho "Considering metadata ${meta_path}."
-
- local kind=$(get_kind "${meta_path}")
- if [ "${kind}" != "minidump" ] && \
- [ "${kind}" != "kcrash" ] && \
- [ "${kind}" != "log" ] &&
- [ "${kind}" != "devcore" ]; then
- lecho "Unknown report kind ${kind}. Removing report."
- remove_report "${meta_path}"
- continue
- fi
-
- if ! is_complete_metadata "${meta_path}"; then
- # This report is incomplete, so if it's old, just remove it.
- local old_meta=$(find "${dir}" -mindepth 1 -name \
- $(basename "${meta_path}") -mtime +1 -type f)
- if [ -n "${old_meta}" ]; then
- lecho "Removing old incomplete metadata."
- remove_report "${meta_path}"
- else
- lecho "Ignoring recent incomplete metadata."
- fi
- continue
- fi
-
- # Ignore device coredump if device coredump uploading is not allowed.
- if [ "${kind}" = "devcore" ] && ! is_device_coredump_upload_allowed; then
- lecho "Ignoring device coredump. Device coredump upload not allowed."
- continue
- fi
-
- if ! is_mock && ! is_official_image; then
- lecho "Not an official OS version. Removing crash."
- remove_report "${meta_path}"
- continue
- fi
-
- # Remove existing crashes in case user consent has not (yet) been given or
- # has been revoked. This must come after the guest mode check because
- # metrics_client always returns "not consented" in guest mode.
- if ! metrics_client -c; then
- lecho "Crash reporting is disabled. Removing crash."
- remove_report "${meta_path}"
- continue
- fi
-
- # Skip report if the upload rate is exceeded. (Don't exit right now because
- # subsequent reports may be candidates for deletion.)
- if ! check_rate; then
- lecho "Sending ${meta_path} would exceed rate. Leaving for later."
- continue
- fi
-
- # The .meta file should be written *after* all to-be-uploaded files that it
- # references. Nevertheless, as a safeguard, a hold-off time of thirty
- # seconds after writing the .meta file is ensured. Also, sending of crash
- # reports is spread out randomly by up to SECONDS_SEND_SPREAD. Thus, for
- # the sleep call the greater of the two delays is used.
- local now=$(date +%s)
- local holdoff_time=$(($(stat -c "%Y" "${meta_path}") + 30 - ${now}))
- local spread_time=$(generate_uniform_random "${SECONDS_SEND_SPREAD}")
- local sleep_time
- if [ ${spread_time} -gt ${holdoff_time} ]; then
- sleep_time="${spread_time}"
- else
- sleep_time="${holdoff_time}"
- fi
- lecho "Scheduled to send in ${sleep_time}s."
- if ! is_mock; then
- if ! sleep "${sleep_time}"; then
- lecho "Sleep failed"
- return 1
- fi
- fi
-
- # Try to upload.
- if ! send_crash "${meta_path}"; then
- lecho "Problem sending ${meta_path}, not removing."
- continue
- fi
-
- # Send was successful, now remove.
- lecho "Successfully sent crash ${meta_path} and removing."
- remove_report "${meta_path}"
- done
-}
-
-usage() {
- cat <<EOF
-Usage: crash_sender [options]
-
-Options:
- -e <var>=<val> Set env |var| to |val| (only some vars)
-EOF
- exit ${1:-1}
-}
-
-parseargs() {
- # Parse the command line arguments.
- while [ $# -gt 0 ]; do
- case $1 in
- -e)
- shift
- case $1 in
- FORCE_OFFICIAL=*|\
- MAX_CRASH_RATE=*|\
- MOCK_DEVELOPER_MODE=*|\
- OVERRIDE_PAUSE_SENDING=*|\
- SECONDS_SEND_SPREAD=*)
- export "$1"
- ;;
- *)
- lecho "Unknown var passed to -e: $1"
- exit 1
- ;;
- esac
- ;;
- -h)
- usage 0
- ;;
- *)
- lecho "Unknown options: $*"
- exit 1
- ;;
- esac
- shift
- done
-}
-
-main() {
- parseargs "$@"
-
- if [ -e "${PAUSE_CRASH_SENDING}" ] && \
- [ ${OVERRIDE_PAUSE_SENDING} -eq 0 ]; then
- lecho "Exiting early due to ${PAUSE_CRASH_SENDING}."
- exit 1
- fi
-
- if is_test_image; then
- lecho "Exiting early due to test image."
- exit 1
- fi
-
- # We don't perform checks on this because we have a master lock with the
- # CRASH_SENDER_LOCK file. This pid file is for the system to keep track
- # (like with autotests) that we're still running.
- echo $$ > "${RUN_FILE}"
-
- for dependency in "$(get_certificates_path)"; do
- if [ ! -x "${dependency}" ]; then
- lecho "Fatal: Crash sending disabled: ${dependency} not found."
- exit 1
- fi
- done
-
- TMP_DIR="$(mktemp -d "${CRASH_STATE_DIR}/tmp/crash_sender.XXXXXX")"
-
- # Send system-wide crashes
- send_crashes "${CRASH_STATE_DIR}/crash"
-}
-
-trap cleanup EXIT INT TERM
-
-#TODO(http://b/23937249): Change the locking logic back to using flock.
-if ! mkdir "${CRASH_SENDER_LOCK}" 2>/dev/null; then
- lecho "Already running; quitting."
- crash_done
- exit 1
-fi
-main "$@"
diff --git a/crash_reporter/dbus_bindings/org.chromium.LibCrosService.xml b/crash_reporter/dbus_bindings/org.chromium.LibCrosService.xml
deleted file mode 100644
index 64b8b84..0000000
--- a/crash_reporter/dbus_bindings/org.chromium.LibCrosService.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-
-<node name="/org/chromium/LibCrosService"
- xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0">
- <interface name="org.chromium.LibCrosServiceInterface">
- <method name="ResolveNetworkProxy">
- <arg name="source_url" type="s" direction="in"/>
- <arg name="signal_interface" type="s" direction="in"/>
- <arg name="signal_name" type="s" direction="in"/>
- <annotation name="org.chromium.DBus.Method.Kind" value="simple"/>
- </method>
- </interface>
- <interface name="org.chromium.CrashReporterLibcrosProxyResolvedInterface">
- <signal name="ProxyResolved">
- <arg name="source_url" type="s" direction="out"/>
- <arg name="proxy_info" type="s" direction="out"/>
- <arg name="error_message" type="s" direction="out"/>
- </signal>
- </interface>
-</node>
diff --git a/crash_reporter/init/crash-reporter.conf b/crash_reporter/init/crash-reporter.conf
deleted file mode 100644
index 19f2cdb..0000000
--- a/crash_reporter/init/crash-reporter.conf
+++ /dev/null
@@ -1,27 +0,0 @@
-# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-description "Initialize crash reporting services"
-author "chromium-os-dev@chromium.org"
-
-# This job merely initializes its service and then terminates; the
-# actual checking and reporting of crash dumps is triggered by an
-# hourly cron job.
-start on starting system-services
-
-pre-start script
- mkdir -p /var/spool
-
- # Only allow device coredumps on a "developer system".
- if ! is_developer_end_user; then
- # consumer end-user - disable device coredumps, if driver exists.
- echo 1 > /sys/class/devcoredump/disabled || true
- fi
-end script
-
-# crash_reporter uses argv[0] as part of the command line for
-# /proc/sys/kernel/core_pattern. That command line is invoked by
-# the kernel, and can't rely on PATH, so argv[0] must be a full
-# path; we invoke it as such here.
-exec /sbin/crash_reporter --init
diff --git a/crash_reporter/init/crash-sender.conf b/crash_reporter/init/crash-sender.conf
deleted file mode 100644
index 892186f..0000000
--- a/crash_reporter/init/crash-sender.conf
+++ /dev/null
@@ -1,11 +0,0 @@
-# Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-description "Run the crash sender periodically"
-author "chromium-os-dev@chromium.org"
-
-start on starting system-services
-stop on stopping system-services
-
-exec periodic_scheduler 3600 14400 crash_sender /sbin/crash_sender
diff --git a/crash_reporter/init/warn-collector.conf b/crash_reporter/init/warn-collector.conf
deleted file mode 100644
index 3be80da..0000000
--- a/crash_reporter/init/warn-collector.conf
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-description "Runs a daemon which collects and reports kernel warnings"
-author "chromium-os-dev@chromium.org"
-
-start on started system-services
-stop on stopping system-services
-respawn
-
-exec warn_collector
diff --git a/crash_reporter/kernel_collector.cc b/crash_reporter/kernel_collector.cc
deleted file mode 100644
index 68f2d9e..0000000
--- a/crash_reporter/kernel_collector.cc
+++ /dev/null
@@ -1,603 +0,0 @@
-/*
- * Copyright (C) 2012 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 "kernel_collector.h"
-
-#include <map>
-#include <sys/stat.h>
-
-#include <base/files/file_util.h>
-#include <base/logging.h>
-#include <base/strings/string_util.h>
-#include <base/strings/stringprintf.h>
-
-using base::FilePath;
-using base::StringPrintf;
-
-namespace {
-
-const char kDefaultKernelStackSignature[] = "kernel-UnspecifiedStackSignature";
-const char kDumpParentPath[] = "/sys/fs";
-const char kDumpPath[] = "/sys/fs/pstore";
-const char kDumpFormat[] = "dmesg-ramoops-%zu";
-const char kKernelExecName[] = "kernel";
-// Maximum number of records to examine in the kDumpPath.
-const size_t kMaxDumpRecords = 100;
-const pid_t kKernelPid = 0;
-const char kKernelSignatureKey[] = "sig";
-// Byte length of maximum human readable portion of a kernel crash signature.
-const int kMaxHumanStringLength = 40;
-const uid_t kRootUid = 0;
-// Time in seconds from the final kernel log message for a call stack
-// to count towards the signature of the kcrash.
-const int kSignatureTimestampWindow = 2;
-// Kernel log timestamp regular expression.
-const char kTimestampRegex[] = "^<.*>\\[\\s*(\\d+\\.\\d+)\\]";
-
-//
-// These regular expressions enable to us capture the PC in a backtrace.
-// The backtrace is obtained through dmesg or the kernel's preserved/kcrashmem
-// feature.
-//
-// For ARM we see:
-// "<5>[ 39.458982] PC is at write_breakme+0xd0/0x1b4"
-// For MIPS we see:
-// "<5>[ 3378.552000] epc : 804010f0 lkdtm_do_action+0x68/0x3f8"
-// For x86:
-// "<0>[ 37.474699] EIP: [<790ed488>] write_breakme+0x80/0x108
-// SS:ESP 0068:e9dd3efc"
-//
-const char* const kPCRegex[] = {
- 0,
- " PC is at ([^\\+ ]+).*",
- " epc\\s+:\\s+\\S+\\s+([^\\+ ]+).*", // MIPS has an exception program counter
- " EIP: \\[<.*>\\] ([^\\+ ]+).*", // X86 uses EIP for the program counter
- " RIP \\[<.*>\\] ([^\\+ ]+).*", // X86_64 uses RIP for the program counter
-};
-
-static_assert(arraysize(kPCRegex) == KernelCollector::kArchCount,
- "Missing Arch PC regexp");
-
-} // namespace
-
-KernelCollector::KernelCollector()
- : is_enabled_(false),
- ramoops_dump_path_(kDumpPath),
- records_(0),
- // We expect crash dumps in the format of architecture we are built for.
- arch_(GetCompilerArch()) {
-}
-
-KernelCollector::~KernelCollector() {
-}
-
-void KernelCollector::OverridePreservedDumpPath(const FilePath &file_path) {
- ramoops_dump_path_ = file_path;
-}
-
-bool KernelCollector::ReadRecordToString(std::string *contents,
- size_t current_record,
- bool *record_found) {
- // A record is a ramoops dump. It has an associated size of "record_size".
- std::string record;
- std::string captured;
-
- // Ramoops appends a header to a crash which contains ==== followed by a
- // timestamp. Ignore the header.
- pcrecpp::RE record_re(
- "====\\d+\\.\\d+\n(.*)",
- pcrecpp::RE_Options().set_multiline(true).set_dotall(true));
-
- pcrecpp::RE sanity_check_re("\n<\\d+>\\[\\s*(\\d+\\.\\d+)\\]");
-
- FilePath ramoops_record;
- GetRamoopsRecordPath(&ramoops_record, current_record);
- if (!base::ReadFileToString(ramoops_record, &record)) {
- LOG(ERROR) << "Unable to open " << ramoops_record.value();
- return false;
- }
-
- *record_found = false;
- if (record_re.FullMatch(record, &captured)) {
- // Found a ramoops header, so strip the header and append the rest.
- contents->append(captured);
- *record_found = true;
- } else if (sanity_check_re.PartialMatch(record.substr(0, 1024))) {
- // pstore compression has been added since kernel 3.12. In order to
- // decompress dmesg correctly, ramoops driver has to strip the header
- // before handing over the record to the pstore driver, so we don't
- // need to do it here anymore. However, the sanity check is needed because
- // sometimes a pstore record is just a chunk of uninitialized memory which
- // is not the result of a kernel crash. See crbug.com/443764
- contents->append(record);
- *record_found = true;
- } else {
- LOG(WARNING) << "Found invalid record at " << ramoops_record.value();
- }
-
- // Remove the record from pstore after it's found.
- if (*record_found)
- base::DeleteFile(ramoops_record, false);
-
- return true;
-}
-
-void KernelCollector::GetRamoopsRecordPath(FilePath *path,
- size_t record) {
- // Disable error "format not a string literal, argument types not checked"
- // because this is valid, but GNU apparently doesn't bother checking a const
- // format string.
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wformat-nonliteral"
- *path = ramoops_dump_path_.Append(StringPrintf(kDumpFormat, record));
- #pragma GCC diagnostic pop
-}
-
-bool KernelCollector::LoadParameters() {
- // Discover how many ramoops records are being exported by the driver.
- size_t count;
-
- for (count = 0; count < kMaxDumpRecords; ++count) {
- FilePath ramoops_record;
- GetRamoopsRecordPath(&ramoops_record, count);
-
- if (!base::PathExists(ramoops_record))
- break;
- }
-
- records_ = count;
- return (records_ > 0);
-}
-
-bool KernelCollector::LoadPreservedDump(std::string *contents) {
- // Load dumps from the preserved memory and save them in contents.
- // Since the system is set to restart on oops we won't actually ever have
- // multiple records (only 0 or 1), but check in case we don't restart on
- // oops in the future.
- bool any_records_found = false;
- bool record_found = false;
- // clear contents since ReadFileToString actually appends to the string.
- contents->clear();
-
- for (size_t i = 0; i < records_; ++i) {
- if (!ReadRecordToString(contents, i, &record_found)) {
- break;
- }
- if (record_found) {
- any_records_found = true;
- }
- }
-
- if (!any_records_found) {
- LOG(ERROR) << "No valid records found in " << ramoops_dump_path_.value();
- return false;
- }
-
- return true;
-}
-
-void KernelCollector::StripSensitiveData(std::string *kernel_dump) {
- // Strip any data that the user might not want sent up to the crash servers.
- // We'll read in from kernel_dump and also place our output there.
- //
- // At the moment, the only sensitive data we strip is MAC addresses.
-
- // Get rid of things that look like MAC addresses, since they could possibly
- // give information about where someone has been. This is strings that look
- // like this: 11:22:33:44:55:66
- // Complications:
- // - Within a given kernel_dump, want to be able to tell when the same MAC
- // was used more than once. Thus, we'll consistently replace the first
- // MAC found with 00:00:00:00:00:01, the second with ...:02, etc.
- // - ACPI commands look like MAC addresses. We'll specifically avoid getting
- // rid of those.
- std::ostringstream result;
- std::string pre_mac_str;
- std::string mac_str;
- std::map<std::string, std::string> mac_map;
- pcrecpp::StringPiece input(*kernel_dump);
-
- // This RE will find the next MAC address and can return us the data preceding
- // the MAC and the MAC itself.
- pcrecpp::RE mac_re("(.*?)("
- "[0-9a-fA-F][0-9a-fA-F]:"
- "[0-9a-fA-F][0-9a-fA-F]:"
- "[0-9a-fA-F][0-9a-fA-F]:"
- "[0-9a-fA-F][0-9a-fA-F]:"
- "[0-9a-fA-F][0-9a-fA-F]:"
- "[0-9a-fA-F][0-9a-fA-F])",
- pcrecpp::RE_Options()
- .set_multiline(true)
- .set_dotall(true));
-
- // This RE will identify when the 'pre_mac_str' shows that the MAC address
- // was really an ACPI cmd. The full string looks like this:
- // ata1.00: ACPI cmd ef/10:03:00:00:00:a0 (SET FEATURES) filtered out
- pcrecpp::RE acpi_re("ACPI cmd ef/$",
- pcrecpp::RE_Options()
- .set_multiline(true)
- .set_dotall(true));
-
- // Keep consuming, building up a result string as we go.
- while (mac_re.Consume(&input, &pre_mac_str, &mac_str)) {
- if (acpi_re.PartialMatch(pre_mac_str)) {
- // We really saw an ACPI command; add to result w/ no stripping.
- result << pre_mac_str << mac_str;
- } else {
- // Found a MAC address; look up in our hash for the mapping.
- std::string replacement_mac = mac_map[mac_str];
- if (replacement_mac == "") {
- // It wasn't present, so build up a replacement string.
- int mac_id = mac_map.size();
-
- // Handle up to 2^32 unique MAC address; overkill, but doesn't hurt.
- replacement_mac = StringPrintf("00:00:%02x:%02x:%02x:%02x",
- (mac_id & 0xff000000) >> 24,
- (mac_id & 0x00ff0000) >> 16,
- (mac_id & 0x0000ff00) >> 8,
- (mac_id & 0x000000ff));
- mac_map[mac_str] = replacement_mac;
- }
-
- // Dump the string before the MAC and the fake MAC address into result.
- result << pre_mac_str << replacement_mac;
- }
- }
-
- // One last bit of data might still be in the input.
- result << input;
-
- // We'll just assign right back to kernel_dump.
- *kernel_dump = result.str();
-}
-
-bool KernelCollector::DumpDirMounted() {
- struct stat st_parent;
- if (stat(kDumpParentPath, &st_parent)) {
- PLOG(WARNING) << "Could not stat " << kDumpParentPath;
- return false;
- }
-
- struct stat st_dump;
- if (stat(kDumpPath, &st_dump)) {
- PLOG(WARNING) << "Could not stat " << kDumpPath;
- return false;
- }
-
- if (st_parent.st_dev == st_dump.st_dev) {
- LOG(WARNING) << "Dump dir " << kDumpPath << " not mounted";
- return false;
- }
-
- return true;
-}
-
-bool KernelCollector::Enable() {
- if (arch_ == kArchUnknown || arch_ >= kArchCount ||
- kPCRegex[arch_] == nullptr) {
- LOG(WARNING) << "KernelCollector does not understand this architecture";
- return false;
- }
-
- if (!DumpDirMounted()) {
- LOG(WARNING) << "Kernel does not support crash dumping";
- return false;
- }
-
- // To enable crashes, we will eventually need to set
- // the chnv bit in BIOS, but it does not yet work.
- LOG(INFO) << "Enabling kernel crash handling";
- is_enabled_ = true;
- return true;
-}
-
-// Hash a string to a number. We define our own hash function to not
-// be dependent on a C++ library that might change. This function
-// uses basically the same approach as tr1/functional_hash.h but with
-// a larger prime number (16127 vs 131).
-static unsigned HashString(const std::string &input) {
- unsigned hash = 0;
- for (size_t i = 0; i < input.length(); ++i)
- hash = hash * 16127 + input[i];
- return hash;
-}
-
-void KernelCollector::ProcessStackTrace(
- pcrecpp::StringPiece kernel_dump,
- bool print_diagnostics,
- unsigned *hash,
- float *last_stack_timestamp,
- bool *is_watchdog_crash) {
- pcrecpp::RE line_re("(.+)", pcrecpp::MULTILINE());
- pcrecpp::RE stack_trace_start_re(std::string(kTimestampRegex) +
- " (Call Trace|Backtrace):$");
-
- // Match lines such as the following and grab out "function_name".
- // The ? may or may not be present.
- //
- // For ARM:
- // <4>[ 3498.731164] [<c0057220>] ? (function_name+0x20/0x2c) from
- // [<c018062c>] (foo_bar+0xdc/0x1bc)
- //
- // For MIPS:
- // <5>[ 3378.656000] [<804010f0>] lkdtm_do_action+0x68/0x3f8
- //
- // For X86:
- // <4>[ 6066.849504] [<7937bcee>] ? function_name+0x66/0x6c
- //
- pcrecpp::RE stack_entry_re(std::string(kTimestampRegex) +
- "\\s+\\[<[[:xdigit:]]+>\\]" // Matches " [<7937bcee>]"
- "([\\s\\?(]+)" // Matches " ? (" (ARM) or " ? " (X86)
- "([^\\+ )]+)"); // Matches until delimiter reached
- std::string line;
- std::string hashable;
- std::string previous_hashable;
- bool is_watchdog = false;
-
- *hash = 0;
- *last_stack_timestamp = 0;
-
- // Find the last and second-to-last stack traces. The latter is used when
- // the panic is from a watchdog timeout.
- while (line_re.FindAndConsume(&kernel_dump, &line)) {
- std::string certainty;
- std::string function_name;
- if (stack_trace_start_re.PartialMatch(line, last_stack_timestamp)) {
- if (print_diagnostics) {
- printf("Stack trace starting.%s\n",
- hashable.empty() ? "" : " Saving prior trace.");
- }
- previous_hashable = hashable;
- hashable.clear();
- is_watchdog = false;
- } else if (stack_entry_re.PartialMatch(line,
- last_stack_timestamp,
- &certainty,
- &function_name)) {
- bool is_certain = certainty.find('?') == std::string::npos;
- if (print_diagnostics) {
- printf("@%f: stack entry for %s (%s)\n",
- *last_stack_timestamp,
- function_name.c_str(),
- is_certain ? "certain" : "uncertain");
- }
- // Do not include any uncertain (prefixed by '?') frames in our hash.
- if (!is_certain)
- continue;
- if (!hashable.empty())
- hashable.append("|");
- if (function_name == "watchdog_timer_fn" ||
- function_name == "watchdog") {
- is_watchdog = true;
- }
- hashable.append(function_name);
- }
- }
-
- // If the last stack trace contains a watchdog function we assume the panic
- // is from the watchdog timer, and we hash the previous stack trace rather
- // than the last one, assuming that the previous stack is that of the hung
- // thread.
- //
- // In addition, if the hashable is empty (meaning all frames are uncertain,
- // for whatever reason) also use the previous frame, as it cannot be any
- // worse.
- if (is_watchdog || hashable.empty()) {
- hashable = previous_hashable;
- }
-
- *hash = HashString(hashable);
- *is_watchdog_crash = is_watchdog;
-
- if (print_diagnostics) {
- printf("Hash based on stack trace: \"%s\" at %f.\n",
- hashable.c_str(), *last_stack_timestamp);
- }
-}
-
-// static
-KernelCollector::ArchKind KernelCollector::GetCompilerArch() {
-#if defined(COMPILER_GCC) && defined(ARCH_CPU_ARM_FAMILY)
- return kArchArm;
-#elif defined(COMPILER_GCC) && defined(ARCH_CPU_MIPS_FAMILY)
- return kArchMips;
-#elif defined(COMPILER_GCC) && defined(ARCH_CPU_X86_64)
- return kArchX86_64;
-#elif defined(COMPILER_GCC) && defined(ARCH_CPU_X86_FAMILY)
- return kArchX86;
-#else
- return kArchUnknown;
-#endif
-}
-
-bool KernelCollector::FindCrashingFunction(
- pcrecpp::StringPiece kernel_dump,
- bool print_diagnostics,
- float stack_trace_timestamp,
- std::string *crashing_function) {
- float timestamp = 0;
-
- // Use the correct regex for this architecture.
- pcrecpp::RE eip_re(std::string(kTimestampRegex) + kPCRegex[arch_],
- pcrecpp::MULTILINE());
-
- while (eip_re.FindAndConsume(&kernel_dump, ×tamp, crashing_function)) {
- if (print_diagnostics) {
- printf("@%f: found crashing function %s\n",
- timestamp,
- crashing_function->c_str());
- }
- }
- if (timestamp == 0) {
- if (print_diagnostics) {
- printf("Found no crashing function.\n");
- }
- return false;
- }
- if (stack_trace_timestamp != 0 &&
- abs(static_cast<int>(stack_trace_timestamp - timestamp))
- > kSignatureTimestampWindow) {
- if (print_diagnostics) {
- printf("Found crashing function but not within window.\n");
- }
- return false;
- }
- if (print_diagnostics) {
- printf("Found crashing function %s\n", crashing_function->c_str());
- }
- return true;
-}
-
-bool KernelCollector::FindPanicMessage(pcrecpp::StringPiece kernel_dump,
- bool print_diagnostics,
- std::string *panic_message) {
- // Match lines such as the following and grab out "Fatal exception"
- // <0>[ 342.841135] Kernel panic - not syncing: Fatal exception
- pcrecpp::RE kernel_panic_re(std::string(kTimestampRegex) +
- " Kernel panic[^\\:]*\\:\\s*(.*)",
- pcrecpp::MULTILINE());
- float timestamp = 0;
- while (kernel_panic_re.FindAndConsume(&kernel_dump,
- ×tamp,
- panic_message)) {
- if (print_diagnostics) {
- printf("@%f: panic message %s\n",
- timestamp,
- panic_message->c_str());
- }
- }
- if (timestamp == 0) {
- if (print_diagnostics) {
- printf("Found no panic message.\n");
- }
- return false;
- }
- return true;
-}
-
-bool KernelCollector::ComputeKernelStackSignature(
- const std::string &kernel_dump,
- std::string *kernel_signature,
- bool print_diagnostics) {
- unsigned stack_hash = 0;
- float last_stack_timestamp = 0;
- std::string human_string;
- bool is_watchdog_crash;
-
- ProcessStackTrace(kernel_dump,
- print_diagnostics,
- &stack_hash,
- &last_stack_timestamp,
- &is_watchdog_crash);
-
- if (!FindCrashingFunction(kernel_dump,
- print_diagnostics,
- last_stack_timestamp,
- &human_string)) {
- if (!FindPanicMessage(kernel_dump, print_diagnostics, &human_string)) {
- if (print_diagnostics) {
- printf("Found no human readable string, using empty string.\n");
- }
- human_string.clear();
- }
- }
-
- if (human_string.empty() && stack_hash == 0) {
- if (print_diagnostics) {
- printf("Found neither a stack nor a human readable string, failing.\n");
- }
- return false;
- }
-
- human_string = human_string.substr(0, kMaxHumanStringLength);
- *kernel_signature = StringPrintf("%s-%s%s-%08X",
- kKernelExecName,
- (is_watchdog_crash ? "(HANG)-" : ""),
- human_string.c_str(),
- stack_hash);
- return true;
-}
-
-bool KernelCollector::Collect() {
- std::string kernel_dump;
- FilePath root_crash_directory;
-
- if (!LoadParameters()) {
- return false;
- }
- if (!LoadPreservedDump(&kernel_dump)) {
- return false;
- }
- StripSensitiveData(&kernel_dump);
- if (kernel_dump.empty()) {
- return false;
- }
- std::string signature;
- if (!ComputeKernelStackSignature(kernel_dump, &signature, false)) {
- signature = kDefaultKernelStackSignature;
- }
-
- std::string reason = "handling";
- bool feedback = true;
- if (IsDeveloperImage()) {
- reason = "developer build - always dumping";
- feedback = true;
- } else if (!is_feedback_allowed_function_()) {
- reason = "ignoring - no consent";
- feedback = false;
- }
-
- LOG(INFO) << "Received prior crash notification from "
- << "kernel (signature " << signature << ") (" << reason << ")";
-
- if (feedback) {
- count_crash_function_();
-
- if (!GetCreatedCrashDirectoryByEuid(kRootUid,
- &root_crash_directory,
- nullptr)) {
- return true;
- }
-
- std::string dump_basename =
- FormatDumpBasename(kKernelExecName, time(nullptr), kKernelPid);
- FilePath kernel_crash_path = root_crash_directory.Append(
- StringPrintf("%s.kcrash", dump_basename.c_str()));
-
- // We must use WriteNewFile instead of base::WriteFile as we
- // do not want to write with root access to a symlink that an attacker
- // might have created.
- if (WriteNewFile(kernel_crash_path,
- kernel_dump.data(),
- kernel_dump.length()) !=
- static_cast<int>(kernel_dump.length())) {
- LOG(INFO) << "Failed to write kernel dump to "
- << kernel_crash_path.value().c_str();
- return true;
- }
-
- AddCrashMetaData(kKernelSignatureKey, signature);
- WriteCrashMetaData(
- root_crash_directory.Append(
- StringPrintf("%s.meta", dump_basename.c_str())),
- kKernelExecName,
- kernel_crash_path.value());
-
- LOG(INFO) << "Stored kcrash to " << kernel_crash_path.value();
- }
-
- return true;
-}
diff --git a/crash_reporter/kernel_collector.h b/crash_reporter/kernel_collector.h
deleted file mode 100644
index 206ee26..0000000
--- a/crash_reporter/kernel_collector.h
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright (C) 2010 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.
- */
-
-#ifndef CRASH_REPORTER_KERNEL_COLLECTOR_H_
-#define CRASH_REPORTER_KERNEL_COLLECTOR_H_
-
-#include <pcrecpp.h>
-
-#include <string>
-
-#include <base/files/file_path.h>
-#include <base/macros.h>
-#include <gtest/gtest_prod.h> // for FRIEND_TEST
-
-#include "crash_collector.h"
-
-// Kernel crash collector.
-class KernelCollector : public CrashCollector {
- public:
- // Enumeration to specify architecture type.
- enum ArchKind {
- kArchUnknown,
- kArchArm,
- kArchMips,
- kArchX86,
- kArchX86_64,
-
- kArchCount // Number of architectures.
- };
-
- KernelCollector();
-
- ~KernelCollector() override;
-
- void OverridePreservedDumpPath(const base::FilePath &file_path);
-
- // Enable collection.
- bool Enable();
-
- // Returns true if the kernel collection currently enabled.
- bool is_enabled() const { return is_enabled_; }
-
- // Collect any preserved kernel crash dump. Returns true if there was
- // a dump (even if there were problems storing the dump), false otherwise.
- bool Collect();
-
- // Compute a stack signature string from a kernel dump.
- bool ComputeKernelStackSignature(const std::string &kernel_dump,
- std::string *kernel_signature,
- bool print_diagnostics);
-
- // Set the architecture of the crash dumps we are looking at.
- void set_arch(ArchKind arch) { arch_ = arch; }
- ArchKind arch() const { return arch_; }
-
- private:
- friend class KernelCollectorTest;
- FRIEND_TEST(KernelCollectorTest, LoadPreservedDump);
- FRIEND_TEST(KernelCollectorTest, StripSensitiveDataBasic);
- FRIEND_TEST(KernelCollectorTest, StripSensitiveDataBulk);
- FRIEND_TEST(KernelCollectorTest, StripSensitiveDataSample);
- FRIEND_TEST(KernelCollectorTest, CollectOK);
-
- virtual bool DumpDirMounted();
-
- bool LoadPreservedDump(std::string *contents);
- void StripSensitiveData(std::string *kernel_dump);
-
- void GetRamoopsRecordPath(base::FilePath *path, size_t record);
- bool LoadParameters();
- bool HasMoreRecords();
-
- // Read a record to string, modified from file_utils since that didn't
- // provide a way to restrict the read length.
- // Return value indicates (only) error state:
- // * false when we get an error (can't read from dump location).
- // * true if no error occured.
- // Not finding a valid record is not an error state and is signaled by the
- // record_found output parameter.
- bool ReadRecordToString(std::string *contents,
- size_t current_record,
- bool *record_found);
-
- void ProcessStackTrace(pcrecpp::StringPiece kernel_dump,
- bool print_diagnostics,
- unsigned *hash,
- float *last_stack_timestamp,
- bool *is_watchdog_crash);
- bool FindCrashingFunction(pcrecpp::StringPiece kernel_dump,
- bool print_diagnostics,
- float stack_trace_timestamp,
- std::string *crashing_function);
- bool FindPanicMessage(pcrecpp::StringPiece kernel_dump,
- bool print_diagnostics,
- std::string *panic_message);
-
- // Returns the architecture kind for which we are built.
- static ArchKind GetCompilerArch();
-
- bool is_enabled_;
- base::FilePath ramoops_dump_path_;
- size_t records_;
-
- // The architecture of kernel dump strings we are working with.
- ArchKind arch_;
-
- DISALLOW_COPY_AND_ASSIGN(KernelCollector);
-};
-
-#endif // CRASH_REPORTER_KERNEL_COLLECTOR_H_
diff --git a/crash_reporter/kernel_collector_test.cc b/crash_reporter/kernel_collector_test.cc
deleted file mode 100644
index 0f6b930..0000000
--- a/crash_reporter/kernel_collector_test.cc
+++ /dev/null
@@ -1,679 +0,0 @@
-/*
- * Copyright (C) 2012 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 "kernel_collector_test.h"
-
-#include <unistd.h>
-
-#include <base/files/file_util.h>
-#include <base/files/scoped_temp_dir.h>
-#include <base/strings/string_util.h>
-#include <base/strings/stringprintf.h>
-#include <brillo/syslog_logging.h>
-#include <gtest/gtest.h>
-
-using base::FilePath;
-using base::StringPrintf;
-using brillo::FindLog;
-using brillo::GetLog;
-
-namespace {
-
-int s_crashes = 0;
-bool s_metrics = false;
-
-void CountCrash() {
- ++s_crashes;
-}
-
-bool IsMetrics() {
- return s_metrics;
-}
-
-} // namespace
-
-class KernelCollectorTest : public ::testing::Test {
- protected:
- void WriteStringToFile(const FilePath &file_path,
- const char *data) {
- unsigned int numBytesWritten =
- base::WriteFile(file_path, data, strlen(data));
- ASSERT_EQ(strlen(data), numBytesWritten);
- }
-
- void SetUpSuccessfulCollect();
- void ComputeKernelStackSignatureCommon();
-
- const FilePath &kcrash_file() const { return test_kcrash_; }
- const FilePath &test_crash_directory() const { return test_crash_directory_; }
-
- KernelCollectorMock collector_;
-
- private:
- void SetUp() override {
- s_crashes = 0;
- s_metrics = true;
-
- EXPECT_CALL(collector_, SetUpDBus()).WillRepeatedly(testing::Return());
-
- collector_.Initialize(CountCrash, IsMetrics);
- ASSERT_TRUE(scoped_temp_dir_.CreateUniqueTempDir());
- test_kcrash_ = scoped_temp_dir_.path().Append("kcrash");
- ASSERT_TRUE(base::CreateDirectory(test_kcrash_));
- collector_.OverridePreservedDumpPath(test_kcrash_);
-
- test_kcrash_ = test_kcrash_.Append("dmesg-ramoops-0");
- ASSERT_FALSE(base::PathExists(test_kcrash_));
-
- test_crash_directory_ = scoped_temp_dir_.path().Append("crash_directory");
- ASSERT_TRUE(base::CreateDirectory(test_crash_directory_));
- brillo::ClearLog();
- }
-
- FilePath test_kcrash_;
- FilePath test_crash_directory_;
- base::ScopedTempDir scoped_temp_dir_;
-};
-
-TEST_F(KernelCollectorTest, ComputeKernelStackSignatureBase) {
- // Make sure the normal build architecture is detected
- EXPECT_NE(KernelCollector::kArchUnknown, collector_.arch());
-}
-
-TEST_F(KernelCollectorTest, LoadPreservedDump) {
- ASSERT_FALSE(base::PathExists(kcrash_file()));
- std::string dump;
- dump.clear();
-
- WriteStringToFile(kcrash_file(),
- "CrashRecordWithoutRamoopsHeader\n<6>[ 0.078852]");
- ASSERT_TRUE(collector_.LoadParameters());
- ASSERT_TRUE(collector_.LoadPreservedDump(&dump));
- ASSERT_EQ("CrashRecordWithoutRamoopsHeader\n<6>[ 0.078852]", dump);
-
- WriteStringToFile(kcrash_file(), "====1.1\nsomething");
- ASSERT_TRUE(collector_.LoadParameters());
- ASSERT_TRUE(collector_.LoadPreservedDump(&dump));
- ASSERT_EQ("something", dump);
-
- WriteStringToFile(kcrash_file(), "\x01\x02\xfe\xff random blob");
- ASSERT_TRUE(collector_.LoadParameters());
- ASSERT_FALSE(collector_.LoadPreservedDump(&dump));
- ASSERT_EQ("", dump);
-}
-
-TEST_F(KernelCollectorTest, EnableMissingKernel) {
- ASSERT_FALSE(collector_.Enable());
- ASSERT_FALSE(collector_.is_enabled());
- ASSERT_TRUE(FindLog(
- "Kernel does not support crash dumping"));
- ASSERT_EQ(s_crashes, 0);
-}
-
-TEST_F(KernelCollectorTest, EnableOK) {
- WriteStringToFile(kcrash_file(), "");
- EXPECT_CALL(collector_, DumpDirMounted()).WillOnce(::testing::Return(true));
- ASSERT_TRUE(collector_.Enable());
- ASSERT_TRUE(collector_.is_enabled());
- ASSERT_TRUE(FindLog("Enabling kernel crash handling"));
- ASSERT_EQ(s_crashes, 0);
-}
-
-TEST_F(KernelCollectorTest, StripSensitiveDataBasic) {
- // Basic tests of StripSensitiveData...
-
- // Make sure we work OK with a string w/ no MAC addresses.
- const std::string kCrashWithNoMacsOrig =
- "<7>[111566.131728] PM: Entering mem sleep\n";
- std::string crash_with_no_macs(kCrashWithNoMacsOrig);
- collector_.StripSensitiveData(&crash_with_no_macs);
- EXPECT_EQ(kCrashWithNoMacsOrig, crash_with_no_macs);
-
- // Make sure that we handle the case where there's nothing before/after the
- // MAC address.
- const std::string kJustAMacOrig =
- "11:22:33:44:55:66";
- const std::string kJustAMacStripped =
- "00:00:00:00:00:01";
- std::string just_a_mac(kJustAMacOrig);
- collector_.StripSensitiveData(&just_a_mac);
- EXPECT_EQ(kJustAMacStripped, just_a_mac);
-
- // Test MAC addresses crammed together to make sure it gets both of them.
- //
- // I'm not sure that the code does ideal on these two test cases (they don't
- // look like two MAC addresses to me), but since we don't see them I think
- // it's OK to behave as shown here.
- const std::string kCrammedMacs1Orig =
- "11:22:33:44:55:66:11:22:33:44:55:66";
- const std::string kCrammedMacs1Stripped =
- "00:00:00:00:00:01:00:00:00:00:00:01";
- std::string crammed_macs_1(kCrammedMacs1Orig);
- collector_.StripSensitiveData(&crammed_macs_1);
- EXPECT_EQ(kCrammedMacs1Stripped, crammed_macs_1);
-
- const std::string kCrammedMacs2Orig =
- "11:22:33:44:55:6611:22:33:44:55:66";
- const std::string kCrammedMacs2Stripped =
- "00:00:00:00:00:0100:00:00:00:00:01";
- std::string crammed_macs_2(kCrammedMacs2Orig);
- collector_.StripSensitiveData(&crammed_macs_2);
- EXPECT_EQ(kCrammedMacs2Stripped, crammed_macs_2);
-
- // Test case-sensitiveness (we shouldn't be case-senstive).
- const std::string kCapsMacOrig =
- "AA:BB:CC:DD:EE:FF";
- const std::string kCapsMacStripped =
- "00:00:00:00:00:01";
- std::string caps_mac(kCapsMacOrig);
- collector_.StripSensitiveData(&caps_mac);
- EXPECT_EQ(kCapsMacStripped, caps_mac);
-
- const std::string kLowerMacOrig =
- "aa:bb:cc:dd:ee:ff";
- const std::string kLowerMacStripped =
- "00:00:00:00:00:01";
- std::string lower_mac(kLowerMacOrig);
- collector_.StripSensitiveData(&lower_mac);
- EXPECT_EQ(kLowerMacStripped, lower_mac);
-}
-
-TEST_F(KernelCollectorTest, StripSensitiveDataBulk) {
- // Test calling StripSensitiveData w/ lots of MAC addresses in the "log".
-
- // Test that stripping code handles more than 256 unique MAC addresses, since
- // that overflows past the last byte...
- // We'll write up some code that generates 258 unique MAC addresses. Sorta
- // cheating since the code is very similar to the current code in
- // StripSensitiveData(), but would catch if someone changed that later.
- std::string lotsa_macs_orig;
- std::string lotsa_macs_stripped;
- int i;
- for (i = 0; i < 258; i++) {
- lotsa_macs_orig += StringPrintf(" 11:11:11:11:%02X:%02x",
- (i & 0xff00) >> 8, i & 0x00ff);
- lotsa_macs_stripped += StringPrintf(" 00:00:00:00:%02X:%02x",
- ((i+1) & 0xff00) >> 8, (i+1) & 0x00ff);
- }
- std::string lotsa_macs(lotsa_macs_orig);
- collector_.StripSensitiveData(&lotsa_macs);
- EXPECT_EQ(lotsa_macs_stripped, lotsa_macs);
-}
-
-TEST_F(KernelCollectorTest, StripSensitiveDataSample) {
- // Test calling StripSensitiveData w/ some actual lines from a real crash;
- // included two MAC addresses (though replaced them with some bogusness).
- const std::string kCrashWithMacsOrig =
- "<6>[111567.195339] ata1.00: ACPI cmd ef/10:03:00:00:00:a0 (SET FEATURES)"
- " filtered out\n"
- "<7>[108539.540144] wlan0: authenticate with 11:22:33:44:55:66 (try 1)\n"
- "<7>[108539.554973] wlan0: associate with 11:22:33:44:55:66 (try 1)\n"
- "<6>[110136.587583] usb0: register 'QCUSBNet2k' at usb-0000:00:1d.7-2,"
- " QCUSBNet Ethernet Device, 99:88:77:66:55:44\n"
- "<7>[110964.314648] wlan0: deauthenticated from 11:22:33:44:55:66"
- " (Reason: 6)\n"
- "<7>[110964.325057] phy0: Removed STA 11:22:33:44:55:66\n"
- "<7>[110964.325115] phy0: Destroyed STA 11:22:33:44:55:66\n"
- "<6>[110969.219172] usb0: register 'QCUSBNet2k' at usb-0000:00:1d.7-2,"
- " QCUSBNet Ethernet Device, 99:88:77:66:55:44\n"
- "<7>[111566.131728] PM: Entering mem sleep\n";
- const std::string kCrashWithMacsStripped =
- "<6>[111567.195339] ata1.00: ACPI cmd ef/10:03:00:00:00:a0 (SET FEATURES)"
- " filtered out\n"
- "<7>[108539.540144] wlan0: authenticate with 00:00:00:00:00:01 (try 1)\n"
- "<7>[108539.554973] wlan0: associate with 00:00:00:00:00:01 (try 1)\n"
- "<6>[110136.587583] usb0: register 'QCUSBNet2k' at usb-0000:00:1d.7-2,"
- " QCUSBNet Ethernet Device, 00:00:00:00:00:02\n"
- "<7>[110964.314648] wlan0: deauthenticated from 00:00:00:00:00:01"
- " (Reason: 6)\n"
- "<7>[110964.325057] phy0: Removed STA 00:00:00:00:00:01\n"
- "<7>[110964.325115] phy0: Destroyed STA 00:00:00:00:00:01\n"
- "<6>[110969.219172] usb0: register 'QCUSBNet2k' at usb-0000:00:1d.7-2,"
- " QCUSBNet Ethernet Device, 00:00:00:00:00:02\n"
- "<7>[111566.131728] PM: Entering mem sleep\n";
- std::string crash_with_macs(kCrashWithMacsOrig);
- collector_.StripSensitiveData(&crash_with_macs);
- EXPECT_EQ(kCrashWithMacsStripped, crash_with_macs);
-}
-
-TEST_F(KernelCollectorTest, CollectPreservedFileMissing) {
- ASSERT_FALSE(collector_.Collect());
- ASSERT_FALSE(FindLog("Stored kcrash to "));
- ASSERT_EQ(0, s_crashes);
-}
-
-void KernelCollectorTest::SetUpSuccessfulCollect() {
- collector_.ForceCrashDirectory(test_crash_directory());
- WriteStringToFile(kcrash_file(), "====1.1\nsomething");
- ASSERT_EQ(0, s_crashes);
-}
-
-TEST_F(KernelCollectorTest, CollectOptedOut) {
- SetUpSuccessfulCollect();
- s_metrics = false;
- ASSERT_TRUE(collector_.Collect());
- ASSERT_TRUE(FindLog("(ignoring - no consent)"));
- ASSERT_EQ(0, s_crashes);
-}
-
-TEST_F(KernelCollectorTest, CollectOK) {
- SetUpSuccessfulCollect();
- ASSERT_TRUE(collector_.Collect());
- ASSERT_EQ(1, s_crashes);
- ASSERT_TRUE(FindLog("(handling)"));
- static const char kNamePrefix[] = "Stored kcrash to ";
- std::string log = brillo::GetLog();
- size_t pos = log.find(kNamePrefix);
- ASSERT_NE(std::string::npos, pos)
- << "Did not find string \"" << kNamePrefix << "\" in log: {\n"
- << log << "}";
- pos += strlen(kNamePrefix);
- std::string filename = log.substr(pos, std::string::npos);
- // Take the name up until \n
- size_t end_pos = filename.find_first_of('\n');
- ASSERT_NE(std::string::npos, end_pos);
- filename = filename.substr(0, end_pos);
- ASSERT_EQ(0U, filename.find(test_crash_directory().value()));
- ASSERT_TRUE(base::PathExists(FilePath(filename)));
- std::string contents;
- ASSERT_TRUE(base::ReadFileToString(FilePath(filename), &contents));
- ASSERT_EQ("something", contents);
-}
-
-// Perform tests which are common across architectures
-void KernelCollectorTest::ComputeKernelStackSignatureCommon() {
- std::string signature;
-
- const char kStackButNoPC[] =
- "<4>[ 6066.829029] [<790340af>] __do_softirq+0xa6/0x143\n";
- EXPECT_TRUE(
- collector_.ComputeKernelStackSignature(kStackButNoPC, &signature, false));
- EXPECT_EQ("kernel--83615F0A", signature);
-
- const char kMissingEverything[] =
- "<4>[ 6066.829029] [<790340af>] ? __do_softirq+0xa6/0x143\n";
- EXPECT_FALSE(
- collector_.ComputeKernelStackSignature(kMissingEverything,
- &signature,
- false));
-
- // Long message.
- const char kTruncatedMessage[] =
- "<0>[ 87.485611] Kernel panic - not syncing: 01234567890123456789"
- "01234567890123456789X\n";
- EXPECT_TRUE(
- collector_.ComputeKernelStackSignature(kTruncatedMessage,
- &signature,
- false));
- EXPECT_EQ("kernel-0123456789012345678901234567890123456789-00000000",
- signature);
-}
-
-TEST_F(KernelCollectorTest, ComputeKernelStackSignatureARM) {
- const char kBugToPanic[] =
- "<5>[ 123.412524] Modules linked in:\n"
- "<5>[ 123.412534] CPU: 0 Tainted: G W "
- "(2.6.37-01030-g51cee64 #153)\n"
- "<5>[ 123.412552] PC is at write_breakme+0xd0/0x1b4\n"
- "<5>[ 123.412560] LR is at write_breakme+0xc8/0x1b4\n"
- "<5>[ 123.412569] pc : [<c0058220>] lr : [<c005821c>] "
- "psr: 60000013\n"
- "<5>[ 123.412574] sp : f4e0ded8 ip : c04d104c fp : 000e45e0\n"
- "<5>[ 123.412581] r10: 400ff000 r9 : f4e0c000 r8 : 00000004\n"
- "<5>[ 123.412589] r7 : f4e0df80 r6 : f4820c80 r5 : 00000004 "
- "r4 : f4e0dee8\n"
- "<5>[ 123.412598] r3 : 00000000 r2 : f4e0decc r1 : c05f88a9 "
- "r0 : 00000039\n"
- "<5>[ 123.412608] Flags: nZCv IRQs on FIQs on Mode SVC_32 ISA "
- "ARM Segment user\n"
- "<5>[ 123.412617] Control: 10c53c7d Table: 34dcc04a DAC: 00000015\n"
- "<0>[ 123.412626] Process bash (pid: 1014, stack limit = 0xf4e0c2f8)\n"
- "<0>[ 123.412634] Stack: (0xf4e0ded8 to 0xf4e0e000)\n"
- "<0>[ 123.412641] dec0: "
- " f4e0dee8 c0183678\n"
- "<0>[ 123.412654] dee0: 00000000 00000000 00677562 0000081f c06a6a78 "
- "400ff000 f4e0dfb0 00000000\n"
- "<0>[ 123.412666] df00: bec7ab44 000b1719 bec7ab0c c004f498 bec7a314 "
- "c024acc8 00000001 c018359c\n"
- "<0>[ 123.412679] df20: f4e0df34 c04d10fc f5803c80 271beb39 000e45e0 "
- "f5803c80 c018359c c017bfe0\n"
- "<0>[ 123.412691] df40: 00000004 f4820c80 400ff000 f4e0df80 00000004 "
- "f4e0c000 00000000 c01383e4\n"
- "<0>[ 123.412703] df60: f4820c80 400ff000 f4820c80 400ff000 00000000 "
- "00000000 00000004 c0138578\n"
- "<0>[ 123.412715] df80: 00000000 00000000 00000004 00000000 00000004 "
- "402f95d0 00000004 00000004\n"
- "<0>[ 123.412727] dfa0: c0054984 c00547c0 00000004 402f95d0 00000001 "
- "400ff000 00000004 00000000\n"
- "<0>[ 123.412739] dfc0: 00000004 402f95d0 00000004 00000004 400ff000 "
- "000c194c bec7ab58 000e45e0\n"
- "<0>[ 123.412751] dfe0: 00000000 bec7aad8 40232520 40284e9c 60000010 "
- "00000001 00000000 00000000\n"
- "<5>[ 39.496577] Backtrace:\n"
- "<5>[ 123.412782] [<c0058220>] (__bug+0x20/0x2c) from [<c0183678>] "
- "(write_breakme+0xdc/0x1bc)\n"
- "<5>[ 123.412798] [<c0183678>] (write_breakme+0xdc/0x1bc) from "
- "[<c017bfe0>] (proc_reg_write+0x88/0x9c)\n";
- std::string signature;
-
- collector_.set_arch(KernelCollector::kArchArm);
- EXPECT_TRUE(
- collector_.ComputeKernelStackSignature(kBugToPanic, &signature, false));
- EXPECT_EQ("kernel-write_breakme-97D3E92F", signature);
-
- ComputeKernelStackSignatureCommon();
-}
-
-TEST_F(KernelCollectorTest, ComputeKernelStackSignatureMIPS) {
- const char kBugToPanic[] =
- "<5>[ 3378.472000] lkdtm: Performing direct entry BUG\n"
- "<5>[ 3378.476000] Kernel bug detected[#1]:\n"
- "<5>[ 3378.484000] CPU: 0 PID: 185 Comm: dash Not tainted 3.14.0 #1\n"
- "<5>[ 3378.488000] task: 8fed5220 ti: 8ec4a000 task.ti: 8ec4a000\n"
- "<5>[ 3378.496000] $ 0 : 00000000 804018b8 804010f0 7785b507\n"
- "<5>[ 3378.500000] $ 4 : 8061ab64 81204478 81205b20 00000000\n"
- "<5>[ 3378.508000] $ 8 : 80830000 20746365 72746e65 55422079\n"
- "<5>[ 3378.512000] $12 : 8ec4be94 000000fc 00000000 00000048\n"
- "<5>[ 3378.520000] $16 : 00000004 8ef54000 80710000 00000002\n"
- "<5>[ 3378.528000] $20 : 7765b6d4 00000004 7fffffff 00000002\n"
- "<5>[ 3378.532000] $24 : 00000001 803dc0dc \n"
- "<5>[ 3378.540000] $28 : 8ec4a000 8ec4be20 7775438d 804018b8\n"
- "<5>[ 3378.544000] Hi : 00000000\n"
- "<5>[ 3378.548000] Lo : 49bf8080\n"
- "<5>[ 3378.552000] epc : 804010f0 lkdtm_do_action+0x68/0x3f8\n"
- "<5>[ 3378.560000] Not tainted\n"
- "<5>[ 3378.564000] ra : 804018b8 direct_entry+0x110/0x154\n"
- "<5>[ 3378.568000] Status: 3100dc03 KERNEL EXL IE \n"
- "<5>[ 3378.572000] Cause : 10800024\n"
- "<5>[ 3378.576000] PrId : 0001a120 (MIPS interAptiv (multi))\n"
- "<5>[ 3378.580000] Modules linked in: uinput cfg80211 nf_conntrack_ipv6 "
- "nf_defrag_ipv6 ip6table_filter ip6_tables pcnet32 mii fuse "
- "ppp_async ppp_generic slhc tun\n"
- "<5>[ 3378.600000] Process dash (pid: 185, threadinfo=8ec4a000, "
- "task=8fed5220, tls=77632490)\n"
- "<5>[ 3378.608000] Stack : 00000006 ffffff9c 00000000 00000000 00000000 "
- "00000000 8083454a 00000022\n"
- "<5> 7765baa1 00001fee 80710000 8ef54000 8ec4bf08 00000002 "
- "7765b6d4 00000004\n"
- "<5> 7fffffff 00000002 7775438d 805e5158 7fffffff 00000002 "
- "00000000 7785b507\n"
- "<5> 806a96bc 00000004 8ef54000 8ec4bf08 00000002 804018b8 "
- "80710000 806a98bc\n"
- "<5> 00000002 00000020 00000004 8d515600 77756450 00000004 "
- "8ec4bf08 802377e4\n"
- "<5> ...\n"
- "<5>[ 3378.652000] Call Trace:\n"
- "<5>[ 3378.656000] [<804010f0>] lkdtm_do_action+0x68/0x3f8\n"
- "<5>[ 3378.660000] [<804018b8>] direct_entry+0x110/0x154\n"
- "<5>[ 3378.664000] [<802377e4>] vfs_write+0xe0/0x1bc\n"
- "<5>[ 3378.672000] [<80237f90>] SyS_write+0x78/0xf8\n"
- "<5>[ 3378.676000] [<80111888>] handle_sys+0x128/0x14c\n"
- "<5>[ 3378.680000] \n"
- "<5>[ 3378.684000] \n"
- "<5>Code: 3c04806b 0c1793aa 248494f0 <000c000d> 3c04806b 248494fc "
- "0c04cc7f 2405017a 08100514 \n"
- "<5>[ 3378.696000] ---[ end trace 75067432f24bbc93 ]---\n";
- std::string signature;
-
- collector_.set_arch(KernelCollector::kArchMips);
- EXPECT_TRUE(
- collector_.ComputeKernelStackSignature(kBugToPanic, &signature, false));
- EXPECT_EQ("kernel-lkdtm_do_action-5E600A6B", signature);
-
- ComputeKernelStackSignatureCommon();
-}
-
-TEST_F(KernelCollectorTest, ComputeKernelStackSignatureX86) {
- const char kBugToPanic[] =
- "<4>[ 6066.829029] [<79039d16>] ? run_timer_softirq+0x165/0x1e6\n"
- "<4>[ 6066.829029] [<790340af>] ignore_old_stack+0xa6/0x143\n"
- "<0>[ 6066.829029] EIP: [<b82d7c15>] ieee80211_stop_tx_ba_session+"
- "0xa3/0xb5 [mac80211] SS:ESP 0068:7951febc\n"
- "<0>[ 6066.829029] CR2: 00000000323038a7\n"
- "<4>[ 6066.845422] ---[ end trace 12b058bb46c43500 ]---\n"
- "<0>[ 6066.845747] Kernel panic - not syncing: Fatal exception "
- "in interrupt\n"
- "<0>[ 6066.846902] Call Trace:\n"
- "<4>[ 6066.846902] [<7937a07b>] ? printk+0x14/0x19\n"
- "<4>[ 6066.949779] [<79379fc1>] panic+0x3e/0xe4\n"
- "<4>[ 6066.949971] [<7937c5c5>] oops_end+0x73/0x81\n"
- "<4>[ 6066.950208] [<7901b260>] no_context+0x10d/0x117\n";
- std::string signature;
-
- collector_.set_arch(KernelCollector::kArchX86);
- EXPECT_TRUE(
- collector_.ComputeKernelStackSignature(kBugToPanic, &signature, false));
- EXPECT_EQ("kernel-ieee80211_stop_tx_ba_session-DE253569", signature);
-
- const char kPCButNoStack[] =
- "<0>[ 6066.829029] EIP: [<b82d7c15>] ieee80211_stop_tx_ba_session+";
- EXPECT_TRUE(
- collector_.ComputeKernelStackSignature(kPCButNoStack, &signature, false));
- EXPECT_EQ("kernel-ieee80211_stop_tx_ba_session-00000000", signature);
-
- const char kBreakmeBug[] =
- "<4>[ 180.492137] [<790970c6>] ? handle_mm_fault+0x67f/0x96d\n"
- "<4>[ 180.492137] [<790dcdfe>] ? proc_reg_write+0x5f/0x73\n"
- "<4>[ 180.492137] [<790e2224>] ? write_breakme+0x0/0x108\n"
- "<4>[ 180.492137] [<790dcd9f>] ? proc_reg_write+0x0/0x73\n"
- "<4>[ 180.492137] [<790ac0aa>] vfs_write+0x85/0xe4\n"
- "<0>[ 180.492137] Code: c6 44 05 b2 00 89 d8 e8 0c ef 09 00 85 c0 75 "
- "0b c7 00 00 00 00 00 e9 8e 00 00 00 ba e6 75 4b 79 89 d8 e8 f1 ee 09 "
- "00 85 c0 75 04 <0f> 0b eb fe ba 58 47 49 79 89 d8 e8 dd ee 09 00 85 "
- "c0 75 0a 68\n"
- "<0>[ 180.492137] EIP: [<790e22a4>] write_breakme+0x80/0x108 SS:ESP "
- "0068:aa3e9efc\n"
- "<4>[ 180.501800] ---[ end trace 2a6b72965e1b1523 ]---\n"
- "<0>[ 180.502026] Kernel panic - not syncing: Fatal exception\n"
- "<4>[ 180.502026] Call Trace:\n"
- "<4>[ 180.502806] [<79379aba>] ? printk+0x14/0x1a\n"
- "<4>[ 180.503033] [<79379a00>] panic+0x3e/0xe4\n"
- "<4>[ 180.503287] [<7937c005>] oops_end+0x73/0x81\n"
- "<4>[ 180.503520] [<790055dd>] die+0x58/0x5e\n"
- "<4>[ 180.503538] [<7937b96c>] do_trap+0x8e/0xa7\n"
- "<4>[ 180.503555] [<79003d70>] ? do_invalid_op+0x0/0x80\n";
-
- EXPECT_TRUE(
- collector_.ComputeKernelStackSignature(kBreakmeBug, &signature, false));
- EXPECT_EQ("kernel-write_breakme-122AB3CD", signature);
-
- const char kPCLineTooOld[] =
- "<4>[ 174.492137] [<790970c6>] ignored_function+0x67f/0x96d\n"
- "<4>[ 175.492137] [<790970c6>] ignored_function2+0x67f/0x96d\n"
- "<0>[ 174.492137] EIP: [<790e22a4>] write_breakme+0x80/0x108 SS:ESP "
- "0068:aa3e9efc\n"
- "<4>[ 180.501800] ---[ end trace 2a6b72965e1b1523 ]---\n"
- "<4>[ 180.502026] Call Trace:\n"
- "<0>[ 180.502026] Kernel panic - not syncing: Fatal exception\n"
- "<4>[ 180.502806] [<79379aba>] printk+0x14/0x1a\n";
-
- EXPECT_TRUE(
- collector_.ComputeKernelStackSignature(kPCLineTooOld, &signature, false));
- EXPECT_EQ("kernel-Fatal exception-ED4C84FE", signature);
-
- // Panic without EIP line.
- const char kExamplePanicOnly[] =
- "<0>[ 87.485611] Kernel panic - not syncing: Testing panic\n"
- "<4>[ 87.485630] Pid: 2825, comm: bash Tainted: G "
- "C 2.6.32.23+drm33.10 #1\n"
- "<4>[ 87.485639] Call Trace:\n"
- "<4>[ 87.485660] [<8133f71d>] ? printk+0x14/0x17\n"
- "<4>[ 87.485674] [<8133f663>] panic+0x3e/0xe4\n"
- "<4>[ 87.485689] [<810d062e>] write_breakme+0xaa/0x124\n";
- EXPECT_TRUE(
- collector_.ComputeKernelStackSignature(kExamplePanicOnly,
- &signature,
- false));
- EXPECT_EQ("kernel-Testing panic-E0FC3552", signature);
-
- // Panic from hung task.
- const char kHungTaskBreakMe[] =
- "<3>[ 720.459157] INFO: task bash:2287 blocked blah blah\n"
- "<5>[ 720.459282] Call Trace:\n"
- "<5>[ 720.459307] [<810a457b>] ? __dentry_open+0x186/0x23e\n"
- "<5>[ 720.459323] [<810b9c71>] ? mntput_no_expire+0x29/0xe2\n"
- "<5>[ 720.459336] [<810b9d48>] ? mntput+0x1e/0x20\n"
- "<5>[ 720.459350] [<810ad135>] ? path_put+0x1a/0x1d\n"
- "<5>[ 720.459366] [<8137cacc>] schedule+0x4d/0x4f\n"
- "<5>[ 720.459379] [<8137ccfb>] schedule_timeout+0x26/0xaf\n"
- "<5>[ 720.459394] [<8102127e>] ? should_resched+0xd/0x27\n"
- "<5>[ 720.459409] [<81174d1f>] ? _copy_from_user+0x3c/0x50\n"
- "<5>[ 720.459423] [<8137cd9e>] "
- "schedule_timeout_uninterruptible+0x1a/0x1c\n"
- "<5>[ 720.459438] [<810dee63>] write_breakme+0xb3/0x178\n"
- "<5>[ 720.459453] [<810dedb0>] ? meminfo_proc_show+0x2f2/0x2f2\n"
- "<5>[ 720.459467] [<810d94ae>] proc_reg_write+0x6d/0x87\n"
- "<5>[ 720.459481] [<810d9441>] ? proc_reg_poll+0x76/0x76\n"
- "<5>[ 720.459493] [<810a5e9e>] vfs_write+0x79/0xa5\n"
- "<5>[ 720.459505] [<810a6011>] sys_write+0x40/0x65\n"
- "<5>[ 720.459519] [<8137e677>] sysenter_do_call+0x12/0x26\n"
- "<0>[ 720.459530] Kernel panic - not syncing: hung_task: blocked tasks\n"
- "<5>[ 720.459768] Pid: 31, comm: khungtaskd Tainted: "
- "G C 3.0.8 #1\n"
- "<5>[ 720.459998] Call Trace:\n"
- "<5>[ 720.460140] [<81378a35>] panic+0x53/0x14a\n"
- "<5>[ 720.460312] [<8105f875>] watchdog+0x15b/0x1a0\n"
- "<5>[ 720.460495] [<8105f71a>] ? hung_task_panic+0x16/0x16\n"
- "<5>[ 720.460693] [<81043af3>] kthread+0x67/0x6c\n"
- "<5>[ 720.460862] [<81043a8c>] ? __init_kthread_worker+0x2d/0x2d\n"
- "<5>[ 720.461106] [<8137eb9e>] kernel_thread_helper+0x6/0x10\n";
-
- EXPECT_TRUE(
- collector_.ComputeKernelStackSignature(kHungTaskBreakMe,
- &signature,
- false));
-
- EXPECT_EQ("kernel-(HANG)-hung_task: blocked tasks-600B37EA", signature);
-
- // Panic with all question marks in the last stack trace.
- const char kUncertainStackTrace[] =
- "<0>[56279.689669] ------------[ cut here ]------------\n"
- "<2>[56279.689677] kernel BUG at /build/x86-alex/tmp/portage/"
- "sys-kernel/chromeos-kernel-0.0.1-r516/work/chromeos-kernel-0.0.1/"
- "kernel/timer.c:844!\n"
- "<0>[56279.689683] invalid opcode: 0000 [#1] SMP \n"
- "<0>[56279.689688] last sysfs file: /sys/power/state\n"
- "<5>[56279.689692] Modules linked in: nls_iso8859_1 nls_cp437 vfat fat "
- "gobi usbnet tsl2583(C) industrialio(C) snd_hda_codec_realtek "
- "snd_hda_intel i2c_dev snd_hda_codec snd_hwdep qcserial snd_pcm usb_wwan "
- "i2c_i801 snd_timer nm10_gpio snd_page_alloc rtc_cmos fuse "
- "nf_conntrack_ipv6 nf_defrag_ipv6 uvcvideo videodev ip6table_filter "
- "ath9k ip6_tables ipv6 mac80211 ath9k_common ath9k_hw ath cfg80211 "
- "xt_mark\n"
- "<5>[56279.689731] \n"
- "<5>[56279.689738] Pid: 24607, comm: powerd_suspend Tainted: G "
- "WC 2.6.38.3+ #1 SAMSUNG ELECTRONICS CO., LTD. Alex/G100 \n"
- "<5>[56279.689748] EIP: 0060:[<8103e3ea>] EFLAGS: 00210286 CPU: 3\n"
- "<5>[56279.689758] EIP is at add_timer+0xd/0x1b\n"
- "<5>[56279.689762] EAX: f5e00684 EBX: f5e003c0 ECX: 00000002 EDX: "
- "00200246\n"
- "<5>[56279.689767] ESI: f5e003c0 EDI: d28bc03c EBP: d2be5e40 ESP: "
- "d2be5e40\n"
- "<5>[56279.689772] DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068\n"
- "<0>[56279.689778] Process powerd_suspend (pid: 24607, ti=d2be4000 "
- "task=f5dc9b60 task.ti=d2be4000)\n"
- "<0>[56279.689782] Stack:\n"
- "<5>[56279.689785] d2be5e4c f8dccced f4ac02c0 d2be5e70 f8ddc752 "
- "f5e003c0 f4ac0458 f4ac092c\n"
- "<5>[56279.689797] f4ac043c f4ac02c0 f4ac0000 f4ac007c d2be5e7c "
- "f8dd4a33 f4ac0164 d2be5e94\n"
- "<5>[56279.689809] f87e0304 f69ff0cc f4ac0164 f87e02a4 f4ac0164 "
- "d2be5eb0 81248968 00000000\n"
- "<0>[56279.689821] Call Trace:\n"
- "<5>[56279.689840] [<f8dccced>] ieee80211_sta_restart+0x25/0x8c "
- "[mac80211]\n"
- "<5>[56279.689854] [<f8ddc752>] ieee80211_reconfig+0x2e9/0x339 "
- "[mac80211]\n"
- "<5>[56279.689869] [<f8dd4a33>] ieee80211_aes_cmac+0x182d/0x184e "
- "[mac80211]\n"
- "<5>[56279.689883] [<f87e0304>] cfg80211_get_dev_from_info+0x29b/0x2c0 "
- "[cfg80211]\n"
- "<5>[56279.689895] [<f87e02a4>] ? "
- "cfg80211_get_dev_from_info+0x23b/0x2c0 [cfg80211]\n"
- "<5>[56279.689904] [<81248968>] legacy_resume+0x25/0x5d\n"
- "<5>[56279.689910] [<812490ae>] device_resume+0xdd/0x110\n"
- "<5>[56279.689917] [<812491c2>] dpm_resume_end+0xe1/0x271\n"
- "<5>[56279.689925] [<81060481>] suspend_devices_and_enter+0x18b/0x1de\n"
- "<5>[56279.689932] [<810605ba>] enter_state+0xe6/0x132\n"
- "<5>[56279.689939] [<8105fd4b>] state_store+0x91/0x9d\n"
- "<5>[56279.689945] [<8105fcba>] ? state_store+0x0/0x9d\n"
- "<5>[56279.689953] [<81178fb1>] kobj_attr_store+0x16/0x22\n"
- "<5>[56279.689961] [<810eea5e>] sysfs_write_file+0xc1/0xec\n"
- "<5>[56279.689969] [<810af443>] vfs_write+0x8f/0x101\n"
- "<5>[56279.689975] [<810ee99d>] ? sysfs_write_file+0x0/0xec\n"
- "<5>[56279.689982] [<810af556>] sys_write+0x40/0x65\n"
- "<5>[56279.689989] [<81002d57>] sysenter_do_call+0x12/0x26\n"
- "<0>[56279.689993] Code: c1 d3 e2 4a 89 55 f4 f7 d2 21 f2 6a 00 31 c9 89 "
- "d8 e8 6e fd ff ff 5a 8d 65 f8 5b 5e 5d c3 55 89 e5 3e 8d 74 26 00 83 38 "
- "00 74 04 <0f> 0b eb fe 8b 50 08 e8 6f ff ff ff 5d c3 55 89 e5 3e 8d 74 "
- "26 \n"
- "<0>[56279.690009] EIP: [<8103e3ea>] add_timer+0xd/0x1b SS:ESP "
- "0068:d2be5e40\n"
- "<4>[56279.690113] ---[ end trace b71141bb67c6032a ]---\n"
- "<7>[56279.694069] wlan0: deauthenticated from 00:00:00:00:00:01 "
- "(Reason: 6)\n"
- "<0>[56279.703465] Kernel panic - not syncing: Fatal exception\n"
- "<5>[56279.703471] Pid: 24607, comm: powerd_suspend Tainted: G D "
- "WC 2.6.38.3+ #1\n"
- "<5>[56279.703475] Call Trace:\n"
- "<5>[56279.703483] [<8136648c>] ? panic+0x55/0x152\n"
- "<5>[56279.703491] [<810057fa>] ? oops_end+0x73/0x81\n"
- "<5>[56279.703497] [<81005a44>] ? die+0xed/0xf5\n"
- "<5>[56279.703503] [<810033cb>] ? do_trap+0x7a/0x80\n"
- "<5>[56279.703509] [<8100369b>] ? do_invalid_op+0x0/0x80\n"
- "<5>[56279.703515] [<81003711>] ? do_invalid_op+0x76/0x80\n"
- "<5>[56279.703522] [<8103e3ea>] ? add_timer+0xd/0x1b\n"
- "<5>[56279.703529] [<81025e23>] ? check_preempt_curr+0x2e/0x69\n"
- "<5>[56279.703536] [<8102ef28>] ? ttwu_post_activation+0x5a/0x11b\n"
- "<5>[56279.703543] [<8102fa8d>] ? try_to_wake_up+0x213/0x21d\n"
- "<5>[56279.703550] [<81368b7f>] ? error_code+0x67/0x6c\n"
- "<5>[56279.703557] [<8103e3ea>] ? add_timer+0xd/0x1b\n"
- "<5>[56279.703577] [<f8dccced>] ? ieee80211_sta_restart+0x25/0x8c "
- "[mac80211]\n"
- "<5>[56279.703591] [<f8ddc752>] ? ieee80211_reconfig+0x2e9/0x339 "
- "[mac80211]\n"
- "<5>[56279.703605] [<f8dd4a33>] ? ieee80211_aes_cmac+0x182d/0x184e "
- "[mac80211]\n"
- "<5>[56279.703618] [<f87e0304>] ? "
- "cfg80211_get_dev_from_info+0x29b/0x2c0 [cfg80211]\n"
- "<5>[56279.703630] [<f87e02a4>] ? "
- "cfg80211_get_dev_from_info+0x23b/0x2c0 [cfg80211]\n"
- "<5>[56279.703637] [<81248968>] ? legacy_resume+0x25/0x5d\n"
- "<5>[56279.703643] [<812490ae>] ? device_resume+0xdd/0x110\n"
- "<5>[56279.703649] [<812491c2>] ? dpm_resume_end+0xe1/0x271\n"
- "<5>[56279.703657] [<81060481>] ? "
- "suspend_devices_and_enter+0x18b/0x1de\n"
- "<5>[56279.703663] [<810605ba>] ? enter_state+0xe6/0x132\n"
- "<5>[56279.703670] [<8105fd4b>] ? state_store+0x91/0x9d\n"
- "<5>[56279.703676] [<8105fcba>] ? state_store+0x0/0x9d\n"
- "<5>[56279.703683] [<81178fb1>] ? kobj_attr_store+0x16/0x22\n"
- "<5>[56279.703690] [<810eea5e>] ? sysfs_write_file+0xc1/0xec\n"
- "<5>[56279.703697] [<810af443>] ? vfs_write+0x8f/0x101\n"
- "<5>[56279.703703] [<810ee99d>] ? sysfs_write_file+0x0/0xec\n"
- "<5>[56279.703709] [<810af556>] ? sys_write+0x40/0x65\n"
- "<5>[56279.703716] [<81002d57>] ? sysenter_do_call+0x12/0x26\n";
-
- EXPECT_TRUE(
- collector_.ComputeKernelStackSignature(kUncertainStackTrace,
- &signature,
- false));
- // The first trace contains only uncertain entries and its hash is 00000000,
- // so, if we used that, the signature would be kernel-add_timer-00000000.
- // Instead we use the second-to-last trace for the hash.
- EXPECT_EQ("kernel-add_timer-B5178878", signature);
-
- ComputeKernelStackSignatureCommon();
-}
diff --git a/crash_reporter/kernel_collector_test.h b/crash_reporter/kernel_collector_test.h
deleted file mode 100644
index f689e7d..0000000
--- a/crash_reporter/kernel_collector_test.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2014 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.
- */
-
-#ifndef CRASH_REPORTER_KERNEL_COLLECTOR_TEST_H_
-#define CRASH_REPORTER_KERNEL_COLLECTOR_TEST_H_
-
-#include "kernel_collector.h"
-
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-
-class KernelCollectorMock : public KernelCollector {
- public:
- MOCK_METHOD0(DumpDirMounted, bool());
- MOCK_METHOD0(SetUpDBus, void());
-};
-
-#endif // CRASH_REPORTER_KERNEL_COLLECTOR_TEST_H_
diff --git a/crash_reporter/kernel_log_collector.sh b/crash_reporter/kernel_log_collector.sh
deleted file mode 100644
index 82512c2..0000000
--- a/crash_reporter/kernel_log_collector.sh
+++ /dev/null
@@ -1,59 +0,0 @@
-#!/bin/sh
-
-# Copyright (C) 2013 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.
-
-# Usage example: "kernel_log_collector.sh XXX YYY"
-# This script searches logs in the /var/log/messages which have the keyword XXX.
-# And only those logs which are within the last YYY seconds of the latest log
-# that has the keyword XXX are printed.
-
-# Kernel log has the possible formats:
-# 2013-06-14T16:31:40.514513-07:00 localhost kernel: [ 2.682472] MSG MSG ...
-# 2013-06-19T20:38:58.661826+00:00 localhost kernel: [ 1.668092] MSG MSG ...
-
-search_key=$1
-time_duration=$2
-msg_pattern="^[0-9-]*T[0-9:.+-]* localhost kernel"
-
-die() {
- echo "kernel_log_collector: $*" >&2
- exit 1
-}
-
-get_timestamp() {
- timestamp="$(echo $1 | cut -d " " -f 1)"
- timestamp="$(date -d "${timestamp}" +%s)" || exit $?
- echo "${timestamp}"
-}
-
-last_line=$(grep "${msg_pattern}" /var/log/messages | grep -- "${search_key}" | tail -n 1)
-
-if [ -n "${last_line}" ]; then
- if ! allowed_timestamp=$(get_timestamp "${last_line}"); then
- die "coule not get timestamp from: ${last_line}"
- fi
- : $(( allowed_timestamp -= ${time_duration} ))
- grep "${msg_pattern}" /var/log/messages | grep -- "${search_key}" | while read line; do
- if ! timestamp=$(get_timestamp "${line}"); then
- die "could not get timestamp from: ${line}"
- fi
- if [ ${timestamp} -gt ${allowed_timestamp} ]; then
- echo "${line}"
- fi
- done
-fi
-
-echo "END-OF-LOG"
-
diff --git a/crash_reporter/kernel_warning_collector.cc b/crash_reporter/kernel_warning_collector.cc
deleted file mode 100644
index e28e8fd..0000000
--- a/crash_reporter/kernel_warning_collector.cc
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright (C) 2012 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 "kernel_warning_collector.h"
-
-#include <base/files/file_util.h>
-#include <base/logging.h>
-#include <base/strings/string_number_conversions.h>
-#include <base/strings/string_util.h>
-#include <base/strings/stringprintf.h>
-
-namespace {
-const char kExecName[] = "kernel-warning";
-const char kKernelWarningSignatureKey[] = "sig";
-const char kKernelWarningPath[] = "/var/run/kwarn/warning";
-const pid_t kKernelPid = 0;
-const uid_t kRootUid = 0;
-} // namespace
-
-using base::FilePath;
-using base::StringPrintf;
-
-KernelWarningCollector::KernelWarningCollector() {
-}
-
-KernelWarningCollector::~KernelWarningCollector() {
-}
-
-bool KernelWarningCollector::LoadKernelWarning(std::string *content,
- std::string *signature) {
- FilePath kernel_warning_path(kKernelWarningPath);
- if (!base::ReadFileToString(kernel_warning_path, content)) {
- LOG(ERROR) << "Could not open " << kKernelWarningPath;
- return false;
- }
- // The signature is in the first line.
- std::string::size_type end_position = content->find('\n');
- if (end_position == std::string::npos) {
- LOG(ERROR) << "unexpected kernel warning format";
- return false;
- }
- *signature = content->substr(0, end_position);
- return true;
-}
-
-bool KernelWarningCollector::Collect() {
- std::string reason = "normal collection";
- bool feedback = true;
- if (IsDeveloperImage()) {
- reason = "always collect from developer builds";
- feedback = true;
- } else if (!is_feedback_allowed_function_()) {
- reason = "no user consent";
- feedback = false;
- }
-
- LOG(INFO) << "Processing kernel warning: " << reason;
-
- if (!feedback) {
- return true;
- }
-
- std::string kernel_warning;
- std::string warning_signature;
- if (!LoadKernelWarning(&kernel_warning, &warning_signature)) {
- return true;
- }
-
- FilePath root_crash_directory;
- if (!GetCreatedCrashDirectoryByEuid(kRootUid, &root_crash_directory,
- nullptr)) {
- return true;
- }
-
- std::string dump_basename =
- FormatDumpBasename(kExecName, time(nullptr), kKernelPid);
- FilePath kernel_crash_path = root_crash_directory.Append(
- StringPrintf("%s.kcrash", dump_basename.c_str()));
-
- // We must use WriteNewFile instead of base::WriteFile as we
- // do not want to write with root access to a symlink that an attacker
- // might have created.
- if (WriteNewFile(kernel_crash_path,
- kernel_warning.data(),
- kernel_warning.length()) !=
- static_cast<int>(kernel_warning.length())) {
- LOG(INFO) << "Failed to write kernel warning to "
- << kernel_crash_path.value().c_str();
- return true;
- }
-
- AddCrashMetaData(kKernelWarningSignatureKey, warning_signature);
- WriteCrashMetaData(
- root_crash_directory.Append(
- StringPrintf("%s.meta", dump_basename.c_str())),
- kExecName, kernel_crash_path.value());
-
- LOG(INFO) << "Stored kernel warning into " << kernel_crash_path.value();
- return true;
-}
diff --git a/crash_reporter/kernel_warning_collector.h b/crash_reporter/kernel_warning_collector.h
deleted file mode 100644
index 5ccb780..0000000
--- a/crash_reporter/kernel_warning_collector.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-
-#ifndef CRASH_REPORTER_KERNEL_WARNING_COLLECTOR_H_
-#define CRASH_REPORTER_KERNEL_WARNING_COLLECTOR_H_
-
-#include <string>
-
-#include <base/macros.h>
-#include <gtest/gtest_prod.h> // for FRIEND_TEST
-
-#include "crash_collector.h"
-
-// Kernel warning collector.
-class KernelWarningCollector : public CrashCollector {
- public:
- KernelWarningCollector();
-
- ~KernelWarningCollector() override;
-
- // Collects warning.
- bool Collect();
-
- private:
- friend class KernelWarningCollectorTest;
- FRIEND_TEST(KernelWarningCollectorTest, CollectOK);
-
- // Reads the full content of the kernel warn dump and its signature.
- bool LoadKernelWarning(std::string *content, std::string *signature);
-
- DISALLOW_COPY_AND_ASSIGN(KernelWarningCollector);
-};
-
-#endif // CRASH_REPORTER_KERNEL_WARNING_COLLECTOR_H_
diff --git a/crash_reporter/list_proxies.cc b/crash_reporter/list_proxies.cc
deleted file mode 100644
index 3374b5f..0000000
--- a/crash_reporter/list_proxies.cc
+++ /dev/null
@@ -1,302 +0,0 @@
-/*
- * Copyright (C) 2011 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 <sysexits.h>
-#include <unistd.h> // for isatty()
-
-#include <string>
-#include <vector>
-
-#include <base/cancelable_callback.h>
-#include <base/command_line.h>
-#include <base/files/file_util.h>
-#include <base/memory/weak_ptr.h>
-#include <base/strings/string_number_conversions.h>
-#include <base/strings/string_tokenizer.h>
-#include <base/strings/string_util.h>
-#include <base/values.h>
-#include <brillo/daemons/dbus_daemon.h>
-#include <brillo/syslog_logging.h>
-
-#include "libcrosservice/dbus-proxies.h"
-
-using std::unique_ptr;
-
-namespace {
-
-const char kLibCrosProxyResolvedSignalInterface[] =
- "org.chromium.CrashReporterLibcrosProxyResolvedInterface";
-const char kLibCrosProxyResolvedName[] = "ProxyResolved";
-const char kLibCrosServiceName[] = "org.chromium.LibCrosService";
-const char kNoProxy[] = "direct://";
-
-const int kTimeoutDefaultSeconds = 5;
-
-const char kHelp[] = "help";
-const char kQuiet[] = "quiet";
-const char kTimeout[] = "timeout";
-const char kVerbose[] = "verbose";
-// Help message to show when the --help command line switch is specified.
-const char kHelpMessage[] =
- "Chromium OS Crash helper: proxy lister\n"
- "\n"
- "Available Switches:\n"
- " --quiet Only print the proxies\n"
- " --verbose Print additional messages even when not run from a TTY\n"
- " --timeout=N Set timeout for browser resolving proxies (default is 5)\n"
- " --help Show this help.\n";
-
-// Copied from src/update_engine/chrome_browser_proxy_resolver.cc
-// Parses the browser's answer for resolved proxies. It returns a
-// list of strings, each of which is a resolved proxy.
-std::vector<std::string> ParseProxyString(const std::string& input) {
- std::vector<std::string> ret;
- // Some of this code taken from
- // http://src.chromium.org/svn/trunk/src/net/proxy/proxy_server.cc and
- // http://src.chromium.org/svn/trunk/src/net/proxy/proxy_list.cc
- base::StringTokenizer entry_tok(input, ";");
- while (entry_tok.GetNext()) {
- std::string token = entry_tok.token();
- base::TrimWhitespaceASCII(token, base::TRIM_ALL, &token);
-
- // Start by finding the first space (if any).
- std::string::iterator space;
- for (space = token.begin(); space != token.end(); ++space) {
- if (base::IsAsciiWhitespace(*space)) {
- break;
- }
- }
-
- std::string scheme = base::ToLowerASCII(std::string(token.begin(), space));
- // Chrome uses "socks" to mean socks4 and "proxy" to mean http.
- if (scheme == "socks")
- scheme += "4";
- else if (scheme == "proxy")
- scheme = "http";
- else if (scheme != "https" &&
- scheme != "socks4" &&
- scheme != "socks5" &&
- scheme != "direct")
- continue; // Invalid proxy scheme
-
- std::string host_and_port = std::string(space, token.end());
- base::TrimWhitespaceASCII(host_and_port, base::TRIM_ALL, &host_and_port);
- if (scheme != "direct" && host_and_port.empty())
- continue; // Must supply host/port when non-direct proxy used.
- ret.push_back(scheme + "://" + host_and_port);
- }
- if (ret.empty() || *ret.rbegin() != kNoProxy)
- ret.push_back(kNoProxy);
- return ret;
-}
-
-// A class for interfacing with Chrome to resolve proxies for a given source
-// url. The class is initialized with the given source url to check, the
-// signal interface and name that Chrome will reply to, and how long to wait
-// for the resolve request to timeout. Once initialized, the Run() function
-// must be called, which blocks on the D-Bus call to Chrome. The call returns
-// after either the timeout or the proxy has been resolved. The resolved
-// proxies can then be accessed through the proxies() function.
-class ProxyResolver : public brillo::DBusDaemon {
- public:
- ProxyResolver(const std::string& source_url,
- const std::string& signal_interface,
- const std::string& signal_name,
- base::TimeDelta timeout)
- : source_url_(source_url),
- signal_interface_(signal_interface),
- signal_name_(signal_name),
- timeout_(timeout),
- weak_ptr_factory_(this),
- timeout_callback_(base::Bind(&ProxyResolver::HandleBrowserTimeout,
- weak_ptr_factory_.GetWeakPtr())) {}
-
- ~ProxyResolver() override {}
-
- const std::vector<std::string>& proxies() {
- return proxies_;
- }
-
- int Run() override {
- // Add task for if the browser proxy call times out.
- base::MessageLoop::current()->PostDelayedTask(
- FROM_HERE,
- timeout_callback_.callback(),
- timeout_);
-
- return brillo::DBusDaemon::Run();
- }
-
- protected:
- // If the browser times out, quit the run loop.
- void HandleBrowserTimeout() {
- LOG(ERROR) << "Timeout while waiting for browser to resolve proxy";
- Quit();
- }
-
- // If the signal handler connects successfully, call the browser's
- // ResolveNetworkProxy D-Bus method. Otherwise, don't do anything and let
- // the timeout task quit the run loop.
- void HandleDBusSignalConnected(const std::string& interface,
- const std::string& signal,
- bool success) {
- if (!success) {
- LOG(ERROR) << "Could not connect to signal " << interface << "."
- << signal;
- timeout_callback_.Cancel();
- Quit();
- return;
- }
-
- brillo::ErrorPtr error;
- call_proxy_->ResolveNetworkProxy(source_url_,
- signal_interface_,
- signal_name_,
- &error);
-
- if (error) {
- LOG(ERROR) << "Call to ResolveNetworkProxy failed: "
- << error->GetMessage();
- timeout_callback_.Cancel();
- Quit();
- }
- }
-
- // Handle incoming ProxyResolved signal.
- void HandleProxyResolvedSignal(const std::string& source_url,
- const std::string& proxy_info,
- const std::string& error_message) {
- timeout_callback_.Cancel();
- proxies_ = ParseProxyString(proxy_info);
- LOG(INFO) << "Found proxies via browser signal: "
- << base::JoinString(proxies_, "x");
-
- Quit();
- }
-
- int OnInit() override {
- int return_code = brillo::DBusDaemon::OnInit();
- if (return_code != EX_OK)
- return return_code;
-
- // Initialize D-Bus proxies.
- call_proxy_.reset(
- new org::chromium::LibCrosServiceInterfaceProxy(bus_,
- kLibCrosServiceName));
- signal_proxy_.reset(
- new org::chromium::CrashReporterLibcrosProxyResolvedInterfaceProxy(
- bus_,
- kLibCrosServiceName));
-
- // Set up the D-Bus signal handler.
- // TODO(crbug.com/446115): Update ResolveNetworkProxy call to use an
- // asynchronous return value rather than a return signal.
- signal_proxy_->RegisterProxyResolvedSignalHandler(
- base::Bind(&ProxyResolver::HandleProxyResolvedSignal,
- weak_ptr_factory_.GetWeakPtr()),
- base::Bind(&ProxyResolver::HandleDBusSignalConnected,
- weak_ptr_factory_.GetWeakPtr()));
-
- return EX_OK;
- }
-
- private:
- unique_ptr<org::chromium::LibCrosServiceInterfaceProxy> call_proxy_;
- unique_ptr<org::chromium::CrashReporterLibcrosProxyResolvedInterfaceProxy>
- signal_proxy_;
-
- const std::string source_url_;
- const std::string signal_interface_;
- const std::string signal_name_;
- base::TimeDelta timeout_;
-
- std::vector<std::string> proxies_;
- base::WeakPtrFactory<ProxyResolver> weak_ptr_factory_;
-
- base::CancelableClosure timeout_callback_;
-
- DISALLOW_COPY_AND_ASSIGN(ProxyResolver);
-};
-
-static bool ShowBrowserProxies(std::string url, base::TimeDelta timeout) {
- // Initialize and run the proxy resolver to watch for signals.
- ProxyResolver resolver(url,
- kLibCrosProxyResolvedSignalInterface,
- kLibCrosProxyResolvedName,
- timeout);
- resolver.Run();
-
- std::vector<std::string> proxies = resolver.proxies();
-
- // If proxies is empty, then the timeout was reached waiting for the proxy
- // resolved signal. If no proxies are defined, proxies will be populated
- // with "direct://".
- if (proxies.empty())
- return false;
-
- for (const auto& proxy : proxies) {
- printf("%s\n", proxy.c_str());
- }
- return true;
-}
-
-} // namespace
-
-int main(int argc, char *argv[]) {
- base::CommandLine::Init(argc, argv);
- base::CommandLine* cl = base::CommandLine::ForCurrentProcess();
-
- if (cl->HasSwitch(kHelp)) {
- LOG(INFO) << kHelpMessage;
- return 0;
- }
-
- bool quiet = cl->HasSwitch(kQuiet);
- bool verbose = cl->HasSwitch(kVerbose);
-
- int timeout = kTimeoutDefaultSeconds;
- std::string str_timeout = cl->GetSwitchValueASCII(kTimeout);
- if (!str_timeout.empty() && !base::StringToInt(str_timeout, &timeout)) {
- LOG(ERROR) << "Invalid timeout value: " << str_timeout;
- return 1;
- }
-
- // Default to logging to syslog.
- int init_flags = brillo::kLogToSyslog;
- // Log to stderr if a TTY (and "-quiet" wasn't passed), or if "-verbose"
- // was passed.
-
- if ((!quiet && isatty(STDERR_FILENO)) || verbose)
- init_flags |= brillo::kLogToStderr;
- brillo::InitLog(init_flags);
-
- std::string url;
- base::CommandLine::StringVector urls = cl->GetArgs();
- if (!urls.empty()) {
- url = urls[0];
- LOG(INFO) << "Resolving proxies for URL: " << url;
- } else {
- LOG(INFO) << "Resolving proxies without URL";
- }
-
- if (!ShowBrowserProxies(url, base::TimeDelta::FromSeconds(timeout))) {
- LOG(ERROR) << "Error resolving proxies via the browser";
- LOG(INFO) << "Assuming direct proxy";
- printf("%s\n", kNoProxy);
- }
-
- return 0;
-}
diff --git a/crash_reporter/periodic_scheduler b/crash_reporter/periodic_scheduler
deleted file mode 100755
index 5408da7..0000000
--- a/crash_reporter/periodic_scheduler
+++ /dev/null
@@ -1,80 +0,0 @@
-#!/system/bin/sh
-
-# Copyright (C) 2014 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.
-
-# Run tasks periodically.
-# Usage: $0 <delay_seconds> <timeout_seconds> <task_name> <task_binary>
-#
-# Executes task <task_name> by running <task_binary> every <delay_seconds>.
-
-set -e -u
-
-SCRIPT_NAME="$(basename "$0")"
-CHECK_DELAY=300 # Check every 5 minutes.
-KILL_DELAY=10 # How long to let the job clean up after a timeout.
-# Let the unittests override.
-: ${SPOOL_DIR:=/data/misc/crash_reporter/spool/cron-lite}
-
-loginfo() {
- log -p i -t "${SCRIPT_NAME}" "$@"
-}
-
-trap "loginfo 'exiting'" EXIT
-
-check_and_fix_spool_paths() {
- # Avoid weird spool paths if possible.
- rm -f "$(dirname "${SPOOL_DIR}")" "${SPOOL_DIR}" 2>/dev/null || :
- mkdir -p "${SPOOL_DIR}"
- if [ ! -O "${SPOOL_DIR}" -o ! -d "${SPOOL_DIR}" ]; then
- loginfo "Spool directory is damaged. Aborting!"
- exit 1
- fi
-}
-
-main() {
- local delay="$1"
- local timeout="$2"
- local name="$3"
- local spool_file="${SPOOL_DIR}/${name}"
- shift 3
-
- [ -z "${delay}" ] && exit 1
- [ -z "${timeout}" ] && exit 1
- [ -z "${name}" ] && exit 1
- [ $# -eq 0 ] && exit 1
- check_and_fix_spool_paths
-
- while true; do
- # Allow the sleep to be killed manually without terminating the handler.
- # Send stderr to /dev/null to suppress the shell's "Terminated" message.
- sleep $(( CHECK_DELAY + KILL_DELAY )) 2>/dev/null || true
-
- [ ! -e "${spool_file}" ] && touch "${spool_file}"
-
- local last_rotation="$(stat -c "%Y" "${spool_file}" 2>/dev/null || echo 0)"
- local now="$(date +%s)"
- local time_diff=$((now - last_rotation))
-
- if [ ${time_diff} -gt ${delay} ]; then
- rm "${spool_file}" || true
- touch "${spool_file}"
- loginfo "${name}: running $*"
- timeout -k ${KILL_DELAY} ${timeout} "$@" || true
- loginfo "${name}: job completed"
- fi
- done
-}
-
-main "$@"
diff --git a/crash_reporter/testrunner.cc b/crash_reporter/testrunner.cc
deleted file mode 100644
index 744cf10..0000000
--- a/crash_reporter/testrunner.cc
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2015 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 <brillo/test_helpers.h>
-#include <gtest/gtest.h>
-
-int main(int argc, char** argv) {
- SetUpTests(&argc, argv, true);
- return RUN_ALL_TESTS();
-}
diff --git a/crash_reporter/udev_collector.cc b/crash_reporter/udev_collector.cc
deleted file mode 100644
index 1e018db..0000000
--- a/crash_reporter/udev_collector.cc
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
- * Copyright (C) 2012 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 "udev_collector.h"
-
-#include <map>
-#include <utility>
-#include <vector>
-
-#include <base/files/file_enumerator.h>
-#include <base/files/file_util.h>
-#include <base/logging.h>
-#include <base/strings/string_number_conversions.h>
-#include <base/strings/string_split.h>
-#include <base/strings/string_util.h>
-#include <base/strings/stringprintf.h>
-#include <brillo/process.h>
-
-using base::FilePath;
-
-namespace {
-
-const char kCollectUdevSignature[] = "crash_reporter-udev-collection";
-const char kGzipPath[] = "/bin/gzip";
-const char kUdevExecName[] = "udev";
-const char kUdevSignatureKey[] = "sig";
-const char kUdevSubsystemDevCoredump[] = "devcoredump";
-const char kDefaultDevCoredumpDirectory[] = "/sys/class/devcoredump";
-const char kDevCoredumpFilePrefixFormat[] = "devcoredump_%s";
-
-} // namespace
-
-UdevCollector::UdevCollector()
- : dev_coredump_directory_(kDefaultDevCoredumpDirectory) {}
-
-UdevCollector::~UdevCollector() {}
-
-bool UdevCollector::HandleCrash(const std::string &udev_event) {
- if (IsDeveloperImage()) {
- LOG(INFO) << "developer image - collect udev crash info.";
- } else if (is_feedback_allowed_function_()) {
- LOG(INFO) << "Consent given - collect udev crash info.";
- } else {
- LOG(INFO) << "Ignoring - Non-developer image and no consent given.";
- return false;
- }
-
- // Process the udev event string.
- // First get all the key-value pairs.
- std::vector<std::pair<std::string, std::string>> udev_event_keyval;
- base::SplitStringIntoKeyValuePairs(udev_event, '=', ':', &udev_event_keyval);
- std::vector<std::pair<std::string, std::string>>::const_iterator iter;
- std::map<std::string, std::string> udev_event_map;
- for (iter = udev_event_keyval.begin();
- iter != udev_event_keyval.end();
- ++iter) {
- udev_event_map[iter->first] = iter->second;
- }
-
- // Make sure the crash directory exists, or create it if it doesn't.
- FilePath crash_directory;
- if (!GetCreatedCrashDirectoryByEuid(0, &crash_directory, nullptr)) {
- LOG(ERROR) << "Could not get crash directory.";
- return false;
- }
-
- if (udev_event_map["SUBSYSTEM"] == kUdevSubsystemDevCoredump) {
- int instance_number;
- if (!base::StringToInt(udev_event_map["KERNEL_NUMBER"], &instance_number)) {
- LOG(ERROR) << "Invalid kernel number: "
- << udev_event_map["KERNEL_NUMBER"];
- return false;
- }
- return ProcessDevCoredump(crash_directory, instance_number);
- }
-
- return ProcessUdevCrashLogs(crash_directory,
- udev_event_map["ACTION"],
- udev_event_map["KERNEL"],
- udev_event_map["SUBSYSTEM"]);
-}
-
-bool UdevCollector::ProcessUdevCrashLogs(const FilePath& crash_directory,
- const std::string& action,
- const std::string& kernel,
- const std::string& subsystem) {
- // Construct the basename string for crash_reporter_logs.conf:
- // "crash_reporter-udev-collection-[action]-[name]-[subsystem]"
- // If a udev field is not provided, "" is used in its place, e.g.:
- // "crash_reporter-udev-collection-[action]--[subsystem]"
- // Hence, "" is used as a wildcard name string.
- // TODO(sque, crosbug.com/32238): Implement wildcard checking.
- std::string basename = action + "-" + kernel + "-" + subsystem;
- std::string udev_log_name = std::string(kCollectUdevSignature) + '-' +
- basename;
-
- // Create the destination path.
- std::string log_file_name =
- FormatDumpBasename(basename, time(nullptr), 0);
- FilePath crash_path = GetCrashPath(crash_directory, log_file_name, "log");
-
- // Handle the crash.
- bool result = GetLogContents(log_config_path_, udev_log_name, crash_path);
- if (!result) {
- LOG(ERROR) << "Error reading udev log info " << udev_log_name;
- return false;
- }
-
- // Compress the output using gzip.
- brillo::ProcessImpl gzip_process;
- gzip_process.AddArg(kGzipPath);
- gzip_process.AddArg(crash_path.value());
- int process_result = gzip_process.Run();
- FilePath crash_path_zipped = FilePath(crash_path.value() + ".gz");
- // If the zip file was not created, use the uncompressed file.
- if (process_result != 0 || !base::PathExists(crash_path_zipped))
- LOG(ERROR) << "Could not create zip file " << crash_path_zipped.value();
- else
- crash_path = crash_path_zipped;
-
- std::string exec_name = std::string(kUdevExecName) + "-" + subsystem;
- AddCrashMetaData(kUdevSignatureKey, udev_log_name);
- WriteCrashMetaData(GetCrashPath(crash_directory, log_file_name, "meta"),
- exec_name, crash_path.value());
- return true;
-}
-
-bool UdevCollector::ProcessDevCoredump(const FilePath& crash_directory,
- int instance_number) {
- FilePath coredump_path =
- FilePath(base::StringPrintf("%s/devcd%d/data",
- dev_coredump_directory_.c_str(),
- instance_number));
- if (!base::PathExists(coredump_path)) {
- LOG(ERROR) << "Device coredump file " << coredump_path.value()
- << " does not exist";
- return false;
- }
-
- // Add coredump file to the crash directory.
- if (!AppendDevCoredump(crash_directory, coredump_path, instance_number)) {
- ClearDevCoredump(coredump_path);
- return false;
- }
-
- // Clear the coredump data to allow generation of future device coredumps
- // without having to wait for the 5-minutes timeout.
- return ClearDevCoredump(coredump_path);
-}
-
-bool UdevCollector::AppendDevCoredump(const FilePath& crash_directory,
- const FilePath& coredump_path,
- int instance_number) {
- // Retrieve the driver name of the failing device.
- std::string driver_name = GetFailingDeviceDriverName(instance_number);
- if (driver_name.empty()) {
- LOG(ERROR) << "Failed to obtain driver name for instance: "
- << instance_number;
- return false;
- }
-
- std::string coredump_prefix =
- base::StringPrintf(kDevCoredumpFilePrefixFormat, driver_name.c_str());
-
- std::string dump_basename = FormatDumpBasename(coredump_prefix,
- time(nullptr),
- instance_number);
- FilePath core_path = GetCrashPath(crash_directory, dump_basename, "devcore");
- FilePath log_path = GetCrashPath(crash_directory, dump_basename, "log");
- FilePath meta_path = GetCrashPath(crash_directory, dump_basename, "meta");
-
- // Collect coredump data.
- if (!base::CopyFile(coredump_path, core_path)) {
- LOG(ERROR) << "Failed to copy device coredumpm file from "
- << coredump_path.value() << " to " << core_path.value();
- return false;
- }
-
- // Collect additional logs if one is specified in the config file.
- std::string udev_log_name = std::string(kCollectUdevSignature) + '-' +
- kUdevSubsystemDevCoredump + '-' + driver_name;
- bool result = GetLogContents(log_config_path_, udev_log_name, log_path);
- if (result) {
- AddCrashMetaUploadFile("logs", log_path.value());
- }
-
- WriteCrashMetaData(meta_path, coredump_prefix, core_path.value());
-
- return true;
-}
-
-bool UdevCollector::ClearDevCoredump(const FilePath& coredump_path) {
- if (!base::WriteFile(coredump_path, "0", 1)) {
- LOG(ERROR) << "Failed to delete the coredump data file "
- << coredump_path.value();
- return false;
- }
- return true;
-}
-
-std::string UdevCollector::GetFailingDeviceDriverName(int instance_number) {
- FilePath failing_uevent_path =
- FilePath(base::StringPrintf("%s/devcd%d/failing_device/uevent",
- dev_coredump_directory_.c_str(),
- instance_number));
- if (!base::PathExists(failing_uevent_path)) {
- LOG(ERROR) << "Failing uevent path " << failing_uevent_path.value()
- << " does not exist";
- return "";
- }
-
- std::string uevent_content;
- if (!base::ReadFileToString(failing_uevent_path, &uevent_content)) {
- LOG(ERROR) << "Failed to read uevent file " << failing_uevent_path.value();
- return "";
- }
-
- // Parse uevent file contents as key-value pairs.
- std::vector<std::pair<std::string, std::string>> uevent_keyval;
- base::SplitStringIntoKeyValuePairs(uevent_content, '=', '\n', &uevent_keyval);
- std::vector<std::pair<std::string, std::string>>::const_iterator iter;
- for (iter = uevent_keyval.begin();
- iter != uevent_keyval.end();
- ++iter) {
- if (iter->first == "DRIVER") {
- return iter->second;
- }
- }
-
- return "";
-}
diff --git a/crash_reporter/udev_collector.h b/crash_reporter/udev_collector.h
deleted file mode 100644
index e267b75..0000000
--- a/crash_reporter/udev_collector.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2012 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.
- */
-
-#ifndef CRASH_REPORTER_UDEV_COLLECTOR_H_
-#define CRASH_REPORTER_UDEV_COLLECTOR_H_
-
-#include <string>
-
-#include <base/files/file_path.h>
-#include <base/macros.h>
-#include <gtest/gtest_prod.h> // for FRIEND_TEST
-
-#include "crash_collector.h"
-
-// Udev crash collector.
-class UdevCollector : public CrashCollector {
- public:
- UdevCollector();
-
- ~UdevCollector() override;
-
- // The udev event string should be formatted as follows:
- // "ACTION=[action]:KERNEL=[name]:SUBSYSTEM=[subsystem]"
- // The values don't have to be in any particular order. One or more of them
- // could be omitted, in which case it would be treated as a wildcard (*).
- bool HandleCrash(const std::string& udev_event);
-
- protected:
- std::string dev_coredump_directory_;
-
- private:
- friend class UdevCollectorTest;
-
- // Process udev crash logs, collecting log files according to the config
- // file (crash_reporter_logs.conf).
- bool ProcessUdevCrashLogs(const base::FilePath& crash_directory,
- const std::string& action,
- const std::string& kernel,
- const std::string& subsystem);
- // Process device coredump, collecting device coredump file.
- // |instance_number| is the kernel number of the virtual device for the device
- // coredump instance.
- bool ProcessDevCoredump(const base::FilePath& crash_directory,
- int instance_number);
- // Copy device coredump file to crash directory, and perform necessary
- // coredump file management.
- bool AppendDevCoredump(const base::FilePath& crash_directory,
- const base::FilePath& coredump_path,
- int instance_number);
- // Clear the device coredump file by performing a dummy write to it.
- bool ClearDevCoredump(const base::FilePath& coredump_path);
- // Return the driver name of the device that generates the coredump.
- std::string GetFailingDeviceDriverName(int instance_number);
-
- // Mutator for unit testing.
- void set_log_config_path(const std::string& path) {
- log_config_path_ = base::FilePath(path);
- }
-
- DISALLOW_COPY_AND_ASSIGN(UdevCollector);
-};
-
-#endif // CRASH_REPORTER_UDEV_COLLECTOR_H_
diff --git a/crash_reporter/udev_collector_test.cc b/crash_reporter/udev_collector_test.cc
deleted file mode 100644
index 5474f48..0000000
--- a/crash_reporter/udev_collector_test.cc
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * Copyright (C) 2012 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 <base/files/file_enumerator.h>
-#include <base/files/file_util.h>
-#include <base/files/scoped_temp_dir.h>
-#include <base/strings/stringprintf.h>
-#include <brillo/syslog_logging.h>
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-
-#include "udev_collector.h"
-
-using base::FilePath;
-
-namespace {
-
-// Dummy log config file name.
-const char kLogConfigFileName[] = "log_config_file";
-
-// Dummy directory for storing device coredumps.
-const char kDevCoredumpDirectory[] = "devcoredump";
-
-// A bunch of random rules to put into the dummy log config file.
-const char kLogConfigFileContents[] =
- "crash_reporter-udev-collection-change-card0-drm=echo change card0 drm\n"
- "crash_reporter-udev-collection-add-state0-cpu=echo change state0 cpu\n"
- "crash_reporter-udev-collection-devcoredump-iwlwifi=echo devcoredump\n"
- "cros_installer=echo not for udev";
-
-const char kCrashLogFilePattern[] = "*.log.gz";
-const char kDevCoredumpFilePattern[] = "*.devcore";
-
-// Dummy content for device coredump data file.
-const char kDevCoredumpDataContents[] = "coredump";
-
-// Content for failing device's uevent file.
-const char kFailingDeviceUeventContents[] = "DRIVER=iwlwifi\n";
-
-void CountCrash() {}
-
-bool s_consent_given = true;
-
-bool IsMetrics() {
- return s_consent_given;
-}
-
-// Returns the number of files found in the given path that matches the
-// specified file name pattern.
-int GetNumFiles(const FilePath& path, const std::string& file_pattern) {
- base::FileEnumerator enumerator(path, false, base::FileEnumerator::FILES,
- file_pattern);
- int num_files = 0;
- for (FilePath file_path = enumerator.Next();
- !file_path.value().empty();
- file_path = enumerator.Next()) {
- num_files++;
- }
- return num_files;
-}
-
-} // namespace
-
-class UdevCollectorMock : public UdevCollector {
- public:
- MOCK_METHOD0(SetUpDBus, void());
-};
-
-class UdevCollectorTest : public ::testing::Test {
- protected:
- base::ScopedTempDir temp_dir_generator_;
-
- void HandleCrash(const std::string &udev_event) {
- collector_.HandleCrash(udev_event);
- }
-
- void GenerateDevCoredump(const std::string& device_name) {
- // Generate coredump data file.
- ASSERT_TRUE(CreateDirectory(
- FilePath(base::StringPrintf("%s/%s",
- collector_.dev_coredump_directory_.c_str(),
- device_name.c_str()))));
- FilePath data_path =
- FilePath(base::StringPrintf("%s/%s/data",
- collector_.dev_coredump_directory_.c_str(),
- device_name.c_str()));
- ASSERT_EQ(strlen(kDevCoredumpDataContents),
- base::WriteFile(data_path,
- kDevCoredumpDataContents,
- strlen(kDevCoredumpDataContents)));
- // Generate uevent file for failing device.
- ASSERT_TRUE(CreateDirectory(
- FilePath(base::StringPrintf("%s/%s/failing_device",
- collector_.dev_coredump_directory_.c_str(),
- device_name.c_str()))));
- FilePath uevent_path =
- FilePath(base::StringPrintf("%s/%s/failing_device/uevent",
- collector_.dev_coredump_directory_.c_str(),
- device_name.c_str()));
- ASSERT_EQ(strlen(kFailingDeviceUeventContents),
- base::WriteFile(uevent_path,
- kFailingDeviceUeventContents,
- strlen(kFailingDeviceUeventContents)));
- }
-
- private:
- void SetUp() override {
- s_consent_given = true;
-
- EXPECT_CALL(collector_, SetUpDBus()).WillRepeatedly(testing::Return());
-
- collector_.Initialize(CountCrash, IsMetrics);
-
- ASSERT_TRUE(temp_dir_generator_.CreateUniqueTempDir());
-
- FilePath log_config_path =
- temp_dir_generator_.path().Append(kLogConfigFileName);
- collector_.log_config_path_ = log_config_path;
- collector_.ForceCrashDirectory(temp_dir_generator_.path());
-
- FilePath dev_coredump_path =
- temp_dir_generator_.path().Append(kDevCoredumpDirectory);
- collector_.dev_coredump_directory_ = dev_coredump_path.value();
-
- // Write to a dummy log config file.
- ASSERT_EQ(strlen(kLogConfigFileContents),
- base::WriteFile(log_config_path,
- kLogConfigFileContents,
- strlen(kLogConfigFileContents)));
-
- brillo::ClearLog();
- }
-
- UdevCollectorMock collector_;
-};
-
-TEST_F(UdevCollectorTest, TestNoConsent) {
- s_consent_given = false;
- HandleCrash("ACTION=change:KERNEL=card0:SUBSYSTEM=drm");
- EXPECT_EQ(0, GetNumFiles(temp_dir_generator_.path(), kCrashLogFilePattern));
-}
-
-TEST_F(UdevCollectorTest, TestNoMatch) {
- // No rule should match this.
- HandleCrash("ACTION=change:KERNEL=foo:SUBSYSTEM=bar");
- EXPECT_EQ(0, GetNumFiles(temp_dir_generator_.path(), kCrashLogFilePattern));
-}
-
-TEST_F(UdevCollectorTest, TestMatches) {
- // Try multiple udev events in sequence. The number of log files generated
- // should increase.
- HandleCrash("ACTION=change:KERNEL=card0:SUBSYSTEM=drm");
- EXPECT_EQ(1, GetNumFiles(temp_dir_generator_.path(), kCrashLogFilePattern));
- HandleCrash("ACTION=add:KERNEL=state0:SUBSYSTEM=cpu");
- EXPECT_EQ(2, GetNumFiles(temp_dir_generator_.path(), kCrashLogFilePattern));
-}
-
-TEST_F(UdevCollectorTest, TestDevCoredump) {
- GenerateDevCoredump("devcd0");
- HandleCrash("ACTION=add:KERNEL_NUMBER=0:SUBSYSTEM=devcoredump");
- EXPECT_EQ(1, GetNumFiles(temp_dir_generator_.path(),
- kDevCoredumpFilePattern));
- GenerateDevCoredump("devcd1");
- HandleCrash("ACTION=add:KERNEL_NUMBER=1:SUBSYSTEM=devcoredump");
- EXPECT_EQ(2, GetNumFiles(temp_dir_generator_.path(),
- kDevCoredumpFilePattern));
-}
-
-// TODO(sque, crosbug.com/32238) - test wildcard cases, multiple identical udev
-// events.
diff --git a/crash_reporter/unclean_shutdown_collector.cc b/crash_reporter/unclean_shutdown_collector.cc
deleted file mode 100644
index 8a092ec..0000000
--- a/crash_reporter/unclean_shutdown_collector.cc
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (C) 2010 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 "unclean_shutdown_collector.h"
-
-#include <base/files/file_util.h>
-#include <base/logging.h>
-
-static const char kUncleanShutdownFile[] =
- "/var/lib/crash_reporter/pending_clean_shutdown";
-
-// Files created by power manager used for crash reporting.
-static const char kPowerdTracePath[] = "/var/lib/power_manager";
-// Presence of this file indicates that the system was suspended
-static const char kPowerdSuspended[] = "powerd_suspended";
-
-using base::FilePath;
-
-UncleanShutdownCollector::UncleanShutdownCollector()
- : unclean_shutdown_file_(kUncleanShutdownFile),
- powerd_trace_path_(kPowerdTracePath),
- powerd_suspended_file_(powerd_trace_path_.Append(kPowerdSuspended)) {
-}
-
-UncleanShutdownCollector::~UncleanShutdownCollector() {
-}
-
-bool UncleanShutdownCollector::Enable() {
- FilePath file_path(unclean_shutdown_file_);
- base::CreateDirectory(file_path.DirName());
- if (base::WriteFile(file_path, "", 0) != 0) {
- LOG(ERROR) << "Unable to create shutdown check file";
- return false;
- }
- return true;
-}
-
-bool UncleanShutdownCollector::DeleteUncleanShutdownFiles() {
- if (!base::DeleteFile(FilePath(unclean_shutdown_file_), false)) {
- LOG(ERROR) << "Failed to delete unclean shutdown file "
- << unclean_shutdown_file_;
- return false;
- }
- // Delete power manager state file if it exists.
- base::DeleteFile(powerd_suspended_file_, false);
- return true;
-}
-
-bool UncleanShutdownCollector::Collect() {
- FilePath unclean_file_path(unclean_shutdown_file_);
- if (!base::PathExists(unclean_file_path)) {
- return false;
- }
- LOG(WARNING) << "Last shutdown was not clean";
- if (DeadBatteryCausedUncleanShutdown()) {
- DeleteUncleanShutdownFiles();
- return false;
- }
- DeleteUncleanShutdownFiles();
-
- if (is_feedback_allowed_function_()) {
- count_crash_function_();
- }
- return true;
-}
-
-bool UncleanShutdownCollector::Disable() {
- LOG(INFO) << "Clean shutdown signalled";
- return DeleteUncleanShutdownFiles();
-}
-
-bool UncleanShutdownCollector::DeadBatteryCausedUncleanShutdown() {
- // Check for case of battery running out while suspended.
- if (base::PathExists(powerd_suspended_file_)) {
- LOG(INFO) << "Unclean shutdown occurred while suspended. Not counting "
- << "toward unclean shutdown statistic.";
- return true;
- }
- return false;
-}
diff --git a/crash_reporter/unclean_shutdown_collector.h b/crash_reporter/unclean_shutdown_collector.h
deleted file mode 100644
index 5bc9968..0000000
--- a/crash_reporter/unclean_shutdown_collector.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2010 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.
- */
-
-#ifndef CRASH_REPORTER_UNCLEAN_SHUTDOWN_COLLECTOR_H_
-#define CRASH_REPORTER_UNCLEAN_SHUTDOWN_COLLECTOR_H_
-
-#include <string>
-
-#include <base/files/file_path.h>
-#include <base/macros.h>
-#include <gtest/gtest_prod.h> // for FRIEND_TEST
-
-#include "crash_collector.h"
-
-// Unclean shutdown collector.
-class UncleanShutdownCollector : public CrashCollector {
- public:
- UncleanShutdownCollector();
- ~UncleanShutdownCollector() override;
-
- // Enable collection - signal that a boot has started.
- bool Enable();
-
- // Collect if there is was an unclean shutdown. Returns true if
- // there was, false otherwise.
- bool Collect();
-
- // Disable collection - signal that the system has been shutdown cleanly.
- bool Disable();
-
- private:
- friend class UncleanShutdownCollectorTest;
- FRIEND_TEST(UncleanShutdownCollectorTest, EnableCannotWrite);
- FRIEND_TEST(UncleanShutdownCollectorTest, CollectDeadBatterySuspended);
-
- bool DeleteUncleanShutdownFiles();
-
- // Check for unclean shutdown due to battery running out by analyzing powerd
- // trace files.
- bool DeadBatteryCausedUncleanShutdown();
-
- const char *unclean_shutdown_file_;
- base::FilePath powerd_trace_path_;
- base::FilePath powerd_suspended_file_;
-
- DISALLOW_COPY_AND_ASSIGN(UncleanShutdownCollector);
-};
-
-#endif // CRASH_REPORTER_UNCLEAN_SHUTDOWN_COLLECTOR_H_
diff --git a/crash_reporter/unclean_shutdown_collector_test.cc b/crash_reporter/unclean_shutdown_collector_test.cc
deleted file mode 100644
index 36372ae..0000000
--- a/crash_reporter/unclean_shutdown_collector_test.cc
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Copyright (C) 2010 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 "unclean_shutdown_collector.h"
-
-#include <unistd.h>
-
-#include <base/files/file_util.h>
-#include <base/files/scoped_temp_dir.h>
-#include <base/strings/string_util.h>
-#include <brillo/syslog_logging.h>
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-
-using base::FilePath;
-using ::brillo::FindLog;
-
-namespace {
-
-int s_crashes = 0;
-bool s_metrics = true;
-
-void CountCrash() {
- ++s_crashes;
-}
-
-bool IsMetrics() {
- return s_metrics;
-}
-
-} // namespace
-
-class UncleanShutdownCollectorMock : public UncleanShutdownCollector {
- public:
- MOCK_METHOD0(SetUpDBus, void());
-};
-
-class UncleanShutdownCollectorTest : public ::testing::Test {
- void SetUp() {
- s_crashes = 0;
-
- EXPECT_CALL(collector_, SetUpDBus()).WillRepeatedly(testing::Return());
-
- collector_.Initialize(CountCrash,
- IsMetrics);
-
- EXPECT_TRUE(test_dir_.CreateUniqueTempDir());
-
- test_directory_ = test_dir_.path().Append("test");
- test_unclean_ = test_dir_.path().Append("test/unclean");
-
- collector_.unclean_shutdown_file_ = test_unclean_.value().c_str();
- base::DeleteFile(test_unclean_, true);
- // Set up an alternate power manager state file as well
- collector_.powerd_suspended_file_ =
- test_dir_.path().Append("test/suspended");
- brillo::ClearLog();
- }
-
- protected:
- void WriteStringToFile(const FilePath &file_path,
- const char *data) {
- unsigned int numBytesWritten =
- base::WriteFile(file_path, data, strlen(data));
- ASSERT_EQ(strlen(data), numBytesWritten);
- }
-
- UncleanShutdownCollectorMock collector_;
-
- // Temporary directory used for tests.
- base::ScopedTempDir test_dir_;
- FilePath test_directory_;
- FilePath test_unclean_;
-};
-
-TEST_F(UncleanShutdownCollectorTest, EnableWithoutParent) {
- ASSERT_TRUE(collector_.Enable());
- ASSERT_TRUE(base::PathExists(test_unclean_));
-}
-
-TEST_F(UncleanShutdownCollectorTest, EnableWithParent) {
- mkdir(test_directory_.value().c_str(), 0777);
- ASSERT_TRUE(collector_.Enable());
- ASSERT_TRUE(base::PathExists(test_unclean_));
-}
-
-TEST_F(UncleanShutdownCollectorTest, EnableCannotWrite) {
- collector_.unclean_shutdown_file_ = "/bad/path";
- ASSERT_FALSE(collector_.Enable());
- ASSERT_TRUE(FindLog("Unable to create shutdown check file"));
-}
-
-TEST_F(UncleanShutdownCollectorTest, CollectTrue) {
- ASSERT_TRUE(collector_.Enable());
- ASSERT_TRUE(base::PathExists(test_unclean_));
- ASSERT_TRUE(collector_.Collect());
- ASSERT_FALSE(base::PathExists(test_unclean_));
- ASSERT_EQ(1, s_crashes);
- ASSERT_TRUE(FindLog("Last shutdown was not clean"));
-}
-
-TEST_F(UncleanShutdownCollectorTest, CollectFalse) {
- ASSERT_FALSE(collector_.Collect());
- ASSERT_EQ(0, s_crashes);
-}
-
-TEST_F(UncleanShutdownCollectorTest, CollectDeadBatterySuspended) {
- ASSERT_TRUE(collector_.Enable());
- ASSERT_TRUE(base::PathExists(test_unclean_));
- base::WriteFile(collector_.powerd_suspended_file_, "", 0);
- ASSERT_FALSE(collector_.Collect());
- ASSERT_FALSE(base::PathExists(test_unclean_));
- ASSERT_FALSE(base::PathExists(collector_.powerd_suspended_file_));
- ASSERT_EQ(0, s_crashes);
- ASSERT_TRUE(FindLog("Unclean shutdown occurred while suspended."));
-}
-
-TEST_F(UncleanShutdownCollectorTest, Disable) {
- ASSERT_TRUE(collector_.Enable());
- ASSERT_TRUE(base::PathExists(test_unclean_));
- ASSERT_TRUE(collector_.Disable());
- ASSERT_FALSE(base::PathExists(test_unclean_));
- ASSERT_FALSE(collector_.Collect());
-}
-
-TEST_F(UncleanShutdownCollectorTest, DisableWhenNotEnabled) {
- ASSERT_TRUE(collector_.Disable());
-}
-
-TEST_F(UncleanShutdownCollectorTest, CantDisable) {
- mkdir(test_directory_.value().c_str(), 0700);
- if (mkdir(test_unclean_.value().c_str(), 0700)) {
- ASSERT_EQ(EEXIST, errno)
- << "Error while creating directory '" << test_unclean_.value()
- << "': " << strerror(errno);
- }
- ASSERT_EQ(0, base::WriteFile(test_unclean_.Append("foo"), "", 0))
- << "Error while creating empty file '"
- << test_unclean_.Append("foo").value() << "': " << strerror(errno);
- ASSERT_FALSE(collector_.Disable());
- rmdir(test_unclean_.value().c_str());
-}
diff --git a/crash_reporter/user_collector.cc b/crash_reporter/user_collector.cc
deleted file mode 100644
index 48b64e9..0000000
--- a/crash_reporter/user_collector.cc
+++ /dev/null
@@ -1,640 +0,0 @@
-/*
- * Copyright (C) 2012 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 "user_collector.h"
-
-#include <elf.h>
-#include <fcntl.h>
-#include <grp.h> // For struct group.
-#include <pcrecpp.h>
-#include <pwd.h> // For struct passwd.
-#include <stdint.h>
-#include <sys/cdefs.h> // For __WORDSIZE
-#include <sys/fsuid.h>
-#include <sys/types.h> // For getpwuid_r, getgrnam_r, WEXITSTATUS.
-#include <unistd.h> // For setgroups
-
-#include <iostream> // For std::oct
-#include <string>
-#include <vector>
-
-#include <base/files/file_util.h>
-#include <base/logging.h>
-#include <base/posix/eintr_wrapper.h>
-#include <base/strings/string_split.h>
-#include <base/strings/string_util.h>
-#include <base/strings/stringprintf.h>
-#include <brillo/process.h>
-#include <brillo/syslog_logging.h>
-#include <cutils/properties.h>
-#include <private/android_filesystem_config.h>
-
-static const char kCollectionErrorSignature[] =
- "crash_reporter-user-collection";
-static const char kCorePatternProperty[] = "crash_reporter.coredump.enabled";
-static const char kCoreToMinidumpConverterPath[] = "/system/bin/core2md";
-
-static const char kStatePrefix[] = "State:\t";
-
-static const char kCoreTempFolder[] = "/data/misc/crash_reporter/tmp";
-
-// Define an otherwise invalid value that represents an unknown UID and GID.
-static const uid_t kUnknownUid = -1;
-static const gid_t kUnknownGid = -1;
-
-const char *UserCollector::kUserId = "Uid:\t";
-const char *UserCollector::kGroupId = "Gid:\t";
-
-
-using base::FilePath;
-using base::StringPrintf;
-
-UserCollector::UserCollector()
- : generate_diagnostics_(false),
- initialized_(false) {
-}
-
-void UserCollector::Initialize(
- UserCollector::CountCrashFunction count_crash_function,
- const std::string &our_path,
- UserCollector::IsFeedbackAllowedFunction is_feedback_allowed_function,
- bool generate_diagnostics,
- bool core2md_failure,
- bool directory_failure,
- const std::string &filter_in) {
- CrashCollector::Initialize(count_crash_function,
- is_feedback_allowed_function);
- our_path_ = our_path;
- initialized_ = true;
- generate_diagnostics_ = generate_diagnostics;
- core2md_failure_ = core2md_failure;
- directory_failure_ = directory_failure;
- filter_in_ = filter_in;
-
- gid_t groups[] = { AID_ROOT, AID_SYSTEM, AID_DBUS, AID_READPROC };
- if (setgroups(arraysize(groups), groups) != 0) {
- PLOG(FATAL) << "Unable to set groups to root, system, dbus, and readproc";
- }
-}
-
-UserCollector::~UserCollector() {
-}
-
-std::string UserCollector::GetErrorTypeSignature(ErrorType error_type) const {
- switch (error_type) {
- case kErrorSystemIssue:
- return "system-issue";
- case kErrorReadCoreData:
- return "read-core-data";
- case kErrorUnusableProcFiles:
- return "unusable-proc-files";
- case kErrorInvalidCoreFile:
- return "invalid-core-file";
- case kErrorUnsupported32BitCoreFile:
- return "unsupported-32bit-core-file";
- case kErrorCore2MinidumpConversion:
- return "core2md-conversion";
- default:
- return "";
- }
-}
-
-bool UserCollector::SetUpInternal(bool enabled) {
- CHECK(initialized_);
- LOG(INFO) << (enabled ? "Enabling" : "Disabling") << " user crash handling";
-
- property_set(kCorePatternProperty, enabled ? "1" : "0");
-
- return true;
-}
-
-bool UserCollector::GetFirstLineWithPrefix(
- const std::vector<std::string> &lines,
- const char *prefix, std::string *line) {
- std::vector<std::string>::const_iterator line_iterator;
- for (line_iterator = lines.begin(); line_iterator != lines.end();
- ++line_iterator) {
- if (line_iterator->find(prefix) == 0) {
- *line = *line_iterator;
- return true;
- }
- }
- return false;
-}
-
-bool UserCollector::GetIdFromStatus(
- const char *prefix, IdKind kind,
- const std::vector<std::string> &status_lines, int *id) {
- // From fs/proc/array.c:task_state(), this file contains:
- // \nUid:\t<uid>\t<euid>\t<suid>\t<fsuid>\n
- std::string id_line;
- if (!GetFirstLineWithPrefix(status_lines, prefix, &id_line)) {
- return false;
- }
- std::string id_substring = id_line.substr(strlen(prefix), std::string::npos);
- std::vector<std::string> ids = base::SplitString(
- id_substring, "\t", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
- if (ids.size() != kIdMax || kind < 0 || kind >= kIdMax) {
- return false;
- }
- const char *number = ids[kind].c_str();
- char *end_number = nullptr;
- *id = strtol(number, &end_number, 10);
- if (*end_number != '\0') {
- return false;
- }
- return true;
-}
-
-bool UserCollector::GetStateFromStatus(
- const std::vector<std::string> &status_lines, std::string *state) {
- std::string state_line;
- if (!GetFirstLineWithPrefix(status_lines, kStatePrefix, &state_line)) {
- return false;
- }
- *state = state_line.substr(strlen(kStatePrefix), std::string::npos);
- return true;
-}
-
-void UserCollector::EnqueueCollectionErrorLog(pid_t pid,
- ErrorType error_type,
- const std::string &exec) {
- FilePath crash_path;
- LOG(INFO) << "Writing conversion problems as separate crash report.";
- if (!GetCreatedCrashDirectoryByEuid(0, &crash_path, nullptr)) {
- LOG(ERROR) << "Could not even get log directory; out of space?";
- return;
- }
- AddCrashMetaData("sig", kCollectionErrorSignature);
- AddCrashMetaData("error_type", GetErrorTypeSignature(error_type));
- std::string dump_basename = FormatDumpBasename(exec, time(nullptr), pid);
- std::string error_log = brillo::GetLog();
- FilePath diag_log_path = GetCrashPath(crash_path, dump_basename, "diaglog");
- if (GetLogContents(FilePath(log_config_path_), kCollectionErrorSignature,
- diag_log_path)) {
- // We load the contents of diag_log into memory and append it to
- // the error log. We cannot just append to files because we need
- // to always create new files to prevent attack.
- std::string diag_log_contents;
- base::ReadFileToString(diag_log_path, &diag_log_contents);
- error_log.append(diag_log_contents);
- base::DeleteFile(diag_log_path, false);
- }
- FilePath log_path = GetCrashPath(crash_path, dump_basename, "log");
- FilePath meta_path = GetCrashPath(crash_path, dump_basename, "meta");
- // We must use WriteNewFile instead of base::WriteFile as we do
- // not want to write with root access to a symlink that an attacker
- // might have created.
- if (WriteNewFile(log_path, error_log.data(), error_log.length()) < 0) {
- LOG(ERROR) << "Error writing new file " << log_path.value();
- return;
- }
- WriteCrashMetaData(meta_path, exec, log_path.value());
-}
-
-bool UserCollector::CopyOffProcFiles(pid_t pid,
- const FilePath &container_dir) {
- if (!base::CreateDirectory(container_dir)) {
- PLOG(ERROR) << "Could not create " << container_dir.value();
- return false;
- }
- int dir_mask = base::FILE_PERMISSION_READ_BY_USER
- | base::FILE_PERMISSION_WRITE_BY_USER
- | base::FILE_PERMISSION_EXECUTE_BY_USER
- | base::FILE_PERMISSION_READ_BY_GROUP
- | base::FILE_PERMISSION_WRITE_BY_GROUP;
- if (!base::SetPosixFilePermissions(container_dir,
- base::FILE_PERMISSION_MASK & dir_mask)) {
- PLOG(ERROR) << "Could not set permissions for " << container_dir.value()
- << " to " << std::oct
- << (base::FILE_PERMISSION_MASK & dir_mask);
- return false;
- }
- FilePath process_path = GetProcessPath(pid);
- if (!base::PathExists(process_path)) {
- LOG(ERROR) << "Path " << process_path.value() << " does not exist";
- return false;
- }
- static const char *proc_files[] = {
- "auxv",
- "cmdline",
- "environ",
- "maps",
- "status"
- };
- for (unsigned i = 0; i < arraysize(proc_files); ++i) {
- if (!base::CopyFile(process_path.Append(proc_files[i]),
- container_dir.Append(proc_files[i]))) {
- LOG(ERROR) << "Could not copy " << proc_files[i] << " file";
- return false;
- }
- }
- return true;
-}
-
-bool UserCollector::ValidateProcFiles(const FilePath &container_dir) const {
- // Check if the maps file is empty, which could be due to the crashed
- // process being reaped by the kernel before finishing a core dump.
- int64_t file_size = 0;
- if (!base::GetFileSize(container_dir.Append("maps"), &file_size)) {
- LOG(ERROR) << "Could not get the size of maps file";
- return false;
- }
- if (file_size == 0) {
- LOG(ERROR) << "maps file is empty";
- return false;
- }
- return true;
-}
-
-UserCollector::ErrorType UserCollector::ValidateCoreFile(
- const FilePath &core_path) const {
- int fd = HANDLE_EINTR(open(core_path.value().c_str(), O_RDONLY));
- if (fd < 0) {
- PLOG(ERROR) << "Could not open core file " << core_path.value();
- return kErrorInvalidCoreFile;
- }
-
- char e_ident[EI_NIDENT];
- bool read_ok = base::ReadFromFD(fd, e_ident, sizeof(e_ident));
- IGNORE_EINTR(close(fd));
- if (!read_ok) {
- LOG(ERROR) << "Could not read header of core file";
- return kErrorInvalidCoreFile;
- }
-
- if (e_ident[EI_MAG0] != ELFMAG0 || e_ident[EI_MAG1] != ELFMAG1 ||
- e_ident[EI_MAG2] != ELFMAG2 || e_ident[EI_MAG3] != ELFMAG3) {
- LOG(ERROR) << "Invalid core file";
- return kErrorInvalidCoreFile;
- }
-
-#if __WORDSIZE == 64
- // TODO(benchan, mkrebs): Remove this check once core2md can
- // handles both 32-bit and 64-bit ELF on a 64-bit platform.
- if (e_ident[EI_CLASS] == ELFCLASS32) {
- LOG(ERROR) << "Conversion of 32-bit core file on 64-bit platform is "
- << "currently not supported";
- return kErrorUnsupported32BitCoreFile;
- }
-#endif
-
- return kErrorNone;
-}
-
-bool UserCollector::GetCreatedCrashDirectory(pid_t pid, uid_t supplied_ruid,
- FilePath *crash_file_path,
- bool *out_of_capacity) {
- FilePath process_path = GetProcessPath(pid);
- std::string status;
- if (directory_failure_) {
- LOG(ERROR) << "Purposefully failing to create spool directory";
- return false;
- }
-
- uid_t uid;
- if (base::ReadFileToString(process_path.Append("status"), &status)) {
- std::vector<std::string> status_lines = base::SplitString(
- status, "\n", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
-
- std::string process_state;
- if (!GetStateFromStatus(status_lines, &process_state)) {
- LOG(ERROR) << "Could not find process state in status file";
- return false;
- }
- LOG(INFO) << "State of crashed process [" << pid << "]: " << process_state;
-
- // Get effective UID of crashing process.
- int id;
- if (!GetIdFromStatus(kUserId, kIdEffective, status_lines, &id)) {
- LOG(ERROR) << "Could not find euid in status file";
- return false;
- }
- uid = id;
- } else if (supplied_ruid != kUnknownUid) {
- LOG(INFO) << "Using supplied UID " << supplied_ruid
- << " for crashed process [" << pid
- << "] due to error reading status file";
- uid = supplied_ruid;
- } else {
- LOG(ERROR) << "Could not read status file and kernel did not supply UID";
- LOG(INFO) << "Path " << process_path.value() << " DirectoryExists: "
- << base::DirectoryExists(process_path);
- return false;
- }
-
- if (!GetCreatedCrashDirectoryByEuid(uid, crash_file_path, out_of_capacity)) {
- LOG(ERROR) << "Could not create crash directory";
- return false;
- }
- return true;
-}
-
-bool UserCollector::CopyStdinToCoreFile(const FilePath &core_path) {
- // Copy off all stdin to a core file.
- FilePath stdin_path("/proc/self/fd/0");
- if (base::CopyFile(stdin_path, core_path)) {
- return true;
- }
-
- PLOG(ERROR) << "Could not write core file";
- // If the file system was full, make sure we remove any remnants.
- base::DeleteFile(core_path, false);
- return false;
-}
-
-bool UserCollector::RunCoreToMinidump(const FilePath &core_path,
- const FilePath &procfs_directory,
- const FilePath &minidump_path,
- const FilePath &temp_directory) {
- FilePath output_path = temp_directory.Append("output");
- brillo::ProcessImpl core2md;
- core2md.RedirectOutput(output_path.value());
- core2md.AddArg(kCoreToMinidumpConverterPath);
- core2md.AddArg(core_path.value());
- core2md.AddArg(procfs_directory.value());
-
- if (!core2md_failure_) {
- core2md.AddArg(minidump_path.value());
- } else {
- // To test how core2md errors are propagaged, cause an error
- // by forgetting a required argument.
- }
-
- int errorlevel = core2md.Run();
-
- std::string output;
- base::ReadFileToString(output_path, &output);
- if (errorlevel != 0) {
- LOG(ERROR) << "Problem during " << kCoreToMinidumpConverterPath
- << " [result=" << errorlevel << "]: " << output;
- return false;
- }
-
- if (!base::PathExists(minidump_path)) {
- LOG(ERROR) << "Minidump file " << minidump_path.value()
- << " was not created";
- return false;
- }
- return true;
-}
-
-UserCollector::ErrorType UserCollector::ConvertCoreToMinidump(
- pid_t pid,
- const FilePath &container_dir,
- const FilePath &core_path,
- const FilePath &minidump_path) {
- // If proc files are unuable, we continue to read the core file from stdin,
- // but only skip the core-to-minidump conversion, so that we may still use
- // the core file for debugging.
- bool proc_files_usable =
- CopyOffProcFiles(pid, container_dir) && ValidateProcFiles(container_dir);
-
- // Switch back to the original UID/GID.
- gid_t rgid, egid, sgid;
- if (getresgid(&rgid, &egid, &sgid) != 0) {
- PLOG(FATAL) << "Unable to read saved gid";
- }
- if (setresgid(sgid, sgid, -1) != 0) {
- PLOG(FATAL) << "Unable to set real group ID back to saved gid";
- } else {
- if (getresgid(&rgid, &egid, &sgid) != 0) {
- // If the groups cannot be read at this point, the rgid variable will
- // contain the previously read group ID from before changing it. This
- // will cause the chown call below to set the incorrect group for
- // non-root crashes. But do not treat this as a fatal error, so that
- // the rest of the collection will continue for potential manual
- // collection by a developer.
- PLOG(ERROR) << "Unable to read real group ID after setting it";
- }
- }
-
- uid_t ruid, euid, suid;
- if (getresuid(&ruid, &euid, &suid) != 0) {
- PLOG(FATAL) << "Unable to read saved uid";
- }
- if (setresuid(suid, suid, -1) != 0) {
- PLOG(FATAL) << "Unable to set real user ID back to saved uid";
- } else {
- if (getresuid(&ruid, &euid, &suid) != 0) {
- // If the user ID cannot be read at this point, the ruid variable will
- // contain the previously read user ID from before changing it. This
- // will cause the chown call below to set the incorrect user for
- // non-root crashes. But do not treat this as a fatal error, so that
- // the rest of the collection will continue for potential manual
- // collection by a developer.
- PLOG(ERROR) << "Unable to read real user ID after setting it";
- }
- }
-
- if (!CopyStdinToCoreFile(core_path)) {
- return kErrorReadCoreData;
- }
-
- if (!proc_files_usable) {
- LOG(INFO) << "Skipped converting core file to minidump due to "
- << "unusable proc files";
- return kErrorUnusableProcFiles;
- }
-
- ErrorType error = ValidateCoreFile(core_path);
- if (error != kErrorNone) {
- return error;
- }
-
- // Chown the temp container directory back to the original user/group that
- // crash_reporter is run as, so that additional files can be written to
- // the temp folder.
- if (chown(container_dir.value().c_str(), ruid, rgid) < 0) {
- PLOG(ERROR) << "Could not set owner for " << container_dir.value();
- }
-
- if (!RunCoreToMinidump(core_path,
- container_dir, // procfs directory
- minidump_path,
- container_dir)) { // temporary directory
- return kErrorCore2MinidumpConversion;
- }
-
- LOG(INFO) << "Stored minidump to " << minidump_path.value();
- return kErrorNone;
-}
-
-UserCollector::ErrorType UserCollector::ConvertAndEnqueueCrash(
- pid_t pid, const std::string &exec, uid_t supplied_ruid,
- bool *out_of_capacity) {
- FilePath crash_path;
- if (!GetCreatedCrashDirectory(pid, supplied_ruid, &crash_path,
- out_of_capacity)) {
- LOG(ERROR) << "Unable to find/create process-specific crash path";
- return kErrorSystemIssue;
- }
-
- // Directory like /tmp/crash_reporter/1234 which contains the
- // procfs entries and other temporary files used during conversion.
- FilePath container_dir(StringPrintf("%s/%d", kCoreTempFolder, pid));
- // Delete a pre-existing directory from crash reporter that may have
- // been left around for diagnostics from a failed conversion attempt.
- // If we don't, existing files can cause forking to fail.
- base::DeleteFile(container_dir, true);
- std::string dump_basename = FormatDumpBasename(exec, time(nullptr), pid);
- FilePath core_path = GetCrashPath(crash_path, dump_basename, "core");
- FilePath meta_path = GetCrashPath(crash_path, dump_basename, "meta");
- FilePath minidump_path = GetCrashPath(crash_path, dump_basename, "dmp");
- FilePath log_path = GetCrashPath(crash_path, dump_basename, "log");
-
- if (GetLogContents(FilePath(log_config_path_), exec, log_path))
- AddCrashMetaData("log", log_path.value());
-
- ErrorType error_type =
- ConvertCoreToMinidump(pid, container_dir, core_path, minidump_path);
- if (error_type != kErrorNone) {
- LOG(INFO) << "Leaving core file at " << core_path.value()
- << " due to conversion error";
- return error_type;
- }
-
- // Here we commit to sending this file. We must not return false
- // after this point or we will generate a log report as well as a
- // crash report.
- WriteCrashMetaData(meta_path,
- exec,
- minidump_path.value());
-
- if (!IsDeveloperImage()) {
- base::DeleteFile(core_path, false);
- } else {
- LOG(INFO) << "Leaving core file at " << core_path.value()
- << " due to developer image";
- }
-
- base::DeleteFile(container_dir, true);
- return kErrorNone;
-}
-
-bool UserCollector::ParseCrashAttributes(const std::string &crash_attributes,
- pid_t *pid, int *signal, uid_t *uid,
- gid_t *gid,
- std::string *kernel_supplied_name) {
- pcrecpp::RE re("(\\d+):(\\d+):(\\d+):(\\d+):(.*)");
- if (re.FullMatch(crash_attributes, pid, signal, uid, gid,
- kernel_supplied_name))
- return true;
-
- LOG(INFO) << "Falling back to parsing crash attributes '"
- << crash_attributes << "' without UID and GID";
- pcrecpp::RE re_without_uid("(\\d+):(\\d+):(.*)");
- *uid = kUnknownUid;
- *gid = kUnknownGid;
- return re_without_uid.FullMatch(crash_attributes, pid, signal,
- kernel_supplied_name);
-}
-
-bool UserCollector::ShouldDump(bool has_owner_consent,
- bool is_developer,
- std::string *reason) {
- reason->clear();
-
- // For developer builds, we always want to keep the crash reports unless
- // we're testing the crash facilities themselves. This overrides
- // feedback. Crash sending still obeys consent.
- if (is_developer) {
- *reason = "developer build - not testing - always dumping";
- return true;
- }
-
- if (!has_owner_consent) {
- *reason = "ignoring - no consent";
- return false;
- }
-
- *reason = "handling";
- return true;
-}
-
-bool UserCollector::HandleCrash(const std::string &crash_attributes,
- const char *force_exec) {
- CHECK(initialized_);
- pid_t pid = 0;
- int signal = 0;
- uid_t supplied_ruid = kUnknownUid;
- gid_t supplied_rgid = kUnknownGid;
- std::string kernel_supplied_name;
-
- if (!ParseCrashAttributes(crash_attributes, &pid, &signal, &supplied_ruid,
- &supplied_rgid, &kernel_supplied_name)) {
- LOG(ERROR) << "Invalid parameter: --user=" << crash_attributes;
- return false;
- }
-
- // Switch to the group and user that ran the crashing binary in order to
- // access their /proc files. Do not set suid/sgid, so that we can switch
- // back after copying the necessary files.
- if (setresgid(supplied_rgid, supplied_rgid, -1) != 0) {
- PLOG(FATAL) << "Unable to set real group ID to access process files";
- }
- if (setresuid(supplied_ruid, supplied_ruid, -1) != 0) {
- PLOG(FATAL) << "Unable to set real user ID to access process files";
- }
-
- std::string exec;
- if (force_exec) {
- exec.assign(force_exec);
- } else if (!GetExecutableBaseNameFromPid(pid, &exec)) {
- // If we cannot find the exec name, use the kernel supplied name.
- // We don't always use the kernel's since it truncates the name to
- // 16 characters.
- exec = StringPrintf("supplied_%s", kernel_supplied_name.c_str());
- }
-
- // Allow us to test the crash reporting mechanism successfully even if
- // other parts of the system crash.
- if (!filter_in_.empty() &&
- (filter_in_ == "none" ||
- filter_in_ != exec)) {
- // We use a different format message to make it more obvious in tests
- // which crashes are test generated and which are real.
- LOG(WARNING) << "Ignoring crash from " << exec << "[" << pid << "] while "
- << "filter_in=" << filter_in_ << ".";
- return true;
- }
-
- std::string reason;
- bool dump = ShouldDump(is_feedback_allowed_function_(),
- IsDeveloperImage(),
- &reason);
-
- LOG(WARNING) << "Received crash notification for " << exec << "[" << pid
- << "] sig " << signal << ", user " << supplied_ruid
- << " (" << reason << ")";
-
- if (dump) {
- count_crash_function_();
-
- if (generate_diagnostics_) {
- bool out_of_capacity = false;
- ErrorType error_type =
- ConvertAndEnqueueCrash(pid, exec, supplied_ruid, &out_of_capacity);
- if (error_type != kErrorNone) {
- if (!out_of_capacity)
- EnqueueCollectionErrorLog(pid, error_type, exec);
- return false;
- }
- }
- }
-
- return true;
-}
diff --git a/crash_reporter/user_collector.h b/crash_reporter/user_collector.h
deleted file mode 100644
index 7261ed4..0000000
--- a/crash_reporter/user_collector.h
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * Copyright (C) 2010 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.
- */
-
-#ifndef CRASH_REPORTER_USER_COLLECTOR_H_
-#define CRASH_REPORTER_USER_COLLECTOR_H_
-
-#include <string>
-#include <vector>
-
-#include <base/files/file_path.h>
-#include <base/macros.h>
-#include <gtest/gtest_prod.h> // for FRIEND_TEST
-
-#include "crash_collector.h"
-
-class SystemLogging;
-
-// User crash collector.
-class UserCollector : public CrashCollector {
- public:
- UserCollector();
-
- // Initialize the user crash collector for detection of crashes,
- // given a crash counting function, the path to this executable,
- // metrics collection enabled oracle, and system logger facility.
- // Crash detection/reporting is not enabled until Enable is called.
- // |generate_diagnostics| is used to indicate whether or not to try
- // to generate a minidump from crashes.
- void Initialize(CountCrashFunction count_crash,
- const std::string &our_path,
- IsFeedbackAllowedFunction is_metrics_allowed,
- bool generate_diagnostics,
- bool core2md_failure,
- bool directory_failure,
- const std::string &filter_in);
-
- ~UserCollector() override;
-
- // Enable collection.
- bool Enable() { return SetUpInternal(true); }
-
- // Disable collection.
- bool Disable() { return SetUpInternal(false); }
-
- // Handle a specific user crash. Returns true on success.
- bool HandleCrash(const std::string &crash_attributes,
- const char *force_exec);
-
- private:
- friend class UserCollectorTest;
- FRIEND_TEST(UserCollectorTest, CopyOffProcFilesBadPath);
- FRIEND_TEST(UserCollectorTest, CopyOffProcFilesBadPid);
- FRIEND_TEST(UserCollectorTest, CopyOffProcFilesOK);
- FRIEND_TEST(UserCollectorTest, GetExecutableBaseNameFromPid);
- FRIEND_TEST(UserCollectorTest, GetFirstLineWithPrefix);
- FRIEND_TEST(UserCollectorTest, GetIdFromStatus);
- FRIEND_TEST(UserCollectorTest, GetStateFromStatus);
- FRIEND_TEST(UserCollectorTest, GetProcessPath);
- FRIEND_TEST(UserCollectorTest, GetSymlinkTarget);
- FRIEND_TEST(UserCollectorTest, GetUserInfoFromName);
- FRIEND_TEST(UserCollectorTest, ParseCrashAttributes);
- FRIEND_TEST(UserCollectorTest, ShouldDumpChromeOverridesDeveloperImage);
- FRIEND_TEST(UserCollectorTest, ShouldDumpDeveloperImageOverridesConsent);
- FRIEND_TEST(UserCollectorTest, ShouldDumpUseConsentProductionImage);
- FRIEND_TEST(UserCollectorTest, ValidateProcFiles);
- FRIEND_TEST(UserCollectorTest, ValidateCoreFile);
-
- // Enumeration to pass to GetIdFromStatus. Must match the order
- // that the kernel lists IDs in the status file.
- enum IdKind {
- kIdReal = 0, // uid and gid
- kIdEffective = 1, // euid and egid
- kIdSet = 2, // suid and sgid
- kIdFileSystem = 3, // fsuid and fsgid
- kIdMax
- };
-
- enum ErrorType {
- kErrorNone,
- kErrorSystemIssue,
- kErrorReadCoreData,
- kErrorUnusableProcFiles,
- kErrorInvalidCoreFile,
- kErrorUnsupported32BitCoreFile,
- kErrorCore2MinidumpConversion,
- };
-
- static const int kForkProblem = 255;
-
- // Returns an error type signature for a given |error_type| value,
- // which is reported to the crash server along with the
- // crash_reporter-user-collection signature.
- std::string GetErrorTypeSignature(ErrorType error_type) const;
-
- bool SetUpInternal(bool enabled);
-
- // Returns, via |line|, the first line in |lines| that starts with |prefix|.
- // Returns true if a line is found, or false otherwise.
- bool GetFirstLineWithPrefix(const std::vector<std::string> &lines,
- const char *prefix, std::string *line);
-
- // Returns the identifier of |kind|, via |id|, found in |status_lines| on
- // the line starting with |prefix|. |status_lines| contains the lines in
- // the status file. Returns true if the identifier can be determined.
- bool GetIdFromStatus(const char *prefix,
- IdKind kind,
- const std::vector<std::string> &status_lines,
- int *id);
-
- // Returns the process state, via |state|, found in |status_lines|, which
- // contains the lines in the status file. Returns true if the process state
- // can be determined.
- bool GetStateFromStatus(const std::vector<std::string> &status_lines,
- std::string *state);
-
- void LogCollectionError(const std::string &error_message);
- void EnqueueCollectionErrorLog(pid_t pid, ErrorType error_type,
- const std::string &exec_name);
-
- bool CopyOffProcFiles(pid_t pid, const base::FilePath &container_dir);
-
- // Validates the proc files at |container_dir| and returns true if they
- // are usable for the core-to-minidump conversion later. For instance, if
- // a process is reaped by the kernel before the copying of its proc files
- // takes place, some proc files like /proc/<pid>/maps may contain nothing
- // and thus become unusable.
- bool ValidateProcFiles(const base::FilePath &container_dir) const;
-
- // Validates the core file at |core_path| and returns kErrorNone if
- // the file contains the ELF magic bytes and an ELF class that matches the
- // platform (i.e. 32-bit ELF on a 32-bit platform or 64-bit ELF on a 64-bit
- // platform), which is due to the limitation in core2md. It returns an error
- // type otherwise.
- ErrorType ValidateCoreFile(const base::FilePath &core_path) const;
-
- // Determines the crash directory for given pid based on pid's owner,
- // and creates the directory if necessary with appropriate permissions.
- // Returns true whether or not directory needed to be created, false on
- // any failure.
- bool GetCreatedCrashDirectory(pid_t pid, uid_t supplied_ruid,
- base::FilePath *crash_file_path,
- bool *out_of_capacity);
- bool CopyStdinToCoreFile(const base::FilePath &core_path);
- bool RunCoreToMinidump(const base::FilePath &core_path,
- const base::FilePath &procfs_directory,
- const base::FilePath &minidump_path,
- const base::FilePath &temp_directory);
- ErrorType ConvertCoreToMinidump(pid_t pid,
- const base::FilePath &container_dir,
- const base::FilePath &core_path,
- const base::FilePath &minidump_path);
- ErrorType ConvertAndEnqueueCrash(pid_t pid, const std::string &exec_name,
- uid_t supplied_ruid, bool *out_of_capacity);
- bool ParseCrashAttributes(const std::string &crash_attributes,
- pid_t *pid, int *signal, uid_t *uid, gid_t *gid,
- std::string *kernel_supplied_name);
-
- bool ShouldDump(bool has_owner_consent,
- bool is_developer,
- std::string *reason);
-
- bool generate_diagnostics_;
- std::string our_path_;
- bool initialized_;
-
- bool core2md_failure_;
- bool directory_failure_;
- std::string filter_in_;
-
- static const char *kUserId;
- static const char *kGroupId;
-
- DISALLOW_COPY_AND_ASSIGN(UserCollector);
-};
-
-#endif // CRASH_REPORTER_USER_COLLECTOR_H_
diff --git a/crash_reporter/user_collector_test.cc b/crash_reporter/user_collector_test.cc
deleted file mode 100644
index 16a5cd5..0000000
--- a/crash_reporter/user_collector_test.cc
+++ /dev/null
@@ -1,440 +0,0 @@
-/*
- * Copyright (C) 2012 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 "user_collector.h"
-
-#include <elf.h>
-#include <sys/cdefs.h> // For __WORDSIZE
-#include <unistd.h>
-
-#include <base/files/file_util.h>
-#include <base/files/scoped_temp_dir.h>
-#include <base/strings/string_split.h>
-#include <brillo/syslog_logging.h>
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-
-using base::FilePath;
-using brillo::FindLog;
-
-namespace {
-
-int s_crashes = 0;
-bool s_metrics = false;
-
-const char kFilePath[] = "/my/path";
-
-void CountCrash() {
- ++s_crashes;
-}
-
-bool IsMetrics() {
- return s_metrics;
-}
-
-} // namespace
-
-class UserCollectorMock : public UserCollector {
- public:
- MOCK_METHOD0(SetUpDBus, void());
-};
-
-class UserCollectorTest : public ::testing::Test {
- void SetUp() {
- s_crashes = 0;
-
- EXPECT_CALL(collector_, SetUpDBus()).WillRepeatedly(testing::Return());
-
- collector_.Initialize(CountCrash,
- kFilePath,
- IsMetrics,
- false,
- false,
- false,
- "");
-
- EXPECT_TRUE(test_dir_.CreateUniqueTempDir());
-
- mkdir(test_dir_.path().Append("test").value().c_str(), 0777);
- pid_ = getpid();
- brillo::ClearLog();
- }
-
- protected:
- void ExpectFileEquals(const char *golden,
- const FilePath &file_path) {
- std::string contents;
- EXPECT_TRUE(base::ReadFileToString(file_path, &contents));
- EXPECT_EQ(golden, contents);
- }
-
- std::vector<std::string> SplitLines(const std::string &lines) const {
- return base::SplitString(lines, "\n", base::TRIM_WHITESPACE,
- base::SPLIT_WANT_ALL);
- }
-
- UserCollectorMock collector_;
- pid_t pid_;
- base::ScopedTempDir test_dir_;
-};
-
-TEST_F(UserCollectorTest, ParseCrashAttributes) {
- pid_t pid;
- int signal;
- uid_t uid;
- gid_t gid;
- std::string exec_name;
- EXPECT_TRUE(collector_.ParseCrashAttributes("123456:11:1000:2000:foobar",
- &pid, &signal, &uid, &gid, &exec_name));
- EXPECT_EQ(123456, pid);
- EXPECT_EQ(11, signal);
- EXPECT_EQ(1000U, uid);
- EXPECT_EQ(2000U, gid);
- EXPECT_EQ("foobar", exec_name);
- EXPECT_TRUE(collector_.ParseCrashAttributes("4321:6:barfoo",
- &pid, &signal, &uid, &gid, &exec_name));
- EXPECT_EQ(4321, pid);
- EXPECT_EQ(6, signal);
- EXPECT_EQ(-1U, uid);
- EXPECT_EQ(-1U, gid);
- EXPECT_EQ("barfoo", exec_name);
-
- EXPECT_FALSE(collector_.ParseCrashAttributes("123456:11",
- &pid, &signal, &uid, &gid, &exec_name));
-
- EXPECT_TRUE(collector_.ParseCrashAttributes("123456:11:exec:extra",
- &pid, &signal, &uid, &gid, &exec_name));
- EXPECT_EQ("exec:extra", exec_name);
-
- EXPECT_FALSE(collector_.ParseCrashAttributes("12345p:11:foobar",
- &pid, &signal, &uid, &gid, &exec_name));
-
- EXPECT_FALSE(collector_.ParseCrashAttributes("123456:1 :foobar",
- &pid, &signal, &uid, &gid, &exec_name));
-
- EXPECT_FALSE(collector_.ParseCrashAttributes("123456::foobar",
- &pid, &signal, &uid, &gid, &exec_name));
-}
-
-TEST_F(UserCollectorTest, ShouldDumpDeveloperImageOverridesConsent) {
- std::string reason;
- EXPECT_TRUE(collector_.ShouldDump(false, true, &reason));
- EXPECT_EQ("developer build - not testing - always dumping", reason);
-
- // When running a crash test, behave as normal.
- EXPECT_FALSE(collector_.ShouldDump(false, false, &reason));
- EXPECT_EQ("ignoring - no consent", reason);
-}
-
-TEST_F(UserCollectorTest, ShouldDumpUseConsentProductionImage) {
- std::string result;
- EXPECT_FALSE(collector_.ShouldDump(false, false, &result));
- EXPECT_EQ("ignoring - no consent", result);
-
- EXPECT_TRUE(collector_.ShouldDump(true, false, &result));
- EXPECT_EQ("handling", result);
-}
-
-TEST_F(UserCollectorTest, HandleCrashWithoutConsent) {
- s_metrics = false;
- collector_.HandleCrash("20:10:ignored", "foobar");
- EXPECT_TRUE(FindLog(
- "Received crash notification for foobar[20] sig 10"));
- ASSERT_EQ(s_crashes, 0);
-}
-
-TEST_F(UserCollectorTest, HandleNonChromeCrashWithConsent) {
- s_metrics = true;
- collector_.HandleCrash("5:2:ignored", "chromeos-wm");
- EXPECT_TRUE(FindLog(
- "Received crash notification for chromeos-wm[5] sig 2"));
- ASSERT_EQ(s_crashes, 1);
-}
-
-TEST_F(UserCollectorTest, GetProcessPath) {
- FilePath path = collector_.GetProcessPath(100);
- ASSERT_EQ("/proc/100", path.value());
-}
-
-TEST_F(UserCollectorTest, GetSymlinkTarget) {
- FilePath result;
- ASSERT_FALSE(collector_.GetSymlinkTarget(FilePath("/does_not_exist"),
- &result));
- ASSERT_TRUE(FindLog(
- "Readlink failed on /does_not_exist with 2"));
- std::string long_link = test_dir_.path().value();
- for (int i = 0; i < 50; ++i)
- long_link += "0123456789";
- long_link += "/gold";
-
- for (size_t len = 1; len <= long_link.size(); ++len) {
- std::string this_link;
- static const char* kLink =
- test_dir_.path().Append("test/this_link").value().c_str();
- this_link.assign(long_link.c_str(), len);
- ASSERT_EQ(len, this_link.size());
- ASSERT_EQ(0, symlink(this_link.c_str(), kLink));
- ASSERT_TRUE(collector_.GetSymlinkTarget(FilePath(kLink), &result));
- ASSERT_EQ(this_link, result.value());
- unlink(kLink);
- }
-}
-
-TEST_F(UserCollectorTest, GetExecutableBaseNameFromPid) {
- std::string base_name;
- EXPECT_FALSE(collector_.GetExecutableBaseNameFromPid(0, &base_name));
- EXPECT_TRUE(FindLog(
- "Readlink failed on /proc/0/exe with 2"));
- EXPECT_TRUE(FindLog(
- "GetSymlinkTarget failed - Path /proc/0 DirectoryExists: 0"));
- EXPECT_TRUE(FindLog("stat /proc/0/exe failed: -1 2"));
-
- brillo::ClearLog();
- pid_t my_pid = getpid();
- EXPECT_TRUE(collector_.GetExecutableBaseNameFromPid(my_pid, &base_name));
- EXPECT_FALSE(FindLog("Readlink failed"));
- EXPECT_EQ("crash_reporter_tests", base_name);
-}
-
-TEST_F(UserCollectorTest, GetFirstLineWithPrefix) {
- std::vector<std::string> lines;
- std::string line;
-
- EXPECT_FALSE(collector_.GetFirstLineWithPrefix(lines, "Name:", &line));
- EXPECT_EQ("", line);
-
- lines.push_back("Name:\tls");
- lines.push_back("State:\tR (running)");
- lines.push_back(" Foo:\t1000");
-
- line.clear();
- EXPECT_TRUE(collector_.GetFirstLineWithPrefix(lines, "Name:", &line));
- EXPECT_EQ(lines[0], line);
-
- line.clear();
- EXPECT_TRUE(collector_.GetFirstLineWithPrefix(lines, "State:", &line));
- EXPECT_EQ(lines[1], line);
-
- line.clear();
- EXPECT_FALSE(collector_.GetFirstLineWithPrefix(lines, "Foo:", &line));
- EXPECT_EQ("", line);
-
- line.clear();
- EXPECT_TRUE(collector_.GetFirstLineWithPrefix(lines, " Foo:", &line));
- EXPECT_EQ(lines[2], line);
-
- line.clear();
- EXPECT_FALSE(collector_.GetFirstLineWithPrefix(lines, "Bar:", &line));
- EXPECT_EQ("", line);
-}
-
-TEST_F(UserCollectorTest, GetIdFromStatus) {
- int id = 1;
- EXPECT_FALSE(collector_.GetIdFromStatus(UserCollector::kUserId,
- UserCollector::kIdEffective,
- SplitLines("nothing here"),
- &id));
- EXPECT_EQ(id, 1);
-
- // Not enough parameters.
- EXPECT_FALSE(collector_.GetIdFromStatus(UserCollector::kUserId,
- UserCollector::kIdReal,
- SplitLines("line 1\nUid:\t1\n"),
- &id));
-
- const std::vector<std::string> valid_contents =
- SplitLines("\nUid:\t1\t2\t3\t4\nGid:\t5\t6\t7\t8\n");
- EXPECT_TRUE(collector_.GetIdFromStatus(UserCollector::kUserId,
- UserCollector::kIdReal,
- valid_contents,
- &id));
- EXPECT_EQ(1, id);
-
- EXPECT_TRUE(collector_.GetIdFromStatus(UserCollector::kUserId,
- UserCollector::kIdEffective,
- valid_contents,
- &id));
- EXPECT_EQ(2, id);
-
- EXPECT_TRUE(collector_.GetIdFromStatus(UserCollector::kUserId,
- UserCollector::kIdFileSystem,
- valid_contents,
- &id));
- EXPECT_EQ(4, id);
-
- EXPECT_TRUE(collector_.GetIdFromStatus(UserCollector::kGroupId,
- UserCollector::kIdEffective,
- valid_contents,
- &id));
- EXPECT_EQ(6, id);
-
- EXPECT_TRUE(collector_.GetIdFromStatus(UserCollector::kGroupId,
- UserCollector::kIdSet,
- valid_contents,
- &id));
- EXPECT_EQ(7, id);
-
- EXPECT_FALSE(collector_.GetIdFromStatus(UserCollector::kGroupId,
- UserCollector::IdKind(5),
- valid_contents,
- &id));
- EXPECT_FALSE(collector_.GetIdFromStatus(UserCollector::kGroupId,
- UserCollector::IdKind(-1),
- valid_contents,
- &id));
-
- // Fail if junk after number
- EXPECT_FALSE(collector_.GetIdFromStatus(UserCollector::kUserId,
- UserCollector::kIdReal,
- SplitLines("Uid:\t1f\t2\t3\t4\n"),
- &id));
- EXPECT_TRUE(collector_.GetIdFromStatus(UserCollector::kUserId,
- UserCollector::kIdReal,
- SplitLines("Uid:\t1\t2\t3\t4\n"),
- &id));
- EXPECT_EQ(1, id);
-
- // Fail if more than 4 numbers.
- EXPECT_FALSE(collector_.GetIdFromStatus(UserCollector::kUserId,
- UserCollector::kIdReal,
- SplitLines("Uid:\t1\t2\t3\t4\t5\n"),
- &id));
-}
-
-TEST_F(UserCollectorTest, GetStateFromStatus) {
- std::string state;
- EXPECT_FALSE(collector_.GetStateFromStatus(SplitLines("nothing here"),
- &state));
- EXPECT_EQ("", state);
-
- EXPECT_TRUE(collector_.GetStateFromStatus(SplitLines("State:\tR (running)"),
- &state));
- EXPECT_EQ("R (running)", state);
-
- EXPECT_TRUE(collector_.GetStateFromStatus(
- SplitLines("Name:\tls\nState:\tZ (zombie)\n"), &state));
- EXPECT_EQ("Z (zombie)", state);
-}
-
-TEST_F(UserCollectorTest, GetUserInfoFromName) {
- gid_t gid = 100;
- uid_t uid = 100;
- EXPECT_TRUE(collector_.GetUserInfoFromName("root", &uid, &gid));
- EXPECT_EQ(0U, uid);
- EXPECT_EQ(0U, gid);
-}
-
-TEST_F(UserCollectorTest, CopyOffProcFilesBadPath) {
- // Try a path that is not writable.
- ASSERT_FALSE(collector_.CopyOffProcFiles(pid_, FilePath("/bad/path")));
- EXPECT_TRUE(FindLog("Could not create /bad/path"));
-}
-
-TEST_F(UserCollectorTest, CopyOffProcFilesBadPid) {
- FilePath container_path(test_dir_.path().Append("test/container"));
- ASSERT_FALSE(collector_.CopyOffProcFiles(0, container_path));
- EXPECT_TRUE(FindLog("Path /proc/0 does not exist"));
-}
-
-TEST_F(UserCollectorTest, CopyOffProcFilesOK) {
- FilePath container_path(test_dir_.path().Append("test/container"));
- ASSERT_TRUE(collector_.CopyOffProcFiles(pid_, container_path));
- EXPECT_FALSE(FindLog("Could not copy"));
- static struct {
- const char *name;
- bool exists;
- } expectations[] = {
- { "auxv", true },
- { "cmdline", true },
- { "environ", true },
- { "maps", true },
- { "mem", false },
- { "mounts", false },
- { "sched", false },
- { "status", true }
- };
- for (unsigned i = 0; i < sizeof(expectations)/sizeof(expectations[0]); ++i) {
- EXPECT_EQ(expectations[i].exists,
- base::PathExists(
- container_path.Append(expectations[i].name)));
- }
-}
-
-TEST_F(UserCollectorTest, ValidateProcFiles) {
- FilePath container_dir = test_dir_.path();
-
- // maps file not exists (i.e. GetFileSize fails)
- EXPECT_FALSE(collector_.ValidateProcFiles(container_dir));
-
- // maps file is empty
- FilePath maps_file = container_dir.Append("maps");
- ASSERT_EQ(0, base::WriteFile(maps_file, nullptr, 0));
- ASSERT_TRUE(base::PathExists(maps_file));
- EXPECT_FALSE(collector_.ValidateProcFiles(container_dir));
-
- // maps file is not empty
- const char data[] = "test data";
- unsigned int numBytesWritten =
- base::WriteFile(maps_file, data, sizeof(data));
- ASSERT_EQ(sizeof(data), numBytesWritten);
- ASSERT_TRUE(base::PathExists(maps_file));
- EXPECT_TRUE(collector_.ValidateProcFiles(container_dir));
-}
-
-TEST_F(UserCollectorTest, ValidateCoreFile) {
- FilePath container_dir = test_dir_.path();
- FilePath core_file = container_dir.Append("core");
-
- // Core file does not exist
- EXPECT_EQ(UserCollector::kErrorInvalidCoreFile,
- collector_.ValidateCoreFile(core_file));
- char e_ident[EI_NIDENT];
- e_ident[EI_MAG0] = ELFMAG0;
- e_ident[EI_MAG1] = ELFMAG1;
- e_ident[EI_MAG2] = ELFMAG2;
- e_ident[EI_MAG3] = ELFMAG3;
-#if __WORDSIZE == 32
- e_ident[EI_CLASS] = ELFCLASS32;
-#elif __WORDSIZE == 64
- e_ident[EI_CLASS] = ELFCLASS64;
-#else
-#error Unknown/unsupported value of __WORDSIZE.
-#endif
-
- // Core file has the expected header
- ASSERT_TRUE(base::WriteFile(core_file, e_ident, sizeof(e_ident)));
- EXPECT_EQ(UserCollector::kErrorNone,
- collector_.ValidateCoreFile(core_file));
-
-#if __WORDSIZE == 64
- // 32-bit core file on 64-bit platform
- e_ident[EI_CLASS] = ELFCLASS32;
- ASSERT_TRUE(base::WriteFile(core_file, e_ident, sizeof(e_ident)));
- EXPECT_EQ(UserCollector::kErrorUnsupported32BitCoreFile,
- collector_.ValidateCoreFile(core_file));
- e_ident[EI_CLASS] = ELFCLASS64;
-#endif
-
- // Invalid core files
- ASSERT_TRUE(base::WriteFile(core_file, e_ident, sizeof(e_ident) - 1));
- EXPECT_EQ(UserCollector::kErrorInvalidCoreFile,
- collector_.ValidateCoreFile(core_file));
-
- e_ident[EI_MAG0] = 0;
- ASSERT_TRUE(base::WriteFile(core_file, e_ident, sizeof(e_ident)));
- EXPECT_EQ(UserCollector::kErrorInvalidCoreFile,
- collector_.ValidateCoreFile(core_file));
-}
diff --git a/crash_reporter/warn_collector.l b/crash_reporter/warn_collector.l
deleted file mode 100644
index 70ab25c..0000000
--- a/crash_reporter/warn_collector.l
+++ /dev/null
@@ -1,335 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- *
- * This flex program reads /var/log/messages as it grows and saves kernel
- * warnings to files. It keeps track of warnings it has seen (based on
- * file/line only, ignoring differences in the stack trace), and reports only
- * the first warning of each kind, but maintains a count of all warnings by
- * using their hashes as buckets in a UMA sparse histogram. It also invokes
- * the crash collector, which collects the warnings and prepares them for later
- * shipment to the crash server.
- */
-
-%option noyywrap
-
-%{
-#include <fcntl.h>
-#include <inttypes.h>
-#include <pwd.h>
-#include <stdarg.h>
-#include <sys/inotify.h>
-#include <sys/select.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include "metrics/c_metrics_library.h"
-
-int WarnStart(void);
-void WarnEnd(void);
-void WarnInput(char *buf, yy_size_t *result, size_t max_size);
-
-#define YY_INPUT(buf, result, max_size) WarnInput(buf, &result, max_size)
-
-%}
-
-/* Define a few useful regular expressions. */
-
-D [0-9]
-PREFIX .*" kernel: [ "*{D}+"."{D}+"]"
-CUT_HERE {PREFIX}" ------------[ cut here".*
-WARNING {PREFIX}" WARNING: at "
-END_TRACE {PREFIX}" ---[ end trace".*
-
-/* Use exclusive start conditions. */
-%x PRE_WARN WARN
-
-%%
- /* The scanner itself. */
-
-^{CUT_HERE}\n{WARNING} BEGIN(PRE_WARN);
-.|\n /* ignore all other input in state 0 */
-<PRE_WARN>[^ ]+.[^ ]+\n if (WarnStart()) {
- /* yytext is
- "file:line func+offset/offset()\n" */
- BEGIN(WARN); ECHO;
- } else {
- BEGIN(0);
- }
-
- /* Assume the warning ends at the "end trace" line */
-<WARN>^{END_TRACE}\n ECHO; BEGIN(0); WarnEnd();
-<WARN>^.*\n ECHO;
-
-%%
-
-#define HASH_BITMAP_SIZE (1 << 15) /* size in bits */
-#define HASH_BITMAP_MASK (HASH_BITMAP_SIZE - 1)
-
-const char warn_hist_name[] = "Platform.KernelWarningHashes";
-uint32_t hash_bitmap[HASH_BITMAP_SIZE / 32];
-CMetricsLibrary metrics_library;
-
-const char *prog_name; /* the name of this program */
-int yyin_fd; /* instead of FILE *yyin to avoid buffering */
-int i_fd; /* for inotify, to detect file changes */
-int testing; /* 1 if running test */
-int filter; /* 1 when using as filter (for development) */
-int fifo; /* 1 when reading from fifo (for devel) */
-int draining; /* 1 when draining renamed log file */
-
-const char *msg_path = "/var/log/messages";
-const char warn_dump_dir[] = "/var/run/kwarn";
-const char *warn_dump_path = "/var/run/kwarn/warning";
-const char *crash_reporter_command;
-
-__attribute__((__format__(__printf__, 1, 2)))
-static void Die(const char *format, ...) {
- va_list ap;
- va_start(ap, format);
- fprintf(stderr, "%s: ", prog_name);
- vfprintf(stderr, format, ap);
- exit(1);
-}
-
-static void RunCrashReporter(void) {
- int status = system(crash_reporter_command);
- if (status != 0)
- Die("%s exited with status %d\n", crash_reporter_command, status);
-}
-
-static uint32_t StringHash(const char *string) {
- uint32_t hash = 0;
- while (*string != '\0') {
- hash = (hash << 5) + hash + *string++;
- }
- return hash;
-}
-
-/* We expect only a handful of different warnings per boot session, so the
- * probability of a collision is very low, and statistically it won't matter
- * (unless warnings with the same hash also happens in tandem, which is even
- * rarer).
- */
-static int HashSeen(uint32_t hash) {
- int word_index = (hash & HASH_BITMAP_MASK) / 32;
- int bit_index = (hash & HASH_BITMAP_MASK) % 32;
- return hash_bitmap[word_index] & 1 << bit_index;
-}
-
-static void SetHashSeen(uint32_t hash) {
- int word_index = (hash & HASH_BITMAP_MASK) / 32;
- int bit_index = (hash & HASH_BITMAP_MASK) % 32;
- hash_bitmap[word_index] |= 1 << bit_index;
-}
-
-#pragma GCC diagnostic ignored "-Wwrite-strings"
-int WarnStart(void) {
- uint32_t hash;
- char *spacep;
-
- if (filter)
- return 1;
-
- hash = StringHash(yytext);
- if (!(testing || fifo || filter)) {
- CMetricsLibrarySendSparseToUMA(metrics_library, warn_hist_name, (int) hash);
- }
- if (HashSeen(hash))
- return 0;
- SetHashSeen(hash);
-
- yyout = fopen(warn_dump_path, "w");
- if (yyout == NULL)
- Die("fopen %s failed: %s\n", warn_dump_path, strerror(errno));
- spacep = strchr(yytext, ' ');
- if (spacep == NULL || spacep[1] == '\0')
- spacep = "unknown-function";
- fprintf(yyout, "%08x-%s\n", hash, spacep + 1);
- return 1;
-}
-
-void WarnEnd(void) {
- if (filter)
- return;
- fclose(yyout);
- yyout = stdout; /* for debugging */
- RunCrashReporter();
-}
-
-static void WarnOpenInput(const char *path) {
- yyin_fd = open(path, O_RDONLY);
- if (yyin_fd < 0)
- Die("could not open %s: %s\n", path, strerror(errno));
- if (!fifo) {
- /* Go directly to the end of the file. We don't want to parse the same
- * warnings multiple times on reboot/restart. We might miss some
- * warnings, but so be it---it's too hard to keep track reliably of the
- * last parsed position in the syslog.
- */
- if (lseek(yyin_fd, 0, SEEK_END) < 0)
- Die("could not lseek %s: %s\n", path, strerror(errno));
- /* Set up notification of file growth and rename. */
- i_fd = inotify_init();
- if (i_fd < 0)
- Die("inotify_init: %s\n", strerror(errno));
- if (inotify_add_watch(i_fd, path, IN_MODIFY | IN_MOVE_SELF) < 0)
- Die("inotify_add_watch: %s\n", strerror(errno));
- }
-}
-
-/* We replace the default YY_INPUT() for the following reasons:
- *
- * 1. We want to read data as soon as it becomes available, but the default
- * YY_INPUT() uses buffered I/O.
- *
- * 2. We want to block on end of input and wait for the file to grow.
- *
- * 3. We want to detect log rotation, and reopen the input file as needed.
- */
-void WarnInput(char *buf, yy_size_t *result, size_t max_size) {
- while (1) {
- ssize_t ret = read(yyin_fd, buf, max_size);
- if (ret < 0)
- Die("read: %s", strerror(errno));
- *result = ret;
- if (*result > 0 || fifo || filter)
- return;
- if (draining) {
- /* Assume we're done with this log, and move to next
- * log. Rsyslogd may keep writing to the old log file
- * for a while, but we don't care since we don't have
- * to be exact.
- */
- close(yyin_fd);
- if (YYSTATE == WARN) {
- /* Be conservative in case we lose the warn
- * terminator during the switch---or we may
- * collect personally identifiable information.
- */
- WarnEnd();
- }
- BEGIN(0); /* see above comment */
- sleep(1); /* avoid race with log rotator */
- WarnOpenInput(msg_path);
- draining = 0;
- continue;
- }
- /* Nothing left to read, so we must wait. */
- struct inotify_event event;
- while (1) {
- int n = read(i_fd, &event, sizeof(event));
- if (n <= 0) {
- if (errno == EINTR)
- continue;
- else
- Die("inotify: %s\n", strerror(errno));
- } else
- break;
- }
- if (event.mask & IN_MOVE_SELF) {
- /* The file has been renamed. Before switching
- * to the new one, we process any remaining
- * content of this file.
- */
- draining = 1;
- }
- }
-}
-
-int main(int argc, char **argv) {
- int result;
- struct passwd *user;
- prog_name = argv[0];
-
- if (argc == 2 && strcmp(argv[1], "--test") == 0)
- testing = 1;
- else if (argc == 2 && strcmp(argv[1], "--filter") == 0)
- filter = 1;
- else if (argc == 2 && strcmp(argv[1], "--fifo") == 0) {
- fifo = 1;
- } else if (argc != 1) {
- fprintf(stderr,
- "usage: %s [single-flag]\n"
- "flags (for testing only):\n"
- "--fifo\tinput is fifo \"fifo\", output is stdout\n"
- "--filter\tinput is stdin, output is stdout\n"
- "--test\trun self-test\n",
- prog_name);
- exit(1);
- }
-
- metrics_library = CMetricsLibraryNew();
- CMetricsLibraryInit(metrics_library);
-
- crash_reporter_command = testing ?
- "./warn_collector_test_reporter.sh" :
- "/sbin/crash_reporter --kernel_warning";
-
- /* When filtering with --filter (for development) use stdin for input.
- * Otherwise read input from a file or a fifo.
- */
- yyin_fd = fileno(stdin);
- if (testing) {
- msg_path = "messages";
- warn_dump_path = "warning";
- }
- if (fifo) {
- msg_path = "fifo";
- }
- if (!filter) {
- WarnOpenInput(msg_path);
- }
-
- /* Create directory for dump file. Still need to be root here. */
- unlink(warn_dump_path);
- if (!testing && !fifo && !filter) {
- rmdir(warn_dump_dir);
- result = mkdir(warn_dump_dir, 0755);
- if (result < 0)
- Die("could not create %s: %s\n",
- warn_dump_dir, strerror(errno));
- }
-
- if (0) {
- /* TODO(semenzato): put this back in once we decide it's safe
- * to make /var/spool/crash rwxrwxrwx root, or use a different
- * owner and setuid for the crash reporter as well.
- */
-
- /* Get low privilege uid, gid. */
- user = getpwnam("chronos");
- if (user == NULL)
- Die("getpwnam failed\n");
-
- /* Change dump directory ownership. */
- if (chown(warn_dump_dir, user->pw_uid, user->pw_gid) < 0)
- Die("chown: %s\n", strerror(errno));
-
- /* Drop privileges. */
- if (setuid(user->pw_uid) < 0) {
- Die("setuid: %s\n", strerror(errno));
- }
- }
-
- /* Go! */
- return yylex();
-}
-
-/* Flex should really know not to generate these functions.
- */
-void UnusedFunctionWarningSuppressor(void) {
- yyunput(0, 0);
-}
diff --git a/crash_reporter/warn_collector_test.c b/crash_reporter/warn_collector_test.c
deleted file mode 100644
index 7ebe0a8..0000000
--- a/crash_reporter/warn_collector_test.c
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-
-/*
- * Test driver for the warn_collector daemon.
- */
-#include <stdlib.h>
-
-int main(int ac, char **av) {
- int status = system("exec \"${SRC}\"/warn_collector_test.sh");
- return status < 0 ? EXIT_FAILURE : WEXITSTATUS(status);
-}
diff --git a/crash_reporter/warn_collector_test.sh b/crash_reporter/warn_collector_test.sh
deleted file mode 100755
index a5af16c..0000000
--- a/crash_reporter/warn_collector_test.sh
+++ /dev/null
@@ -1,90 +0,0 @@
-#! /bin/bash
-
-# Copyright (C) 2013 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.
-
-# Test for warn_collector. Run the warn collector in the background, emulate
-# the kernel by appending lines to the log file "messages", and observe the log
-# of the (fake) crash reporter each time is run by the warn collector daemon.
-
-set -e
-
-fail() {
- printf '[ FAIL ] %b\n' "$*"
- exit 1
-}
-
-if [[ -z ${SYSROOT} ]]; then
- fail "SYSROOT must be set for this test to work"
-fi
-: ${OUT:=${PWD}}
-cd "${OUT}"
-PATH=${OUT}:${PATH}
-TESTLOG="${OUT}/warn-test-log"
-
-echo "Testing: $(which warn_collector)"
-
-cleanup() {
- # Kill daemon (if started) on exit
- kill %
-}
-
-check_log() {
- local n_expected=$1
- if [[ ! -f ${TESTLOG} ]]; then
- fail "${TESTLOG} was not created"
- fi
- if [[ $(wc -l < "${TESTLOG}") -ne ${n_expected} ]]; then
- fail "expected ${n_expected} lines in ${TESTLOG}, found this instead:
-$(<"${TESTLOG}")"
- fi
- if egrep -qv '^[0-9a-f]{8}' "${TESTLOG}"; then
- fail "found bad lines in ${TESTLOG}:
-$(<"${TESTLOG}")"
- fi
-}
-
-rm -f "${TESTLOG}"
-cp "${SRC}/warn_collector_test_reporter.sh" .
-cp "${SRC}/TEST_WARNING" .
-cp TEST_WARNING messages
-
-# Start the collector daemon. With the --test option, the daemon reads input
-# from ./messages, writes the warning into ./warning, and invokes
-# ./warn_collector_test_reporter.sh to report the warning.
-warn_collector --test &
-trap cleanup EXIT
-
-# After a while, check that the first warning has been collected.
-sleep 1
-check_log 1
-
-# Add the same warning to messages, verify that it is NOT collected
-cat TEST_WARNING >> messages
-sleep 1
-check_log 1
-
-# Add a slightly different warning to messages, check that it is collected.
-sed s/intel_dp.c/intel_xx.c/ < TEST_WARNING >> messages
-sleep 1
-check_log 2
-
-# Emulate log rotation, add a warning, and check.
-mv messages messages.1
-sed s/intel_dp.c/intel_xy.c/ < TEST_WARNING > messages
-sleep 2
-check_log 3
-
-# Success!
-exit 0
diff --git a/crash_reporter/warn_collector_test_reporter.sh b/crash_reporter/warn_collector_test_reporter.sh
deleted file mode 100755
index b6096ed..0000000
--- a/crash_reporter/warn_collector_test_reporter.sh
+++ /dev/null
@@ -1,27 +0,0 @@
-#! /bin/sh
-
-# Copyright (C) 2013 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.
-
-# Replacement for the crash reporter, for testing. Log the first line of the
-# "warning" file, which by convention contains the warning hash, and remove the
-# file.
-
-set -e
-
-exec 1>> warn-test-log
-exec 2>> warn-test-log
-
-head -1 warning
-rm warning
diff --git a/include/system/graphics.h b/include/system/graphics.h
index a9e451f..529a562 100644
--- a/include/system/graphics.h
+++ b/include/system/graphics.h
@@ -477,6 +477,102 @@
uint32_t reserved[8];
};
+/*
+ * Structures for describing flexible YUVA/RGBA formats for consumption by
+ * applications. Such flexible formats contain a plane for each component (e.g.
+ * red, green, blue), where each plane is laid out in a grid-like pattern
+ * occupying unique byte addresses and with consistent byte offsets between
+ * neighboring pixels.
+ *
+ * The android_flex_layout structure is used with any pixel format that can be
+ * represented by it, such as:
+ * - HAL_PIXEL_FORMAT_YCbCr_*_888
+ * - HAL_PIXEL_FORMAT_FLEX_RGB*_888
+ * - HAL_PIXEL_FORMAT_RGB[AX]_888[8],BGRA_8888,RGB_888
+ * - HAL_PIXEL_FORMAT_YV12,Y8,Y16,YCbCr_422_SP/I,YCrCb_420_SP
+ * - even implementation defined formats that can be represented by
+ * the structures
+ *
+ * Vertical increment (aka. row increment or stride) describes the distance in
+ * bytes from the first pixel of one row to the first pixel of the next row
+ * (below) for the component plane. This can be negative.
+ *
+ * Horizontal increment (aka. column or pixel increment) describes the distance
+ * in bytes from one pixel to the next pixel (to the right) on the same row for
+ * the component plane. This can be negative.
+ *
+ * Each plane can be subsampled either vertically or horizontally by
+ * a power-of-two factor.
+ *
+ * The bit-depth of each component can be arbitrary, as long as the pixels are
+ * laid out on whole bytes, in native byte-order, using the most significant
+ * bits of each unit.
+ */
+
+typedef enum android_flex_component {
+ /* luma */
+ FLEX_COMPONENT_Y = 1 << 0,
+ /* chroma blue */
+ FLEX_COMPONENT_Cb = 1 << 1,
+ /* chroma red */
+ FLEX_COMPONENT_Cr = 1 << 2,
+
+ /* red */
+ FLEX_COMPONENT_R = 1 << 10,
+ /* green */
+ FLEX_COMPONENT_G = 1 << 11,
+ /* blue */
+ FLEX_COMPONENT_B = 1 << 12,
+
+ /* alpha */
+ FLEX_COMPONENT_A = 1 << 30,
+} android_flex_component_t;
+
+typedef struct android_flex_plane {
+ /* pointer to the first byte of the top-left pixel of the plane. */
+ uint8_t *top_left;
+
+ android_flex_component_t component;
+
+ /* bits allocated for the component in each pixel. Must be a positive
+ multiple of 8. */
+ int32_t bits_per_component;
+ /* number of the most significant bits used in the format for this
+ component. Must be between 1 and bits_per_component, inclusive. */
+ int32_t bits_used;
+
+ /* horizontal increment */
+ int32_t h_increment;
+ /* vertical increment */
+ int32_t v_increment;
+ /* horizontal subsampling. Must be a positive power of 2. */
+ int32_t h_subsampling;
+ /* vertical subsampling. Must be a positive power of 2. */
+ int32_t v_subsampling;
+} android_flex_plane_t;
+
+typedef enum android_flex_format {
+ /* not a flexible format */
+ FLEX_FORMAT_INVALID = 0x0,
+ FLEX_FORMAT_Y = FLEX_COMPONENT_Y,
+ FLEX_FORMAT_YCbCr = FLEX_COMPONENT_Y | FLEX_COMPONENT_Cb | FLEX_COMPONENT_Cr,
+ FLEX_FORMAT_YCbCrA = FLEX_FORMAT_YCbCr | FLEX_COMPONENT_A,
+ FLEX_FORMAT_RGB = FLEX_COMPONENT_R | FLEX_COMPONENT_G | FLEX_COMPONENT_B,
+ FLEX_FORMAT_RGBA = FLEX_FORMAT_RGB | FLEX_COMPONENT_A,
+} android_flex_format_t;
+
+typedef struct android_flex_layout {
+ /* the kind of flexible format */
+ android_flex_format_t format;
+
+ /* number of planes; 0 for FLEX_FORMAT_INVALID */
+ uint32_t num_planes;
+ /* a plane for each component; ordered in increasing component value order.
+ E.g. FLEX_FORMAT_RGBA maps 0 -> R, 1 -> G, etc.
+ Can be NULL for FLEX_FORMAT_INVALID */
+ android_flex_plane_t *planes;
+} android_flex_layout_t;
+
/**
* Structure used to define depth point clouds for format HAL_PIXEL_FORMAT_BLOB
* with dataSpace value of HAL_DATASPACE_DEPTH.
@@ -1039,6 +1135,236 @@
} android_dataspace_t;
/*
+ * Color modes that may be supported by a display.
+ *
+ * Definitions:
+ * Rendering intent generally defines the goal in mapping a source (input)
+ * color to a destination device color for a given color mode.
+ *
+ * It is important to keep in mind three cases where mapping may be applied:
+ * 1. The source gamut is much smaller than the destination (display) gamut
+ * 2. The source gamut is much larger than the destination gamut (this will
+ * ordinarily be handled using colorimetric rendering, below)
+ * 3. The source and destination gamuts are roughly equal, although not
+ * completely overlapping
+ * Also, a common requirement for mappings is that skin tones should be
+ * preserved, or at least remain natural in appearance.
+ *
+ * Colorimetric Rendering Intent (All cases):
+ * Colorimetric indicates that colors should be preserved. In the case
+ * that the source gamut lies wholly within the destination gamut or is
+ * about the same (#1, #3), this will simply mean that no manipulations
+ * (no saturation boost, for example) are applied. In the case where some
+ * source colors lie outside the destination gamut (#2, #3), those will
+ * need to be mapped to colors that are within the destination gamut,
+ * while the already in-gamut colors remain unchanged.
+ *
+ * Non-colorimetric transforms can take many forms. There are no hard
+ * rules and it's left to the implementation to define.
+ * Two common intents are described below.
+ *
+ * Stretched-Gamut Enhancement Intent (Source < Destination):
+ * When the destination gamut is much larger than the source gamut (#1), the
+ * source primaries may be redefined to reflect the full extent of the
+ * destination space, or to reflect an intermediate gamut.
+ * Skin-tone preservation would likely be applied. An example might be sRGB
+ * input displayed on a DCI-P3 capable device, with skin-tone preservation.
+ *
+ * Within-Gamut Enhancement Intent (Source >= Destination):
+ * When the device (destination) gamut is not larger than the source gamut
+ * (#2 or #3), but the appearance of a larger gamut is desired, techniques
+ * such as saturation boost may be applied to the source colors. Skin-tone
+ * preservation may be applied. There is no unique method for within-gamut
+ * enhancement; it would be defined within a flexible color mode.
+ *
+ */
+typedef enum android_color_mode {
+
+ /*
+ * HAL_COLOR_MODE_DEFAULT is the "native" gamut of the display.
+ * White Point: Vendor/OEM defined
+ * Panel Gamma: Vendor/OEM defined (typically 2.2)
+ * Rendering Intent: Vendor/OEM defined (typically 'enhanced')
+ */
+ HAL_COLOR_MODE_NATIVE = 0,
+
+ /*
+ * HAL_COLOR_MODE_STANDARD_BT601_625 corresponds with display
+ * settings that implement the ITU-R Recommendation BT.601
+ * or Rec 601. Using 625 line version
+ * Rendering Intent: Colorimetric
+ * Primaries:
+ * x y
+ * green 0.290 0.600
+ * blue 0.150 0.060
+ * red 0.640 0.330
+ * white (D65) 0.3127 0.3290
+ *
+ * KR = 0.299, KB = 0.114. This adjusts the luminance interpretation
+ * for RGB conversion from the one purely determined by the primaries
+ * to minimize the color shift into RGB space that uses BT.709
+ * primaries.
+ *
+ * Gamma Correction (GC):
+ *
+ * if Vlinear < 0.018
+ * Vnonlinear = 4.500 * Vlinear
+ * else
+ * Vnonlinear = 1.099 * (Vlinear)^(0.45) – 0.099
+ */
+ HAL_COLOR_MODE_STANDARD_BT601_625 = 1,
+
+ /*
+ * Primaries:
+ * x y
+ * green 0.290 0.600
+ * blue 0.150 0.060
+ * red 0.640 0.330
+ * white (D65) 0.3127 0.3290
+ *
+ * Use the unadjusted KR = 0.222, KB = 0.071 luminance interpretation
+ * for RGB conversion.
+ *
+ * Gamma Correction (GC):
+ *
+ * if Vlinear < 0.018
+ * Vnonlinear = 4.500 * Vlinear
+ * else
+ * Vnonlinear = 1.099 * (Vlinear)^(0.45) – 0.099
+ */
+ HAL_COLOR_MODE_STANDARD_BT601_625_UNADJUSTED = 2,
+
+ /*
+ * Primaries:
+ * x y
+ * green 0.310 0.595
+ * blue 0.155 0.070
+ * red 0.630 0.340
+ * white (D65) 0.3127 0.3290
+ *
+ * KR = 0.299, KB = 0.114. This adjusts the luminance interpretation
+ * for RGB conversion from the one purely determined by the primaries
+ * to minimize the color shift into RGB space that uses BT.709
+ * primaries.
+ *
+ * Gamma Correction (GC):
+ *
+ * if Vlinear < 0.018
+ * Vnonlinear = 4.500 * Vlinear
+ * else
+ * Vnonlinear = 1.099 * (Vlinear)^(0.45) – 0.099
+ */
+ HAL_COLOR_MODE_STANDARD_BT601_525 = 3,
+
+ /*
+ * Primaries:
+ * x y
+ * green 0.310 0.595
+ * blue 0.155 0.070
+ * red 0.630 0.340
+ * white (D65) 0.3127 0.3290
+ *
+ * Use the unadjusted KR = 0.212, KB = 0.087 luminance interpretation
+ * for RGB conversion (as in SMPTE 240M).
+ *
+ * Gamma Correction (GC):
+ *
+ * if Vlinear < 0.018
+ * Vnonlinear = 4.500 * Vlinear
+ * else
+ * Vnonlinear = 1.099 * (Vlinear)^(0.45) – 0.099
+ */
+ HAL_COLOR_MODE_STANDARD_BT601_525_UNADJUSTED = 4,
+
+ /*
+ * HAL_COLOR_MODE_REC709 corresponds with display settings that implement
+ * the ITU-R Recommendation BT.709 / Rec. 709 for high-definition television.
+ * Rendering Intent: Colorimetric
+ * Primaries:
+ * x y
+ * green 0.300 0.600
+ * blue 0.150 0.060
+ * red 0.640 0.330
+ * white (D65) 0.3127 0.3290
+ *
+ * HDTV REC709 Inverse Gamma Correction (IGC): V represents normalized
+ * (with [0 to 1] range) value of R, G, or B.
+ *
+ * if Vnonlinear < 0.081
+ * Vlinear = Vnonlinear / 4.5
+ * else
+ * Vlinear = ((Vnonlinear + 0.099) / 1.099) ^ (1/0.45)
+ *
+ * HDTV REC709 Gamma Correction (GC):
+ *
+ * if Vlinear < 0.018
+ * Vnonlinear = 4.5 * Vlinear
+ * else
+ * Vnonlinear = 1.099 * (Vlinear) ^ 0.45 – 0.099
+ */
+ HAL_COLOR_MODE_STANDARD_BT709 = 5,
+
+ /*
+ * HAL_COLOR_MODE_DCI_P3 corresponds with display settings that implement
+ * SMPTE EG 432-1 and SMPTE RP 431-2
+ * Rendering Intent: Colorimetric
+ * Primaries:
+ * x y
+ * green 0.265 0.690
+ * blue 0.150 0.060
+ * red 0.680 0.320
+ * white (D65) 0.3127 0.3290
+ *
+ * Gamma: 2.2
+ */
+ HAL_COLOR_MODE_DCI_P3 = 6,
+
+ /*
+ * HAL_COLOR_MODE_SRGB corresponds with display settings that implement
+ * the sRGB color space. Uses the same primaries as ITU-R Recommendation
+ * BT.709
+ * Rendering Intent: Colorimetric
+ * Primaries:
+ * x y
+ * green 0.300 0.600
+ * blue 0.150 0.060
+ * red 0.640 0.330
+ * white (D65) 0.3127 0.3290
+ *
+ * PC/Internet (sRGB) Inverse Gamma Correction (IGC):
+ *
+ * if Vnonlinear ≤ 0.03928
+ * Vlinear = Vnonlinear / 12.92
+ * else
+ * Vlinear = ((Vnonlinear + 0.055)/1.055) ^ 2.4
+ *
+ * PC/Internet (sRGB) Gamma Correction (GC):
+ *
+ * if Vlinear ≤ 0.0031308
+ * Vnonlinear = 12.92 * Vlinear
+ * else
+ * Vnonlinear = 1.055 * (Vlinear)^(1/2.4) – 0.055
+ */
+ HAL_COLOR_MODE_SRGB = 7,
+
+ /*
+ * HAL_COLOR_MODE_ADOBE_RGB corresponds with the RGB color space developed
+ * by Adobe Systems, Inc. in 1998.
+ * Rendering Intent: Colorimetric
+ * Primaries:
+ * x y
+ * green 0.210 0.710
+ * blue 0.150 0.060
+ * red 0.640 0.330
+ * white (D65) 0.3127 0.3290
+ *
+ * Gamma: 2.2
+ */
+ HAL_COLOR_MODE_ADOBE_RGB = 8
+
+} android_color_mode_t;
+
+/*
* Color transforms that may be applied by hardware composer to the whole
* display.
*/
diff --git a/libnetutils/Android.mk b/libnetutils/Android.mk
index ce7c3ba..2150279 100644
--- a/libnetutils/Android.mk
+++ b/libnetutils/Android.mk
@@ -19,10 +19,3 @@
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
include $(BUILD_SHARED_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := dhcptool.c
-LOCAL_SHARED_LIBRARIES := libnetutils
-LOCAL_MODULE := dhcptool
-LOCAL_MODULE_TAGS := debug
-include $(BUILD_EXECUTABLE)
diff --git a/libnetutils/dhcptool.c b/libnetutils/dhcptool.c
deleted file mode 100644
index d23afd3..0000000
--- a/libnetutils/dhcptool.c
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 2015, 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 <err.h>
-#include <errno.h>
-#include <error.h>
-#include <stdbool.h>
-#include <stdlib.h>
-
-#include <netutils/ifc.h>
-
-extern int do_dhcp(char*);
-
-int main(int argc, char* argv[]) {
- if (argc != 2) {
- error(EXIT_FAILURE, 0, "usage: %s INTERFACE", argv[0]);
- }
-
- char* interface = argv[1];
- if (ifc_init()) {
- err(errno, "dhcptool %s: ifc_init failed", interface);
- ifc_close();
- return EXIT_FAILURE;
- }
-
- int rc = do_dhcp(interface);
- if (rc) {
- err(errno, "dhcptool %s: do_dhcp failed", interface);
- }
-
- ifc_close();
-
- return rc ? EXIT_FAILURE : EXIT_SUCCESS;
-}
diff --git a/metricsd/.clang-format b/metricsd/.clang-format
deleted file mode 120000
index f9066d4..0000000
--- a/metricsd/.clang-format
+++ /dev/null
@@ -1 +0,0 @@
-../../../build/tools/brillo-clang-format
\ No newline at end of file
diff --git a/metricsd/Android.mk b/metricsd/Android.mk
deleted file mode 100644
index 65ca1f6..0000000
--- a/metricsd/Android.mk
+++ /dev/null
@@ -1,226 +0,0 @@
-# Copyright (C) 2015 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.
-
-LOCAL_PATH := $(call my-dir)
-
-metrics_cpp_extension := .cc
-libmetrics_sources := \
- c_metrics_library.cc \
- metrics_library.cc \
- timer.cc
-
-metrics_client_sources := \
- metrics_client.cc
-
-metrics_collector_common := \
- collectors/averaged_statistics_collector.cc \
- collectors/cpu_usage_collector.cc \
- collectors/disk_usage_collector.cc \
- metrics_collector.cc \
- metrics_collector_service_impl.cc \
- persistent_integer.cc
-
-metricsd_common := \
- persistent_integer.cc \
- uploader/bn_metricsd_impl.cc \
- uploader/crash_counters.cc \
- uploader/metrics_hashes.cc \
- uploader/metrics_log_base.cc \
- uploader/metrics_log.cc \
- uploader/metricsd_service_runner.cc \
- uploader/sender_http.cc \
- uploader/system_profile_cache.cc \
- uploader/upload_service.cc
-
-metrics_collector_tests_sources := \
- collectors/averaged_statistics_collector_test.cc \
- collectors/cpu_usage_collector_test.cc \
- metrics_collector_test.cc \
- metrics_library_test.cc \
- persistent_integer_test.cc \
- timer_test.cc
-
-metricsd_tests_sources := \
- uploader/metrics_hashes_unittest.cc \
- uploader/metrics_log_base_unittest.cc \
- uploader/mock/sender_mock.cc \
- uploader/upload_service_test.cc
-
-metrics_CFLAGS := -Wall \
- -Wno-char-subscripts \
- -Wno-missing-field-initializers \
- -Wno-unused-parameter \
- -Werror \
- -fvisibility=default
-metrics_CPPFLAGS := -Wno-non-virtual-dtor \
- -Wno-sign-promo \
- -Wno-strict-aliasing \
- -fvisibility=default
-metrics_includes := external/gtest/include \
- $(LOCAL_PATH)/include
-libmetrics_shared_libraries := libchrome libbinder libbrillo libutils
-metrics_collector_shared_libraries := $(libmetrics_shared_libraries) \
- libbrillo-binder \
- libbrillo-http \
- libmetrics \
- librootdev \
- libweaved
-
-metrics_collector_static_libraries := libmetricscollectorservice
-
-metricsd_shared_libraries := \
- libbinder \
- libbrillo \
- libbrillo-binder \
- libbrillo-http \
- libchrome \
- libprotobuf-cpp-lite \
- libupdate_engine_client \
- libutils
-
-# Static proxy library for the metricsd binder interface.
-# ========================================================
-include $(CLEAR_VARS)
-LOCAL_MODULE := metricsd_binder_proxy
-LOCAL_SHARED_LIBRARIES := libbinder libutils
-LOCAL_SRC_FILES := aidl/android/brillo/metrics/IMetricsd.aidl
-include $(BUILD_STATIC_LIBRARY)
-
-# Static library for the metrics_collector binder interface.
-# ==========================================================
-include $(CLEAR_VARS)
-LOCAL_MODULE := libmetricscollectorservice
-LOCAL_CLANG := true
-LOCAL_SHARED_LIBRARIES := libbinder libbrillo-binder libchrome libutils
-LOCAL_CPP_EXTENSION := $(metrics_cpp_extension)
-LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-LOCAL_SRC_FILES := \
- aidl/android/brillo/metrics/IMetricsCollectorService.aidl \
- metrics_collector_service_client.cc
-include $(BUILD_STATIC_LIBRARY)
-
-# Shared library for metrics.
-# ========================================================
-include $(CLEAR_VARS)
-LOCAL_MODULE := libmetrics
-LOCAL_C_INCLUDES := $(metrics_includes)
-LOCAL_CFLAGS := $(metrics_CFLAGS)
-LOCAL_CLANG := true
-LOCAL_CPP_EXTENSION := $(metrics_cpp_extension)
-LOCAL_CPPFLAGS := $(metrics_CPPFLAGS)
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-LOCAL_SHARED_LIBRARIES := $(libmetrics_shared_libraries)
-LOCAL_SRC_FILES := $(libmetrics_sources)
-LOCAL_STATIC_LIBRARIES := metricsd_binder_proxy
-include $(BUILD_SHARED_LIBRARY)
-
-# CLI client for metrics.
-# ========================================================
-include $(CLEAR_VARS)
-LOCAL_MODULE := metrics_client
-LOCAL_C_INCLUDES := $(metrics_includes)
-LOCAL_CFLAGS := $(metrics_CFLAGS)
-LOCAL_CLANG := true
-LOCAL_CPP_EXTENSION := $(metrics_cpp_extension)
-LOCAL_CPPFLAGS := $(metrics_CPPFLAGS)
-LOCAL_SHARED_LIBRARIES := $(libmetrics_shared_libraries) \
- libmetrics
-LOCAL_SRC_FILES := $(metrics_client_sources)
-LOCAL_STATIC_LIBRARIES := metricsd_binder_proxy
-include $(BUILD_EXECUTABLE)
-
-# Protobuf library for metricsd.
-# ========================================================
-include $(CLEAR_VARS)
-LOCAL_MODULE := metricsd_protos
-LOCAL_MODULE_CLASS := STATIC_LIBRARIES
-generated_sources_dir := $(call local-generated-sources-dir)
-LOCAL_EXPORT_C_INCLUDE_DIRS += \
- $(generated_sources_dir)/proto/system/core/metricsd
-LOCAL_SRC_FILES := $(call all-proto-files-under,uploader/proto)
-include $(BUILD_STATIC_LIBRARY)
-
-# metrics_collector daemon.
-# ========================================================
-include $(CLEAR_VARS)
-LOCAL_MODULE := metrics_collector
-LOCAL_C_INCLUDES := $(metrics_includes)
-LOCAL_CFLAGS := $(metrics_CFLAGS)
-LOCAL_CLANG := true
-LOCAL_CPP_EXTENSION := $(metrics_cpp_extension)
-LOCAL_CPPFLAGS := $(metrics_CPPFLAGS)
-LOCAL_INIT_RC := metrics_collector.rc
-LOCAL_REQUIRED_MODULES := metrics.json
-LOCAL_SHARED_LIBRARIES := $(metrics_collector_shared_libraries)
-LOCAL_SRC_FILES := $(metrics_collector_common) \
- metrics_collector_main.cc
-LOCAL_STATIC_LIBRARIES := metricsd_binder_proxy \
- $(metrics_collector_static_libraries)
-include $(BUILD_EXECUTABLE)
-
-# metricsd daemon.
-# ========================================================
-include $(CLEAR_VARS)
-LOCAL_MODULE := metricsd
-LOCAL_C_INCLUDES := $(metrics_includes)
-LOCAL_CFLAGS := $(metrics_CFLAGS)
-LOCAL_CLANG := true
-LOCAL_CPP_EXTENSION := $(metrics_cpp_extension)
-LOCAL_CPPFLAGS := $(metrics_CPPFLAGS)
-LOCAL_INIT_RC := metricsd.rc
-LOCAL_REQUIRED_MODULES := \
- metrics_collector
-LOCAL_SHARED_LIBRARIES := $(metricsd_shared_libraries)
-LOCAL_STATIC_LIBRARIES := metricsd_protos metricsd_binder_proxy
-LOCAL_SRC_FILES := $(metricsd_common) \
- metricsd_main.cc
-include $(BUILD_EXECUTABLE)
-
-# Unit tests for metricsd.
-# ========================================================
-include $(CLEAR_VARS)
-LOCAL_MODULE := metricsd_tests
-LOCAL_CFLAGS := $(metrics_CFLAGS)
-LOCAL_CLANG := true
-LOCAL_CPP_EXTENSION := $(metrics_cpp_extension)
-LOCAL_CPPFLAGS := $(metrics_CPPFLAGS) -Wno-sign-compare
-LOCAL_SHARED_LIBRARIES := $(metricsd_shared_libraries)
-LOCAL_SRC_FILES := $(metricsd_tests_sources) $(metricsd_common)
-LOCAL_STATIC_LIBRARIES := libBionicGtestMain libgmock metricsd_protos metricsd_binder_proxy
-include $(BUILD_NATIVE_TEST)
-
-# Unit tests for metrics_collector.
-# ========================================================
-include $(CLEAR_VARS)
-LOCAL_MODULE := metrics_collector_tests
-LOCAL_CFLAGS := $(metrics_CFLAGS)
-LOCAL_CLANG := true
-LOCAL_CPP_EXTENSION := $(metrics_cpp_extension)
-LOCAL_CPPFLAGS := $(metrics_CPPFLAGS) -Wno-sign-compare
-LOCAL_SHARED_LIBRARIES := $(metrics_collector_shared_libraries)
-LOCAL_SRC_FILES := $(metrics_collector_tests_sources) \
- $(metrics_collector_common)
-LOCAL_STATIC_LIBRARIES := libBionicGtestMain libgmock metricsd_binder_proxy \
- $(metrics_collector_static_libraries)
-include $(BUILD_NATIVE_TEST)
-
-# Weave schema files
-# ========================================================
-include $(CLEAR_VARS)
-LOCAL_MODULE := metrics.json
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/weaved/traits
-LOCAL_SRC_FILES := etc/weaved/traits/$(LOCAL_MODULE)
-include $(BUILD_PREBUILT)
diff --git a/metricsd/OWNERS b/metricsd/OWNERS
deleted file mode 100644
index 7f5e50d..0000000
--- a/metricsd/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-semenzato@chromium.org
-derat@chromium.org
-bsimonnet@chromium.org
diff --git a/metricsd/README.md b/metricsd/README.md
deleted file mode 100644
index 8d4828c..0000000
--- a/metricsd/README.md
+++ /dev/null
@@ -1,124 +0,0 @@
-Metricsd
-========
-
-The metricsd daemon is used to gather metrics from the platform and application,
-aggregate them and upload them periodically to a server.
-The metrics will then be available in their aggregated form to the developer
-for analysis.
-
-Three components are provided to interact with `metricsd`: `libmetrics`,
-`metrics_collector` and `metrics_client`.
-
-The Metrics Library: libmetrics
--------------------------------
-
-`libmetrics` is a small library that implements the basic C++ API for
-metrics collection. All metrics collection is funneled through this library. The
-easiest and recommended way for a client-side module to collect user metrics is
-to link `libmetrics` and use its APIs to send metrics to `metricsd` for transport to
-UMA. In order to use the library in a module, you need to do the following:
-
-- Add a dependency on the shared library in your Android.mk file:
- `LOCAL_SHARED_LIBRARIES += libmetrics`
-
-- To access the metrics library API in the module, include the
- <metrics/metrics_library.h> header file.
-
-- The API is documented in `metrics_library.h`. Before using the API methods, a
- MetricsLibrary object needs to be constructed and initialized through its
- Init method.
-
-- Samples are uploaded only if the `/data/misc/metrics/enabled` file exists.
-
-
-Server Side
------------
-
-You will be able to see all uploaded metrics on the metrics dashboard,
-accessible via the developer console.
-
-*** note
-It usually takes a day for metrics to be available on the dashboard.
-***
-
-
-The Metrics Client: metrics_client
-----------------------------------
-
-`metrics_client` is a simple shell command-line utility for sending histogram
-samples and querying `metricsd`. It's installed under `/system/bin` on the target
-platform and uses `libmetrics`.
-
-For usage information and command-line options, run `metrics_client` on the
-target platform or look for "Usage:" in `metrics_client.cc`.
-
-
-The Metrics Daemon: metricsd
-----------------------------
-
-`metricsd` is the daemon that listens for metrics logging calls (via Binder),
-aggregates the metrics and uploads them periodically. This daemon should start as
-early as possible so that depending daemons can log at any time.
-
-`metricsd` is made of two threads that work as follows:
-
-* The binder thread listens for one-way Binder calls, aggregates the metrics in
- memory (via `base::StatisticsRecorder`) and increments the crash counters when a
- crash is reported. This thread is kept as simple as possible to ensure the
- maximum throughput possible.
-* The uploader thread takes care of backing up the metrics to disk periodically
- (to avoid losing metrics on crashes), collecting metadata about the client
- (version number, channel, etc..) and uploading the metrics periodically to the
- server.
-
-
-The Metrics Collector: metrics_collector
-----------------------------------------
-
-metrics_collector is a daemon that runs in the background on the target platform,
-gathers health information about the system and maintains long running counters
-(ex: number of crashes per week).
-
-The recommended way to generate metrics data from a module is to link and use
-libmetrics directly. However, we may not want to add a dependency on libmetrics
-to some modules (ex: kernel). In this case, we can add a collector to
-metrics_collector that will, for example, take measurements and report them
-periodically to metricsd (this is the case for the disk utilization histogram).
-
-
-FAQ
----
-
-### What should my histogram's |min| and |max| values be set at?
-
-You should set the values to a range that covers the vast majority of samples
-that would appear in the field. Note that samples below the |min| will still
-be collected in the underflow bucket and samples above the |max| will end up
-in the overflow bucket. Also, the reported mean of the data will be correct
-regardless of the range.
-
-### How many buckets should I use in my histogram?
-
-You should allocate as many buckets as necessary to perform proper analysis
-on the collected data. Note, however, that the memory allocated in metricsd
-for each histogram is proportional to the number of buckets. Therefore, it is
-strongly recommended to keep this number low (e.g., 50 is normal, while 100
-is probably high).
-
-### When should I use an enumeration (linear) histogram vs. a regular (exponential) histogram?
-
-Enumeration histograms should really be used only for sampling enumerated
-events and, in some cases, percentages. Normally, you should use a regular
-histogram with exponential bucket layout that provides higher resolution at
-the low end of the range and lower resolution at the high end. Regular
-histograms are generally used for collecting performance data (e.g., timing,
-memory usage, power) as well as aggregated event counts.
-
-### How can I test that my histogram was reported correctly?
-
-* Make sure no error messages appear in logcat when you log a sample.
-* Run `metrics_client -d` to dump the currently aggregated metrics. Your
- histogram should appear in the list.
-* Make sure that the aggregated metrics were uploaded to the server successfully
- (check for an OK message from `metricsd` in logcat).
-* After a day, your histogram should be available on the dashboard.
diff --git a/metricsd/WATCHLISTS b/metricsd/WATCHLISTS
deleted file mode 100644
index a051f35..0000000
--- a/metricsd/WATCHLISTS
+++ /dev/null
@@ -1,16 +0,0 @@
-# See http://dev.chromium.org/developers/contributing-code/watchlists for
-# a description of this file's format.
-# Please keep these keys in alphabetical order.
-
-{
- 'WATCHLIST_DEFINITIONS': {
- 'all': {
- 'filepath': '.',
- },
- },
- 'WATCHLISTS': {
- 'all': ['petkov@chromium.org',
- 'semenzato@chromium.org',
- 'sosa@chromium.org']
- },
-}
diff --git a/metricsd/aidl/android/brillo/metrics/IMetricsCollectorService.aidl b/metricsd/aidl/android/brillo/metrics/IMetricsCollectorService.aidl
deleted file mode 100644
index 49f484f..0000000
--- a/metricsd/aidl/android/brillo/metrics/IMetricsCollectorService.aidl
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (C) 2015 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.brillo.metrics;
-
-interface IMetricsCollectorService {
- oneway void notifyUserCrash();
-}
diff --git a/metricsd/aidl/android/brillo/metrics/IMetricsd.aidl b/metricsd/aidl/android/brillo/metrics/IMetricsd.aidl
deleted file mode 100644
index aa3cb34..0000000
--- a/metricsd/aidl/android/brillo/metrics/IMetricsd.aidl
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2015 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.brillo.metrics;
-
-interface IMetricsd {
- oneway void recordHistogram(String name, int sample, int min, int max,
- int nbuckets);
- oneway void recordLinearHistogram(String name, int sample, int max);
- oneway void recordSparseHistogram(String name, int sample);
- oneway void recordCrash(String type);
- String getHistogramsDump();
-}
diff --git a/metricsd/c_metrics_library.cc b/metricsd/c_metrics_library.cc
deleted file mode 100644
index 47a543e..0000000
--- a/metricsd/c_metrics_library.cc
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-
-//
-// C wrapper to libmetrics
-//
-
-#include "metrics/c_metrics_library.h"
-
-#include <string>
-
-#include "metrics/metrics_library.h"
-
-extern "C" CMetricsLibrary CMetricsLibraryNew(void) {
- MetricsLibrary* lib = new MetricsLibrary;
- return reinterpret_cast<CMetricsLibrary>(lib);
-}
-
-extern "C" void CMetricsLibraryDelete(CMetricsLibrary handle) {
- MetricsLibrary* lib = reinterpret_cast<MetricsLibrary*>(handle);
- delete lib;
-}
-
-extern "C" void CMetricsLibraryInit(CMetricsLibrary handle) {
- MetricsLibrary* lib = reinterpret_cast<MetricsLibrary*>(handle);
- if (lib != NULL)
- lib->Init();
-}
-
-extern "C" int CMetricsLibrarySendToUMA(CMetricsLibrary handle,
- const char* name, int sample,
- int min, int max, int nbuckets) {
- MetricsLibrary* lib = reinterpret_cast<MetricsLibrary*>(handle);
- if (lib == NULL)
- return 0;
- return lib->SendToUMA(std::string(name), sample, min, max, nbuckets);
-}
-
-extern "C" int CMetricsLibrarySendEnumToUMA(CMetricsLibrary handle,
- const char* name, int sample,
- int max) {
- MetricsLibrary* lib = reinterpret_cast<MetricsLibrary*>(handle);
- if (lib == NULL)
- return 0;
- return lib->SendEnumToUMA(std::string(name), sample, max);
-}
-
-extern "C" int CMetricsLibrarySendSparseToUMA(CMetricsLibrary handle,
- const char* name, int sample) {
- MetricsLibrary* lib = reinterpret_cast<MetricsLibrary*>(handle);
- if (lib == NULL)
- return 0;
- return lib->SendSparseToUMA(std::string(name), sample);
-}
-
-extern "C" int CMetricsLibrarySendCrashToUMA(CMetricsLibrary handle,
- const char* crash_kind) {
- MetricsLibrary* lib = reinterpret_cast<MetricsLibrary*>(handle);
- if (lib == NULL)
- return 0;
- return lib->SendCrashToUMA(crash_kind);
-}
-
-extern "C" int CMetricsLibraryAreMetricsEnabled(CMetricsLibrary handle) {
- MetricsLibrary* lib = reinterpret_cast<MetricsLibrary*>(handle);
- if (lib == NULL)
- return 0;
- return lib->AreMetricsEnabled();
-}
diff --git a/metricsd/collectors/averaged_statistics_collector.cc b/metricsd/collectors/averaged_statistics_collector.cc
deleted file mode 100644
index a3aaa98..0000000
--- a/metricsd/collectors/averaged_statistics_collector.cc
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- * Copyright (C) 2015 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 "averaged_statistics_collector.h"
-
-#include <base/bind.h>
-#include <base/files/file_util.h>
-#include <base/files/file_path.h>
-#include <base/strings/string_number_conversions.h>
-#include <base/strings/string_split.h>
-
-#include "metrics_collector.h"
-
-namespace {
-
-// disk stats metrics
-
-// The {Read,Write}Sectors numbers are in sectors/second.
-// A sector is usually 512 bytes.
-const char kReadSectorsHistogramName[] = "Platform.ReadSectors";
-const char kWriteSectorsHistogramName[] = "Platform.WriteSectors";
-const int kDiskMetricsStatItemCount = 11;
-
-// Assume a max rate of 250Mb/s for reads (worse for writes) and 512 byte
-// sectors.
-const int kSectorsIOMax = 500000; // sectors/second
-const int kSectorsBuckets = 50; // buckets
-
-// Page size is 4k, sector size is 0.5k. We're not interested in page fault
-// rates that the disk cannot sustain.
-const int kPageFaultsMax = kSectorsIOMax / 8; // Page faults/second
-const int kPageFaultsBuckets = 50;
-
-// Major page faults, i.e. the ones that require data to be read from disk.
-const char kPageFaultsHistogramName[] = "Platform.PageFaults";
-
-// Swap in and Swap out
-const char kSwapInHistogramName[] = "Platform.SwapIn";
-const char kSwapOutHistogramName[] = "Platform.SwapOut";
-
-const int kIntervalBetweenCollection = 60; // seconds
-const int kCollectionDuration = 1; // seconds
-
-} // namespace
-
-AveragedStatisticsCollector::AveragedStatisticsCollector(
- MetricsLibraryInterface* metrics_library,
- const std::string& diskstats_path,
- const std::string& vmstats_path) :
- metrics_lib_(metrics_library),
- diskstats_path_(diskstats_path),
- vmstats_path_(vmstats_path) {
-}
-
-void AveragedStatisticsCollector::ScheduleWait() {
- base::MessageLoop::current()->PostDelayedTask(FROM_HERE,
- base::Bind(&AveragedStatisticsCollector::WaitCallback,
- base::Unretained(this)),
- base::TimeDelta::FromSeconds(
- kIntervalBetweenCollection - kCollectionDuration));
-}
-
-void AveragedStatisticsCollector::ScheduleCollect() {
- base::MessageLoop::current()->PostDelayedTask(FROM_HERE,
- base::Bind(&AveragedStatisticsCollector::CollectCallback,
- base::Unretained(this)),
- base::TimeDelta::FromSeconds(kCollectionDuration));
-}
-
-void AveragedStatisticsCollector::WaitCallback() {
- ReadInitialValues();
- ScheduleCollect();
-}
-
-void AveragedStatisticsCollector::CollectCallback() {
- Collect();
- ScheduleWait();
-}
-
-void AveragedStatisticsCollector::ReadInitialValues() {
- stats_start_time_ = MetricsCollector::GetActiveTime();
- DiskStatsReadStats(&read_sectors_, &write_sectors_);
- VmStatsReadStats(&vmstats_);
-}
-
-bool AveragedStatisticsCollector::DiskStatsReadStats(
- uint64_t* read_sectors, uint64_t* write_sectors) {
- CHECK(read_sectors);
- CHECK(write_sectors);
- std::string line;
- if (diskstats_path_.empty()) {
- return false;
- }
-
- if (!base::ReadFileToString(base::FilePath(diskstats_path_), &line)) {
- PLOG(WARNING) << "Could not read disk stats from "
- << diskstats_path_.value();
- return false;
- }
-
- std::vector<std::string> parts = base::SplitString(
- line, " ", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
- if (parts.size() != kDiskMetricsStatItemCount) {
- LOG(ERROR) << "Could not parse disk stat correctly. Expected "
- << kDiskMetricsStatItemCount << " elements but got "
- << parts.size();
- return false;
- }
- if (!base::StringToUint64(parts[2], read_sectors)) {
- LOG(ERROR) << "Couldn't convert read sectors " << parts[2] << " to uint64";
- return false;
- }
- if (!base::StringToUint64(parts[6], write_sectors)) {
- LOG(ERROR) << "Couldn't convert write sectors " << parts[6] << " to uint64";
- return false;
- }
-
- return true;
-}
-
-bool AveragedStatisticsCollector::VmStatsParseStats(
- const char* stats, struct VmstatRecord* record) {
- CHECK(stats);
- CHECK(record);
- base::StringPairs pairs;
- base::SplitStringIntoKeyValuePairs(stats, ' ', '\n', &pairs);
-
- for (base::StringPairs::iterator it = pairs.begin();
- it != pairs.end(); ++it) {
- if (it->first == "pgmajfault" &&
- !base::StringToUint64(it->second, &record->page_faults)) {
- return false;
- }
- if (it->first == "pswpin" &&
- !base::StringToUint64(it->second, &record->swap_in)) {
- return false;
- }
- if (it->first == "pswpout" &&
- !base::StringToUint64(it->second, &record->swap_out)) {
- return false;
- }
- }
- return true;
-}
-
-bool AveragedStatisticsCollector::VmStatsReadStats(struct VmstatRecord* stats) {
- CHECK(stats);
- std::string value_string;
- if (!base::ReadFileToString(vmstats_path_, &value_string)) {
- LOG(WARNING) << "cannot read " << vmstats_path_.value();
- return false;
- }
- return VmStatsParseStats(value_string.c_str(), stats);
-}
-
-void AveragedStatisticsCollector::Collect() {
- uint64_t read_sectors_now, write_sectors_now;
- struct VmstatRecord vmstats_now;
- double time_now = MetricsCollector::GetActiveTime();
- double delta_time = time_now - stats_start_time_;
- bool diskstats_success = DiskStatsReadStats(&read_sectors_now,
- &write_sectors_now);
-
- int delta_read = read_sectors_now - read_sectors_;
- int delta_write = write_sectors_now - write_sectors_;
- int read_sectors_per_second = delta_read / delta_time;
- int write_sectors_per_second = delta_write / delta_time;
- bool vmstats_success = VmStatsReadStats(&vmstats_now);
- uint64_t delta_faults = vmstats_now.page_faults - vmstats_.page_faults;
- uint64_t delta_swap_in = vmstats_now.swap_in - vmstats_.swap_in;
- uint64_t delta_swap_out = vmstats_now.swap_out - vmstats_.swap_out;
- uint64_t page_faults_per_second = delta_faults / delta_time;
- uint64_t swap_in_per_second = delta_swap_in / delta_time;
- uint64_t swap_out_per_second = delta_swap_out / delta_time;
- if (diskstats_success) {
- metrics_lib_->SendToUMA(kReadSectorsHistogramName,
- read_sectors_per_second,
- 1,
- kSectorsIOMax,
- kSectorsBuckets);
- metrics_lib_->SendToUMA(kWriteSectorsHistogramName,
- write_sectors_per_second,
- 1,
- kSectorsIOMax,
- kSectorsBuckets);
- }
- if (vmstats_success) {
- metrics_lib_->SendToUMA(kPageFaultsHistogramName,
- page_faults_per_second,
- 1,
- kPageFaultsMax,
- kPageFaultsBuckets);
- metrics_lib_->SendToUMA(kSwapInHistogramName,
- swap_in_per_second,
- 1,
- kPageFaultsMax,
- kPageFaultsBuckets);
- metrics_lib_->SendToUMA(kSwapOutHistogramName,
- swap_out_per_second,
- 1,
- kPageFaultsMax,
- kPageFaultsBuckets);
- }
-}
diff --git a/metricsd/collectors/averaged_statistics_collector.h b/metricsd/collectors/averaged_statistics_collector.h
deleted file mode 100644
index 753f70c..0000000
--- a/metricsd/collectors/averaged_statistics_collector.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-
-#ifndef METRICSD_COLLECTORS_AVERAGED_STATISTICS_COLLECTOR_H_
-#define METRICSD_COLLECTORS_AVERAGED_STATISTICS_COLLECTOR_H_
-
-#include "metrics/metrics_library.h"
-
-class AveragedStatisticsCollector {
- public:
- AveragedStatisticsCollector(MetricsLibraryInterface* metrics_library,
- const std::string& diskstats_path,
- const std::string& vmstat_path);
-
- // Schedule a wait period.
- void ScheduleWait();
-
- // Schedule a collection period.
- void ScheduleCollect();
-
- // Callback used by the main loop.
- void CollectCallback();
-
- // Callback used by the main loop.
- void WaitCallback();
-
- // Read and store the initial values at the beginning of a collection cycle.
- void ReadInitialValues();
-
- // Collect the disk usage statistics and report them.
- void Collect();
-
- private:
- friend class AveragedStatisticsTest;
- FRIEND_TEST(AveragedStatisticsTest, ParseDiskStats);
- FRIEND_TEST(AveragedStatisticsTest, ParseVmStats);
-
- // Record for retrieving and reporting values from /proc/vmstat
- struct VmstatRecord {
- uint64_t page_faults; // major faults
- uint64_t swap_in; // pages swapped in
- uint64_t swap_out; // pages swapped out
- };
-
- // Read the disk read/write statistics for the main disk.
- bool DiskStatsReadStats(uint64_t* read_sectors, uint64_t* write_sectors);
-
- // Parse the content of the vmstats file into |record|.
- bool VmStatsParseStats(const char* stats, struct VmstatRecord* record);
-
- // Read the vmstats into |stats|.
- bool VmStatsReadStats(struct VmstatRecord* stats);
-
- MetricsLibraryInterface* metrics_lib_;
- base::FilePath diskstats_path_;
- base::FilePath vmstats_path_;
-
- // Values observed at the beginning of the collection period.
- uint64_t read_sectors_;
- uint64_t write_sectors_;
- struct VmstatRecord vmstats_;
-
- double stats_start_time_;
-};
-
-#endif // METRICSD_COLLECTORS_AVERAGED_STATISTICS_COLLECTOR_H_
diff --git a/metricsd/collectors/averaged_statistics_collector_test.cc b/metricsd/collectors/averaged_statistics_collector_test.cc
deleted file mode 100644
index 68f9f2f..0000000
--- a/metricsd/collectors/averaged_statistics_collector_test.cc
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (C) 2015 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 "averaged_statistics_collector.h"
-
-#include <memory>
-
-#include <inttypes.h>
-
-#include <base/files/file_util.h>
-#include <base/files/scoped_temp_dir.h>
-#include <base/strings/stringprintf.h>
-#include <gtest/gtest.h>
-
-
-static const char kFakeDiskStatsFormat[] =
- " 1793 1788 %" PRIu64 " 105580 "
- " 196 175 %" PRIu64 " 30290 "
- " 0 44060 135850\n";
-static const uint64_t kFakeReadSectors[] = {80000, 100000};
-static const uint64_t kFakeWriteSectors[] = {3000, 4000};
-
-
-class AveragedStatisticsTest : public testing::Test {
- protected:
- std::string kFakeDiskStats0;
- std::string kFakeDiskStats1;
-
- virtual void SetUp() {
- ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
- disk_stats_path_ = temp_dir_.path().Append("disk_stats");
- collector_.reset(new AveragedStatisticsCollector(
- &metrics_lib_, disk_stats_path_.value(), ""));
-
- kFakeDiskStats0 = base::StringPrintf(kFakeDiskStatsFormat,
- kFakeReadSectors[0],
- kFakeWriteSectors[0]);
- kFakeDiskStats1 = base::StringPrintf(kFakeDiskStatsFormat,
- kFakeReadSectors[1],
- kFakeWriteSectors[1]);
-
- CreateFakeDiskStatsFile(kFakeDiskStats0);
- }
-
- // Creates or overwrites an input file containing fake disk stats.
- void CreateFakeDiskStatsFile(const std::string& fake_stats) {
- EXPECT_EQ(base::WriteFile(disk_stats_path_,
- fake_stats.data(), fake_stats.size()),
- fake_stats.size());
- }
-
- // Collector used for tests.
- std::unique_ptr<AveragedStatisticsCollector> collector_;
-
- // Temporary directory used for tests.
- base::ScopedTempDir temp_dir_;
-
- // Path for the fake files.
- base::FilePath disk_stats_path_;
-
- MetricsLibrary metrics_lib_;
-};
-
-TEST_F(AveragedStatisticsTest, ParseDiskStats) {
- uint64_t read_sectors_now, write_sectors_now;
- CreateFakeDiskStatsFile(kFakeDiskStats0);
- ASSERT_TRUE(collector_->DiskStatsReadStats(&read_sectors_now,
- &write_sectors_now));
- EXPECT_EQ(read_sectors_now, kFakeReadSectors[0]);
- EXPECT_EQ(write_sectors_now, kFakeWriteSectors[0]);
-
- CreateFakeDiskStatsFile(kFakeDiskStats1);
- ASSERT_TRUE(collector_->DiskStatsReadStats(&read_sectors_now,
- &write_sectors_now));
- EXPECT_EQ(read_sectors_now, kFakeReadSectors[1]);
- EXPECT_EQ(write_sectors_now, kFakeWriteSectors[1]);
-}
-
-TEST_F(AveragedStatisticsTest, ParseVmStats) {
- static char kVmStats[] = "pswpin 1345\npswpout 8896\n"
- "foo 100\nbar 200\npgmajfault 42\netcetc 300\n";
- struct AveragedStatisticsCollector::VmstatRecord stats;
- EXPECT_TRUE(collector_->VmStatsParseStats(kVmStats, &stats));
- EXPECT_EQ(stats.page_faults, 42);
- EXPECT_EQ(stats.swap_in, 1345);
- EXPECT_EQ(stats.swap_out, 8896);
-}
diff --git a/metricsd/collectors/cpu_usage_collector.cc b/metricsd/collectors/cpu_usage_collector.cc
deleted file mode 100644
index 9b0bb34..0000000
--- a/metricsd/collectors/cpu_usage_collector.cc
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright (C) 2015 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 "collectors/cpu_usage_collector.h"
-
-#include <base/bind.h>
-#include <base/files/file_path.h>
-#include <base/files/file_util.h>
-#include <base/message_loop/message_loop.h>
-#include <base/strings/string_number_conversions.h>
-#include <base/strings/string_split.h>
-#include <base/strings/string_util.h>
-#include <base/sys_info.h>
-
-#include "metrics/metrics_library.h"
-
-namespace {
-
-const char kCpuUsagePercent[] = "Platform.CpuUsage.Percent";
-const char kMetricsProcStatFileName[] = "/proc/stat";
-const int kMetricsProcStatFirstLineItemsCount = 11;
-
-// Collect every minute.
-const int kCollectionIntervalSecs = 60;
-
-} // namespace
-
-using base::TimeDelta;
-
-CpuUsageCollector::CpuUsageCollector(MetricsLibraryInterface* metrics_library) {
- CHECK(metrics_library);
- metrics_lib_ = metrics_library;
- collect_interval_ = TimeDelta::FromSeconds(kCollectionIntervalSecs);
-}
-
-void CpuUsageCollector::Init() {
- num_cpu_ = base::SysInfo::NumberOfProcessors();
-
- // Get ticks per second (HZ) on this system.
- // Sysconf cannot fail, so no sanity checks are needed.
- ticks_per_second_ = sysconf(_SC_CLK_TCK);
- CHECK_GT(ticks_per_second_, uint64_t(0))
- << "Number of ticks per seconds should be positive.";
-
- latest_cpu_use_ = GetCumulativeCpuUse();
-}
-
-void CpuUsageCollector::CollectCallback() {
- Collect();
- Schedule();
-}
-
-void CpuUsageCollector::Schedule() {
- base::MessageLoop::current()->PostDelayedTask(FROM_HERE,
- base::Bind(&CpuUsageCollector::CollectCallback, base::Unretained(this)),
- collect_interval_);
-}
-
-void CpuUsageCollector::Collect() {
- TimeDelta cpu_use = GetCumulativeCpuUse();
- TimeDelta diff_per_cpu = (cpu_use - latest_cpu_use_) / num_cpu_;
- latest_cpu_use_ = cpu_use;
-
- // Report the cpu usage as a percentage of the total cpu usage possible.
- int percent_use = diff_per_cpu.InMilliseconds() * 100 /
- (kCollectionIntervalSecs * 1000);
-
- metrics_lib_->SendEnumToUMA(kCpuUsagePercent, percent_use, 101);
-}
-
-TimeDelta CpuUsageCollector::GetCumulativeCpuUse() {
- base::FilePath proc_stat_path(kMetricsProcStatFileName);
- std::string proc_stat_string;
- if (!base::ReadFileToString(proc_stat_path, &proc_stat_string)) {
- LOG(WARNING) << "cannot open " << kMetricsProcStatFileName;
- return TimeDelta();
- }
-
- uint64_t user_ticks, user_nice_ticks, system_ticks;
- if (!ParseProcStat(proc_stat_string, &user_ticks, &user_nice_ticks,
- &system_ticks)) {
- return TimeDelta();
- }
-
- uint64_t total = user_ticks + user_nice_ticks + system_ticks;
- return TimeDelta::FromMicroseconds(
- total * 1000 * 1000 / ticks_per_second_);
-}
-
-bool CpuUsageCollector::ParseProcStat(const std::string& stat_content,
- uint64_t *user_ticks,
- uint64_t *user_nice_ticks,
- uint64_t *system_ticks) {
- std::vector<std::string> proc_stat_lines = base::SplitString(
- stat_content, "\n", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
- if (proc_stat_lines.empty()) {
- LOG(WARNING) << "No lines found in " << kMetricsProcStatFileName;
- return false;
- }
- std::vector<std::string> proc_stat_totals =
- base::SplitString(proc_stat_lines[0], base::kWhitespaceASCII,
- base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
-
- if (proc_stat_totals.size() != kMetricsProcStatFirstLineItemsCount ||
- proc_stat_totals[0] != "cpu" ||
- !base::StringToUint64(proc_stat_totals[1], user_ticks) ||
- !base::StringToUint64(proc_stat_totals[2], user_nice_ticks) ||
- !base::StringToUint64(proc_stat_totals[3], system_ticks)) {
- LOG(WARNING) << "cannot parse first line: " << proc_stat_lines[0];
- return false;
- }
- return true;
-}
diff --git a/metricsd/collectors/cpu_usage_collector.h b/metricsd/collectors/cpu_usage_collector.h
deleted file mode 100644
index 9f92cf3..0000000
--- a/metricsd/collectors/cpu_usage_collector.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-
-#ifndef METRICSD_COLLECTORS_CPU_USAGE_COLLECTOR_H_
-#define METRICSD_COLLECTORS_CPU_USAGE_COLLECTOR_H_
-
-#include <base/time/time.h>
-
-#include "metrics/metrics_library.h"
-
-class CpuUsageCollector {
- public:
- explicit CpuUsageCollector(MetricsLibraryInterface* metrics_library);
-
- // Initialize this collector's state.
- void Init();
-
- // Schedule a collection interval.
- void Schedule();
-
- // Callback called at the end of the collection interval.
- void CollectCallback();
-
- // Measure the cpu use and report it.
- void Collect();
-
- // Gets the current cumulated Cpu usage.
- base::TimeDelta GetCumulativeCpuUse();
-
- private:
- FRIEND_TEST(CpuUsageTest, ParseProcStat);
- bool ParseProcStat(const std::string& stat_content,
- uint64_t *user_ticks,
- uint64_t *user_nice_ticks,
- uint64_t *system_ticks);
-
- int num_cpu_;
- uint32_t ticks_per_second_;
-
- base::TimeDelta collect_interval_;
- base::TimeDelta latest_cpu_use_;
-
- MetricsLibraryInterface* metrics_lib_;
-};
-
-#endif // METRICSD_COLLECTORS_CPU_USAGE_COLLECTOR_H_
diff --git a/metricsd/collectors/cpu_usage_collector_test.cc b/metricsd/collectors/cpu_usage_collector_test.cc
deleted file mode 100644
index ee5c92b..0000000
--- a/metricsd/collectors/cpu_usage_collector_test.cc
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2015 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 <gtest/gtest.h>
-
-#include "collectors/cpu_usage_collector.h"
-#include "metrics/metrics_library_mock.h"
-
-
-TEST(CpuUsageTest, ParseProcStat) {
- MetricsLibraryMock metrics_lib_mock;
- CpuUsageCollector collector(&metrics_lib_mock);
- std::vector<std::string> invalid_contents = {
- "",
- // First line does not start with cpu.
- "spu 17191 11 36579 151118 289 0 2 0 0 0\n"
- "cpu0 1564 2 866 48650 68 0 2 0 0 0\n"
- "cpu1 14299 0 35116 1844 81 0 0 0 0 0\n",
- // One of the field is not a number.
- "cpu a17191 11 36579 151118 289 0 2 0 0 0",
- // To many numbers in the first line.
- "cpu 17191 11 36579 151118 289 0 2 0 0 0 102"
- };
-
- uint64_t user, nice, system;
- for (int i = 0; i < invalid_contents.size(); i++) {
- ASSERT_FALSE(collector.ParseProcStat(invalid_contents[i], &user, &nice,
- &system));
- }
-
- ASSERT_TRUE(collector.ParseProcStat(
- std::string("cpu 17191 11 36579 151118 289 0 2 0 0 0"),
- &user, &nice, &system));
- ASSERT_EQ(17191, user);
- ASSERT_EQ(11, nice);
- ASSERT_EQ(36579, system);
-}
diff --git a/metricsd/collectors/disk_usage_collector.cc b/metricsd/collectors/disk_usage_collector.cc
deleted file mode 100644
index 5ab51fb..0000000
--- a/metricsd/collectors/disk_usage_collector.cc
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2015 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 "collectors/disk_usage_collector.h"
-
-#include <base/bind.h>
-#include <base/bind_helpers.h>
-#include <base/message_loop/message_loop.h>
-#include <sys/statvfs.h>
-
-#include "metrics/metrics_library.h"
-
-namespace {
-
-const char kDiskUsageMB[] = "Platform.DataPartitionUsed.MB";
-const char kDiskUsagePercent[] = "Platform.DataPartitionUsed.Percent";
-const char kDataPartitionPath[] = "/data";
-
-// Collect every 15 minutes.
-const int kDiskUsageCollectorIntervalSeconds = 900;
-
-} // namespace
-
-DiskUsageCollector::DiskUsageCollector(
- MetricsLibraryInterface* metrics_library) {
- collect_interval_ = base::TimeDelta::FromSeconds(
- kDiskUsageCollectorIntervalSeconds);
- CHECK(metrics_library);
- metrics_lib_ = metrics_library;
-}
-
-void DiskUsageCollector::Collect() {
- struct statvfs buf;
- int result = statvfs(kDataPartitionPath, &buf);
- if (result != 0) {
- PLOG(ERROR) << "Failed to check the available space in "
- << kDataPartitionPath;
- return;
- }
-
- unsigned long total_space = buf.f_blocks * buf.f_bsize;
- unsigned long used_space = (buf.f_blocks - buf.f_bfree) * buf.f_bsize;
- int percent_used = (used_space * 100) / total_space;
-
- metrics_lib_->SendToUMA(kDiskUsageMB,
- used_space / (1024 * 1024),
- 0,
- 1024, // up to 1 GB.
- 100);
- metrics_lib_->SendEnumToUMA(kDiskUsagePercent, percent_used, 101);
-}
-
-void DiskUsageCollector::CollectCallback() {
- Collect();
- Schedule();
-}
-
-void DiskUsageCollector::Schedule() {
- base::MessageLoop::current()->PostDelayedTask(FROM_HERE,
- base::Bind(&DiskUsageCollector::CollectCallback, base::Unretained(this)),
- collect_interval_);
-}
diff --git a/metricsd/collectors/disk_usage_collector.h b/metricsd/collectors/disk_usage_collector.h
deleted file mode 100644
index 288b34b..0000000
--- a/metricsd/collectors/disk_usage_collector.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-
-#ifndef METRICSD_COLLECTORS_DISK_USAGE_COLLECTOR_H_
-#define METRICSD_COLLECTORS_DISK_USAGE_COLLECTOR_H_
-
-#include <base/time/time.h>
-
-#include "metrics/metrics_library.h"
-
-class DiskUsageCollector {
- public:
- explicit DiskUsageCollector(MetricsLibraryInterface* metrics_library);
-
- // Schedule the next collection.
- void Schedule();
-
- // Callback used by the main loop.
- void CollectCallback();
-
- // Collect the disk usage statistics and report them.
- void Collect();
-
- private:
- base::TimeDelta collect_interval_;
- MetricsLibraryInterface* metrics_lib_;
-};
-
-#endif // METRICSD_COLLECTORS_DISK_USAGE_COLLECTOR_H_
diff --git a/metricsd/constants.h b/metricsd/constants.h
deleted file mode 100644
index b702737..0000000
--- a/metricsd/constants.h
+++ /dev/null
@@ -1,42 +0,0 @@
-//
-// Copyright (C) 2015 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.
-//
-
-#ifndef METRICS_CONSTANTS_H_
-#define METRICS_CONSTANTS_H_
-
-namespace metrics {
-static const char kSharedMetricsDirectory[] = "/data/misc/metrics/";
-static const char kMetricsdDirectory[] = "/data/misc/metricsd/";
-static const char kMetricsCollectorDirectory[] =
- "/data/misc/metrics_collector/";
-static const char kMetricsGUIDFileName[] = "Sysinfo.GUID";
-static const char kMetricsServer[] = "https://clients4.google.com/uma/v2";
-static const char kConsentFileName[] = "enabled";
-static const char kStagedLogName[] = "staged_log";
-static const char kSavedLogName[] = "saved_log";
-static const char kFailedUploadCountName[] = "failed_upload_count";
-static const char kDefaultVersion[] = "0.0.0.0";
-
-// Build time properties name.
-static const char kProductId[] = "product_id";
-static const char kProductVersion[] = "product_version";
-
-// Weave configuration.
-static const char kWeaveConfigurationFile[] = "/system/etc/weaved/weaved.conf";
-static const char kModelManifestId[] = "model_id";
-} // namespace metrics
-
-#endif // METRICS_CONSTANTS_H_
diff --git a/metricsd/etc/weaved/traits/metrics.json b/metricsd/etc/weaved/traits/metrics.json
deleted file mode 100644
index 7583270..0000000
--- a/metricsd/etc/weaved/traits/metrics.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
- "_metrics": {
- "commands": {
- "enableAnalyticsReporting": {
- "minimalRole": "manager",
- "parameters": {}
- },
- "disableAnalyticsReporting": {
- "minimalRole": "manager",
- "parameters": {}
- }
- },
- "state": {
- "analyticsReportingState": {
- "type": "string",
- "enum": [ "enabled", "disabled" ]
- }
- }
- }
-}
diff --git a/metricsd/include/metrics/c_metrics_library.h b/metricsd/include/metrics/c_metrics_library.h
deleted file mode 100644
index 1e597c2..0000000
--- a/metricsd/include/metrics/c_metrics_library.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-
-#ifndef METRICS_C_METRICS_LIBRARY_H_
-#define METRICS_C_METRICS_LIBRARY_H_
-
-#if defined(__cplusplus)
-extern "C" {
-#endif
-typedef struct CMetricsLibraryOpaque* CMetricsLibrary;
-
-// C wrapper for MetricsLibrary::MetricsLibrary.
-CMetricsLibrary CMetricsLibraryNew(void);
-
-// C wrapper for MetricsLibrary::~MetricsLibrary.
-void CMetricsLibraryDelete(CMetricsLibrary handle);
-
-// C wrapper for MetricsLibrary::Init.
-void CMetricsLibraryInit(CMetricsLibrary handle);
-
-// C wrapper for MetricsLibrary::SendToUMA.
-int CMetricsLibrarySendToUMA(CMetricsLibrary handle,
- const char* name, int sample,
- int min, int max, int nbuckets);
-
-// C wrapper for MetricsLibrary::SendEnumToUMA.
-int CMetricsLibrarySendEnumToUMA(CMetricsLibrary handle,
- const char* name, int sample, int max);
-
-// C wrapper for MetricsLibrary::SendSparseToUMA.
-int CMetricsLibrarySendSparseToUMA(CMetricsLibrary handle,
- const char* name, int sample);
-
-// C wrapper for MetricsLibrary::SendCrashToUMA.
-int CMetricsLibrarySendCrashToUMA(CMetricsLibrary handle,
- const char* crash_kind);
-
-// C wrapper for MetricsLibrary::AreMetricsEnabled.
-int CMetricsLibraryAreMetricsEnabled(CMetricsLibrary handle);
-
-#if defined(__cplusplus)
-}
-#endif
-#endif // METRICS_C_METRICS_LIBRARY_H_
diff --git a/metricsd/include/metrics/metrics_collector_service_client.h b/metricsd/include/metrics/metrics_collector_service_client.h
deleted file mode 100644
index c800eae..0000000
--- a/metricsd/include/metrics/metrics_collector_service_client.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-
-// Client interface to IMetricsCollectorService.
-
-#ifndef METRICS_METRICS_COLLECTOR_SERVICE_CLIENT_H_
-#define METRICS_METRICS_COLLECTOR_SERVICE_CLIENT_H_
-
-#include "android/brillo/metrics/IMetricsCollectorService.h"
-
-class MetricsCollectorServiceClient {
- public:
- MetricsCollectorServiceClient() = default;
- ~MetricsCollectorServiceClient() = default;
-
- // Initialize. Returns true if OK, or false if IMetricsCollectorService
- // is not registered.
- bool Init();
-
- // Called by crash_reporter to report a userspace crash event. Returns
- // true if successfully called the IMetricsCollectorService method of the
- // same name, or false if the service was not registered at Init() time.
- bool notifyUserCrash();
-
- private:
- // IMetricsCollectorService binder proxy
- android::sp<android::brillo::metrics::IMetricsCollectorService>
- metrics_collector_service_;
-};
-
-#endif // METRICS_METRICS_COLLECTOR_SERVICE_CLIENT_H_
diff --git a/metricsd/include/metrics/metrics_library.h b/metricsd/include/metrics/metrics_library.h
deleted file mode 100644
index a1bb926..0000000
--- a/metricsd/include/metrics/metrics_library.h
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-
-#ifndef METRICS_METRICS_LIBRARY_H_
-#define METRICS_METRICS_LIBRARY_H_
-
-#include <sys/types.h>
-#include <string>
-#include <unistd.h>
-
-#include <base/compiler_specific.h>
-#include <base/files/file_path.h>
-#include <base/macros.h>
-#include <binder/IServiceManager.h>
-#include <gtest/gtest_prod.h> // for FRIEND_TEST
-
-namespace android {
-namespace brillo {
-namespace metrics {
-class IMetricsd;
-} // namespace metrics
-} // namespace brillo
-} // namespace android
-
-class MetricsLibraryInterface {
- public:
- virtual void Init() = 0;
- virtual bool AreMetricsEnabled() = 0;
- virtual bool SendToUMA(const std::string& name, int sample,
- int min, int max, int nbuckets) = 0;
- virtual bool SendEnumToUMA(const std::string& name, int sample, int max) = 0;
- virtual bool SendBoolToUMA(const std::string& name, bool sample) = 0;
- virtual bool SendSparseToUMA(const std::string& name, int sample) = 0;
- virtual ~MetricsLibraryInterface() {}
-};
-
-// Library used to send metrics to Chrome/UMA.
-class MetricsLibrary : public MetricsLibraryInterface {
- public:
- MetricsLibrary();
- virtual ~MetricsLibrary();
-
- // Initializes the library.
- void Init() override;
-
- // Initializes the library and disables the cache of whether or not the
- // metrics collection is enabled.
- // By disabling this, we may have to check for the metrics status more often
- // but the result will never be stale.
- void InitWithNoCaching();
-
- // Returns whether or not the machine is running in guest mode.
- bool IsGuestMode();
-
- // Returns whether or not metrics collection is enabled.
- bool AreMetricsEnabled() override;
-
- // Sends histogram data to Chrome for transport to UMA and returns
- // true on success. This method results in the equivalent of an
- // asynchronous non-blocking RPC to UMA_HISTOGRAM_CUSTOM_COUNTS
- // inside Chrome (see base/histogram.h).
- //
- // |sample| is the sample value to be recorded (|min| <= |sample| < |max|).
- // |min| is the minimum value of the histogram samples (|min| > 0).
- // |max| is the maximum value of the histogram samples.
- // |nbuckets| is the number of histogram buckets.
- // [0,min) is the implicit underflow bucket.
- // [|max|,infinity) is the implicit overflow bucket.
- //
- // Note that the memory allocated in Chrome for each histogram is
- // proportional to the number of buckets. Therefore, it is strongly
- // recommended to keep this number low (e.g., 50 is normal, while
- // 100 is high).
- bool SendToUMA(const std::string& name, int sample,
- int min, int max, int nbuckets) override;
-
- // Sends linear histogram data to Chrome for transport to UMA and
- // returns true on success. This method results in the equivalent of
- // an asynchronous non-blocking RPC to UMA_HISTOGRAM_ENUMERATION
- // inside Chrome (see base/histogram.h).
- //
- // |sample| is the sample value to be recorded (1 <= |sample| < |max|).
- // |max| is the maximum value of the histogram samples.
- // 0 is the implicit underflow bucket.
- // [|max|,infinity) is the implicit overflow bucket.
- //
- // An enumeration histogram requires |max| + 1 number of
- // buckets. Note that the memory allocated in Chrome for each
- // histogram is proportional to the number of buckets. Therefore, it
- // is strongly recommended to keep this number low (e.g., 50 is
- // normal, while 100 is high).
- bool SendEnumToUMA(const std::string& name, int sample, int max) override;
-
- // Specialization of SendEnumToUMA for boolean values.
- bool SendBoolToUMA(const std::string& name, bool sample) override;
-
- // Sends sparse histogram sample to Chrome for transport to UMA. Returns
- // true on success.
- //
- // |sample| is the 32-bit integer value to be recorded.
- bool SendSparseToUMA(const std::string& name, int sample) override;
-
- // Sends a signal to UMA that a crash of the given |crash_kind|
- // has occurred. Used by UMA to generate stability statistics.
- bool SendCrashToUMA(const char *crash_kind);
-
- // Sends a "generic Chrome OS event" to UMA. This is an event name
- // that is translated into an enumerated histogram entry. Event names
- // are added to metrics_library.cc. Optionally, they can be added
- // to histograms.xml---but part of the reason for this is to simplify
- // the addition of events (at the cost of having to look them up by
- // number in the histograms dashboard).
- bool SendCrosEventToUMA(const std::string& event);
-
- // Debugging only.
- // Dumps the histograms aggregated since metricsd started into |dump|.
- // Returns true iff the dump succeeds.
- bool GetHistogramsDump(std::string* dump);
-
- private:
- friend class CMetricsLibraryTest;
- friend class MetricsLibraryTest;
- friend class UploadServiceTest;
- FRIEND_TEST(MetricsLibraryTest, AreMetricsEnabled);
- FRIEND_TEST(MetricsLibraryTest, AreMetricsEnabledNoCaching);
- FRIEND_TEST(MetricsLibraryTest, FormatChromeMessage);
- FRIEND_TEST(MetricsLibraryTest, FormatChromeMessageTooLong);
- FRIEND_TEST(MetricsLibraryTest, IsDeviceMounted);
- FRIEND_TEST(MetricsLibraryTest, SendMessageToChrome);
- FRIEND_TEST(MetricsLibraryTest, SendMessageToChromeUMAEventsBadFileLocation);
-
- void InitForTest(const base::FilePath& metrics_directory);
-
- // Sets |*result| to whether or not the |mounts_file| indicates that
- // the |device_name| is currently mounted. Uses |buffer| of
- // |buffer_size| to read the file. Returns false if any error.
- bool IsDeviceMounted(const char* device_name,
- const char* mounts_file,
- char* buffer, int buffer_size,
- bool* result);
-
- // Connects to IMetricsd if the proxy does not exist or is not alive.
- // Don't block if we fail to get the proxy for any reason.
- bool CheckService();
-
- // Time at which we last checked if metrics were enabled.
- time_t cached_enabled_time_;
-
- // Cached state of whether or not metrics were enabled.
- bool cached_enabled_;
-
- // True iff we should cache the enabled/disabled status.
- bool use_caching_;
-
- android::sp<android::IServiceManager> manager_;
- android::sp<android::brillo::metrics::IMetricsd> metricsd_proxy_;
- base::FilePath consent_file_;
-
- DISALLOW_COPY_AND_ASSIGN(MetricsLibrary);
-};
-
-#endif // METRICS_METRICS_LIBRARY_H_
diff --git a/metricsd/include/metrics/metrics_library_mock.h b/metricsd/include/metrics/metrics_library_mock.h
deleted file mode 100644
index 3b0b24d..0000000
--- a/metricsd/include/metrics/metrics_library_mock.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-
-#ifndef METRICS_METRICS_LIBRARY_MOCK_H_
-#define METRICS_METRICS_LIBRARY_MOCK_H_
-
-#include <string>
-
-#include "metrics/metrics_library.h"
-
-#include <gmock/gmock.h>
-
-class MetricsLibraryMock : public MetricsLibraryInterface {
- public:
- bool metrics_enabled_ = true;
-
- MOCK_METHOD0(Init, void());
- MOCK_METHOD5(SendToUMA, bool(const std::string& name, int sample,
- int min, int max, int nbuckets));
- MOCK_METHOD3(SendEnumToUMA, bool(const std::string& name, int sample,
- int max));
- MOCK_METHOD2(SendBoolToUMA, bool(const std::string& name, bool sample));
- MOCK_METHOD2(SendSparseToUMA, bool(const std::string& name, int sample));
-
- bool AreMetricsEnabled() override {return metrics_enabled_;};
-};
-
-#endif // METRICS_METRICS_LIBRARY_MOCK_H_
diff --git a/metricsd/include/metrics/timer.h b/metricsd/include/metrics/timer.h
deleted file mode 100644
index c1b8ede..0000000
--- a/metricsd/include/metrics/timer.h
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-
-// Timer - class that provides timer tracking.
-
-#ifndef METRICS_TIMER_H_
-#define METRICS_TIMER_H_
-
-#include <memory>
-#include <string>
-
-#include <base/macros.h>
-#include <base/time/time.h>
-#include <gtest/gtest_prod.h> // for FRIEND_TEST
-
-class MetricsLibraryInterface;
-
-namespace chromeos_metrics {
-
-class TimerInterface {
- public:
- virtual ~TimerInterface() {}
-
- virtual bool Start() = 0;
- virtual bool Stop() = 0;
- virtual bool Reset() = 0;
- virtual bool HasStarted() const = 0;
-};
-
-// Wrapper for calls to the system clock.
-class ClockWrapper {
- public:
- ClockWrapper() {}
- virtual ~ClockWrapper() {}
-
- // Returns the current time from the system.
- virtual base::TimeTicks GetCurrentTime() const;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ClockWrapper);
-};
-
-// Implements a Timer.
-class Timer : public TimerInterface {
- public:
- Timer();
- virtual ~Timer() {}
-
- // Starts the timer. If a timer is already running, also resets current
- // timer. Always returns true.
- virtual bool Start();
-
- // Stops the timer and calculates the total time elapsed between now and when
- // Start() was called. Note that this method needs a prior call to Start().
- // Otherwise, it fails (returns false).
- virtual bool Stop();
-
- // Pauses a timer. If the timer is stopped, this call starts the timer in
- // the paused state. Fails (returns false) if the timer is already paused.
- virtual bool Pause();
-
- // Restarts a paused timer (or starts a stopped timer). This method fails
- // (returns false) if the timer is already running; otherwise, returns true.
- virtual bool Resume();
-
- // Resets the timer, erasing the current duration being tracked. Always
- // returns true.
- virtual bool Reset();
-
- // Returns whether the timer has started or not.
- virtual bool HasStarted() const;
-
- // Stores the current elapsed time in |elapsed_time|. If timer is stopped,
- // stores the elapsed time from when Stop() was last called. Otherwise,
- // calculates and stores the elapsed time since the last Start().
- // Returns false if the timer was never Start()'ed or if called with a null
- // pointer argument.
- virtual bool GetElapsedTime(base::TimeDelta* elapsed_time) const;
-
- private:
- enum TimerState { kTimerStopped, kTimerRunning, kTimerPaused };
- friend class TimerTest;
- friend class TimerReporterTest;
- FRIEND_TEST(TimerReporterTest, StartStopReport);
- FRIEND_TEST(TimerTest, InvalidElapsedTime);
- FRIEND_TEST(TimerTest, InvalidStop);
- FRIEND_TEST(TimerTest, PauseResumeStop);
- FRIEND_TEST(TimerTest, PauseStartStopResume);
- FRIEND_TEST(TimerTest, PauseStop);
- FRIEND_TEST(TimerTest, Reset);
- FRIEND_TEST(TimerTest, ReStart);
- FRIEND_TEST(TimerTest, ResumeStartStopPause);
- FRIEND_TEST(TimerTest, SeparatedTimers);
- FRIEND_TEST(TimerTest, StartPauseResumePauseResumeStop);
- FRIEND_TEST(TimerTest, StartPauseResumePauseStop);
- FRIEND_TEST(TimerTest, StartPauseResumeStop);
- FRIEND_TEST(TimerTest, StartPauseStop);
- FRIEND_TEST(TimerTest, StartResumeStop);
- FRIEND_TEST(TimerTest, StartStop);
-
- // Elapsed time of the last use of the timer.
- base::TimeDelta elapsed_time_;
-
- // Starting time value.
- base::TimeTicks start_time_;
-
- // Whether the timer is running, stopped, or paused.
- TimerState timer_state_;
-
- // Wrapper for the calls to the system clock.
- std::unique_ptr<ClockWrapper> clock_wrapper_;
-
- DISALLOW_COPY_AND_ASSIGN(Timer);
-};
-
-// Extends the Timer class to report the elapsed time in milliseconds through
-// the UMA metrics library.
-class TimerReporter : public Timer {
- public:
- // Initializes the timer by providing a |histogram_name| to report to with
- // |min|, |max| and |num_buckets| attributes for the histogram.
- TimerReporter(const std::string& histogram_name, int min, int max,
- int num_buckets);
- virtual ~TimerReporter() {}
-
- // Sets the metrics library used by all instances of this class.
- static void set_metrics_lib(MetricsLibraryInterface* metrics_lib) {
- metrics_lib_ = metrics_lib;
- }
-
- // Reports the current duration to UMA, in milliseconds. Returns false if
- // there is nothing to report, e.g. a metrics library is not set.
- virtual bool ReportMilliseconds() const;
-
- // Accessor methods.
- const std::string& histogram_name() const { return histogram_name_; }
- int min() const { return min_; }
- int max() const { return max_; }
- int num_buckets() const { return num_buckets_; }
-
- private:
- friend class TimerReporterTest;
- FRIEND_TEST(TimerReporterTest, StartStopReport);
- FRIEND_TEST(TimerReporterTest, InvalidReport);
-
- static MetricsLibraryInterface* metrics_lib_;
- std::string histogram_name_;
- int min_;
- int max_;
- int num_buckets_;
-
- DISALLOW_COPY_AND_ASSIGN(TimerReporter);
-};
-
-} // namespace chromeos_metrics
-
-#endif // METRICS_TIMER_H_
diff --git a/metricsd/include/metrics/timer_mock.h b/metricsd/include/metrics/timer_mock.h
deleted file mode 100644
index 200ee9a..0000000
--- a/metricsd/include/metrics/timer_mock.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-
-#ifndef METRICS_TIMER_MOCK_H_
-#define METRICS_TIMER_MOCK_H_
-
-#include <string>
-
-#include <gmock/gmock.h>
-
-#include "metrics/timer.h"
-
-namespace chromeos_metrics {
-
-class TimerMock : public Timer {
- public:
- MOCK_METHOD0(Start, bool());
- MOCK_METHOD0(Stop, bool());
- MOCK_METHOD0(Reset, bool());
- MOCK_CONST_METHOD0(HasStarted, bool());
- MOCK_CONST_METHOD1(GetElapsedTime, bool(base::TimeDelta* elapsed_time));
-};
-
-class TimerReporterMock : public TimerReporter {
- public:
- TimerReporterMock() : TimerReporter("", 0, 0, 0) {}
- MOCK_METHOD0(Start, bool());
- MOCK_METHOD0(Stop, bool());
- MOCK_METHOD0(Reset, bool());
- MOCK_CONST_METHOD0(HasStarted, bool());
- MOCK_CONST_METHOD1(GetElapsedTime, bool(base::TimeDelta* elapsed_time));
- MOCK_CONST_METHOD0(ReportMilliseconds, bool());
- MOCK_CONST_METHOD0(histogram_name, std::string&());
- MOCK_CONST_METHOD0(min, int());
- MOCK_CONST_METHOD0(max, int());
- MOCK_CONST_METHOD0(num_buckets, int());
-};
-
-class ClockWrapperMock : public ClockWrapper {
- public:
- MOCK_CONST_METHOD0(GetCurrentTime, base::TimeTicks());
-};
-
-} // namespace chromeos_metrics
-
-#endif // METRICS_TIMER_MOCK_H_
diff --git a/metricsd/libmetrics-369476.gyp b/metricsd/libmetrics-369476.gyp
deleted file mode 100644
index b545d35..0000000
--- a/metricsd/libmetrics-369476.gyp
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- 'variables': {
- 'libbase_ver': 369476,
- },
- 'includes': [
- 'libmetrics.gypi',
- ],
-}
diff --git a/metricsd/libmetrics.gypi b/metricsd/libmetrics.gypi
deleted file mode 100644
index 3c8fc7c..0000000
--- a/metricsd/libmetrics.gypi
+++ /dev/null
@@ -1,33 +0,0 @@
-{
- 'target_defaults': {
- 'variables': {
- 'deps': [
- 'libbrillo-<(libbase_ver)',
- 'libchrome-<(libbase_ver)',
- ]
- },
- 'cflags_cc': [
- '-fno-exceptions',
- ],
- },
- 'targets': [
- {
- 'target_name': 'libmetrics-<(libbase_ver)',
- 'type': 'shared_library',
- 'cflags': [
- '-fvisibility=default',
- ],
- 'libraries+': [
- '-lpolicy-<(libbase_ver)',
- ],
- 'sources': [
- 'c_metrics_library.cc',
- 'metrics_library.cc',
- 'serialization/metric_sample.cc',
- 'serialization/serialization_utils.cc',
- 'timer.cc',
- ],
- 'include_dirs': ['.'],
- },
- ],
-}
diff --git a/metricsd/libmetrics.pc.in b/metricsd/libmetrics.pc.in
deleted file mode 100644
index 233f318..0000000
--- a/metricsd/libmetrics.pc.in
+++ /dev/null
@@ -1,7 +0,0 @@
-bslot=@BSLOT@
-
-Name: libmetrics
-Description: Chrome OS metrics library
-Version: ${bslot}
-Requires.private: libchrome-${bslot}
-Libs: -lmetrics-${bslot}
diff --git a/metricsd/metrics.gyp b/metricsd/metrics.gyp
deleted file mode 100644
index c9c02d7..0000000
--- a/metricsd/metrics.gyp
+++ /dev/null
@@ -1,184 +0,0 @@
-{
- 'target_defaults': {
- 'variables': {
- 'deps': [
- 'dbus-1',
- 'libbrillo-<(libbase_ver)',
- 'libchrome-<(libbase_ver)',
- ]
- },
- 'cflags_cc': [
- '-fno-exceptions',
- ],
- },
- 'targets': [
- {
- 'target_name': 'libmetrics_daemon',
- 'type': 'static_library',
- 'dependencies': [
- '../metrics/libmetrics-<(libbase_ver).gyp:libmetrics-<(libbase_ver)',
- 'libupload_service',
- 'metrics_proto',
- ],
- 'link_settings': {
- 'libraries': [
- '-lrootdev',
- ],
- },
- 'sources': [
- 'persistent_integer.cc',
- 'metrics_daemon.cc',
- 'metrics_daemon_main.cc',
- ],
- 'include_dirs': ['.'],
- },
- {
- 'target_name': 'metrics_client',
- 'type': 'executable',
- 'dependencies': [
- '../metrics/libmetrics-<(libbase_ver).gyp:libmetrics-<(libbase_ver)',
- ],
- 'sources': [
- 'metrics_client.cc',
- ]
- },
- {
- 'target_name': 'libupload_service',
- 'type': 'static_library',
- 'dependencies': [
- 'metrics_proto',
- '../metrics/libmetrics-<(libbase_ver).gyp:libmetrics-<(libbase_ver)',
- ],
- 'link_settings': {
- 'libraries': [
- '-lvboot_host',
- ],
- },
- 'variables': {
- 'exported_deps': [
- 'protobuf-lite',
- ],
- 'deps': [
- '<@(exported_deps)',
- ],
- },
- 'all_dependent_settings': {
- 'variables': {
- 'deps+': [
- '<@(exported_deps)',
- ],
- },
- },
- 'sources': [
- 'uploader/upload_service.cc',
- 'uploader/metrics_hashes.cc',
- 'uploader/metrics_log.cc',
- 'uploader/metrics_log_base.cc',
- 'uploader/system_profile_cache.cc',
- 'uploader/sender_http.cc',
- ],
- 'include_dirs': ['.']
- },
- {
- 'target_name': 'metrics_proto',
- 'type': 'static_library',
- 'variables': {
- 'proto_in_dir': 'uploader/proto',
- 'proto_out_dir': 'include/metrics/uploader/proto',
- },
- 'sources': [
- '<(proto_in_dir)/chrome_user_metrics_extension.proto',
- '<(proto_in_dir)/histogram_event.proto',
- '<(proto_in_dir)/system_profile.proto',
- '<(proto_in_dir)/user_action_event.proto',
- ],
- 'includes': [
- '../common-mk/protoc.gypi'
- ],
- },
- ],
- 'conditions': [
- ['USE_passive_metrics == 1', {
- 'targets': [
- {
- 'target_name': 'metrics_daemon',
- 'type': 'executable',
- 'dependencies': ['libmetrics_daemon'],
- },
- ],
- }],
- ['USE_test == 1', {
- 'targets': [
- {
- 'target_name': 'persistent_integer_test',
- 'type': 'executable',
- 'includes': ['../common-mk/common_test.gypi'],
- 'sources': [
- 'persistent_integer.cc',
- 'persistent_integer_test.cc',
- ]
- },
- {
- 'target_name': 'metrics_library_test',
- 'type': 'executable',
- 'dependencies': [
- '../metrics/libmetrics-<(libbase_ver).gyp:libmetrics-<(libbase_ver)',
- ],
- 'includes': ['../common-mk/common_test.gypi'],
- 'sources': [
- 'metrics_library_test.cc',
- 'serialization/serialization_utils_unittest.cc',
- ],
- 'link_settings': {
- 'libraries': [
- '-lpolicy-<(libbase_ver)',
- ]
- }
- },
- {
- 'target_name': 'timer_test',
- 'type': 'executable',
- 'includes': ['../common-mk/common_test.gypi'],
- 'sources': [
- 'timer.cc',
- 'timer_test.cc',
- ]
- },
- {
- 'target_name': 'upload_service_test',
- 'type': 'executable',
- 'sources': [
- 'persistent_integer.cc',
- 'uploader/metrics_hashes_unittest.cc',
- 'uploader/metrics_log_base_unittest.cc',
- 'uploader/mock/sender_mock.cc',
- 'uploader/upload_service_test.cc',
- ],
- 'dependencies': [
- 'libupload_service',
- ],
- 'includes':[
- '../common-mk/common_test.gypi',
- ],
- 'include_dirs': ['.']
- },
- ],
- }],
- ['USE_passive_metrics == 1 and USE_test == 1', {
- 'targets': [
- {
- 'target_name': 'metrics_daemon_test',
- 'type': 'executable',
- 'dependencies': [
- 'libmetrics_daemon',
- ],
- 'includes': ['../common-mk/common_test.gypi'],
- 'sources': [
- 'metrics_daemon_test.cc',
- ],
- 'include_dirs': ['.'],
- },
- ],
- }],
- ]
-}
diff --git a/metricsd/metrics_client.cc b/metricsd/metrics_client.cc
deleted file mode 100644
index c66b975..0000000
--- a/metricsd/metrics_client.cc
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- * Copyright (C) 2015 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 <cstdio>
-#include <cstdlib>
-
-#include "constants.h"
-#include "metrics/metrics_library.h"
-
-enum Mode {
- kModeDumpHistograms,
- kModeSendSample,
- kModeSendEnumSample,
- kModeSendSparseSample,
- kModeSendCrosEvent,
- kModeHasConsent,
- kModeIsGuestMode,
-};
-
-void ShowUsage() {
- fprintf(stderr,
- "Usage: metrics_client [-t] name sample min max nbuckets\n"
- " metrics_client -e name sample max\n"
- " metrics_client -s name sample\n"
- " metrics_client -v event\n"
- " metrics_client [-cdg]\n"
- "\n"
- " default: send metric with integer values \n"
- " |min| > 0, |min| <= sample < |max|\n"
- " -c: return exit status 0 if user consents to stats, 1 otherwise,\n"
- " in guest mode always return 1\n"
- " -d: dump the histograms recorded by metricsd to stdout\n"
- " -e: send linear/enumeration histogram data\n"
- " -g: return exit status 0 if machine in guest mode, 1 otherwise\n"
- " -s: send a sparse histogram sample\n"
- " -t: convert sample from double seconds to int milliseconds\n"
- " -v: send a Platform.CrOSEvent enum histogram sample\n");
- exit(1);
-}
-
-static int ParseInt(const char *arg) {
- char *endptr;
- int value = strtol(arg, &endptr, 0);
- if (*endptr != '\0') {
- fprintf(stderr, "metrics client: bad integer \"%s\"\n", arg);
- ShowUsage();
- }
- return value;
-}
-
-static double ParseDouble(const char *arg) {
- char *endptr;
- double value = strtod(arg, &endptr);
- if (*endptr != '\0') {
- fprintf(stderr, "metrics client: bad double \"%s\"\n", arg);
- ShowUsage();
- }
- return value;
-}
-
-static int DumpHistograms() {
- MetricsLibrary metrics_lib;
- metrics_lib.Init();
-
- std::string dump;
- if (!metrics_lib.GetHistogramsDump(&dump)) {
- printf("Failed to dump the histograms.");
- return 1;
- }
-
- printf("%s\n", dump.c_str());
- return 0;
-}
-
-static int SendStats(char* argv[],
- int name_index,
- enum Mode mode,
- bool secs_to_msecs) {
- const char* name = argv[name_index];
- int sample;
- if (secs_to_msecs) {
- sample = static_cast<int>(ParseDouble(argv[name_index + 1]) * 1000.0);
- } else {
- sample = ParseInt(argv[name_index + 1]);
- }
-
- MetricsLibrary metrics_lib;
- metrics_lib.Init();
- if (mode == kModeSendSparseSample) {
- metrics_lib.SendSparseToUMA(name, sample);
- } else if (mode == kModeSendEnumSample) {
- int max = ParseInt(argv[name_index + 2]);
- metrics_lib.SendEnumToUMA(name, sample, max);
- } else {
- int min = ParseInt(argv[name_index + 2]);
- int max = ParseInt(argv[name_index + 3]);
- int nbuckets = ParseInt(argv[name_index + 4]);
- metrics_lib.SendToUMA(name, sample, min, max, nbuckets);
- }
- return 0;
-}
-
-static int SendCrosEvent(char* argv[], int action_index) {
- const char* event = argv[action_index];
- bool result;
- MetricsLibrary metrics_lib;
- metrics_lib.Init();
- result = metrics_lib.SendCrosEventToUMA(event);
- if (!result) {
- fprintf(stderr, "metrics_client: could not send event %s\n", event);
- return 1;
- }
- return 0;
-}
-
-static int HasConsent() {
- MetricsLibrary metrics_lib;
- metrics_lib.Init();
- return metrics_lib.AreMetricsEnabled() ? 0 : 1;
-}
-
-static int IsGuestMode() {
- MetricsLibrary metrics_lib;
- metrics_lib.Init();
- return metrics_lib.IsGuestMode() ? 0 : 1;
-}
-
-int main(int argc, char** argv) {
- enum Mode mode = kModeSendSample;
- bool secs_to_msecs = false;
-
- // Parse arguments
- int flag;
- while ((flag = getopt(argc, argv, "abcdegstv")) != -1) {
- switch (flag) {
- case 'c':
- mode = kModeHasConsent;
- break;
- case 'd':
- mode = kModeDumpHistograms;
- break;
- case 'e':
- mode = kModeSendEnumSample;
- break;
- case 'g':
- mode = kModeIsGuestMode;
- break;
- case 's':
- mode = kModeSendSparseSample;
- break;
- case 't':
- secs_to_msecs = true;
- break;
- case 'v':
- mode = kModeSendCrosEvent;
- break;
- default:
- ShowUsage();
- break;
- }
- }
- int arg_index = optind;
-
- int expected_args = 0;
- if (mode == kModeSendSample)
- expected_args = 5;
- else if (mode == kModeSendEnumSample)
- expected_args = 3;
- else if (mode == kModeSendSparseSample)
- expected_args = 2;
- else if (mode == kModeSendCrosEvent)
- expected_args = 1;
-
- if ((arg_index + expected_args) != argc) {
- ShowUsage();
- }
-
- switch (mode) {
- case kModeDumpHistograms:
- return DumpHistograms();
- case kModeSendSample:
- case kModeSendEnumSample:
- case kModeSendSparseSample:
- if ((mode != kModeSendSample) && secs_to_msecs) {
- ShowUsage();
- }
- return SendStats(argv,
- arg_index,
- mode,
- secs_to_msecs);
- case kModeSendCrosEvent:
- return SendCrosEvent(argv, arg_index);
- case kModeHasConsent:
- return HasConsent();
- case kModeIsGuestMode:
- return IsGuestMode();
- default:
- ShowUsage();
- return 0;
- }
-}
diff --git a/metricsd/metrics_collector.cc b/metricsd/metrics_collector.cc
deleted file mode 100644
index 45ae0a4..0000000
--- a/metricsd/metrics_collector.cc
+++ /dev/null
@@ -1,756 +0,0 @@
-/*
- * Copyright (C) 2015 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 "metrics_collector.h"
-
-#include <sysexits.h>
-#include <time.h>
-
-#include <memory>
-
-#include <base/bind.h>
-#include <base/files/file_path.h>
-#include <base/files/file_util.h>
-#include <base/hash.h>
-#include <base/logging.h>
-#include <base/strings/string_number_conversions.h>
-#include <base/strings/string_split.h>
-#include <base/strings/string_util.h>
-#include <base/strings/stringprintf.h>
-#include <brillo/binder_watcher.h>
-#include <brillo/osrelease_reader.h>
-
-#include "constants.h"
-#include "metrics_collector_service_impl.h"
-
-using base::FilePath;
-using base::StringPrintf;
-using base::Time;
-using base::TimeDelta;
-using base::TimeTicks;
-using chromeos_metrics::PersistentInteger;
-using std::map;
-using std::string;
-using std::vector;
-
-namespace {
-
-const int kSecondsPerMinute = 60;
-const int kMinutesPerHour = 60;
-const int kHoursPerDay = 24;
-const int kMinutesPerDay = kHoursPerDay * kMinutesPerHour;
-const int kSecondsPerDay = kSecondsPerMinute * kMinutesPerDay;
-const int kDaysPerWeek = 7;
-const int kSecondsPerWeek = kSecondsPerDay * kDaysPerWeek;
-
-// Interval between calls to UpdateStats().
-const uint32_t kUpdateStatsIntervalMs = 300000;
-
-const char kKernelCrashDetectedFile[] =
- "/data/misc/crash_reporter/run/kernel-crash-detected";
-const char kUncleanShutdownDetectedFile[] =
- "/var/run/unclean-shutdown-detected";
-
-const int kMetricMeminfoInterval = 30; // seconds
-
-const char kMeminfoFileName[] = "/proc/meminfo";
-const char kVmStatFileName[] = "/proc/vmstat";
-
-const char kWeaveComponent[] = "metrics";
-const char kWeaveTrait[] = "_metrics";
-
-} // namespace
-
-// Zram sysfs entries.
-
-const char MetricsCollector::kComprDataSizeName[] = "compr_data_size";
-const char MetricsCollector::kOrigDataSizeName[] = "orig_data_size";
-const char MetricsCollector::kZeroPagesName[] = "zero_pages";
-
-// Memory use stats collection intervals. We collect some memory use interval
-// at these intervals after boot, and we stop collecting after the last one,
-// with the assumption that in most cases the memory use won't change much
-// after that.
-static const int kMemuseIntervals[] = {
- 1 * kSecondsPerMinute, // 1 minute mark
- 4 * kSecondsPerMinute, // 5 minute mark
- 25 * kSecondsPerMinute, // 0.5 hour mark
- 120 * kSecondsPerMinute, // 2.5 hour mark
- 600 * kSecondsPerMinute, // 12.5 hour mark
-};
-
-MetricsCollector::MetricsCollector()
- : memuse_final_time_(0),
- memuse_interval_index_(0) {}
-
-MetricsCollector::~MetricsCollector() {
-}
-
-// static
-double MetricsCollector::GetActiveTime() {
- struct timespec ts;
- int r = clock_gettime(CLOCK_MONOTONIC, &ts);
- if (r < 0) {
- PLOG(WARNING) << "clock_gettime(CLOCK_MONOTONIC) failed";
- return 0;
- } else {
- return ts.tv_sec + static_cast<double>(ts.tv_nsec) / (1000 * 1000 * 1000);
- }
-}
-
-int MetricsCollector::Run() {
- if (CheckSystemCrash(kKernelCrashDetectedFile)) {
- ProcessKernelCrash();
- }
-
- if (CheckSystemCrash(kUncleanShutdownDetectedFile)) {
- ProcessUncleanShutdown();
- }
-
- // On OS version change, clear version stats (which are reported daily).
- int32_t version = GetOsVersionHash();
- if (version_cycle_->Get() != version) {
- version_cycle_->Set(version);
- kernel_crashes_version_count_->Set(0);
- version_cumulative_active_use_->Set(0);
- version_cumulative_cpu_use_->Set(0);
- }
-
- // Start metricscollectorservice
- android::sp<BnMetricsCollectorServiceImpl> metrics_collector_service =
- new BnMetricsCollectorServiceImpl(this);
- android::status_t status = android::defaultServiceManager()->addService(
- metrics_collector_service->getInterfaceDescriptor(),
- metrics_collector_service);
- CHECK(status == android::OK)
- << "failed to register service metricscollectorservice";
-
- // Watch Binder events in the main loop
- brillo::BinderWatcher binder_watcher;
- CHECK(binder_watcher.Init()) << "Binder FD watcher init failed";
- return brillo::Daemon::Run();
-}
-
-uint32_t MetricsCollector::GetOsVersionHash() {
- brillo::OsReleaseReader reader;
- reader.Load();
- string version;
- if (!reader.GetString(metrics::kProductVersion, &version)) {
- LOG(ERROR) << "failed to read the product version.";
- version = metrics::kDefaultVersion;
- }
-
- uint32_t version_hash = base::Hash(version);
- if (testing_) {
- version_hash = 42; // return any plausible value for the hash
- }
- return version_hash;
-}
-
-void MetricsCollector::Init(bool testing, MetricsLibraryInterface* metrics_lib,
- const string& diskstats_path,
- const base::FilePath& private_metrics_directory,
- const base::FilePath& shared_metrics_directory) {
- CHECK(metrics_lib);
- testing_ = testing;
- shared_metrics_directory_ = shared_metrics_directory;
- metrics_lib_ = metrics_lib;
-
- daily_active_use_.reset(new PersistentInteger("Platform.UseTime.PerDay",
- private_metrics_directory));
- version_cumulative_active_use_.reset(new PersistentInteger(
- "Platform.CumulativeUseTime", private_metrics_directory));
- version_cumulative_cpu_use_.reset(new PersistentInteger(
- "Platform.CumulativeCpuTime", private_metrics_directory));
-
- kernel_crash_interval_.reset(new PersistentInteger(
- "Platform.KernelCrashInterval", private_metrics_directory));
- unclean_shutdown_interval_.reset(new PersistentInteger(
- "Platform.UncleanShutdownInterval", private_metrics_directory));
- user_crash_interval_.reset(new PersistentInteger("Platform.UserCrashInterval",
- private_metrics_directory));
-
- any_crashes_daily_count_.reset(new PersistentInteger(
- "Platform.AnyCrashes.PerDay", private_metrics_directory));
- any_crashes_weekly_count_.reset(new PersistentInteger(
- "Platform.AnyCrashes.PerWeek", private_metrics_directory));
- user_crashes_daily_count_.reset(new PersistentInteger(
- "Platform.UserCrashes.PerDay", private_metrics_directory));
- user_crashes_weekly_count_.reset(new PersistentInteger(
- "Platform.UserCrashes.PerWeek", private_metrics_directory));
- kernel_crashes_daily_count_.reset(new PersistentInteger(
- "Platform.KernelCrashes.PerDay", private_metrics_directory));
- kernel_crashes_weekly_count_.reset(new PersistentInteger(
- "Platform.KernelCrashes.PerWeek", private_metrics_directory));
- kernel_crashes_version_count_.reset(new PersistentInteger(
- "Platform.KernelCrashesSinceUpdate", private_metrics_directory));
- unclean_shutdowns_daily_count_.reset(new PersistentInteger(
- "Platform.UncleanShutdown.PerDay", private_metrics_directory));
- unclean_shutdowns_weekly_count_.reset(new PersistentInteger(
- "Platform.UncleanShutdowns.PerWeek", private_metrics_directory));
-
- daily_cycle_.reset(
- new PersistentInteger("daily.cycle", private_metrics_directory));
- weekly_cycle_.reset(
- new PersistentInteger("weekly.cycle", private_metrics_directory));
- version_cycle_.reset(
- new PersistentInteger("version.cycle", private_metrics_directory));
-
- disk_usage_collector_.reset(new DiskUsageCollector(metrics_lib_));
- averaged_stats_collector_.reset(
- new AveragedStatisticsCollector(metrics_lib_, diskstats_path,
- kVmStatFileName));
- cpu_usage_collector_.reset(new CpuUsageCollector(metrics_lib_));
-}
-
-int MetricsCollector::OnInit() {
- int return_code = brillo::Daemon::OnInit();
- if (return_code != EX_OK)
- return return_code;
-
- StatsReporterInit();
-
- // Start collecting meminfo stats.
- ScheduleMeminfoCallback(kMetricMeminfoInterval);
- memuse_final_time_ = GetActiveTime() + kMemuseIntervals[0];
- ScheduleMemuseCallback(kMemuseIntervals[0]);
-
- if (testing_)
- return EX_OK;
-
- weave_service_subscription_ = weaved::Service::Connect(
- brillo::MessageLoop::current(),
- base::Bind(&MetricsCollector::OnWeaveServiceConnected,
- weak_ptr_factory_.GetWeakPtr()));
-
- latest_cpu_use_microseconds_ = cpu_usage_collector_->GetCumulativeCpuUse();
- base::MessageLoop::current()->PostDelayedTask(FROM_HERE,
- base::Bind(&MetricsCollector::HandleUpdateStatsTimeout,
- weak_ptr_factory_.GetWeakPtr()),
- base::TimeDelta::FromMilliseconds(kUpdateStatsIntervalMs));
-
- return EX_OK;
-}
-
-void MetricsCollector::OnWeaveServiceConnected(
- const std::weak_ptr<weaved::Service>& service) {
- service_ = service;
- auto weave_service = service_.lock();
- if (!weave_service)
- return;
-
- weave_service->AddComponent(kWeaveComponent, {kWeaveTrait}, nullptr);
- weave_service->AddCommandHandler(
- kWeaveComponent, kWeaveTrait, "enableAnalyticsReporting",
- base::Bind(&MetricsCollector::OnEnableMetrics,
- weak_ptr_factory_.GetWeakPtr()));
- weave_service->AddCommandHandler(
- kWeaveComponent, kWeaveTrait, "disableAnalyticsReporting",
- base::Bind(&MetricsCollector::OnDisableMetrics,
- weak_ptr_factory_.GetWeakPtr()));
-
- UpdateWeaveState();
-}
-
-void MetricsCollector::OnEnableMetrics(
- std::unique_ptr<weaved::Command> command) {
- if (base::WriteFile(
- shared_metrics_directory_.Append(metrics::kConsentFileName), "", 0) !=
- 0) {
- PLOG(ERROR) << "Could not create the consent file.";
- command->Abort("metrics_error", "Could not create the consent file",
- nullptr);
- return;
- }
-
- UpdateWeaveState();
- command->Complete({}, nullptr);
-}
-
-void MetricsCollector::OnDisableMetrics(
- std::unique_ptr<weaved::Command> command) {
- if (!base::DeleteFile(
- shared_metrics_directory_.Append(metrics::kConsentFileName), false)) {
- PLOG(ERROR) << "Could not delete the consent file.";
- command->Abort("metrics_error", "Could not delete the consent file",
- nullptr);
- return;
- }
-
- UpdateWeaveState();
- command->Complete({}, nullptr);
-}
-
-void MetricsCollector::UpdateWeaveState() {
- auto weave_service = service_.lock();
- if (!weave_service)
- return;
-
- std::string enabled =
- metrics_lib_->AreMetricsEnabled() ? "enabled" : "disabled";
-
- if (!weave_service->SetStateProperty(kWeaveComponent, kWeaveTrait,
- "analyticsReportingState",
- *brillo::ToValue(enabled),
- nullptr)) {
- LOG(ERROR) << "failed to update weave's state";
- }
-}
-
-void MetricsCollector::ProcessUserCrash() {
- // Counts the active time up to now.
- UpdateStats(TimeTicks::Now(), Time::Now());
-
- // Reports the active use time since the last crash and resets it.
- SendAndResetCrashIntervalSample(user_crash_interval_);
-
- any_crashes_daily_count_->Add(1);
- any_crashes_weekly_count_->Add(1);
- user_crashes_daily_count_->Add(1);
- user_crashes_weekly_count_->Add(1);
-}
-
-void MetricsCollector::ProcessKernelCrash() {
- // Counts the active time up to now.
- UpdateStats(TimeTicks::Now(), Time::Now());
-
- // Reports the active use time since the last crash and resets it.
- SendAndResetCrashIntervalSample(kernel_crash_interval_);
-
- any_crashes_daily_count_->Add(1);
- any_crashes_weekly_count_->Add(1);
- kernel_crashes_daily_count_->Add(1);
- kernel_crashes_weekly_count_->Add(1);
-
- kernel_crashes_version_count_->Add(1);
-}
-
-void MetricsCollector::ProcessUncleanShutdown() {
- // Counts the active time up to now.
- UpdateStats(TimeTicks::Now(), Time::Now());
-
- // Reports the active use time since the last crash and resets it.
- SendAndResetCrashIntervalSample(unclean_shutdown_interval_);
-
- unclean_shutdowns_daily_count_->Add(1);
- unclean_shutdowns_weekly_count_->Add(1);
- any_crashes_daily_count_->Add(1);
- any_crashes_weekly_count_->Add(1);
-}
-
-bool MetricsCollector::CheckSystemCrash(const string& crash_file) {
- FilePath crash_detected(crash_file);
- if (!base::PathExists(crash_detected))
- return false;
-
- // Deletes the crash-detected file so that the daemon doesn't report
- // another kernel crash in case it's restarted.
- base::DeleteFile(crash_detected, false); // not recursive
- return true;
-}
-
-void MetricsCollector::StatsReporterInit() {
- disk_usage_collector_->Schedule();
-
- cpu_usage_collector_->Init();
- cpu_usage_collector_->Schedule();
-
- // Don't start a collection cycle during the first run to avoid delaying the
- // boot.
- averaged_stats_collector_->ScheduleWait();
-}
-
-void MetricsCollector::ScheduleMeminfoCallback(int wait) {
- if (testing_) {
- return;
- }
- base::TimeDelta waitDelta = base::TimeDelta::FromSeconds(wait);
- base::MessageLoop::current()->PostDelayedTask(FROM_HERE,
- base::Bind(&MetricsCollector::MeminfoCallback,
- weak_ptr_factory_.GetWeakPtr(), waitDelta),
- waitDelta);
-}
-
-void MetricsCollector::MeminfoCallback(base::TimeDelta wait) {
- string meminfo_raw;
- const FilePath meminfo_path(kMeminfoFileName);
- if (!base::ReadFileToString(meminfo_path, &meminfo_raw)) {
- LOG(WARNING) << "cannot read " << meminfo_path.value().c_str();
- return;
- }
- // Make both calls even if the first one fails.
- if (ProcessMeminfo(meminfo_raw)) {
- base::MessageLoop::current()->PostDelayedTask(FROM_HERE,
- base::Bind(&MetricsCollector::MeminfoCallback,
- weak_ptr_factory_.GetWeakPtr(), wait),
- wait);
- }
-}
-
-// static
-bool MetricsCollector::ReadFileToUint64(const base::FilePath& path,
- uint64_t* value) {
- std::string content;
- if (!base::ReadFileToString(path, &content)) {
- PLOG(WARNING) << "cannot read " << path.MaybeAsASCII();
- return false;
- }
- // Remove final newline.
- base::TrimWhitespaceASCII(content, base::TRIM_TRAILING, &content);
- if (!base::StringToUint64(content, value)) {
- LOG(WARNING) << "invalid integer: " << content;
- return false;
- }
- return true;
-}
-
-bool MetricsCollector::ReportZram(const base::FilePath& zram_dir) {
- // Data sizes are in bytes. |zero_pages| is in number of pages.
- uint64_t compr_data_size, orig_data_size, zero_pages;
- const size_t page_size = 4096;
-
- if (!ReadFileToUint64(zram_dir.Append(kComprDataSizeName),
- &compr_data_size) ||
- !ReadFileToUint64(zram_dir.Append(kOrigDataSizeName), &orig_data_size) ||
- !ReadFileToUint64(zram_dir.Append(kZeroPagesName), &zero_pages)) {
- return false;
- }
-
- // |orig_data_size| does not include zero-filled pages.
- orig_data_size += zero_pages * page_size;
-
- const int compr_data_size_mb = compr_data_size >> 20;
- const int savings_mb = (orig_data_size - compr_data_size) >> 20;
- const int zero_ratio_percent = zero_pages * page_size * 100 / orig_data_size;
-
- // Report compressed size in megabytes. 100 MB or less has little impact.
- SendSample("Platform.ZramCompressedSize", compr_data_size_mb, 100, 4000, 50);
- SendSample("Platform.ZramSavings", savings_mb, 100, 4000, 50);
- // The compression ratio is multiplied by 100 for better resolution. The
- // ratios of interest are between 1 and 6 (100% and 600% as reported). We
- // don't want samples when very little memory is being compressed.
- if (compr_data_size_mb >= 1) {
- SendSample("Platform.ZramCompressionRatioPercent",
- orig_data_size * 100 / compr_data_size, 100, 600, 50);
- }
- // The values of interest for zero_pages are between 1MB and 1GB. The units
- // are number of pages.
- SendSample("Platform.ZramZeroPages", zero_pages, 256, 256 * 1024, 50);
- SendSample("Platform.ZramZeroRatioPercent", zero_ratio_percent, 1, 50, 50);
-
- return true;
-}
-
-bool MetricsCollector::ProcessMeminfo(const string& meminfo_raw) {
- static const MeminfoRecord fields_array[] = {
- { "MemTotal", "MemTotal" }, // SPECIAL CASE: total system memory
- { "MemFree", "MemFree" },
- { "Buffers", "Buffers" },
- { "Cached", "Cached" },
- // { "SwapCached", "SwapCached" },
- { "Active", "Active" },
- { "Inactive", "Inactive" },
- { "ActiveAnon", "Active(anon)" },
- { "InactiveAnon", "Inactive(anon)" },
- { "ActiveFile" , "Active(file)" },
- { "InactiveFile", "Inactive(file)" },
- { "Unevictable", "Unevictable", kMeminfoOp_HistLog },
- // { "Mlocked", "Mlocked" },
- { "SwapTotal", "SwapTotal", kMeminfoOp_SwapTotal },
- { "SwapFree", "SwapFree", kMeminfoOp_SwapFree },
- // { "Dirty", "Dirty" },
- // { "Writeback", "Writeback" },
- { "AnonPages", "AnonPages" },
- { "Mapped", "Mapped" },
- { "Shmem", "Shmem", kMeminfoOp_HistLog },
- { "Slab", "Slab", kMeminfoOp_HistLog },
- // { "SReclaimable", "SReclaimable" },
- // { "SUnreclaim", "SUnreclaim" },
- };
- vector<MeminfoRecord> fields(fields_array,
- fields_array + arraysize(fields_array));
- if (!FillMeminfo(meminfo_raw, &fields)) {
- return false;
- }
- int total_memory = fields[0].value;
- if (total_memory == 0) {
- // this "cannot happen"
- LOG(WARNING) << "borked meminfo parser";
- return false;
- }
- int swap_total = 0;
- int swap_free = 0;
- // Send all fields retrieved, except total memory.
- for (unsigned int i = 1; i < fields.size(); i++) {
- string metrics_name = base::StringPrintf("Platform.Meminfo%s",
- fields[i].name);
- int percent;
- switch (fields[i].op) {
- case kMeminfoOp_HistPercent:
- // report value as percent of total memory
- percent = fields[i].value * 100 / total_memory;
- SendLinearSample(metrics_name, percent, 100, 101);
- break;
- case kMeminfoOp_HistLog:
- // report value in kbytes, log scale, 4Gb max
- SendSample(metrics_name, fields[i].value, 1, 4 * 1000 * 1000, 100);
- break;
- case kMeminfoOp_SwapTotal:
- swap_total = fields[i].value;
- case kMeminfoOp_SwapFree:
- swap_free = fields[i].value;
- break;
- }
- }
- if (swap_total > 0) {
- int swap_used = swap_total - swap_free;
- int swap_used_percent = swap_used * 100 / swap_total;
- SendSample("Platform.MeminfoSwapUsed", swap_used, 1, 8 * 1000 * 1000, 100);
- SendLinearSample("Platform.MeminfoSwapUsed.Percent", swap_used_percent,
- 100, 101);
- }
- return true;
-}
-
-bool MetricsCollector::FillMeminfo(const string& meminfo_raw,
- vector<MeminfoRecord>* fields) {
- vector<std::string> lines =
- base::SplitString(meminfo_raw, "\n", base::KEEP_WHITESPACE,
- base::SPLIT_WANT_NONEMPTY);
-
- // Scan meminfo output and collect field values. Each field name has to
- // match a meminfo entry (case insensitive) after removing non-alpha
- // characters from the entry.
- size_t ifield = 0;
- for (size_t iline = 0;
- iline < lines.size() && ifield < fields->size();
- iline++) {
- vector<string> tokens =
- base::SplitString(lines[iline], ": ", base::KEEP_WHITESPACE,
- base::SPLIT_WANT_NONEMPTY);
- if (strcmp((*fields)[ifield].match, tokens[0].c_str()) == 0) {
- // Name matches. Parse value and save.
- if (!base::StringToInt(tokens[1], &(*fields)[ifield].value)) {
- LOG(WARNING) << "Cound not convert " << tokens[1] << " to int";
- return false;
- }
- ifield++;
- }
- }
- if (ifield < fields->size()) {
- // End of input reached while scanning.
- LOG(WARNING) << "cannot find field " << (*fields)[ifield].match
- << " and following";
- return false;
- }
- return true;
-}
-
-void MetricsCollector::ScheduleMemuseCallback(double interval) {
- if (testing_) {
- return;
- }
- base::MessageLoop::current()->PostDelayedTask(FROM_HERE,
- base::Bind(&MetricsCollector::MemuseCallback,
- weak_ptr_factory_.GetWeakPtr()),
- base::TimeDelta::FromSeconds(interval));
-}
-
-void MetricsCollector::MemuseCallback() {
- // Since we only care about active time (i.e. uptime minus sleep time) but
- // the callbacks are driven by real time (uptime), we check if we should
- // reschedule this callback due to intervening sleep periods.
- double now = GetActiveTime();
- // Avoid intervals of less than one second.
- double remaining_time = ceil(memuse_final_time_ - now);
- if (remaining_time > 0) {
- ScheduleMemuseCallback(remaining_time);
- } else {
- // Report stats and advance the measurement interval unless there are
- // errors or we've completed the last interval.
- if (MemuseCallbackWork() &&
- memuse_interval_index_ < arraysize(kMemuseIntervals)) {
- double interval = kMemuseIntervals[memuse_interval_index_++];
- memuse_final_time_ = now + interval;
- ScheduleMemuseCallback(interval);
- }
- }
-}
-
-bool MetricsCollector::MemuseCallbackWork() {
- string meminfo_raw;
- const FilePath meminfo_path(kMeminfoFileName);
- if (!base::ReadFileToString(meminfo_path, &meminfo_raw)) {
- LOG(WARNING) << "cannot read " << meminfo_path.value().c_str();
- return false;
- }
- return ProcessMemuse(meminfo_raw);
-}
-
-bool MetricsCollector::ProcessMemuse(const string& meminfo_raw) {
- static const MeminfoRecord fields_array[] = {
- { "MemTotal", "MemTotal" }, // SPECIAL CASE: total system memory
- { "ActiveAnon", "Active(anon)" },
- { "InactiveAnon", "Inactive(anon)" },
- };
- vector<MeminfoRecord> fields(fields_array,
- fields_array + arraysize(fields_array));
- if (!FillMeminfo(meminfo_raw, &fields)) {
- return false;
- }
- int total = fields[0].value;
- int active_anon = fields[1].value;
- int inactive_anon = fields[2].value;
- if (total == 0) {
- // this "cannot happen"
- LOG(WARNING) << "borked meminfo parser";
- return false;
- }
- string metrics_name = base::StringPrintf("Platform.MemuseAnon%d",
- memuse_interval_index_);
- SendLinearSample(metrics_name, (active_anon + inactive_anon) * 100 / total,
- 100, 101);
- return true;
-}
-
-void MetricsCollector::SendSample(const string& name, int sample,
- int min, int max, int nbuckets) {
- metrics_lib_->SendToUMA(name, sample, min, max, nbuckets);
-}
-
-void MetricsCollector::SendKernelCrashesCumulativeCountStats() {
- // Report the number of crashes for this OS version, but don't clear the
- // counter. It is cleared elsewhere on version change.
- int64_t crashes_count = kernel_crashes_version_count_->Get();
- SendSample(kernel_crashes_version_count_->Name(),
- crashes_count,
- 1, // value of first bucket
- 500, // value of last bucket
- 100); // number of buckets
-
-
- int64_t cpu_use_ms = version_cumulative_cpu_use_->Get();
- SendSample(version_cumulative_cpu_use_->Name(),
- cpu_use_ms / 1000, // stat is in seconds
- 1, // device may be used very little...
- 8 * 1000 * 1000, // ... or a lot (a little over 90 days)
- 100);
-
- // On the first run after an autoupdate, cpu_use_ms and active_use_seconds
- // can be zero. Avoid division by zero.
- if (cpu_use_ms > 0) {
- // Send the crash frequency since update in number of crashes per CPU year.
- SendSample("Logging.KernelCrashesPerCpuYear",
- crashes_count * kSecondsPerDay * 365 * 1000 / cpu_use_ms,
- 1,
- 1000 * 1000, // about one crash every 30s of CPU time
- 100);
- }
-
- int64_t active_use_seconds = version_cumulative_active_use_->Get();
- if (active_use_seconds > 0) {
- SendSample(version_cumulative_active_use_->Name(),
- active_use_seconds,
- 1, // device may be used very little...
- 8 * 1000 * 1000, // ... or a lot (about 90 days)
- 100);
- // Same as above, but per year of active time.
- SendSample("Logging.KernelCrashesPerActiveYear",
- crashes_count * kSecondsPerDay * 365 / active_use_seconds,
- 1,
- 1000 * 1000, // about one crash every 30s of active time
- 100);
- }
-}
-
-void MetricsCollector::SendAndResetDailyUseSample(
- const unique_ptr<PersistentInteger>& use) {
- SendSample(use->Name(),
- use->GetAndClear(),
- 1, // value of first bucket
- kSecondsPerDay, // value of last bucket
- 50); // number of buckets
-}
-
-void MetricsCollector::SendAndResetCrashIntervalSample(
- const unique_ptr<PersistentInteger>& interval) {
- SendSample(interval->Name(),
- interval->GetAndClear(),
- 1, // value of first bucket
- 4 * kSecondsPerWeek, // value of last bucket
- 50); // number of buckets
-}
-
-void MetricsCollector::SendAndResetCrashFrequencySample(
- const unique_ptr<PersistentInteger>& frequency) {
- SendSample(frequency->Name(),
- frequency->GetAndClear(),
- 1, // value of first bucket
- 100, // value of last bucket
- 50); // number of buckets
-}
-
-void MetricsCollector::SendLinearSample(const string& name, int sample,
- int max, int nbuckets) {
- // TODO(semenzato): add a proper linear histogram to the Chrome external
- // metrics API.
- LOG_IF(FATAL, nbuckets != max + 1) << "unsupported histogram scale";
- metrics_lib_->SendEnumToUMA(name, sample, max);
-}
-
-void MetricsCollector::UpdateStats(TimeTicks now_ticks,
- Time now_wall_time) {
- const int elapsed_seconds = (now_ticks - last_update_stats_time_).InSeconds();
- daily_active_use_->Add(elapsed_seconds);
- version_cumulative_active_use_->Add(elapsed_seconds);
- user_crash_interval_->Add(elapsed_seconds);
- kernel_crash_interval_->Add(elapsed_seconds);
- TimeDelta cpu_use = cpu_usage_collector_->GetCumulativeCpuUse();
- version_cumulative_cpu_use_->Add(
- (cpu_use - latest_cpu_use_microseconds_).InMilliseconds());
- latest_cpu_use_microseconds_ = cpu_use;
- last_update_stats_time_ = now_ticks;
-
- const TimeDelta since_epoch = now_wall_time - Time::UnixEpoch();
- const int day = since_epoch.InDays();
- const int week = day / 7;
-
- if (daily_cycle_->Get() != day) {
- daily_cycle_->Set(day);
- SendAndResetDailyUseSample(daily_active_use_);
- SendAndResetCrashFrequencySample(any_crashes_daily_count_);
- SendAndResetCrashFrequencySample(user_crashes_daily_count_);
- SendAndResetCrashFrequencySample(kernel_crashes_daily_count_);
- SendAndResetCrashFrequencySample(unclean_shutdowns_daily_count_);
- SendKernelCrashesCumulativeCountStats();
- }
-
- if (weekly_cycle_->Get() != week) {
- weekly_cycle_->Set(week);
- SendAndResetCrashFrequencySample(any_crashes_weekly_count_);
- SendAndResetCrashFrequencySample(user_crashes_weekly_count_);
- SendAndResetCrashFrequencySample(kernel_crashes_weekly_count_);
- SendAndResetCrashFrequencySample(unclean_shutdowns_weekly_count_);
- }
-}
-
-void MetricsCollector::HandleUpdateStatsTimeout() {
- UpdateStats(TimeTicks::Now(), Time::Now());
- base::MessageLoop::current()->PostDelayedTask(FROM_HERE,
- base::Bind(&MetricsCollector::HandleUpdateStatsTimeout,
- weak_ptr_factory_.GetWeakPtr()),
- base::TimeDelta::FromMilliseconds(kUpdateStatsIntervalMs));
-}
diff --git a/metricsd/metrics_collector.h b/metricsd/metrics_collector.h
deleted file mode 100644
index 30659bd..0000000
--- a/metricsd/metrics_collector.h
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-
-#ifndef METRICS_METRICS_COLLECTOR_H_
-#define METRICS_METRICS_COLLECTOR_H_
-
-#include <stdint.h>
-
-#include <map>
-#include <memory>
-#include <string>
-#include <vector>
-
-#include <base/files/file_path.h>
-#include <base/memory/weak_ptr.h>
-#include <base/time/time.h>
-#include <brillo/binder_watcher.h>
-#include <brillo/daemons/daemon.h>
-#include <libweaved/command.h>
-#include <libweaved/service.h>
-#include <gtest/gtest_prod.h> // for FRIEND_TEST
-
-#include "collectors/averaged_statistics_collector.h"
-#include "collectors/cpu_usage_collector.h"
-#include "collectors/disk_usage_collector.h"
-#include "metrics/metrics_library.h"
-#include "persistent_integer.h"
-
-using chromeos_metrics::PersistentInteger;
-using std::unique_ptr;
-
-class MetricsCollector : public brillo::Daemon {
- public:
- MetricsCollector();
- ~MetricsCollector();
-
- // Initializes metrics class variables.
- void Init(bool testing,
- MetricsLibraryInterface* metrics_lib,
- const std::string& diskstats_path,
- const base::FilePath& private_metrics_directory,
- const base::FilePath& shared_metrics_directory);
-
- // Initializes the daemon.
- int OnInit() override;
-
- // Does all the work.
- int Run() override;
-
- // Returns the active time since boot (uptime minus sleep time) in seconds.
- static double GetActiveTime();
-
- // Updates the active use time and logs time between user-space
- // process crashes. Called via MetricsCollectorServiceTrampoline.
- void ProcessUserCrash();
-
- protected:
- // Used also by the unit tests.
- static const char kComprDataSizeName[];
- static const char kOrigDataSizeName[];
- static const char kZeroPagesName[];
-
- private:
- friend class MetricsCollectorTest;
- FRIEND_TEST(MetricsCollectorTest, CheckSystemCrash);
- FRIEND_TEST(MetricsCollectorTest, ComputeEpochNoCurrent);
- FRIEND_TEST(MetricsCollectorTest, ComputeEpochNoLast);
- FRIEND_TEST(MetricsCollectorTest, GetHistogramPath);
- FRIEND_TEST(MetricsCollectorTest, IsNewEpoch);
- FRIEND_TEST(MetricsCollectorTest, MessageFilter);
- FRIEND_TEST(MetricsCollectorTest, ProcessKernelCrash);
- FRIEND_TEST(MetricsCollectorTest, ProcessMeminfo);
- FRIEND_TEST(MetricsCollectorTest, ProcessMeminfo2);
- FRIEND_TEST(MetricsCollectorTest, ProcessUncleanShutdown);
- FRIEND_TEST(MetricsCollectorTest, ProcessUserCrash);
- FRIEND_TEST(MetricsCollectorTest, ReportCrashesDailyFrequency);
- FRIEND_TEST(MetricsCollectorTest, ReportKernelCrashInterval);
- FRIEND_TEST(MetricsCollectorTest, ReportUncleanShutdownInterval);
- FRIEND_TEST(MetricsCollectorTest, ReportUserCrashInterval);
- FRIEND_TEST(MetricsCollectorTest, SendSample);
- FRIEND_TEST(MetricsCollectorTest, SendZramMetrics);
-
- // Type of scale to use for meminfo histograms. For most of them we use
- // percent of total RAM, but for some we use absolute numbers, usually in
- // megabytes, on a log scale from 0 to 4000, and 0 to 8000 for compressed
- // swap (since it can be larger than total RAM).
- enum MeminfoOp {
- kMeminfoOp_HistPercent = 0,
- kMeminfoOp_HistLog,
- kMeminfoOp_SwapTotal,
- kMeminfoOp_SwapFree,
- };
-
- // Record for retrieving and reporting values from /proc/meminfo.
- struct MeminfoRecord {
- const char* name; // print name
- const char* match; // string to match in output of /proc/meminfo
- MeminfoOp op; // histogram scale selector, or other operator
- int value; // value from /proc/meminfo
- };
-
- // Enables metrics reporting.
- void OnEnableMetrics(std::unique_ptr<weaved::Command> command);
-
- // Disables metrics reporting.
- void OnDisableMetrics(std::unique_ptr<weaved::Command> command);
-
- // Updates the weave device state.
- void UpdateWeaveState();
-
- // Updates the active use time and logs time between kernel crashes.
- void ProcessKernelCrash();
-
- // Updates the active use time and logs time between unclean shutdowns.
- void ProcessUncleanShutdown();
-
- // Checks if a kernel crash has been detected and returns true if
- // so. The method assumes that a kernel crash has happened if
- // |crash_file| exists. It removes the file immediately if it
- // exists, so it must not be called more than once.
- bool CheckSystemCrash(const std::string& crash_file);
-
- // Sends a regular (exponential) histogram sample to Chrome for
- // transport to UMA. See MetricsLibrary::SendToUMA in
- // metrics_library.h for a description of the arguments.
- void SendSample(const std::string& name, int sample,
- int min, int max, int nbuckets);
-
- // Sends a linear histogram sample to Chrome for transport to UMA. See
- // MetricsLibrary::SendToUMA in metrics_library.h for a description of the
- // arguments.
- void SendLinearSample(const std::string& name, int sample,
- int max, int nbuckets);
-
- // Sends various cumulative kernel crash-related stats, for instance the
- // total number of kernel crashes since the last version update.
- void SendKernelCrashesCumulativeCountStats();
-
- // Sends a sample representing the number of seconds of active use
- // for a 24-hour period and reset |use|.
- void SendAndResetDailyUseSample(const unique_ptr<PersistentInteger>& use);
-
- // Sends a sample representing a time interval between two crashes of the
- // same type and reset |interval|.
- void SendAndResetCrashIntervalSample(
- const unique_ptr<PersistentInteger>& interval);
-
- // Sends a sample representing a frequency of crashes of some type and reset
- // |frequency|.
- void SendAndResetCrashFrequencySample(
- const unique_ptr<PersistentInteger>& frequency);
-
- // Initializes vm and disk stats reporting.
- void StatsReporterInit();
-
- // Schedules meminfo collection callback.
- void ScheduleMeminfoCallback(int wait);
-
- // Reports memory statistics. Reschedules callback on success.
- void MeminfoCallback(base::TimeDelta wait);
-
- // Parses content of /proc/meminfo and sends fields of interest to UMA.
- // Returns false on errors. |meminfo_raw| contains the content of
- // /proc/meminfo.
- bool ProcessMeminfo(const std::string& meminfo_raw);
-
- // Parses meminfo data from |meminfo_raw|. |fields| is a vector containing
- // the fields of interest. The order of the fields must be the same in which
- // /proc/meminfo prints them. The result of parsing fields[i] is placed in
- // fields[i].value.
- bool FillMeminfo(const std::string& meminfo_raw,
- std::vector<MeminfoRecord>* fields);
-
- // Schedule a memory use callback in |interval| seconds.
- void ScheduleMemuseCallback(double interval);
-
- // Calls MemuseCallbackWork, and possibly schedules next callback, if enough
- // active time has passed. Otherwise reschedules itself to simulate active
- // time callbacks (i.e. wall clock time minus sleep time).
- void MemuseCallback();
-
- // Reads /proc/meminfo and sends total anonymous memory usage to UMA.
- bool MemuseCallbackWork();
-
- // Parses meminfo data and sends it to UMA.
- bool ProcessMemuse(const std::string& meminfo_raw);
-
- // Reads the current OS version from /etc/lsb-release and hashes it
- // to a unsigned 32-bit int.
- uint32_t GetOsVersionHash();
-
- // Updates stats, additionally sending them to UMA if enough time has elapsed
- // since the last report.
- void UpdateStats(base::TimeTicks now_ticks, base::Time now_wall_time);
-
- // Invoked periodically by |update_stats_timeout_id_| to call UpdateStats().
- void HandleUpdateStatsTimeout();
-
- // Reports zram statistics.
- bool ReportZram(const base::FilePath& zram_dir);
-
- // Reads a string from a file and converts it to uint64_t.
- static bool ReadFileToUint64(const base::FilePath& path, uint64_t* value);
-
- // Callback invoked when a connection to weaved's service is established
- // over Binder interface.
- void OnWeaveServiceConnected(const std::weak_ptr<weaved::Service>& service);
-
- // VARIABLES
-
- // Test mode.
- bool testing_;
-
- // Publicly readable metrics directory.
- base::FilePath shared_metrics_directory_;
-
- // The metrics library handle.
- MetricsLibraryInterface* metrics_lib_;
-
- // The last time that UpdateStats() was called.
- base::TimeTicks last_update_stats_time_;
-
- // End time of current memuse stat collection interval.
- double memuse_final_time_;
-
- // Selects the wait time for the next memory use callback.
- unsigned int memuse_interval_index_;
-
- // Used internally by GetIncrementalCpuUse() to return the CPU utilization
- // between calls.
- base::TimeDelta latest_cpu_use_microseconds_;
-
- // Persistent values and accumulators for crash statistics.
- unique_ptr<PersistentInteger> daily_cycle_;
- unique_ptr<PersistentInteger> weekly_cycle_;
- unique_ptr<PersistentInteger> version_cycle_;
-
- // Active use accumulated in a day.
- unique_ptr<PersistentInteger> daily_active_use_;
- // Active use accumulated since the latest version update.
- unique_ptr<PersistentInteger> version_cumulative_active_use_;
-
- // The CPU time accumulator. This contains the CPU time, in milliseconds,
- // used by the system since the most recent OS version update.
- unique_ptr<PersistentInteger> version_cumulative_cpu_use_;
-
- unique_ptr<PersistentInteger> user_crash_interval_;
- unique_ptr<PersistentInteger> kernel_crash_interval_;
- unique_ptr<PersistentInteger> unclean_shutdown_interval_;
-
- unique_ptr<PersistentInteger> any_crashes_daily_count_;
- unique_ptr<PersistentInteger> any_crashes_weekly_count_;
- unique_ptr<PersistentInteger> user_crashes_daily_count_;
- unique_ptr<PersistentInteger> user_crashes_weekly_count_;
- unique_ptr<PersistentInteger> kernel_crashes_daily_count_;
- unique_ptr<PersistentInteger> kernel_crashes_weekly_count_;
- unique_ptr<PersistentInteger> kernel_crashes_version_count_;
- unique_ptr<PersistentInteger> unclean_shutdowns_daily_count_;
- unique_ptr<PersistentInteger> unclean_shutdowns_weekly_count_;
-
- unique_ptr<CpuUsageCollector> cpu_usage_collector_;
- unique_ptr<DiskUsageCollector> disk_usage_collector_;
- unique_ptr<AveragedStatisticsCollector> averaged_stats_collector_;
-
- unique_ptr<weaved::Service::Subscription> weave_service_subscription_;
- std::weak_ptr<weaved::Service> service_;
-
- base::WeakPtrFactory<MetricsCollector> weak_ptr_factory_{this};
-};
-
-#endif // METRICS_METRICS_COLLECTOR_H_
diff --git a/metricsd/metrics_collector.rc b/metricsd/metrics_collector.rc
deleted file mode 100644
index 2d7667d..0000000
--- a/metricsd/metrics_collector.rc
+++ /dev/null
@@ -1,4 +0,0 @@
-service metricscollector /system/bin/metrics_collector --foreground --logtosyslog
- class late_start
- user metrics_coll
- group metrics_coll
diff --git a/metricsd/metrics_collector_main.cc b/metricsd/metrics_collector_main.cc
deleted file mode 100644
index 14bb935..0000000
--- a/metricsd/metrics_collector_main.cc
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2015 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 <base/at_exit.h>
-#include <base/command_line.h>
-#include <base/logging.h>
-#include <base/strings/string_util.h>
-#include <brillo/flag_helper.h>
-#include <brillo/syslog_logging.h>
-#include <rootdev.h>
-
-#include "constants.h"
-#include "metrics_collector.h"
-
-
-// Returns the path to the disk stats in the sysfs. Returns the null string if
-// it cannot find the disk stats file.
-static
-const std::string MetricsMainDiskStatsPath() {
- char dev_path_cstr[PATH_MAX];
- std::string dev_prefix = "/dev/block/";
- std::string dev_path;
-
- int ret = rootdev(dev_path_cstr, sizeof(dev_path_cstr), true, true);
- if (ret != 0) {
- LOG(WARNING) << "error " << ret << " determining root device";
- return "";
- }
- dev_path = dev_path_cstr;
- // Check that rootdev begins with "/dev/block/".
- if (!base::StartsWith(dev_path, dev_prefix,
- base::CompareCase::INSENSITIVE_ASCII)) {
- LOG(WARNING) << "unexpected root device " << dev_path;
- return "";
- }
- return "/sys/class/block/" + dev_path.substr(dev_prefix.length()) + "/stat";
-}
-
-int main(int argc, char** argv) {
- DEFINE_bool(foreground, false, "Don't daemonize");
-
- DEFINE_string(private_directory, metrics::kMetricsCollectorDirectory,
- "Path to the private directory used by metrics_collector "
- "(testing only)");
- DEFINE_string(shared_directory, metrics::kSharedMetricsDirectory,
- "Path to the shared metrics directory, used by "
- "metrics_collector, metricsd and all metrics clients "
- "(testing only)");
-
- DEFINE_bool(logtostderr, false, "Log to standard error");
- DEFINE_bool(logtosyslog, false, "Log to syslog");
-
- brillo::FlagHelper::Init(argc, argv, "Chromium OS Metrics Daemon");
-
- int logging_location = (FLAGS_foreground ? brillo::kLogToStderr
- : brillo::kLogToSyslog);
- if (FLAGS_logtosyslog)
- logging_location = brillo::kLogToSyslog;
-
- if (FLAGS_logtostderr)
- logging_location = brillo::kLogToStderr;
-
- // Also log to stderr when not running as daemon.
- brillo::InitLog(logging_location | brillo::kLogHeader);
-
- if (FLAGS_logtostderr && FLAGS_logtosyslog) {
- LOG(ERROR) << "only one of --logtosyslog and --logtostderr can be set";
- return 1;
- }
-
- if (!FLAGS_foreground && daemon(0, 0) != 0) {
- return errno;
- }
-
- MetricsLibrary metrics_lib;
- metrics_lib.InitWithNoCaching();
- MetricsCollector daemon;
- daemon.Init(false,
- &metrics_lib,
- MetricsMainDiskStatsPath(),
- base::FilePath(FLAGS_private_directory),
- base::FilePath(FLAGS_shared_directory));
-
- daemon.Run();
-}
diff --git a/metricsd/metrics_collector_service_client.cc b/metricsd/metrics_collector_service_client.cc
deleted file mode 100644
index 08aaa4a..0000000
--- a/metricsd/metrics_collector_service_client.cc
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-
-// Client interface to IMetricsCollectorService.
-
-#include "metrics/metrics_collector_service_client.h"
-
-#include <base/logging.h>
-#include <binder/IServiceManager.h>
-#include <utils/String16.h>
-
-#include "android/brillo/metrics/IMetricsCollectorService.h"
-
-namespace {
-const char kMetricsCollectorServiceName[] =
- "android.brillo.metrics.IMetricsCollectorService";
-}
-
-bool MetricsCollectorServiceClient::Init() {
- const android::String16 name(kMetricsCollectorServiceName);
- metrics_collector_service_ = android::interface_cast<
- android::brillo::metrics::IMetricsCollectorService>(
- android::defaultServiceManager()->checkService(name));
-
- if (metrics_collector_service_ == nullptr)
- LOG(ERROR) << "Unable to lookup service " << kMetricsCollectorServiceName;
-
- return metrics_collector_service_ != nullptr;
-}
-
-bool MetricsCollectorServiceClient::notifyUserCrash() {
- if (metrics_collector_service_ == nullptr)
- return false;
-
- metrics_collector_service_->notifyUserCrash();
- return true;
-}
diff --git a/metricsd/metrics_collector_service_impl.cc b/metricsd/metrics_collector_service_impl.cc
deleted file mode 100644
index 4d9a05a..0000000
--- a/metricsd/metrics_collector_service_impl.cc
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2015 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 "metrics_collector_service_impl.h"
-
-#include <binder/IServiceManager.h>
-#include <binder/Status.h>
-#include <utils/Errors.h>
-
-#include "metrics_collector.h"
-
-using namespace android;
-
-BnMetricsCollectorServiceImpl::BnMetricsCollectorServiceImpl(
- MetricsCollector* metrics_collector)
- : metrics_collector_(metrics_collector) {
-}
-
-android::binder::Status BnMetricsCollectorServiceImpl::notifyUserCrash() {
- metrics_collector_->ProcessUserCrash();
- return android::binder::Status::ok();
-}
diff --git a/metricsd/metrics_collector_service_impl.h b/metricsd/metrics_collector_service_impl.h
deleted file mode 100644
index 8db418a..0000000
--- a/metricsd/metrics_collector_service_impl.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-
-#ifndef METRICSD_METRICS_COLLECTOR_SERVICE_IMPL_H_
-#define METRICSD_METRICS_COLLECTOR_SERVICE_IMPL_H_
-
-// metrics_collector binder service implementation. Constructed by
-// MetricsCollector.
-
-#include "android/brillo/metrics/BnMetricsCollectorService.h"
-
-#include <binder/Status.h>
-
-class MetricsCollector;
-
-class BnMetricsCollectorServiceImpl
- : public android::brillo::metrics::BnMetricsCollectorService {
- public:
- // Passed a this pointer from the MetricsCollector object that constructs us.
- explicit BnMetricsCollectorServiceImpl(
- MetricsCollector* metrics_collector_service);
-
- virtual ~BnMetricsCollectorServiceImpl() = default;
-
- // Called by crash_reporter to report a userspace crash event. We relay
- // this to MetricsCollector.
- android::binder::Status notifyUserCrash();
-
- private:
- // MetricsCollector object that constructs us, we use this to call back
- // to it.
- MetricsCollector* metrics_collector_;
-};
-
-#endif // METRICSD_METRICS_COLLECTOR_SERVICE_IMPL_H_
diff --git a/metricsd/metrics_collector_test.cc b/metricsd/metrics_collector_test.cc
deleted file mode 100644
index 8dda529..0000000
--- a/metricsd/metrics_collector_test.cc
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * Copyright (C) 2015 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 <vector>
-
-#include <base/at_exit.h>
-#include <base/files/file_util.h>
-#include <base/files/scoped_temp_dir.h>
-#include <base/strings/string_number_conversions.h>
-#include <brillo/flag_helper.h>
-#include <gtest/gtest.h>
-
-#include "constants.h"
-#include "metrics_collector.h"
-#include "metrics/metrics_library_mock.h"
-#include "persistent_integer_mock.h"
-
-using base::FilePath;
-using base::TimeDelta;
-using std::string;
-using std::vector;
-using ::testing::_;
-using ::testing::AnyNumber;
-using ::testing::AtLeast;
-using ::testing::Return;
-using ::testing::StrictMock;
-using chromeos_metrics::PersistentIntegerMock;
-
-
-class MetricsCollectorTest : public testing::Test {
- protected:
- virtual void SetUp() {
- brillo::FlagHelper::Init(0, nullptr, "");
- EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
-
- base::FilePath private_dir = temp_dir_.path().Append("private");
- base::FilePath shared_dir = temp_dir_.path().Append("shared");
-
- EXPECT_TRUE(base::CreateDirectory(private_dir));
- EXPECT_TRUE(base::CreateDirectory(shared_dir));
-
- daemon_.Init(true, &metrics_lib_, "", private_dir, shared_dir);
- }
-
- // Adds a metrics library mock expectation that the specified metric
- // will be generated.
- void ExpectSample(const std::string& name, int sample) {
- EXPECT_CALL(metrics_lib_, SendToUMA(name, sample, _, _, _))
- .Times(1)
- .WillOnce(Return(true))
- .RetiresOnSaturation();
- }
-
- // Creates or overwrites the file in |path| so that it contains the printable
- // representation of |value|.
- void CreateUint64ValueFile(const base::FilePath& path, uint64_t value) {
- std::string value_string = base::Uint64ToString(value);
- ASSERT_EQ(value_string.length(),
- base::WriteFile(path, value_string.c_str(),
- value_string.length()));
- }
-
- // The MetricsCollector under test.
- MetricsCollector daemon_;
-
- // Temporary directory used for tests.
- base::ScopedTempDir temp_dir_;
-
- // Mocks. They are strict mock so that all unexpected
- // calls are marked as failures.
- StrictMock<MetricsLibraryMock> metrics_lib_;
-};
-
-TEST_F(MetricsCollectorTest, SendSample) {
- ExpectSample("Dummy.Metric", 3);
- daemon_.SendSample("Dummy.Metric", /* sample */ 3,
- /* min */ 1, /* max */ 100, /* buckets */ 50);
-}
-
-TEST_F(MetricsCollectorTest, ProcessMeminfo) {
- string meminfo =
- "MemTotal: 2000000 kB\nMemFree: 500000 kB\n"
- "Buffers: 1000000 kB\nCached: 213652 kB\n"
- "SwapCached: 0 kB\nActive: 133400 kB\n"
- "Inactive: 183396 kB\nActive(anon): 92984 kB\n"
- "Inactive(anon): 58860 kB\nActive(file): 40416 kB\n"
- "Inactive(file): 124536 kB\nUnevictable: 0 kB\n"
- "Mlocked: 0 kB\nSwapTotal: 0 kB\n"
- "SwapFree: 0 kB\nDirty: 40 kB\n"
- "Writeback: 0 kB\nAnonPages: 92652 kB\n"
- "Mapped: 59716 kB\nShmem: 59196 kB\n"
- "Slab: 16656 kB\nSReclaimable: 6132 kB\n"
- "SUnreclaim: 10524 kB\nKernelStack: 1648 kB\n"
- "PageTables: 2780 kB\nNFS_Unstable: 0 kB\n"
- "Bounce: 0 kB\nWritebackTmp: 0 kB\n"
- "CommitLimit: 970656 kB\nCommitted_AS: 1260528 kB\n"
- "VmallocTotal: 122880 kB\nVmallocUsed: 12144 kB\n"
- "VmallocChunk: 103824 kB\nDirectMap4k: 9636 kB\n"
- "DirectMap2M: 1955840 kB\n";
-
- // All enum calls must report percents.
- EXPECT_CALL(metrics_lib_, SendEnumToUMA(_, _, 100)).Times(AtLeast(1));
- // Check that MemFree is correctly computed at 25%.
- EXPECT_CALL(metrics_lib_, SendEnumToUMA("Platform.MeminfoMemFree", 25, 100))
- .Times(AtLeast(1));
- // Check that we call SendToUma at least once (log histogram).
- EXPECT_CALL(metrics_lib_, SendToUMA(_, _, _, _, _))
- .Times(AtLeast(1));
- // Make sure we don't report fields not in the list.
- EXPECT_CALL(metrics_lib_, SendToUMA("Platform.MeminfoMlocked", _, _, _, _))
- .Times(0);
- EXPECT_CALL(metrics_lib_, SendEnumToUMA("Platform.MeminfoMlocked", _, _))
- .Times(0);
- EXPECT_TRUE(daemon_.ProcessMeminfo(meminfo));
-}
-
-TEST_F(MetricsCollectorTest, ProcessMeminfo2) {
- string meminfo = "MemTotal: 2000000 kB\nMemFree: 1000000 kB\n";
- // Not enough fields.
- EXPECT_FALSE(daemon_.ProcessMeminfo(meminfo));
-}
-
-TEST_F(MetricsCollectorTest, SendZramMetrics) {
- EXPECT_TRUE(daemon_.testing_);
-
- // |compr_data_size| is the size in bytes of compressed data.
- const uint64_t compr_data_size = 50 * 1000 * 1000;
- // The constant '3' is a realistic but random choice.
- // |orig_data_size| does not include zero pages.
- const uint64_t orig_data_size = compr_data_size * 3;
- const uint64_t page_size = 4096;
- const uint64_t zero_pages = 10 * 1000 * 1000 / page_size;
-
- CreateUint64ValueFile(
- temp_dir_.path().Append(MetricsCollector::kComprDataSizeName),
- compr_data_size);
- CreateUint64ValueFile(
- temp_dir_.path().Append(MetricsCollector::kOrigDataSizeName),
- orig_data_size);
- CreateUint64ValueFile(
- temp_dir_.path().Append(MetricsCollector::kZeroPagesName), zero_pages);
-
- const uint64_t real_orig_size = orig_data_size + zero_pages * page_size;
- const uint64_t zero_ratio_percent =
- zero_pages * page_size * 100 / real_orig_size;
- // Ratio samples are in percents.
- const uint64_t actual_ratio_sample = real_orig_size * 100 / compr_data_size;
-
- EXPECT_CALL(metrics_lib_, SendToUMA(_, compr_data_size >> 20, _, _, _));
- EXPECT_CALL(metrics_lib_,
- SendToUMA(_, (real_orig_size - compr_data_size) >> 20, _, _, _));
- EXPECT_CALL(metrics_lib_, SendToUMA(_, actual_ratio_sample, _, _, _));
- EXPECT_CALL(metrics_lib_, SendToUMA(_, zero_pages, _, _, _));
- EXPECT_CALL(metrics_lib_, SendToUMA(_, zero_ratio_percent, _, _, _));
-
- EXPECT_TRUE(daemon_.ReportZram(temp_dir_.path()));
-}
diff --git a/metricsd/metrics_library.cc b/metricsd/metrics_library.cc
deleted file mode 100644
index d211ab4..0000000
--- a/metricsd/metrics_library.cc
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * Copyright (C) 2015 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 "metrics/metrics_library.h"
-
-#include <base/logging.h>
-#include <base/strings/stringprintf.h>
-#include <binder/IServiceManager.h>
-#include <errno.h>
-#include <sys/file.h>
-#include <sys/stat.h>
-#include <utils/String16.h>
-
-#include <cstdio>
-#include <cstring>
-
-#include "android/brillo/metrics/IMetricsd.h"
-#include "constants.h"
-
-static const char kCrosEventHistogramName[] = "Platform.CrOSEvent";
-static const int kCrosEventHistogramMax = 100;
-static const char kMetricsServiceName[] = "android.brillo.metrics.IMetricsd";
-
-/* Add new cros events here.
- *
- * The index of the event is sent in the message, so please do not
- * reorder the names.
- */
-static const char *kCrosEventNames[] = {
- "ModemManagerCommandSendFailure", // 0
- "HwWatchdogReboot", // 1
- "Cras.NoCodecsFoundAtBoot", // 2
- "Chaps.DatabaseCorrupted", // 3
- "Chaps.DatabaseRepairFailure", // 4
- "Chaps.DatabaseCreateFailure", // 5
- "Attestation.OriginSpecificExhausted", // 6
- "SpringPowerSupply.Original.High", // 7
- "SpringPowerSupply.Other.High", // 8
- "SpringPowerSupply.Original.Low", // 9
- "SpringPowerSupply.ChargerIdle", // 10
- "TPM.NonZeroDictionaryAttackCounter", // 11
- "TPM.EarlyResetDuringCommand", // 12
-};
-
-using android::binder::Status;
-using android::brillo::metrics::IMetricsd;
-using android::String16;
-
-MetricsLibrary::MetricsLibrary() {}
-MetricsLibrary::~MetricsLibrary() {}
-
-// We take buffer and buffer_size as parameters in order to simplify testing
-// of various alignments of the |device_name| with |buffer_size|.
-bool MetricsLibrary::IsDeviceMounted(const char* device_name,
- const char* mounts_file,
- char* buffer,
- int buffer_size,
- bool* result) {
- if (buffer == nullptr || buffer_size < 1)
- return false;
- int mounts_fd = open(mounts_file, O_RDONLY);
- if (mounts_fd < 0)
- return false;
- // match_offset describes:
- // -1 -- not beginning of line
- // 0..strlen(device_name)-1 -- this offset in device_name is next to match
- // strlen(device_name) -- matched full name, just need a space.
- int match_offset = 0;
- bool match = false;
- while (!match) {
- int read_size = read(mounts_fd, buffer, buffer_size);
- if (read_size <= 0) {
- if (errno == -EINTR)
- continue;
- break;
- }
- for (int i = 0; i < read_size; ++i) {
- if (buffer[i] == '\n') {
- match_offset = 0;
- continue;
- }
- if (match_offset < 0) {
- continue;
- }
- if (device_name[match_offset] == '\0') {
- if (buffer[i] == ' ') {
- match = true;
- break;
- }
- match_offset = -1;
- continue;
- }
-
- if (buffer[i] == device_name[match_offset]) {
- ++match_offset;
- } else {
- match_offset = -1;
- }
- }
- }
- close(mounts_fd);
- *result = match;
- return true;
-}
-
-bool MetricsLibrary::IsGuestMode() {
- char buffer[256];
- bool result = false;
- if (!IsDeviceMounted("guestfs",
- "/proc/mounts",
- buffer,
- sizeof(buffer),
- &result)) {
- return false;
- }
- return result && (access("/var/run/state/logged-in", F_OK) == 0);
-}
-
-bool MetricsLibrary::CheckService() {
- if (metricsd_proxy_.get() &&
- android::IInterface::asBinder(metricsd_proxy_)->isBinderAlive())
- return true;
-
- const String16 name(kMetricsServiceName);
- metricsd_proxy_ = android::interface_cast<IMetricsd>(
- android::defaultServiceManager()->checkService(name));
- return metricsd_proxy_.get();
-}
-
-bool MetricsLibrary::AreMetricsEnabled() {
- static struct stat stat_buffer;
- time_t this_check_time = time(nullptr);
- if (!use_caching_ || this_check_time != cached_enabled_time_) {
- cached_enabled_time_ = this_check_time;
- cached_enabled_ = stat(consent_file_.value().data(), &stat_buffer) >= 0;
- }
- return cached_enabled_;
-}
-
-void MetricsLibrary::Init() {
- base::FilePath dir = base::FilePath(metrics::kSharedMetricsDirectory);
- consent_file_ = dir.Append(metrics::kConsentFileName);
- cached_enabled_ = false;
- cached_enabled_time_ = 0;
- use_caching_ = true;
-}
-
-void MetricsLibrary::InitWithNoCaching() {
- Init();
- use_caching_ = false;
-}
-
-void MetricsLibrary::InitForTest(const base::FilePath& metrics_directory) {
- consent_file_ = metrics_directory.Append(metrics::kConsentFileName);
- cached_enabled_ = false;
- cached_enabled_time_ = 0;
- use_caching_ = true;
-}
-
-bool MetricsLibrary::SendToUMA(
- const std::string& name, int sample, int min, int max, int nbuckets) {
- return CheckService() &&
- metricsd_proxy_->recordHistogram(String16(name.c_str()), sample, min,
- max, nbuckets)
- .isOk();
-}
-
-bool MetricsLibrary::SendEnumToUMA(const std::string& name,
- int sample,
- int max) {
- return CheckService() &&
- metricsd_proxy_->recordLinearHistogram(String16(name.c_str()), sample,
- max)
- .isOk();
-}
-
-bool MetricsLibrary::SendBoolToUMA(const std::string& name, bool sample) {
- return CheckService() &&
- metricsd_proxy_->recordLinearHistogram(String16(name.c_str()),
- sample ? 1 : 0, 2)
- .isOk();
-}
-
-bool MetricsLibrary::SendSparseToUMA(const std::string& name, int sample) {
- return CheckService() &&
- metricsd_proxy_->recordSparseHistogram(String16(name.c_str()), sample)
- .isOk();
-}
-
-bool MetricsLibrary::SendCrashToUMA(const char* crash_kind) {
- return CheckService() &&
- metricsd_proxy_->recordCrash(String16(crash_kind)).isOk();
-}
-
-bool MetricsLibrary::SendCrosEventToUMA(const std::string& event) {
- for (size_t i = 0; i < arraysize(kCrosEventNames); i++) {
- if (strcmp(event.c_str(), kCrosEventNames[i]) == 0) {
- return SendEnumToUMA(kCrosEventHistogramName, i, kCrosEventHistogramMax);
- }
- }
- return false;
-}
-
-bool MetricsLibrary::GetHistogramsDump(std::string* dump) {
- android::String16 temp_dump;
- if (!CheckService() ||
- !metricsd_proxy_->getHistogramsDump(&temp_dump).isOk()) {
- return false;
- }
-
- *dump = android::String8(temp_dump).string();
- return true;
-}
diff --git a/metricsd/metrics_library_test.cc b/metricsd/metrics_library_test.cc
deleted file mode 100644
index 52fcce3..0000000
--- a/metricsd/metrics_library_test.cc
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (C) 2015 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 <base/files/file_util.h>
-#include <base/files/scoped_temp_dir.h>
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-
-#include "metrics/c_metrics_library.h"
-#include "metrics/metrics_library.h"
-
-
-class MetricsLibraryTest : public testing::Test {
- protected:
- virtual void SetUp() {
- ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
- lib_.InitForTest(temp_dir_.path());
- // Defeat metrics enabled caching between tests.
- lib_.cached_enabled_time_ = 0;
- }
-
- void SetMetricsConsent(bool enabled) {
- if (enabled) {
- ASSERT_EQ(base::WriteFile(lib_.consent_file_, "", 0), 0);
- } else {
- ASSERT_TRUE(base::DeleteFile(lib_.consent_file_, false));
- }
- }
-
- void VerifyEnabledCacheHit(bool to_value);
- void VerifyEnabledCacheEviction(bool to_value);
-
- MetricsLibrary lib_;
- base::ScopedTempDir temp_dir_;
-};
-
-TEST_F(MetricsLibraryTest, AreMetricsEnabledFalse) {
- SetMetricsConsent(false);
- EXPECT_FALSE(lib_.AreMetricsEnabled());
-}
-
-TEST_F(MetricsLibraryTest, AreMetricsEnabledTrue) {
- SetMetricsConsent(true);
- EXPECT_TRUE(lib_.AreMetricsEnabled());
-}
-
-void MetricsLibraryTest::VerifyEnabledCacheHit(bool to_value) {
- // We might step from one second to the next one time, but not 100
- // times in a row.
- for (int i = 0; i < 100; ++i) {
- lib_.cached_enabled_time_ = 0;
- SetMetricsConsent(to_value);
- lib_.AreMetricsEnabled();
- // If we check the metrics status twice in a row, we use the cached value
- // the second time.
- SetMetricsConsent(!to_value);
- if (lib_.AreMetricsEnabled() == to_value)
- return;
- }
- ADD_FAILURE() << "Did not see evidence of caching";
-}
-
-void MetricsLibraryTest::VerifyEnabledCacheEviction(bool to_value) {
- lib_.cached_enabled_time_ = 0;
- SetMetricsConsent(!to_value);
- ASSERT_EQ(!to_value, lib_.AreMetricsEnabled());
-
- SetMetricsConsent(to_value);
- // Sleep one second (or cheat to be faster) and check that we are not using
- // the cached value.
- --lib_.cached_enabled_time_;
- ASSERT_EQ(to_value, lib_.AreMetricsEnabled());
-}
-
-TEST_F(MetricsLibraryTest, AreMetricsEnabledCaching) {
- VerifyEnabledCacheHit(false);
- VerifyEnabledCacheHit(true);
- VerifyEnabledCacheEviction(false);
- VerifyEnabledCacheEviction(true);
-}
-
-TEST_F(MetricsLibraryTest, AreMetricsEnabledNoCaching) {
- // disable caching.
- lib_.use_caching_ = false;
-
- // Checking the consent repeatedly should return the right result.
- for (int i=0; i<100; ++i) {
- SetMetricsConsent(true);
- ASSERT_EQ(true, lib_.AreMetricsEnabled());
- SetMetricsConsent(false);
- ASSERT_EQ(false, lib_.AreMetricsEnabled());
- }
-}
diff --git a/metricsd/metricsd.rc b/metricsd/metricsd.rc
deleted file mode 100644
index 3d3e695..0000000
--- a/metricsd/metricsd.rc
+++ /dev/null
@@ -1,9 +0,0 @@
-on post-fs-data
- mkdir /data/misc/metrics 0750 metrics_coll system
- mkdir /data/misc/metricsd 0700 metricsd metricsd
- mkdir /data/misc/metrics_collector 0700 metrics_coll metrics_coll
-
-service metricsd /system/bin/metricsd --foreground --logtosyslog
- class late_start
- user metricsd
- group system inet
diff --git a/metricsd/metricsd_main.cc b/metricsd/metricsd_main.cc
deleted file mode 100644
index 0178342..0000000
--- a/metricsd/metricsd_main.cc
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2015 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 <base/command_line.h>
-#include <base/files/file_path.h>
-#include <base/logging.h>
-#include <base/time/time.h>
-#include <brillo/flag_helper.h>
-#include <brillo/syslog_logging.h>
-
-#include "constants.h"
-#include "uploader/metricsd_service_runner.h"
-#include "uploader/upload_service.h"
-
-int main(int argc, char** argv) {
- DEFINE_bool(foreground, false, "Don't daemonize");
-
- // Upload the metrics once and exit. (used for testing)
- DEFINE_bool(uploader_test, false, "run the uploader once and exit");
-
- // Upload Service flags.
- DEFINE_int32(upload_interval_secs, 1800,
- "Interval at which metricsd uploads the metrics.");
- DEFINE_int32(disk_persistence_interval_secs, 300,
- "Interval at which metricsd saves the aggregated metrics to "
- "disk to avoid losing them if metricsd stops in between "
- "two uploads.");
- DEFINE_string(server, metrics::kMetricsServer,
- "Server to upload the metrics to.");
- DEFINE_string(private_directory, metrics::kMetricsdDirectory,
- "Path to the private directory used by metricsd "
- "(testing only)");
- DEFINE_string(shared_directory, metrics::kSharedMetricsDirectory,
- "Path to the shared metrics directory, used by "
- "metrics_collector, metricsd and all metrics clients "
- "(testing only)");
-
- DEFINE_bool(logtostderr, false, "Log to standard error");
- DEFINE_bool(logtosyslog, false, "Log to syslog");
-
- brillo::FlagHelper::Init(argc, argv, "Brillo metrics daemon.");
-
- int logging_location =
- (FLAGS_foreground ? brillo::kLogToStderr : brillo::kLogToSyslog);
- if (FLAGS_logtosyslog)
- logging_location = brillo::kLogToSyslog;
-
- if (FLAGS_logtostderr)
- logging_location = brillo::kLogToStderr;
-
- // Also log to stderr when not running as daemon.
- brillo::InitLog(logging_location | brillo::kLogHeader);
-
- if (FLAGS_logtostderr && FLAGS_logtosyslog) {
- LOG(ERROR) << "only one of --logtosyslog and --logtostderr can be set";
- return 1;
- }
-
- if (!FLAGS_foreground && daemon(0, 0) != 0) {
- return errno;
- }
-
- UploadService upload_service(
- FLAGS_server, base::TimeDelta::FromSeconds(FLAGS_upload_interval_secs),
- base::TimeDelta::FromSeconds(FLAGS_disk_persistence_interval_secs),
- base::FilePath(FLAGS_private_directory),
- base::FilePath(FLAGS_shared_directory));
-
- return upload_service.Run();
-}
diff --git a/metricsd/persistent_integer.cc b/metricsd/persistent_integer.cc
deleted file mode 100644
index 7fe355e..0000000
--- a/metricsd/persistent_integer.cc
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 2015 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 "persistent_integer.h"
-
-#include <fcntl.h>
-
-#include <base/logging.h>
-#include <base/posix/eintr_wrapper.h>
-
-#include "constants.h"
-
-namespace chromeos_metrics {
-
-PersistentInteger::PersistentInteger(const std::string& name,
- const base::FilePath& directory)
- : value_(0),
- version_(kVersion),
- name_(name),
- backing_file_path_(directory.Append(name_)),
- synced_(false) {}
-
-PersistentInteger::~PersistentInteger() {}
-
-void PersistentInteger::Set(int64_t value) {
- value_ = value;
- Write();
-}
-
-int64_t PersistentInteger::Get() {
- // If not synced, then read. If the read fails, it's a good idea to write.
- if (!synced_ && !Read())
- Write();
- return value_;
-}
-
-int64_t PersistentInteger::GetAndClear() {
- int64_t v = Get();
- Set(0);
- return v;
-}
-
-void PersistentInteger::Add(int64_t x) {
- Set(Get() + x);
-}
-
-void PersistentInteger::Write() {
- int fd = HANDLE_EINTR(open(backing_file_path_.value().c_str(),
- O_WRONLY | O_CREAT | O_TRUNC,
- S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH));
- PCHECK(fd >= 0) << "cannot open " << backing_file_path_.value()
- << " for writing";
- PCHECK((HANDLE_EINTR(write(fd, &version_, sizeof(version_))) ==
- sizeof(version_)) &&
- (HANDLE_EINTR(write(fd, &value_, sizeof(value_))) ==
- sizeof(value_)))
- << "cannot write to " << backing_file_path_.value();
- close(fd);
- synced_ = true;
-}
-
-bool PersistentInteger::Read() {
- int fd = HANDLE_EINTR(open(backing_file_path_.value().c_str(), O_RDONLY));
- if (fd < 0) {
- PLOG(WARNING) << "cannot open " << backing_file_path_.value()
- << " for reading";
- return false;
- }
- int32_t version;
- int64_t value;
- bool read_succeeded = false;
- if (HANDLE_EINTR(read(fd, &version, sizeof(version))) == sizeof(version) &&
- version == version_ &&
- HANDLE_EINTR(read(fd, &value, sizeof(value))) == sizeof(value)) {
- value_ = value;
- read_succeeded = true;
- synced_ = true;
- }
- close(fd);
- return read_succeeded;
-}
-
-} // namespace chromeos_metrics
diff --git a/metricsd/persistent_integer.h b/metricsd/persistent_integer.h
deleted file mode 100644
index 96d9fc0..0000000
--- a/metricsd/persistent_integer.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-
-#ifndef METRICS_PERSISTENT_INTEGER_H_
-#define METRICS_PERSISTENT_INTEGER_H_
-
-#include <stdint.h>
-
-#include <string>
-
-#include <base/files/file_path.h>
-
-namespace chromeos_metrics {
-
-// PersistentIntegers is a named 64-bit integer value backed by a file.
-// The in-memory value acts as a write-through cache of the file value.
-// If the backing file doesn't exist or has bad content, the value is 0.
-
-class PersistentInteger {
- public:
- PersistentInteger(const std::string& name, const base::FilePath& directory);
-
- // Virtual only because of mock.
- virtual ~PersistentInteger();
-
- // Sets the value. This writes through to the backing file.
- void Set(int64_t v);
-
- // Gets the value. May sync from backing file first.
- int64_t Get();
-
- // Returns the name of the object.
- std::string Name() { return name_; }
-
- // Convenience function for Get() followed by Set(0).
- int64_t GetAndClear();
-
- // Convenience function for v = Get, Set(v + x).
- // Virtual only because of mock.
- virtual void Add(int64_t x);
-
- private:
- static const int kVersion = 1001;
-
- // Writes |value_| to the backing file, creating it if necessary.
- void Write();
-
- // Reads the value from the backing file, stores it in |value_|, and returns
- // true if the backing file is valid. Returns false otherwise, and creates
- // a valid backing file as a side effect.
- bool Read();
-
- int64_t value_;
- int32_t version_;
- std::string name_;
- base::FilePath backing_file_path_;
- bool synced_;
-};
-
-} // namespace chromeos_metrics
-
-#endif // METRICS_PERSISTENT_INTEGER_H_
diff --git a/metricsd/persistent_integer_mock.h b/metricsd/persistent_integer_mock.h
deleted file mode 100644
index 0be54d4..0000000
--- a/metricsd/persistent_integer_mock.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-
-#ifndef METRICS_PERSISTENT_INTEGER_MOCK_H_
-#define METRICS_PERSISTENT_INTEGER_MOCK_H_
-
-#include <string>
-
-#include <gmock/gmock.h>
-
-#include "persistent_integer.h"
-
-namespace chromeos_metrics {
-
-class PersistentIntegerMock : public PersistentInteger {
- public:
- explicit PersistentIntegerMock(const std::string& name,
- const base::FilePath& directory)
- : PersistentInteger(name, directory) {}
- MOCK_METHOD1(Add, void(int64_t count));
-};
-
-} // namespace chromeos_metrics
-
-#endif // METRICS_PERSISTENT_INTEGER_MOCK_H_
diff --git a/metricsd/persistent_integer_test.cc b/metricsd/persistent_integer_test.cc
deleted file mode 100644
index bf76261..0000000
--- a/metricsd/persistent_integer_test.cc
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2015 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 <memory>
-
-#include <base/compiler_specific.h>
-#include <base/files/file_enumerator.h>
-#include <base/files/file_util.h>
-#include <base/files/scoped_temp_dir.h>
-#include <gtest/gtest.h>
-
-#include "persistent_integer.h"
-
-const char kBackingFileName[] = "1.pibakf";
-
-using chromeos_metrics::PersistentInteger;
-
-class PersistentIntegerTest : public testing::Test {
- void SetUp() override {
- // Set testing mode.
- ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
- }
-
- protected:
- base::ScopedTempDir temp_dir_;
-};
-
-TEST_F(PersistentIntegerTest, BasicChecks) {
- std::unique_ptr<PersistentInteger> pi(
- new PersistentInteger(kBackingFileName, temp_dir_.path()));
-
- // Test initialization.
- EXPECT_EQ(0, pi->Get());
- EXPECT_EQ(kBackingFileName, pi->Name()); // boring
-
- // Test set and add.
- pi->Set(2);
- pi->Add(3);
- EXPECT_EQ(5, pi->Get());
-
- // Test persistence.
- pi.reset(new PersistentInteger(kBackingFileName, temp_dir_.path()));
- EXPECT_EQ(5, pi->Get());
-
- // Test GetAndClear.
- EXPECT_EQ(5, pi->GetAndClear());
- EXPECT_EQ(pi->Get(), 0);
-
- // Another persistence test.
- pi.reset(new PersistentInteger(kBackingFileName, temp_dir_.path()));
- EXPECT_EQ(0, pi->Get());
-}
diff --git a/metricsd/timer.cc b/metricsd/timer.cc
deleted file mode 100644
index 06fc336..0000000
--- a/metricsd/timer.cc
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (C) 2015 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 "metrics/timer.h"
-
-#include <string>
-
-#include "metrics/metrics_library.h"
-
-namespace chromeos_metrics {
-
-base::TimeTicks ClockWrapper::GetCurrentTime() const {
- return base::TimeTicks::Now();
-}
-
-Timer::Timer()
- : timer_state_(kTimerStopped),
- clock_wrapper_(new ClockWrapper()) {}
-
-bool Timer::Start() {
- elapsed_time_ = base::TimeDelta(); // Sets elapsed_time_ to zero.
- start_time_ = clock_wrapper_->GetCurrentTime();
- timer_state_ = kTimerRunning;
- return true;
-}
-
-bool Timer::Stop() {
- if (timer_state_ == kTimerStopped)
- return false;
- if (timer_state_ == kTimerRunning)
- elapsed_time_ += clock_wrapper_->GetCurrentTime() - start_time_;
- timer_state_ = kTimerStopped;
- return true;
-}
-
-bool Timer::Pause() {
- switch (timer_state_) {
- case kTimerStopped:
- if (!Start())
- return false;
- timer_state_ = kTimerPaused;
- return true;
- case kTimerRunning:
- timer_state_ = kTimerPaused;
- elapsed_time_ += clock_wrapper_->GetCurrentTime() - start_time_;
- return true;
- default:
- return false;
- }
-}
-
-bool Timer::Resume() {
- switch (timer_state_) {
- case kTimerStopped:
- return Start();
- case kTimerPaused:
- start_time_ = clock_wrapper_->GetCurrentTime();
- timer_state_ = kTimerRunning;
- return true;
- default:
- return false;
- }
-}
-
-bool Timer::Reset() {
- elapsed_time_ = base::TimeDelta(); // Sets elapsed_time_ to zero.
- timer_state_ = kTimerStopped;
- return true;
-}
-
-bool Timer::HasStarted() const {
- return timer_state_ != kTimerStopped;
-}
-
-bool Timer::GetElapsedTime(base::TimeDelta* elapsed_time) const {
- if (start_time_.is_null() || !elapsed_time)
- return false;
- *elapsed_time = elapsed_time_;
- if (timer_state_ == kTimerRunning) {
- *elapsed_time += clock_wrapper_->GetCurrentTime() - start_time_;
- }
- return true;
-}
-
-// static
-MetricsLibraryInterface* TimerReporter::metrics_lib_ = nullptr;
-
-TimerReporter::TimerReporter(const std::string& histogram_name, int min,
- int max, int num_buckets)
- : histogram_name_(histogram_name),
- min_(min),
- max_(max),
- num_buckets_(num_buckets) {}
-
-bool TimerReporter::ReportMilliseconds() const {
- base::TimeDelta elapsed_time;
- if (!metrics_lib_ || !GetElapsedTime(&elapsed_time)) return false;
- return metrics_lib_->SendToUMA(histogram_name_,
- elapsed_time.InMilliseconds(),
- min_,
- max_,
- num_buckets_);
-}
-
-} // namespace chromeos_metrics
diff --git a/metricsd/timer_test.cc b/metricsd/timer_test.cc
deleted file mode 100644
index cfbcd8a..0000000
--- a/metricsd/timer_test.cc
+++ /dev/null
@@ -1,464 +0,0 @@
-/*
- * Copyright (C) 2015 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 <stdint.h>
-
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-#include <memory>
-
-#include "metrics/metrics_library_mock.h"
-#include "metrics/timer.h"
-#include "metrics/timer_mock.h"
-
-using ::testing::_;
-using ::testing::Return;
-
-namespace chromeos_metrics {
-
-namespace {
-const int64_t kStime1MSec = 1400;
-const int64_t kEtime1MSec = 3000;
-const int64_t kDelta1MSec = 1600;
-
-const int64_t kStime2MSec = 4200;
-const int64_t kEtime2MSec = 5000;
-const int64_t kDelta2MSec = 800;
-
-const int64_t kStime3MSec = 6600;
-const int64_t kEtime3MSec = 6800;
-const int64_t kDelta3MSec = 200;
-} // namespace
-
-class TimerTest : public testing::Test {
- public:
- TimerTest() : clock_wrapper_mock_(new ClockWrapperMock()) {}
-
- protected:
- virtual void SetUp() {
- EXPECT_EQ(Timer::kTimerStopped, timer_.timer_state_);
- stime += base::TimeDelta::FromMilliseconds(kStime1MSec);
- etime += base::TimeDelta::FromMilliseconds(kEtime1MSec);
- stime2 += base::TimeDelta::FromMilliseconds(kStime2MSec);
- etime2 += base::TimeDelta::FromMilliseconds(kEtime2MSec);
- stime3 += base::TimeDelta::FromMilliseconds(kStime3MSec);
- etime3 += base::TimeDelta::FromMilliseconds(kEtime3MSec);
- }
-
- virtual void TearDown() {}
-
- Timer timer_;
- std::unique_ptr<ClockWrapperMock> clock_wrapper_mock_;
- base::TimeTicks stime, etime, stime2, etime2, stime3, etime3;
-};
-
-TEST_F(TimerTest, StartStop) {
- EXPECT_CALL(*clock_wrapper_mock_, GetCurrentTime())
- .WillOnce(Return(stime))
- .WillOnce(Return(etime));
- timer_.clock_wrapper_ = std::move(clock_wrapper_mock_);
- ASSERT_TRUE(timer_.Start());
- ASSERT_TRUE(timer_.start_time_ == stime);
- ASSERT_TRUE(timer_.HasStarted());
- ASSERT_TRUE(timer_.Stop());
- ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(), kDelta1MSec);
-
- base::TimeDelta elapsed_time;
- ASSERT_TRUE(timer_.GetElapsedTime(&elapsed_time));
- ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(),
- elapsed_time.InMilliseconds());
-
- ASSERT_FALSE(timer_.HasStarted());
-}
-
-TEST_F(TimerTest, ReStart) {
- EXPECT_CALL(*clock_wrapper_mock_, GetCurrentTime())
- .WillOnce(Return(stime))
- .WillOnce(Return(etime));
- timer_.clock_wrapper_ = std::move(clock_wrapper_mock_);
- timer_.Start();
- base::TimeTicks buffer = timer_.start_time_;
- timer_.Start();
- ASSERT_FALSE(timer_.start_time_ == buffer);
-}
-
-TEST_F(TimerTest, Reset) {
- EXPECT_CALL(*clock_wrapper_mock_, GetCurrentTime())
- .WillOnce(Return(stime));
- timer_.clock_wrapper_ = std::move(clock_wrapper_mock_);
- timer_.Start();
- ASSERT_TRUE(timer_.Reset());
- ASSERT_FALSE(timer_.HasStarted());
-}
-
-TEST_F(TimerTest, SeparatedTimers) {
- EXPECT_CALL(*clock_wrapper_mock_, GetCurrentTime())
- .WillOnce(Return(stime))
- .WillOnce(Return(etime))
- .WillOnce(Return(stime2))
- .WillOnce(Return(etime2));
- timer_.clock_wrapper_ = std::move(clock_wrapper_mock_);
- ASSERT_TRUE(timer_.Start());
- ASSERT_TRUE(timer_.Stop());
- ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(), kDelta1MSec);
- ASSERT_TRUE(timer_.Start());
- ASSERT_TRUE(timer_.start_time_ == stime2);
- ASSERT_TRUE(timer_.Stop());
- ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(), kDelta2MSec);
- ASSERT_FALSE(timer_.HasStarted());
-
- base::TimeDelta elapsed_time;
- ASSERT_TRUE(timer_.GetElapsedTime(&elapsed_time));
- ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(),
- elapsed_time.InMilliseconds());
-}
-
-TEST_F(TimerTest, InvalidStop) {
- EXPECT_CALL(*clock_wrapper_mock_, GetCurrentTime())
- .WillOnce(Return(stime))
- .WillOnce(Return(etime));
- timer_.clock_wrapper_ = std::move(clock_wrapper_mock_);
- ASSERT_FALSE(timer_.Stop());
- // Now we try it again, but after a valid start/stop.
- timer_.Start();
- timer_.Stop();
- base::TimeDelta elapsed_time = timer_.elapsed_time_;
- ASSERT_FALSE(timer_.Stop());
- ASSERT_TRUE(elapsed_time == timer_.elapsed_time_);
-}
-
-TEST_F(TimerTest, InvalidElapsedTime) {
- base::TimeDelta elapsed_time;
- ASSERT_FALSE(timer_.GetElapsedTime(&elapsed_time));
-}
-
-TEST_F(TimerTest, PauseStartStopResume) {
- EXPECT_CALL(*clock_wrapper_mock_, GetCurrentTime())
- .WillOnce(Return(stime))
- .WillOnce(Return(stime2))
- .WillOnce(Return(etime2))
- .WillOnce(Return(stime3))
- .WillOnce(Return(etime3));
- timer_.clock_wrapper_ = std::move(clock_wrapper_mock_);
- ASSERT_TRUE(timer_.Pause()); // Starts timer paused.
- ASSERT_TRUE(timer_.start_time_ == stime);
- ASSERT_TRUE(timer_.HasStarted());
-
- ASSERT_TRUE(timer_.Start()); // Restarts timer.
- ASSERT_TRUE(timer_.start_time_ == stime2);
- ASSERT_TRUE(timer_.HasStarted());
-
- ASSERT_TRUE(timer_.Stop());
- ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(), kDelta2MSec);
- ASSERT_FALSE(timer_.HasStarted());
- base::TimeDelta elapsed_time;
- ASSERT_TRUE(timer_.GetElapsedTime(&elapsed_time));
- ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(),
- elapsed_time.InMilliseconds());
-
- ASSERT_TRUE(timer_.Resume());
- ASSERT_TRUE(timer_.HasStarted());
- ASSERT_TRUE(timer_.GetElapsedTime(&elapsed_time));
- ASSERT_EQ(kDelta3MSec, elapsed_time.InMilliseconds());
-}
-
-TEST_F(TimerTest, ResumeStartStopPause) {
- EXPECT_CALL(*clock_wrapper_mock_, GetCurrentTime())
- .WillOnce(Return(stime))
- .WillOnce(Return(stime2))
- .WillOnce(Return(etime2))
- .WillOnce(Return(stime3));
- timer_.clock_wrapper_ = std::move(clock_wrapper_mock_);
- ASSERT_TRUE(timer_.Resume());
- ASSERT_TRUE(timer_.start_time_ == stime);
- ASSERT_TRUE(timer_.HasStarted());
-
- ASSERT_TRUE(timer_.Start());
- ASSERT_TRUE(timer_.start_time_ == stime2);
- ASSERT_TRUE(timer_.HasStarted());
-
- ASSERT_TRUE(timer_.Stop());
- ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(), kDelta2MSec);
- ASSERT_FALSE(timer_.HasStarted());
- base::TimeDelta elapsed_time;
- ASSERT_TRUE(timer_.GetElapsedTime(&elapsed_time));
- ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(),
- elapsed_time.InMilliseconds());
-
- ASSERT_TRUE(timer_.Pause());
- ASSERT_TRUE(timer_.HasStarted());
- ASSERT_TRUE(timer_.GetElapsedTime(&elapsed_time));
- ASSERT_EQ(0, elapsed_time.InMilliseconds());
-}
-
-TEST_F(TimerTest, StartResumeStop) {
- EXPECT_CALL(*clock_wrapper_mock_, GetCurrentTime())
- .WillOnce(Return(stime))
- .WillOnce(Return(etime));
- timer_.clock_wrapper_ = std::move(clock_wrapper_mock_);
- ASSERT_TRUE(timer_.Start());
- ASSERT_TRUE(timer_.start_time_ == stime);
- ASSERT_TRUE(timer_.HasStarted());
-
- ASSERT_FALSE(timer_.Resume());
- ASSERT_TRUE(timer_.start_time_ == stime);
- ASSERT_TRUE(timer_.HasStarted());
-
- ASSERT_TRUE(timer_.Stop());
- ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(), kDelta1MSec);
- ASSERT_FALSE(timer_.HasStarted());
- base::TimeDelta elapsed_time;
- ASSERT_TRUE(timer_.GetElapsedTime(&elapsed_time));
- ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(),
- elapsed_time.InMilliseconds());
-}
-
-TEST_F(TimerTest, StartPauseStop) {
- EXPECT_CALL(*clock_wrapper_mock_, GetCurrentTime())
- .WillOnce(Return(stime))
- .WillOnce(Return(etime));
- timer_.clock_wrapper_ = std::move(clock_wrapper_mock_);
- ASSERT_TRUE(timer_.Start());
- ASSERT_TRUE(timer_.start_time_ == stime);
- ASSERT_TRUE(timer_.HasStarted());
-
- ASSERT_TRUE(timer_.Pause());
- ASSERT_TRUE(timer_.HasStarted());
- ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(), kDelta1MSec);
- base::TimeDelta elapsed_time;
- ASSERT_TRUE(timer_.GetElapsedTime(&elapsed_time));
- ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(),
- elapsed_time.InMilliseconds());
-
- ASSERT_TRUE(timer_.Stop());
- ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(), kDelta1MSec);
- ASSERT_FALSE(timer_.HasStarted());
- ASSERT_TRUE(timer_.GetElapsedTime(&elapsed_time));
- ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(),
- elapsed_time.InMilliseconds());
-}
-
-TEST_F(TimerTest, StartPauseResumeStop) {
- EXPECT_CALL(*clock_wrapper_mock_, GetCurrentTime())
- .WillOnce(Return(stime))
- .WillOnce(Return(etime))
- .WillOnce(Return(stime2))
- .WillOnce(Return(etime2));
- timer_.clock_wrapper_ = std::move(clock_wrapper_mock_);
- ASSERT_TRUE(timer_.Start());
- ASSERT_TRUE(timer_.start_time_ == stime);
- ASSERT_TRUE(timer_.HasStarted());
-
- ASSERT_TRUE(timer_.Pause());
- ASSERT_TRUE(timer_.HasStarted());
- ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(), kDelta1MSec);
- base::TimeDelta elapsed_time;
- ASSERT_TRUE(timer_.GetElapsedTime(&elapsed_time));
- ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(),
- elapsed_time.InMilliseconds());
-
- ASSERT_TRUE(timer_.Resume());
- ASSERT_TRUE(timer_.HasStarted());
-
- ASSERT_TRUE(timer_.Stop());
- ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(), kDelta1MSec + kDelta2MSec);
- ASSERT_FALSE(timer_.HasStarted());
- ASSERT_TRUE(timer_.GetElapsedTime(&elapsed_time));
- ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(),
- elapsed_time.InMilliseconds());
-}
-
-TEST_F(TimerTest, PauseStop) {
- EXPECT_CALL(*clock_wrapper_mock_, GetCurrentTime())
- .WillOnce(Return(stime));
- timer_.clock_wrapper_ = std::move(clock_wrapper_mock_);
- ASSERT_TRUE(timer_.Pause());
- ASSERT_TRUE(timer_.start_time_ == stime);
- ASSERT_TRUE(timer_.HasStarted());
- ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(), 0);
-
- ASSERT_TRUE(timer_.Stop());
- ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(), 0);
- ASSERT_FALSE(timer_.HasStarted());
- base::TimeDelta elapsed_time;
- ASSERT_TRUE(timer_.GetElapsedTime(&elapsed_time));
- ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(),
- elapsed_time.InMilliseconds());
-}
-
-TEST_F(TimerTest, PauseResumeStop) {
- EXPECT_CALL(*clock_wrapper_mock_, GetCurrentTime())
- .WillOnce(Return(stime))
- .WillOnce(Return(stime2))
- .WillOnce(Return(etime2));
- timer_.clock_wrapper_ = std::move(clock_wrapper_mock_);
- ASSERT_TRUE(timer_.Pause());
- ASSERT_TRUE(timer_.start_time_ == stime);
- ASSERT_TRUE(timer_.HasStarted());
-
- ASSERT_TRUE(timer_.Resume());
- ASSERT_TRUE(timer_.HasStarted());
-
- ASSERT_TRUE(timer_.Stop());
- ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(), kDelta2MSec);
- ASSERT_FALSE(timer_.HasStarted());
- base::TimeDelta elapsed_time;
- ASSERT_TRUE(timer_.GetElapsedTime(&elapsed_time));
- ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(),
- elapsed_time.InMilliseconds());
-}
-
-TEST_F(TimerTest, StartPauseResumePauseStop) {
- EXPECT_CALL(*clock_wrapper_mock_, GetCurrentTime())
- .WillOnce(Return(stime))
- .WillOnce(Return(etime))
- .WillOnce(Return(stime2))
- .WillOnce(Return(stime3))
- .WillOnce(Return(etime3));
- timer_.clock_wrapper_ = std::move(clock_wrapper_mock_);
- ASSERT_TRUE(timer_.Start());
- ASSERT_TRUE(timer_.start_time_ == stime);
- ASSERT_TRUE(timer_.HasStarted());
-
- ASSERT_TRUE(timer_.Pause());
- ASSERT_TRUE(timer_.HasStarted());
- ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(), kDelta1MSec);
- base::TimeDelta elapsed_time;
- ASSERT_TRUE(timer_.GetElapsedTime(&elapsed_time));
- ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(),
- elapsed_time.InMilliseconds());
-
- ASSERT_TRUE(timer_.Resume());
- ASSERT_TRUE(timer_.HasStarted());
- // Make sure GetElapsedTime works while we're running.
- ASSERT_TRUE(timer_.GetElapsedTime(&elapsed_time));
- ASSERT_EQ(kDelta1MSec + kStime3MSec - kStime2MSec,
- elapsed_time.InMilliseconds());
-
- ASSERT_TRUE(timer_.Pause());
- ASSERT_TRUE(timer_.HasStarted());
- ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(),
- kDelta1MSec + kEtime3MSec - kStime2MSec);
- ASSERT_TRUE(timer_.GetElapsedTime(&elapsed_time));
- ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(),
- elapsed_time.InMilliseconds());
-
- ASSERT_TRUE(timer_.Stop());
- ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(),
- kDelta1MSec + kEtime3MSec - kStime2MSec);
- ASSERT_FALSE(timer_.HasStarted());
- ASSERT_TRUE(timer_.GetElapsedTime(&elapsed_time));
- ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(),
- elapsed_time.InMilliseconds());
-}
-
-TEST_F(TimerTest, StartPauseResumePauseResumeStop) {
- EXPECT_CALL(*clock_wrapper_mock_, GetCurrentTime())
- .WillOnce(Return(stime))
- .WillOnce(Return(etime))
- .WillOnce(Return(stime2))
- .WillOnce(Return(etime2))
- .WillOnce(Return(stime3))
- .WillOnce(Return(etime3));
- timer_.clock_wrapper_ = std::move(clock_wrapper_mock_);
- ASSERT_TRUE(timer_.Start());
- ASSERT_TRUE(timer_.start_time_ == stime);
- ASSERT_TRUE(timer_.HasStarted());
-
- ASSERT_TRUE(timer_.Pause());
- ASSERT_TRUE(timer_.HasStarted());
- ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(), kDelta1MSec);
- base::TimeDelta elapsed_time;
- ASSERT_TRUE(timer_.GetElapsedTime(&elapsed_time));
- ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(),
- elapsed_time.InMilliseconds());
-
- ASSERT_TRUE(timer_.Resume());
- ASSERT_TRUE(timer_.HasStarted());
-
- ASSERT_TRUE(timer_.Pause());
- ASSERT_TRUE(timer_.HasStarted());
- ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(), kDelta1MSec + kDelta2MSec);
- ASSERT_TRUE(timer_.GetElapsedTime(&elapsed_time));
- ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(),
- elapsed_time.InMilliseconds());
-
- ASSERT_TRUE(timer_.Resume());
- ASSERT_TRUE(timer_.HasStarted());
-
- ASSERT_TRUE(timer_.Stop());
- ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(),
- kDelta1MSec + kDelta2MSec + kDelta3MSec);
- ASSERT_FALSE(timer_.HasStarted());
- ASSERT_TRUE(timer_.GetElapsedTime(&elapsed_time));
- ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(),
- elapsed_time.InMilliseconds());
-}
-
-static const char kMetricName[] = "test-timer";
-static const int kMinSample = 0;
-static const int kMaxSample = 120 * 1E6;
-static const int kNumBuckets = 50;
-
-class TimerReporterTest : public testing::Test {
- public:
- TimerReporterTest() : timer_reporter_(kMetricName, kMinSample, kMaxSample,
- kNumBuckets),
- clock_wrapper_mock_(new ClockWrapperMock()) {}
-
- protected:
- virtual void SetUp() {
- timer_reporter_.set_metrics_lib(&lib_);
- EXPECT_EQ(timer_reporter_.histogram_name_, kMetricName);
- EXPECT_EQ(timer_reporter_.min_, kMinSample);
- EXPECT_EQ(timer_reporter_.max_, kMaxSample);
- EXPECT_EQ(timer_reporter_.num_buckets_, kNumBuckets);
- stime += base::TimeDelta::FromMilliseconds(kStime1MSec);
- etime += base::TimeDelta::FromMilliseconds(kEtime1MSec);
- }
-
- virtual void TearDown() {
- timer_reporter_.set_metrics_lib(nullptr);
- }
-
- TimerReporter timer_reporter_;
- MetricsLibraryMock lib_;
- std::unique_ptr<ClockWrapperMock> clock_wrapper_mock_;
- base::TimeTicks stime, etime;
-};
-
-TEST_F(TimerReporterTest, StartStopReport) {
- EXPECT_CALL(*clock_wrapper_mock_, GetCurrentTime())
- .WillOnce(Return(stime))
- .WillOnce(Return(etime));
- timer_reporter_.clock_wrapper_ = std::move(clock_wrapper_mock_);
- EXPECT_CALL(lib_, SendToUMA(kMetricName, kDelta1MSec, kMinSample, kMaxSample,
- kNumBuckets)).WillOnce(Return(true));
- ASSERT_TRUE(timer_reporter_.Start());
- ASSERT_TRUE(timer_reporter_.Stop());
- ASSERT_TRUE(timer_reporter_.ReportMilliseconds());
-}
-
-TEST_F(TimerReporterTest, InvalidReport) {
- ASSERT_FALSE(timer_reporter_.ReportMilliseconds());
-}
-
-} // namespace chromeos_metrics
-
-int main(int argc, char **argv) {
- testing::InitGoogleTest(&argc, argv);
- return RUN_ALL_TESTS();
-}
diff --git a/metricsd/uploader/bn_metricsd_impl.cc b/metricsd/uploader/bn_metricsd_impl.cc
deleted file mode 100644
index 219ed60..0000000
--- a/metricsd/uploader/bn_metricsd_impl.cc
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2015 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 "uploader/bn_metricsd_impl.h"
-
-#include <base/metrics/histogram.h>
-#include <base/metrics/sparse_histogram.h>
-#include <base/metrics/statistics_recorder.h>
-#include <utils/Errors.h>
-#include <utils/String16.h>
-#include <utils/String8.h>
-
-using android::binder::Status;
-using android::String16;
-
-static const char16_t kCrashTypeKernel[] = u"kernel";
-static const char16_t kCrashTypeUncleanShutdown[] = u"uncleanshutdown";
-static const char16_t kCrashTypeUser[] = u"user";
-
-BnMetricsdImpl::BnMetricsdImpl(const std::shared_ptr<CrashCounters>& counters)
- : counters_(counters) {
- CHECK(counters_) << "Invalid counters argument to constructor";
-}
-
-Status BnMetricsdImpl::recordHistogram(
- const String16& name, int sample, int min, int max, int nbuckets) {
- base::HistogramBase* histogram = base::Histogram::FactoryGet(
- android::String8(name).string(), min, max, nbuckets,
- base::Histogram::kUmaTargetedHistogramFlag);
- // |histogram| may be null if a client reports two contradicting histograms
- // with the same name but different limits.
- // FactoryGet will print a useful message if that is the case.
- if (histogram) {
- histogram->Add(sample);
- }
- return Status::ok();
-}
-
-Status BnMetricsdImpl::recordLinearHistogram(const String16& name,
- int sample,
- int max) {
- base::HistogramBase* histogram = base::LinearHistogram::FactoryGet(
- android::String8(name).string(), 1, max, max + 1,
- base::Histogram::kUmaTargetedHistogramFlag);
- // |histogram| may be null if a client reports two contradicting histograms
- // with the same name but different limits.
- // FactoryGet will print a useful message if that is the case.
- if (histogram) {
- histogram->Add(sample);
- }
- return Status::ok();
-}
-
-Status BnMetricsdImpl::recordSparseHistogram(const String16& name, int sample) {
- base::HistogramBase* histogram = base::SparseHistogram::FactoryGet(
- android::String8(name).string(),
- base::Histogram::kUmaTargetedHistogramFlag);
- // |histogram| may be null if a client reports two contradicting histograms
- // with the same name but different limits.
- // FactoryGet will print a useful message if that is the case.
- if (histogram) {
- histogram->Add(sample);
- }
- return Status::ok();
-}
-
-Status BnMetricsdImpl::recordCrash(const String16& type) {
- if (type == kCrashTypeUser) {
- counters_->IncrementUserCrashCount();
- } else if (type == kCrashTypeKernel) {
- counters_->IncrementKernelCrashCount();
- } else if (type == kCrashTypeUncleanShutdown) {
- counters_->IncrementUncleanShutdownCount();
- } else {
- LOG(ERROR) << "Unknown crash type received: " << type;
- }
- return Status::ok();
-}
-
-Status BnMetricsdImpl::getHistogramsDump(String16* dump) {
- std::string str_dump;
- base::StatisticsRecorder::WriteGraph(std::string(), &str_dump);
- *dump = String16(str_dump.c_str());
- return Status::ok();
-}
diff --git a/metricsd/uploader/bn_metricsd_impl.h b/metricsd/uploader/bn_metricsd_impl.h
deleted file mode 100644
index bf47e80..0000000
--- a/metricsd/uploader/bn_metricsd_impl.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-
-#ifndef METRICSD_UPLOADER_BN_METRICSD_IMPL_H_
-#define METRICSD_UPLOADER_BN_METRICSD_IMPL_H_
-
-#include "android/brillo/metrics/BnMetricsd.h"
-#include "uploader/crash_counters.h"
-
-class BnMetricsdImpl : public android::brillo::metrics::BnMetricsd {
- public:
- explicit BnMetricsdImpl(const std::shared_ptr<CrashCounters>& counters);
- virtual ~BnMetricsdImpl() = default;
-
- // Records a histogram.
- android::binder::Status recordHistogram(const android::String16& name,
- int sample,
- int min,
- int max,
- int nbuckets) override;
-
- // Records a linear histogram.
- android::binder::Status recordLinearHistogram(const android::String16& name,
- int sample,
- int max) override;
-
- // Records a sparse histogram.
- android::binder::Status recordSparseHistogram(const android::String16& name,
- int sample) override;
-
- // Records a crash.
- android::binder::Status recordCrash(const android::String16& type) override;
-
- // Returns a dump of the histograms aggregated in memory.
- android::binder::Status getHistogramsDump(android::String16* dump) override;
-
- private:
- std::shared_ptr<CrashCounters> counters_;
-};
-
-#endif // METRICSD_UPLOADER_BN_METRICSD_IMPL_H_
diff --git a/metricsd/uploader/crash_counters.cc b/metricsd/uploader/crash_counters.cc
deleted file mode 100644
index 1478b9a..0000000
--- a/metricsd/uploader/crash_counters.cc
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2015 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 "uploader/crash_counters.h"
-
-CrashCounters::CrashCounters()
- : kernel_crashes_(0), unclean_shutdowns_(0), user_crashes_(0) {}
-
-void CrashCounters::IncrementKernelCrashCount() {
- kernel_crashes_++;
-}
-
-unsigned int CrashCounters::GetAndResetKernelCrashCount() {
- return kernel_crashes_.exchange(0);
-}
-
-void CrashCounters::IncrementUncleanShutdownCount() {
- unclean_shutdowns_++;
-}
-
-unsigned int CrashCounters::GetAndResetUncleanShutdownCount() {
- return unclean_shutdowns_.exchange(0);
-}
-
-void CrashCounters::IncrementUserCrashCount() {
- user_crashes_++;
-}
-
-unsigned int CrashCounters::GetAndResetUserCrashCount() {
- return user_crashes_.exchange(0);
-}
diff --git a/metricsd/uploader/crash_counters.h b/metricsd/uploader/crash_counters.h
deleted file mode 100644
index 3fdbf3f..0000000
--- a/metricsd/uploader/crash_counters.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-
-#ifndef METRICSD_UPLOADER_CRASH_COUNTERS_H_
-#define METRICSD_UPLOADER_CRASH_COUNTERS_H_
-
-#include <atomic>
-
-// This class is used to keep track of the crash counters.
-// An instance of it will be used by both the binder thread (to increment the
-// counters) and the uploader thread (to gather and reset the counters).
-// As such, the internal counters are atomic uints to allow concurrent access.
-class CrashCounters {
- public:
- CrashCounters();
-
- void IncrementKernelCrashCount();
- unsigned int GetAndResetKernelCrashCount();
-
- void IncrementUserCrashCount();
- unsigned int GetAndResetUserCrashCount();
-
- void IncrementUncleanShutdownCount();
- unsigned int GetAndResetUncleanShutdownCount();
-
- private:
- std::atomic_uint kernel_crashes_;
- std::atomic_uint unclean_shutdowns_;
- std::atomic_uint user_crashes_;
-};
-
-#endif // METRICSD_UPLOADER_CRASH_COUNTERS_H_
diff --git a/metricsd/uploader/metrics_hashes.cc b/metricsd/uploader/metrics_hashes.cc
deleted file mode 100644
index 208c560..0000000
--- a/metricsd/uploader/metrics_hashes.cc
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2015 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 "uploader/metrics_hashes.h"
-
-#include "base/logging.h"
-#include "base/md5.h"
-#include "base/sys_byteorder.h"
-
-namespace metrics {
-
-namespace {
-
-// Converts the 8-byte prefix of an MD5 hash into a uint64 value.
-inline uint64_t HashToUInt64(const std::string& hash) {
- uint64_t value;
- DCHECK_GE(hash.size(), sizeof(value));
- memcpy(&value, hash.data(), sizeof(value));
- return base::HostToNet64(value);
-}
-
-} // namespace
-
-uint64_t HashMetricName(const std::string& name) {
- // Create an MD5 hash of the given |name|, represented as a byte buffer
- // encoded as an std::string.
- base::MD5Context context;
- base::MD5Init(&context);
- base::MD5Update(&context, name);
-
- base::MD5Digest digest;
- base::MD5Final(&digest, &context);
-
- std::string hash_str(reinterpret_cast<char*>(digest.a), arraysize(digest.a));
- return HashToUInt64(hash_str);
-}
-
-} // namespace metrics
diff --git a/metricsd/uploader/metrics_hashes.h b/metricsd/uploader/metrics_hashes.h
deleted file mode 100644
index 1082b42..0000000
--- a/metricsd/uploader/metrics_hashes.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-
-#ifndef METRICS_UPLOADER_METRICS_HASHES_H_
-#define METRICS_UPLOADER_METRICS_HASHES_H_
-
-#include <string>
-
-namespace metrics {
-
-// Computes a uint64 hash of a given string based on its MD5 hash. Suitable for
-// metric names.
-uint64_t HashMetricName(const std::string& name);
-
-} // namespace metrics
-
-#endif // METRICS_UPLOADER_METRICS_HASHES_H_
diff --git a/metricsd/uploader/metrics_hashes_unittest.cc b/metricsd/uploader/metrics_hashes_unittest.cc
deleted file mode 100644
index b8c2575..0000000
--- a/metricsd/uploader/metrics_hashes_unittest.cc
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2015 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 "uploader/metrics_hashes.h"
-
-#include <base/format_macros.h>
-#include <base/macros.h>
-#include <base/strings/stringprintf.h>
-#include <gtest/gtest.h>
-
-namespace metrics {
-
-// Make sure our ID hashes are the same as what we see on the server side.
-TEST(MetricsUtilTest, HashMetricName) {
- static const struct {
- std::string input;
- std::string output;
- } cases[] = {
- {"Back", "0x0557fa923dcee4d0"},
- {"Forward", "0x67d2f6740a8eaebf"},
- {"NewTab", "0x290eb683f96572f1"},
- };
-
- for (size_t i = 0; i < arraysize(cases); ++i) {
- uint64_t hash = HashMetricName(cases[i].input);
- std::string hash_hex = base::StringPrintf("0x%016" PRIx64, hash);
- EXPECT_EQ(cases[i].output, hash_hex);
- }
-}
-
-} // namespace metrics
diff --git a/metricsd/uploader/metrics_log.cc b/metricsd/uploader/metrics_log.cc
deleted file mode 100644
index fcaa8c1..0000000
--- a/metricsd/uploader/metrics_log.cc
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2015 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 "uploader/metrics_log.h"
-
-#include <string>
-
-#include <base/files/file_util.h>
-
-#include "uploader/proto/system_profile.pb.h"
-#include "uploader/system_profile_setter.h"
-
-// We use default values for the MetricsLogBase constructor as the setter will
-// override them.
-MetricsLog::MetricsLog()
- : MetricsLogBase("", 0, metrics::MetricsLogBase::ONGOING_LOG, "") {
-}
-
-bool MetricsLog::LoadFromFile(const base::FilePath& saved_log) {
- std::string encoded_log;
- if (!base::ReadFileToString(saved_log, &encoded_log)) {
- LOG(ERROR) << "Failed to read the metrics log backup from "
- << saved_log.value();
- return false;
- }
-
- if (!uma_proto()->ParseFromString(encoded_log)) {
- LOG(ERROR) << "Failed to parse log from " << saved_log.value()
- << ", deleting the log";
- base::DeleteFile(saved_log, false);
- uma_proto()->Clear();
- return false;
- }
-
- VLOG(1) << uma_proto()->histogram_event_size() << " histograms loaded from "
- << saved_log.value();
-
- return true;
-}
-
-bool MetricsLog::SaveToFile(const base::FilePath& path) {
- std::string encoded_log;
- GetEncodedLog(&encoded_log);
-
- if (static_cast<int>(encoded_log.size()) !=
- base::WriteFile(path, encoded_log.data(), encoded_log.size())) {
- LOG(ERROR) << "Failed to persist the current log to " << path.value();
- return false;
- }
- return true;
-}
-
-void MetricsLog::IncrementUserCrashCount(unsigned int count) {
- metrics::SystemProfileProto::Stability* stability(
- uma_proto()->mutable_system_profile()->mutable_stability());
- int current = stability->other_user_crash_count();
- stability->set_other_user_crash_count(current + count);
-}
-
-void MetricsLog::IncrementKernelCrashCount(unsigned int count) {
- metrics::SystemProfileProto::Stability* stability(
- uma_proto()->mutable_system_profile()->mutable_stability());
- int current = stability->kernel_crash_count();
- stability->set_kernel_crash_count(current + count);
-}
-
-void MetricsLog::IncrementUncleanShutdownCount(unsigned int count) {
- metrics::SystemProfileProto::Stability* stability(
- uma_proto()->mutable_system_profile()->mutable_stability());
- int current = stability->unclean_system_shutdown_count();
- stability->set_unclean_system_shutdown_count(current + count);
-}
-
-bool MetricsLog::PopulateSystemProfile(SystemProfileSetter* profile_setter) {
- CHECK(profile_setter);
- return profile_setter->Populate(uma_proto());
-}
diff --git a/metricsd/uploader/metrics_log.h b/metricsd/uploader/metrics_log.h
deleted file mode 100644
index 9e60b97..0000000
--- a/metricsd/uploader/metrics_log.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-
-#ifndef METRICSD_UPLOADER_METRICS_LOG_H_
-#define METRICSD_UPLOADER_METRICS_LOG_H_
-
-#include <string>
-
-#include <base/files/file_path.h>
-#include <base/macros.h>
-
-#include "uploader/metrics_log_base.h"
-
-// This file defines a set of user experience metrics data recorded by
-// the MetricsService. This is the unit of data that is sent to the server.
-class SystemProfileSetter;
-
-// This class provides base functionality for logging metrics data.
-class MetricsLog : public metrics::MetricsLogBase {
- public:
- // The constructor doesn't set any metadata. The metadata is only set by a
- // SystemProfileSetter.
- MetricsLog();
-
- // Increment the crash counters in the protobuf.
- // These methods don't have to be thread safe as metrics logs are only
- // accessed by the uploader thread.
- void IncrementUserCrashCount(unsigned int count);
- void IncrementKernelCrashCount(unsigned int count);
- void IncrementUncleanShutdownCount(unsigned int count);
-
- // Populate the system profile with system information using setter.
- bool PopulateSystemProfile(SystemProfileSetter* setter);
-
- // Load the log from |path|.
- bool LoadFromFile(const base::FilePath& path);
-
- // Save this log to |path|.
- bool SaveToFile(const base::FilePath& path);
-
- private:
- friend class UploadServiceTest;
- FRIEND_TEST(UploadServiceTest, CurrentLogSavedAndResumed);
- FRIEND_TEST(UploadServiceTest, LogContainsAggregatedValues);
- FRIEND_TEST(UploadServiceTest, LogContainsCrashCounts);
- FRIEND_TEST(UploadServiceTest, LogKernelCrash);
- FRIEND_TEST(UploadServiceTest, LogUncleanShutdown);
- FRIEND_TEST(UploadServiceTest, LogUserCrash);
- FRIEND_TEST(UploadServiceTest, UnknownCrashIgnored);
-
- DISALLOW_COPY_AND_ASSIGN(MetricsLog);
-};
-
-#endif // METRICSD_UPLOADER_METRICS_LOG_H_
diff --git a/metricsd/uploader/metrics_log_base.cc b/metricsd/uploader/metrics_log_base.cc
deleted file mode 100644
index f23bd63..0000000
--- a/metricsd/uploader/metrics_log_base.cc
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * Copyright (C) 2015 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 "uploader/metrics_log_base.h"
-
-#include <memory>
-
-#include "base/build_time.h"
-#include "base/metrics/histogram_base.h"
-#include "base/metrics/histogram_samples.h"
-#include "uploader/metrics_hashes.h"
-#include "uploader/proto/histogram_event.pb.h"
-#include "uploader/proto/system_profile.pb.h"
-#include "uploader/proto/user_action_event.pb.h"
-
-using base::Histogram;
-using base::HistogramBase;
-using base::HistogramSamples;
-using base::SampleCountIterator;
-using base::Time;
-using base::TimeDelta;
-using metrics::HistogramEventProto;
-using metrics::SystemProfileProto;
-using metrics::UserActionEventProto;
-
-namespace metrics {
-namespace {
-
-// Any id less than 16 bytes is considered to be a testing id.
-bool IsTestingID(const std::string& id) {
- return id.size() < 16;
-}
-
-} // namespace
-
-MetricsLogBase::MetricsLogBase(const std::string& client_id,
- int session_id,
- LogType log_type,
- const std::string& version_string)
- : num_events_(0),
- locked_(false),
- log_type_(log_type) {
- DCHECK_NE(NO_LOG, log_type);
- if (IsTestingID(client_id))
- uma_proto_.set_client_id(0);
- else
- uma_proto_.set_client_id(Hash(client_id));
-
- uma_proto_.set_session_id(session_id);
- uma_proto_.mutable_system_profile()->set_build_timestamp(GetBuildTime());
- uma_proto_.mutable_system_profile()->set_app_version(version_string);
-}
-
-MetricsLogBase::~MetricsLogBase() {}
-
-// static
-uint64_t MetricsLogBase::Hash(const std::string& value) {
- uint64_t hash = metrics::HashMetricName(value);
-
- // The following log is VERY helpful when folks add some named histogram into
- // the code, but forgot to update the descriptive list of histograms. When
- // that happens, all we get to see (server side) is a hash of the histogram
- // name. We can then use this logging to find out what histogram name was
- // being hashed to a given MD5 value by just running the version of Chromium
- // in question with --enable-logging.
- VLOG(1) << "Metrics: Hash numeric [" << value << "]=[" << hash << "]";
-
- return hash;
-}
-
-// static
-int64_t MetricsLogBase::GetBuildTime() {
- static int64_t integral_build_time = 0;
- if (!integral_build_time) {
- Time time = base::GetBuildTime();
- integral_build_time = static_cast<int64_t>(time.ToTimeT());
- }
- return integral_build_time;
-}
-
-// static
-int64_t MetricsLogBase::GetCurrentTime() {
- return (base::TimeTicks::Now() - base::TimeTicks()).InSeconds();
-}
-
-void MetricsLogBase::CloseLog() {
- DCHECK(!locked_);
- locked_ = true;
-}
-
-void MetricsLogBase::GetEncodedLog(std::string* encoded_log) {
- DCHECK(locked_);
- uma_proto_.SerializeToString(encoded_log);
-}
-
-void MetricsLogBase::RecordUserAction(const std::string& key) {
- DCHECK(!locked_);
-
- UserActionEventProto* user_action = uma_proto_.add_user_action_event();
- user_action->set_name_hash(Hash(key));
- user_action->set_time(GetCurrentTime());
-
- ++num_events_;
-}
-
-void MetricsLogBase::RecordHistogramDelta(const std::string& histogram_name,
- const HistogramSamples& snapshot) {
- DCHECK(!locked_);
- DCHECK_NE(0, snapshot.TotalCount());
-
- // We will ignore the MAX_INT/infinite value in the last element of range[].
-
- HistogramEventProto* histogram_proto = uma_proto_.add_histogram_event();
- histogram_proto->set_name_hash(Hash(histogram_name));
- histogram_proto->set_sum(snapshot.sum());
-
- for (std::unique_ptr<SampleCountIterator> it = snapshot.Iterator(); !it->Done();
- it->Next()) {
- HistogramBase::Sample min;
- HistogramBase::Sample max;
- HistogramBase::Count count;
- it->Get(&min, &max, &count);
- HistogramEventProto::Bucket* bucket = histogram_proto->add_bucket();
- bucket->set_min(min);
- bucket->set_max(max);
- bucket->set_count(count);
- }
-
- // Omit fields to save space (see rules in histogram_event.proto comments).
- for (int i = 0; i < histogram_proto->bucket_size(); ++i) {
- HistogramEventProto::Bucket* bucket = histogram_proto->mutable_bucket(i);
- if (i + 1 < histogram_proto->bucket_size() &&
- bucket->max() == histogram_proto->bucket(i + 1).min()) {
- bucket->clear_max();
- } else if (bucket->max() == bucket->min() + 1) {
- bucket->clear_min();
- }
- }
-}
-
-} // namespace metrics
diff --git a/metricsd/uploader/metrics_log_base.h b/metricsd/uploader/metrics_log_base.h
deleted file mode 100644
index f4e1995..0000000
--- a/metricsd/uploader/metrics_log_base.h
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-
-// This file defines a set of user experience metrics data recorded by
-// the MetricsService. This is the unit of data that is sent to the server.
-
-#ifndef METRICS_UPLOADER_METRICS_LOG_BASE_H_
-#define METRICS_UPLOADER_METRICS_LOG_BASE_H_
-
-#include <string>
-
-#include "base/macros.h"
-#include "base/metrics/histogram.h"
-#include "base/time/time.h"
-#include "uploader/proto/chrome_user_metrics_extension.pb.h"
-
-namespace base {
-class HistogramSamples;
-} // namespace base
-
-namespace metrics {
-
-// This class provides base functionality for logging metrics data.
-class MetricsLogBase {
- public:
- // TODO(asvitkine): Remove the NO_LOG value.
- enum LogType {
- INITIAL_STABILITY_LOG, // The initial log containing stability stats.
- ONGOING_LOG, // Subsequent logs in a session.
- NO_LOG, // Placeholder value for when there is no log.
- };
-
- // Creates a new metrics log of the specified type.
- // client_id is the identifier for this profile on this installation
- // session_id is an integer that's incremented on each application launch
- MetricsLogBase(const std::string& client_id,
- int session_id,
- LogType log_type,
- const std::string& version_string);
- virtual ~MetricsLogBase();
-
- // Computes the MD5 hash of the given string, and returns the first 8 bytes of
- // the hash.
- static uint64_t Hash(const std::string& value);
-
- // Get the GMT buildtime for the current binary, expressed in seconds since
- // January 1, 1970 GMT.
- // The value is used to identify when a new build is run, so that previous
- // reliability stats, from other builds, can be abandoned.
- static int64_t GetBuildTime();
-
- // Convenience function to return the current time at a resolution in seconds.
- // This wraps base::TimeTicks, and hence provides an abstract time that is
- // always incrementing for use in measuring time durations.
- static int64_t GetCurrentTime();
-
- // Records a user-initiated action.
- void RecordUserAction(const std::string& key);
-
- // Record any changes in a given histogram for transmission.
- void RecordHistogramDelta(const std::string& histogram_name,
- const base::HistogramSamples& snapshot);
-
- // Stop writing to this record and generate the encoded representation.
- // None of the Record* methods can be called after this is called.
- void CloseLog();
-
- // Fills |encoded_log| with the serialized protobuf representation of the
- // record. Must only be called after CloseLog() has been called.
- void GetEncodedLog(std::string* encoded_log);
-
- int num_events() { return num_events_; }
-
- void set_hardware_class(const std::string& hardware_class) {
- uma_proto_.mutable_system_profile()->mutable_hardware()->set_hardware_class(
- hardware_class);
- }
-
- LogType log_type() const { return log_type_; }
-
- protected:
- bool locked() const { return locked_; }
-
- metrics::ChromeUserMetricsExtension* uma_proto() { return &uma_proto_; }
- const metrics::ChromeUserMetricsExtension* uma_proto() const {
- return &uma_proto_;
- }
-
- // TODO(isherman): Remove this once the XML pipeline is outta here.
- int num_events_; // the number of events recorded in this log
-
- private:
- // locked_ is true when record has been packed up for sending, and should
- // no longer be written to. It is only used for sanity checking and is
- // not a real lock.
- bool locked_;
-
- // The type of the log, i.e. initial or ongoing.
- const LogType log_type_;
-
- // Stores the protocol buffer representation for this log.
- metrics::ChromeUserMetricsExtension uma_proto_;
-
- DISALLOW_COPY_AND_ASSIGN(MetricsLogBase);
-};
-
-} // namespace metrics
-
-#endif // METRICS_UPLOADER_METRICS_LOG_BASE_H_
diff --git a/metricsd/uploader/metrics_log_base_unittest.cc b/metricsd/uploader/metrics_log_base_unittest.cc
deleted file mode 100644
index 980afd5..0000000
--- a/metricsd/uploader/metrics_log_base_unittest.cc
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * Copyright (C) 2015 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 "uploader/metrics_log_base.h"
-
-#include <string>
-
-#include <base/metrics/bucket_ranges.h>
-#include <base/metrics/sample_vector.h>
-#include <gtest/gtest.h>
-
-#include "uploader/proto/chrome_user_metrics_extension.pb.h"
-
-namespace metrics {
-
-namespace {
-
-class TestMetricsLogBase : public MetricsLogBase {
- public:
- TestMetricsLogBase()
- : MetricsLogBase("client_id", 1, MetricsLogBase::ONGOING_LOG, "1.2.3.4") {
- }
- virtual ~TestMetricsLogBase() {}
-
- using MetricsLogBase::uma_proto;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(TestMetricsLogBase);
-};
-
-} // namespace
-
-TEST(MetricsLogBaseTest, LogType) {
- MetricsLogBase log1("id", 0, MetricsLogBase::ONGOING_LOG, "1.2.3");
- EXPECT_EQ(MetricsLogBase::ONGOING_LOG, log1.log_type());
-
- MetricsLogBase log2("id", 0, MetricsLogBase::INITIAL_STABILITY_LOG, "1.2.3");
- EXPECT_EQ(MetricsLogBase::INITIAL_STABILITY_LOG, log2.log_type());
-}
-
-TEST(MetricsLogBaseTest, EmptyRecord) {
- MetricsLogBase log("totally bogus client ID", 137,
- MetricsLogBase::ONGOING_LOG, "bogus version");
- log.set_hardware_class("sample-class");
- log.CloseLog();
-
- std::string encoded;
- log.GetEncodedLog(&encoded);
-
- // A couple of fields are hard to mock, so these will be copied over directly
- // for the expected output.
- metrics::ChromeUserMetricsExtension parsed;
- ASSERT_TRUE(parsed.ParseFromString(encoded));
-
- metrics::ChromeUserMetricsExtension expected;
- expected.set_client_id(5217101509553811875); // Hashed bogus client ID
- expected.set_session_id(137);
- expected.mutable_system_profile()->set_build_timestamp(
- parsed.system_profile().build_timestamp());
- expected.mutable_system_profile()->set_app_version("bogus version");
- expected.mutable_system_profile()->mutable_hardware()->set_hardware_class(
- "sample-class");
-
- EXPECT_EQ(expected.SerializeAsString(), encoded);
-}
-
-TEST(MetricsLogBaseTest, HistogramBucketFields) {
- // Create buckets: 1-5, 5-7, 7-8, 8-9, 9-10, 10-11, 11-12.
- base::BucketRanges ranges(8);
- ranges.set_range(0, 1);
- ranges.set_range(1, 5);
- ranges.set_range(2, 7);
- ranges.set_range(3, 8);
- ranges.set_range(4, 9);
- ranges.set_range(5, 10);
- ranges.set_range(6, 11);
- ranges.set_range(7, 12);
-
- base::SampleVector samples(&ranges);
- samples.Accumulate(3, 1); // Bucket 1-5.
- samples.Accumulate(6, 1); // Bucket 5-7.
- samples.Accumulate(8, 1); // Bucket 8-9. (7-8 skipped)
- samples.Accumulate(10, 1); // Bucket 10-11. (9-10 skipped)
- samples.Accumulate(11, 1); // Bucket 11-12.
-
- TestMetricsLogBase log;
- log.RecordHistogramDelta("Test", samples);
-
- const metrics::ChromeUserMetricsExtension* uma_proto = log.uma_proto();
- const metrics::HistogramEventProto& histogram_proto =
- uma_proto->histogram_event(uma_proto->histogram_event_size() - 1);
-
- // Buckets with samples: 1-5, 5-7, 8-9, 10-11, 11-12.
- // Should become: 1-/, 5-7, /-9, 10-/, /-12.
- ASSERT_EQ(5, histogram_proto.bucket_size());
-
- // 1-5 becomes 1-/ (max is same as next min).
- EXPECT_TRUE(histogram_proto.bucket(0).has_min());
- EXPECT_FALSE(histogram_proto.bucket(0).has_max());
- EXPECT_EQ(1, histogram_proto.bucket(0).min());
-
- // 5-7 stays 5-7 (no optimization possible).
- EXPECT_TRUE(histogram_proto.bucket(1).has_min());
- EXPECT_TRUE(histogram_proto.bucket(1).has_max());
- EXPECT_EQ(5, histogram_proto.bucket(1).min());
- EXPECT_EQ(7, histogram_proto.bucket(1).max());
-
- // 8-9 becomes /-9 (min is same as max - 1).
- EXPECT_FALSE(histogram_proto.bucket(2).has_min());
- EXPECT_TRUE(histogram_proto.bucket(2).has_max());
- EXPECT_EQ(9, histogram_proto.bucket(2).max());
-
- // 10-11 becomes 10-/ (both optimizations apply, omit max is prioritized).
- EXPECT_TRUE(histogram_proto.bucket(3).has_min());
- EXPECT_FALSE(histogram_proto.bucket(3).has_max());
- EXPECT_EQ(10, histogram_proto.bucket(3).min());
-
- // 11-12 becomes /-12 (last record must keep max, min is same as max - 1).
- EXPECT_FALSE(histogram_proto.bucket(4).has_min());
- EXPECT_TRUE(histogram_proto.bucket(4).has_max());
- EXPECT_EQ(12, histogram_proto.bucket(4).max());
-}
-
-} // namespace metrics
diff --git a/metricsd/uploader/metricsd_service_runner.cc b/metricsd/uploader/metricsd_service_runner.cc
deleted file mode 100644
index 4361cac..0000000
--- a/metricsd/uploader/metricsd_service_runner.cc
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2015 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 "uploader/metricsd_service_runner.h"
-
-#include <thread>
-
-#include <binder/IServiceManager.h>
-#include <brillo/binder_watcher.h>
-#include <brillo/message_loops/base_message_loop.h>
-#include <utils/Errors.h>
-
-#include "uploader/bn_metricsd_impl.h"
-
-MetricsdServiceRunner::MetricsdServiceRunner(
- std::shared_ptr<CrashCounters> counters)
- : counters_(counters) {}
-
-void MetricsdServiceRunner::Start() {
- thread_.reset(new std::thread(&MetricsdServiceRunner::Run, this));
-}
-
-void MetricsdServiceRunner::Run() {
- android::sp<BnMetricsdImpl> metrics_service(new BnMetricsdImpl(counters_));
-
- android::status_t status = android::defaultServiceManager()->addService(
- metrics_service->getInterfaceDescriptor(), metrics_service);
- CHECK(status == android::OK) << "Metricsd service registration failed";
-
- message_loop_for_io_.reset(new base::MessageLoopForIO);
- message_loop_.reset(new brillo::BaseMessageLoop(message_loop_for_io_.get()));
-
- brillo::BinderWatcher watcher(message_loop_.get());
- CHECK(watcher.Init()) << "failed to initialize the binder file descriptor "
- << "watcher";
-
- message_loop_->Run();
-
- // Delete the message loop here as it needs to be deconstructed in the thread
- // it is attached to.
- message_loop_.reset();
- message_loop_for_io_.reset();
-}
-
-void MetricsdServiceRunner::Stop() {
- message_loop_for_io_->PostTask(FROM_HERE,
- message_loop_for_io_->QuitWhenIdleClosure());
-
- thread_->join();
-}
diff --git a/metricsd/uploader/metricsd_service_runner.h b/metricsd/uploader/metricsd_service_runner.h
deleted file mode 100644
index b36d4a5..0000000
--- a/metricsd/uploader/metricsd_service_runner.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-
-#ifndef METRICS_UPLOADER_METRISCD_SERVICE_RUNNER_H_
-#define METRICS_UPLOADER_METRISCD_SERVICE_RUNNER_H_
-
-#include <memory>
-#include <thread>
-
-#include <base/message_loop/message_loop.h>
-#include <brillo/message_loops/message_loop.h>
-
-#include "uploader/crash_counters.h"
-
-class MetricsdServiceRunner {
- public:
- explicit MetricsdServiceRunner(std::shared_ptr<CrashCounters> counters);
-
- // Start the Metricsd Binder service in a new thread.
- void Start();
-
- // Stop the Metricsd service and wait for its thread to exit.
- void Stop();
-
- private:
- // Creates and run the main loop for metricsd's Binder service.
- void Run();
-
- std::unique_ptr<base::MessageLoopForIO> message_loop_for_io_;
- std::unique_ptr<brillo::MessageLoop> message_loop_;
-
- std::unique_ptr<std::thread> thread_;
- std::shared_ptr<CrashCounters> counters_;
-};
-
-#endif // METRICS_UPLOADER_METRISCD_SERVICE_RUNNER_H_
diff --git a/metricsd/uploader/mock/mock_system_profile_setter.h b/metricsd/uploader/mock/mock_system_profile_setter.h
deleted file mode 100644
index 9b20291..0000000
--- a/metricsd/uploader/mock/mock_system_profile_setter.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-
-#ifndef METRICS_UPLOADER_MOCK_MOCK_SYSTEM_PROFILE_SETTER_H_
-#define METRICS_UPLOADER_MOCK_MOCK_SYSTEM_PROFILE_SETTER_H_
-
-#include "uploader/system_profile_setter.h"
-
-namespace metrics {
-class ChromeUserMetricsExtension;
-}
-
-// Mock profile setter used for testing.
-class MockSystemProfileSetter : public SystemProfileSetter {
- public:
- bool Populate(metrics::ChromeUserMetricsExtension* profile_proto) override {
- return true;
- }
-};
-
-#endif // METRICS_UPLOADER_MOCK_MOCK_SYSTEM_PROFILE_SETTER_H_
diff --git a/metricsd/uploader/mock/sender_mock.cc b/metricsd/uploader/mock/sender_mock.cc
deleted file mode 100644
index bb4dc7d..0000000
--- a/metricsd/uploader/mock/sender_mock.cc
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2015 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 "uploader/mock/sender_mock.h"
-
-SenderMock::SenderMock() {
- Reset();
-}
-
-bool SenderMock::Send(const std::string& content, const std::string& hash) {
- send_call_count_ += 1;
- last_message_ = content;
- is_good_proto_ = last_message_proto_.ParseFromString(content);
- return should_succeed_;
-}
-
-void SenderMock::Reset() {
- send_call_count_ = 0;
- last_message_ = "";
- should_succeed_ = true;
- last_message_proto_.Clear();
- is_good_proto_ = false;
-}
diff --git a/metricsd/uploader/mock/sender_mock.h b/metricsd/uploader/mock/sender_mock.h
deleted file mode 100644
index e79233f..0000000
--- a/metricsd/uploader/mock/sender_mock.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-
-#ifndef METRICS_UPLOADER_MOCK_SENDER_MOCK_H_
-#define METRICS_UPLOADER_MOCK_SENDER_MOCK_H_
-
-#include <string>
-
-#include "base/compiler_specific.h"
-#include "uploader/proto/chrome_user_metrics_extension.pb.h"
-#include "uploader/sender.h"
-
-class SenderMock : public Sender {
- public:
- SenderMock();
-
- bool Send(const std::string& content, const std::string& hash) override;
- void Reset();
-
- bool is_good_proto() { return is_good_proto_; }
- int send_call_count() { return send_call_count_; }
- const std::string last_message() { return last_message_; }
- metrics::ChromeUserMetricsExtension last_message_proto() {
- return last_message_proto_;
- }
- void set_should_succeed(bool succeed) { should_succeed_ = succeed; }
-
- private:
- // Is set to true if the proto was parsed successfully.
- bool is_good_proto_;
-
- // If set to true, the Send method will return true to simulate a successful
- // send.
- bool should_succeed_;
-
- // Count of how many times Send was called since the last reset.
- int send_call_count_;
-
- // Last message received by Send.
- std::string last_message_;
-
- // If is_good_proto is true, last_message_proto is the deserialized
- // representation of last_message.
- metrics::ChromeUserMetricsExtension last_message_proto_;
-};
-
-#endif // METRICS_UPLOADER_MOCK_SENDER_MOCK_H_
diff --git a/metricsd/uploader/proto/README b/metricsd/uploader/proto/README
deleted file mode 100644
index 4292a40..0000000
--- a/metricsd/uploader/proto/README
+++ /dev/null
@@ -1,37 +0,0 @@
-Copyright (C) 2015 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.
-
-
-
-
-This directory contains the protocol buffers used by the standalone metrics
-uploader. Those protobuffers are copied from the chromium protobuffers from
-https://chromium.googlesource.com/chromium/src/+/master/components/metrics/proto/
-at 3bfe5f2b4c03d2cac718d137ed14cd2c6354bfed.
-
-Any change to this protobuf must first be made to the backend's protobuf and be
-compatible with the chromium protobuffers.
-
-
-Q: Why fork the chromium protobuffers ?
-A: The standalone metrics uploader needs chromium os fields that are not defined
-by the chromium protobufs. Instead of pushing chromium os specific changes to
-chromium, we can add them only to chromium os (and to the backend of course).
-
-
-Q: What's the difference between those protobuffers and chromium's protobuffers?
-A: When the protobuffers were copied, some chromium specific protobuffers were
-not imported:
-* omnibox related protobuffers.
-* performance profiling protobuffers (not used in chromium os).
diff --git a/metricsd/uploader/proto/chrome_user_metrics_extension.proto b/metricsd/uploader/proto/chrome_user_metrics_extension.proto
deleted file mode 100644
index a07830f..0000000
--- a/metricsd/uploader/proto/chrome_user_metrics_extension.proto
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-//
-// Protocol buffer for Chrome UMA (User Metrics Analysis).
-//
-// Note: this protobuf must be compatible with the one in chromium.
-
-syntax = "proto2";
-
-option optimize_for = LITE_RUNTIME;
-option java_outer_classname = "ChromeUserMetricsExtensionProtos";
-option java_package = "org.chromium.components.metrics";
-
-package metrics;
-
-import "system/core/metricsd/uploader/proto/histogram_event.proto";
-import "system/core/metricsd/uploader/proto/system_profile.proto";
-import "system/core/metricsd/uploader/proto/user_action_event.proto";
-
-// Next tag: 13
-message ChromeUserMetricsExtension {
- // The product (i.e. end user application) for a given UMA log.
- enum Product {
- // Google Chrome product family.
- CHROME = 0;
- }
- // The product corresponding to this log. The field type is int32 instead of
- // Product so that downstream users of the Chromium metrics component can
- // introduce products without needing to make changes to the Chromium code
- // (though they still need to add the new product to the server-side enum).
- // Note: The default value is Chrome, so Chrome products will not transmit
- // this field.
- optional int32 product = 10 [default = 0];
-
- // The id of the client install that generated these events.
- //
- // For Chrome clients, this id is unique to a top-level (one level above the
- // "Default" directory) Chrome user data directory [1], and so is shared among
- // all Chrome user profiles contained in this user data directory.
- // An id of 0 is reserved for test data (monitoring and internal testing) and
- // should normally be ignored in analysis of the data.
- // [1] http://www.chromium.org/user-experience/user-data-directory
- optional fixed64 client_id = 1;
-
- // The session id for this user.
- // Values such as tab ids are only meaningful within a particular session.
- // The client keeps track of the session id and sends it with each event.
- // The session id is simply an integer that is incremented each time the user
- // relaunches Chrome.
- optional int32 session_id = 2;
-
- // Information about the user's browser and system configuration.
- optional SystemProfileProto system_profile = 3;
-
- // This message will log one or more of the following event types:
- repeated UserActionEventProto user_action_event = 4;
- repeated HistogramEventProto histogram_event = 6;
-
-}
diff --git a/metricsd/uploader/proto/histogram_event.proto b/metricsd/uploader/proto/histogram_event.proto
deleted file mode 100644
index 3825063..0000000
--- a/metricsd/uploader/proto/histogram_event.proto
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-//
-// Histogram-collected metrics.
-
-syntax = "proto2";
-
-option optimize_for = LITE_RUNTIME;
-option java_outer_classname = "HistogramEventProtos";
-option java_package = "org.chromium.components.metrics";
-
-package metrics;
-
-// Next tag: 4
-message HistogramEventProto {
- // The name of the histogram, hashed.
- optional fixed64 name_hash = 1;
-
- // The sum of all the sample values.
- // Together with the total count of the sample values, this allows us to
- // compute the average value. The count of all sample values is just the sum
- // of the counts of all the buckets.
- optional int64 sum = 2;
-
- // The per-bucket data.
- message Bucket {
- // Each bucket's range is bounded by min <= x < max.
- // It is valid to omit one of these two fields in a bucket, but not both.
- // If the min field is omitted, its value is assumed to be equal to max - 1.
- // If the max field is omitted, its value is assumed to be equal to the next
- // bucket's min value (possibly computed per above). The last bucket in a
- // histogram should always include the max field.
- optional int64 min = 1;
- optional int64 max = 2;
-
- // The bucket's index in the list of buckets, sorted in ascending order.
- // This field was intended to provide extra redundancy to detect corrupted
- // records, but was never used. As of M31, it is no longer sent by Chrome
- // clients to reduce the UMA upload size.
- optional int32 bucket_index = 3 [deprecated = true];
-
- // The number of entries in this bucket.
- optional int64 count = 4;
- }
- repeated Bucket bucket = 3;
-}
diff --git a/metricsd/uploader/proto/system_profile.proto b/metricsd/uploader/proto/system_profile.proto
deleted file mode 100644
index bac828b..0000000
--- a/metricsd/uploader/proto/system_profile.proto
+++ /dev/null
@@ -1,759 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-//
-// Stores information about the user's brower and system configuration.
-// The system configuration fields are recorded once per client session.
-
-syntax = "proto2";
-
-option optimize_for = LITE_RUNTIME;
-option java_outer_classname = "SystemProfileProtos";
-option java_package = "org.chromium.components.metrics";
-
-package metrics;
-
-// Next tag: 21
-message SystemProfileProto {
- // The time when the client was compiled/linked, in seconds since the epoch.
- optional int64 build_timestamp = 1;
-
- // A version number string for the application.
- // Most commonly this is the browser version number found in a user agent
- // string, and is typically a 4-tuple of numbers separated by periods. In
- // cases where the user agent version might be ambiguous (example: Linux 64-
- // bit build, rather than 32-bit build, or a Windows version used in some
- // special context, such as ChromeFrame running in IE), then this may include
- // some additional postfix to provide clarification not available in the UA
- // string.
- //
- // An example of a browser version 4-tuple is "5.0.322.0". Currently used
- // postfixes are:
- //
- // "-64": a 64-bit build
- // "-F": Chrome is running under control of ChromeFrame
- // "-devel": this is not an official build of Chrome
- //
- // A full version number string could look similar to:
- // "5.0.322.0-F-devel".
- //
- // This value, when available, is more trustworthy than the UA string
- // associated with the request; and including the postfix, may be more
- // specific.
- optional string app_version = 2;
-
- // The brand code or distribution tag assigned to a partner, if available.
- // Brand codes are only available on Windows. Not every Windows install
- // though will have a brand code.
- optional string brand_code = 12;
-
- // The possible channels for an installation, from least to most stable.
- enum Channel {
- CHANNEL_UNKNOWN = 0; // Unknown channel -- perhaps an unofficial build?
- CHANNEL_CANARY = 1;
- CHANNEL_DEV = 2;
- CHANNEL_BETA = 3;
- CHANNEL_STABLE = 4;
- }
- optional Channel channel = 10;
-
- // True if Chrome build is ASan-instrumented.
- optional bool is_asan_build = 20 [default = false];
-
- // The date the user enabled UMA, in seconds since the epoch.
- // If the user has toggled the UMA enabled state multiple times, this will
- // be the most recent date on which UMA was enabled.
- // For privacy, this is rounded to the nearest hour.
- optional int64 uma_enabled_date = 3;
-
- // The time when the client was installed, in seconds since the epoch.
- // For privacy, this is rounded to the nearest hour.
- optional int64 install_date = 16;
-
- // The user's selected application locale, i.e. the user interface language.
- // The locale includes a language code and, possibly, also a country code,
- // e.g. "en-US".
- optional string application_locale = 4;
-
- message BrilloDeviceData {
- optional string product_id = 1;
- }
- optional BrilloDeviceData brillo = 21;
-
- // Information on the user's operating system.
- message OS {
- // The user's operating system. This should be one of:
- // - Android
- // - Windows NT
- // - Linux (includes ChromeOS)
- // - iPhone OS
- // - Mac OS X
- optional string name = 1;
-
- // The version of the OS. The meaning of this field is OS-dependent.
- optional string version = 2;
-
- // The fingerprint of the build. This field is used only on Android.
- optional string fingerprint = 3;
-
- // Whether the version of iOS appears to be "jailbroken". This field is
- // used only on iOS. Chrome for iOS detects whether device contains a
- // DynamicLibraries/ directory. It's a necessary but insufficient indicator
- // of whether the operating system has been jailbroken.
- optional bool is_jailbroken = 4;
- }
- optional OS os = 5;
-
- // Next tag for Hardware: 18
- // Information on the user's hardware.
- message Hardware {
- // The CPU architecture (x86, PowerPC, x86_64, ...)
- optional string cpu_architecture = 1;
-
- // The amount of RAM present on the system, in megabytes.
- optional int64 system_ram_mb = 2;
-
- // The base memory address that chrome.dll was loaded at.
- // (Logged only on Windows.)
- optional int64 dll_base = 3;
-
- // The Chrome OS device hardware class ID is a unique string associated with
- // each Chrome OS device product revision generally assigned at hardware
- // qualification time. The hardware class effectively identifies the
- // configured system components such as CPU, WiFi adapter, etc.
- //
- // An example of such a hardware class is "IEC MARIO PONY 6101". An
- // internal database associates this hardware class with the qualified
- // device specifications including OEM information, schematics, hardware
- // qualification reports, test device tags, etc.
- optional string hardware_class = 4;
-
- // The number of physical screens.
- optional int32 screen_count = 5;
-
- // The screen dimensions of the primary screen, in pixels.
- optional int32 primary_screen_width = 6;
- optional int32 primary_screen_height = 7;
-
- // The device scale factor of the primary screen.
- optional float primary_screen_scale_factor = 12;
-
- // Max DPI for any attached screen. (Windows only)
- optional float max_dpi_x = 9;
- optional float max_dpi_y = 10;
-
- // Information on the CPU obtained by CPUID.
- message CPU {
- // A 12 character string naming the vendor, e.g. "GeniuneIntel".
- optional string vendor_name = 1;
-
- // The signature reported by CPUID (from EAX).
- optional uint32 signature = 2;
-
- // Number of logical processors/cores on the current machine.
- optional uint32 num_cores = 3;
- }
- optional CPU cpu = 13;
-
- // Information on the GPU
- message Graphics {
- // The GPU manufacturer's vendor id.
- optional uint32 vendor_id = 1;
-
- // The GPU manufacturer's device id for the chip set.
- optional uint32 device_id = 2;
-
- // The driver version on the GPU.
- optional string driver_version = 3;
-
- // The driver date on the GPU.
- optional string driver_date = 4;
-
- // The GL_VENDOR string. An example of a gl_vendor string is
- // "Imagination Technologies". "" if we are not using OpenGL.
- optional string gl_vendor = 6;
-
- // The GL_RENDERER string. An example of a gl_renderer string is
- // "PowerVR SGX 540". "" if we are not using OpenGL.
- optional string gl_renderer = 7;
- }
- optional Graphics gpu = 8;
-
- // Information about Bluetooth devices paired with the system.
- message Bluetooth {
- // Whether Bluetooth is present on this system.
- optional bool is_present = 1;
-
- // Whether Bluetooth is enabled on this system.
- optional bool is_enabled = 2;
-
- // Describes a paired device.
- message PairedDevice {
- // Assigned class of the device. This is a bitfield according to the
- // Bluetooth specification available at the following URL:
- // https://www.bluetooth.org/en-us/specification/assigned-numbers-overview/baseband
- optional uint32 bluetooth_class = 1;
-
- // Decoded device type.
- enum Type {
- DEVICE_UNKNOWN = 0;
- DEVICE_COMPUTER = 1;
- DEVICE_PHONE = 2;
- DEVICE_MODEM = 3;
- DEVICE_AUDIO = 4;
- DEVICE_CAR_AUDIO = 5;
- DEVICE_VIDEO = 6;
- DEVICE_PERIPHERAL = 7;
- DEVICE_JOYSTICK = 8;
- DEVICE_GAMEPAD = 9;
- DEVICE_KEYBOARD = 10;
- DEVICE_MOUSE = 11;
- DEVICE_TABLET = 12;
- DEVICE_KEYBOARD_MOUSE_COMBO = 13;
- }
- optional Type type = 2;
-
- // Vendor prefix of the Bluetooth address, these are OUI registered by
- // the IEEE and are encoded with the first byte in bits 16-23, the
- // second byte in bits 8-15 and the third byte in bits 0-7.
- //
- // ie. Google's OUI (00:1A:11) is encoded as 0x00001A11
- optional uint32 vendor_prefix = 4;
-
- // The Vendor ID of a device, returned in vendor_id below, can be
- // either allocated by the Bluetooth SIG or USB IF, providing two
- // completely overlapping namespaces for identifiers.
- //
- // This field should be read along with vendor_id to correctly
- // identify the vendor. For example Google is identified by either
- // vendor_id_source = VENDOR_ID_BLUETOOTH, vendor_id = 0x00E0 or
- // vendor_id_source = VENDOR_ID_USB, vendor_id = 0x18D1.
- //
- // If the device does not support the Device ID specification the
- // unknown value will be set.
- enum VendorIDSource {
- VENDOR_ID_UNKNOWN = 0;
- VENDOR_ID_BLUETOOTH = 1;
- VENDOR_ID_USB = 2;
- }
- optional VendorIDSource vendor_id_source = 8;
-
- // Vendor ID of the device, where available.
- optional uint32 vendor_id = 5;
-
- // Product ID of the device, where available.
- optional uint32 product_id = 6;
-
- // Device ID of the device, generally the release or version number in
- // BCD format, where available.
- optional uint32 device_id = 7;
- }
- repeated PairedDevice paired_device = 3;
- }
- optional Bluetooth bluetooth = 11;
-
- // Whether the internal display produces touch events. Omitted if unknown.
- // Logged on ChromeOS only.
- optional bool internal_display_supports_touch = 14;
-
- // Vendor ids and product ids of external touchscreens.
- message TouchScreen {
- // Touch screen vendor id.
- optional uint32 vendor_id = 1;
- // Touch screen product id.
- optional uint32 product_id = 2;
- }
- // Lists vendor and product ids of external touchscreens.
- // Logged on ChromeOS only.
- repeated TouchScreen external_touchscreen = 15;
-
- // Drive messages are currently logged on Windows 7+, iOS, and Android.
- message Drive {
- // Whether this drive incurs a time penalty when randomly accessed. This
- // should be true for spinning disks but false for SSDs or other
- // flash-based drives.
- optional bool has_seek_penalty = 1;
- }
- // The drive that the application executable was loaded from.
- optional Drive app_drive = 16;
- // The drive that the current user data directory was loaded from.
- optional Drive user_data_drive = 17;
- }
- optional Hardware hardware = 6;
-
- // Information about the network connection.
- message Network {
- // Set to true if connection_type changed during the lifetime of the log.
- optional bool connection_type_is_ambiguous = 1;
-
- // See net::NetworkChangeNotifier::ConnectionType.
- enum ConnectionType {
- CONNECTION_UNKNOWN = 0;
- CONNECTION_ETHERNET = 1;
- CONNECTION_WIFI = 2;
- CONNECTION_2G = 3;
- CONNECTION_3G = 4;
- CONNECTION_4G = 5;
- CONNECTION_BLUETOOTH = 6;
- }
- // The connection type according to NetworkChangeNotifier.
- optional ConnectionType connection_type = 2;
-
- // Set to true if wifi_phy_layer_protocol changed during the lifetime of the log.
- optional bool wifi_phy_layer_protocol_is_ambiguous = 3;
-
- // See net::WifiPHYLayerProtocol.
- enum WifiPHYLayerProtocol {
- WIFI_PHY_LAYER_PROTOCOL_NONE = 0;
- WIFI_PHY_LAYER_PROTOCOL_ANCIENT = 1;
- WIFI_PHY_LAYER_PROTOCOL_A = 2;
- WIFI_PHY_LAYER_PROTOCOL_B = 3;
- WIFI_PHY_LAYER_PROTOCOL_G = 4;
- WIFI_PHY_LAYER_PROTOCOL_N = 5;
- WIFI_PHY_LAYER_PROTOCOL_UNKNOWN = 6;
- }
- // The physical layer mode of the associated wifi access point, if any.
- optional WifiPHYLayerProtocol wifi_phy_layer_protocol = 4;
-
- // Describe wifi access point information.
- message WifiAccessPoint {
- // Vendor prefix of the access point's BSSID, these are OUIs
- // (Organizationally Unique Identifiers) registered by
- // the IEEE and are encoded with the first byte in bits 16-23, the
- // second byte in bits 8-15 and the third byte in bits 0-7.
- optional uint32 vendor_prefix = 1;
-
- // Access point seurity mode definitions.
- enum SecurityMode {
- SECURITY_UNKNOWN = 0;
- SECURITY_WPA = 1;
- SECURITY_WEP = 2;
- SECURITY_RSN = 3;
- SECURITY_802_1X = 4;
- SECURITY_PSK = 5;
- SECURITY_NONE = 6;
- }
- // The security mode of the access point.
- optional SecurityMode security_mode = 2;
-
- // Vendor specific information.
- message VendorInformation {
- // The model number, for example "0".
- optional string model_number = 1;
-
- // The model name (sometimes the same as the model_number),
- // for example "WZR-HP-AG300H".
- optional string model_name = 2;
-
- // The device name (sometimes the same as the model_number),
- // for example "Dummynet"
- optional string device_name = 3;
-
- // The list of vendor-specific OUIs (Organziationally Unqiue
- // Identifiers). These are provided by the vendor through WPS
- // (Wireless Provisioning Service) information elements, which
- // identifies the content of the element.
- repeated uint32 element_identifier = 4;
- }
- // The wireless access point vendor information.
- optional VendorInformation vendor_info = 3;
- }
- // Information of the wireless AP that device is connected to.
- optional WifiAccessPoint access_point_info = 5;
- }
- optional Network network = 13;
-
- // Information on the Google Update install that is managing this client.
- message GoogleUpdate {
- // Whether the Google Update install is system-level or user-level.
- optional bool is_system_install = 1;
-
- // The date at which Google Update last started performing an automatic
- // update check, in seconds since the Unix epoch.
- optional int64 last_automatic_start_timestamp = 2;
-
- // The date at which Google Update last successfully sent an update check
- // and recieved an intact response from the server, in seconds since the
- // Unix epoch. (The updates don't need to be successfully installed.)
- optional int64 last_update_check_timestamp = 3;
-
- // Describes a product being managed by Google Update. (This can also
- // describe Google Update itself.)
- message ProductInfo {
- // The current version of the product that is installed.
- optional string version = 1;
-
- // The date at which Google Update successfully updated this product,
- // stored in seconds since the Unix epoch. This is updated when an update
- // is successfully applied, or if the server reports that no update
- // is available.
- optional int64 last_update_success_timestamp = 2;
-
- // The result reported by the product updater on its last run.
- enum InstallResult {
- INSTALL_RESULT_SUCCESS = 0;
- INSTALL_RESULT_FAILED_CUSTOM_ERROR = 1;
- INSTALL_RESULT_FAILED_MSI_ERROR = 2;
- INSTALL_RESULT_FAILED_SYSTEM_ERROR = 3;
- INSTALL_RESULT_EXIT_CODE = 4;
- }
- optional InstallResult last_result = 3;
-
- // The error code reported by the product updater on its last run. This
- // will typically be a error code specific to the product installer.
- optional int32 last_error = 4;
-
- // The extra error code reported by the product updater on its last run.
- // This will typically be a Win32 error code.
- optional int32 last_extra_error = 5;
- }
- optional ProductInfo google_update_status = 4;
- optional ProductInfo client_status = 5;
- }
- optional GoogleUpdate google_update = 11;
-
- // Information on all installed plugins.
- message Plugin {
- // The plugin's self-reported name and filename (without path).
- optional string name = 1;
- optional string filename = 2;
-
- // The plugin's version.
- optional string version = 3;
-
- // True if the plugin is disabled.
- // If a client has multiple local Chrome user accounts, this is logged based
- // on the first user account launched during the current session.
- optional bool is_disabled = 4;
-
- // True if the plugin is PPAPI.
- optional bool is_pepper = 5;
- }
- repeated Plugin plugin = 7;
-
- // Figures that can be used to generate application stability metrics.
- // All values are counts of events since the last time that these
- // values were reported.
- // Next tag: 24
- message Stability {
- // Total amount of time that the program was running, in seconds,
- // since the last time a log was recorded, as measured using a client-side
- // clock implemented via TimeTicks, which guarantees that it is monotonic
- // and does not jump if the user changes his/her clock. The TimeTicks
- // implementation also makes the clock not count time the computer is
- // suspended.
- optional int64 incremental_uptime_sec = 1;
-
- // Total amount of time that the program was running, in seconds,
- // since startup, as measured using a client-side clock implemented
- // via TimeTicks, which guarantees that it is monotonic and does not
- // jump if the user changes his/her clock. The TimeTicks implementation
- // also makes the clock not count time the computer is suspended.
- // This field was added for M-35.
- optional int64 uptime_sec = 23;
-
- // Page loads along with renderer crashes and hangs, since page load count
- // roughly corresponds to usage.
- optional int32 page_load_count = 2;
- optional int32 renderer_crash_count = 3;
- optional int32 renderer_hang_count = 4;
-
- // Number of renderer crashes that were for extensions. These crashes are
- // not counted in renderer_crash_count.
- optional int32 extension_renderer_crash_count = 5;
-
- // Number of non-renderer child process crashes.
- optional int32 child_process_crash_count = 6;
-
- // Number of times the browser has crashed while logged in as the "other
- // user" (guest) account.
- // Logged on ChromeOS only.
- optional int32 other_user_crash_count = 7;
-
- // Number of times the kernel has crashed.
- // Logged on ChromeOS only.
- optional int32 kernel_crash_count = 8;
-
- // Number of times the system has shut down uncleanly.
- // Logged on ChromeOS only.
- optional int32 unclean_system_shutdown_count = 9;
-
- //
- // All the remaining fields in the Stability are recorded at most once per
- // client session.
- //
-
- // The number of times the program was launched.
- // This will typically be equal to 1. However, it is possible that Chrome
- // was unable to upload stability metrics for previous launches (e.g. due to
- // crashing early during startup), and hence this value might be greater
- // than 1.
- optional int32 launch_count = 15;
- // The number of times that it didn't exit cleanly (which we assume to be
- // mostly crashes).
- optional int32 crash_count = 16;
-
- // The number of times the program began, but did not complete, the shutdown
- // process. (For example, this may occur when Windows is shutting down, and
- // it only gives the process a few seconds to clean up.)
- optional int32 incomplete_shutdown_count = 17;
-
- // The number of times the program was able register with breakpad crash
- // services.
- optional int32 breakpad_registration_success_count = 18;
-
- // The number of times the program failed to register with breakpad crash
- // services. If crash registration fails then when the program crashes no
- // crash report will be generated.
- optional int32 breakpad_registration_failure_count = 19;
-
- // The number of times the program has run under a debugger. This should
- // be an exceptional condition. Running under a debugger prevents crash
- // dumps from being generated.
- optional int32 debugger_present_count = 20;
-
- // The number of times the program has run without a debugger attached.
- // This should be most common scenario and should be very close to
- // |launch_count|.
- optional int32 debugger_not_present_count = 21;
-
- // Stability information for all installed plugins.
- message PluginStability {
- // The relevant plugin's information (name, etc.)
- optional Plugin plugin = 1;
-
- // The number of times this plugin's process was launched.
- optional int32 launch_count = 2;
-
- // The number of times this plugin was instantiated on a web page.
- // This will be >= |launch_count|.
- // (A page load with multiple sections drawn by this plugin will
- // increase this count multiple times.)
- optional int32 instance_count = 3;
-
- // The number of times this plugin process crashed.
- // This value will be <= |launch_count|.
- optional int32 crash_count = 4;
-
- // The number of times this plugin could not be loaded.
- optional int32 loading_error_count = 5;
- }
- repeated PluginStability plugin_stability = 22;
- }
- optional Stability stability = 8;
-
- // Description of a field trial or experiment that the user is currently
- // enrolled in.
- // All metrics reported in this upload can potentially be influenced by the
- // field trial.
- message FieldTrial {
- // The name of the field trial, as a 32-bit identifier.
- // Currently, the identifier is a hash of the field trial's name.
- optional fixed32 name_id = 1;
-
- // The user's group within the field trial, as a 32-bit identifier.
- // Currently, the identifier is a hash of the group's name.
- optional fixed32 group_id = 2;
- }
- repeated FieldTrial field_trial = 9;
-
- // Information about the A/V output device(s) (typically just a TV).
- // However, a configuration may have one or more intermediate A/V devices
- // between the source device and the TV (e.g. an A/V receiver, video
- // processor, etc.).
- message ExternalAudioVideoDevice {
- // The manufacturer name (possibly encoded as a 3-letter code, e.g. "YMH"
- // for Yamaha).
- optional string manufacturer_name = 1;
-
- // The model name (e.g. "RX-V1900"). Some devices may report generic names
- // like "receiver" or use the full manufacturer name (e.g "PHILIPS").
- optional string model_name = 2;
-
- // The product code (e.g. "0218").
- optional string product_code = 3;
-
- // The device types. A single device can have multiple types (e.g. a set-top
- // box could be both a tuner and a player). The same type may even be
- // repeated (e.g a device that reports two tuners).
- enum AVDeviceType {
- AV_DEVICE_TYPE_UNKNOWN = 0;
- AV_DEVICE_TYPE_TV = 1;
- AV_DEVICE_TYPE_RECORDER = 2;
- AV_DEVICE_TYPE_TUNER = 3;
- AV_DEVICE_TYPE_PLAYER = 4;
- AV_DEVICE_TYPE_AUDIO_SYSTEM = 5;
- }
- repeated AVDeviceType av_device_type = 4;
-
- // The year of manufacture.
- optional int32 manufacture_year = 5;
-
- // The week of manufacture.
- // Note: per the Wikipedia EDID article, numbering for this field may not
- // be consistent between manufacturers.
- optional int32 manufacture_week = 6;
-
- // Max horizontal resolution in pixels.
- optional int32 horizontal_resolution = 7;
-
- // Max vertical resolution in pixels.
- optional int32 vertical_resolution = 8;
-
- // Audio capabilities of the device.
- // Ref: http://en.wikipedia.org/wiki/Extended_display_identification_data
- message AudioDescription {
- // Audio format
- enum AudioFormat {
- AUDIO_FORMAT_UNKNOWN = 0;
- AUDIO_FORMAT_LPCM = 1;
- AUDIO_FORMAT_AC_3 = 2;
- AUDIO_FORMAT_MPEG1 = 3;
- AUDIO_FORMAT_MP3 = 4;
- AUDIO_FORMAT_MPEG2 = 5;
- AUDIO_FORMAT_AAC = 6;
- AUDIO_FORMAT_DTS = 7;
- AUDIO_FORMAT_ATRAC = 8;
- AUDIO_FORMAT_ONE_BIT = 9;
- AUDIO_FORMAT_DD_PLUS = 10;
- AUDIO_FORMAT_DTS_HD = 11;
- AUDIO_FORMAT_MLP_DOLBY_TRUEHD = 12;
- AUDIO_FORMAT_DST_AUDIO = 13;
- AUDIO_FORMAT_MICROSOFT_WMA_PRO = 14;
- }
- optional AudioFormat audio_format = 1;
-
- // Number of channels (e.g. 1, 2, 8, etc.).
- optional int32 num_channels = 2;
-
- // Supported sample frequencies in Hz (e.g. 32000, 44100, etc.).
- // Multiple frequencies may be specified.
- repeated int32 sample_frequency_hz = 3;
-
- // Maximum bit rate in bits/s.
- optional int32 max_bit_rate_per_second = 4;
-
- // Bit depth (e.g. 16, 20, 24, etc.).
- optional int32 bit_depth = 5;
- }
- repeated AudioDescription audio_description = 9;
-
- // The position in AV setup.
- // A value of 0 means this device is the TV.
- // A value of 1 means this device is directly connected to one of
- // the TV's inputs.
- // Values > 1 indicate there are 1 or more devices between this device
- // and the TV.
- optional int32 position_in_setup = 10;
-
- // Whether this device is in the path to the TV.
- optional bool is_in_path_to_tv = 11;
-
- // The CEC version the device supports.
- // CEC stands for Consumer Electronics Control, a part of the HDMI
- // specification. Not all HDMI devices support CEC.
- // Only devices that support CEC will report a value here.
- optional int32 cec_version = 12;
-
- // This message reports CEC commands seen by a device.
- // After each log is sent, this information is cleared and gathered again.
- // By collecting CEC status information by opcode we can determine
- // which CEC features can be supported.
- message CECCommand {
- // The CEC command opcode. CEC supports up to 256 opcodes.
- // We add only one CECCommand message per unique opcode. Only opcodes
- // seen by the device will be reported. The remainder of the message
- // accumulates status for this opcode (and device).
- optional int32 opcode = 1;
-
- // The total number of commands received from the external device.
- optional int32 num_received_direct = 2;
-
- // The number of commands received from the external device as part of a
- // broadcast message.
- optional int32 num_received_broadcast = 3;
-
- // The total number of commands sent to the external device.
- optional int32 num_sent_direct = 4;
-
- // The number of commands sent to the external device as part of a
- // broadcast message.
- optional int32 num_sent_broadcast = 5;
-
- // The number of aborted commands for unknown reasons.
- optional int32 num_aborted_unknown_reason = 6;
-
- // The number of aborted commands because of an unrecognized opcode.
- optional int32 num_aborted_unrecognized = 7;
- }
- repeated CECCommand cec_command = 13;
- }
- repeated ExternalAudioVideoDevice external_audio_video_device = 14;
-
- // Information about the current wireless access point. Collected directly
- // from the wireless access point via standard apis if the device is
- // connected to the Internet wirelessly. Introduced for Chrome on TV devices
- // but also can be collected by ChromeOS, Android or other clients.
- message ExternalAccessPoint {
- // The manufacturer name, for example "ASUSTeK Computer Inc.".
- optional string manufacturer = 1;
-
- // The model name, for example "Wi-Fi Protected Setup Router".
- optional string model_name = 2;
-
- // The model number, for example "RT-N16".
- optional string model_number = 3;
-
- // The device name (sometime same as model_number), for example "RT-N16".
- optional string device_name = 4;
- }
- optional ExternalAccessPoint external_access_point = 15;
-
- // Number of users currently signed into a multiprofile session.
- // A zero value indicates that the user count changed while the log is open.
- // Logged only on ChromeOS.
- optional uint32 multi_profile_user_count = 17;
-
- // Information about extensions that are installed, masked to provide better
- // privacy. Only extensions from a single profile are reported; this will
- // generally be the profile used when the browser is started. The profile
- // reported on will remain consistent at least until the browser is
- // relaunched (or the profile is deleted by the user).
- //
- // Each client first picks a value for client_key derived from its UMA
- // client_id:
- // client_key = client_id % 4096
- // Then, each installed extension is mapped into a hash bucket according to
- // bucket = CityHash64(StringPrintf("%d:%s",
- // client_key, extension_id)) % 1024
- // The client reports the set of hash buckets occupied by all installed
- // extensions. If multiple extensions map to the same bucket, that bucket is
- // still only reported once.
- repeated int32 occupied_extension_bucket = 18;
-
- // The state of loaded extensions for this system. The system can have either
- // no applicable extensions, extensions only from the webstore and verified by
- // the webstore, extensions only from the webstore but not verified, or
- // extensions not from the store. If there is a single off-store extension,
- // then HAS_OFFSTORE is reported. This should be kept in sync with the
- // corresponding enum in chrome/browser/metrics/extensions_metrics_provider.cc
- enum ExtensionsState {
- NO_EXTENSIONS = 0;
- NO_OFFSTORE_VERIFIED = 1;
- NO_OFFSTORE_UNVERIFIED = 2;
- HAS_OFFSTORE = 3;
- }
- optional ExtensionsState offstore_extensions_state = 19;
-}
diff --git a/metricsd/uploader/proto/user_action_event.proto b/metricsd/uploader/proto/user_action_event.proto
deleted file mode 100644
index 464f3c8..0000000
--- a/metricsd/uploader/proto/user_action_event.proto
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-//
-// Stores information about an event that occurs in response to a user action,
-// e.g. an interaction with a browser UI element.
-
-syntax = "proto2";
-
-option optimize_for = LITE_RUNTIME;
-option java_outer_classname = "UserActionEventProtos";
-option java_package = "org.chromium.components.metrics";
-
-package metrics;
-
-// Next tag: 3
-message UserActionEventProto {
- // The name of the action, hashed.
- optional fixed64 name_hash = 1;
-
- // The timestamp for the event, in seconds since the epoch.
- optional int64 time = 2;
-}
diff --git a/metricsd/uploader/sender.h b/metricsd/uploader/sender.h
deleted file mode 100644
index 369c9c2..0000000
--- a/metricsd/uploader/sender.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-
-#ifndef METRICS_UPLOADER_SENDER_H_
-#define METRICS_UPLOADER_SENDER_H_
-
-#include <string>
-
-// Abstract class for a Sender that uploads a metrics message.
-class Sender {
- public:
- virtual ~Sender() {}
- // Sends a message |content| with its sha1 hash |hash|
- virtual bool Send(const std::string& content, const std::string& hash) = 0;
-};
-
-#endif // METRICS_UPLOADER_SENDER_H_
diff --git a/metricsd/uploader/sender_http.cc b/metricsd/uploader/sender_http.cc
deleted file mode 100644
index 1f775df..0000000
--- a/metricsd/uploader/sender_http.cc
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2015 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 "uploader/sender_http.h"
-
-#include <string>
-
-#include <base/logging.h>
-#include <base/strings/string_number_conversions.h>
-#include <brillo/http/http_utils.h>
-#include <brillo/mime_utils.h>
-
-HttpSender::HttpSender(const std::string& server_url)
- : server_url_(server_url) {}
-
-bool HttpSender::Send(const std::string& content,
- const std::string& content_hash) {
- const std::string hash =
- base::HexEncode(content_hash.data(), content_hash.size());
-
- brillo::http::HeaderList headers = {{"X-Chrome-UMA-Log-SHA1", hash}};
- brillo::ErrorPtr error;
- auto response = brillo::http::PostTextAndBlock(
- server_url_,
- content,
- brillo::mime::application::kWwwFormUrlEncoded,
- headers,
- brillo::http::Transport::CreateDefault(),
- &error);
- if (!response || response->ExtractDataAsString() != "OK") {
- if (error) {
- DLOG(ERROR) << "Failed to send data: " << error->GetMessage();
- }
- return false;
- }
- return true;
-}
diff --git a/metricsd/uploader/sender_http.h b/metricsd/uploader/sender_http.h
deleted file mode 100644
index 0d64c74..0000000
--- a/metricsd/uploader/sender_http.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-
-#ifndef METRICS_UPLOADER_SENDER_HTTP_H_
-#define METRICS_UPLOADER_SENDER_HTTP_H_
-
-#include <string>
-
-#include <base/macros.h>
-
-#include "uploader/sender.h"
-
-// Sender implemented using http_utils from libbrillo
-class HttpSender : public Sender {
- public:
- explicit HttpSender(const std::string& server_url);
- ~HttpSender() override = default;
- // Sends |content| whose SHA1 hash is |hash| to server_url with a synchronous
- // POST request to server_url.
- bool Send(const std::string& content, const std::string& hash) override;
-
- private:
- const std::string server_url_;
-
- DISALLOW_COPY_AND_ASSIGN(HttpSender);
-};
-
-#endif // METRICS_UPLOADER_SENDER_HTTP_H_
diff --git a/metricsd/uploader/system_profile_cache.cc b/metricsd/uploader/system_profile_cache.cc
deleted file mode 100644
index e6f6617..0000000
--- a/metricsd/uploader/system_profile_cache.cc
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * Copyright (C) 2015 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 "uploader/system_profile_cache.h"
-
-#include <base/files/file_util.h>
-#include <base/guid.h>
-#include <base/logging.h>
-#include <base/strings/string_number_conversions.h>
-#include <base/strings/string_util.h>
-#include <brillo/osrelease_reader.h>
-#include <string>
-#include <update_engine/client.h>
-#include <vector>
-
-#include "constants.h"
-#include "persistent_integer.h"
-#include "uploader/metrics_log_base.h"
-#include "uploader/proto/chrome_user_metrics_extension.pb.h"
-
-namespace {
-
-const char kPersistentSessionIdFilename[] = "Sysinfo.SessionId";
-
-} // namespace
-
-std::string ChannelToString(
- const metrics::SystemProfileProto_Channel& channel) {
- switch (channel) {
- case metrics::SystemProfileProto::CHANNEL_STABLE:
- return "STABLE";
- case metrics::SystemProfileProto::CHANNEL_DEV:
- return "DEV";
- case metrics::SystemProfileProto::CHANNEL_BETA:
- return "BETA";
- case metrics::SystemProfileProto::CHANNEL_CANARY:
- return "CANARY";
- default:
- return "UNKNOWN";
- }
-}
-
-SystemProfileCache::SystemProfileCache()
- : initialized_(false),
- testing_(false),
- metrics_directory_(metrics::kMetricsdDirectory),
- session_id_(new chromeos_metrics::PersistentInteger(
- kPersistentSessionIdFilename, metrics_directory_)) {}
-
-SystemProfileCache::SystemProfileCache(bool testing,
- const base::FilePath& metrics_directory)
- : initialized_(false),
- testing_(testing),
- metrics_directory_(metrics_directory),
- session_id_(new chromeos_metrics::PersistentInteger(
- kPersistentSessionIdFilename, metrics_directory)) {}
-
-bool SystemProfileCache::Initialize() {
- CHECK(!initialized_)
- << "this should be called only once in the metrics_daemon lifetime.";
-
- brillo::OsReleaseReader reader;
- std::string channel;
- if (testing_) {
- reader.LoadTestingOnly(metrics_directory_);
- channel = "unknown";
- } else {
- reader.Load();
- auto client = update_engine::UpdateEngineClient::CreateInstance();
- if (!client) {
- LOG(ERROR) << "failed to create the update engine client";
- return false;
- }
- if (!client->GetChannel(&channel)) {
- LOG(ERROR) << "failed to read the current channel from update engine.";
- return false;
- }
- }
-
- if (!reader.GetString(metrics::kProductId, &profile_.product_id)
- || profile_.product_id.empty()) {
- LOG(ERROR) << "product_id is not set.";
- return false;
- }
-
- if (!reader.GetString(metrics::kProductVersion, &profile_.version)) {
- LOG(ERROR) << "failed to read the product version";
- }
-
- if (channel.empty() || profile_.version.empty()) {
- // If the channel or version is missing, the image is not official.
- // In this case, set the channel to unknown and the version to 0.0.0.0 to
- // avoid polluting the production data.
- channel = "";
- profile_.version = metrics::kDefaultVersion;
- }
- std::string guid_path = metrics_directory_.Append(
- metrics::kMetricsGUIDFileName).value();
- profile_.client_id = testing_ ?
- "client_id_test" :
- GetPersistentGUID(guid_path);
- profile_.model_manifest_id = "unknown";
- if (!testing_) {
- brillo::KeyValueStore weave_config;
- if (!weave_config.Load(base::FilePath(metrics::kWeaveConfigurationFile))) {
- LOG(ERROR) << "Failed to load the weave configuration file.";
- } else if (!weave_config.GetString(metrics::kModelManifestId,
- &profile_.model_manifest_id)) {
- LOG(ERROR) << "The model manifest id (model_id) is undefined in "
- << metrics::kWeaveConfigurationFile;
- }
- }
-
- profile_.channel = ProtoChannelFromString(channel);
-
- // Increment the session_id everytime we initialize this. If metrics_daemon
- // does not crash, this should correspond to the number of reboots of the
- // system.
- session_id_->Add(1);
- profile_.session_id = static_cast<int32_t>(session_id_->Get());
-
- initialized_ = true;
- return initialized_;
-}
-
-bool SystemProfileCache::InitializeOrCheck() {
- return initialized_ || Initialize();
-}
-
-bool SystemProfileCache::Populate(
- metrics::ChromeUserMetricsExtension* metrics_proto) {
- CHECK(metrics_proto);
- if (not InitializeOrCheck()) {
- return false;
- }
-
- // The client id is hashed before being sent.
- metrics_proto->set_client_id(
- metrics::MetricsLogBase::Hash(profile_.client_id));
- metrics_proto->set_session_id(profile_.session_id);
-
- // Sets the product id.
- metrics_proto->set_product(9);
-
- metrics::SystemProfileProto* profile_proto =
- metrics_proto->mutable_system_profile();
- profile_proto->mutable_hardware()->set_hardware_class(
- profile_.model_manifest_id);
- profile_proto->set_app_version(profile_.version);
- profile_proto->set_channel(profile_.channel);
- metrics::SystemProfileProto_BrilloDeviceData* device_data =
- profile_proto->mutable_brillo();
- device_data->set_product_id(profile_.product_id);
-
- return true;
-}
-
-std::string SystemProfileCache::GetPersistentGUID(
- const std::string& filename) {
- std::string guid;
- base::FilePath filepath(filename);
- if (!base::ReadFileToString(filepath, &guid)) {
- guid = base::GenerateGUID();
- // If we can't read or write the file, the guid will not be preserved during
- // the next reboot. Crash.
- CHECK(base::WriteFile(filepath, guid.c_str(), guid.size()));
- }
- return guid;
-}
-
-metrics::SystemProfileProto_Channel SystemProfileCache::ProtoChannelFromString(
- const std::string& channel) {
- if (channel == "stable-channel") {
- return metrics::SystemProfileProto::CHANNEL_STABLE;
- } else if (channel == "dev-channel") {
- return metrics::SystemProfileProto::CHANNEL_DEV;
- } else if (channel == "beta-channel") {
- return metrics::SystemProfileProto::CHANNEL_BETA;
- } else if (channel == "canary-channel") {
- return metrics::SystemProfileProto::CHANNEL_CANARY;
- }
-
- DLOG(INFO) << "unknown channel: " << channel;
- return metrics::SystemProfileProto::CHANNEL_UNKNOWN;
-}
diff --git a/metricsd/uploader/system_profile_cache.h b/metricsd/uploader/system_profile_cache.h
deleted file mode 100644
index f9c484c..0000000
--- a/metricsd/uploader/system_profile_cache.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-
-#ifndef METRICS_UPLOADER_SYSTEM_PROFILE_CACHE_H_
-#define METRICS_UPLOADER_SYSTEM_PROFILE_CACHE_H_
-
-#include <stdint.h>
-
-#include <memory>
-#include <string>
-
-#include "base/compiler_specific.h"
-#include "base/files/file_path.h"
-#include "base/gtest_prod_util.h"
-#include "persistent_integer.h"
-#include "uploader/proto/system_profile.pb.h"
-#include "uploader/system_profile_setter.h"
-
-namespace metrics {
-class ChromeUserMetricsExtension;
-}
-
-struct SystemProfile {
- std::string version;
- std::string model_manifest_id;
- std::string client_id;
- int session_id;
- metrics::SystemProfileProto::Channel channel;
- std::string product_id;
-};
-
-// Retrieves general system informations needed by the protobuf for context and
-// remembers them to avoid expensive calls.
-//
-// The cache is populated lazily. The only method needed is Populate.
-class SystemProfileCache : public SystemProfileSetter {
- public:
- SystemProfileCache();
-
- SystemProfileCache(bool testing, const base::FilePath& metrics_directory);
-
- // Populates the ProfileSystem protobuf with system information.
- bool Populate(metrics::ChromeUserMetricsExtension* metrics_proto) override;
-
- // Converts a string representation of the channel to a
- // SystemProfileProto_Channel
- static metrics::SystemProfileProto_Channel ProtoChannelFromString(
- const std::string& channel);
-
- // Gets the persistent GUID and create it if it has not been created yet.
- static std::string GetPersistentGUID(const std::string& filename);
-
- private:
- friend class UploadServiceTest;
- FRIEND_TEST(UploadServiceTest, ExtractChannelFromDescription);
- FRIEND_TEST(UploadServiceTest, ReadKeyValueFromFile);
- FRIEND_TEST(UploadServiceTest, SessionIdIncrementedAtInitialization);
- FRIEND_TEST(UploadServiceTest, ValuesInConfigFileAreSent);
- FRIEND_TEST(UploadServiceTest, ProductIdMandatory);
-
- // Fetches all informations and populates |profile_|
- bool Initialize();
-
- // Initializes |profile_| only if it has not been yet initialized.
- bool InitializeOrCheck();
-
- bool initialized_;
- bool testing_;
- base::FilePath metrics_directory_;
- std::unique_ptr<chromeos_metrics::PersistentInteger> session_id_;
- SystemProfile profile_;
-};
-
-#endif // METRICS_UPLOADER_SYSTEM_PROFILE_CACHE_H_
diff --git a/metricsd/uploader/system_profile_setter.h b/metricsd/uploader/system_profile_setter.h
deleted file mode 100644
index bd3ff42..0000000
--- a/metricsd/uploader/system_profile_setter.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-
-#ifndef METRICS_UPLOADER_SYSTEM_PROFILE_SETTER_H_
-#define METRICS_UPLOADER_SYSTEM_PROFILE_SETTER_H_
-
-namespace metrics {
-class ChromeUserMetricsExtension;
-}
-
-// Abstract class used to delegate populating SystemProfileProto with system
-// information to simplify testing.
-class SystemProfileSetter {
- public:
- virtual ~SystemProfileSetter() {}
- // Populates the protobuf with system informations.
- virtual bool Populate(metrics::ChromeUserMetricsExtension* profile_proto) = 0;
-};
-
-#endif // METRICS_UPLOADER_SYSTEM_PROFILE_SETTER_H_
diff --git a/metricsd/uploader/upload_service.cc b/metricsd/uploader/upload_service.cc
deleted file mode 100644
index 333a7e6..0000000
--- a/metricsd/uploader/upload_service.cc
+++ /dev/null
@@ -1,256 +0,0 @@
-/*
- * Copyright (C) 2015 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 "uploader/upload_service.h"
-
-#include <sysexits.h>
-
-#include <memory>
-#include <string>
-
-#include <base/bind.h>
-#include <base/files/file_util.h>
-#include <base/logging.h>
-#include <base/memory/scoped_vector.h>
-#include <base/message_loop/message_loop.h>
-#include <base/metrics/histogram.h>
-#include <base/metrics/histogram_base.h>
-#include <base/metrics/histogram_snapshot_manager.h>
-#include <base/metrics/sparse_histogram.h>
-#include <base/metrics/statistics_recorder.h>
-#include <base/sha1.h>
-
-#include "constants.h"
-#include "uploader/metrics_log.h"
-#include "uploader/sender_http.h"
-#include "uploader/system_profile_setter.h"
-
-const int UploadService::kMaxFailedUpload = 10;
-
-UploadService::UploadService(const std::string& server,
- const base::TimeDelta& upload_interval,
- const base::TimeDelta& disk_persistence_interval,
- const base::FilePath& private_metrics_directory,
- const base::FilePath& shared_metrics_directory)
- : brillo::Daemon(),
- histogram_snapshot_manager_(this),
- sender_(new HttpSender(server)),
- failed_upload_count_(metrics::kFailedUploadCountName,
- private_metrics_directory),
- counters_(new CrashCounters),
- upload_interval_(upload_interval),
- disk_persistence_interval_(disk_persistence_interval),
- metricsd_service_runner_(counters_) {
- staged_log_path_ = private_metrics_directory.Append(metrics::kStagedLogName);
- saved_log_path_ = private_metrics_directory.Append(metrics::kSavedLogName);
- consent_file_ = shared_metrics_directory.Append(metrics::kConsentFileName);
-}
-
-void UploadService::LoadSavedLog() {
- if (base::PathExists(saved_log_path_)) {
- GetOrCreateCurrentLog()->LoadFromFile(saved_log_path_);
- }
-}
-
-int UploadService::OnInit() {
- brillo::Daemon::OnInit();
-
- base::StatisticsRecorder::Initialize();
- metricsd_service_runner_.Start();
-
- system_profile_setter_.reset(new SystemProfileCache());
-
- base::MessageLoop::current()->PostDelayedTask(
- FROM_HERE,
- base::Bind(&UploadService::UploadEventCallback, base::Unretained(this)),
- upload_interval_);
-
- base::MessageLoop::current()->PostDelayedTask(
- FROM_HERE,
- base::Bind(&UploadService::PersistEventCallback, base::Unretained(this)),
- disk_persistence_interval_);
-
- LoadSavedLog();
-
- return EX_OK;
-}
-
-void UploadService::OnShutdown(int* exit_code) {
- metricsd_service_runner_.Stop();
- PersistToDisk();
-}
-
-void UploadService::InitForTest(SystemProfileSetter* setter) {
- LoadSavedLog();
- system_profile_setter_.reset(setter);
-}
-
-void UploadService::StartNewLog() {
- current_log_.reset(new MetricsLog());
-}
-
-void UploadService::UploadEventCallback() {
- UploadEvent();
-
- base::MessageLoop::current()->PostDelayedTask(
- FROM_HERE,
- base::Bind(&UploadService::UploadEventCallback, base::Unretained(this)),
- upload_interval_);
-}
-
-void UploadService::PersistEventCallback() {
- PersistToDisk();
-
- base::MessageLoop::current()->PostDelayedTask(
- FROM_HERE,
- base::Bind(&UploadService::PersistEventCallback, base::Unretained(this)),
- disk_persistence_interval_);
-}
-
-void UploadService::PersistToDisk() {
- GatherHistograms();
- if (current_log_) {
- current_log_->SaveToFile(saved_log_path_);
- }
-}
-
-void UploadService::UploadEvent() {
- // If the system shutdown or crashed while uploading a report, we may not have
- // deleted an old log.
- RemoveFailedLog();
-
- if (HasStagedLog()) {
- // Previous upload failed, retry sending the logs.
- SendStagedLog();
- return;
- }
-
- // Previous upload successful, stage another log.
- GatherHistograms();
- StageCurrentLog();
-
- // If a log is available for upload, upload it.
- if (HasStagedLog()) {
- SendStagedLog();
- }
-}
-
-void UploadService::SendStagedLog() {
- // If metrics are not enabled, discard the log and exit.
- if (!AreMetricsEnabled()) {
- LOG(INFO) << "Metrics disabled. Don't upload metrics samples.";
- base::DeleteFile(staged_log_path_, false);
- return;
- }
-
- std::string staged_log;
- CHECK(base::ReadFileToString(staged_log_path_, &staged_log));
-
- // Increase the failed count in case the daemon crashes while sending the log.
- failed_upload_count_.Add(1);
-
- if (!sender_->Send(staged_log, base::SHA1HashString(staged_log))) {
- LOG(WARNING) << "log failed to upload";
- } else {
- VLOG(1) << "uploaded " << staged_log.length() << " bytes";
- base::DeleteFile(staged_log_path_, false);
- }
-
- RemoveFailedLog();
-}
-
-void UploadService::Reset() {
- base::DeleteFile(staged_log_path_, false);
- current_log_.reset();
- failed_upload_count_.Set(0);
-}
-
-void UploadService::GatherHistograms() {
- base::StatisticsRecorder::Histograms histograms;
- base::StatisticsRecorder::GetHistograms(&histograms);
-
- histogram_snapshot_manager_.PrepareDeltas(
- histograms.begin(), histograms.end(),
- base::Histogram::kNoFlags, base::Histogram::kUmaTargetedHistogramFlag);
-
- // Gather and reset the crash counters, shared with the binder threads.
- unsigned int kernel_crashes = counters_->GetAndResetKernelCrashCount();
- unsigned int unclean_shutdowns = counters_->GetAndResetUncleanShutdownCount();
- unsigned int user_crashes = counters_->GetAndResetUserCrashCount();
-
- // Only create a log if the counters have changed.
- if (kernel_crashes > 0 || unclean_shutdowns > 0 || user_crashes > 0) {
- GetOrCreateCurrentLog()->IncrementKernelCrashCount(kernel_crashes);
- GetOrCreateCurrentLog()->IncrementUncleanShutdownCount(unclean_shutdowns);
- GetOrCreateCurrentLog()->IncrementUserCrashCount(user_crashes);
- }
-}
-
-void UploadService::RecordDelta(const base::HistogramBase& histogram,
- const base::HistogramSamples& snapshot) {
- GetOrCreateCurrentLog()->RecordHistogramDelta(histogram.histogram_name(),
- snapshot);
-}
-
-void UploadService::StageCurrentLog() {
- // If we haven't logged anything since the last upload, don't upload an empty
- // report.
- if (!current_log_)
- return;
-
- std::unique_ptr<MetricsLog> staged_log;
- staged_log.swap(current_log_);
- staged_log->CloseLog();
- if (!staged_log->PopulateSystemProfile(system_profile_setter_.get())) {
- LOG(WARNING) << "Error while adding metadata to the log. Discarding the "
- << "log.";
- return;
- }
-
- if (!base::DeleteFile(saved_log_path_, false)) {
- // There is a chance that we will upload the same metrics twice but, if we
- // are lucky, the backup should be overridden before that. In doubt, try not
- // to lose any metrics.
- LOG(ERROR) << "failed to delete the last backup of the current log.";
- }
-
- failed_upload_count_.Set(0);
- staged_log->SaveToFile(staged_log_path_);
-}
-
-MetricsLog* UploadService::GetOrCreateCurrentLog() {
- if (!current_log_) {
- StartNewLog();
- }
- return current_log_.get();
-}
-
-bool UploadService::HasStagedLog() {
- return base::PathExists(staged_log_path_);
-}
-
-void UploadService::RemoveFailedLog() {
- if (failed_upload_count_.Get() > kMaxFailedUpload) {
- LOG(INFO) << "log failed more than " << kMaxFailedUpload << " times.";
- CHECK(base::DeleteFile(staged_log_path_, false))
- << "failed to delete staged log at " << staged_log_path_.value();
- failed_upload_count_.Set(0);
- }
-}
-
-bool UploadService::AreMetricsEnabled() {
- return base::PathExists(consent_file_);
-}
diff --git a/metricsd/uploader/upload_service.h b/metricsd/uploader/upload_service.h
deleted file mode 100644
index a1d9d3b..0000000
--- a/metricsd/uploader/upload_service.h
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-
-#ifndef METRICS_UPLOADER_UPLOAD_SERVICE_H_
-#define METRICS_UPLOADER_UPLOAD_SERVICE_H_
-
-#include <memory>
-#include <string>
-
-#include <base/metrics/histogram_base.h>
-#include <base/metrics/histogram_flattener.h>
-#include <base/metrics/histogram_snapshot_manager.h>
-#include <brillo/daemons/daemon.h>
-
-#include "persistent_integer.h"
-#include "uploader/crash_counters.h"
-#include "uploader/metrics_log.h"
-#include "uploader/metricsd_service_runner.h"
-#include "uploader/proto/chrome_user_metrics_extension.pb.h"
-#include "uploader/sender.h"
-#include "uploader/system_profile_cache.h"
-
-class SystemProfileSetter;
-
-// Service responsible for backing up the currently aggregated metrics to disk
-// and uploading them periodically to the server.
-//
-// A given metrics sample can be in one of three locations.
-// * in-memory metrics: in memory aggregated metrics, waiting to be staged for
-// upload.
-// * saved log: protobuf message, written to disk periodically and on shutdown
-// to make a backup of metrics data for uploading later.
-// * staged log: protobuf message waiting to be uploaded.
-//
-// The service works as follows:
-// On startup, we create the in-memory metrics from the saved log if it exists.
-//
-// Periodically (every |disk_persistence_interval_| seconds), we take a snapshot
-// of the in-memory metrics and save them to disk.
-//
-// Periodically (every |upload_interval| seconds), we:
-// * take a snapshot of the in-memory metrics and create the staged log
-// * save the staged log to disk to avoid losing it if metricsd or the system
-// crashes between two uploads.
-// * delete the last saved log: all the metrics contained in it are also in the
-// newly created staged log.
-//
-// On shutdown (SIGINT or SIGTERM), we save the in-memory metrics to disk.
-//
-// Note: the in-memory metrics can be stored in |current_log_| or
-// base::StatisticsRecorder.
-class UploadService : public base::HistogramFlattener, public brillo::Daemon {
- public:
- UploadService(const std::string& server,
- const base::TimeDelta& upload_interval,
- const base::TimeDelta& disk_persistence_interval,
- const base::FilePath& private_metrics_directory,
- const base::FilePath& shared_metrics_directory);
-
- // Initializes the upload service.
- int OnInit() override;
-
- // Cleans up the internal state before exiting.
- void OnShutdown(int* exit_code) override;
-
- // Starts a new log. The log needs to be regenerated after each successful
- // launch as it is destroyed when staging the log.
- void StartNewLog();
-
- // Saves the current metrics to a file.
- void PersistToDisk();
-
- // Triggers an upload event.
- void UploadEvent();
-
- // Sends the staged log.
- void SendStagedLog();
-
- // Implements inconsistency detection to match HistogramFlattener's
- // interface.
- void InconsistencyDetected(
- base::HistogramBase::Inconsistency problem) override {}
- void UniqueInconsistencyDetected(
- base::HistogramBase::Inconsistency problem) override {}
- void InconsistencyDetectedInLoggedCount(int amount) override {}
-
- private:
- friend class UploadServiceTest;
-
- FRIEND_TEST(UploadServiceTest, CanSendMultipleTimes);
- FRIEND_TEST(UploadServiceTest, CorruptedSavedLog);
- FRIEND_TEST(UploadServiceTest, CurrentLogSavedAndResumed);
- FRIEND_TEST(UploadServiceTest, DiscardLogsAfterTooManyFailedUpload);
- FRIEND_TEST(UploadServiceTest, EmptyLogsAreNotSent);
- FRIEND_TEST(UploadServiceTest, FailedSendAreRetried);
- FRIEND_TEST(UploadServiceTest, LogContainsAggregatedValues);
- FRIEND_TEST(UploadServiceTest, LogContainsCrashCounts);
- FRIEND_TEST(UploadServiceTest, LogEmptyAfterUpload);
- FRIEND_TEST(UploadServiceTest, LogEmptyByDefault);
- FRIEND_TEST(UploadServiceTest, LogFromTheMetricsLibrary);
- FRIEND_TEST(UploadServiceTest, LogKernelCrash);
- FRIEND_TEST(UploadServiceTest, LogUncleanShutdown);
- FRIEND_TEST(UploadServiceTest, LogUserCrash);
- FRIEND_TEST(UploadServiceTest, PersistEmptyLog);
- FRIEND_TEST(UploadServiceTest, UnknownCrashIgnored);
- FRIEND_TEST(UploadServiceTest, ValuesInConfigFileAreSent);
-
- // Initializes the upload service for testing.
- void InitForTest(SystemProfileSetter* setter);
-
- // If a staged log fails to upload more than kMaxFailedUpload times, it
- // will be discarded.
- static const int kMaxFailedUpload;
-
- // Loads the log saved to disk if it exists.
- void LoadSavedLog();
-
- // Resets the internal state.
- void Reset();
-
- // Returns true iff metrics reporting is enabled.
- bool AreMetricsEnabled();
-
- // Event callback for handling Upload events.
- void UploadEventCallback();
-
- // Event callback for handling Persist events.
- void PersistEventCallback();
-
- // Aggregates all histogram available in memory and store them in the current
- // log.
- void GatherHistograms();
-
- // Callback for HistogramSnapshotManager to store the histograms.
- void RecordDelta(const base::HistogramBase& histogram,
- const base::HistogramSamples& snapshot) override;
-
- // Compiles all the samples received into a single protobuf and adds all
- // system information.
- void StageCurrentLog();
-
- // Returns true iff a log is staged.
- bool HasStagedLog();
-
- // Remove the staged log iff the upload failed more than |kMaxFailedUpload|.
- void RemoveFailedLog();
-
- // Returns the current log. If there is no current log, creates it first.
- MetricsLog* GetOrCreateCurrentLog();
-
- std::unique_ptr<SystemProfileSetter> system_profile_setter_;
- base::HistogramSnapshotManager histogram_snapshot_manager_;
- std::unique_ptr<Sender> sender_;
- chromeos_metrics::PersistentInteger failed_upload_count_;
- std::unique_ptr<MetricsLog> current_log_;
- std::shared_ptr<CrashCounters> counters_;
-
- base::TimeDelta upload_interval_;
- base::TimeDelta disk_persistence_interval_;
-
- MetricsdServiceRunner metricsd_service_runner_;
-
- base::FilePath consent_file_;
- base::FilePath staged_log_path_;
- base::FilePath saved_log_path_;
-
- bool testing_;
-};
-
-#endif // METRICS_UPLOADER_UPLOAD_SERVICE_H_
diff --git a/metricsd/uploader/upload_service_test.cc b/metricsd/uploader/upload_service_test.cc
deleted file mode 100644
index 0f77fe4..0000000
--- a/metricsd/uploader/upload_service_test.cc
+++ /dev/null
@@ -1,339 +0,0 @@
-/*
- * Copyright (C) 2015 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 <memory>
-
-#include <base/at_exit.h>
-#include <base/files/file_util.h>
-#include <base/files/scoped_temp_dir.h>
-#include <base/logging.h>
-#include <base/metrics/sparse_histogram.h>
-#include <base/metrics/statistics_recorder.h>
-#include <base/sys_info.h>
-#include <gtest/gtest.h>
-
-#include "constants.h"
-#include "persistent_integer.h"
-#include "uploader/metrics_log.h"
-#include "uploader/mock/mock_system_profile_setter.h"
-#include "uploader/mock/sender_mock.h"
-#include "uploader/proto/chrome_user_metrics_extension.pb.h"
-#include "uploader/proto/histogram_event.pb.h"
-#include "uploader/proto/system_profile.pb.h"
-#include "uploader/system_profile_cache.h"
-#include "uploader/upload_service.h"
-
-class UploadServiceTest : public testing::Test {
- protected:
- virtual void SetUp() {
- CHECK(dir_.CreateUniqueTempDir());
- // Make sure the statistics recorder is inactive (contains no metrics) then
- // initialize it.
- ASSERT_FALSE(base::StatisticsRecorder::IsActive());
- base::StatisticsRecorder::Initialize();
-
- private_dir_ = dir_.path().Append("private");
- shared_dir_ = dir_.path().Append("shared");
-
- EXPECT_TRUE(base::CreateDirectory(private_dir_));
- EXPECT_TRUE(base::CreateDirectory(shared_dir_));
-
- ASSERT_EQ(0, base::WriteFile(shared_dir_.Append(metrics::kConsentFileName),
- "", 0));
-
- upload_service_.reset(new UploadService(
- "", base::TimeDelta(), base::TimeDelta(), private_dir_, shared_dir_));
- counters_ = upload_service_->counters_;
-
- upload_service_->sender_.reset(new SenderMock);
- upload_service_->InitForTest(new MockSystemProfileSetter);
- upload_service_->GatherHistograms();
- upload_service_->Reset();
- }
-
- void SendSparseHistogram(const std::string& name, int sample) {
- base::HistogramBase* histogram = base::SparseHistogram::FactoryGet(
- name, base::Histogram::kUmaTargetedHistogramFlag);
- histogram->Add(sample);
- }
-
- void SendHistogram(
- const std::string& name, int sample, int min, int max, int nbuckets) {
- base::HistogramBase* histogram = base::Histogram::FactoryGet(
- name, min, max, nbuckets, base::Histogram::kUmaTargetedHistogramFlag);
- histogram->Add(sample);
- }
-
- void SetTestingProperty(const std::string& name, const std::string& value) {
- base::FilePath filepath =
- dir_.path().Append("etc/os-release.d").Append(name);
- ASSERT_TRUE(base::CreateDirectory(filepath.DirName()));
- ASSERT_EQ(value.size(),
- base::WriteFile(filepath, value.data(), value.size()));
- }
-
- const metrics::SystemProfileProto_Stability GetCurrentStability() {
- EXPECT_TRUE(upload_service_->current_log_.get());
-
- return upload_service_->current_log_->uma_proto()
- ->system_profile()
- .stability();
- }
-
- base::ScopedTempDir dir_;
- std::unique_ptr<UploadService> upload_service_;
-
- std::unique_ptr<base::AtExitManager> exit_manager_;
- std::shared_ptr<CrashCounters> counters_;
- base::FilePath private_dir_;
- base::FilePath shared_dir_;
-};
-
-TEST_F(UploadServiceTest, FailedSendAreRetried) {
- SenderMock* sender = new SenderMock();
- upload_service_->sender_.reset(sender);
-
- sender->set_should_succeed(false);
-
- SendSparseHistogram("hello", 1);
- upload_service_->UploadEvent();
- EXPECT_EQ(1, sender->send_call_count());
- std::string sent_string = sender->last_message();
-
- upload_service_->UploadEvent();
- EXPECT_EQ(2, sender->send_call_count());
- EXPECT_EQ(sent_string, sender->last_message());
-}
-
-TEST_F(UploadServiceTest, DiscardLogsAfterTooManyFailedUpload) {
- SenderMock* sender = new SenderMock();
- upload_service_->sender_.reset(sender);
-
- sender->set_should_succeed(false);
-
- SendSparseHistogram("hello", 1);
-
- for (int i = 0; i < UploadService::kMaxFailedUpload; i++) {
- upload_service_->UploadEvent();
- }
-
- EXPECT_TRUE(upload_service_->HasStagedLog());
- upload_service_->UploadEvent();
- EXPECT_FALSE(upload_service_->HasStagedLog());
-
- // Log a new sample. The failed upload counter should be reset.
- SendSparseHistogram("hello", 1);
- for (int i = 0; i < UploadService::kMaxFailedUpload; i++) {
- upload_service_->UploadEvent();
- }
- // The log is not discarded after multiple failed uploads.
- EXPECT_TRUE(upload_service_->HasStagedLog());
-}
-
-TEST_F(UploadServiceTest, EmptyLogsAreNotSent) {
- SenderMock* sender = new SenderMock();
- upload_service_->sender_.reset(sender);
- upload_service_->UploadEvent();
- EXPECT_FALSE(upload_service_->current_log_);
- EXPECT_EQ(0, sender->send_call_count());
-}
-
-TEST_F(UploadServiceTest, LogEmptyByDefault) {
- // current_log_ should be initialized later as it needs AtExitManager to exist
- // in order to gather system information from SysInfo.
- EXPECT_FALSE(upload_service_->current_log_);
-}
-
-TEST_F(UploadServiceTest, CanSendMultipleTimes) {
- SenderMock* sender = new SenderMock();
- upload_service_->sender_.reset(sender);
-
- SendSparseHistogram("hello", 1);
-
- upload_service_->UploadEvent();
-
- std::string first_message = sender->last_message();
- SendSparseHistogram("hello", 2);
-
- upload_service_->UploadEvent();
-
- EXPECT_NE(first_message, sender->last_message());
-}
-
-TEST_F(UploadServiceTest, LogEmptyAfterUpload) {
- SendSparseHistogram("hello", 2);
-
- upload_service_->UploadEvent();
- EXPECT_FALSE(upload_service_->current_log_);
-}
-
-TEST_F(UploadServiceTest, LogContainsAggregatedValues) {
- SendHistogram("foo", 11, 0, 42, 10);
- SendHistogram("foo", 12, 0, 42, 10);
-
- upload_service_->GatherHistograms();
- metrics::ChromeUserMetricsExtension* proto =
- upload_service_->current_log_->uma_proto();
- EXPECT_EQ(1, proto->histogram_event().size());
-}
-
-TEST_F(UploadServiceTest, LogContainsCrashCounts) {
- // By default, there is no current log.
- upload_service_->GatherHistograms();
- EXPECT_FALSE(upload_service_->current_log_);
-
- // If the user crash counter is incremented, we add the count to the current
- // log.
- counters_->IncrementUserCrashCount();
- upload_service_->GatherHistograms();
- EXPECT_EQ(1, GetCurrentStability().other_user_crash_count());
-
- // If the kernel crash counter is incremented, we add the count to the current
- // log.
- counters_->IncrementKernelCrashCount();
- upload_service_->GatherHistograms();
- EXPECT_EQ(1, GetCurrentStability().kernel_crash_count());
-
- // If the kernel crash counter is incremented, we add the count to the current
- // log.
- counters_->IncrementUncleanShutdownCount();
- counters_->IncrementUncleanShutdownCount();
- upload_service_->GatherHistograms();
- EXPECT_EQ(2, GetCurrentStability().unclean_system_shutdown_count());
-
- // If no counter is incremented, the reported numbers don't change.
- upload_service_->GatherHistograms();
- EXPECT_EQ(1, GetCurrentStability().other_user_crash_count());
- EXPECT_EQ(1, GetCurrentStability().kernel_crash_count());
- EXPECT_EQ(2, GetCurrentStability().unclean_system_shutdown_count());
-}
-
-TEST_F(UploadServiceTest, ExtractChannelFromString) {
- EXPECT_EQ(SystemProfileCache::ProtoChannelFromString("developer-build"),
- metrics::SystemProfileProto::CHANNEL_UNKNOWN);
-
- EXPECT_EQ(metrics::SystemProfileProto::CHANNEL_DEV,
- SystemProfileCache::ProtoChannelFromString("dev-channel"));
-
- EXPECT_EQ(metrics::SystemProfileProto::CHANNEL_STABLE,
- SystemProfileCache::ProtoChannelFromString("stable-channel"));
-
- EXPECT_EQ(metrics::SystemProfileProto::CHANNEL_UNKNOWN,
- SystemProfileCache::ProtoChannelFromString("this is a test"));
-}
-
-TEST_F(UploadServiceTest, ValuesInConfigFileAreSent) {
- SenderMock* sender = new SenderMock();
- upload_service_->sender_.reset(sender);
-
- SetTestingProperty(metrics::kProductId, "hello");
- SetTestingProperty(metrics::kProductVersion, "1.2.3.4");
-
- SendSparseHistogram("hello", 1);
-
- // Reset to create the new log with the profile setter.
- upload_service_->system_profile_setter_.reset(
- new SystemProfileCache(true, dir_.path()));
- upload_service_->Reset();
- upload_service_->UploadEvent();
-
- EXPECT_EQ(1, sender->send_call_count());
- EXPECT_TRUE(sender->is_good_proto());
- EXPECT_EQ(1, sender->last_message_proto().histogram_event().size());
-
- EXPECT_NE(0, sender->last_message_proto().client_id());
- EXPECT_NE(0, sender->last_message_proto().system_profile().build_timestamp());
- EXPECT_NE(0, sender->last_message_proto().session_id());
-}
-
-TEST_F(UploadServiceTest, PersistentGUID) {
- std::string tmp_file = dir_.path().Append("tmpfile").value();
-
- std::string first_guid = SystemProfileCache::GetPersistentGUID(tmp_file);
- std::string second_guid = SystemProfileCache::GetPersistentGUID(tmp_file);
-
- // The GUID are cached.
- EXPECT_EQ(first_guid, second_guid);
-
- base::DeleteFile(base::FilePath(tmp_file), false);
-
- first_guid = SystemProfileCache::GetPersistentGUID(tmp_file);
- base::DeleteFile(base::FilePath(tmp_file), false);
- second_guid = SystemProfileCache::GetPersistentGUID(tmp_file);
-
- // Random GUIDs are generated (not all the same).
- EXPECT_NE(first_guid, second_guid);
-}
-
-TEST_F(UploadServiceTest, SessionIdIncrementedAtInitialization) {
- SetTestingProperty(metrics::kProductId, "hello");
- SystemProfileCache cache(true, dir_.path());
- cache.Initialize();
- int session_id = cache.profile_.session_id;
- cache.initialized_ = false;
- cache.Initialize();
- EXPECT_EQ(cache.profile_.session_id, session_id + 1);
-}
-
-// The product id must be set for metrics to be uploaded.
-// If it is not set, the system profile cache should fail to initialize.
-TEST_F(UploadServiceTest, ProductIdMandatory) {
- SystemProfileCache cache(true, dir_.path());
- ASSERT_FALSE(cache.Initialize());
- SetTestingProperty(metrics::kProductId, "");
- ASSERT_FALSE(cache.Initialize());
- SetTestingProperty(metrics::kProductId, "hello");
- ASSERT_TRUE(cache.Initialize());
-}
-
-TEST_F(UploadServiceTest, CurrentLogSavedAndResumed) {
- SendHistogram("hello", 10, 0, 100, 10);
- upload_service_->PersistToDisk();
- EXPECT_EQ(
- 1, upload_service_->current_log_->uma_proto()->histogram_event().size());
- // Destroy the old service before creating a new one.
- upload_service_.reset();
- upload_service_.reset(new UploadService(
- "", base::TimeDelta(), base::TimeDelta(), private_dir_, shared_dir_));
- upload_service_->InitForTest(nullptr);
-
- SendHistogram("hello", 10, 0, 100, 10);
- upload_service_->GatherHistograms();
- EXPECT_EQ(2, upload_service_->GetOrCreateCurrentLog()
- ->uma_proto()
- ->histogram_event()
- .size());
-}
-
-TEST_F(UploadServiceTest, PersistEmptyLog) {
- upload_service_->PersistToDisk();
- EXPECT_FALSE(base::PathExists(upload_service_->saved_log_path_));
-}
-
-TEST_F(UploadServiceTest, CorruptedSavedLog) {
- // Write a bogus saved log.
- EXPECT_EQ(5, base::WriteFile(upload_service_->saved_log_path_, "hello", 5));
-
- // Destroy the old service before creating a new one.
- upload_service_.reset();
- upload_service_.reset(new UploadService(
- "", base::TimeDelta(), base::TimeDelta(), private_dir_, shared_dir_));
-
- upload_service_->InitForTest(nullptr);
- // If the log is unreadable, we drop it and continue execution.
- ASSERT_NE(nullptr, upload_service_->GetOrCreateCurrentLog());
- ASSERT_FALSE(base::PathExists(upload_service_->saved_log_path_));
-}