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