Skip to content

Commit 76b3a64

Browse files
Saurabh NijharaCommit Bot
Saurabh Nijhara
authored and
Commit Bot
committed
update_engine: Add restricted intervals monitor
This CL introduces class UpdateTimeRestrictionsMonitor responsible for tracking the restricted time intervals from DeviceAutoUpdateTimeRestrictions policy during which update download is not allowed. It reads the policy, chooses the next interval according to current time and notifies the delegate when it starts. UpdateTimeRestrictionsMonitor is also able to detect and handle changes in restricted intervals during its lifetime. This monitor would be used in a follow up CL to cancel the download process during a restricted interval. This class would be short lived with its lifetime restricted to during the DownloadAction so that it can notify the delegate when restricted interval starts which would then cancel the update process. Resuming the update process when interval ends would be handled by the next auto update after interval end as update engine checkpoints the download progress. BUG=chromium:1117450 TEST=FEATURES=test emerge-${BOARD} update_engine Change-Id: Ia7190a488efecf1de53c6396ff67a2b7ef10aa57 Reviewed-on: https://chromium-review.googlesource.com/c/aosp/platform/system/update_engine/+/2560619 Tested-by: Saurabh Nijhara <[email protected]> Reviewed-by: Amin Hassani <[email protected]> Reviewed-by: Jae Hoon Kim <[email protected]> Commit-Queue: Saurabh Nijhara <[email protected]>
1 parent 043355b commit 76b3a64

5 files changed

+519
-1
lines changed

BUILD.gn

+2
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@ static_library("libupdate_engine") {
236236
"update_manager/staging_utils.cc",
237237
"update_manager/state_factory.cc",
238238
"update_manager/update_manager.cc",
239+
"update_manager/update_time_restrictions_monitor.cc",
239240
"update_manager/update_time_restrictions_policy_impl.cc",
240241
"update_manager/weekly_time.cc",
241242
"update_status_utils.cc",
@@ -537,6 +538,7 @@ if (use.test) {
537538
"update_manager/real_updater_provider_unittest.cc",
538539
"update_manager/staging_utils_unittest.cc",
539540
"update_manager/update_manager_unittest.cc",
541+
"update_manager/update_time_restrictions_monitor_unittest.cc",
540542
"update_manager/update_time_restrictions_policy_impl_unittest.cc",
541543
"update_manager/variable_unittest.cc",
542544
"update_manager/weekly_time_unittest.cc",

update_manager/fake_device_policy_provider.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ class FakeDevicePolicyProvider : public DevicePolicyProvider {
138138
FakeVariable<std::string> var_auto_launched_kiosk_app_id_{
139139
"auto_launched_kiosk_app_id", kVariableModePoll};
140140
FakeVariable<WeeklyTimeIntervalVector> var_disallowed_time_intervals_{
141-
"disallowed_time_intervals", kVariableModePoll};
141+
"disallowed_time_intervals", kVariableModeAsync};
142142
FakeVariable<ChannelDowngradeBehavior> var_channel_downgrade_behavior_{
143143
"channel_downgrade_behavior", kVariableModePoll};
144144
FakeVariable<base::Version> var_device_minimum_version_{
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
//
2+
// Copyright (C) 2020 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/update_manager/update_time_restrictions_monitor.h"
18+
19+
#include <base/bind.h>
20+
#include <base/time/time.h>
21+
22+
#include "update_engine/common/system_state.h"
23+
24+
using base::TimeDelta;
25+
using brillo::MessageLoop;
26+
using chromeos_update_engine::SystemState;
27+
28+
namespace chromeos_update_manager {
29+
30+
namespace {
31+
32+
const WeeklyTimeInterval* FindNextNearestInterval(
33+
const WeeklyTimeIntervalVector& intervals, const WeeklyTime& now) {
34+
const WeeklyTimeInterval* result_interval = nullptr;
35+
// As we are dealing with weekly time here, the maximum duration can be one
36+
// week.
37+
TimeDelta duration_till_next_interval = TimeDelta::FromDays(7);
38+
for (const auto& interval : intervals) {
39+
if (interval.InRange(now)) {
40+
return &interval;
41+
}
42+
const TimeDelta current_duration = now.GetDurationTo(interval.start());
43+
if (current_duration < duration_till_next_interval) {
44+
result_interval = &interval;
45+
duration_till_next_interval = current_duration;
46+
}
47+
}
48+
return result_interval;
49+
}
50+
51+
WeeklyTime Now() {
52+
return WeeklyTime::FromTime(SystemState::Get()->clock()->GetWallclockTime());
53+
}
54+
55+
} // namespace
56+
57+
UpdateTimeRestrictionsMonitor::UpdateTimeRestrictionsMonitor(
58+
DevicePolicyProvider* device_policy_provider, Delegate* delegate)
59+
: evaluation_context_(/* evaluation_timeout = */ TimeDelta::Max(),
60+
/* expiration_timeout = */ TimeDelta::Max(),
61+
/* unregister_cb = */ {}),
62+
device_policy_provider_(device_policy_provider),
63+
delegate_(delegate),
64+
weak_ptr_factory_(this) {
65+
if (device_policy_provider_ != nullptr && delegate_ != nullptr)
66+
StartMonitoring();
67+
}
68+
69+
UpdateTimeRestrictionsMonitor::~UpdateTimeRestrictionsMonitor() {
70+
StopMonitoring();
71+
}
72+
73+
void UpdateTimeRestrictionsMonitor::StartMonitoring() {
74+
DCHECK(device_policy_provider_);
75+
const WeeklyTimeIntervalVector* new_intervals = evaluation_context_.GetValue(
76+
device_policy_provider_->var_disallowed_time_intervals());
77+
if (new_intervals && !new_intervals->empty())
78+
WaitForRestrictedIntervalStarts(*new_intervals);
79+
80+
const bool is_registered = evaluation_context_.RunOnValueChangeOrTimeout(
81+
base::Bind(&UpdateTimeRestrictionsMonitor::OnIntervalsChanged,
82+
base::Unretained(this)));
83+
DCHECK(is_registered);
84+
}
85+
86+
void UpdateTimeRestrictionsMonitor::WaitForRestrictedIntervalStarts(
87+
const WeeklyTimeIntervalVector& restricted_time_intervals) {
88+
DCHECK(!restricted_time_intervals.empty());
89+
90+
const WeeklyTimeInterval* current_interval =
91+
FindNextNearestInterval(restricted_time_intervals, Now());
92+
if (current_interval == nullptr) {
93+
LOG(WARNING) << "Could not find next nearest restricted interval.";
94+
return;
95+
}
96+
97+
// If |current_interval| happens right now, set delay to zero.
98+
const TimeDelta duration_till_start =
99+
current_interval->InRange(Now())
100+
? TimeDelta::FromMicroseconds(0)
101+
: Now().GetDurationTo(current_interval->start());
102+
LOG(INFO) << "Found restricted interval starting at "
103+
<< (SystemState::Get()->clock()->GetWallclockTime() +
104+
duration_till_start);
105+
106+
timeout_event_ = MessageLoop::current()->PostDelayedTask(
107+
FROM_HERE,
108+
base::Bind(&UpdateTimeRestrictionsMonitor::HandleRestrictedIntervalStarts,
109+
weak_ptr_factory_.GetWeakPtr()),
110+
duration_till_start);
111+
}
112+
113+
void UpdateTimeRestrictionsMonitor::HandleRestrictedIntervalStarts() {
114+
timeout_event_ = MessageLoop::kTaskIdNull;
115+
if (delegate_)
116+
delegate_->OnRestrictedIntervalStarts();
117+
}
118+
119+
void UpdateTimeRestrictionsMonitor::StopMonitoring() {
120+
MessageLoop::current()->CancelTask(timeout_event_);
121+
timeout_event_ = MessageLoop::kTaskIdNull;
122+
}
123+
124+
void UpdateTimeRestrictionsMonitor::OnIntervalsChanged() {
125+
DCHECK(!evaluation_context_.is_expired());
126+
127+
StopMonitoring();
128+
evaluation_context_.ResetEvaluation();
129+
StartMonitoring();
130+
}
131+
132+
} // namespace chromeos_update_manager
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
//
2+
// Copyright (C) 2020 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+
#ifndef UPDATE_ENGINE_UPDATE_MANAGER_UPDATE_TIME_RESTRICTIONS_MONITOR_H_
18+
#define UPDATE_ENGINE_UPDATE_MANAGER_UPDATE_TIME_RESTRICTIONS_MONITOR_H_
19+
20+
#include <memory>
21+
22+
#include <base/memory/weak_ptr.h>
23+
#include <brillo/message_loops/message_loop.h>
24+
25+
#include "update_engine/update_manager/device_policy_provider.h"
26+
#include "update_engine/update_manager/evaluation_context.h"
27+
#include "update_engine/update_manager/weekly_time.h"
28+
29+
namespace chromeos_update_manager {
30+
31+
// Represents a monitor tracking start of restricted time intervals during which
32+
// update download is not allowed. It reads |var_disallowed_time_intervals|,
33+
// chooses the next interval according to current time, awaits its start and
34+
// notifies the delegate. If the chosen interval is already happening, the
35+
// monitor notifies immediately. The monitor will never notify the delegate
36+
// while the current list of restricted intervals is empty.
37+
//
38+
// The monitor detects changes in the restricted intervals and handles the
39+
// change with following cases:
40+
// 1. No restricted time intervals or none of the intervals is in progress -> no
41+
// new restricted intervals or none of the new intervals matches the current
42+
// time.
43+
// The monitor starts tracking the next interval from the new ones, if any.
44+
// 2. No restricted time intervals or none of the intervals is in progress ->
45+
// there is a new interval matching current time.
46+
// The monitor shall pick this new interval and notify the delegate
47+
// immediately about the start of the restricted interval.
48+
class UpdateTimeRestrictionsMonitor {
49+
public:
50+
// Interface to handle start of a restricted time interval.
51+
class Delegate {
52+
public:
53+
virtual ~Delegate() = default;
54+
55+
virtual void OnRestrictedIntervalStarts() = 0;
56+
};
57+
58+
// Creates an instance and starts monitoring the next nearest restricted time
59+
// interval if present. If no intervals are available yet the monitor will be
60+
// idle until intervals list changes.
61+
UpdateTimeRestrictionsMonitor(DevicePolicyProvider* device_policy_provider,
62+
Delegate* delegate);
63+
64+
UpdateTimeRestrictionsMonitor(const UpdateTimeRestrictionsMonitor&) = delete;
65+
UpdateTimeRestrictionsMonitor& operator=(
66+
const UpdateTimeRestrictionsMonitor&) = delete;
67+
68+
~UpdateTimeRestrictionsMonitor();
69+
70+
bool IsMonitoringInterval() {
71+
return timeout_event_ != brillo::MessageLoop::kTaskIdNull;
72+
}
73+
74+
private:
75+
// Starts monitoring the start of nearest restricted time interval if present
76+
// and any change in restricted time intervals from policy.
77+
void StartMonitoring();
78+
void WaitForRestrictedIntervalStarts(
79+
const WeeklyTimeIntervalVector& restricted_time_intervals);
80+
81+
// Called when current time lies within a restricted interval.
82+
void HandleRestrictedIntervalStarts();
83+
84+
// Stop monotoring any restricted intervals.
85+
void StopMonitoring();
86+
87+
// Called upon change of restricted intervals.
88+
void OnIntervalsChanged();
89+
90+
// To access restricted time intervals from |device_policy_provider_|.
91+
EvaluationContext evaluation_context_;
92+
93+
DevicePolicyProvider* const device_policy_provider_;
94+
Delegate* const delegate_;
95+
96+
// The TaskId returned by the message loop identifying the timeout callback.
97+
// Used for cancelling the timeout callback.
98+
brillo::MessageLoop::TaskId timeout_event_{brillo::MessageLoop::kTaskIdNull};
99+
100+
base::WeakPtrFactory<UpdateTimeRestrictionsMonitor> weak_ptr_factory_;
101+
};
102+
103+
} // namespace chromeos_update_manager
104+
105+
#endif // UPDATE_ENGINE_UPDATE_MANAGER_UPDATE_TIME_RESTRICTIONS_MONITOR_H_

0 commit comments

Comments
 (0)