1// 2// Copyright (C) 2012 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// 16 17#include "update_engine/common_service.h" 18 19#include <set> 20#include <string> 21 22#include <base/location.h> 23#include <base/logging.h> 24#include <base/strings/stringprintf.h> 25#include <brillo/bind_lambda.h> 26#include <brillo/message_loops/message_loop.h> 27#include <brillo/strings/string_utils.h> 28#include <policy/device_policy.h> 29 30#include "update_engine/common/clock_interface.h" 31#include "update_engine/common/hardware_interface.h" 32#include "update_engine/common/prefs.h" 33#include "update_engine/common/utils.h" 34#include "update_engine/connection_manager_interface.h" 35#include "update_engine/omaha_request_params.h" 36#include "update_engine/p2p_manager.h" 37#include "update_engine/update_attempter.h" 38#include "update_engine/payload_state_interface.h" 39 40using base::StringPrintf; 41using brillo::ErrorPtr; 42using brillo::string_utils::ToString; 43using std::set; 44using std::string; 45 46namespace chromeos_update_engine { 47 48namespace { 49// Log and set the error on the passed ErrorPtr. 50void LogAndSetError(ErrorPtr* error, 51 const tracked_objects::Location& location, 52 const string& reason) { 53 brillo::Error::AddTo(error, 54 location, 55 UpdateEngineService::kErrorDomain, 56 UpdateEngineService::kErrorFailed, 57 reason); 58 LOG(ERROR) << "Sending Update Engine Failure: " << location.ToString() << ": " 59 << reason; 60} 61} // namespace 62 63const char* const UpdateEngineService::kErrorDomain = "update_engine"; 64const char* const UpdateEngineService::kErrorFailed = 65 "org.chromium.UpdateEngine.Error.Failed"; 66 67UpdateEngineService::UpdateEngineService(SystemState* system_state) 68 : system_state_(system_state) { 69} 70 71// org::chromium::UpdateEngineInterfaceInterface methods implementation. 72 73bool UpdateEngineService::AttemptUpdate(ErrorPtr* /* error */, 74 const string& in_app_version, 75 const string& in_omaha_url, 76 int32_t in_flags_as_int) { 77 AttemptUpdateFlags flags = static_cast<AttemptUpdateFlags>(in_flags_as_int); 78 bool interactive = !(flags & kAttemptUpdateFlagNonInteractive); 79 80 LOG(INFO) << "Attempt update: app_version=\"" << in_app_version << "\" " 81 << "omaha_url=\"" << in_omaha_url << "\" " 82 << "flags=0x" << std::hex << flags << " " 83 << "interactive=" << (interactive ? "yes" : "no"); 84 system_state_->update_attempter()->CheckForUpdate( 85 in_app_version, in_omaha_url, interactive); 86 return true; 87} 88 89bool UpdateEngineService::AttemptRollback(ErrorPtr* error, bool in_powerwash) { 90 LOG(INFO) << "Attempting rollback to non-active partitions."; 91 92 if (!system_state_->update_attempter()->Rollback(in_powerwash)) { 93 // TODO(dgarrett): Give a more specific error code/reason. 94 LogAndSetError(error, FROM_HERE, "Rollback attempt failed."); 95 return false; 96 } 97 return true; 98} 99 100bool UpdateEngineService::CanRollback(ErrorPtr* /* error */, 101 bool* out_can_rollback) { 102 bool can_rollback = system_state_->update_attempter()->CanRollback(); 103 LOG(INFO) << "Checking to see if we can rollback . Result: " << can_rollback; 104 *out_can_rollback = can_rollback; 105 return true; 106} 107 108bool UpdateEngineService::ResetStatus(ErrorPtr* error) { 109 if (!system_state_->update_attempter()->ResetStatus()) { 110 // TODO(dgarrett): Give a more specific error code/reason. 111 LogAndSetError(error, FROM_HERE, "ResetStatus failed."); 112 return false; 113 } 114 return true; 115} 116 117bool UpdateEngineService::GetStatus(ErrorPtr* error, 118 int64_t* out_last_checked_time, 119 double* out_progress, 120 string* out_current_operation, 121 string* out_new_version, 122 int64_t* out_new_size) { 123 if (!system_state_->update_attempter()->GetStatus(out_last_checked_time, 124 out_progress, 125 out_current_operation, 126 out_new_version, 127 out_new_size)) { 128 LogAndSetError(error, FROM_HERE, "GetStatus failed."); 129 return false; 130 } 131 return true; 132} 133 134bool UpdateEngineService::RebootIfNeeded(ErrorPtr* error) { 135 if (!system_state_->update_attempter()->RebootIfNeeded()) { 136 // TODO(dgarrett): Give a more specific error code/reason. 137 LogAndSetError(error, FROM_HERE, "Reboot not needed, or attempt failed."); 138 return false; 139 } 140 return true; 141} 142 143bool UpdateEngineService::SetChannel(ErrorPtr* error, 144 const string& in_target_channel, 145 bool in_is_powerwash_allowed) { 146 const policy::DevicePolicy* device_policy = system_state_->device_policy(); 147 148 // The device_policy is loaded in a lazy way before an update check. Load it 149 // now from the libbrillo cache if it wasn't already loaded. 150 if (!device_policy) { 151 UpdateAttempter* update_attempter = system_state_->update_attempter(); 152 if (update_attempter) { 153 update_attempter->RefreshDevicePolicy(); 154 device_policy = system_state_->device_policy(); 155 } 156 } 157 158 bool delegated = false; 159 if (device_policy && device_policy->GetReleaseChannelDelegated(&delegated) && 160 !delegated) { 161 LogAndSetError(error, 162 FROM_HERE, 163 "Cannot set target channel explicitly when channel " 164 "policy/settings is not delegated"); 165 return false; 166 } 167 168 LOG(INFO) << "Setting destination channel to: " << in_target_channel; 169 string error_message; 170 if (!system_state_->request_params()->SetTargetChannel( 171 in_target_channel, in_is_powerwash_allowed, &error_message)) { 172 LogAndSetError(error, FROM_HERE, error_message); 173 return false; 174 } 175 // Update the weave state because updated the target channel. 176 system_state_->update_attempter()->BroadcastChannel(); 177 return true; 178} 179 180bool UpdateEngineService::GetChannel(ErrorPtr* /* error */, 181 bool in_get_current_channel, 182 string* out_channel) { 183 OmahaRequestParams* rp = system_state_->request_params(); 184 *out_channel = 185 (in_get_current_channel ? rp->current_channel() : rp->target_channel()); 186 return true; 187} 188 189bool UpdateEngineService::SetP2PUpdatePermission(ErrorPtr* error, 190 bool in_enabled) { 191 PrefsInterface* prefs = system_state_->prefs(); 192 193 if (!prefs->SetBoolean(kPrefsP2PEnabled, in_enabled)) { 194 LogAndSetError( 195 error, 196 FROM_HERE, 197 StringPrintf("Error setting the update via p2p permission to %s.", 198 ToString(in_enabled).c_str())); 199 return false; 200 } 201 return true; 202} 203 204bool UpdateEngineService::GetP2PUpdatePermission(ErrorPtr* error, 205 bool* out_enabled) { 206 PrefsInterface* prefs = system_state_->prefs(); 207 208 bool p2p_pref = false; // Default if no setting is present. 209 if (prefs->Exists(kPrefsP2PEnabled) && 210 !prefs->GetBoolean(kPrefsP2PEnabled, &p2p_pref)) { 211 LogAndSetError(error, FROM_HERE, "Error getting the P2PEnabled setting."); 212 return false; 213 } 214 215 *out_enabled = p2p_pref; 216 return true; 217} 218 219bool UpdateEngineService::SetUpdateOverCellularPermission(ErrorPtr* error, 220 bool in_allowed) { 221 set<string> allowed_types; 222 const policy::DevicePolicy* device_policy = system_state_->device_policy(); 223 224 // The device_policy is loaded in a lazy way before an update check. Load it 225 // now from the libbrillo cache if it wasn't already loaded. 226 if (!device_policy) { 227 UpdateAttempter* update_attempter = system_state_->update_attempter(); 228 if (update_attempter) { 229 update_attempter->RefreshDevicePolicy(); 230 device_policy = system_state_->device_policy(); 231 } 232 } 233 234 // Check if this setting is allowed by the device policy. 235 if (device_policy && 236 device_policy->GetAllowedConnectionTypesForUpdate(&allowed_types)) { 237 LogAndSetError(error, 238 FROM_HERE, 239 "Ignoring the update over cellular setting since there's " 240 "a device policy enforcing this setting."); 241 return false; 242 } 243 244 // If the policy wasn't loaded yet, then it is still OK to change the local 245 // setting because the policy will be checked again during the update check. 246 247 PrefsInterface* prefs = system_state_->prefs(); 248 249 if (!prefs->SetBoolean(kPrefsUpdateOverCellularPermission, in_allowed)) { 250 LogAndSetError(error, 251 FROM_HERE, 252 string("Error setting the update over cellular to ") + 253 (in_allowed ? "true" : "false")); 254 return false; 255 } 256 return true; 257} 258 259bool UpdateEngineService::GetUpdateOverCellularPermission(ErrorPtr* /* error */, 260 bool* out_allowed) { 261 ConnectionManagerInterface* cm = system_state_->connection_manager(); 262 263 // The device_policy is loaded in a lazy way before an update check and is 264 // used to determine if an update is allowed over cellular. Load the device 265 // policy now from the libbrillo cache if it wasn't already loaded. 266 if (!system_state_->device_policy()) { 267 UpdateAttempter* update_attempter = system_state_->update_attempter(); 268 if (update_attempter) 269 update_attempter->RefreshDevicePolicy(); 270 } 271 272 // Return the current setting based on the same logic used while checking for 273 // updates. A log message could be printed as the result of this test. 274 LOG(INFO) << "Checking if updates over cellular networks are allowed:"; 275 *out_allowed = cm->IsUpdateAllowedOver( 276 chromeos_update_engine::NetworkConnectionType::kCellular, 277 chromeos_update_engine::NetworkTethering::kUnknown); 278 return true; 279} 280 281bool UpdateEngineService::GetDurationSinceUpdate(ErrorPtr* error, 282 int64_t* out_usec_wallclock) { 283 base::Time time; 284 if (!system_state_->update_attempter()->GetBootTimeAtUpdate(&time)) { 285 LogAndSetError(error, FROM_HERE, "No pending update."); 286 return false; 287 } 288 289 ClockInterface* clock = system_state_->clock(); 290 *out_usec_wallclock = (clock->GetBootTime() - time).InMicroseconds(); 291 return true; 292} 293 294bool UpdateEngineService::GetPrevVersion(ErrorPtr* /* error */, 295 string* out_prev_version) { 296 *out_prev_version = system_state_->update_attempter()->GetPrevVersion(); 297 return true; 298} 299 300bool UpdateEngineService::GetRollbackPartition( 301 ErrorPtr* /* error */, string* out_rollback_partition_name) { 302 BootControlInterface::Slot rollback_slot = 303 system_state_->update_attempter()->GetRollbackSlot(); 304 305 if (rollback_slot == BootControlInterface::kInvalidSlot) { 306 out_rollback_partition_name->clear(); 307 return true; 308 } 309 310 string name; 311 if (!system_state_->boot_control()->GetPartitionDevice( 312 "KERNEL", rollback_slot, &name)) { 313 LOG(ERROR) << "Invalid rollback device"; 314 return false; 315 } 316 317 LOG(INFO) << "Getting rollback partition name. Result: " << name; 318 *out_rollback_partition_name = name; 319 return true; 320} 321 322bool UpdateEngineService::GetLastAttemptError(ErrorPtr* /* error */, 323 int32_t* out_last_attempt_error) { 324 ErrorCode error_code = system_state_->payload_state()->GetAttemptErrorCode(); 325 *out_last_attempt_error = static_cast<int>(error_code); 326 return true; 327} 328} // namespace chromeos_update_engine 329