1 /*
2  * Copyright (C) 2017 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 #pragma once
18 
19 #include "condition/condition_util.h"
20 #include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
21 #include "matchers/LogMatchingTracker.h"
22 #include "matchers/matcher_util.h"
23 
24 #include <utils/RefBase.h>
25 
26 #include <unordered_map>
27 
28 namespace android {
29 namespace os {
30 namespace statsd {
31 
32 class ConditionTracker : public virtual RefBase {
33 public:
ConditionTracker(const int64_t & id,const int index)34     ConditionTracker(const int64_t& id, const int index)
35         : mConditionId(id),
36           mIndex(index),
37           mInitialized(false),
38           mTrackerIndex(),
39           mNonSlicedConditionState(ConditionState::kUnknown),
40           mSliced(false){};
41 
~ConditionTracker()42     virtual ~ConditionTracker(){};
43 
getId()44     inline const int64_t& getId() { return mConditionId; }
45 
46     // Initialize this ConditionTracker. This initialization is done recursively (DFS). It can also
47     // be done in the constructor, but we do it separately because (1) easy to return a bool to
48     // indicate whether the initialization is successful. (2) makes unit test easier.
49     // allConditionConfig: the list of all Predicate config from statsd_config.
50     // allConditionTrackers: the list of all ConditionTrackers (this is needed because we may also
51     //                       need to call init() on children conditions)
52     // conditionIdIndexMap: the mapping from condition id to its index.
53     // stack: a bit map to keep track which nodes have been visited on the stack in the recursion.
54     virtual bool init(const std::vector<Predicate>& allConditionConfig,
55                       const std::vector<sp<ConditionTracker>>& allConditionTrackers,
56                       const std::unordered_map<int64_t, int>& conditionIdIndexMap,
57                       std::vector<bool>& stack) = 0;
58 
59     // evaluate current condition given the new event.
60     // event: the new log event
61     // eventMatcherValues: the results of the LogMatcherTrackers. LogMatcherTrackers always process
62     //                     event before ConditionTrackers, because ConditionTracker depends on
63     //                     LogMatchingTrackers.
64     // mAllConditions: the list of all ConditionTracker
65     // conditionCache: the cached non-sliced condition of the ConditionTrackers for this new event.
66     // conditionChanged: the bit map to record whether the condition has changed.
67     //                   If the condition has dimension, then any sub condition changes will report
68     //                   conditionChanged.
69     virtual void evaluateCondition(const LogEvent& event,
70                                    const std::vector<MatchingState>& eventMatcherValues,
71                                    const std::vector<sp<ConditionTracker>>& mAllConditions,
72                                    std::vector<ConditionState>& conditionCache,
73                                    std::vector<bool>& conditionChanged) = 0;
74 
75     // Return the current condition state.
isConditionMet()76     virtual ConditionState isConditionMet() const {
77         return mNonSlicedConditionState;
78     };
79 
80     // Query the condition with parameters.
81     // [conditionParameters]: a map from condition name to the HashableDimensionKey to query the
82     //                       condition.
83     // [allConditions]: all condition trackers. This is needed because the condition evaluation is
84     //                  done recursively
85     // [dimensionFields]: the needed dimension fields which should be all or subset of the condition
86     //                    tracker output dimension.
87     // [isSubOutputDimensionFields]: true if the needed dimension fields which is strictly subset of
88     //                               the condition tracker output dimension.
89     // [isPartialLink]: true if the link specified by 'conditionParameters' contains all the fields
90     //                  in the condition tracker output dimension.
91     // [conditionCache]: the cache holding the condition evaluation values.
92     // [dimensionsKeySet]: the dimensions where the sliced condition is true. For combination
93     //                    condition, it assumes that only one child predicate is sliced.
94     virtual void isConditionMet(
95             const ConditionKey& conditionParameters,
96             const std::vector<sp<ConditionTracker>>& allConditions,
97             const vector<Matcher>& dimensionFields,
98             const bool isSubOutputDimensionFields,
99             const bool isPartialLink,
100             std::vector<ConditionState>& conditionCache,
101             std::unordered_set<HashableDimensionKey>& dimensionsKeySet) const = 0;
102 
103     virtual ConditionState getMetConditionDimension(
104             const std::vector<sp<ConditionTracker>>& allConditions,
105             const vector<Matcher>& dimensionFields,
106             const bool isSubOutputDimensionFields,
107             std::unordered_set<HashableDimensionKey>& dimensionsKeySet) const = 0;
108 
109     // return the list of LogMatchingTracker index that this ConditionTracker uses.
getLogTrackerIndex()110     virtual const std::set<int>& getLogTrackerIndex() const {
111         return mTrackerIndex;
112     }
113 
setSliced(bool sliced)114     virtual void setSliced(bool sliced) {
115         mSliced = mSliced | sliced;
116     }
117 
isSliced()118     inline bool isSliced() const {
119         return mSliced;
120     }
121 
122     virtual const std::set<HashableDimensionKey>* getChangedToTrueDimensions(
123             const std::vector<sp<ConditionTracker>>& allConditions) const = 0;
124     virtual const std::set<HashableDimensionKey>* getChangedToFalseDimensions(
125             const std::vector<sp<ConditionTracker>>& allConditions) const = 0;
126 
getConditionId()127     inline int64_t getConditionId() const {
128         return mConditionId;
129     }
130 
131     virtual void getTrueSlicedDimensions(
132         const std::vector<sp<ConditionTracker>>& allConditions,
133         std::set<HashableDimensionKey>* dimensions) const = 0;
134 
135     virtual bool IsChangedDimensionTrackable() const = 0;
136 
137     virtual bool IsSimpleCondition() const = 0;
138 
139     virtual bool equalOutputDimensions(
140         const std::vector<sp<ConditionTracker>>& allConditions,
141         const vector<Matcher>& dimensions) const = 0;
142 
getUnSlicedPartConditionState()143     inline ConditionState getUnSlicedPartConditionState() const  {
144         return mUnSlicedPart;
145     }
146 
147 protected:
148     const int64_t mConditionId;
149 
150     // the index of this condition in the manager's condition list.
151     const int mIndex;
152 
153     // if it's properly initialized.
154     bool mInitialized;
155 
156     // the list of LogMatchingTracker index that this ConditionTracker uses.
157     std::set<int> mTrackerIndex;
158 
159     ConditionState mNonSlicedConditionState;
160 
161     bool mSliced;
162     ConditionState mUnSlicedPart;
163 };
164 
165 }  // namespace statsd
166 }  // namespace os
167 }  // namespace android
168