blob: 7c9d0c2849d9d51524f943599096f51b50f564d3 [file] [log] [blame]
Jay Srinivasane73acab2012-07-10 14:34:03 -07001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -07002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "update_engine/dbus_service.h"
Darin Petkova07586b2010-10-20 13:41:15 -07006
Alex Deymof4867c42013-06-28 14:41:39 -07007#include <set>
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -07008#include <string>
Darin Petkova07586b2010-10-20 13:41:15 -07009
Alex Deymob7ca0962014-10-01 17:58:07 -070010#include <base/location.h>
Darin Petkova07586b2010-10-20 13:41:15 -070011#include <base/logging.h>
Alex Vakulenko2bddadd2014-03-27 13:23:46 -070012#include <base/strings/stringprintf.h>
Alex Deymob7ca0962014-10-01 17:58:07 -070013#include <chromeos/bind_lambda.h>
14#include <chromeos/message_loops/message_loop.h>
Gilad Arnoldccd09572014-10-27 13:37:50 -070015#include <chromeos/strings/string_utils.h>
Jay Srinivasan1c0fe792013-03-28 16:45:25 -070016#include <policy/device_policy.h>
Darin Petkova07586b2010-10-20 13:41:15 -070017
David Zeuthen3c55abd2013-10-14 12:48:03 -070018#include "update_engine/clock_interface.h"
Alex Deymof6ee0162015-07-31 12:35:22 -070019#include "update_engine/connection_manager_interface.h"
David Zeuthen75a4c3e2013-09-06 11:36:59 -070020#include "update_engine/dbus_constants.h"
J. Richard Barnette056b0ab2013-10-29 15:24:56 -070021#include "update_engine/hardware_interface.h"
Darin Petkov49d91322010-10-25 16:34:58 -070022#include "update_engine/omaha_request_params.h"
Alex Deymo5fdf7762013-07-17 20:01:40 -070023#include "update_engine/p2p_manager.h"
Alex Deymof4867c42013-06-28 14:41:39 -070024#include "update_engine/prefs.h"
J. Richard Barnette056b0ab2013-10-29 15:24:56 -070025#include "update_engine/update_attempter.h"
Darin Petkova07586b2010-10-20 13:41:15 -070026#include "update_engine/utils.h"
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -070027
Gilad Arnoldccd09572014-10-27 13:37:50 -070028using base::StringPrintf;
Alex Deymob7ca0962014-10-01 17:58:07 -070029using chromeos::ErrorPtr;
Gilad Arnoldccd09572014-10-27 13:37:50 -070030using chromeos::string_utils::ToString;
David Zeuthen75a4c3e2013-09-06 11:36:59 -070031using chromeos_update_engine::AttemptUpdateFlags;
32using chromeos_update_engine::kAttemptUpdateFlagNonInteractive;
Alex Deymof329b932014-10-30 01:37:48 -070033using std::set;
34using std::string;
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -070035
Alex Deymob7ca0962014-10-01 17:58:07 -070036namespace {
37// Log and set the error on the passed ErrorPtr.
38void LogAndSetError(ErrorPtr *error,
39 const tracked_objects::Location& location,
40 const string& reason) {
41 chromeos::Error::AddTo(
42 error, location,
43 chromeos::errors::dbus::kDomain,
44 chromeos_update_engine::kUpdateEngineServiceErrorFailed, reason);
45 LOG(ERROR) << "Sending DBus Failure: " << location.ToString() << ": "
46 << reason;
47}
48} // namespace
Don Garrettbb26fc82013-11-15 10:40:17 -080049
Alex Deymob7ca0962014-10-01 17:58:07 -070050namespace chromeos_update_engine {
Don Garrettbb26fc82013-11-15 10:40:17 -080051
Alex Deymob7ca0962014-10-01 17:58:07 -070052UpdateEngineService::UpdateEngineService(SystemState* system_state)
53 : system_state_(system_state) {}
Don Garrettbb26fc82013-11-15 10:40:17 -080054
Alex Deymob7ca0962014-10-01 17:58:07 -070055// org::chromium::UpdateEngineInterfaceInterface methods implementation.
Don Garrettbb26fc82013-11-15 10:40:17 -080056
Alex Deymob7ca0962014-10-01 17:58:07 -070057bool UpdateEngineService::AttemptUpdate(ErrorPtr* error,
58 const string& in_app_version,
59 const string& in_omaha_url) {
60 return AttemptUpdateWithFlags(
61 error, in_app_version, in_omaha_url, 0 /* no flags */);
Don Garrettbb26fc82013-11-15 10:40:17 -080062}
63
Alex Deymob7ca0962014-10-01 17:58:07 -070064bool UpdateEngineService::AttemptUpdateWithFlags(ErrorPtr* /* error */,
65 const string& in_app_version,
66 const string& in_omaha_url,
67 int32_t in_flags_as_int) {
68 AttemptUpdateFlags flags = static_cast<AttemptUpdateFlags>(in_flags_as_int);
David Pursell02c18642014-11-06 11:26:11 -080069 bool interactive = !(flags & kAttemptUpdateFlagNonInteractive);
Jay Srinivasane73acab2012-07-10 14:34:03 -070070
Alex Deymob7ca0962014-10-01 17:58:07 -070071 LOG(INFO) << "Attempt update: app_version=\"" << in_app_version << "\" "
72 << "omaha_url=\"" << in_omaha_url << "\" "
David Zeuthen75a4c3e2013-09-06 11:36:59 -070073 << "flags=0x" << std::hex << flags << " "
Gilad Arnoldb92f0df2013-01-10 16:32:45 -080074 << "interactive=" << (interactive? "yes" : "no");
Alex Deymob7ca0962014-10-01 17:58:07 -070075 system_state_->update_attempter()->CheckForUpdate(
76 in_app_version, in_omaha_url, interactive);
77 return true;
Darin Petkov296889c2010-07-23 16:20:54 -070078}
79
Alex Deymob7ca0962014-10-01 17:58:07 -070080bool UpdateEngineService::AttemptRollback(ErrorPtr* error,
81 bool in_powerwash) {
Chris Sosad317e402013-06-12 13:47:09 -070082 LOG(INFO) << "Attempting rollback to non-active partitions.";
Don Garrettbb26fc82013-11-15 10:40:17 -080083
Alex Deymob7ca0962014-10-01 17:58:07 -070084 if (!system_state_->update_attempter()->Rollback(in_powerwash)) {
Don Garrettbb26fc82013-11-15 10:40:17 -080085 // TODO(dgarrett): Give a more specific error code/reason.
Alex Deymob7ca0962014-10-01 17:58:07 -070086 LogAndSetError(error, FROM_HERE, "Rollback attempt failed.");
87 return false;
Don Garrettbb26fc82013-11-15 10:40:17 -080088 }
Alex Deymob7ca0962014-10-01 17:58:07 -070089 return true;
Chris Sosad317e402013-06-12 13:47:09 -070090}
91
Alex Deymob7ca0962014-10-01 17:58:07 -070092bool UpdateEngineService::CanRollback(ErrorPtr* /* error */,
93 bool* out_can_rollback) {
94 bool can_rollback = system_state_->update_attempter()->CanRollback();
Chris Sosa44b9b7e2014-04-02 13:53:46 -070095 LOG(INFO) << "Checking to see if we can rollback . Result: " << can_rollback;
Alex Vakulenko2bddadd2014-03-27 13:23:46 -070096 *out_can_rollback = can_rollback;
Alex Deymob7ca0962014-10-01 17:58:07 -070097 return true;
Alex Vakulenko2bddadd2014-03-27 13:23:46 -070098}
99
Alex Deymob7ca0962014-10-01 17:58:07 -0700100bool UpdateEngineService::ResetStatus(ErrorPtr* error) {
101 if (!system_state_->update_attempter()->ResetStatus()) {
Don Garrettbb26fc82013-11-15 10:40:17 -0800102 // TODO(dgarrett): Give a more specific error code/reason.
Alex Deymob7ca0962014-10-01 17:58:07 -0700103 LogAndSetError(error, FROM_HERE, "ResetStatus failed.");
104 return false;
Don Garrettbb26fc82013-11-15 10:40:17 -0800105 }
Alex Deymob7ca0962014-10-01 17:58:07 -0700106 return true;
Don Garrettbb26fc82013-11-15 10:40:17 -0800107}
Jay Srinivasanc1ba09a2012-08-14 14:15:57 -0700108
Alex Deymob7ca0962014-10-01 17:58:07 -0700109bool UpdateEngineService::GetStatus(ErrorPtr* error,
110 int64_t* out_last_checked_time,
111 double* out_progress,
112 string* out_current_operation,
113 string* out_new_version,
114 int64_t* out_new_size) {
115 if (!system_state_->update_attempter()->GetStatus(out_last_checked_time,
116 out_progress,
117 out_current_operation,
118 out_new_version,
119 out_new_size)) {
120 LogAndSetError(error, FROM_HERE, "GetStatus failed.");
121 return false;
Chris Masonec6c57a52010-09-23 13:06:14 -0700122 }
Alex Deymob7ca0962014-10-01 17:58:07 -0700123 return true;
Andrew de los Reyes4e9b9f42010-04-26 15:06:43 -0700124}
125
Alex Deymob7ca0962014-10-01 17:58:07 -0700126bool UpdateEngineService::RebootIfNeeded(ErrorPtr* error) {
127 if (!system_state_->update_attempter()->RebootIfNeeded()) {
Don Garrettbb26fc82013-11-15 10:40:17 -0800128 // TODO(dgarrett): Give a more specific error code/reason.
Alex Deymob7ca0962014-10-01 17:58:07 -0700129 LogAndSetError(error, FROM_HERE, "Reboot not needed, or attempt failed.");
130 return false;
Darin Petkov296889c2010-07-23 16:20:54 -0700131 }
Alex Deymob7ca0962014-10-01 17:58:07 -0700132 return true;
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700133}
134
Alex Deymob7ca0962014-10-01 17:58:07 -0700135bool UpdateEngineService::SetChannel(ErrorPtr* error,
136 const string& in_target_channel,
137 bool in_is_powerwash_allowed) {
138 const policy::DevicePolicy* device_policy = system_state_->device_policy();
Chris Sosacb7fa882013-07-25 17:02:59 -0700139
140 // The device_policy is loaded in a lazy way before an update check. Load it
141 // now from the libchromeos cache if it wasn't already loaded.
Jay Srinivasan1c0fe792013-03-28 16:45:25 -0700142 if (!device_policy) {
Alex Deymob7ca0962014-10-01 17:58:07 -0700143 UpdateAttempter* update_attempter = system_state_->update_attempter();
Chris Sosacb7fa882013-07-25 17:02:59 -0700144 if (update_attempter) {
145 update_attempter->RefreshDevicePolicy();
Alex Deymob7ca0962014-10-01 17:58:07 -0700146 device_policy = system_state_->device_policy();
Chris Sosacb7fa882013-07-25 17:02:59 -0700147 }
Darin Petkov8daa3242010-10-25 13:28:47 -0700148 }
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700149
150 bool delegated = false;
Chris Sosacb7fa882013-07-25 17:02:59 -0700151 if (device_policy &&
152 device_policy->GetReleaseChannelDelegated(&delegated) && !delegated) {
Alex Deymob7ca0962014-10-01 17:58:07 -0700153 LogAndSetError(
154 error, FROM_HERE,
Don Garrettbb26fc82013-11-15 10:40:17 -0800155 "Cannot set target channel explicitly when channel "
156 "policy/settings is not delegated");
Alex Deymob7ca0962014-10-01 17:58:07 -0700157 return false;
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700158 }
159
Alex Deymob7ca0962014-10-01 17:58:07 -0700160 LOG(INFO) << "Setting destination channel to: " << in_target_channel;
161 if (!system_state_->request_params()->SetTargetChannel(
162 in_target_channel, in_is_powerwash_allowed)) {
Don Garrettbb26fc82013-11-15 10:40:17 -0800163 // TODO(dgarrett): Give a more specific error code/reason.
Alex Deymob7ca0962014-10-01 17:58:07 -0700164 LogAndSetError(error, FROM_HERE, "Setting channel failed.");
165 return false;
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700166 }
Alex Deymob7ca0962014-10-01 17:58:07 -0700167 return true;
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700168}
169
Alex Deymob7ca0962014-10-01 17:58:07 -0700170bool UpdateEngineService::GetChannel(ErrorPtr* /* error */,
171 bool in_get_current_channel,
172 string* out_channel) {
173 OmahaRequestParams* rp = system_state_->request_params();
174 *out_channel = (in_get_current_channel ?
175 rp->current_channel() : rp->target_channel());
176 return true;
Darin Petkov8daa3242010-10-25 13:28:47 -0700177}
178
Alex Deymob7ca0962014-10-01 17:58:07 -0700179bool UpdateEngineService::SetP2PUpdatePermission(ErrorPtr* error,
180 bool in_enabled) {
181 PrefsInterface* prefs = system_state_->prefs();
Alex Deymo5fdf7762013-07-17 20:01:40 -0700182
Alex Deymob7ca0962014-10-01 17:58:07 -0700183 if (!prefs->SetBoolean(kPrefsP2PEnabled, in_enabled)) {
184 LogAndSetError(
185 error, FROM_HERE,
Gilad Arnoldccd09572014-10-27 13:37:50 -0700186 StringPrintf("Error setting the update via p2p permission to %s.",
Alex Deymob7ca0962014-10-01 17:58:07 -0700187 ToString(in_enabled).c_str()));
188 return false;
Alex Deymo5fdf7762013-07-17 20:01:40 -0700189 }
Alex Deymob7ca0962014-10-01 17:58:07 -0700190 return true;
Alex Deymo5fdf7762013-07-17 20:01:40 -0700191}
192
Alex Deymob7ca0962014-10-01 17:58:07 -0700193bool UpdateEngineService::GetP2PUpdatePermission(ErrorPtr* error,
194 bool* out_enabled) {
195 PrefsInterface* prefs = system_state_->prefs();
Alex Deymo5fdf7762013-07-17 20:01:40 -0700196
Gilad Arnold367a3ad2014-10-23 16:00:17 -0700197 bool p2p_pref = false; // Default if no setting is present.
Alex Deymob7ca0962014-10-01 17:58:07 -0700198 if (prefs->Exists(kPrefsP2PEnabled) &&
199 !prefs->GetBoolean(kPrefsP2PEnabled, &p2p_pref)) {
200 LogAndSetError(error, FROM_HERE, "Error getting the P2PEnabled setting.");
201 return false;
Alex Deymo5fdf7762013-07-17 20:01:40 -0700202 }
203
Alex Deymob7ca0962014-10-01 17:58:07 -0700204 *out_enabled = p2p_pref;
205 return true;
Alex Deymo5fdf7762013-07-17 20:01:40 -0700206}
207
Alex Deymob7ca0962014-10-01 17:58:07 -0700208bool UpdateEngineService::SetUpdateOverCellularPermission(ErrorPtr* error,
209 bool in_allowed) {
Alex Deymof4867c42013-06-28 14:41:39 -0700210 set<string> allowed_types;
Alex Deymob7ca0962014-10-01 17:58:07 -0700211 const policy::DevicePolicy* device_policy = system_state_->device_policy();
Alex Deymof4867c42013-06-28 14:41:39 -0700212
213 // The device_policy is loaded in a lazy way before an update check. Load it
214 // now from the libchromeos cache if it wasn't already loaded.
215 if (!device_policy) {
Alex Deymob7ca0962014-10-01 17:58:07 -0700216 UpdateAttempter* update_attempter = system_state_->update_attempter();
Alex Deymof4867c42013-06-28 14:41:39 -0700217 if (update_attempter) {
218 update_attempter->RefreshDevicePolicy();
Alex Deymob7ca0962014-10-01 17:58:07 -0700219 device_policy = system_state_->device_policy();
Alex Deymof4867c42013-06-28 14:41:39 -0700220 }
221 }
222
223 // Check if this setting is allowed by the device policy.
224 if (device_policy &&
225 device_policy->GetAllowedConnectionTypesForUpdate(&allowed_types)) {
Alex Deymob7ca0962014-10-01 17:58:07 -0700226 LogAndSetError(error, FROM_HERE,
227 "Ignoring the update over cellular setting since there's "
228 "a device policy enforcing this setting.");
229 return false;
Alex Deymof4867c42013-06-28 14:41:39 -0700230 }
231
232 // If the policy wasn't loaded yet, then it is still OK to change the local
233 // setting because the policy will be checked again during the update check.
234
Alex Deymob7ca0962014-10-01 17:58:07 -0700235 PrefsInterface* prefs = system_state_->prefs();
Alex Deymof4867c42013-06-28 14:41:39 -0700236
Alex Deymob7ca0962014-10-01 17:58:07 -0700237 if (!prefs->SetBoolean(kPrefsUpdateOverCellularPermission, in_allowed)) {
238 LogAndSetError(error, FROM_HERE,
239 string("Error setting the update over cellular to ") +
240 (in_allowed ? "true" : "false"));
241 return false;
Alex Deymof4867c42013-06-28 14:41:39 -0700242 }
Alex Deymob7ca0962014-10-01 17:58:07 -0700243 return true;
Alex Deymof4867c42013-06-28 14:41:39 -0700244}
245
Alex Deymob7ca0962014-10-01 17:58:07 -0700246bool UpdateEngineService::GetUpdateOverCellularPermission(ErrorPtr* /* error */,
247 bool* out_allowed) {
248 ConnectionManagerInterface* cm = system_state_->connection_manager();
Alex Deymof4867c42013-06-28 14:41:39 -0700249
250 // The device_policy is loaded in a lazy way before an update check and is
251 // used to determine if an update is allowed over cellular. Load the device
252 // policy now from the libchromeos cache if it wasn't already loaded.
Alex Deymob7ca0962014-10-01 17:58:07 -0700253 if (!system_state_->device_policy()) {
254 UpdateAttempter* update_attempter = system_state_->update_attempter();
Alex Deymof4867c42013-06-28 14:41:39 -0700255 if (update_attempter)
256 update_attempter->RefreshDevicePolicy();
257 }
258
259 // Return the current setting based on the same logic used while checking for
260 // updates. A log message could be printed as the result of this test.
261 LOG(INFO) << "Checking if updates over cellular networks are allowed:";
Alex Deymob7ca0962014-10-01 17:58:07 -0700262 *out_allowed = cm->IsUpdateAllowedOver(
Alex Deymo75eac7e2015-07-29 13:39:14 -0700263 chromeos_update_engine::NetworkConnectionType::kCellular,
Alex Deymo6ae91202014-03-10 19:21:25 -0700264 chromeos_update_engine::NetworkTethering::kUnknown);
Alex Deymob7ca0962014-10-01 17:58:07 -0700265 return true;
Alex Deymof4867c42013-06-28 14:41:39 -0700266}
267
Alex Deymob7ca0962014-10-01 17:58:07 -0700268bool UpdateEngineService::GetDurationSinceUpdate(ErrorPtr* error,
269 int64_t* out_usec_wallclock) {
David Zeuthen3c55abd2013-10-14 12:48:03 -0700270 base::Time time;
Alex Deymob7ca0962014-10-01 17:58:07 -0700271 if (!system_state_->update_attempter()->GetBootTimeAtUpdate(&time)) {
272 LogAndSetError(error, FROM_HERE, "No pending update.");
273 return false;
Don Garrettbb26fc82013-11-15 10:40:17 -0800274 }
David Zeuthen3c55abd2013-10-14 12:48:03 -0700275
Alex Deymob7ca0962014-10-01 17:58:07 -0700276 ClockInterface* clock = system_state_->clock();
David Zeuthen3c55abd2013-10-14 12:48:03 -0700277 *out_usec_wallclock = (clock->GetBootTime() - time).InMicroseconds();
Alex Deymob7ca0962014-10-01 17:58:07 -0700278 return true;
David Zeuthen3c55abd2013-10-14 12:48:03 -0700279}
280
Alex Deymob7ca0962014-10-01 17:58:07 -0700281bool UpdateEngineService::GetPrevVersion(ErrorPtr* /* error */,
282 string* out_prev_version) {
283 *out_prev_version = system_state_->update_attempter()->GetPrevVersion();
284 return true;
Andrew de los Reyes63b96d72010-05-10 13:08:54 -0700285}
Alex Vakulenkodea2eac2014-03-14 15:56:59 -0700286
Alex Deymob7ca0962014-10-01 17:58:07 -0700287bool UpdateEngineService::GetKernelDevices(ErrorPtr* /* error */,
288 string* out_kernel_devices) {
289 auto devices = system_state_->update_attempter()->GetKernelDevices();
290 string info;
291 for (const auto& device : devices) {
292 base::StringAppendF(&info, "%d:%s\n",
293 device.second ? 1 : 0, device.first.c_str());
294 }
295 LOG(INFO) << "Available kernel devices: " << info;
296 *out_kernel_devices = info;
297 return true;
Alex Vakulenkodea2eac2014-03-14 15:56:59 -0700298}
Alex Deymob7ca0962014-10-01 17:58:07 -0700299
300bool UpdateEngineService::GetRollbackPartition(
301 ErrorPtr* /* error */,
302 string* out_rollback_partition_name) {
303 string name = system_state_->update_attempter()->GetRollbackPartition();
304 LOG(INFO) << "Getting rollback partition name. Result: " << name;
305 *out_rollback_partition_name = name;
306 return true;
307}
308
309
310UpdateEngineAdaptor::UpdateEngineAdaptor(SystemState* system_state,
311 const scoped_refptr<dbus::Bus>& bus)
312 : org::chromium::UpdateEngineInterfaceAdaptor(&dbus_service_),
313 bus_(bus),
314 dbus_service_(system_state),
315 dbus_object_(nullptr, bus, dbus::ObjectPath(kUpdateEngineServicePath)) {}
316
317void UpdateEngineAdaptor::RegisterAsync(
318 const base::Callback<void(bool)>& completion_callback) {
319 RegisterWithDBusObject(&dbus_object_);
320 dbus_object_.RegisterAsync(completion_callback);
321}
322
323bool UpdateEngineAdaptor::RequestOwnership() {
324 return bus_->RequestOwnershipAndBlock(kUpdateEngineServiceName,
325 dbus::Bus::REQUIRE_PRIMARY);
326}
327
328} // namespace chromeos_update_engine