Home | History | Annotate | Download | only in include
      1 /*
      2  * Copyright 2018 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 BTIF_STATE_MACHINE_H
     18 #define BTIF_STATE_MACHINE_H
     19 
     20 #include <map>
     21 #include <utility>
     22 
     23 #include <base/logging.h>
     24 
     25 /**
     26  * State machine used by BTIF components.
     27  */
     28 class BtifStateMachine {
     29  public:
     30   enum { kStateInvalid = -1 };
     31 
     32   /**
     33    * A class to represent the state in the State Machine.
     34    */
     35   class State {
     36     friend class BtifStateMachine;
     37 
     38    public:
     39     /**
     40      * Constructor.
     41      *
     42      * @param sm the State Machine to use
     43      * @param state_id the unique State ID. It should be a non-negative number.
     44      */
     45     State(BtifStateMachine& sm, int state_id) : sm_(sm), state_id_(state_id) {}
     46 
     47     virtual ~State() = default;
     48 
     49     /**
     50      * Process an event.
     51      * TODO: The arguments are wrong - used for backward compatibility.
     52      * Will be replaced later.
     53      *
     54      * @param event the event type
     55      * @param p_data the event data
     56      * @return true if the processing was completed, otherwise false
     57      */
     58     virtual bool ProcessEvent(uint32_t event, void* p_data) = 0;
     59 
     60     /**
     61      * Get the State ID.
     62      *
     63      * @return the State ID
     64      */
     65     int StateId() const { return state_id_; }
     66 
     67    protected:
     68     /**
     69      * Called when a state is entered.
     70      */
     71     virtual void OnEnter() {}
     72 
     73     /**
     74      * Called when a state is exited.
     75      */
     76     virtual void OnExit() {}
     77 
     78     /**
     79      * Transition the State Machine to a new state.
     80      *
     81      * @param dest_state_id the state ID to transition to. It must be one
     82      * of the unique state IDs when the corresponding state was created.
     83      */
     84     void TransitionTo(int dest_state_id) { sm_.TransitionTo(dest_state_id); }
     85 
     86     /**
     87      * Transition the State Machine to a new state.
     88      *
     89      * @param dest_state the state to transition to. It cannot be nullptr.
     90      */
     91     void TransitionTo(BtifStateMachine::State* dest_state) {
     92       sm_.TransitionTo(dest_state);
     93     }
     94 
     95    private:
     96     BtifStateMachine& sm_;
     97     int state_id_;
     98   };
     99 
    100   BtifStateMachine()
    101       : initial_state_(nullptr),
    102         previous_state_(nullptr),
    103         current_state_(nullptr) {}
    104   ~BtifStateMachine() {
    105     for (auto& kv : states_) delete kv.second;
    106   }
    107 
    108   /**
    109    * Start the State Machine operation.
    110    */
    111   void Start() { TransitionTo(initial_state_); }
    112 
    113   /**
    114    * Quit the State Machine operation.
    115    */
    116   void Quit() { previous_state_ = current_state_ = nullptr; }
    117 
    118   /**
    119    * Get the current State ID.
    120    *
    121    * @return the current State ID
    122    */
    123   int StateId() const {
    124     if (current_state_ != nullptr) {
    125       return current_state_->StateId();
    126     }
    127     return kStateInvalid;
    128   }
    129 
    130   /**
    131    * Get the previous current State ID.
    132    *
    133    * @return the previous State ID
    134    */
    135   int PreviousStateId() const {
    136     if (previous_state_ != nullptr) {
    137       return previous_state_->StateId();
    138     }
    139     return kStateInvalid;
    140   }
    141 
    142   /**
    143    * Process an event.
    144    * TODO: The arguments are wrong - used for backward compatibility.
    145    * Will be replaced later.
    146    *
    147    * @param event the event type
    148    * @param p_data the event data
    149    * @return true if the processing was completed, otherwise false
    150    */
    151   bool ProcessEvent(uint32_t event, void* p_data) {
    152     if (current_state_ == nullptr) return false;
    153     return current_state_->ProcessEvent(event, p_data);
    154   }
    155 
    156   /**
    157    * Transition the State Machine to a new state.
    158    *
    159    * @param dest_state_id the state ID to transition to. It must be one
    160    * of the unique state IDs when the corresponding state was created.
    161    */
    162   void TransitionTo(int dest_state_id) {
    163     auto it = states_.find(dest_state_id);
    164 
    165     CHECK(it != states_.end()) << "Unknown State ID: " << dest_state_id;
    166     State* dest_state = it->second;
    167     TransitionTo(dest_state);
    168   }
    169 
    170   /**
    171    * Transition the State Machine to a new state.
    172    *
    173    * @param dest_state the state to transition to. It cannot be nullptr.
    174    */
    175   void TransitionTo(BtifStateMachine::State* dest_state) {
    176     if (current_state_ != nullptr) {
    177       current_state_->OnExit();
    178     }
    179     previous_state_ = current_state_;
    180     current_state_ = dest_state;
    181     current_state_->OnEnter();
    182   }
    183 
    184   /**
    185    * Add a state to the State Machine.
    186    * The state machine takes ownership on the state - i.e., the state will
    187    * be deleted by the State Machine itself.
    188    *
    189    * @param state the state to add
    190    */
    191   void AddState(State* state) {
    192     states_.insert(std::make_pair(state->StateId(), state));
    193   }
    194 
    195   /**
    196    * Set the initial state of the State Machine.
    197    *
    198    * @param initial_state the initial state
    199    */
    200   void SetInitialState(State* initial_state) { initial_state_ = initial_state; }
    201 
    202  private:
    203   State* initial_state_;
    204   State* previous_state_;
    205   State* current_state_;
    206   std::map<int, State*> states_;
    207 };
    208 
    209 #endif  // BTIF_STATE_MACHINE_H
    210