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 "stats_event.h"
17 #include "tests/statsd_test_util.h"
18 
19 #include <gmock/gmock.h>
20 #include <gtest/gtest.h>
21 #include <stdio.h>
22 #include <vector>
23 #include <numeric>
24 
25 using std::map;
26 using std::unordered_map;
27 using std::vector;
28 
29 #ifdef __ANDROID__
30 
31 namespace android {
32 namespace os {
33 namespace statsd {
34 
35 namespace {
36 
37 const ConfigKey kConfigKey(0, 12345);
38 
39 const int ATTRIBUTION_NODE_FIELD_ID = 1;
40 const int ATTRIBUTION_UID_FIELD_ID = 1;
41 const int TAG_ID = 1;
42 const uint64_t protoHash = 0x123456789;
43 
getWakeLockHeldCondition(bool countNesting,bool defaultFalse,bool outputSlicedUid,Position position)44 SimplePredicate getWakeLockHeldCondition(bool countNesting, bool defaultFalse,
45                                          bool outputSlicedUid, Position position) {
46     SimplePredicate simplePredicate;
47     simplePredicate.set_start(StringToId("WAKE_LOCK_ACQUIRE"));
48     simplePredicate.set_stop(StringToId("WAKE_LOCK_RELEASE"));
49     simplePredicate.set_stop_all(StringToId("RELEASE_ALL"));
50     if (outputSlicedUid) {
51         simplePredicate.mutable_dimensions()->set_field(TAG_ID);
52         simplePredicate.mutable_dimensions()->add_child()->set_field(ATTRIBUTION_NODE_FIELD_ID);
53         simplePredicate.mutable_dimensions()->mutable_child(0)->set_position(position);
54         simplePredicate.mutable_dimensions()->mutable_child(0)->add_child()->set_field(
55             ATTRIBUTION_UID_FIELD_ID);
56     }
57 
58     simplePredicate.set_count_nesting(countNesting);
59     simplePredicate.set_initial_value(defaultFalse ? SimplePredicate_InitialValue_FALSE
60                                                        : SimplePredicate_InitialValue_UNKNOWN);
61     return simplePredicate;
62 }
63 
makeWakeLockEvent(LogEvent * logEvent,uint32_t atomId,uint64_t timestamp,const vector<int> & uids,const string & wl,int acquire)64 void makeWakeLockEvent(LogEvent* logEvent, uint32_t atomId, uint64_t timestamp,
65                        const vector<int>& uids, const string& wl, int acquire) {
66     AStatsEvent* statsEvent = AStatsEvent_obtain();
67     AStatsEvent_setAtomId(statsEvent, atomId);
68     AStatsEvent_overwriteTimestamp(statsEvent, timestamp);
69 
70     vector<std::string> tags(uids.size()); // vector of empty strings
71     writeAttribution(statsEvent, uids, tags);
72 
73     AStatsEvent_writeString(statsEvent, wl.c_str());
74     AStatsEvent_writeInt32(statsEvent, acquire);
75 
76     parseStatsEventToLogEvent(statsEvent, logEvent);
77 }
78 
79 } // anonymous namespace
80 
81 
getWakeLockQueryKey(const Position position,const std::vector<int> & uids,const string & conditionName)82 std::map<int64_t, HashableDimensionKey> getWakeLockQueryKey(
83     const Position position,
84     const std::vector<int> &uids, const string& conditionName) {
85     std::map<int64_t, HashableDimensionKey> outputKeyMap;
86     std::vector<int> uid_indexes;
87     int pos[] = {1, 1, 1};
88     int depth = 2;
89     Field field(1, pos, depth);
90     switch(position) {
91         case Position::FIRST:
92             uid_indexes.push_back(0);
93             break;
94         case Position::LAST:
95             uid_indexes.push_back(uids.size() - 1);
96             field.setField(0x02018001);
97             break;
98         case Position::ANY:
99             uid_indexes.resize(uids.size());
100             std::iota(uid_indexes.begin(), uid_indexes.end(), 0);
101             field.setField(0x02010001);
102             break;
103         default:
104             break;
105     }
106 
107     for (const int idx : uid_indexes) {
108         Value value((int32_t)uids[idx]);
109         HashableDimensionKey dim;
110         dim.addValue(FieldValue(field, value));
111         outputKeyMap[StringToId(conditionName)] = dim;
112     }
113     return outputKeyMap;
114 }
115 
TEST(SimpleConditionTrackerTest,TestNonSlicedInitialValueFalse)116 TEST(SimpleConditionTrackerTest, TestNonSlicedInitialValueFalse) {
117     SimplePredicate simplePredicate;
118     simplePredicate.set_start(StringToId("SCREEN_TURNED_ON"));
119     simplePredicate.set_stop(StringToId("SCREEN_TURNED_OFF"));
120     simplePredicate.set_count_nesting(false);
121     simplePredicate.set_initial_value(SimplePredicate_InitialValue_FALSE);
122 
123     unordered_map<int64_t, int> trackerNameIndexMap;
124     trackerNameIndexMap[StringToId("SCREEN_TURNED_ON")] = 0;
125     trackerNameIndexMap[StringToId("SCREEN_TURNED_OFF")] = 1;
126 
127     SimpleConditionTracker conditionTracker(kConfigKey, StringToId("SCREEN_IS_ON"), protoHash,
128                                             0 /*tracker index*/, simplePredicate,
129                                             trackerNameIndexMap);
130 
131     ConditionKey queryKey;
132     vector<sp<ConditionTracker>> allPredicates;
133     vector<ConditionState> conditionCache(1, ConditionState::kNotEvaluated);
134 
135     // Check that initial condition is false.
136     conditionTracker.isConditionMet(queryKey, allPredicates, false, conditionCache);
137     EXPECT_EQ(ConditionState::kFalse, conditionCache[0]);
138 
139     vector<MatchingState> matcherState;
140     vector<bool> changedCache(1, false);
141 
142     // Matched stop event.
143     // Check that condition is still false.
144     unique_ptr<LogEvent> screenOffEvent =
145             CreateScreenStateChangedEvent(/*timestamp=*/50, android::view::DISPLAY_STATE_OFF);
146     matcherState.clear();
147     matcherState.push_back(MatchingState::kNotMatched);  // On matcher not matched
148     matcherState.push_back(MatchingState::kMatched);     // Off matcher matched
149     conditionCache[0] = ConditionState::kNotEvaluated;
150     conditionTracker.evaluateCondition(*screenOffEvent, matcherState, allPredicates, conditionCache,
151                                        changedCache);
152     EXPECT_EQ(ConditionState::kFalse, conditionCache[0]);
153     EXPECT_FALSE(changedCache[0]);
154 
155     // Matched start event.
156     // Check that condition has changed to true.
157     unique_ptr<LogEvent> screenOnEvent =
158             CreateScreenStateChangedEvent(/*timestamp=*/100, android::view::DISPLAY_STATE_ON);
159     matcherState.clear();
160     matcherState.push_back(MatchingState::kMatched);     // On matcher matched
161     matcherState.push_back(MatchingState::kNotMatched);  // Off matcher not matched
162     conditionCache[0] = ConditionState::kNotEvaluated;
163     changedCache[0] = false;
164     conditionTracker.evaluateCondition(*screenOnEvent, matcherState, allPredicates, conditionCache,
165                                        changedCache);
166     EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
167     EXPECT_TRUE(changedCache[0]);
168 }
169 
TEST(SimpleConditionTrackerTest,TestNonSlicedInitialValueUnknown)170 TEST(SimpleConditionTrackerTest, TestNonSlicedInitialValueUnknown) {
171     SimplePredicate simplePredicate;
172     simplePredicate.set_start(StringToId("SCREEN_TURNED_ON"));
173     simplePredicate.set_stop(StringToId("SCREEN_TURNED_OFF"));
174     simplePredicate.set_count_nesting(false);
175     simplePredicate.set_initial_value(SimplePredicate_InitialValue_UNKNOWN);
176 
177     unordered_map<int64_t, int> trackerNameIndexMap;
178     trackerNameIndexMap[StringToId("SCREEN_TURNED_ON")] = 0;
179     trackerNameIndexMap[StringToId("SCREEN_TURNED_OFF")] = 1;
180 
181     SimpleConditionTracker conditionTracker(kConfigKey, StringToId("SCREEN_IS_ON"), protoHash,
182                                             0 /*tracker index*/, simplePredicate,
183                                             trackerNameIndexMap);
184 
185     ConditionKey queryKey;
186     vector<sp<ConditionTracker>> allPredicates;
187     vector<ConditionState> conditionCache(1, ConditionState::kNotEvaluated);
188 
189     // Check that initial condition is unknown.
190     conditionTracker.isConditionMet(queryKey, allPredicates, false, conditionCache);
191     EXPECT_EQ(ConditionState::kUnknown, conditionCache[0]);
192 
193     vector<MatchingState> matcherState;
194     vector<bool> changedCache(1, false);
195 
196     // Matched stop event.
197     // Check that condition is changed to false.
198     unique_ptr<LogEvent> screenOffEvent =
199             CreateScreenStateChangedEvent(/*timestamp=*/50, android::view::DISPLAY_STATE_OFF);
200     matcherState.clear();
201     matcherState.push_back(MatchingState::kNotMatched);  // On matcher not matched
202     matcherState.push_back(MatchingState::kMatched);     // Off matcher matched
203     conditionCache[0] = ConditionState::kNotEvaluated;
204     conditionTracker.evaluateCondition(*screenOffEvent, matcherState, allPredicates, conditionCache,
205                                        changedCache);
206     EXPECT_EQ(ConditionState::kFalse, conditionCache[0]);
207     EXPECT_TRUE(changedCache[0]);
208 
209     // Matched start event.
210     // Check that condition has changed to true.
211     unique_ptr<LogEvent> screenOnEvent =
212             CreateScreenStateChangedEvent(/*timestamp=*/100, android::view::DISPLAY_STATE_ON);
213     matcherState.clear();
214     matcherState.push_back(MatchingState::kMatched);     // On matcher matched
215     matcherState.push_back(MatchingState::kNotMatched);  // Off matcher not matched
216     conditionCache[0] = ConditionState::kNotEvaluated;
217     changedCache[0] = false;
218     conditionTracker.evaluateCondition(*screenOnEvent, matcherState, allPredicates, conditionCache,
219                                        changedCache);
220     EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
221     EXPECT_TRUE(changedCache[0]);
222 }
223 
TEST(SimpleConditionTrackerTest,TestNonSlicedCondition)224 TEST(SimpleConditionTrackerTest, TestNonSlicedCondition) {
225     SimplePredicate simplePredicate;
226     simplePredicate.set_start(StringToId("SCREEN_TURNED_ON"));
227     simplePredicate.set_stop(StringToId("SCREEN_TURNED_OFF"));
228     simplePredicate.set_count_nesting(false);
229     simplePredicate.set_initial_value(SimplePredicate_InitialValue_UNKNOWN);
230 
231     unordered_map<int64_t, int> trackerNameIndexMap;
232     trackerNameIndexMap[StringToId("SCREEN_TURNED_ON")] = 0;
233     trackerNameIndexMap[StringToId("SCREEN_TURNED_OFF")] = 1;
234 
235     SimpleConditionTracker conditionTracker(kConfigKey, StringToId("SCREEN_IS_ON"), protoHash,
236                                             0 /*tracker index*/, simplePredicate,
237                                             trackerNameIndexMap);
238     EXPECT_FALSE(conditionTracker.isSliced());
239 
240     // This event is not accessed in this test besides dimensions which is why this is okay.
241     // This is technically an invalid LogEvent because we do not call parseBuffer.
242     LogEvent event(/*uid=*/0, /*pid=*/0);
243 
244     vector<MatchingState> matcherState;
245     matcherState.push_back(MatchingState::kNotMatched);
246     matcherState.push_back(MatchingState::kNotMatched);
247 
248     vector<sp<ConditionTracker>> allPredicates;
249     vector<ConditionState> conditionCache(1, ConditionState::kNotEvaluated);
250     vector<bool> changedCache(1, false);
251 
252     conditionTracker.evaluateCondition(event, matcherState, allPredicates, conditionCache,
253                                        changedCache);
254     // not matched start or stop. condition doesn't change
255     EXPECT_EQ(ConditionState::kUnknown, conditionCache[0]);
256     EXPECT_FALSE(changedCache[0]);
257 
258     // prepare a case for match start.
259     matcherState.clear();
260     matcherState.push_back(MatchingState::kMatched);
261     matcherState.push_back(MatchingState::kNotMatched);
262     conditionCache[0] = ConditionState::kNotEvaluated;
263     changedCache[0] = false;
264 
265     conditionTracker.evaluateCondition(event, matcherState, allPredicates, conditionCache,
266                                        changedCache);
267     // now condition should change to true.
268     EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
269     EXPECT_TRUE(changedCache[0]);
270 
271     // match nothing.
272     matcherState.clear();
273     matcherState.push_back(MatchingState::kNotMatched);
274     matcherState.push_back(MatchingState::kNotMatched);
275     conditionCache[0] = ConditionState::kNotEvaluated;
276     changedCache[0] = false;
277 
278     conditionTracker.evaluateCondition(event, matcherState, allPredicates, conditionCache,
279                                        changedCache);
280     EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
281     EXPECT_FALSE(changedCache[0]);
282 
283     // the case for match stop.
284     matcherState.clear();
285     matcherState.push_back(MatchingState::kNotMatched);
286     matcherState.push_back(MatchingState::kMatched);
287     conditionCache[0] = ConditionState::kNotEvaluated;
288     changedCache[0] = false;
289 
290     conditionTracker.evaluateCondition(event, matcherState, allPredicates, conditionCache,
291                                        changedCache);
292 
293     // condition changes to false.
294     EXPECT_EQ(ConditionState::kFalse, conditionCache[0]);
295     EXPECT_TRUE(changedCache[0]);
296 
297     // match stop again.
298     matcherState.clear();
299     matcherState.push_back(MatchingState::kNotMatched);
300     matcherState.push_back(MatchingState::kMatched);
301     conditionCache[0] = ConditionState::kNotEvaluated;
302     changedCache[0] = false;
303 
304     conditionTracker.evaluateCondition(event, matcherState, allPredicates, conditionCache,
305                                        changedCache);
306     // condition should still be false. not changed.
307     EXPECT_EQ(ConditionState::kFalse, conditionCache[0]);
308     EXPECT_FALSE(changedCache[0]);
309 }
310 
TEST(SimpleConditionTrackerTest,TestNonSlicedConditionNestCounting)311 TEST(SimpleConditionTrackerTest, TestNonSlicedConditionNestCounting) {
312     std::vector<sp<ConditionTracker>> allConditions;
313     SimplePredicate simplePredicate;
314     simplePredicate.set_start(StringToId("SCREEN_TURNED_ON"));
315     simplePredicate.set_stop(StringToId("SCREEN_TURNED_OFF"));
316     simplePredicate.set_count_nesting(true);
317 
318     unordered_map<int64_t, int> trackerNameIndexMap;
319     trackerNameIndexMap[StringToId("SCREEN_TURNED_ON")] = 0;
320     trackerNameIndexMap[StringToId("SCREEN_TURNED_OFF")] = 1;
321 
322     SimpleConditionTracker conditionTracker(kConfigKey, StringToId("SCREEN_IS_ON"), protoHash,
323                                             0 /*condition tracker index*/, simplePredicate,
324                                             trackerNameIndexMap);
325     EXPECT_FALSE(conditionTracker.isSliced());
326 
327     // This event is not accessed in this test besides dimensions which is why this is okay.
328     // This is technically an invalid LogEvent because we do not call parseBuffer.
329     LogEvent event(/*uid=*/0, /*pid=*/0);
330 
331     // one matched start
332     vector<MatchingState> matcherState;
333     matcherState.push_back(MatchingState::kMatched);
334     matcherState.push_back(MatchingState::kNotMatched);
335     vector<sp<ConditionTracker>> allPredicates;
336     vector<ConditionState> conditionCache(1, ConditionState::kNotEvaluated);
337     vector<bool> changedCache(1, false);
338 
339     conditionTracker.evaluateCondition(event, matcherState, allPredicates, conditionCache,
340                                        changedCache);
341 
342     EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
343     EXPECT_TRUE(changedCache[0]);
344 
345     // prepare for another matched start.
346     matcherState.clear();
347     matcherState.push_back(MatchingState::kMatched);
348     matcherState.push_back(MatchingState::kNotMatched);
349     conditionCache[0] = ConditionState::kNotEvaluated;
350     changedCache[0] = false;
351 
352     conditionTracker.evaluateCondition(event, matcherState, allPredicates, conditionCache,
353                                        changedCache);
354 
355     EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
356     EXPECT_FALSE(changedCache[0]);
357 
358     // ONE MATCHED STOP
359     matcherState.clear();
360     matcherState.push_back(MatchingState::kNotMatched);
361     matcherState.push_back(MatchingState::kMatched);
362     conditionCache[0] = ConditionState::kNotEvaluated;
363     changedCache[0] = false;
364 
365     conditionTracker.evaluateCondition(event, matcherState, allPredicates, conditionCache,
366                                        changedCache);
367     // result should still be true
368     EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
369     EXPECT_FALSE(changedCache[0]);
370 
371     // ANOTHER MATCHED STOP
372     matcherState.clear();
373     matcherState.push_back(MatchingState::kNotMatched);
374     matcherState.push_back(MatchingState::kMatched);
375     conditionCache[0] = ConditionState::kNotEvaluated;
376     changedCache[0] = false;
377 
378     conditionTracker.evaluateCondition(event, matcherState, allPredicates, conditionCache,
379                                        changedCache);
380     EXPECT_EQ(ConditionState::kFalse, conditionCache[0]);
381     EXPECT_TRUE(changedCache[0]);
382 }
383 
TEST(SimpleConditionTrackerTest,TestSlicedCondition)384 TEST(SimpleConditionTrackerTest, TestSlicedCondition) {
385     std::vector<sp<ConditionTracker>> allConditions;
386     for (Position position : {Position::FIRST, Position::LAST}) {
387         SimplePredicate simplePredicate = getWakeLockHeldCondition(
388                 true /*nesting*/, true /*default to false*/, true /*output slice by uid*/,
389                 position);
390         string conditionName = "WL_HELD_BY_UID2";
391 
392         unordered_map<int64_t, int> trackerNameIndexMap;
393         trackerNameIndexMap[StringToId("WAKE_LOCK_ACQUIRE")] = 0;
394         trackerNameIndexMap[StringToId("WAKE_LOCK_RELEASE")] = 1;
395         trackerNameIndexMap[StringToId("RELEASE_ALL")] = 2;
396 
397         SimpleConditionTracker conditionTracker(kConfigKey, StringToId(conditionName), protoHash,
398                                                 0 /*condition tracker index*/, simplePredicate,
399                                                 trackerNameIndexMap);
400 
401         std::vector<int> uids = {111, 222, 333};
402 
403         LogEvent event1(/*uid=*/0, /*pid=*/0);
404         makeWakeLockEvent(&event1, /*atomId=*/1, /*timestamp=*/0, uids, "wl1", /*acquire=*/1);
405 
406         // one matched start
407         vector<MatchingState> matcherState;
408         matcherState.push_back(MatchingState::kMatched);
409         matcherState.push_back(MatchingState::kNotMatched);
410         matcherState.push_back(MatchingState::kNotMatched);
411         vector<sp<ConditionTracker>> allPredicates;
412         vector<ConditionState> conditionCache(1, ConditionState::kNotEvaluated);
413         vector<bool> changedCache(1, false);
414 
415         conditionTracker.evaluateCondition(event1, matcherState, allPredicates, conditionCache,
416                                            changedCache);
417 
418         if (position == Position::FIRST || position == Position::LAST) {
419             ASSERT_EQ(1UL, conditionTracker.mSlicedConditionState.size());
420         } else {
421             ASSERT_EQ(uids.size(), conditionTracker.mSlicedConditionState.size());
422         }
423         EXPECT_TRUE(changedCache[0]);
424         if (position == Position::FIRST || position == Position::LAST) {
425             ASSERT_EQ(conditionTracker.getChangedToTrueDimensions(allConditions)->size(), 1u);
426             EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
427         } else {
428             EXPECT_EQ(conditionTracker.getChangedToTrueDimensions(allConditions)->size(),
429                       uids.size());
430         }
431 
432         // Now test query
433         const auto queryKey = getWakeLockQueryKey(position, uids, conditionName);
434         conditionCache[0] = ConditionState::kNotEvaluated;
435 
436         conditionTracker.isConditionMet(queryKey, allPredicates, false, conditionCache);
437         EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
438 
439         // another wake lock acquired by this uid
440         LogEvent event2(/*uid=*/0, /*pid=*/0);
441         makeWakeLockEvent(&event2, /*atomId=*/1, /*timestamp=*/0, uids, "wl2", /*acquire=*/1);
442         matcherState.clear();
443         matcherState.push_back(MatchingState::kMatched);
444         matcherState.push_back(MatchingState::kNotMatched);
445         conditionCache[0] = ConditionState::kNotEvaluated;
446         changedCache[0] = false;
447         conditionTracker.evaluateCondition(event2, matcherState, allPredicates, conditionCache,
448                                            changedCache);
449         EXPECT_FALSE(changedCache[0]);
450         if (position == Position::FIRST || position == Position::LAST) {
451             ASSERT_EQ(1UL, conditionTracker.mSlicedConditionState.size());
452         } else {
453             ASSERT_EQ(uids.size(), conditionTracker.mSlicedConditionState.size());
454         }
455         EXPECT_TRUE(conditionTracker.getChangedToTrueDimensions(allConditions)->empty());
456         EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
457 
458 
459         // wake lock 1 release
460         LogEvent event3(/*uid=*/0, /*pid=*/0);
461         makeWakeLockEvent(&event3, /*atomId=*/1, /*timestamp=*/0, uids, "wl1", /*acquire=*/0);
462         matcherState.clear();
463         matcherState.push_back(MatchingState::kNotMatched);
464         matcherState.push_back(MatchingState::kMatched);
465         conditionCache[0] = ConditionState::kNotEvaluated;
466         changedCache[0] = false;
467         conditionTracker.evaluateCondition(event3, matcherState, allPredicates, conditionCache,
468                                            changedCache);
469         // nothing changes, because wake lock 2 is still held for this uid
470         EXPECT_FALSE(changedCache[0]);
471         if (position == Position::FIRST || position == Position::LAST) {
472             ASSERT_EQ(1UL, conditionTracker.mSlicedConditionState.size());
473         } else {
474             ASSERT_EQ(uids.size(), conditionTracker.mSlicedConditionState.size());
475         }
476         EXPECT_TRUE(conditionTracker.getChangedToTrueDimensions(allConditions)->empty());
477         EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
478 
479         LogEvent event4(/*uid=*/0, /*pid=*/0);
480         makeWakeLockEvent(&event4, /*atomId=*/1, /*timestamp=*/0, uids, "wl2", /*acquire=*/0);
481         matcherState.clear();
482         matcherState.push_back(MatchingState::kNotMatched);
483         matcherState.push_back(MatchingState::kMatched);
484         conditionCache[0] = ConditionState::kNotEvaluated;
485         changedCache[0] = false;
486         conditionTracker.evaluateCondition(event4, matcherState, allPredicates, conditionCache,
487                                            changedCache);
488         ASSERT_EQ(0UL, conditionTracker.mSlicedConditionState.size());
489         EXPECT_TRUE(changedCache[0]);
490         if (position == Position::FIRST || position == Position::LAST) {
491             ASSERT_EQ(conditionTracker.getChangedToFalseDimensions(allConditions)->size(), 1u);
492             EXPECT_TRUE(conditionTracker.getChangedToTrueDimensions(allConditions)->empty());
493         } else {
494             EXPECT_EQ(conditionTracker.getChangedToFalseDimensions(allConditions)->size(),
495                       uids.size());
496         }
497 
498         // query again
499         conditionCache[0] = ConditionState::kNotEvaluated;
500         conditionTracker.isConditionMet(queryKey, allPredicates, false, conditionCache);
501         EXPECT_EQ(ConditionState::kFalse, conditionCache[0]);
502     }
503 
504 }
505 
TEST(SimpleConditionTrackerTest,TestSlicedWithNoOutputDim)506 TEST(SimpleConditionTrackerTest, TestSlicedWithNoOutputDim) {
507     std::vector<sp<ConditionTracker>> allConditions;
508 
509     SimplePredicate simplePredicate =
510             getWakeLockHeldCondition(true /*nesting*/, true /*default to false*/,
511                                      false /*slice output by uid*/, Position::ANY /* position */);
512     string conditionName = "WL_HELD";
513 
514     unordered_map<int64_t, int> trackerNameIndexMap;
515     trackerNameIndexMap[StringToId("WAKE_LOCK_ACQUIRE")] = 0;
516     trackerNameIndexMap[StringToId("WAKE_LOCK_RELEASE")] = 1;
517     trackerNameIndexMap[StringToId("RELEASE_ALL")] = 2;
518 
519     SimpleConditionTracker conditionTracker(kConfigKey, StringToId(conditionName), protoHash,
520                                             0 /*condition tracker index*/, simplePredicate,
521                                             trackerNameIndexMap);
522 
523     EXPECT_FALSE(conditionTracker.isSliced());
524 
525     std::vector<int> uids1 = {111, 1111, 11111};
526     string uid1_wl1 = "wl1_1";
527     std::vector<int> uids2 = {222, 2222, 22222};
528     string uid2_wl1 = "wl2_1";
529 
530     LogEvent event1(/*uid=*/0, /*pid=*/0);
531     makeWakeLockEvent(&event1, /*atomId=*/1, /*timestamp=*/0, uids1, uid1_wl1, /*acquire=*/1);
532 
533     // one matched start for uid1
534     vector<MatchingState> matcherState;
535     matcherState.push_back(MatchingState::kMatched);
536     matcherState.push_back(MatchingState::kNotMatched);
537     matcherState.push_back(MatchingState::kNotMatched);
538     vector<sp<ConditionTracker>> allPredicates;
539     vector<ConditionState> conditionCache(1, ConditionState::kNotEvaluated);
540     vector<bool> changedCache(1, false);
541 
542     conditionTracker.evaluateCondition(event1, matcherState, allPredicates, conditionCache,
543                                        changedCache);
544 
545     ASSERT_EQ(1UL, conditionTracker.mSlicedConditionState.size());
546     EXPECT_TRUE(changedCache[0]);
547 
548     // Now test query
549     ConditionKey queryKey;
550     conditionCache[0] = ConditionState::kNotEvaluated;
551 
552     conditionTracker.isConditionMet(queryKey, allPredicates, true, conditionCache);
553     EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
554 
555     // another wake lock acquired by this uid
556     LogEvent event2(/*uid=*/0, /*pid=*/0);
557     makeWakeLockEvent(&event2, /*atomId=*/1, /*timestamp=*/0, uids2, uid2_wl1, /*acquire=*/1);
558 
559     matcherState.clear();
560     matcherState.push_back(MatchingState::kMatched);
561     matcherState.push_back(MatchingState::kNotMatched);
562     conditionCache[0] = ConditionState::kNotEvaluated;
563     changedCache[0] = false;
564     conditionTracker.evaluateCondition(event2, matcherState, allPredicates, conditionCache,
565                                        changedCache);
566     EXPECT_FALSE(changedCache[0]);
567 
568     // uid1 wake lock 1 release
569     LogEvent event3(/*uid=*/0, /*pid=*/0);
570     makeWakeLockEvent(&event3, /*atomId=*/1, /*timestamp=*/0, uids1, uid1_wl1,
571                       /*release=*/0);  // now release it.
572 
573     matcherState.clear();
574     matcherState.push_back(MatchingState::kNotMatched);
575     matcherState.push_back(MatchingState::kMatched);
576     conditionCache[0] = ConditionState::kNotEvaluated;
577     changedCache[0] = false;
578     conditionTracker.evaluateCondition(event3, matcherState, allPredicates, conditionCache,
579                                        changedCache);
580     // nothing changes, because uid2 is still holding wl.
581     EXPECT_FALSE(changedCache[0]);
582 
583     LogEvent event4(/*uid=*/0, /*pid=*/0);
584     makeWakeLockEvent(&event4, /*atomId=*/1, /*timestamp=*/0, uids2, uid2_wl1,
585                       /*acquire=*/0);  // now release it.
586     matcherState.clear();
587     matcherState.push_back(MatchingState::kNotMatched);
588     matcherState.push_back(MatchingState::kMatched);
589     conditionCache[0] = ConditionState::kNotEvaluated;
590     changedCache[0] = false;
591     conditionTracker.evaluateCondition(event4, matcherState, allPredicates, conditionCache,
592                                        changedCache);
593     ASSERT_EQ(0UL, conditionTracker.mSlicedConditionState.size());
594     EXPECT_TRUE(changedCache[0]);
595 
596     // query again
597     conditionCache[0] = ConditionState::kNotEvaluated;
598     conditionTracker.isConditionMet(queryKey, allPredicates, true, conditionCache);
599     EXPECT_EQ(ConditionState::kFalse, conditionCache[0]);
600 }
601 
TEST(SimpleConditionTrackerTest,TestStopAll)602 TEST(SimpleConditionTrackerTest, TestStopAll) {
603     std::vector<sp<ConditionTracker>> allConditions;
604     for (Position position : {Position::FIRST, Position::LAST}) {
605         SimplePredicate simplePredicate =
606                 getWakeLockHeldCondition(true /*nesting*/, true /*default to false*/,
607                                          true /*output slice by uid*/, position);
608         string conditionName = "WL_HELD_BY_UID3";
609 
610         unordered_map<int64_t, int> trackerNameIndexMap;
611         trackerNameIndexMap[StringToId("WAKE_LOCK_ACQUIRE")] = 0;
612         trackerNameIndexMap[StringToId("WAKE_LOCK_RELEASE")] = 1;
613         trackerNameIndexMap[StringToId("RELEASE_ALL")] = 2;
614 
615         SimpleConditionTracker conditionTracker(kConfigKey, StringToId(conditionName), protoHash,
616                                                 0 /*condition tracker index*/, simplePredicate,
617                                                 trackerNameIndexMap);
618 
619         std::vector<int> uids1 = {111, 1111, 11111};
620         std::vector<int> uids2 = {222, 2222, 22222};
621 
622         LogEvent event1(/*uid=*/0, /*pid=*/0);
623         makeWakeLockEvent(&event1, /*atomId=*/1, /*timestamp=*/0, uids1, "wl1", /*acquire=*/1);
624 
625         // one matched start
626         vector<MatchingState> matcherState;
627         matcherState.push_back(MatchingState::kMatched);
628         matcherState.push_back(MatchingState::kNotMatched);
629         matcherState.push_back(MatchingState::kNotMatched);
630         vector<sp<ConditionTracker>> allPredicates;
631         vector<ConditionState> conditionCache(1, ConditionState::kNotEvaluated);
632         vector<bool> changedCache(1, false);
633 
634         conditionTracker.evaluateCondition(event1, matcherState, allPredicates, conditionCache,
635                                            changedCache);
636         if (position == Position::FIRST || position == Position::LAST) {
637             ASSERT_EQ(1UL, conditionTracker.mSlicedConditionState.size());
638         } else {
639             ASSERT_EQ(uids1.size(), conditionTracker.mSlicedConditionState.size());
640         }
641         EXPECT_TRUE(changedCache[0]);
642         {
643             if (position == Position::FIRST || position == Position::LAST) {
644                 ASSERT_EQ(1UL, conditionTracker.getChangedToTrueDimensions(allConditions)->size());
645                 EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
646             } else {
647                 EXPECT_EQ(uids1.size(),
648                           conditionTracker.getChangedToTrueDimensions(allConditions)->size());
649                 EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
650             }
651         }
652 
653         // Now test query
654         const auto queryKey = getWakeLockQueryKey(position, uids1, conditionName);
655         conditionCache[0] = ConditionState::kNotEvaluated;
656 
657         conditionTracker.isConditionMet(queryKey, allPredicates, false, conditionCache);
658         EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
659 
660         // another wake lock acquired by uid2
661         LogEvent event2(/*uid=*/0, /*pid=*/0);
662         makeWakeLockEvent(&event2, /*atomId=*/1, /*timestamp=*/0, uids2, "wl2", /*acquire=*/1);
663 
664         matcherState.clear();
665         matcherState.push_back(MatchingState::kMatched);
666         matcherState.push_back(MatchingState::kNotMatched);
667         matcherState.push_back(MatchingState::kNotMatched);
668         conditionCache[0] = ConditionState::kNotEvaluated;
669         changedCache[0] = false;
670         conditionTracker.evaluateCondition(event2, matcherState, allPredicates, conditionCache,
671                                            changedCache);
672         if (position == Position::FIRST || position == Position::LAST) {
673             ASSERT_EQ(2UL, conditionTracker.mSlicedConditionState.size());
674         } else {
675             ASSERT_EQ(uids1.size() + uids2.size(), conditionTracker.mSlicedConditionState.size());
676         }
677         EXPECT_TRUE(changedCache[0]);
678         {
679             if (position == Position::FIRST || position == Position::LAST) {
680                 ASSERT_EQ(1UL, conditionTracker.getChangedToTrueDimensions(allConditions)->size());
681                 EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
682             } else {
683                 EXPECT_EQ(uids2.size(),
684                           conditionTracker.getChangedToTrueDimensions(allConditions)->size());
685                 EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
686             }
687         }
688 
689         // TEST QUERY
690         const auto queryKey2 = getWakeLockQueryKey(position, uids2, conditionName);
691         conditionCache[0] = ConditionState::kNotEvaluated;
692         conditionTracker.isConditionMet(queryKey, allPredicates, false, conditionCache);
693 
694         EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
695 
696         // stop all event
697         LogEvent event3(/*uid=*/0, /*pid=*/0);
698         makeWakeLockEvent(&event3, /*atomId=*/1, /*timestamp=*/0, uids2, "wl2", /*acquire=*/1);
699 
700         matcherState.clear();
701         matcherState.push_back(MatchingState::kNotMatched);
702         matcherState.push_back(MatchingState::kNotMatched);
703         matcherState.push_back(MatchingState::kMatched);
704 
705         conditionCache[0] = ConditionState::kNotEvaluated;
706         changedCache[0] = false;
707         conditionTracker.evaluateCondition(event3, matcherState, allPredicates, conditionCache,
708                                            changedCache);
709         EXPECT_TRUE(changedCache[0]);
710         ASSERT_EQ(0UL, conditionTracker.mSlicedConditionState.size());
711         {
712             if (position == Position::FIRST || position == Position::LAST) {
713                 ASSERT_EQ(2UL, conditionTracker.getChangedToFalseDimensions(allConditions)->size());
714                 EXPECT_TRUE(conditionTracker.getChangedToTrueDimensions(allConditions)->empty());
715             } else {
716                 EXPECT_EQ(uids1.size() + uids2.size(),
717                           conditionTracker.getChangedToFalseDimensions(allConditions)->size());
718                 EXPECT_TRUE(conditionTracker.getChangedToTrueDimensions(allConditions)->empty());
719             }
720         }
721 
722         // TEST QUERY
723         const auto queryKey3 = getWakeLockQueryKey(position, uids1, conditionName);
724         conditionCache[0] = ConditionState::kNotEvaluated;
725         conditionTracker.isConditionMet(queryKey, allPredicates, false, conditionCache);
726         EXPECT_EQ(ConditionState::kFalse, conditionCache[0]);
727 
728         // TEST QUERY
729         const auto queryKey4 = getWakeLockQueryKey(position, uids2, conditionName);
730         conditionCache[0] = ConditionState::kNotEvaluated;
731         conditionTracker.isConditionMet(queryKey, allPredicates, false, conditionCache);
732         EXPECT_EQ(ConditionState::kFalse, conditionCache[0]);
733     }
734 }
735 
736 }  // namespace statsd
737 }  // namespace os
738 }  // namespace android
739 #else
740 GTEST_LOG_(INFO) << "This test does nothing.\n";
741 #endif
742