blob: 8635fb0b5cbb9a2d42a033a65f10801b74082a77 [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 SIMONNET26993622015-08-20 14:08:41 -070024#include <cutils/properties.h>
Bertrand SIMONNET46b49da2014-06-25 14:38:07 -070025#include <string>
26#include <vector>
27
Bertrand SIMONNETbd3505e2015-08-04 14:04:51 -070028#include "constants.h"
Bertrand SIMONNET4b915ae2015-07-28 15:38:14 -070029#include "persistent_integer.h"
30#include "uploader/metrics_log_base.h"
31#include "uploader/proto/chrome_user_metrics_extension.pb.h"
Bertrand SIMONNET46b49da2014-06-25 14:38:07 -070032
Bertrand SIMONNET71a62ef2014-10-07 11:26:25 -070033namespace {
Bertrand SIMONNET46b49da2014-06-25 14:38:07 -070034
Bertrand SIMONNET71a62ef2014-10-07 11:26:25 -070035const char kPersistentSessionIdFilename[] = "Sysinfo.SessionId";
Bertrand SIMONNET71a62ef2014-10-07 11:26:25 -070036
37} // namespace
38
Bertrand SIMONNETa8bcc182014-12-19 09:35:15 -080039std::string ChannelToString(
40 const metrics::SystemProfileProto_Channel& channel) {
41 switch (channel) {
42 case metrics::SystemProfileProto::CHANNEL_STABLE:
43 return "STABLE";
44 case metrics::SystemProfileProto::CHANNEL_DEV:
45 return "DEV";
46 case metrics::SystemProfileProto::CHANNEL_BETA:
47 return "BETA";
48 case metrics::SystemProfileProto::CHANNEL_CANARY:
49 return "CANARY";
50 default:
51 return "UNKNOWN";
52 }
53}
Bertrand SIMONNET71a62ef2014-10-07 11:26:25 -070054
55SystemProfileCache::SystemProfileCache()
56 : initialized_(false),
57 testing_(false),
58 config_root_("/"),
59 session_id_(new chromeos_metrics::PersistentInteger(
60 kPersistentSessionIdFilename)) {
61}
62
63SystemProfileCache::SystemProfileCache(bool testing,
Bertrand SIMONNET12531862015-08-31 11:11:57 -070064 const base::FilePath& config_root)
Bertrand SIMONNET46b49da2014-06-25 14:38:07 -070065 : initialized_(false),
Bertrand SIMONNETeb815be2014-09-11 07:38:17 -070066 testing_(testing),
Bertrand SIMONNET71a62ef2014-10-07 11:26:25 -070067 config_root_(config_root),
Bertrand SIMONNET46b49da2014-06-25 14:38:07 -070068 session_id_(new chromeos_metrics::PersistentInteger(
69 kPersistentSessionIdFilename)) {
70}
71
72bool SystemProfileCache::Initialize() {
73 CHECK(!initialized_)
74 << "this should be called only once in the metrics_daemon lifetime.";
75
Bertrand SIMONNET12531862015-08-31 11:11:57 -070076 profile_.build_target_id = GetProperty(metrics::kBuildTargetIdProperty);
Bertrand SIMONNET26993622015-08-20 14:08:41 -070077
78 if (profile_.build_target_id.empty()) {
79 LOG(ERROR) << "System property " << metrics::kBuildTargetIdProperty
80 << " is not set.";
Bertrand SIMONNET46b49da2014-06-25 14:38:07 -070081 return false;
82 }
83
Bertrand SIMONNET12531862015-08-31 11:11:57 -070084 std::string channel = GetProperty(metrics::kChannelProperty);
85 profile_.version = GetProperty(metrics::kProductVersionProperty);
Bertrand SIMONNET26993622015-08-20 14:08:41 -070086
87 if (channel.empty() || profile_.version.empty()) {
Bertrand SIMONNETbae5dcc2015-08-04 14:12:10 -070088 // If the channel or version is missing, the image is not official.
89 // In this case, set the channel to unknown and the version to 0.0.0.0 to
90 // avoid polluting the production data.
91 channel = "";
92 profile_.version = metrics::kDefaultVersion;
Bertrand SIMONNETbae5dcc2015-08-04 14:12:10 -070093 }
Bertrand SIMONNET46b49da2014-06-25 14:38:07 -070094 profile_.client_id =
Bertrand SIMONNET52e1d552015-08-04 15:06:21 -070095 testing_ ? "client_id_test" :
96 GetPersistentGUID(metrics::kMetricsGUIDFilePath);
97 profile_.hardware_class = "unknown";
98 profile_.channel = ProtoChannelFromString(channel);
Bertrand SIMONNET46b49da2014-06-25 14:38:07 -070099
100 // Increment the session_id everytime we initialize this. If metrics_daemon
101 // does not crash, this should correspond to the number of reboots of the
102 // system.
Bertrand SIMONNET46b49da2014-06-25 14:38:07 -0700103 session_id_->Add(1);
Ben Chanf05ab402014-08-07 00:54:59 -0700104 profile_.session_id = static_cast<int32_t>(session_id_->Get());
Bertrand SIMONNET46b49da2014-06-25 14:38:07 -0700105
106 initialized_ = true;
107 return initialized_;
108}
109
110bool SystemProfileCache::InitializeOrCheck() {
111 return initialized_ || Initialize();
112}
113
Bertrand SIMONNET1f146552015-08-19 18:13:02 -0700114bool SystemProfileCache::Populate(
Bertrand SIMONNET46b49da2014-06-25 14:38:07 -0700115 metrics::ChromeUserMetricsExtension* metrics_proto) {
116 CHECK(metrics_proto);
Bertrand SIMONNET1f146552015-08-19 18:13:02 -0700117 if (not InitializeOrCheck()) {
118 return false;
119 }
Bertrand SIMONNET46b49da2014-06-25 14:38:07 -0700120
121 // The client id is hashed before being sent.
122 metrics_proto->set_client_id(
123 metrics::MetricsLogBase::Hash(profile_.client_id));
124 metrics_proto->set_session_id(profile_.session_id);
125
Bertrand SIMONNET71a62ef2014-10-07 11:26:25 -0700126 // Sets the product id.
Bertrand SIMONNET52e1d552015-08-04 15:06:21 -0700127 metrics_proto->set_product(9);
Bertrand SIMONNET71a62ef2014-10-07 11:26:25 -0700128
Bertrand SIMONNET46b49da2014-06-25 14:38:07 -0700129 metrics::SystemProfileProto* profile_proto =
130 metrics_proto->mutable_system_profile();
131 profile_proto->mutable_hardware()->set_hardware_class(
132 profile_.hardware_class);
Bertrand SIMONNET52e1d552015-08-04 15:06:21 -0700133 profile_proto->set_app_version(profile_.version);
Bertrand SIMONNET46b49da2014-06-25 14:38:07 -0700134 profile_proto->set_channel(profile_.channel);
Bertrand SIMONNET52e1d552015-08-04 15:06:21 -0700135 metrics::SystemProfileProto_BrilloDeviceData* device_data =
136 profile_proto->mutable_brillo();
137 device_data->set_build_target_id(profile_.build_target_id);
Bertrand SIMONNET1f146552015-08-19 18:13:02 -0700138
139 return true;
Bertrand SIMONNET46b49da2014-06-25 14:38:07 -0700140}
141
Bertrand SIMONNET52e1d552015-08-04 15:06:21 -0700142std::string SystemProfileCache::GetPersistentGUID(
143 const std::string& filename) {
Bertrand SIMONNET46b49da2014-06-25 14:38:07 -0700144 std::string guid;
145 base::FilePath filepath(filename);
146 if (!base::ReadFileToString(filepath, &guid)) {
147 guid = base::GenerateGUID();
148 // If we can't read or write the file, the guid will not be preserved during
149 // the next reboot. Crash.
150 CHECK(base::WriteFile(filepath, guid.c_str(), guid.size()));
151 }
152 return guid;
153}
154
Bertrand SIMONNET12531862015-08-31 11:11:57 -0700155std::string SystemProfileCache::GetProperty(const std::string& name) {
156 if (testing_) {
157 std::string content;
158 base::ReadFileToString(config_root_.Append(name), &content);
159 return content;
160 } else {
161 char value[PROPERTY_VALUE_MAX];
162 property_get(name.data(), value, "");
163 return std::string(value);
164 }
165}
166
Bertrand SIMONNET46b49da2014-06-25 14:38:07 -0700167metrics::SystemProfileProto_Channel SystemProfileCache::ProtoChannelFromString(
168 const std::string& channel) {
Bertrand SIMONNET52e1d552015-08-04 15:06:21 -0700169 if (channel == "stable") {
Bertrand SIMONNET46b49da2014-06-25 14:38:07 -0700170 return metrics::SystemProfileProto::CHANNEL_STABLE;
Bertrand SIMONNET52e1d552015-08-04 15:06:21 -0700171 } else if (channel == "dev") {
Bertrand SIMONNET46b49da2014-06-25 14:38:07 -0700172 return metrics::SystemProfileProto::CHANNEL_DEV;
Bertrand SIMONNET52e1d552015-08-04 15:06:21 -0700173 } else if (channel == "beta") {
Bertrand SIMONNET46b49da2014-06-25 14:38:07 -0700174 return metrics::SystemProfileProto::CHANNEL_BETA;
Bertrand SIMONNET52e1d552015-08-04 15:06:21 -0700175 } else if (channel == "canary") {
Bertrand SIMONNET46b49da2014-06-25 14:38:07 -0700176 return metrics::SystemProfileProto::CHANNEL_CANARY;
177 }
178
179 DLOG(INFO) << "unknown channel: " << channel;
180 return metrics::SystemProfileProto::CHANNEL_UNKNOWN;
181}