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