common_service.cc 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431
  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. #include "update_engine/common_service.h"
  17. #include <string>
  18. #include <base/bind.h>
  19. #include <base/location.h>
  20. #include <base/logging.h>
  21. #include <base/strings/stringprintf.h>
  22. #include <brillo/message_loops/message_loop.h>
  23. #include <brillo/strings/string_utils.h>
  24. #include <policy/device_policy.h>
  25. #include "update_engine/common/clock_interface.h"
  26. #include "update_engine/common/hardware_interface.h"
  27. #include "update_engine/common/prefs.h"
  28. #include "update_engine/common/utils.h"
  29. #include "update_engine/connection_manager_interface.h"
  30. #include "update_engine/omaha_request_params.h"
  31. #include "update_engine/omaha_utils.h"
  32. #include "update_engine/p2p_manager.h"
  33. #include "update_engine/payload_state_interface.h"
  34. #include "update_engine/update_attempter.h"
  35. using base::StringPrintf;
  36. using brillo::ErrorPtr;
  37. using brillo::string_utils::ToString;
  38. using std::string;
  39. using std::vector;
  40. using update_engine::UpdateAttemptFlags;
  41. using update_engine::UpdateEngineStatus;
  42. namespace chromeos_update_engine {
  43. namespace {
  44. // Log and set the error on the passed ErrorPtr.
  45. void LogAndSetError(ErrorPtr* error,
  46. #if BASE_VER < 576279
  47. const tracked_objects::Location& location,
  48. #else
  49. const base::Location& location,
  50. #endif
  51. const string& reason) {
  52. brillo::Error::AddTo(error,
  53. location,
  54. UpdateEngineService::kErrorDomain,
  55. UpdateEngineService::kErrorFailed,
  56. reason);
  57. LOG(ERROR) << "Sending Update Engine Failure: " << location.ToString() << ": "
  58. << reason;
  59. }
  60. } // namespace
  61. const char* const UpdateEngineService::kErrorDomain = "update_engine";
  62. const char* const UpdateEngineService::kErrorFailed =
  63. "org.chromium.UpdateEngine.Error.Failed";
  64. UpdateEngineService::UpdateEngineService(SystemState* system_state)
  65. : system_state_(system_state) {}
  66. // org::chromium::UpdateEngineInterfaceInterface methods implementation.
  67. bool UpdateEngineService::SetUpdateAttemptFlags(ErrorPtr* /* error */,
  68. int32_t in_flags_as_int) {
  69. auto flags = static_cast<UpdateAttemptFlags>(in_flags_as_int);
  70. LOG(INFO) << "Setting Update Attempt Flags: "
  71. << "flags=0x" << std::hex << flags << " "
  72. << "RestrictDownload="
  73. << ((flags & UpdateAttemptFlags::kFlagRestrictDownload) ? "yes"
  74. : "no");
  75. system_state_->update_attempter()->SetUpdateAttemptFlags(flags);
  76. return true;
  77. }
  78. bool UpdateEngineService::AttemptUpdate(ErrorPtr* /* error */,
  79. const string& in_app_version,
  80. const string& in_omaha_url,
  81. int32_t in_flags_as_int,
  82. bool* out_result) {
  83. auto flags = static_cast<UpdateAttemptFlags>(in_flags_as_int);
  84. bool interactive = !(flags & UpdateAttemptFlags::kFlagNonInteractive);
  85. bool restrict_downloads = (flags & UpdateAttemptFlags::kFlagRestrictDownload);
  86. LOG(INFO) << "Attempt update: app_version=\"" << in_app_version << "\" "
  87. << "omaha_url=\"" << in_omaha_url << "\" "
  88. << "flags=0x" << std::hex << flags << " "
  89. << "interactive=" << (interactive ? "yes " : "no ")
  90. << "RestrictDownload=" << (restrict_downloads ? "yes " : "no ");
  91. *out_result = system_state_->update_attempter()->CheckForUpdate(
  92. in_app_version, in_omaha_url, flags);
  93. return true;
  94. }
  95. bool UpdateEngineService::AttemptInstall(brillo::ErrorPtr* error,
  96. const string& omaha_url,
  97. const vector<string>& dlc_module_ids) {
  98. if (!system_state_->update_attempter()->CheckForInstall(dlc_module_ids,
  99. omaha_url)) {
  100. // TODO(xiaochu): support more detailed error messages.
  101. LogAndSetError(error, FROM_HERE, "Could not schedule install operation.");
  102. return false;
  103. }
  104. return true;
  105. }
  106. bool UpdateEngineService::AttemptRollback(ErrorPtr* error, bool in_powerwash) {
  107. LOG(INFO) << "Attempting rollback to non-active partitions.";
  108. if (!system_state_->update_attempter()->Rollback(in_powerwash)) {
  109. // TODO(dgarrett): Give a more specific error code/reason.
  110. LogAndSetError(error, FROM_HERE, "Rollback attempt failed.");
  111. return false;
  112. }
  113. return true;
  114. }
  115. bool UpdateEngineService::CanRollback(ErrorPtr* /* error */,
  116. bool* out_can_rollback) {
  117. bool can_rollback = system_state_->update_attempter()->CanRollback();
  118. LOG(INFO) << "Checking to see if we can rollback . Result: " << can_rollback;
  119. *out_can_rollback = can_rollback;
  120. return true;
  121. }
  122. bool UpdateEngineService::ResetStatus(ErrorPtr* error) {
  123. if (!system_state_->update_attempter()->ResetStatus()) {
  124. // TODO(dgarrett): Give a more specific error code/reason.
  125. LogAndSetError(error, FROM_HERE, "ResetStatus failed.");
  126. return false;
  127. }
  128. return true;
  129. }
  130. bool UpdateEngineService::GetStatus(ErrorPtr* error,
  131. UpdateEngineStatus* out_status) {
  132. if (!system_state_->update_attempter()->GetStatus(out_status)) {
  133. LogAndSetError(error, FROM_HERE, "GetStatus failed.");
  134. return false;
  135. }
  136. return true;
  137. }
  138. bool UpdateEngineService::RebootIfNeeded(ErrorPtr* error) {
  139. if (!system_state_->update_attempter()->RebootIfNeeded()) {
  140. // TODO(dgarrett): Give a more specific error code/reason.
  141. LogAndSetError(error, FROM_HERE, "Reboot not needed, or attempt failed.");
  142. return false;
  143. }
  144. return true;
  145. }
  146. bool UpdateEngineService::SetChannel(ErrorPtr* error,
  147. const string& in_target_channel,
  148. bool in_is_powerwash_allowed) {
  149. const policy::DevicePolicy* device_policy = system_state_->device_policy();
  150. // The device_policy is loaded in a lazy way before an update check. Load it
  151. // now from the libbrillo cache if it wasn't already loaded.
  152. if (!device_policy) {
  153. UpdateAttempter* update_attempter = system_state_->update_attempter();
  154. if (update_attempter) {
  155. update_attempter->RefreshDevicePolicy();
  156. device_policy = system_state_->device_policy();
  157. }
  158. }
  159. bool delegated = false;
  160. if (device_policy && device_policy->GetReleaseChannelDelegated(&delegated) &&
  161. !delegated) {
  162. LogAndSetError(error,
  163. FROM_HERE,
  164. "Cannot set target channel explicitly when channel "
  165. "policy/settings is not delegated");
  166. return false;
  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. return true;
  176. }
  177. bool UpdateEngineService::GetChannel(ErrorPtr* /* error */,
  178. bool in_get_current_channel,
  179. string* out_channel) {
  180. OmahaRequestParams* rp = system_state_->request_params();
  181. *out_channel =
  182. (in_get_current_channel ? rp->current_channel() : rp->target_channel());
  183. return true;
  184. }
  185. bool UpdateEngineService::SetCohortHint(ErrorPtr* error,
  186. string in_cohort_hint) {
  187. PrefsInterface* prefs = system_state_->prefs();
  188. // It is ok to override the cohort hint with an invalid value since it is
  189. // stored in stateful partition. The code reading it should sanitize it
  190. // anyway.
  191. if (!prefs->SetString(kPrefsOmahaCohortHint, in_cohort_hint)) {
  192. LogAndSetError(
  193. error,
  194. FROM_HERE,
  195. StringPrintf("Error setting the cohort hint value to \"%s\".",
  196. in_cohort_hint.c_str()));
  197. return false;
  198. }
  199. return true;
  200. }
  201. bool UpdateEngineService::GetCohortHint(ErrorPtr* error,
  202. string* out_cohort_hint) {
  203. PrefsInterface* prefs = system_state_->prefs();
  204. *out_cohort_hint = "";
  205. if (prefs->Exists(kPrefsOmahaCohortHint) &&
  206. !prefs->GetString(kPrefsOmahaCohortHint, out_cohort_hint)) {
  207. LogAndSetError(error, FROM_HERE, "Error getting the cohort hint.");
  208. return false;
  209. }
  210. return true;
  211. }
  212. bool UpdateEngineService::SetP2PUpdatePermission(ErrorPtr* error,
  213. bool in_enabled) {
  214. PrefsInterface* prefs = system_state_->prefs();
  215. if (!prefs->SetBoolean(kPrefsP2PEnabled, in_enabled)) {
  216. LogAndSetError(
  217. error,
  218. FROM_HERE,
  219. StringPrintf("Error setting the update via p2p permission to %s.",
  220. ToString(in_enabled).c_str()));
  221. return false;
  222. }
  223. return true;
  224. }
  225. bool UpdateEngineService::GetP2PUpdatePermission(ErrorPtr* error,
  226. bool* out_enabled) {
  227. PrefsInterface* prefs = system_state_->prefs();
  228. bool p2p_pref = false; // Default if no setting is present.
  229. if (prefs->Exists(kPrefsP2PEnabled) &&
  230. !prefs->GetBoolean(kPrefsP2PEnabled, &p2p_pref)) {
  231. LogAndSetError(error, FROM_HERE, "Error getting the P2PEnabled setting.");
  232. return false;
  233. }
  234. *out_enabled = p2p_pref;
  235. return true;
  236. }
  237. bool UpdateEngineService::SetUpdateOverCellularPermission(ErrorPtr* error,
  238. bool in_allowed) {
  239. ConnectionManagerInterface* connection_manager =
  240. system_state_->connection_manager();
  241. // Check if this setting is allowed by the device policy.
  242. if (connection_manager->IsAllowedConnectionTypesForUpdateSet()) {
  243. LogAndSetError(error,
  244. FROM_HERE,
  245. "Ignoring the update over cellular setting since there's "
  246. "a device policy enforcing this setting.");
  247. return false;
  248. }
  249. // If the policy wasn't loaded yet, then it is still OK to change the local
  250. // setting because the policy will be checked again during the update check.
  251. PrefsInterface* prefs = system_state_->prefs();
  252. if (!prefs ||
  253. !prefs->SetBoolean(kPrefsUpdateOverCellularPermission, in_allowed)) {
  254. LogAndSetError(error,
  255. FROM_HERE,
  256. string("Error setting the update over cellular to ") +
  257. (in_allowed ? "true" : "false"));
  258. return false;
  259. }
  260. return true;
  261. }
  262. bool UpdateEngineService::SetUpdateOverCellularTarget(
  263. brillo::ErrorPtr* error,
  264. const std::string& target_version,
  265. int64_t target_size) {
  266. ConnectionManagerInterface* connection_manager =
  267. system_state_->connection_manager();
  268. // Check if this setting is allowed by the device policy.
  269. if (connection_manager->IsAllowedConnectionTypesForUpdateSet()) {
  270. LogAndSetError(error,
  271. FROM_HERE,
  272. "Ignoring the update over cellular setting since there's "
  273. "a device policy enforcing this setting.");
  274. return false;
  275. }
  276. // If the policy wasn't loaded yet, then it is still OK to change the local
  277. // setting because the policy will be checked again during the update check.
  278. PrefsInterface* prefs = system_state_->prefs();
  279. if (!prefs ||
  280. !prefs->SetString(kPrefsUpdateOverCellularTargetVersion,
  281. target_version) ||
  282. !prefs->SetInt64(kPrefsUpdateOverCellularTargetSize, target_size)) {
  283. LogAndSetError(
  284. error, FROM_HERE, "Error setting the target for update over cellular.");
  285. return false;
  286. }
  287. return true;
  288. }
  289. bool UpdateEngineService::GetUpdateOverCellularPermission(ErrorPtr* error,
  290. bool* out_allowed) {
  291. ConnectionManagerInterface* connection_manager =
  292. system_state_->connection_manager();
  293. if (connection_manager->IsAllowedConnectionTypesForUpdateSet()) {
  294. // We have device policy, so ignore the user preferences.
  295. *out_allowed = connection_manager->IsUpdateAllowedOver(
  296. ConnectionType::kCellular, ConnectionTethering::kUnknown);
  297. } else {
  298. PrefsInterface* prefs = system_state_->prefs();
  299. if (!prefs || !prefs->Exists(kPrefsUpdateOverCellularPermission)) {
  300. // Update is not allowed as user preference is not set or not available.
  301. *out_allowed = false;
  302. return true;
  303. }
  304. bool is_allowed;
  305. if (!prefs->GetBoolean(kPrefsUpdateOverCellularPermission, &is_allowed)) {
  306. LogAndSetError(error,
  307. FROM_HERE,
  308. "Error getting the update over cellular preference.");
  309. return false;
  310. }
  311. *out_allowed = is_allowed;
  312. }
  313. return true;
  314. }
  315. bool UpdateEngineService::GetDurationSinceUpdate(ErrorPtr* error,
  316. int64_t* out_usec_wallclock) {
  317. base::Time time;
  318. if (!system_state_->update_attempter()->GetBootTimeAtUpdate(&time)) {
  319. LogAndSetError(error, FROM_HERE, "No pending update.");
  320. return false;
  321. }
  322. ClockInterface* clock = system_state_->clock();
  323. *out_usec_wallclock = (clock->GetBootTime() - time).InMicroseconds();
  324. return true;
  325. }
  326. bool UpdateEngineService::GetPrevVersion(ErrorPtr* /* error */,
  327. string* out_prev_version) {
  328. *out_prev_version = system_state_->update_attempter()->GetPrevVersion();
  329. return true;
  330. }
  331. bool UpdateEngineService::GetRollbackPartition(
  332. ErrorPtr* /* error */, string* out_rollback_partition_name) {
  333. BootControlInterface::Slot rollback_slot =
  334. system_state_->update_attempter()->GetRollbackSlot();
  335. if (rollback_slot == BootControlInterface::kInvalidSlot) {
  336. out_rollback_partition_name->clear();
  337. return true;
  338. }
  339. string name;
  340. if (!system_state_->boot_control()->GetPartitionDevice(
  341. "KERNEL", rollback_slot, &name)) {
  342. LOG(ERROR) << "Invalid rollback device";
  343. return false;
  344. }
  345. LOG(INFO) << "Getting rollback partition name. Result: " << name;
  346. *out_rollback_partition_name = name;
  347. return true;
  348. }
  349. bool UpdateEngineService::GetLastAttemptError(ErrorPtr* /* error */,
  350. int32_t* out_last_attempt_error) {
  351. ErrorCode error_code =
  352. system_state_->update_attempter()->GetAttemptErrorCode();
  353. *out_last_attempt_error = static_cast<int>(error_code);
  354. return true;
  355. }
  356. bool UpdateEngineService::GetEolStatus(ErrorPtr* error,
  357. int32_t* out_eol_status) {
  358. PrefsInterface* prefs = system_state_->prefs();
  359. string str_eol_status;
  360. if (prefs->Exists(kPrefsOmahaEolStatus) &&
  361. !prefs->GetString(kPrefsOmahaEolStatus, &str_eol_status)) {
  362. LogAndSetError(error, FROM_HERE, "Error getting the end-of-life status.");
  363. return false;
  364. }
  365. // StringToEolStatus will return kSupported for invalid values.
  366. *out_eol_status = static_cast<int32_t>(StringToEolStatus(str_eol_status));
  367. return true;
  368. }
  369. } // namespace chromeos_update_engine