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