Home | History | Annotate | Download | only in condition
      1 // Copyright (C) 2017 The Android Open Source Project
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //      http://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 
     15 #include "src/condition/SimpleConditionTracker.h"
     16 #include "tests/statsd_test_util.h"
     17 
     18 #include <gmock/gmock.h>
     19 #include <gtest/gtest.h>
     20 #include <stdio.h>
     21 #include <vector>
     22 #include <numeric>
     23 
     24 using std::map;
     25 using std::unordered_map;
     26 using std::vector;
     27 
     28 #ifdef __ANDROID__
     29 
     30 namespace android {
     31 namespace os {
     32 namespace statsd {
     33 
     34 const ConfigKey kConfigKey(0, 12345);
     35 
     36 const int ATTRIBUTION_NODE_FIELD_ID = 1;
     37 const int ATTRIBUTION_UID_FIELD_ID = 1;
     38 const int TAG_ID = 1;
     39 
     40 SimplePredicate getWakeLockHeldCondition(bool countNesting, bool defaultFalse,
     41                                          bool outputSlicedUid, Position position) {
     42     SimplePredicate simplePredicate;
     43     simplePredicate.set_start(StringToId("WAKE_LOCK_ACQUIRE"));
     44     simplePredicate.set_stop(StringToId("WAKE_LOCK_RELEASE"));
     45     simplePredicate.set_stop_all(StringToId("RELEASE_ALL"));
     46     if (outputSlicedUid) {
     47         simplePredicate.mutable_dimensions()->set_field(TAG_ID);
     48         simplePredicate.mutable_dimensions()->add_child()->set_field(ATTRIBUTION_NODE_FIELD_ID);
     49         simplePredicate.mutable_dimensions()->mutable_child(0)->set_position(position);
     50         simplePredicate.mutable_dimensions()->mutable_child(0)->add_child()->set_field(
     51             ATTRIBUTION_UID_FIELD_ID);
     52     }
     53 
     54     simplePredicate.set_count_nesting(countNesting);
     55     simplePredicate.set_initial_value(defaultFalse ? SimplePredicate_InitialValue_FALSE
     56                                                        : SimplePredicate_InitialValue_UNKNOWN);
     57     return simplePredicate;
     58 }
     59 
     60 void writeAttributionNodesToEvent(LogEvent* event, const std::vector<int> &uids) {
     61     std::vector<AttributionNodeInternal> nodes;
     62     for (size_t i = 0; i < uids.size(); ++i) {
     63         AttributionNodeInternal node;
     64         node.set_uid(uids[i]);
     65         nodes.push_back(node);
     66     }
     67     event->write(nodes);  // attribution chain.
     68 }
     69 
     70 void makeWakeLockEvent(
     71         LogEvent* event, const std::vector<int> &uids, const string& wl, int acquire) {
     72     writeAttributionNodesToEvent(event, uids);
     73     event->write(wl);
     74     event->write(acquire);
     75     event->init();
     76 }
     77 
     78 std::map<int64_t, HashableDimensionKey> getWakeLockQueryKey(
     79     const Position position,
     80     const std::vector<int> &uids, const string& conditionName) {
     81     std::map<int64_t, HashableDimensionKey> outputKeyMap;
     82     std::vector<int> uid_indexes;
     83     int pos[] = {1, 1, 1};
     84     int depth = 2;
     85     Field field(1, pos, depth);
     86     switch(position) {
     87         case Position::FIRST:
     88             uid_indexes.push_back(0);
     89             break;
     90         case Position::LAST:
     91             uid_indexes.push_back(uids.size() - 1);
     92             field.setField(0x02018001);
     93             break;
     94         case Position::ANY:
     95             uid_indexes.resize(uids.size());
     96             std::iota(uid_indexes.begin(), uid_indexes.end(), 0);
     97             field.setField(0x02010001);
     98             break;
     99         default:
    100             break;
    101     }
    102 
    103     for (const int idx : uid_indexes) {
    104         Value value((int32_t)uids[idx]);
    105         HashableDimensionKey dim;
    106         dim.addValue(FieldValue(field, value));
    107         outputKeyMap[StringToId(conditionName)] = dim;
    108     }
    109     return outputKeyMap;
    110 }
    111 
    112 TEST(SimpleConditionTrackerTest, TestNonSlicedCondition) {
    113     SimplePredicate simplePredicate;
    114     simplePredicate.set_start(StringToId("SCREEN_TURNED_ON"));
    115     simplePredicate.set_stop(StringToId("SCREEN_TURNED_OFF"));
    116     simplePredicate.set_count_nesting(false);
    117     simplePredicate.set_initial_value(SimplePredicate_InitialValue_UNKNOWN);
    118 
    119     unordered_map<int64_t, int> trackerNameIndexMap;
    120     trackerNameIndexMap[StringToId("SCREEN_TURNED_ON")] = 0;
    121     trackerNameIndexMap[StringToId("SCREEN_TURNED_OFF")] = 1;
    122 
    123     SimpleConditionTracker conditionTracker(kConfigKey, StringToId("SCREEN_IS_ON"), 0 /*tracker index*/,
    124                                             simplePredicate, trackerNameIndexMap);
    125     EXPECT_FALSE(conditionTracker.isSliced());
    126 
    127     LogEvent event(1 /*tagId*/, 0 /*timestamp*/);
    128 
    129     vector<MatchingState> matcherState;
    130     matcherState.push_back(MatchingState::kNotMatched);
    131     matcherState.push_back(MatchingState::kNotMatched);
    132 
    133     vector<sp<ConditionTracker>> allPredicates;
    134     vector<ConditionState> conditionCache(1, ConditionState::kNotEvaluated);
    135     vector<bool> changedCache(1, false);
    136 
    137     conditionTracker.evaluateCondition(event, matcherState, allPredicates, conditionCache,
    138                                        changedCache);
    139     // not matched start or stop. condition doesn't change
    140     EXPECT_EQ(ConditionState::kUnknown, conditionCache[0]);
    141     EXPECT_FALSE(changedCache[0]);
    142 
    143     // prepare a case for match start.
    144     matcherState.clear();
    145     matcherState.push_back(MatchingState::kMatched);
    146     matcherState.push_back(MatchingState::kNotMatched);
    147     conditionCache[0] = ConditionState::kNotEvaluated;
    148     changedCache[0] = false;
    149 
    150     conditionTracker.evaluateCondition(event, matcherState, allPredicates, conditionCache,
    151                                        changedCache);
    152     // now condition should change to true.
    153     EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
    154     EXPECT_TRUE(changedCache[0]);
    155 
    156     // match nothing.
    157     matcherState.clear();
    158     matcherState.push_back(MatchingState::kNotMatched);
    159     matcherState.push_back(MatchingState::kNotMatched);
    160     conditionCache[0] = ConditionState::kNotEvaluated;
    161     changedCache[0] = false;
    162 
    163     conditionTracker.evaluateCondition(event, matcherState, allPredicates, conditionCache,
    164                                        changedCache);
    165     EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
    166     EXPECT_FALSE(changedCache[0]);
    167 
    168     // the case for match stop.
    169     matcherState.clear();
    170     matcherState.push_back(MatchingState::kNotMatched);
    171     matcherState.push_back(MatchingState::kMatched);
    172     conditionCache[0] = ConditionState::kNotEvaluated;
    173     changedCache[0] = false;
    174 
    175     conditionTracker.evaluateCondition(event, matcherState, allPredicates, conditionCache,
    176                                        changedCache);
    177 
    178     // condition changes to false.
    179     EXPECT_EQ(ConditionState::kFalse, conditionCache[0]);
    180     EXPECT_TRUE(changedCache[0]);
    181 
    182     // match stop again.
    183     matcherState.clear();
    184     matcherState.push_back(MatchingState::kNotMatched);
    185     matcherState.push_back(MatchingState::kMatched);
    186     conditionCache[0] = ConditionState::kNotEvaluated;
    187     changedCache[0] = false;
    188 
    189     conditionTracker.evaluateCondition(event, matcherState, allPredicates, conditionCache,
    190                                        changedCache);
    191     // condition should still be false. not changed.
    192     EXPECT_EQ(ConditionState::kFalse, conditionCache[0]);
    193     EXPECT_FALSE(changedCache[0]);
    194 }
    195 
    196 TEST(SimpleConditionTrackerTest, TestNonSlicedConditionNestCounting) {
    197     std::vector<sp<ConditionTracker>> allConditions;
    198     SimplePredicate simplePredicate;
    199     simplePredicate.set_start(StringToId("SCREEN_TURNED_ON"));
    200     simplePredicate.set_stop(StringToId("SCREEN_TURNED_OFF"));
    201     simplePredicate.set_count_nesting(true);
    202 
    203     unordered_map<int64_t, int> trackerNameIndexMap;
    204     trackerNameIndexMap[StringToId("SCREEN_TURNED_ON")] = 0;
    205     trackerNameIndexMap[StringToId("SCREEN_TURNED_OFF")] = 1;
    206 
    207     SimpleConditionTracker conditionTracker(kConfigKey, StringToId("SCREEN_IS_ON"),
    208                                             0 /*condition tracker index*/, simplePredicate,
    209                                             trackerNameIndexMap);
    210     EXPECT_FALSE(conditionTracker.isSliced());
    211 
    212     LogEvent event(1 /*tagId*/, 0 /*timestamp*/);
    213 
    214     // one matched start
    215     vector<MatchingState> matcherState;
    216     matcherState.push_back(MatchingState::kMatched);
    217     matcherState.push_back(MatchingState::kNotMatched);
    218     vector<sp<ConditionTracker>> allPredicates;
    219     vector<ConditionState> conditionCache(1, ConditionState::kNotEvaluated);
    220     vector<bool> changedCache(1, false);
    221 
    222     conditionTracker.evaluateCondition(event, matcherState, allPredicates, conditionCache,
    223                                        changedCache);
    224 
    225     EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
    226     EXPECT_TRUE(changedCache[0]);
    227 
    228     // prepare for another matched start.
    229     matcherState.clear();
    230     matcherState.push_back(MatchingState::kMatched);
    231     matcherState.push_back(MatchingState::kNotMatched);
    232     conditionCache[0] = ConditionState::kNotEvaluated;
    233     changedCache[0] = false;
    234 
    235     conditionTracker.evaluateCondition(event, matcherState, allPredicates, conditionCache,
    236                                        changedCache);
    237 
    238     EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
    239     EXPECT_FALSE(changedCache[0]);
    240 
    241     // ONE MATCHED STOP
    242     matcherState.clear();
    243     matcherState.push_back(MatchingState::kNotMatched);
    244     matcherState.push_back(MatchingState::kMatched);
    245     conditionCache[0] = ConditionState::kNotEvaluated;
    246     changedCache[0] = false;
    247 
    248     conditionTracker.evaluateCondition(event, matcherState, allPredicates, conditionCache,
    249                                        changedCache);
    250     // result should still be true
    251     EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
    252     EXPECT_FALSE(changedCache[0]);
    253 
    254     // ANOTHER MATCHED STOP
    255     matcherState.clear();
    256     matcherState.push_back(MatchingState::kNotMatched);
    257     matcherState.push_back(MatchingState::kMatched);
    258     conditionCache[0] = ConditionState::kNotEvaluated;
    259     changedCache[0] = false;
    260 
    261     conditionTracker.evaluateCondition(event, matcherState, allPredicates, conditionCache,
    262                                        changedCache);
    263     EXPECT_EQ(ConditionState::kFalse, conditionCache[0]);
    264     EXPECT_TRUE(changedCache[0]);
    265 }
    266 
    267 TEST(SimpleConditionTrackerTest, TestSlicedCondition) {
    268     std::vector<sp<ConditionTracker>> allConditions;
    269     for (Position position :
    270             { Position::FIRST, Position::LAST}) {
    271         vector<Matcher> dimensionInCondition;
    272         std::unordered_set<HashableDimensionKey> dimensionKeys;
    273 
    274         SimplePredicate simplePredicate = getWakeLockHeldCondition(
    275                 true /*nesting*/, true /*default to false*/, true /*output slice by uid*/,
    276                 position);
    277         string conditionName = "WL_HELD_BY_UID2";
    278 
    279         unordered_map<int64_t, int> trackerNameIndexMap;
    280         trackerNameIndexMap[StringToId("WAKE_LOCK_ACQUIRE")] = 0;
    281         trackerNameIndexMap[StringToId("WAKE_LOCK_RELEASE")] = 1;
    282         trackerNameIndexMap[StringToId("RELEASE_ALL")] = 2;
    283 
    284         SimpleConditionTracker conditionTracker(kConfigKey, StringToId(conditionName),
    285                                                 0 /*condition tracker index*/, simplePredicate,
    286                                                 trackerNameIndexMap);
    287 
    288         std::vector<int> uids = {111, 222, 333};
    289 
    290         LogEvent event(1 /*tagId*/, 0 /*timestamp*/);
    291         makeWakeLockEvent(&event, uids, "wl1", 1);
    292 
    293         // one matched start
    294         vector<MatchingState> matcherState;
    295         matcherState.push_back(MatchingState::kMatched);
    296         matcherState.push_back(MatchingState::kNotMatched);
    297         matcherState.push_back(MatchingState::kNotMatched);
    298         vector<sp<ConditionTracker>> allPredicates;
    299         vector<ConditionState> conditionCache(1, ConditionState::kNotEvaluated);
    300         vector<bool> changedCache(1, false);
    301 
    302         conditionTracker.evaluateCondition(event, matcherState, allPredicates, conditionCache,
    303                                            changedCache);
    304 
    305         if (position == Position::FIRST ||
    306             position == Position::LAST) {
    307             EXPECT_EQ(1UL, conditionTracker.mSlicedConditionState.size());
    308         } else {
    309             EXPECT_EQ(uids.size(), conditionTracker.mSlicedConditionState.size());
    310         }
    311         EXPECT_TRUE(changedCache[0]);
    312         if (position == Position::FIRST ||
    313             position == Position::LAST) {
    314             EXPECT_EQ(conditionTracker.getChangedToTrueDimensions(allConditions)->size(), 1u);
    315             EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
    316         } else {
    317             EXPECT_EQ(conditionTracker.getChangedToTrueDimensions(allConditions)->size(), uids.size());
    318         }
    319 
    320         // Now test query
    321         const auto queryKey = getWakeLockQueryKey(position, uids, conditionName);
    322         conditionCache[0] = ConditionState::kNotEvaluated;
    323 
    324         conditionTracker.isConditionMet(queryKey, allPredicates, dimensionInCondition,
    325                                         false, false,
    326                                         conditionCache, dimensionKeys);
    327         EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
    328 
    329         // another wake lock acquired by this uid
    330         LogEvent event2(1 /*tagId*/, 0 /*timestamp*/);
    331         makeWakeLockEvent(&event2, uids, "wl2", 1);
    332         matcherState.clear();
    333         matcherState.push_back(MatchingState::kMatched);
    334         matcherState.push_back(MatchingState::kNotMatched);
    335         conditionCache[0] = ConditionState::kNotEvaluated;
    336         changedCache[0] = false;
    337         conditionTracker.evaluateCondition(event2, matcherState, allPredicates, conditionCache,
    338                                            changedCache);
    339         EXPECT_FALSE(changedCache[0]);
    340         if (position == Position::FIRST ||
    341             position == Position::LAST) {
    342             EXPECT_EQ(1UL, conditionTracker.mSlicedConditionState.size());
    343         } else {
    344             EXPECT_EQ(uids.size(), conditionTracker.mSlicedConditionState.size());
    345         }
    346         EXPECT_TRUE(conditionTracker.getChangedToTrueDimensions(allConditions)->empty());
    347         EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
    348 
    349 
    350         // wake lock 1 release
    351         LogEvent event3(1 /*tagId*/, 0 /*timestamp*/);
    352         makeWakeLockEvent(&event3, uids, "wl1", 0);  // now release it.
    353         matcherState.clear();
    354         matcherState.push_back(MatchingState::kNotMatched);
    355         matcherState.push_back(MatchingState::kMatched);
    356         conditionCache[0] = ConditionState::kNotEvaluated;
    357         changedCache[0] = false;
    358         conditionTracker.evaluateCondition(event3, matcherState, allPredicates, conditionCache,
    359                                            changedCache);
    360         // nothing changes, because wake lock 2 is still held for this uid
    361         EXPECT_FALSE(changedCache[0]);
    362         if (position == Position::FIRST ||
    363             position == Position::LAST) {
    364             EXPECT_EQ(1UL, conditionTracker.mSlicedConditionState.size());
    365         } else {
    366             EXPECT_EQ(uids.size(), conditionTracker.mSlicedConditionState.size());
    367         }
    368         EXPECT_TRUE(conditionTracker.getChangedToTrueDimensions(allConditions)->empty());
    369         EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
    370 
    371         LogEvent event4(1 /*tagId*/, 0 /*timestamp*/);
    372         makeWakeLockEvent(&event4, uids, "wl2", 0);  // now release it.
    373         matcherState.clear();
    374         matcherState.push_back(MatchingState::kNotMatched);
    375         matcherState.push_back(MatchingState::kMatched);
    376         conditionCache[0] = ConditionState::kNotEvaluated;
    377         changedCache[0] = false;
    378         conditionTracker.evaluateCondition(event4, matcherState, allPredicates, conditionCache,
    379                                            changedCache);
    380         EXPECT_EQ(0UL, conditionTracker.mSlicedConditionState.size());
    381         EXPECT_TRUE(changedCache[0]);
    382         if (position == Position::FIRST ||
    383             position == Position::LAST) {
    384             EXPECT_EQ(conditionTracker.getChangedToFalseDimensions(allConditions)->size(), 1u);
    385             EXPECT_TRUE(conditionTracker.getChangedToTrueDimensions(allConditions)->empty());
    386         } else {
    387             EXPECT_EQ(conditionTracker.getChangedToFalseDimensions(allConditions)->size(), uids.size());
    388         }
    389 
    390         // query again
    391         conditionCache[0] = ConditionState::kNotEvaluated;
    392         conditionTracker.isConditionMet(queryKey, allPredicates, dimensionInCondition,
    393                                         false, false,
    394                                         conditionCache, dimensionKeys);
    395         EXPECT_EQ(ConditionState::kFalse, conditionCache[0]);
    396     }
    397 
    398 }
    399 
    400 TEST(SimpleConditionTrackerTest, TestSlicedWithNoOutputDim) {
    401     std::vector<sp<ConditionTracker>> allConditions;
    402     vector<Matcher> dimensionInCondition;
    403     std::unordered_set<HashableDimensionKey> dimensionKeys;
    404 
    405     SimplePredicate simplePredicate = getWakeLockHeldCondition(
    406             true /*nesting*/, true /*default to false*/, false /*slice output by uid*/,
    407             Position::ANY /* position */);
    408     string conditionName = "WL_HELD";
    409 
    410     unordered_map<int64_t, int> trackerNameIndexMap;
    411     trackerNameIndexMap[StringToId("WAKE_LOCK_ACQUIRE")] = 0;
    412     trackerNameIndexMap[StringToId("WAKE_LOCK_RELEASE")] = 1;
    413     trackerNameIndexMap[StringToId("RELEASE_ALL")] = 2;
    414 
    415     SimpleConditionTracker conditionTracker(kConfigKey, StringToId(conditionName),
    416                                             0 /*condition tracker index*/, simplePredicate,
    417                                             trackerNameIndexMap);
    418 
    419     EXPECT_FALSE(conditionTracker.isSliced());
    420 
    421     std::vector<int> uid_list1 = {111, 1111, 11111};
    422     string uid1_wl1 = "wl1_1";
    423     std::vector<int> uid_list2 = {222, 2222, 22222};
    424     string uid2_wl1 = "wl2_1";
    425 
    426     LogEvent event(1 /*tagId*/, 0 /*timestamp*/);
    427     makeWakeLockEvent(&event, uid_list1, uid1_wl1, 1);
    428 
    429     // one matched start for uid1
    430     vector<MatchingState> matcherState;
    431     matcherState.push_back(MatchingState::kMatched);
    432     matcherState.push_back(MatchingState::kNotMatched);
    433     matcherState.push_back(MatchingState::kNotMatched);
    434     vector<sp<ConditionTracker>> allPredicates;
    435     vector<ConditionState> conditionCache(1, ConditionState::kNotEvaluated);
    436     vector<bool> changedCache(1, false);
    437 
    438     conditionTracker.evaluateCondition(event, matcherState, allPredicates, conditionCache,
    439                                        changedCache);
    440 
    441     EXPECT_EQ(1UL, conditionTracker.mSlicedConditionState.size());
    442     EXPECT_TRUE(changedCache[0]);
    443 
    444     // Now test query
    445     ConditionKey queryKey;
    446     conditionCache[0] = ConditionState::kNotEvaluated;
    447 
    448     conditionTracker.isConditionMet(queryKey, allPredicates, dimensionInCondition,
    449                                     true, true,
    450                                     conditionCache, dimensionKeys);
    451     EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
    452 
    453     // another wake lock acquired by this uid
    454     LogEvent event2(1 /*tagId*/, 0 /*timestamp*/);
    455     makeWakeLockEvent(&event2, uid_list2, uid2_wl1, 1);
    456     matcherState.clear();
    457     matcherState.push_back(MatchingState::kMatched);
    458     matcherState.push_back(MatchingState::kNotMatched);
    459     conditionCache[0] = ConditionState::kNotEvaluated;
    460     changedCache[0] = false;
    461     conditionTracker.evaluateCondition(event2, matcherState, allPredicates, conditionCache,
    462                                        changedCache);
    463     EXPECT_FALSE(changedCache[0]);
    464 
    465     // uid1 wake lock 1 release
    466     LogEvent event3(1 /*tagId*/, 0 /*timestamp*/);
    467     makeWakeLockEvent(&event3, uid_list1, uid1_wl1, 0);  // now release it.
    468     matcherState.clear();
    469     matcherState.push_back(MatchingState::kNotMatched);
    470     matcherState.push_back(MatchingState::kMatched);
    471     conditionCache[0] = ConditionState::kNotEvaluated;
    472     changedCache[0] = false;
    473     conditionTracker.evaluateCondition(event3, matcherState, allPredicates, conditionCache,
    474                                        changedCache);
    475     // nothing changes, because uid2 is still holding wl.
    476     EXPECT_FALSE(changedCache[0]);
    477 
    478     LogEvent event4(1 /*tagId*/, 0 /*timestamp*/);
    479     makeWakeLockEvent(&event4, uid_list2, uid2_wl1, 0);  // now release it.
    480     matcherState.clear();
    481     matcherState.push_back(MatchingState::kNotMatched);
    482     matcherState.push_back(MatchingState::kMatched);
    483     conditionCache[0] = ConditionState::kNotEvaluated;
    484     changedCache[0] = false;
    485     conditionTracker.evaluateCondition(event4, matcherState, allPredicates, conditionCache,
    486                                        changedCache);
    487     EXPECT_EQ(0UL, conditionTracker.mSlicedConditionState.size());
    488     EXPECT_TRUE(changedCache[0]);
    489 
    490     // query again
    491     conditionCache[0] = ConditionState::kNotEvaluated;
    492     dimensionKeys.clear();
    493     conditionTracker.isConditionMet(queryKey, allPredicates, dimensionInCondition,
    494                                     true, true,
    495                                     conditionCache, dimensionKeys);
    496     EXPECT_EQ(ConditionState::kFalse, conditionCache[0]);
    497 }
    498 
    499 TEST(SimpleConditionTrackerTest, TestStopAll) {
    500     std::vector<sp<ConditionTracker>> allConditions;
    501     for (Position position :
    502             { Position::FIRST, Position::LAST }) {
    503         vector<Matcher> dimensionInCondition;
    504         std::unordered_set<HashableDimensionKey> dimensionKeys;
    505         SimplePredicate simplePredicate = getWakeLockHeldCondition(
    506                 true /*nesting*/, true /*default to false*/, true /*output slice by uid*/,
    507                 position);
    508         string conditionName = "WL_HELD_BY_UID3";
    509 
    510         unordered_map<int64_t, int> trackerNameIndexMap;
    511         trackerNameIndexMap[StringToId("WAKE_LOCK_ACQUIRE")] = 0;
    512         trackerNameIndexMap[StringToId("WAKE_LOCK_RELEASE")] = 1;
    513         trackerNameIndexMap[StringToId("RELEASE_ALL")] = 2;
    514 
    515         SimpleConditionTracker conditionTracker(kConfigKey, StringToId(conditionName),
    516                                                 0 /*condition tracker index*/, simplePredicate,
    517                                                 trackerNameIndexMap);
    518 
    519         std::vector<int> uid_list1 = {111, 1111, 11111};
    520         std::vector<int> uid_list2 = {222, 2222, 22222};
    521 
    522         LogEvent event(1 /*tagId*/, 0 /*timestamp*/);
    523         makeWakeLockEvent(&event, uid_list1, "wl1", 1);
    524 
    525         // one matched start
    526         vector<MatchingState> matcherState;
    527         matcherState.push_back(MatchingState::kMatched);
    528         matcherState.push_back(MatchingState::kNotMatched);
    529         matcherState.push_back(MatchingState::kNotMatched);
    530         vector<sp<ConditionTracker>> allPredicates;
    531         vector<ConditionState> conditionCache(1, ConditionState::kNotEvaluated);
    532         vector<bool> changedCache(1, false);
    533 
    534         conditionTracker.evaluateCondition(event, matcherState, allPredicates, conditionCache,
    535                                            changedCache);
    536         if (position == Position::FIRST ||
    537             position == Position::LAST) {
    538             EXPECT_EQ(1UL, conditionTracker.mSlicedConditionState.size());
    539         } else {
    540             EXPECT_EQ(uid_list1.size(), conditionTracker.mSlicedConditionState.size());
    541         }
    542         EXPECT_TRUE(changedCache[0]);
    543         {
    544             if (position == Position::FIRST ||
    545                 position == Position::LAST) {
    546                 EXPECT_EQ(1UL, conditionTracker.getChangedToTrueDimensions(allConditions)->size());
    547                 EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
    548             } else {
    549                 EXPECT_EQ(uid_list1.size(), conditionTracker.getChangedToTrueDimensions(allConditions)->size());
    550                 EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
    551             }
    552         }
    553 
    554         // Now test query
    555         const auto queryKey = getWakeLockQueryKey(position, uid_list1, conditionName);
    556         conditionCache[0] = ConditionState::kNotEvaluated;
    557 
    558         conditionTracker.isConditionMet(queryKey, allPredicates, dimensionInCondition,
    559                                         false, false,
    560                                         conditionCache, dimensionKeys);
    561         EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
    562 
    563         // another wake lock acquired by uid2
    564         LogEvent event2(1 /*tagId*/, 0 /*timestamp*/);
    565         makeWakeLockEvent(&event2, uid_list2, "wl2", 1);
    566         matcherState.clear();
    567         matcherState.push_back(MatchingState::kMatched);
    568         matcherState.push_back(MatchingState::kNotMatched);
    569         matcherState.push_back(MatchingState::kNotMatched);
    570         conditionCache[0] = ConditionState::kNotEvaluated;
    571         changedCache[0] = false;
    572         conditionTracker.evaluateCondition(event2, matcherState, allPredicates, conditionCache,
    573                                            changedCache);
    574         if (position == Position::FIRST ||
    575             position == Position::LAST) {
    576             EXPECT_EQ(2UL, conditionTracker.mSlicedConditionState.size());
    577         } else {
    578             EXPECT_EQ(uid_list1.size() + uid_list2.size(),
    579                       conditionTracker.mSlicedConditionState.size());
    580         }
    581         EXPECT_TRUE(changedCache[0]);
    582         {
    583             if (position == Position::FIRST ||
    584                 position == Position::LAST) {
    585                 EXPECT_EQ(1UL, conditionTracker.getChangedToTrueDimensions(allConditions)->size());
    586                 EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
    587             } else {
    588                 EXPECT_EQ(uid_list2.size(), conditionTracker.getChangedToTrueDimensions(allConditions)->size());
    589                 EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
    590             }
    591         }
    592 
    593 
    594         // TEST QUERY
    595         const auto queryKey2 = getWakeLockQueryKey(position, uid_list2, conditionName);
    596         conditionCache[0] = ConditionState::kNotEvaluated;
    597         conditionTracker.isConditionMet(queryKey, allPredicates, dimensionInCondition,
    598                                         false, false,
    599                                         conditionCache, dimensionKeys);
    600 
    601         EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
    602 
    603 
    604         // stop all event
    605         LogEvent event3(2 /*tagId*/, 0 /*timestamp*/);
    606         matcherState.clear();
    607         matcherState.push_back(MatchingState::kNotMatched);
    608         matcherState.push_back(MatchingState::kNotMatched);
    609         matcherState.push_back(MatchingState::kMatched);
    610 
    611         conditionCache[0] = ConditionState::kNotEvaluated;
    612         changedCache[0] = false;
    613         conditionTracker.evaluateCondition(event3, matcherState, allPredicates, conditionCache,
    614                                            changedCache);
    615         EXPECT_TRUE(changedCache[0]);
    616         EXPECT_EQ(0UL, conditionTracker.mSlicedConditionState.size());
    617         {
    618             if (position == Position::FIRST || position == Position::LAST) {
    619                 EXPECT_EQ(2UL, conditionTracker.getChangedToFalseDimensions(allConditions)->size());
    620                 EXPECT_TRUE(conditionTracker.getChangedToTrueDimensions(allConditions)->empty());
    621             } else {
    622                 EXPECT_EQ(uid_list1.size() + uid_list2.size(),
    623                           conditionTracker.getChangedToFalseDimensions(allConditions)->size());
    624                 EXPECT_TRUE(conditionTracker.getChangedToTrueDimensions(allConditions)->empty());
    625             }
    626         }
    627 
    628         // TEST QUERY
    629         const auto queryKey3 = getWakeLockQueryKey(position, uid_list1, conditionName);
    630         conditionCache[0] = ConditionState::kNotEvaluated;
    631         conditionTracker.isConditionMet(queryKey, allPredicates, dimensionInCondition,
    632                                         false, false,
    633                                         conditionCache, dimensionKeys);
    634         EXPECT_EQ(ConditionState::kFalse, conditionCache[0]);
    635 
    636         // TEST QUERY
    637         const auto queryKey4 = getWakeLockQueryKey(position, uid_list2, conditionName);
    638         conditionCache[0] = ConditionState::kNotEvaluated;
    639         conditionTracker.isConditionMet(queryKey, allPredicates, dimensionInCondition,
    640                                         false, false,
    641                                         conditionCache, dimensionKeys);
    642         EXPECT_EQ(ConditionState::kFalse, conditionCache[0]);
    643     }
    644 }
    645 
    646 }  // namespace statsd
    647 }  // namespace os
    648 }  // namespace android
    649 #else
    650 GTEST_LOG_(INFO) << "This test does nothing.\n";
    651 #endif
    652