Add flag for restricting downloads
This adds a flag that can be used to turn off the ability to download
and apply updates from the API. This value applies to all future
update checks that the update_engine performs. Changing this value
during an update check has no effect on the current update check.
Bug: 66016687
Test: unit-tests, manual OTA
Change-Id: I655adf23cae44c63079bfa9dc18ba8ca65d7a304
(cherry picked from commit e22f2ddfec92623d38efbf17c17917f68e52907a)
diff --git a/Android.mk b/Android.mk
index 2470865..8f1de53 100644
--- a/Android.mk
+++ b/Android.mk
@@ -306,6 +306,7 @@
real_system_state.cc \
update_attempter.cc \
update_manager/android_things_policy.cc \
+ update_manager/api_restricted_downloads_policy_impl.cc \
update_manager/boxed_value.cc \
update_manager/default_policy.cc \
update_manager/enough_slots_ab_updates_policy_impl.cc \
diff --git a/binder_bindings/android/brillo/IUpdateEngine.aidl b/binder_bindings/android/brillo/IUpdateEngine.aidl
index b1a1b4f..c85c0dc 100644
--- a/binder_bindings/android/brillo/IUpdateEngine.aidl
+++ b/binder_bindings/android/brillo/IUpdateEngine.aidl
@@ -20,6 +20,7 @@
import android.brillo.ParcelableUpdateEngineStatus;
interface IUpdateEngine {
+ void SetUpdateAttemptFlags(in int flags);
void AttemptUpdate(in String app_version, in String omaha_url, in int flags);
void AttemptRollback(in boolean powerwash);
boolean CanRollback();
diff --git a/binder_service_brillo.cc b/binder_service_brillo.cc
index 74803c4..c57561c 100644
--- a/binder_service_brillo.cc
+++ b/binder_service_brillo.cc
@@ -58,6 +58,10 @@
return ToStatus(&error);
}
+Status BinderUpdateEngineBrilloService::SetUpdateAttemptFlags(int flags) {
+ return CallCommonHandler(&UpdateEngineService::SetUpdateAttemptFlags, flags);
+}
+
Status BinderUpdateEngineBrilloService::AttemptUpdate(
const String16& app_version, const String16& omaha_url, int flags) {
return CallCommonHandler(&UpdateEngineService::AttemptUpdate,
diff --git a/binder_service_brillo.h b/binder_service_brillo.h
index 51f0fab..81a4e4c 100644
--- a/binder_service_brillo.h
+++ b/binder_service_brillo.h
@@ -51,6 +51,7 @@
void SendPayloadApplicationComplete(ErrorCode error_code) override {}
// android::brillo::BnUpdateEngine overrides.
+ android::binder::Status SetUpdateAttemptFlags(int flags) override;
android::binder::Status AttemptUpdate(const android::String16& app_version,
const android::String16& omaha_url,
int flags) override;
diff --git a/client_library/client_binder.cc b/client_library/client_binder.cc
index fecd9a3..b4625e4 100644
--- a/client_library/client_binder.cc
+++ b/client_library/client_binder.cc
@@ -25,15 +25,15 @@
#include "update_engine/parcelable_update_engine_status.h"
#include "update_engine/update_status_utils.h"
-using android::OK;
-using android::String16;
-using android::String8;
using android::binder::Status;
using android::brillo::ParcelableUpdateEngineStatus;
using android::getService;
+using android::OK;
+using android::String16;
+using android::String8;
using chromeos_update_engine::StringToUpdateStatus;
-using chromeos_update_engine::UpdateEngineService;
using std::string;
+using update_engine::UpdateAttemptFlags;
namespace update_engine {
namespace internal {
@@ -48,10 +48,12 @@
bool BinderUpdateEngineClient::AttemptUpdate(const string& in_app_version,
const string& in_omaha_url,
bool at_user_request) {
- return service_->AttemptUpdate(String16{in_app_version.c_str()},
- String16{in_omaha_url.c_str()},
- at_user_request ? 0 :
- UpdateEngineService::kAttemptUpdateFlagNonInteractive).isOk();
+ return service_
+ ->AttemptUpdate(
+ String16{in_app_version.c_str()},
+ String16{in_omaha_url.c_str()},
+ at_user_request ? 0 : UpdateAttemptFlags::kFlagNonInteractive)
+ .isOk();
}
bool BinderUpdateEngineClient::GetStatus(int64_t* out_last_checked_time,
diff --git a/client_library/include/update_engine/update_status.h b/client_library/include/update_engine/update_status.h
index 76dd865..d93ca91 100644
--- a/client_library/include/update_engine/update_status.h
+++ b/client_library/include/update_engine/update_status.h
@@ -34,6 +34,32 @@
DISABLED,
};
+// Enum of bit-wise flags for controlling how updates are attempted.
+enum UpdateAttemptFlags : int32_t {
+ kNone = 0,
+ // Treat the update like a non-interactive update, even when being triggered
+ // by the interactive APIs.
+ kFlagNonInteractive = (1 << 0),
+ // Restrict (disallow) downloading of updates.
+ kFlagRestrictDownload = (1 << 1),
+};
+
+// These bit-wise operators for the above flags allow for standard bit-wise
+// operations to return values in an expected manner, with the need to
+// continually cast the results back to UpdateAttemptFlags after the implicit
+// conversion to int from enum to perform the bitwise comparison using the
+// underlying type.
+inline UpdateAttemptFlags operator|(const UpdateAttemptFlags& l,
+ const UpdateAttemptFlags& r) {
+ return static_cast<UpdateAttemptFlags>(static_cast<const int32_t&>(l) |
+ static_cast<const int32_t&>(r));
+}
+inline UpdateAttemptFlags operator&(const UpdateAttemptFlags& l,
+ const UpdateAttemptFlags& r) {
+ return static_cast<UpdateAttemptFlags>(static_cast<const int32_t&>(l) &
+ static_cast<const int32_t&>(r));
+}
+
struct UpdateEngineStatus {
// When the update_engine last checked for updates (ms since Epoch)
int64_t last_checked_time_ms;
diff --git a/common_service.cc b/common_service.cc
index 15feca7..38a3096 100644
--- a/common_service.cc
+++ b/common_service.cc
@@ -43,6 +43,7 @@
using brillo::string_utils::ToString;
using std::set;
using std::string;
+using update_engine::UpdateAttemptFlags;
using update_engine::UpdateEngineStatus;
namespace chromeos_update_engine {
@@ -72,12 +73,24 @@
// org::chromium::UpdateEngineInterfaceInterface methods implementation.
+bool UpdateEngineService::SetUpdateAttemptFlags(ErrorPtr* /* error */,
+ int32_t in_flags_as_int) {
+ auto flags = static_cast<UpdateAttemptFlags>(in_flags_as_int);
+ LOG(INFO) << "Setting Update Attempt Flags: "
+ << "flags=0x" << std::hex << flags << " "
+ << "RestrictDownload="
+ << ((flags & UpdateAttemptFlags::kFlagRestrictDownload) ? "yes"
+ : "no");
+ system_state_->update_attempter()->SetUpdateAttemptFlags(flags);
+ return true;
+}
+
bool UpdateEngineService::AttemptUpdate(ErrorPtr* /* error */,
const string& in_app_version,
const string& in_omaha_url,
int32_t in_flags_as_int) {
- AttemptUpdateFlags flags = static_cast<AttemptUpdateFlags>(in_flags_as_int);
- bool interactive = !(flags & kAttemptUpdateFlagNonInteractive);
+ auto flags = static_cast<UpdateAttemptFlags>(in_flags_as_int);
+ bool interactive = !(flags & UpdateAttemptFlags::kFlagNonInteractive);
LOG(INFO) << "Attempt update: app_version=\"" << in_app_version << "\" "
<< "omaha_url=\"" << in_omaha_url << "\" "
diff --git a/common_service.h b/common_service.h
index 7e7fea8..261c9e8 100644
--- a/common_service.h
+++ b/common_service.h
@@ -31,11 +31,6 @@
class UpdateEngineService {
public:
- // Flags used in the AttemptUpdateWithFlags() D-Bus method.
- typedef enum {
- kAttemptUpdateFlagNonInteractive = (1<<0)
- } AttemptUpdateFlags;
-
// Error domain for all the service errors.
static const char* const kErrorDomain;
@@ -45,6 +40,12 @@
explicit UpdateEngineService(SystemState* system_state);
virtual ~UpdateEngineService() = default;
+ // Set flags that influence how updates and checks are performed. These
+ // influence all future checks and updates until changed or the device
+ // reboots. The |in_flags_as_int| values are a union of values from
+ // |UpdateAttemptFlags|
+ bool SetUpdateAttemptFlags(brillo::ErrorPtr* error, int32_t in_flags_as_int);
+
bool AttemptUpdate(brillo::ErrorPtr* error,
const std::string& in_app_version,
const std::string& in_omaha_url,
diff --git a/common_service_unittest.cc b/common_service_unittest.cc
index 0a7bfc3..71e42d0 100644
--- a/common_service_unittest.cc
+++ b/common_service_unittest.cc
@@ -28,9 +28,10 @@
#include "update_engine/omaha_utils.h"
using std::string;
+using testing::_;
using testing::Return;
using testing::SetArgumentPointee;
-using testing::_;
+using update_engine::UpdateAttemptFlags;
namespace chromeos_update_engine {
@@ -60,8 +61,7 @@
"app_ver", "url", false /* interactive */));
// The update is non-interactive when we pass the non-interactive flag.
EXPECT_TRUE(common_service_.AttemptUpdate(
- &error_, "app_ver", "url",
- UpdateEngineService::kAttemptUpdateFlagNonInteractive));
+ &error_, "app_ver", "url", UpdateAttemptFlags::kFlagNonInteractive));
EXPECT_EQ(nullptr, error_);
}
diff --git a/mock_update_attempter.h b/mock_update_attempter.h
index 9634bab..d64dcbe 100644
--- a/mock_update_attempter.h
+++ b/mock_update_attempter.h
@@ -42,6 +42,8 @@
MOCK_METHOD0(ResetStatus, bool(void));
+ MOCK_METHOD0(GetCurrentUpdateAttemptFlags, UpdateAttemptFlags(void));
+
MOCK_METHOD3(CheckForUpdate, void(const std::string& app_version,
const std::string& omaha_url,
bool is_interactive));
diff --git a/update_attempter.cc b/update_attempter.cc
index c7c0177..e40dfe7 100644
--- a/update_attempter.cc
+++ b/update_attempter.cc
@@ -78,6 +78,7 @@
using std::shared_ptr;
using std::string;
using std::vector;
+using update_engine::UpdateAttemptFlags;
using update_engine::UpdateEngineStatus;
namespace chromeos_update_engine {
@@ -859,6 +860,12 @@
<< (params.is_interactive ? "interactive" : "periodic")
<< " update.";
+ // Cache the update attempt flags that will be used by this update attempt
+ // so that they can't be changed mid-way through.
+ current_update_attempt_flags_ = update_attempt_flags_;
+ LOG(INFO) << "Update attempt flags in use = 0x" << std::hex
+ << current_update_attempt_flags_;
+
Update(forced_app_version_, forced_omaha_url_, params.target_channel,
params.target_version_prefix, false, params.is_interactive);
// Always clear the forced app_version and omaha_url after an update attempt
@@ -892,6 +899,9 @@
// Reset cpu shares back to normal.
cpu_limiter_.StopLimiter();
+ // reset the state that's only valid for a single update pass
+ current_update_attempt_flags_ = UpdateAttemptFlags::kNone;
+
if (status_ == UpdateStatus::REPORTING_ERROR_EVENT) {
LOG(INFO) << "Error event sent.";
diff --git a/update_attempter.h b/update_attempter.h
index 6b2a7a7..758494a 100644
--- a/update_attempter.h
+++ b/update_attempter.h
@@ -66,6 +66,7 @@
public PostinstallRunnerAction::DelegateInterface {
public:
using UpdateStatus = update_engine::UpdateStatus;
+ using UpdateAttemptFlags = update_engine::UpdateAttemptFlags;
static const int kMaxDeltaUpdateFailures;
UpdateAttempter(SystemState* system_state,
@@ -130,6 +131,20 @@
int http_response_code() const { return http_response_code_; }
void set_http_response_code(int code) { http_response_code_ = code; }
+ // Set flags that influence how updates and checks are performed. These
+ // influence all future checks and updates until changed or the device
+ // reboots.
+ void SetUpdateAttemptFlags(UpdateAttemptFlags flags) {
+ update_attempt_flags_ = flags;
+ }
+
+ // Returns the update attempt flags that are in place for the current update
+ // attempt. These are cached at the start of an update attempt so that they
+ // remain constant throughout the process.
+ virtual UpdateAttemptFlags GetCurrentUpdateAttemptFlags() {
+ return current_update_attempt_flags_;
+ }
+
// This is the internal entry point for going through an
// update. If the current status is idle invokes Update.
// This is called by the DBus implementation.
@@ -259,6 +274,7 @@
FRIEND_TEST(UpdateAttempterTest, ScheduleErrorEventActionNoEventTest);
FRIEND_TEST(UpdateAttempterTest, ScheduleErrorEventActionTest);
FRIEND_TEST(UpdateAttempterTest, TargetVersionPrefixSetAndReset);
+ FRIEND_TEST(UpdateAttempterTest, UpdateAttemptFlagsCachedAtUpdateStart);
FRIEND_TEST(UpdateAttempterTest, UpdateDeferredByPolicyTest);
FRIEND_TEST(UpdateAttempterTest, UpdateIsNotRunningWhenUpdateAvailable);
FRIEND_TEST(UpdateAttempterTest, UpdateTest);
@@ -439,6 +455,11 @@
std::string new_version_ = "0.0.0.0";
std::string new_system_version_;
uint64_t new_payload_size_ = 0;
+ // Flags influencing all periodic update checks
+ UpdateAttemptFlags update_attempt_flags_ = UpdateAttemptFlags::kNone;
+ // Flags influencing the currently in-progress check (cached at the start of
+ // the update check).
+ UpdateAttemptFlags current_update_attempt_flags_ = UpdateAttemptFlags::kNone;
// Common parameters for all Omaha requests.
OmahaRequestParams* omaha_request_params_ = nullptr;
diff --git a/update_attempter_unittest.cc b/update_attempter_unittest.cc
index 7ecc5a6..d54c867 100644
--- a/update_attempter_unittest.cc
+++ b/update_attempter_unittest.cc
@@ -62,10 +62,17 @@
using base::Time;
using base::TimeDelta;
+using chromeos_update_manager::EvalStatus;
+using chromeos_update_manager::UpdateCheckParams;
using org::chromium::NetworkProxyServiceInterfaceProxyInterface;
using org::chromium::NetworkProxyServiceInterfaceProxyMock;
+#if USE_LIBCROS
+using org::chromium::LibCrosServiceInterfaceProxyMock;
+using org::chromium::UpdateEngineLibcrosProxyResolvedInterfaceProxyMock;
+#endif // USE_LIBCROS
using std::string;
using std::unique_ptr;
+using testing::_;
using testing::DoAll;
using testing::Field;
using testing::InSequence;
@@ -76,7 +83,7 @@
using testing::ReturnPointee;
using testing::SaveArg;
using testing::SetArgumentPointee;
-using testing::_;
+using update_engine::UpdateAttemptFlags;
using update_engine::UpdateEngineStatus;
using update_engine::UpdateStatus;
@@ -1118,4 +1125,14 @@
EXPECT_TRUE(attempter_.IsUpdateRunningOrScheduled());
}
+TEST_F(UpdateAttempterTest, UpdateAttemptFlagsCachedAtUpdateStart) {
+ attempter_.SetUpdateAttemptFlags(UpdateAttemptFlags::kFlagRestrictDownload);
+
+ UpdateCheckParams params = {.updates_enabled = true};
+ attempter_.OnUpdateScheduled(EvalStatus::kSucceeded, params);
+
+ EXPECT_EQ(UpdateAttemptFlags::kFlagRestrictDownload,
+ attempter_.GetCurrentUpdateAttemptFlags());
+}
+
} // namespace chromeos_update_engine
diff --git a/update_manager/android_things_policy.cc b/update_manager/android_things_policy.cc
index 2304f12..3af93cc 100644
--- a/update_manager/android_things_policy.cc
+++ b/update_manager/android_things_policy.cc
@@ -22,6 +22,7 @@
#include <base/logging.h>
#include <base/time/time.h>
+#include "update_engine/update_manager/api_restricted_downloads_policy_impl.h"
#include "update_engine/update_manager/enough_slots_ab_updates_policy_impl.h"
#include "update_engine/update_manager/interactive_update_policy_impl.h"
#include "update_engine/update_manager/official_build_check_policy_impl.h"
@@ -96,15 +97,43 @@
}
}
-// Always returns |EvalStatus::kSucceeded|
+// Uses the |UpdateRestrictions| to determine if the download and apply can
+// occur at this time.
EvalStatus AndroidThingsPolicy::UpdateCanBeApplied(
EvaluationContext* ec,
State* state,
string* error,
- chromeos_update_engine::ErrorCode* result,
+ ErrorCode* result,
chromeos_update_engine::InstallPlan* install_plan) const {
- *result = ErrorCode::kSuccess;
- return EvalStatus::kSucceeded;
+ // Build a list of policies to consult. Note that each policy may modify the
+ // result structure, even if it signals kContinue.
+ ApiRestrictedDownloadsPolicyImpl api_restricted_downloads_policy;
+
+ vector<Policy const*> policies_to_consult = {
+
+ // Do not apply the update if all updates are restricted by the API.
+ &api_restricted_downloads_policy,
+ };
+
+ // Now that the list of policy implementations, and the order to consult them,
+ // as been setup, do that. If none of the policies make a definitive
+ // decisions about whether or not to check for updates, then allow the update
+ // check to happen.
+ EvalStatus status = ConsultPolicies(policies_to_consult,
+ &Policy::UpdateCanBeApplied,
+ ec,
+ state,
+ error,
+ result,
+ install_plan);
+ if (EvalStatus::kContinue != status) {
+ return status;
+ } else {
+ // The update can proceed.
+ LOG(INFO) << "Allowing update to be applied.";
+ *result = ErrorCode::kSuccess;
+ return EvalStatus::kSucceeded;
+ }
}
// Always returns |EvalStatus::kSucceeded|
diff --git a/update_manager/android_things_policy.h b/update_manager/android_things_policy.h
index 6f8f4ad..b45e955 100644
--- a/update_manager/android_things_policy.h
+++ b/update_manager/android_things_policy.h
@@ -37,7 +37,8 @@
std::string* error,
UpdateCheckParams* result) const override;
- // Always returns |EvalStatus::kSucceeded|
+ // Uses the |UpdateRestrictions| to determine if the download and apply can
+ // occur at this time.
EvalStatus UpdateCanBeApplied(
EvaluationContext* ec,
State* state,
diff --git a/update_manager/android_things_policy_unittest.cc b/update_manager/android_things_policy_unittest.cc
index 8b7d128..04b0e0e 100644
--- a/update_manager/android_things_policy_unittest.cc
+++ b/update_manager/android_things_policy_unittest.cc
@@ -21,6 +21,8 @@
using base::Time;
using base::TimeDelta;
+using chromeos_update_engine::ErrorCode;
+using chromeos_update_engine::InstallPlan;
namespace chromeos_update_manager {
@@ -153,4 +155,30 @@
EXPECT_FALSE(result.is_interactive);
}
+TEST_F(UmAndroidThingsPolicyTest, UpdateCanBeAppliedOk) {
+ // UpdateCanBeApplied should return kSucceeded in the base case
+
+ InstallPlan plan;
+ ErrorCode result;
+ ExpectPolicyStatus(
+ EvalStatus::kSucceeded, &Policy::UpdateCanBeApplied, &result, &plan);
+
+ EXPECT_EQ(ErrorCode::kSuccess, result);
+}
+
+TEST_F(UmAndroidThingsPolicyTest, UpdateCanBeAppliedRestricted) {
+ // UpdateCanBeApplied should return kOmahaUpdateDeferredPerPolicy in
+ // when the restricted flag is set in the Updater.
+
+ fake_state_.updater_provider()->var_update_restrictions()->reset(
+ new UpdateRestrictions(UpdateRestrictions::kRestrictDownloading));
+
+ InstallPlan plan;
+ ErrorCode result;
+ ExpectPolicyStatus(
+ EvalStatus::kSucceeded, &Policy::UpdateCanBeApplied, &result, &plan);
+
+ EXPECT_EQ(ErrorCode::kOmahaUpdateDeferredPerPolicy, result);
+}
+
} // namespace chromeos_update_manager
diff --git a/update_manager/api_restricted_downloads_policy_impl.cc b/update_manager/api_restricted_downloads_policy_impl.cc
new file mode 100644
index 0000000..d413cca
--- /dev/null
+++ b/update_manager/api_restricted_downloads_policy_impl.cc
@@ -0,0 +1,47 @@
+//
+// Copyright (C) 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "update_engine/update_manager/api_restricted_downloads_policy_impl.h"
+
+using chromeos_update_engine::ErrorCode;
+using std::string;
+using std::vector;
+
+namespace chromeos_update_manager {
+
+// Allow the API to restrict the downloading of updates.
+EvalStatus ApiRestrictedDownloadsPolicyImpl::UpdateCanBeApplied(
+ EvaluationContext* ec,
+ State* state,
+ std::string* error,
+ ErrorCode* result,
+ chromeos_update_engine::InstallPlan* install_plan) const {
+ // Next, check to see if updates can be applied (in general).
+ const UpdateRestrictions* update_restrictions_p =
+ ec->GetValue(state->updater_provider()->var_update_restrictions());
+ if (update_restrictions_p) {
+ if (*update_restrictions_p & UpdateRestrictions::kRestrictDownloading) {
+ *result = ErrorCode::kOmahaUpdateDeferredPerPolicy;
+ return EvalStatus::kSucceeded;
+ }
+ }
+
+ // The API isn't restricting downloads, so implicitly allow them to happen
+ // but don't explicitly return success from this policy implementation.
+ return EvalStatus::kContinue;
+}
+
+} // namespace chromeos_update_manager
diff --git a/update_manager/api_restricted_downloads_policy_impl.h b/update_manager/api_restricted_downloads_policy_impl.h
new file mode 100644
index 0000000..69686d6
--- /dev/null
+++ b/update_manager/api_restricted_downloads_policy_impl.h
@@ -0,0 +1,51 @@
+//
+// Copyright (C) 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef UPDATE_ENGINE_UPDATE_MANAGER_API_RESTRICTED_DOWNLOADS_POLICY_IMPL_H_
+#define UPDATE_ENGINE_UPDATE_MANAGER_API_RESTRICTED_DOWNLOADS_POLICY_IMPL_H_
+
+#include <string>
+
+#include "update_engine/update_manager/policy_utils.h"
+
+namespace chromeos_update_manager {
+
+// Allow the API to restrict the downloading of updates.
+class ApiRestrictedDownloadsPolicyImpl : public PolicyImplBase {
+ public:
+ ApiRestrictedDownloadsPolicyImpl() = default;
+ ~ApiRestrictedDownloadsPolicyImpl() override = default;
+
+ // Policy overrides.
+ EvalStatus UpdateCanBeApplied(
+ EvaluationContext* ec,
+ State* state,
+ std::string* error,
+ chromeos_update_engine::ErrorCode* result,
+ chromeos_update_engine::InstallPlan* install_plan) const override;
+
+ protected:
+ std::string PolicyName() const override {
+ return "ApiRestrictedDownloadsPolicyImpl";
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ApiRestrictedDownloadsPolicyImpl);
+};
+
+} // namespace chromeos_update_manager
+
+#endif // UPDATE_ENGINE_UPDATE_MANAGER_API_RESTRICTED_DOWNLOADS_POLICY_IMPL_H_
\ No newline at end of file
diff --git a/update_manager/boxed_value.cc b/update_manager/boxed_value.cc
index 9758d33..a437c02 100644
--- a/update_manager/boxed_value.cc
+++ b/update_manager/boxed_value.cc
@@ -176,4 +176,19 @@
return "Unknown";
}
+template <>
+string BoxedValue::ValuePrinter<UpdateRestrictions>(const void* value) {
+ const UpdateRestrictions* val =
+ reinterpret_cast<const UpdateRestrictions*>(value);
+
+ if (*val == UpdateRestrictions::kNone) {
+ return "None";
+ }
+ string retval = "Flags:";
+ if (*val & kRestrictDownloading) {
+ retval += " RestrictDownloading";
+ }
+ return retval;
+}
+
} // namespace chromeos_update_manager
diff --git a/update_manager/boxed_value_unittest.cc b/update_manager/boxed_value_unittest.cc
index 2a086a6..83d8de7 100644
--- a/update_manager/boxed_value_unittest.cc
+++ b/update_manager/boxed_value_unittest.cc
@@ -231,4 +231,14 @@
EXPECT_EQ("DeleterMarker:true", value.ToString());
}
+TEST(UmBoxedValueTest, UpdateRestrictionsToString) {
+ EXPECT_EQ(
+ "None",
+ BoxedValue(new UpdateRestrictions(UpdateRestrictions::kNone)).ToString());
+ EXPECT_EQ("Flags: RestrictDownloading",
+ BoxedValue(new UpdateRestrictions(
+ UpdateRestrictions::kRestrictDownloading))
+ .ToString());
+}
+
} // namespace chromeos_update_manager
diff --git a/update_manager/fake_updater_provider.h b/update_manager/fake_updater_provider.h
index a7c15b5..3e03d43 100644
--- a/update_manager/fake_updater_provider.h
+++ b/update_manager/fake_updater_provider.h
@@ -85,6 +85,10 @@
return &var_forced_update_requested_;
}
+ FakeVariable<UpdateRestrictions>* var_update_restrictions() override {
+ return &var_update_restrictions_;
+ }
+
private:
FakeVariable<base::Time>
var_updater_started_time_{ // NOLINT(whitespace/braces)
@@ -121,6 +125,10 @@
FakeVariable<UpdateRequestStatus>
var_forced_update_requested_{ // NOLINT(whitespace/braces)
"forced_update_requested", kVariableModeAsync};
+ FakeVariable<UpdateRestrictions> var_update_restrictions_{
+ // NOLINT(whitespace/braces)
+ "update_restrictions",
+ kVariableModePoll};
DISALLOW_COPY_AND_ASSIGN(FakeUpdaterProvider);
};
diff --git a/update_manager/real_updater_provider.cc b/update_manager/real_updater_provider.cc
index a085f42..efa3609 100644
--- a/update_manager/real_updater_provider.cc
+++ b/update_manager/real_updater_provider.cc
@@ -38,6 +38,7 @@
using chromeos_update_engine::OmahaRequestParams;
using chromeos_update_engine::SystemState;
using std::string;
+using update_engine::UpdateAttemptFlags;
using update_engine::UpdateEngineStatus;
namespace chromeos_update_manager {
@@ -416,40 +417,66 @@
DISALLOW_COPY_AND_ASSIGN(ForcedUpdateRequestedVariable);
};
+// A variable returning the current update restrictions that are in effect.
+class UpdateRestrictionsVariable
+ : public UpdaterVariableBase<UpdateRestrictions> {
+ public:
+ UpdateRestrictionsVariable(const string& name, SystemState* system_state)
+ : UpdaterVariableBase<UpdateRestrictions>(
+ name, kVariableModePoll, system_state) {}
+
+ private:
+ const UpdateRestrictions* GetValue(TimeDelta /* timeout */,
+ string* /* errmsg */) override {
+ UpdateAttemptFlags attempt_flags =
+ system_state()->update_attempter()->GetCurrentUpdateAttemptFlags();
+ UpdateRestrictions restriction_flags = UpdateRestrictions::kNone;
+ // Don't blindly copy the whole value, test and set bits that should
+ // transfer from one set of flags to the other.
+ if (attempt_flags & UpdateAttemptFlags::kFlagRestrictDownload) {
+ restriction_flags = static_cast<UpdateRestrictions>(
+ restriction_flags | UpdateRestrictions::kRestrictDownloading);
+ }
+
+ return new UpdateRestrictions(restriction_flags);
+ }
+
+ DISALLOW_COPY_AND_ASSIGN(UpdateRestrictionsVariable);
+};
+
// RealUpdaterProvider methods.
RealUpdaterProvider::RealUpdaterProvider(SystemState* system_state)
- : system_state_(system_state),
- var_updater_started_time_("updater_started_time",
- system_state->clock()->GetWallclockTime()),
- var_last_checked_time_(
- new LastCheckedTimeVariable("last_checked_time", system_state_)),
- var_update_completed_time_(
- new UpdateCompletedTimeVariable("update_completed_time",
- system_state_)),
- var_progress_(new ProgressVariable("progress", system_state_)),
- var_stage_(new StageVariable("stage", system_state_)),
- var_new_version_(new NewVersionVariable("new_version", system_state_)),
- var_payload_size_(new PayloadSizeVariable("payload_size", system_state_)),
- var_curr_channel_(new CurrChannelVariable("curr_channel", system_state_)),
- var_new_channel_(new NewChannelVariable("new_channel", system_state_)),
- var_p2p_enabled_(
- new BooleanPrefVariable("p2p_enabled", system_state_->prefs(),
- chromeos_update_engine::kPrefsP2PEnabled,
- false)),
- var_cellular_enabled_(
- new BooleanPrefVariable(
- "cellular_enabled", system_state_->prefs(),
- chromeos_update_engine::kPrefsUpdateOverCellularPermission,
- false)),
- var_consecutive_failed_update_checks_(
- new ConsecutiveFailedUpdateChecksVariable(
- "consecutive_failed_update_checks", system_state_)),
- var_server_dictated_poll_interval_(
- new ServerDictatedPollIntervalVariable(
- "server_dictated_poll_interval", system_state_)),
- var_forced_update_requested_(
- new ForcedUpdateRequestedVariable(
- "forced_update_requested", system_state_)) {}
-
+ : system_state_(system_state),
+ var_updater_started_time_("updater_started_time",
+ system_state->clock()->GetWallclockTime()),
+ var_last_checked_time_(
+ new LastCheckedTimeVariable("last_checked_time", system_state_)),
+ var_update_completed_time_(new UpdateCompletedTimeVariable(
+ "update_completed_time", system_state_)),
+ var_progress_(new ProgressVariable("progress", system_state_)),
+ var_stage_(new StageVariable("stage", system_state_)),
+ var_new_version_(new NewVersionVariable("new_version", system_state_)),
+ var_payload_size_(new PayloadSizeVariable("payload_size", system_state_)),
+ var_curr_channel_(new CurrChannelVariable("curr_channel", system_state_)),
+ var_new_channel_(new NewChannelVariable("new_channel", system_state_)),
+ var_p2p_enabled_(
+ new BooleanPrefVariable("p2p_enabled",
+ system_state_->prefs(),
+ chromeos_update_engine::kPrefsP2PEnabled,
+ false)),
+ var_cellular_enabled_(new BooleanPrefVariable(
+ "cellular_enabled",
+ system_state_->prefs(),
+ chromeos_update_engine::kPrefsUpdateOverCellularPermission,
+ false)),
+ var_consecutive_failed_update_checks_(
+ new ConsecutiveFailedUpdateChecksVariable(
+ "consecutive_failed_update_checks", system_state_)),
+ var_server_dictated_poll_interval_(new ServerDictatedPollIntervalVariable(
+ "server_dictated_poll_interval", system_state_)),
+ var_forced_update_requested_(new ForcedUpdateRequestedVariable(
+ "forced_update_requested", system_state_)),
+ var_update_restrictions_(new UpdateRestrictionsVariable(
+ "update_restrictions", system_state_)) {}
} // namespace chromeos_update_manager
diff --git a/update_manager/real_updater_provider.h b/update_manager/real_updater_provider.h
index eb8b8e6..5e3e27b 100644
--- a/update_manager/real_updater_provider.h
+++ b/update_manager/real_updater_provider.h
@@ -96,6 +96,10 @@
return var_forced_update_requested_.get();
}
+ Variable<UpdateRestrictions>* var_update_restrictions() override {
+ return var_update_restrictions_.get();
+ }
+
private:
// A pointer to the update engine's system state aggregator.
chromeos_update_engine::SystemState* system_state_;
@@ -115,6 +119,7 @@
std::unique_ptr<Variable<unsigned int>> var_consecutive_failed_update_checks_;
std::unique_ptr<Variable<unsigned int>> var_server_dictated_poll_interval_;
std::unique_ptr<Variable<UpdateRequestStatus>> var_forced_update_requested_;
+ std::unique_ptr<Variable<UpdateRestrictions>> var_update_restrictions_;
DISALLOW_COPY_AND_ASSIGN(RealUpdaterProvider);
};
diff --git a/update_manager/real_updater_provider_unittest.cc b/update_manager/real_updater_provider_unittest.cc
index f128c77..72e664b 100644
--- a/update_manager/real_updater_provider_unittest.cc
+++ b/update_manager/real_updater_provider_unittest.cc
@@ -38,10 +38,11 @@
using chromeos_update_engine::OmahaRequestParams;
using std::string;
using std::unique_ptr;
+using testing::_;
using testing::DoAll;
using testing::Return;
using testing::SetArgPointee;
-using testing::_;
+using update_engine::UpdateAttemptFlags;
namespace {
@@ -425,4 +426,20 @@
kPollInterval, provider_->var_server_dictated_poll_interval());
}
+TEST_F(UmRealUpdaterProviderTest, GetUpdateRestrictions) {
+ EXPECT_CALL(*fake_sys_state_.mock_update_attempter(),
+ GetCurrentUpdateAttemptFlags())
+ .WillRepeatedly(Return(UpdateAttemptFlags::kFlagRestrictDownload |
+ UpdateAttemptFlags::kFlagNonInteractive));
+ UmTestUtils::ExpectVariableHasValue(UpdateRestrictions::kRestrictDownloading,
+ provider_->var_update_restrictions());
+}
+
+TEST_F(UmRealUpdaterProviderTest, GetUpdateRestrictionsNone) {
+ EXPECT_CALL(*fake_sys_state_.mock_update_attempter(),
+ GetCurrentUpdateAttemptFlags())
+ .WillRepeatedly(Return(UpdateAttemptFlags::kNone));
+ UmTestUtils::ExpectVariableHasValue(UpdateRestrictions::kNone,
+ provider_->var_update_restrictions());
+}
} // namespace chromeos_update_manager
diff --git a/update_manager/updater_provider.h b/update_manager/updater_provider.h
index 549aea9..cb62623 100644
--- a/update_manager/updater_provider.h
+++ b/update_manager/updater_provider.h
@@ -44,6 +44,12 @@
kPeriodic,
};
+// These enum values are a bit-field.
+enum UpdateRestrictions : int {
+ kNone,
+ kRestrictDownloading = (1 << 0),
+};
+
// Provider for Chrome OS update related information.
class UpdaterProvider : public Provider {
public:
@@ -105,6 +111,10 @@
// scheduled update.
virtual Variable<UpdateRequestStatus>* var_forced_update_requested() = 0;
+ // A variable that returns the update restriction flags that are set
+ // for all updates.
+ virtual Variable<UpdateRestrictions>* var_update_restrictions() = 0;
+
protected:
UpdaterProvider() {}