1aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
2aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// Copyright (C) 2014 The Android Open Source Project
3aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
4aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// Licensed under the Apache License, Version 2.0 (the "License");
5aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// you may not use this file except in compliance with the License.
6aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// You may obtain a copy of the License at
7aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
8aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//      http://www.apache.org/licenses/LICENSE-2.0
9aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
10aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// Unless required by applicable law or agreed to in writing, software
11aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// distributed under the License is distributed on an "AS IS" BASIS,
12aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// See the License for the specific language governing permissions and
14aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// limitations under the License.
15aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
1623949d4e086ca984ca2ce07efb6d4ae2bc5daf42Alex Deymo
1763784a578dd26880454d70797519358a2326291bAlex Deymo#include "update_engine/update_manager/evaluation_context.h"
1823949d4e086ca984ca2ce07efb6d4ae2bc5daf42Alex Deymo
19f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold#include <algorithm>
2002f7c1dee242f490143791dbb73fa23fa3007cfaBen Chan#include <memory>
21c14902888be0b8d41759e6ff0a7100af4097fd09David Zeuthen#include <string>
22067053eea5711adb79307f290f05fd0a876be0ebBen Chan#include <utility>
23c14902888be0b8d41759e6ff0a7100af4097fd09David Zeuthen
2453556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo#include <base/bind.h>
25c14902888be0b8d41759e6ff0a7100af4097fd09David Zeuthen#include <base/json/json_writer.h>
260bb234147ea8f0247b733375fcf1685eaf329aacAlex Deymo#include <base/location.h>
27067053eea5711adb79307f290f05fd0a876be0ebBen Chan#include <base/memory/ptr_util.h>
286e5ab5c011a214aa345ecbba3d910c2ffaec3c83Gilad Arnold#include <base/strings/string_util.h>
29c14902888be0b8d41759e6ff0a7100af4097fd09David Zeuthen#include <base/values.h>
30c14902888be0b8d41759e6ff0a7100af4097fd09David Zeuthen
3139910dcd1d68987ccee7c3031dc269233a8490bbAlex Deymo#include "update_engine/common/utils.h"
3253556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo
3383ffddaa3b09ceb4361e5c01ba300d57ab697a7eGilad Arnoldusing base::Callback;
3453556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymousing base::Closure;
3541a75a7ca3f0252f2c9f991dd465aa332e7ce4d1Alex Deymousing base::Time;
3623949d4e086ca984ca2ce07efb6d4ae2bc5daf42Alex Deymousing base::TimeDelta;
373f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenkousing brillo::MessageLoop;
3841a75a7ca3f0252f2c9f991dd465aa332e7ce4d1Alex Deymousing chromeos_update_engine::ClockInterface;
39c14902888be0b8d41759e6ff0a7100af4097fd09David Zeuthenusing std::string;
4002f7c1dee242f490143791dbb73fa23fa3007cfaBen Chanusing std::unique_ptr;
4123949d4e086ca984ca2ce07efb6d4ae2bc5daf42Alex Deymo
42a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnoldnamespace {
43a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold
44a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold// Returns whether |curr_time| surpassed |ref_time|; if not, also checks whether
45a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold// |ref_time| is sooner than the current value of |*reeval_time|, in which case
46a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold// the latter is updated to the former.
47f329b933db41d26644a97afef928eb1b319d6d99Alex Deymobool IsTimeGreaterThanHelper(Time ref_time, Time curr_time,
48f329b933db41d26644a97afef928eb1b319d6d99Alex Deymo                             Time* reeval_time) {
49a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold  if (curr_time > ref_time)
50a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold    return true;
51a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold  // Remember the nearest reference we've checked against in this evaluation.
52a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold  if (*reeval_time > ref_time)
53a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold    *reeval_time = ref_time;
54a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold  return false;
55a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold}
56a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold
57a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold// If |expires| never happens (maximal value), returns the maximal interval;
58a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold// otherwise, returns the difference between |expires| and |curr|.
59f329b933db41d26644a97afef928eb1b319d6d99Alex DeymoTimeDelta GetTimeout(Time curr, Time expires) {
60a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold  if (expires.is_max())
61a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold    return TimeDelta::Max();
62a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold  return expires - curr;
63a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold}
64a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold
65a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold}  // namespace
66a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold
6763784a578dd26880454d70797519358a2326291bAlex Deymonamespace chromeos_update_manager {
6823949d4e086ca984ca2ce07efb6d4ae2bc5daf42Alex Deymo
6983ffddaa3b09ceb4361e5c01ba300d57ab697a7eGilad ArnoldEvaluationContext::EvaluationContext(
7083ffddaa3b09ceb4361e5c01ba300d57ab697a7eGilad Arnold    ClockInterface* clock,
7183ffddaa3b09ceb4361e5c01ba300d57ab697a7eGilad Arnold    TimeDelta evaluation_timeout,
7283ffddaa3b09ceb4361e5c01ba300d57ab697a7eGilad Arnold    TimeDelta expiration_timeout,
7302f7c1dee242f490143791dbb73fa23fa3007cfaBen Chan    unique_ptr<Callback<void(EvaluationContext*)>> unregister_cb)
7441a75a7ca3f0252f2c9f991dd465aa332e7ce4d1Alex Deymo    : clock_(clock),
75b227199133f2d694414293697c67599a761f23beGilad Arnold      evaluation_timeout_(evaluation_timeout),
76fd45a731d9f9176ce134b34e2a84acc0cf403d1dGilad Arnold      expiration_timeout_(expiration_timeout),
7702f7c1dee242f490143791dbb73fa23fa3007cfaBen Chan      unregister_cb_(std::move(unregister_cb)),
7841a75a7ca3f0252f2c9f991dd465aa332e7ce4d1Alex Deymo      weak_ptr_factory_(this) {
7941a75a7ca3f0252f2c9f991dd465aa332e7ce4d1Alex Deymo  ResetEvaluation();
80fd45a731d9f9176ce134b34e2a84acc0cf403d1dGilad Arnold  ResetExpiration();
8141a75a7ca3f0252f2c9f991dd465aa332e7ce4d1Alex Deymo}
8241a75a7ca3f0252f2c9f991dd465aa332e7ce4d1Alex Deymo
8353556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex DeymoEvaluationContext::~EvaluationContext() {
8453556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo  RemoveObserversAndTimeout();
8583ffddaa3b09ceb4361e5c01ba300d57ab697a7eGilad Arnold  if (unregister_cb_.get())
8683ffddaa3b09ceb4361e5c01ba300d57ab697a7eGilad Arnold    unregister_cb_->Run(this);
8753556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo}
8853556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo
8902f7c1dee242f490143791dbb73fa23fa3007cfaBen Chanunique_ptr<Closure> EvaluationContext::RemoveObserversAndTimeout() {
9053556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo  for (auto& it : value_cache_) {
9153556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo    if (it.first->GetMode() == kVariableModeAsync)
9253556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo      it.first->RemoveObserver(this);
9353556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo  }
94509dd5376f47e38d18fe7d29da776e3dc9a9786dAlex Deymo  MessageLoop::current()->CancelTask(timeout_event_);
95509dd5376f47e38d18fe7d29da776e3dc9a9786dAlex Deymo  timeout_event_ = MessageLoop::kTaskIdNull;
9683ffddaa3b09ceb4361e5c01ba300d57ab697a7eGilad Arnold
97ce8c8ee8f9df9bea3b5aedf930dfeba5da46031cAlex Vakulenko  return std::move(callback_);
9853556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo}
9953556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo
100f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad ArnoldTimeDelta EvaluationContext::RemainingTime(Time monotonic_deadline) const {
101f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold  if (monotonic_deadline.is_max())
102f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold    return TimeDelta::Max();
103f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold  TimeDelta remaining = monotonic_deadline - clock_->GetMonotonicTime();
104f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold  return std::max(remaining, TimeDelta());
105f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold}
106f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold
107f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad ArnoldTime EvaluationContext::MonotonicDeadline(TimeDelta timeout) {
108f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold  return (timeout.is_max() ? Time::Max() :
109f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold          clock_->GetMonotonicTime() + timeout);
11023949d4e086ca984ca2ce07efb6d4ae2bc5daf42Alex Deymo}
11123949d4e086ca984ca2ce07efb6d4ae2bc5daf42Alex Deymo
11253556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymovoid EvaluationContext::ValueChanged(BaseVariable* var) {
113f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold  DLOG(INFO) << "ValueChanged() called for variable " << var->GetName();
114f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold  OnValueChangedOrTimeout();
11553556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo}
11653556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo
117f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnoldvoid EvaluationContext::OnTimeout() {
118f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold  DLOG(INFO) << "OnTimeout() called due to "
119f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold             << (timeout_marks_expiration_ ? "expiration" : "poll interval");
120509dd5376f47e38d18fe7d29da776e3dc9a9786dAlex Deymo  timeout_event_ = MessageLoop::kTaskIdNull;
121f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold  is_expired_ = timeout_marks_expiration_;
122f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold  OnValueChangedOrTimeout();
12353556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo}
12453556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo
125f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnoldvoid EvaluationContext::OnValueChangedOrTimeout() {
126f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold  // Copy the callback handle locally, allowing it to be reassigned.
12702f7c1dee242f490143791dbb73fa23fa3007cfaBen Chan  unique_ptr<Closure> callback = RemoveObserversAndTimeout();
128f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold
129f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold  if (callback.get())
130fb794f4b7274576e10b0df291655ad6c88a97df4Gilad Arnold    callback->Run();
13141a75a7ca3f0252f2c9f991dd465aa332e7ce4d1Alex Deymo}
13241a75a7ca3f0252f2c9f991dd465aa332e7ce4d1Alex Deymo
133f329b933db41d26644a97afef928eb1b319d6d99Alex Deymobool EvaluationContext::IsWallclockTimeGreaterThan(Time timestamp) {
134a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold  return IsTimeGreaterThanHelper(timestamp, evaluation_start_wallclock_,
135a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold                                 &reevaluation_time_wallclock_);
136a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold}
137a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold
138f329b933db41d26644a97afef928eb1b319d6d99Alex Deymobool EvaluationContext::IsMonotonicTimeGreaterThan(Time timestamp) {
139a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold  return IsTimeGreaterThanHelper(timestamp, evaluation_start_monotonic_,
140a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold                                 &reevaluation_time_monotonic_);
14141a75a7ca3f0252f2c9f991dd465aa332e7ce4d1Alex Deymo}
14241a75a7ca3f0252f2c9f991dd465aa332e7ce4d1Alex Deymo
14341a75a7ca3f0252f2c9f991dd465aa332e7ce4d1Alex Deymovoid EvaluationContext::ResetEvaluation() {
144a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold  evaluation_start_wallclock_ = clock_->GetWallclockTime();
145a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold  evaluation_start_monotonic_ = clock_->GetMonotonicTime();
146a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold  reevaluation_time_wallclock_ = Time::Max();
147a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold  reevaluation_time_monotonic_ = Time::Max();
148f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold  evaluation_monotonic_deadline_ = MonotonicDeadline(evaluation_timeout_);
14941a75a7ca3f0252f2c9f991dd465aa332e7ce4d1Alex Deymo
15053556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo  // Remove the cached values of non-const variables
15153556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo  for (auto it = value_cache_.begin(); it != value_cache_.end(); ) {
15253556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo    if (it->first->GetMode() == kVariableModeConst) {
15353556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo      ++it;
15453556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo    } else {
15553556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo      it = value_cache_.erase(it);
15653556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo    }
15753556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo  }
15853556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo}
15953556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo
160fd45a731d9f9176ce134b34e2a84acc0cf403d1dGilad Arnoldvoid EvaluationContext::ResetExpiration() {
161fd45a731d9f9176ce134b34e2a84acc0cf403d1dGilad Arnold  expiration_monotonic_deadline_ = MonotonicDeadline(expiration_timeout_);
162fd45a731d9f9176ce134b34e2a84acc0cf403d1dGilad Arnold  is_expired_ = false;
163fd45a731d9f9176ce134b34e2a84acc0cf403d1dGilad Arnold}
164fd45a731d9f9176ce134b34e2a84acc0cf403d1dGilad Arnold
16553556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymobool EvaluationContext::RunOnValueChangeOrTimeout(Closure callback) {
166f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold  // Check that the method was not called more than once.
16788b591f24cb3f94f982d7024c2e8ed25c2cc26a2Alex Vakulenko  if (callback_.get()) {
168f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold    LOG(ERROR) << "RunOnValueChangeOrTimeout called more than once.";
169f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold    return false;
17041a75a7ca3f0252f2c9f991dd465aa332e7ce4d1Alex Deymo  }
17141a75a7ca3f0252f2c9f991dd465aa332e7ce4d1Alex Deymo
172f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold  // Check that the context did not yet expire.
173f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold  if (is_expired()) {
174f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold    LOG(ERROR) << "RunOnValueChangeOrTimeout called on an expired context.";
17553556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo    return false;
17653556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo  }
17753556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo
178a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold  // Handle reevaluation due to a Is{Wallclock,Monotonic}TimeGreaterThan(). We
179a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold  // choose the smaller of the differences between evaluation start time and
180a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold  // reevaluation time among the wallclock and monotonic scales.
181a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold  TimeDelta timeout = std::min(
182a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold      GetTimeout(evaluation_start_wallclock_, reevaluation_time_wallclock_),
183a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold      GetTimeout(evaluation_start_monotonic_, reevaluation_time_monotonic_));
184f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold
185f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold  // Handle reevaluation due to async or poll variables.
186a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold  bool waiting_for_value_change = false;
18753556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo  for (auto& it : value_cache_) {
18853556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo    switch (it.first->GetMode()) {
18953556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo      case kVariableModeAsync:
19053556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo        DLOG(INFO) << "Waiting for value on " << it.first->GetName();
19153556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo        it.first->AddObserver(this);
192f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold        waiting_for_value_change = true;
19353556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo        break;
19453556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo      case kVariableModePoll:
195f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold        timeout = std::min(timeout, it.first->GetPollInterval());
19653556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo        break;
19753556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo      case kVariableModeConst:
19853556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo        // Ignored.
19953556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo        break;
20053556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo    }
20153556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo  }
202f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold
20353556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo  // Check if the re-evaluation is actually being scheduled. If there are no
20453556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo  // events waited for, this function should return false.
205f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold  if (!waiting_for_value_change && timeout.is_max())
20653556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo    return false;
207f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold
208f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold  // Ensure that we take into account the expiration timeout.
209f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold  TimeDelta expiration = RemainingTime(expiration_monotonic_deadline_);
210f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold  timeout_marks_expiration_ = expiration < timeout;
211f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold  if (timeout_marks_expiration_)
212f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold    timeout = expiration;
213f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold
214f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold  // Store the reevaluation callback.
215f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold  callback_.reset(new Closure(callback));
216f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold
217f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold  // Schedule a timeout event, if one is set.
218f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold  if (!timeout.is_max()) {
219f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold    DLOG(INFO) << "Waiting for timeout in "
220f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold               << chromeos_update_engine::utils::FormatTimeDelta(timeout);
221509dd5376f47e38d18fe7d29da776e3dc9a9786dAlex Deymo    timeout_event_ = MessageLoop::current()->PostDelayedTask(
2220bb234147ea8f0247b733375fcf1685eaf329aacAlex Deymo        FROM_HERE,
223f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold        base::Bind(&EvaluationContext::OnTimeout,
224db799534a8f6ae061ed6d6a46ed800f55d50325bAlex Deymo                   weak_ptr_factory_.GetWeakPtr()),
225f9f85d6680164064648ce3ed1d31589e1f1b7a29Gilad Arnold        timeout);
22653556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo  }
22753556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo
22853556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo  return true;
22953556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo}
23053556eccd206bacd5c9c8bb6605bcceb1bcb6190Alex Deymo
231c14902888be0b8d41759e6ff0a7100af4097fd09David Zeuthenstring EvaluationContext::DumpContext() const {
232067053eea5711adb79307f290f05fd0a876be0ebBen Chan  auto variables = base::MakeUnique<base::DictionaryValue>();
233c14902888be0b8d41759e6ff0a7100af4097fd09David Zeuthen  for (auto& it : value_cache_) {
234c14902888be0b8d41759e6ff0a7100af4097fd09David Zeuthen    variables->SetString(it.first->GetName(), it.second.ToString());
235c14902888be0b8d41759e6ff0a7100af4097fd09David Zeuthen  }
236c14902888be0b8d41759e6ff0a7100af4097fd09David Zeuthen
237c14902888be0b8d41759e6ff0a7100af4097fd09David Zeuthen  base::DictionaryValue value;
238067053eea5711adb79307f290f05fd0a876be0ebBen Chan  value.Set("variables", std::move(variables));
239a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold  value.SetString(
240a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold      "evaluation_start_wallclock",
241a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold      chromeos_update_engine::utils::ToString(evaluation_start_wallclock_));
242a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold  value.SetString(
243a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold      "evaluation_start_monotonic",
244a65fced5f4c2b551616b26ee90a800b44090735fGilad Arnold      chromeos_update_engine::utils::ToString(evaluation_start_monotonic_));
245c14902888be0b8d41759e6ff0a7100af4097fd09David Zeuthen
246c14902888be0b8d41759e6ff0a7100af4097fd09David Zeuthen  string json_str;
2476a9d3497bcf57b8b9f5765a2909a51c9f8119cd1Alex Vakulenko  base::JSONWriter::WriteWithOptions(
2486a9d3497bcf57b8b9f5765a2909a51c9f8119cd1Alex Vakulenko      value, base::JSONWriter::OPTIONS_PRETTY_PRINT, &json_str);
2496e5ab5c011a214aa345ecbba3d910c2ffaec3c83Gilad Arnold  base::TrimWhitespaceASCII(json_str, base::TRIM_TRAILING, &json_str);
250c14902888be0b8d41759e6ff0a7100af4097fd09David Zeuthen
251c14902888be0b8d41759e6ff0a7100af4097fd09David Zeuthen  return json_str;
252c14902888be0b8d41759e6ff0a7100af4097fd09David Zeuthen}
253c14902888be0b8d41759e6ff0a7100af4097fd09David Zeuthen
25463784a578dd26880454d70797519358a2326291bAlex Deymo}  // namespace chromeos_update_manager
255