blob: 8928a0d8a33a304290dc6c84bb76b8ab121cfcb1 [file] [log] [blame]
Bertrand SIMONNET52e5b992015-08-10 15:18:00 -07001/*
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 */
Bertrand SIMONNET46b49da2014-06-25 14:38:07 -070016
Bertrand SIMONNET4b915ae2015-07-28 15:38:14 -070017#include "uploader/system_profile_cache.h"
Bertrand SIMONNET46b49da2014-06-25 14:38:07 -070018
Bertrand SIMONNETbd3505e2015-08-04 14:04:51 -070019#include <base/files/file_util.h>
20#include <base/guid.h>
21#include <base/logging.h>
22#include <base/strings/string_number_conversions.h>
23#include <base/strings/string_util.h>
Bertrand SIMONNETeb697ab2015-10-14 13:26:42 -070024#include <brillo/osrelease_reader.h>
Bertrand SIMONNET46b49da2014-06-25 14:38:07 -070025#include <string>
Bertrand SIMONNETeb697ab2015-10-14 13:26:42 -070026#include <update_engine/client.h>
Bertrand SIMONNET46b49da2014-06-25 14:38:07 -070027#include <vector>
28
Bertrand SIMONNETbd3505e2015-08-04 14:04:51 -070029#include "constants.h"
Bertrand SIMONNET4b915ae2015-07-28 15:38:14 -070030#include "persistent_integer.h"
31#include "uploader/metrics_log_base.h"
32#include "uploader/proto/chrome_user_metrics_extension.pb.h"
Bertrand SIMONNET46b49da2014-06-25 14:38:07 -070033
Bertrand SIMONNET71a62ef2014-10-07 11:26:25 -070034namespace {
Bertrand SIMONNET46b49da2014-06-25 14:38:07 -070035
Bertrand SIMONNET71a62ef2014-10-07 11:26:25 -070036const char kPersistentSessionIdFilename[] = "Sysinfo.SessionId";
Bertrand SIMONNET71a62ef2014-10-07 11:26:25 -070037
38} // namespace
39
Bertrand SIMONNETa8bcc182014-12-19 09:35:15 -080040std::string ChannelToString(
41 const metrics::SystemProfileProto_Channel& channel) {
42 switch (channel) {
43 case metrics::SystemProfileProto::CHANNEL_STABLE:
44 return "STABLE";
45 case metrics::SystemProfileProto::CHANNEL_DEV:
46 return "DEV";
47 case metrics::SystemProfileProto::CHANNEL_BETA:
48 return "BETA";
49 case metrics::SystemProfileProto::CHANNEL_CANARY:
50 return "CANARY";
51 default:
52 return "UNKNOWN";
53 }
54}
Bertrand SIMONNET71a62ef2014-10-07 11:26:25 -070055
56SystemProfileCache::SystemProfileCache()
57 : initialized_(false),
58 testing_(false),
Bertrand SIMONNET2765d0a2015-09-09 10:38:20 -070059 metrics_directory_(metrics::kMetricsDirectory),
Bertrand SIMONNET71a62ef2014-10-07 11:26:25 -070060 session_id_(new chromeos_metrics::PersistentInteger(
61 kPersistentSessionIdFilename)) {
62}
63
64SystemProfileCache::SystemProfileCache(bool testing,
Bertrand SIMONNET2765d0a2015-09-09 10:38:20 -070065 const base::FilePath& metrics_directory)
Bertrand SIMONNET46b49da2014-06-25 14:38:07 -070066 : initialized_(false),
Bertrand SIMONNETeb815be2014-09-11 07:38:17 -070067 testing_(testing),
Bertrand SIMONNET2765d0a2015-09-09 10:38:20 -070068 metrics_directory_(metrics_directory),
Bertrand SIMONNET46b49da2014-06-25 14:38:07 -070069 session_id_(new chromeos_metrics::PersistentInteger(
70 kPersistentSessionIdFilename)) {
71}
72
73bool SystemProfileCache::Initialize() {
74 CHECK(!initialized_)
75 << "this should be called only once in the metrics_daemon lifetime.";
76
Bertrand SIMONNETeb697ab2015-10-14 13:26:42 -070077 brillo::OsReleaseReader reader;
78 std::string channel;
79 if (testing_) {
80 reader.LoadTestingOnly(metrics_directory_);
81 channel = "unknown";
82 } else {
83 reader.Load();
84 auto client = update_engine::UpdateEngineClient::CreateInstance();
85 if (!client->GetChannel(&channel)) {
86 LOG(ERROR) << "failed to read the current channel from update engine.";
Bertrand SIMONNET608e4282015-11-12 17:52:17 -080087 return false;
Bertrand SIMONNETeb697ab2015-10-14 13:26:42 -070088 }
89 }
Bertrand SIMONNET26993622015-08-20 14:08:41 -070090
Bertrand SIMONNET1d15d462015-11-17 13:20:06 -080091 if (!reader.GetString(metrics::kProductId, &profile_.product_id)
92 || profile_.product_id.empty()) {
Bertrand SIMONNETeb697ab2015-10-14 13:26:42 -070093 LOG(ERROR) << "product_id is not set.";
Bertrand SIMONNET46b49da2014-06-25 14:38:07 -070094 return false;
95 }
96
Bertrand SIMONNETeb697ab2015-10-14 13:26:42 -070097 if (!reader.GetString(metrics::kProductVersion, &profile_.version)) {
98 LOG(ERROR) << "failed to read the product version";
99 }
Bertrand SIMONNET26993622015-08-20 14:08:41 -0700100
101 if (channel.empty() || profile_.version.empty()) {
Bertrand SIMONNETbae5dcc2015-08-04 14:12:10 -0700102 // If the channel or version is missing, the image is not official.
103 // In this case, set the channel to unknown and the version to 0.0.0.0 to
104 // avoid polluting the production data.
105 channel = "";
106 profile_.version = metrics::kDefaultVersion;
Bertrand SIMONNETbae5dcc2015-08-04 14:12:10 -0700107 }
Bertrand SIMONNET2765d0a2015-09-09 10:38:20 -0700108 std::string guid_path = metrics_directory_.Append(
109 metrics::kMetricsGUIDFileName).value();
110 profile_.client_id = testing_ ?
111 "client_id_test" :
112 GetPersistentGUID(guid_path);
Bertrand SIMONNETe6b96d62015-10-30 13:04:40 -0700113 profile_.model_manifest_id = "unknown";
114 if (!testing_) {
115 brillo::KeyValueStore weave_config;
116 if (!weave_config.Load(base::FilePath(metrics::kWeaveConfigurationFile))) {
117 LOG(ERROR) << "Failed to load the weave configuration file.";
118 } else if (!weave_config.GetString(metrics::kModelManifestId,
119 &profile_.model_manifest_id)) {
120 LOG(ERROR) << "The model manifest id (model_id) is undefined in "
121 << metrics::kWeaveConfigurationFile;
122 }
123 }
124
Bertrand SIMONNET52e1d552015-08-04 15:06:21 -0700125 profile_.channel = ProtoChannelFromString(channel);
Bertrand SIMONNET46b49da2014-06-25 14:38:07 -0700126
127 // Increment the session_id everytime we initialize this. If metrics_daemon
128 // does not crash, this should correspond to the number of reboots of the
129 // system.
Bertrand SIMONNET46b49da2014-06-25 14:38:07 -0700130 session_id_->Add(1);
Ben Chanf05ab402014-08-07 00:54:59 -0700131 profile_.session_id = static_cast<int32_t>(session_id_->Get());
Bertrand SIMONNET46b49da2014-06-25 14:38:07 -0700132
133 initialized_ = true;
134 return initialized_;
135}
136
137bool SystemProfileCache::InitializeOrCheck() {
138 return initialized_ || Initialize();
139}
140
Bertrand SIMONNET1f146552015-08-19 18:13:02 -0700141bool SystemProfileCache::Populate(
Bertrand SIMONNET46b49da2014-06-25 14:38:07 -0700142 metrics::ChromeUserMetricsExtension* metrics_proto) {
143 CHECK(metrics_proto);
Bertrand SIMONNET1f146552015-08-19 18:13:02 -0700144 if (not InitializeOrCheck()) {
145 return false;
146 }
Bertrand SIMONNET46b49da2014-06-25 14:38:07 -0700147
148 // The client id is hashed before being sent.
149 metrics_proto->set_client_id(
150 metrics::MetricsLogBase::Hash(profile_.client_id));
151 metrics_proto->set_session_id(profile_.session_id);
152
Bertrand SIMONNET71a62ef2014-10-07 11:26:25 -0700153 // Sets the product id.
Bertrand SIMONNET52e1d552015-08-04 15:06:21 -0700154 metrics_proto->set_product(9);
Bertrand SIMONNET71a62ef2014-10-07 11:26:25 -0700155
Bertrand SIMONNET46b49da2014-06-25 14:38:07 -0700156 metrics::SystemProfileProto* profile_proto =
157 metrics_proto->mutable_system_profile();
158 profile_proto->mutable_hardware()->set_hardware_class(
Bertrand SIMONNETe6b96d62015-10-30 13:04:40 -0700159 profile_.model_manifest_id);
Bertrand SIMONNET52e1d552015-08-04 15:06:21 -0700160 profile_proto->set_app_version(profile_.version);
Bertrand SIMONNET46b49da2014-06-25 14:38:07 -0700161 profile_proto->set_channel(profile_.channel);
Bertrand SIMONNET52e1d552015-08-04 15:06:21 -0700162 metrics::SystemProfileProto_BrilloDeviceData* device_data =
163 profile_proto->mutable_brillo();
Bertrand SIMONNET7dc78272015-10-06 15:27:37 -0700164 device_data->set_product_id(profile_.product_id);
Bertrand SIMONNET1f146552015-08-19 18:13:02 -0700165
166 return true;
Bertrand SIMONNET46b49da2014-06-25 14:38:07 -0700167}
168
Bertrand SIMONNET52e1d552015-08-04 15:06:21 -0700169std::string SystemProfileCache::GetPersistentGUID(
170 const std::string& filename) {
Bertrand SIMONNET46b49da2014-06-25 14:38:07 -0700171 std::string guid;
172 base::FilePath filepath(filename);
173 if (!base::ReadFileToString(filepath, &guid)) {
174 guid = base::GenerateGUID();
175 // If we can't read or write the file, the guid will not be preserved during
176 // the next reboot. Crash.
177 CHECK(base::WriteFile(filepath, guid.c_str(), guid.size()));
178 }
179 return guid;
180}
181
Bertrand SIMONNET46b49da2014-06-25 14:38:07 -0700182metrics::SystemProfileProto_Channel SystemProfileCache::ProtoChannelFromString(
183 const std::string& channel) {
Bertrand SIMONNETdc225c82015-11-12 14:04:03 -0800184 if (channel == "stable-channel") {
Bertrand SIMONNET46b49da2014-06-25 14:38:07 -0700185 return metrics::SystemProfileProto::CHANNEL_STABLE;
Bertrand SIMONNETdc225c82015-11-12 14:04:03 -0800186 } else if (channel == "dev-channel") {
Bertrand SIMONNET46b49da2014-06-25 14:38:07 -0700187 return metrics::SystemProfileProto::CHANNEL_DEV;
Bertrand SIMONNETdc225c82015-11-12 14:04:03 -0800188 } else if (channel == "beta-channel") {
Bertrand SIMONNET46b49da2014-06-25 14:38:07 -0700189 return metrics::SystemProfileProto::CHANNEL_BETA;
Bertrand SIMONNETdc225c82015-11-12 14:04:03 -0800190 } else if (channel == "canary-channel") {
Bertrand SIMONNET46b49da2014-06-25 14:38:07 -0700191 return metrics::SystemProfileProto::CHANNEL_CANARY;
192 }
193
194 DLOG(INFO) << "unknown channel: " << channel;
195 return metrics::SystemProfileProto::CHANNEL_UNKNOWN;
196}