|  | // | 
|  | // 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/time/time.h> | 
|  |  | 
|  | #include "update_engine/common/system_state.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 { | 
|  |  | 
|  | // Please do not move this class into a new file for simplicity. | 
|  | // This pure virtual class is purely created for purpose of testing. The reason | 
|  | // was that |UpdateManager|'s member functions are templatized, which does not | 
|  | // play nicely when testing (mocking + faking). Whenever a specialized member of | 
|  | // |UpdateManager| must be tested, please add a specialized template member | 
|  | // function within this class for testing. | 
|  | class SpecializedPolicyRequestInterface { | 
|  | public: | 
|  | virtual ~SpecializedPolicyRequestInterface() = default; | 
|  |  | 
|  | virtual void AsyncPolicyRequestUpdateCheckAllowed( | 
|  | base::Callback<void(EvalStatus, const UpdateCheckParams& result)> | 
|  | callback, | 
|  | EvalStatus (Policy::*policy_method)(EvaluationContext*, | 
|  | State*, | 
|  | std::string*, | 
|  | UpdateCheckParams*) const) = 0; | 
|  | }; | 
|  |  | 
|  | // The main Update Manager singleton class. | 
|  | class UpdateManager : public SpecializedPolicyRequestInterface { | 
|  | public: | 
|  | // Creates the UpdateManager instance, assuming ownership on the provided | 
|  | // |state|. | 
|  | UpdateManager(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); | 
|  |  | 
|  | void AsyncPolicyRequestUpdateCheckAllowed( | 
|  | base::Callback<void(EvalStatus, const UpdateCheckParams& result)> | 
|  | callback, | 
|  | EvalStatus (Policy::*policy_method)(EvaluationContext*, | 
|  | State*, | 
|  | std::string*, | 
|  | UpdateCheckParams*) const) override; | 
|  |  | 
|  | 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( | 
|  | std::shared_ptr<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_; | 
|  |  | 
|  | // 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<std::shared_ptr<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_ |