blob: e3f63398f68a94b4a144ad3b722f8ed536606407 [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),
Bertrand SIMONNET2765d0a2015-09-09 10:38:20 -070058 metrics_directory_(metrics::kMetricsDirectory),
Bertrand SIMONNET71a62ef2014-10-07 11:26:25 -070059 session_id_(new chromeos_metrics::PersistentInteger(
60 kPersistentSessionIdFilename)) {
61}
62
63SystemProfileCache::SystemProfileCache(bool testing,
Bertrand SIMONNET2765d0a2015-09-09 10:38:20 -070064 const base::FilePath& metrics_directory)
Bertrand SIMONNET46b49da2014-06-25 14:38:07 -070065 : initialized_(false),
Bertrand SIMONNETeb815be2014-09-11 07:38:17 -070066 testing_(testing),
Bertrand SIMONNET2765d0a2015-09-09 10:38:20 -070067 metrics_directory_(metrics_directory),
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 SIMONNET2765d0a2015-09-09 10:38:20 -070094 std::string guid_path = metrics_directory_.Append(
95 metrics::kMetricsGUIDFileName).value();
96 profile_.client_id = testing_ ?
97 "client_id_test" :
98 GetPersistentGUID(guid_path);
Bertrand SIMONNET52e1d552015-08-04 15:06:21 -070099 profile_.hardware_class = "unknown";
100 profile_.channel = ProtoChannelFromString(channel);
Bertrand SIMONNET46b49da2014-06-25 14:38:07 -0700101
102 // Increment the session_id everytime we initialize this. If metrics_daemon
103 // does not crash, this should correspond to the number of reboots of the
104 // system.
Bertrand SIMONNET46b49da2014-06-25 14:38:07 -0700105 session_id_->Add(1);
Ben Chanf05ab402014-08-07 00:54:59 -0700106 profile_.session_id = static_cast<int32_t>(session_id_->Get());
Bertrand SIMONNET46b49da2014-06-25 14:38:07 -0700107
108 initialized_ = true;
109 return initialized_;
110}
111
112bool SystemProfileCache::InitializeOrCheck() {
113 return initialized_ || Initialize();
114}
115
Bertrand SIMONNET1f146552015-08-19 18:13:02 -0700116bool SystemProfileCache::Populate(
Bertrand SIMONNET46b49da2014-06-25 14:38:07 -0700117 metrics::ChromeUserMetricsExtension* metrics_proto) {
118 CHECK(metrics_proto);
Bertrand SIMONNET1f146552015-08-19 18:13:02 -0700119 if (not InitializeOrCheck()) {
120 return false;
121 }
Bertrand SIMONNET46b49da2014-06-25 14:38:07 -0700122
123 // The client id is hashed before being sent.
124 metrics_proto->set_client_id(
125 metrics::MetricsLogBase::Hash(profile_.client_id));
126 metrics_proto->set_session_id(profile_.session_id);
127
Bertrand SIMONNET71a62ef2014-10-07 11:26:25 -0700128 // Sets the product id.
Bertrand SIMONNET52e1d552015-08-04 15:06:21 -0700129 metrics_proto->set_product(9);
Bertrand SIMONNET71a62ef2014-10-07 11:26:25 -0700130
Bertrand SIMONNET46b49da2014-06-25 14:38:07 -0700131 metrics::SystemProfileProto* profile_proto =
132 metrics_proto->mutable_system_profile();
133 profile_proto->mutable_hardware()->set_hardware_class(
134 profile_.hardware_class);
Bertrand SIMONNET52e1d552015-08-04 15:06:21 -0700135 profile_proto->set_app_version(profile_.version);
Bertrand SIMONNET46b49da2014-06-25 14:38:07 -0700136 profile_proto->set_channel(profile_.channel);
Bertrand SIMONNET52e1d552015-08-04 15:06:21 -0700137 metrics::SystemProfileProto_BrilloDeviceData* device_data =
138 profile_proto->mutable_brillo();
139 device_data->set_build_target_id(profile_.build_target_id);
Bertrand SIMONNET1f146552015-08-19 18:13:02 -0700140
141 return true;
Bertrand SIMONNET46b49da2014-06-25 14:38:07 -0700142}
143
Bertrand SIMONNET52e1d552015-08-04 15:06:21 -0700144std::string SystemProfileCache::GetPersistentGUID(
145 const std::string& filename) {
Bertrand SIMONNET46b49da2014-06-25 14:38:07 -0700146 std::string guid;
147 base::FilePath filepath(filename);
148 if (!base::ReadFileToString(filepath, &guid)) {
149 guid = base::GenerateGUID();
150 // If we can't read or write the file, the guid will not be preserved during
151 // the next reboot. Crash.
152 CHECK(base::WriteFile(filepath, guid.c_str(), guid.size()));
153 }
154 return guid;
155}
156
Bertrand SIMONNET12531862015-08-31 11:11:57 -0700157std::string SystemProfileCache::GetProperty(const std::string& name) {
158 if (testing_) {
159 std::string content;
Bertrand SIMONNET2765d0a2015-09-09 10:38:20 -0700160 base::ReadFileToString(metrics_directory_.Append(name), &content);
Bertrand SIMONNET12531862015-08-31 11:11:57 -0700161 return content;
162 } else {
163 char value[PROPERTY_VALUE_MAX];
164 property_get(name.data(), value, "");
165 return std::string(value);
166 }
167}
168
Bertrand SIMONNET46b49da2014-06-25 14:38:07 -0700169metrics::SystemProfileProto_Channel SystemProfileCache::ProtoChannelFromString(
170 const std::string& channel) {
Bertrand SIMONNET52e1d552015-08-04 15:06:21 -0700171 if (channel == "stable") {
Bertrand SIMONNET46b49da2014-06-25 14:38:07 -0700172 return metrics::SystemProfileProto::CHANNEL_STABLE;
Bertrand SIMONNET52e1d552015-08-04 15:06:21 -0700173 } else if (channel == "dev") {
Bertrand SIMONNET46b49da2014-06-25 14:38:07 -0700174 return metrics::SystemProfileProto::CHANNEL_DEV;
Bertrand SIMONNET52e1d552015-08-04 15:06:21 -0700175 } else if (channel == "beta") {
Bertrand SIMONNET46b49da2014-06-25 14:38:07 -0700176 return metrics::SystemProfileProto::CHANNEL_BETA;
Bertrand SIMONNET52e1d552015-08-04 15:06:21 -0700177 } else if (channel == "canary") {
Bertrand SIMONNET46b49da2014-06-25 14:38:07 -0700178 return metrics::SystemProfileProto::CHANNEL_CANARY;
179 }
180
181 DLOG(INFO) << "unknown channel: " << channel;
182 return metrics::SystemProfileProto::CHANNEL_UNKNOWN;
183}