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#pragma once
17
18#include <gtest/gtest_prod.h>
19#include "ConditionTracker.h"
20#include "config/ConfigKey.h"
21#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
22#include "stats_util.h"
23
24namespace android {
25namespace os {
26namespace statsd {
27
28class StateTracker : public virtual ConditionTracker {
29public:
30    StateTracker(const ConfigKey& key, const int64_t& id, const int index,
31                 const SimplePredicate& simplePredicate,
32                 const std::unordered_map<int64_t, int>& trackerNameIndexMap,
33                 const vector<Matcher> primaryKeys);
34
35    ~StateTracker();
36
37    bool init(const std::vector<Predicate>& allConditionConfig,
38              const std::vector<sp<ConditionTracker>>& allConditionTrackers,
39              const std::unordered_map<int64_t, int>& conditionIdIndexMap,
40              std::vector<bool>& stack) override;
41
42    void evaluateCondition(const LogEvent& event,
43                           const std::vector<MatchingState>& eventMatcherValues,
44                           const std::vector<sp<ConditionTracker>>& mAllConditions,
45                           std::vector<ConditionState>& conditionCache,
46                           std::vector<bool>& changedCache) override;
47
48    /**
49     * Note: dimensionFields will be ignored in StateTracker, because we demand metrics
50     * must take the entire dimension fields from StateTracker. This is to make implementation
51     * simple and efficient.
52     *
53     * For example: wakelock duration by uid process states:
54     *              dimension in condition must be {uid, process state}.
55     */
56    void isConditionMet(const ConditionKey& conditionParameters,
57                        const std::vector<sp<ConditionTracker>>& allConditions,
58                        const vector<Matcher>& dimensionFields,
59                        const bool isSubOutputDimensionFields,
60                        const bool isPartialLink,
61                        std::vector<ConditionState>& conditionCache,
62                        std::unordered_set<HashableDimensionKey>& dimensionsKeySet) const override;
63
64    /**
65     * Note: dimensionFields will be ignored in StateTracker, because we demand metrics
66     * must take the entire dimension fields from StateTracker. This is to make implementation
67     * simple and efficient.
68     */
69    ConditionState getMetConditionDimension(
70            const std::vector<sp<ConditionTracker>>& allConditions,
71            const vector<Matcher>& dimensionFields,
72            const bool isSubOutputDimensionFields,
73            std::unordered_set<HashableDimensionKey>& dimensionsKeySet) const override;
74
75    virtual const std::set<HashableDimensionKey>* getChangedToTrueDimensions(
76            const std::vector<sp<ConditionTracker>>& allConditions) const {
77        return &mLastChangedToTrueDimensions;
78    }
79
80    virtual const std::set<HashableDimensionKey>* getChangedToFalseDimensions(
81            const std::vector<sp<ConditionTracker>>& allConditions) const {
82        return &mLastChangedToFalseDimensions;
83    }
84
85    bool IsChangedDimensionTrackable() const  override { return true; }
86
87    bool IsSimpleCondition() const  override { return true; }
88
89    bool equalOutputDimensions(
90        const std::vector<sp<ConditionTracker>>& allConditions,
91        const vector<Matcher>& dimensions) const override {
92            return equalDimensions(mOutputDimensions, dimensions);
93    }
94
95    void getTrueSlicedDimensions(
96            const std::vector<sp<ConditionTracker>>& allConditions,
97            std::set<HashableDimensionKey>* dimensions) const override {
98        for (const auto& itr : mSlicedState) {
99            dimensions->insert(itr.second);
100        }
101    }
102
103private:
104    const ConfigKey mConfigKey;
105
106    // The index of the LogEventMatcher which defines the start.
107    int mStartLogMatcherIndex;
108
109    std::set<HashableDimensionKey> mLastChangedToTrueDimensions;
110    std::set<HashableDimensionKey> mLastChangedToFalseDimensions;
111
112    std::vector<Matcher> mOutputDimensions;
113    std::vector<Matcher> mPrimaryKeys;
114
115    ConditionState mInitialValue;
116
117    int mDimensionTag;
118
119    void dumpState();
120
121    bool hitGuardRail(const HashableDimensionKey& newKey);
122
123    // maps from [primary_key] to [primary_key, exclusive_state].
124    std::unordered_map<HashableDimensionKey, HashableDimensionKey> mSlicedState;
125
126    FRIEND_TEST(StateTrackerTest, TestStateChange);
127};
128
129}  // namespace statsd
130}  // namespace os
131}  // namespace android