1 //
2 // Copyright (C) 2014 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_MANAGER_H_
18 #define UPDATE_ENGINE_UPDATE_MANAGER_UPDATE_MANAGER_H_
19 
20 #include <memory>
21 #include <set>
22 #include <string>
23 
24 #include <base/callback.h>
25 #include <base/time/time.h>
26 
27 #include "update_engine/common/system_state.h"
28 #include "update_engine/update_manager/default_policy.h"
29 #include "update_engine/update_manager/evaluation_context.h"
30 #include "update_engine/update_manager/policy.h"
31 #include "update_engine/update_manager/state.h"
32 
33 namespace chromeos_update_manager {
34 
35 // Please do not move this class into a new file for simplicity.
36 // This pure virtual class is purely created for purpose of testing. The reason
37 // was that |UpdateManager|'s member functions are templatized, which does not
38 // play nicely when testing (mocking + faking). Whenever a specialized member of
39 // |UpdateManager| must be tested, please add a specialized template member
40 // function within this class for testing.
41 class SpecializedPolicyRequestInterface {
42  public:
43   virtual ~SpecializedPolicyRequestInterface() = default;
44 
45   virtual void AsyncPolicyRequestUpdateCheckAllowed(
46       base::Callback<void(EvalStatus, const UpdateCheckParams& result)>
47           callback,
48       EvalStatus (Policy::*policy_method)(EvaluationContext*,
49                                           State*,
50                                           std::string*,
51                                           UpdateCheckParams*) const) = 0;
52 };
53 
54 // The main Update Manager singleton class.
55 class UpdateManager : public SpecializedPolicyRequestInterface {
56  public:
57   // Creates the UpdateManager instance, assuming ownership on the provided
58   // |state|.
59   UpdateManager(base::TimeDelta evaluation_timeout,
60                 base::TimeDelta expiration_timeout,
61                 State* state);
62 
63   virtual ~UpdateManager();
64 
65   // PolicyRequest() evaluates the given policy with the provided arguments and
66   // returns the result. The |policy_method| is the pointer-to-method of the
67   // Policy class for the policy request to call. The UpdateManager will call
68   // this method on the right policy. The pointer |result| must not be null
69   // and the remaining |args| depend on the arguments required by the passed
70   // |policy_method|.
71   //
72   // When the policy request succeeds, the |result| is set and the method
73   // returns EvalStatus::kSucceeded, otherwise, the |result| may not be set.  A
74   // policy called with this method should not block (i.e. return
75   // EvalStatus::kAskMeAgainLater), which is considered a programming error. On
76   // failure, EvalStatus::kFailed is returned.
77   //
78   // An example call to this method is:
79   //   um.PolicyRequest(&Policy::SomePolicyMethod, &bool_result, arg1, arg2);
80   template <typename R, typename... ActualArgs, typename... ExpectedArgs>
81   EvalStatus PolicyRequest(
82       EvalStatus (Policy::*policy_method)(
83           EvaluationContext*, State*, std::string*, R*, ExpectedArgs...) const,
84       R* result,
85       ActualArgs...);
86 
87   // Evaluates the given |policy_method| policy with the provided |args|
88   // arguments and calls the |callback| callback with the result when done.
89   //
90   // If the policy implementation should block, returning a
91   // EvalStatus::kAskMeAgainLater status the Update Manager will re-evaluate the
92   // policy until another status is returned. If the policy implementation based
93   // its return value solely on const variables, the callback will be called
94   // with the EvalStatus::kAskMeAgainLater status (which indicates an error).
95   template <typename R, typename... ActualArgs, typename... ExpectedArgs>
96   void AsyncPolicyRequest(
97       base::Callback<void(EvalStatus, const R& result)> callback,
98       EvalStatus (Policy::*policy_method)(
99           EvaluationContext*, State*, std::string*, R*, ExpectedArgs...) const,
100       ActualArgs... args);
101 
102   void AsyncPolicyRequestUpdateCheckAllowed(
103       base::Callback<void(EvalStatus, const UpdateCheckParams& result)>
104           callback,
105       EvalStatus (Policy::*policy_method)(EvaluationContext*,
106                                           State*,
107                                           std::string*,
108                                           UpdateCheckParams*) const) override;
109 
110  protected:
111   // The UpdateManager receives ownership of the passed Policy instance.
set_policy(const Policy * policy)112   void set_policy(const Policy* policy) { policy_.reset(policy); }
113 
114   // State getter used for testing.
state()115   State* state() { return state_.get(); }
116 
117  private:
118   FRIEND_TEST(UmUpdateManagerTest, PolicyRequestCallsPolicy);
119   FRIEND_TEST(UmUpdateManagerTest, PolicyRequestCallsDefaultOnError);
120   FRIEND_TEST(UmUpdateManagerTest, PolicyRequestDoesntBlockDeathTest);
121   FRIEND_TEST(UmUpdateManagerTest, AsyncPolicyRequestDelaysEvaluation);
122   FRIEND_TEST(UmUpdateManagerTest, AsyncPolicyRequestTimeoutDoesNotFire);
123   FRIEND_TEST(UmUpdateManagerTest, AsyncPolicyRequestTimesOut);
124 
125   // EvaluatePolicy() evaluates the passed |policy_method| method on the current
126   // policy with the given |args| arguments. If the method fails, the default
127   // policy is used instead.
128   template <typename R, typename... Args>
129   EvalStatus EvaluatePolicy(
130       EvaluationContext* ec,
131       EvalStatus (Policy::*policy_method)(
132           EvaluationContext*, State*, std::string*, R*, Args...) const,
133       R* result,
134       Args... args);
135 
136   // OnPolicyReadyToEvaluate() is called by the main loop when the evaluation
137   // of the given |policy_method| should be executed. If the evaluation finishes
138   // the |callback| callback is called passing the |result| and the |status|
139   // returned by the policy. If the evaluation returns an
140   // EvalStatus::kAskMeAgainLater state, the |callback| will NOT be called and
141   // the evaluation will be re-scheduled to be called later.
142   template <typename R, typename... Args>
143   void OnPolicyReadyToEvaluate(
144       std::shared_ptr<EvaluationContext> ec,
145       base::Callback<void(EvalStatus status, const R& result)> callback,
146       EvalStatus (Policy::*policy_method)(
147           EvaluationContext*, State*, std::string*, R*, Args...) const,
148       Args... args);
149 
150   // Unregisters (removes from repo) a previously created EvaluationContext.
151   void UnregisterEvalContext(EvaluationContext* ec);
152 
153   // The policy used by the UpdateManager. Note that since it is a const Policy,
154   // policy implementations are not allowed to persist state on this class.
155   std::unique_ptr<const Policy> policy_;
156 
157   // A safe default value to the current policy. This policy is used whenever
158   // a policy implementation fails with EvalStatus::kFailed.
159   const DefaultPolicy default_policy_;
160 
161   // State Providers.
162   std::unique_ptr<State> state_;
163 
164   // Timeout for a policy evaluation.
165   const base::TimeDelta evaluation_timeout_;
166 
167   // Timeout for expiration of the evaluation context, used for async requests.
168   const base::TimeDelta expiration_timeout_;
169 
170   // Repository of previously created EvaluationContext objects. These are being
171   // unregistered (and the reference released) when the context is being
172   // destructed; alternatively, when the UpdateManager instance is destroyed, it
173   // will remove all pending events associated with all outstanding contexts
174   // (which should, in turn, trigger their destruction).
175   std::set<std::shared_ptr<EvaluationContext>> ec_repo_;
176 
177   base::WeakPtrFactory<UpdateManager> weak_ptr_factory_;
178 
179   DISALLOW_COPY_AND_ASSIGN(UpdateManager);
180 };
181 
182 }  // namespace chromeos_update_manager
183 
184 // Include the implementation of the template methods.
185 #include "update_engine/update_manager/update_manager-inl.h"
186 
187 #endif  // UPDATE_ENGINE_UPDATE_MANAGER_UPDATE_MANAGER_H_
188