| Bertrand SIMONNET | 52e5b99 | 2015-08-10 15:18:00 -0700 | [diff] [blame] | 1 | /* | 
 | 2 |  * Copyright (C) 2015 The Android Open Source Project | 
 | 3 |  * | 
 | 4 |  * Licensed under the Apache License, Version 2.0 (the "License"); | 
 | 5 |  * you may not use this file except in compliance with the License. | 
 | 6 |  * You may obtain a copy of the License at | 
 | 7 |  * | 
 | 8 |  *      http://www.apache.org/licenses/LICENSE-2.0 | 
 | 9 |  * | 
 | 10 |  * Unless required by applicable law or agreed to in writing, software | 
 | 11 |  * distributed under the License is distributed on an "AS IS" BASIS, | 
 | 12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 | 13 |  * See the License for the specific language governing permissions and | 
 | 14 |  * limitations under the License. | 
 | 15 |  */ | 
| Darin Petkov | 65b0146 | 2010-04-14 13:32:20 -0700 | [diff] [blame] | 16 |  | 
| Bertrand SIMONNET | d83ca80 | 2014-07-09 16:34:29 -0700 | [diff] [blame] | 17 | #include "metrics/metrics_library.h" | 
| Darin Petkov | 65b0146 | 2010-04-14 13:32:20 -0700 | [diff] [blame] | 18 |  | 
| Luigi Semenzato | 41c5450 | 2014-05-13 15:16:24 -0700 | [diff] [blame] | 19 | #include <base/logging.h> | 
 | 20 | #include <base/strings/stringprintf.h> | 
| Darin Petkov | 65b0146 | 2010-04-14 13:32:20 -0700 | [diff] [blame] | 21 | #include <errno.h> | 
 | 22 | #include <sys/file.h> | 
| Ken Mixter | 4c5daa4 | 2010-08-26 18:35:06 -0700 | [diff] [blame] | 23 | #include <sys/stat.h> | 
| Darin Petkov | 4fcb2ac | 2010-04-15 16:40:23 -0700 | [diff] [blame] | 24 |  | 
| Darin Petkov | 4fcb2ac | 2010-04-15 16:40:23 -0700 | [diff] [blame] | 25 | #include <cstdio> | 
 | 26 | #include <cstring> | 
| Darin Petkov | 65b0146 | 2010-04-14 13:32:20 -0700 | [diff] [blame] | 27 |  | 
| Bertrand SIMONNET | bd3505e | 2015-08-04 14:04:51 -0700 | [diff] [blame] | 28 | #include "constants.h" | 
| Bertrand SIMONNET | 4b915ae | 2015-07-28 15:38:14 -0700 | [diff] [blame] | 29 | #include "serialization/metric_sample.h" | 
 | 30 | #include "serialization/serialization_utils.h" | 
| Chris Masone | e10b548 | 2013-02-14 12:15:35 -0800 | [diff] [blame] | 31 |  | 
| Luigi Semenzato | 3268422 | 2013-03-13 10:53:55 -0700 | [diff] [blame] | 32 | static const char kCrosEventHistogramName[] = "Platform.CrOSEvent"; | 
 | 33 | static const int kCrosEventHistogramMax = 100; | 
| Darin Petkov | 65b0146 | 2010-04-14 13:32:20 -0700 | [diff] [blame] | 34 |  | 
| Chih-Chung Chang | 6844c06 | 2013-04-01 14:27:39 +0800 | [diff] [blame] | 35 | /* Add new cros events here. | 
 | 36 |  * | 
 | 37 |  * The index of the event is sent in the message, so please do not | 
 | 38 |  * reorder the names. | 
 | 39 |  */ | 
 | 40 | static const char *kCrosEventNames[] = { | 
 | 41 |   "ModemManagerCommandSendFailure",  // 0 | 
 | 42 |   "HwWatchdogReboot",  // 1 | 
 | 43 |   "Cras.NoCodecsFoundAtBoot",  // 2 | 
| Darren Krahn | 6e55c115 | 2013-07-19 14:09:50 -0700 | [diff] [blame] | 44 |   "Chaps.DatabaseCorrupted",  // 3 | 
 | 45 |   "Chaps.DatabaseRepairFailure",  // 4 | 
 | 46 |   "Chaps.DatabaseCreateFailure",  // 5 | 
| Darren Krahn | 86830ba | 2013-07-26 13:37:20 -0700 | [diff] [blame] | 47 |   "Attestation.OriginSpecificExhausted",  // 6 | 
| Luigi Semenzato | e57398a | 2013-11-11 14:24:44 -0800 | [diff] [blame] | 48 |   "SpringPowerSupply.Original.High",  // 7 | 
 | 49 |   "SpringPowerSupply.Other.High",  // 8 | 
| Luigi Semenzato | e8fd968 | 2013-11-13 16:28:43 -0800 | [diff] [blame] | 50 |   "SpringPowerSupply.Original.Low",  // 9 | 
 | 51 |   "SpringPowerSupply.ChargerIdle",  // 10 | 
| Darren Krahn | 09a15fa | 2014-02-07 16:51:15 -0800 | [diff] [blame] | 52 |   "TPM.NonZeroDictionaryAttackCounter",  // 11 | 
| Luigi Semenzato | 538e209 | 2015-03-19 17:18:24 -0700 | [diff] [blame] | 53 |   "TPM.EarlyResetDuringCommand",  // 12 | 
| Chih-Chung Chang | 6844c06 | 2013-04-01 14:27:39 +0800 | [diff] [blame] | 54 | }; | 
 | 55 |  | 
| Bertrand SIMONNET | 2765d0a | 2015-09-09 10:38:20 -0700 | [diff] [blame] | 56 | MetricsLibrary::MetricsLibrary() {} | 
| Daniel Erat | fd15829 | 2014-03-09 21:39:08 -0700 | [diff] [blame] | 57 | MetricsLibrary::~MetricsLibrary() {} | 
 | 58 |  | 
| Ken Mixter | eafbbdf | 2010-10-01 15:38:42 -0700 | [diff] [blame] | 59 | // We take buffer and buffer_size as parameters in order to simplify testing | 
 | 60 | // of various alignments of the |device_name| with |buffer_size|. | 
 | 61 | bool MetricsLibrary::IsDeviceMounted(const char* device_name, | 
 | 62 |                                      const char* mounts_file, | 
 | 63 |                                      char* buffer, | 
 | 64 |                                      int buffer_size, | 
 | 65 |                                      bool* result) { | 
| Alex Vakulenko | 1459503 | 2014-08-28 14:59:56 -0700 | [diff] [blame] | 66 |   if (buffer == nullptr || buffer_size < 1) | 
| Ken Mixter | eafbbdf | 2010-10-01 15:38:42 -0700 | [diff] [blame] | 67 |     return false; | 
 | 68 |   int mounts_fd = open(mounts_file, O_RDONLY); | 
 | 69 |   if (mounts_fd < 0) | 
 | 70 |     return false; | 
 | 71 |   // match_offset describes: | 
 | 72 |   //   -1 -- not beginning of line | 
 | 73 |   //   0..strlen(device_name)-1 -- this offset in device_name is next to match | 
 | 74 |   //   strlen(device_name) -- matched full name, just need a space. | 
 | 75 |   int match_offset = 0; | 
 | 76 |   bool match = false; | 
 | 77 |   while (!match) { | 
 | 78 |     int read_size = read(mounts_fd, buffer, buffer_size); | 
 | 79 |     if (read_size <= 0) { | 
 | 80 |       if (errno == -EINTR) | 
 | 81 |         continue; | 
 | 82 |       break; | 
 | 83 |     } | 
 | 84 |     for (int i = 0; i < read_size; ++i) { | 
 | 85 |       if (buffer[i] == '\n') { | 
 | 86 |         match_offset = 0; | 
 | 87 |         continue; | 
 | 88 |       } | 
 | 89 |       if (match_offset < 0) { | 
 | 90 |         continue; | 
 | 91 |       } | 
 | 92 |       if (device_name[match_offset] == '\0') { | 
 | 93 |         if (buffer[i] == ' ') { | 
 | 94 |           match = true; | 
 | 95 |           break; | 
 | 96 |         } | 
 | 97 |         match_offset = -1; | 
 | 98 |         continue; | 
 | 99 |       } | 
 | 100 |  | 
 | 101 |       if (buffer[i] == device_name[match_offset]) { | 
 | 102 |         ++match_offset; | 
 | 103 |       } else { | 
 | 104 |         match_offset = -1; | 
 | 105 |       } | 
 | 106 |     } | 
 | 107 |   } | 
 | 108 |   close(mounts_fd); | 
 | 109 |   *result = match; | 
 | 110 |   return true; | 
 | 111 | } | 
 | 112 |  | 
 | 113 | bool MetricsLibrary::IsGuestMode() { | 
 | 114 |   char buffer[256]; | 
 | 115 |   bool result = false; | 
 | 116 |   if (!IsDeviceMounted("guestfs", | 
 | 117 |                        "/proc/mounts", | 
 | 118 |                        buffer, | 
 | 119 |                        sizeof(buffer), | 
 | 120 |                        &result)) { | 
 | 121 |     return false; | 
 | 122 |   } | 
| Arkaitz Ruiz Alvarez | 9f1a774 | 2011-05-26 12:22:22 -0700 | [diff] [blame] | 123 |   return result && (access("/var/run/state/logged-in", F_OK) == 0); | 
| Ken Mixter | eafbbdf | 2010-10-01 15:38:42 -0700 | [diff] [blame] | 124 | } | 
 | 125 |  | 
| Ken Mixter | 4c5daa4 | 2010-08-26 18:35:06 -0700 | [diff] [blame] | 126 | bool MetricsLibrary::AreMetricsEnabled() { | 
| Julian Pastarmov | 70b7abd | 2011-08-02 16:10:49 +0200 | [diff] [blame] | 127 |   static struct stat stat_buffer; | 
| Alex Vakulenko | 1459503 | 2014-08-28 14:59:56 -0700 | [diff] [blame] | 128 |   time_t this_check_time = time(nullptr); | 
| Bertrand SIMONNET | a5b40d0 | 2015-10-02 16:40:51 -0700 | [diff] [blame] | 129 |   if (!use_caching_ || this_check_time != cached_enabled_time_) { | 
| Ken Mixter | 4c5daa4 | 2010-08-26 18:35:06 -0700 | [diff] [blame] | 130 |     cached_enabled_time_ = this_check_time; | 
| Bertrand SIMONNET | 2765d0a | 2015-09-09 10:38:20 -0700 | [diff] [blame] | 131 |     cached_enabled_ = stat(consent_file_.value().data(), &stat_buffer) >= 0; | 
| Ken Mixter | 4c5daa4 | 2010-08-26 18:35:06 -0700 | [diff] [blame] | 132 |   } | 
 | 133 |   return cached_enabled_; | 
 | 134 | } | 
| Darin Petkov | 11b8eb3 | 2010-05-18 11:00:59 -0700 | [diff] [blame] | 135 |  | 
| Darin Petkov | fc91b42 | 2010-05-12 13:05:45 -0700 | [diff] [blame] | 136 | void MetricsLibrary::Init() { | 
| Bertrand SIMONNET | 9d3a4ae | 2015-11-25 13:49:12 -0800 | [diff] [blame] | 137 |   base::FilePath dir = base::FilePath(metrics::kSharedMetricsDirectory); | 
| Bertrand SIMONNET | 2765d0a | 2015-09-09 10:38:20 -0700 | [diff] [blame] | 138 |   uma_events_file_ = dir.Append(metrics::kMetricsEventsFileName); | 
 | 139 |   consent_file_ = dir.Append(metrics::kConsentFileName); | 
| Bertrand SIMONNET | 3598d95 | 2015-09-28 11:04:29 -0700 | [diff] [blame] | 140 |   cached_enabled_ = false; | 
 | 141 |   cached_enabled_time_ = 0; | 
| Bertrand SIMONNET | a5b40d0 | 2015-10-02 16:40:51 -0700 | [diff] [blame] | 142 |   use_caching_ = true; | 
 | 143 | } | 
 | 144 |  | 
 | 145 | void MetricsLibrary::InitWithNoCaching() { | 
 | 146 |   Init(); | 
 | 147 |   use_caching_ = false; | 
| Darin Petkov | fc91b42 | 2010-05-12 13:05:45 -0700 | [diff] [blame] | 148 | } | 
 | 149 |  | 
| Bertrand SIMONNET | 2765d0a | 2015-09-09 10:38:20 -0700 | [diff] [blame] | 150 | void MetricsLibrary::InitForTest(const base::FilePath& metrics_directory) { | 
 | 151 |   uma_events_file_ = metrics_directory.Append(metrics::kMetricsEventsFileName); | 
 | 152 |   consent_file_ = metrics_directory.Append(metrics::kConsentFileName); | 
| Bertrand SIMONNET | 3598d95 | 2015-09-28 11:04:29 -0700 | [diff] [blame] | 153 |   cached_enabled_ = false; | 
 | 154 |   cached_enabled_time_ = 0; | 
| Bertrand SIMONNET | a5b40d0 | 2015-10-02 16:40:51 -0700 | [diff] [blame] | 155 |   use_caching_ = true; | 
| Bertrand SIMONNET | 1253186 | 2015-08-31 11:11:57 -0700 | [diff] [blame] | 156 | } | 
 | 157 |  | 
| Luigi Semenzato | 41c5450 | 2014-05-13 15:16:24 -0700 | [diff] [blame] | 158 | bool MetricsLibrary::SendToUMA(const std::string& name, | 
 | 159 |                                int sample, | 
 | 160 |                                int min, | 
 | 161 |                                int max, | 
 | 162 |                                int nbuckets) { | 
| Bertrand SIMONNET | d83ca80 | 2014-07-09 16:34:29 -0700 | [diff] [blame] | 163 |   return metrics::SerializationUtils::WriteMetricToFile( | 
 | 164 |       *metrics::MetricSample::HistogramSample(name, sample, min, max, nbuckets) | 
 | 165 |            .get(), | 
| Bertrand SIMONNET | 2765d0a | 2015-09-09 10:38:20 -0700 | [diff] [blame] | 166 |       uma_events_file_.value()); | 
| Darin Petkov | 65b0146 | 2010-04-14 13:32:20 -0700 | [diff] [blame] | 167 | } | 
| Darin Petkov | 5b7dce1 | 2010-04-21 15:45:10 -0700 | [diff] [blame] | 168 |  | 
| Darin Petkov | 21cd2c5 | 2010-05-12 15:26:16 -0700 | [diff] [blame] | 169 | bool MetricsLibrary::SendEnumToUMA(const std::string& name, int sample, | 
 | 170 |                                    int max) { | 
| Bertrand SIMONNET | d83ca80 | 2014-07-09 16:34:29 -0700 | [diff] [blame] | 171 |   return metrics::SerializationUtils::WriteMetricToFile( | 
 | 172 |       *metrics::MetricSample::LinearHistogramSample(name, sample, max).get(), | 
| Bertrand SIMONNET | 2765d0a | 2015-09-09 10:38:20 -0700 | [diff] [blame] | 173 |       uma_events_file_.value()); | 
| Darin Petkov | ed82485 | 2011-01-06 10:51:47 -0800 | [diff] [blame] | 174 | } | 
 | 175 |  | 
| Nathan Bullock | adc1c23 | 2015-11-06 14:02:45 -0500 | [diff] [blame] | 176 | bool MetricsLibrary::SendBoolToUMA(const std::string& name, bool sample) { | 
 | 177 |   return metrics::SerializationUtils::WriteMetricToFile( | 
 | 178 |       *metrics::MetricSample::LinearHistogramSample(name, | 
 | 179 |                                                     sample ? 1 : 0, 2).get(), | 
 | 180 |       uma_events_file_.value()); | 
 | 181 | } | 
 | 182 |  | 
| Luigi Semenzato | a7ebeb3 | 2013-03-19 15:02:42 -0700 | [diff] [blame] | 183 | bool MetricsLibrary::SendSparseToUMA(const std::string& name, int sample) { | 
| Bertrand SIMONNET | d83ca80 | 2014-07-09 16:34:29 -0700 | [diff] [blame] | 184 |   return metrics::SerializationUtils::WriteMetricToFile( | 
 | 185 |       *metrics::MetricSample::SparseHistogramSample(name, sample).get(), | 
| Bertrand SIMONNET | 2765d0a | 2015-09-09 10:38:20 -0700 | [diff] [blame] | 186 |       uma_events_file_.value()); | 
| Luigi Semenzato | a7ebeb3 | 2013-03-19 15:02:42 -0700 | [diff] [blame] | 187 | } | 
 | 188 |  | 
| Darin Petkov | ed82485 | 2011-01-06 10:51:47 -0800 | [diff] [blame] | 189 | bool MetricsLibrary::SendUserActionToUMA(const std::string& action) { | 
| Bertrand SIMONNET | d83ca80 | 2014-07-09 16:34:29 -0700 | [diff] [blame] | 190 |   return metrics::SerializationUtils::WriteMetricToFile( | 
| Bertrand SIMONNET | 2765d0a | 2015-09-09 10:38:20 -0700 | [diff] [blame] | 191 |       *metrics::MetricSample::UserActionSample(action).get(), | 
 | 192 |       uma_events_file_.value()); | 
| Darin Petkov | 5b7dce1 | 2010-04-21 15:45:10 -0700 | [diff] [blame] | 193 | } | 
| Ken Mixter | be2e13b | 2011-01-22 06:15:56 -0800 | [diff] [blame] | 194 |  | 
 | 195 | bool MetricsLibrary::SendCrashToUMA(const char *crash_kind) { | 
| Bertrand SIMONNET | d83ca80 | 2014-07-09 16:34:29 -0700 | [diff] [blame] | 196 |   return metrics::SerializationUtils::WriteMetricToFile( | 
| Bertrand SIMONNET | 2765d0a | 2015-09-09 10:38:20 -0700 | [diff] [blame] | 197 |       *metrics::MetricSample::CrashSample(crash_kind).get(), | 
 | 198 |       uma_events_file_.value()); | 
| Ken Mixter | be2e13b | 2011-01-22 06:15:56 -0800 | [diff] [blame] | 199 | } | 
| Ken Mixter | b2f1709 | 2011-07-22 14:59:51 -0700 | [diff] [blame] | 200 |  | 
| Luigi Semenzato | 3268422 | 2013-03-13 10:53:55 -0700 | [diff] [blame] | 201 | bool MetricsLibrary::SendCrosEventToUMA(const std::string& event) { | 
| Alex Vakulenko | 788d3b6 | 2014-12-11 09:48:46 -0800 | [diff] [blame] | 202 |   for (size_t i = 0; i < arraysize(kCrosEventNames); i++) { | 
| Chih-Chung Chang | 6844c06 | 2013-04-01 14:27:39 +0800 | [diff] [blame] | 203 |     if (strcmp(event.c_str(), kCrosEventNames[i]) == 0) { | 
 | 204 |       return SendEnumToUMA(kCrosEventHistogramName, i, kCrosEventHistogramMax); | 
 | 205 |     } | 
| Luigi Semenzato | 3268422 | 2013-03-13 10:53:55 -0700 | [diff] [blame] | 206 |   } | 
| Chih-Chung Chang | 6844c06 | 2013-04-01 14:27:39 +0800 | [diff] [blame] | 207 |   return false; | 
| Luigi Semenzato | 3268422 | 2013-03-13 10:53:55 -0700 | [diff] [blame] | 208 | } |