| // | 
 | // Copyright (C) 2014 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_UPDATE_MANAGER_H_ | 
 | #define UPDATE_ENGINE_UPDATE_MANAGER_UPDATE_MANAGER_H_ | 
 |  | 
 | #include <memory> | 
 | #include <set> | 
 | #include <string> | 
 |  | 
 | #include <base/callback.h> | 
 | #include <base/memory/ref_counted.h> | 
 | #include <base/time/time.h> | 
 |  | 
 | #include "update_engine/common/clock_interface.h" | 
 | #include "update_engine/update_manager/default_policy.h" | 
 | #include "update_engine/update_manager/evaluation_context.h" | 
 | #include "update_engine/update_manager/policy.h" | 
 | #include "update_engine/update_manager/state.h" | 
 |  | 
 | namespace chromeos_update_manager { | 
 |  | 
 | // Comparator for scoped_refptr objects. | 
 | template<typename T> | 
 | struct ScopedRefPtrLess { | 
 |   bool operator()(const scoped_refptr<T>& first, | 
 |                   const scoped_refptr<T>& second) const { | 
 |     return first.get() < second.get(); | 
 |   } | 
 | }; | 
 |  | 
 | // The main Update Manager singleton class. | 
 | class UpdateManager { | 
 |  public: | 
 |   // Creates the UpdateManager instance, assuming ownership on the provided | 
 |   // |state|. | 
 |   UpdateManager(chromeos_update_engine::ClockInterface* clock, | 
 |                 base::TimeDelta evaluation_timeout, | 
 |                 base::TimeDelta expiration_timeout, State* state); | 
 |  | 
 |   virtual ~UpdateManager(); | 
 |  | 
 |   // PolicyRequest() evaluates the given policy with the provided arguments and | 
 |   // returns the result. The |policy_method| is the pointer-to-method of the | 
 |   // Policy class for the policy request to call. The UpdateManager will call | 
 |   // this method on the right policy. The pointer |result| must not be null | 
 |   // and the remaining |args| depend on the arguments required by the passed | 
 |   // |policy_method|. | 
 |   // | 
 |   // When the policy request succeeds, the |result| is set and the method | 
 |   // returns EvalStatus::kSucceeded, otherwise, the |result| may not be set.  A | 
 |   // policy called with this method should not block (i.e. return | 
 |   // EvalStatus::kAskMeAgainLater), which is considered a programming error. On | 
 |   // failure, EvalStatus::kFailed is returned. | 
 |   // | 
 |   // An example call to this method is: | 
 |   //   um.PolicyRequest(&Policy::SomePolicyMethod, &bool_result, arg1, arg2); | 
 |   template<typename R, typename... ActualArgs, typename... ExpectedArgs> | 
 |   EvalStatus PolicyRequest( | 
 |       EvalStatus (Policy::*policy_method)(EvaluationContext*, State*, | 
 |                                           std::string*, R*, | 
 |                                           ExpectedArgs...) const, | 
 |       R* result, ActualArgs...); | 
 |  | 
 |   // Evaluates the given |policy_method| policy with the provided |args| | 
 |   // arguments and calls the |callback| callback with the result when done. | 
 |   // | 
 |   // If the policy implementation should block, returning a | 
 |   // EvalStatus::kAskMeAgainLater status the Update Manager will re-evaluate the | 
 |   // policy until another status is returned. If the policy implementation based | 
 |   // its return value solely on const variables, the callback will be called | 
 |   // with the EvalStatus::kAskMeAgainLater status (which indicates an error). | 
 |   template<typename R, typename... ActualArgs, typename... ExpectedArgs> | 
 |   void AsyncPolicyRequest( | 
 |       base::Callback<void(EvalStatus, const R& result)> callback, | 
 |       EvalStatus (Policy::*policy_method)(EvaluationContext*, State*, | 
 |                                           std::string*, R*, | 
 |                                           ExpectedArgs...) const, | 
 |       ActualArgs... args); | 
 |  | 
 |  protected: | 
 |   // The UpdateManager receives ownership of the passed Policy instance. | 
 |   void set_policy(const Policy* policy) { | 
 |     policy_.reset(policy); | 
 |   } | 
 |  | 
 |   // State getter used for testing. | 
 |   State* state() { return state_.get(); } | 
 |  | 
 |  private: | 
 |   FRIEND_TEST(UmUpdateManagerTest, PolicyRequestCallsPolicy); | 
 |   FRIEND_TEST(UmUpdateManagerTest, PolicyRequestCallsDefaultOnError); | 
 |   FRIEND_TEST(UmUpdateManagerTest, PolicyRequestDoesntBlockDeathTest); | 
 |   FRIEND_TEST(UmUpdateManagerTest, AsyncPolicyRequestDelaysEvaluation); | 
 |   FRIEND_TEST(UmUpdateManagerTest, AsyncPolicyRequestTimeoutDoesNotFire); | 
 |   FRIEND_TEST(UmUpdateManagerTest, AsyncPolicyRequestTimesOut); | 
 |  | 
 |   // EvaluatePolicy() evaluates the passed |policy_method| method on the current | 
 |   // policy with the given |args| arguments. If the method fails, the default | 
 |   // policy is used instead. | 
 |   template<typename R, typename... Args> | 
 |   EvalStatus EvaluatePolicy( | 
 |       EvaluationContext* ec, | 
 |       EvalStatus (Policy::*policy_method)(EvaluationContext*, State*, | 
 |                                           std::string*, R*, | 
 |                                           Args...) const, | 
 |       R* result, Args... args); | 
 |  | 
 |   // OnPolicyReadyToEvaluate() is called by the main loop when the evaluation | 
 |   // of the given |policy_method| should be executed. If the evaluation finishes | 
 |   // the |callback| callback is called passing the |result| and the |status| | 
 |   // returned by the policy. If the evaluation returns an | 
 |   // EvalStatus::kAskMeAgainLater state, the |callback| will NOT be called and | 
 |   // the evaluation will be re-scheduled to be called later. | 
 |   template<typename R, typename... Args> | 
 |   void OnPolicyReadyToEvaluate( | 
 |       scoped_refptr<EvaluationContext> ec, | 
 |       base::Callback<void(EvalStatus status, const R& result)> callback, | 
 |       EvalStatus (Policy::*policy_method)(EvaluationContext*, State*, | 
 |                                           std::string*, R*, | 
 |                                           Args...) const, | 
 |       Args... args); | 
 |  | 
 |   // Unregisters (removes from repo) a previously created EvaluationContext. | 
 |   void UnregisterEvalContext(EvaluationContext* ec); | 
 |  | 
 |   // The policy used by the UpdateManager. Note that since it is a const Policy, | 
 |   // policy implementations are not allowed to persist state on this class. | 
 |   std::unique_ptr<const Policy> policy_; | 
 |  | 
 |   // A safe default value to the current policy. This policy is used whenever | 
 |   // a policy implementation fails with EvalStatus::kFailed. | 
 |   const DefaultPolicy default_policy_; | 
 |  | 
 |   // State Providers. | 
 |   std::unique_ptr<State> state_; | 
 |  | 
 |   // Pointer to the mockable clock interface; | 
 |   chromeos_update_engine::ClockInterface* clock_; | 
 |  | 
 |   // Timeout for a policy evaluation. | 
 |   const base::TimeDelta evaluation_timeout_; | 
 |  | 
 |   // Timeout for expiration of the evaluation context, used for async requests. | 
 |   const base::TimeDelta expiration_timeout_; | 
 |  | 
 |   // Repository of previously created EvaluationContext objects. These are being | 
 |   // unregistered (and the reference released) when the context is being | 
 |   // destructed; alternatively, when the UpdateManager instance is destroyed, it | 
 |   // will remove all pending events associated with all outstanding contexts | 
 |   // (which should, in turn, trigger their destruction). | 
 |   std::set<scoped_refptr<EvaluationContext>, | 
 |            ScopedRefPtrLess<EvaluationContext>> ec_repo_; | 
 |  | 
 |   base::WeakPtrFactory<UpdateManager> weak_ptr_factory_; | 
 |  | 
 |   DISALLOW_COPY_AND_ASSIGN(UpdateManager); | 
 | }; | 
 |  | 
 | }  // namespace chromeos_update_manager | 
 |  | 
 | // Include the implementation of the template methods. | 
 | #include "update_engine/update_manager/update_manager-inl.h" | 
 |  | 
 | #endif  // UPDATE_ENGINE_UPDATE_MANAGER_UPDATE_MANAGER_H_ |