blob: 26a3733ed598467756fafdfe002854cefea458e9 [file] [log] [blame]
tsaichristine10978642019-09-10 14:12:49 -07001/*
2 * Copyright (C) 2019, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#include <gtest/gtest.h>
17#include "state/StateManager.h"
18#include "state/StateTracker.h"
19#include "state/StateListener.h"
20
21#include "tests/statsd_test_util.h"
22
23#ifdef __ANDROID__
24
25namespace android {
26namespace os {
27namespace statsd {
28
29/**
30 * Mock StateListener class for testing.
31 * Stores primary key and state pairs.
32 */
33class TestStateListener : public virtual StateListener {
34public:
35 TestStateListener(){};
36
37 virtual ~TestStateListener(){};
38
39 struct Update {
40 Update(const HashableDimensionKey& key, int state) : mKey(key), mState(state){};
41 HashableDimensionKey mKey;
42 int mState;
43 };
44
45 std::vector<Update> updates;
46
tsaichristine8d73dc92019-12-06 02:11:02 -080047 void onStateChanged(const int64_t eventTimeNs, const int32_t atomId,
48 const HashableDimensionKey& primaryKey, int oldState, int newState) {
tsaichristine10978642019-09-10 14:12:49 -070049 updates.emplace_back(primaryKey, newState);
50 }
51};
52
tsaichristine69000e62019-10-18 17:34:52 -070053int getStateInt(StateManager& mgr, int atomId, const HashableDimensionKey& queryKey) {
54 FieldValue output;
55 mgr.getStateValue(atomId, queryKey, &output);
56 return output.mValue.int_value;
57}
58
tsaichristine10978642019-09-10 14:12:49 -070059// START: build event functions.
60// State with no primary fields - ScreenStateChanged
61std::shared_ptr<LogEvent> buildScreenEvent(int state) {
62 std::shared_ptr<LogEvent> event =
63 std::make_shared<LogEvent>(android::util::SCREEN_STATE_CHANGED, 1000 /*timestamp*/);
64 event->write((int32_t)state);
65 event->init();
66 return event;
67}
68
69// State with one primary field - UidProcessStateChanged
70std::shared_ptr<LogEvent> buildUidProcessEvent(int uid, int state) {
71 std::shared_ptr<LogEvent> event =
72 std::make_shared<LogEvent>(android::util::UID_PROCESS_STATE_CHANGED, 1000 /*timestamp*/);
73 event->write((int32_t)uid);
74 event->write((int32_t)state);
75 event->init();
76 return event;
77}
78
79// State with multiple primary fields - OverlayStateChanged
80std::shared_ptr<LogEvent> buildOverlayEvent(int uid, const std::string& packageName, int state) {
81 std::shared_ptr<LogEvent> event =
82 std::make_shared<LogEvent>(android::util::OVERLAY_STATE_CHANGED, 1000 /*timestamp*/);
83 event->write((int32_t)uid);
84 event->write(packageName);
85 event->write(true); // using_alert_window
86 event->write((int32_t)state);
87 event->init();
88 return event;
89}
90
tsaichristined21aacf2019-10-07 14:47:38 -070091// Incorrect event - missing fields
tsaichristine10978642019-09-10 14:12:49 -070092std::shared_ptr<LogEvent> buildIncorrectOverlayEvent(int uid, const std::string& packageName, int state) {
93 std::shared_ptr<LogEvent> event =
94 std::make_shared<LogEvent>(android::util::OVERLAY_STATE_CHANGED, 1000 /*timestamp*/);
95 event->write((int32_t)uid);
96 event->write(packageName);
97 event->write((int32_t)state);
98 event->init();
99 return event;
100}
tsaichristined21aacf2019-10-07 14:47:38 -0700101
102// Incorrect event - exclusive state has wrong type
103std::shared_ptr<LogEvent> buildOverlayEventBadStateType(int uid, const std::string& packageName) {
104 std::shared_ptr<LogEvent> event =
105 std::make_shared<LogEvent>(android::util::OVERLAY_STATE_CHANGED, 1000 /*timestamp*/);
106 event->write((int32_t)uid);
107 event->write(packageName);
108 event->write(true);
109 event->write("string"); // exclusive state: string instead of int
110 event->init();
111 return event;
112}
tsaichristine10978642019-09-10 14:12:49 -0700113// END: build event functions.
114
115// START: get primary key functions
116void getUidProcessKey(int uid, HashableDimensionKey* key) {
117 int pos1[] = {1, 0, 0};
118 Field field1(27 /* atom id */, pos1, 0 /* depth */);
119 Value value1((int32_t)uid);
120
121 key->addValue(FieldValue(field1, value1));
122}
123
124void getOverlayKey(int uid, string packageName, HashableDimensionKey* key) {
125 int pos1[] = {1, 0, 0};
126 int pos2[] = {2, 0, 0};
127
128 Field field1(59 /* atom id */, pos1, 0 /* depth */);
129 Field field2(59 /* atom id */, pos2, 0 /* depth */);
130
131 Value value1((int32_t)uid);
132 Value value2(packageName);
133
134 key->addValue(FieldValue(field1, value1));
135 key->addValue(FieldValue(field2, value2));
136}
137// END: get primary key functions
138
139TEST(StateListenerTest, TestStateListenerWeakPointer) {
140 sp<TestStateListener> listener = new TestStateListener();
141 wp<TestStateListener> wListener = listener;
142 listener = nullptr; // let go of listener
143 EXPECT_TRUE(wListener.promote() == nullptr);
144}
145
146TEST(StateManagerTest, TestStateManagerGetInstance) {
147 sp<TestStateListener> listener1 = new TestStateListener();
148 StateManager& mgr = StateManager::getInstance();
tsaichristinec876b492019-12-10 13:47:05 -0800149 mgr.clear();
tsaichristine10978642019-09-10 14:12:49 -0700150
151 mgr.registerListener(android::util::SCREEN_STATE_CHANGED, listener1);
152 EXPECT_EQ(1, mgr.getStateTrackersCount());
153 EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
154}
155
156/**
157 * Test registering listeners to StateTrackers
158 *
159 * - StateManager will create a new StateTracker if it doesn't already exist
160 * and then register the listener to the StateTracker.
161 * - If a listener is already registered to a StateTracker, it is not added again.
162 * - StateTrackers are only created for atoms that are state atoms.
163 */
164TEST(StateTrackerTest, TestRegisterListener) {
165 sp<TestStateListener> listener1 = new TestStateListener();
166 sp<TestStateListener> listener2 = new TestStateListener();
167 StateManager mgr;
168
169 // Register listener to non-existing StateTracker
170 EXPECT_EQ(0, mgr.getStateTrackersCount());
tsaichristined21aacf2019-10-07 14:47:38 -0700171 EXPECT_TRUE(mgr.registerListener(android::util::SCREEN_STATE_CHANGED, listener1));
tsaichristine10978642019-09-10 14:12:49 -0700172 EXPECT_EQ(1, mgr.getStateTrackersCount());
173 EXPECT_EQ(1, mgr.getListenersCount(android::util::SCREEN_STATE_CHANGED));
174
175 // Register listener to existing StateTracker
tsaichristined21aacf2019-10-07 14:47:38 -0700176 EXPECT_TRUE(mgr.registerListener(android::util::SCREEN_STATE_CHANGED, listener2));
tsaichristine10978642019-09-10 14:12:49 -0700177 EXPECT_EQ(1, mgr.getStateTrackersCount());
178 EXPECT_EQ(2, mgr.getListenersCount(android::util::SCREEN_STATE_CHANGED));
179
180 // Register already registered listener to existing StateTracker
tsaichristined21aacf2019-10-07 14:47:38 -0700181 EXPECT_TRUE(mgr.registerListener(android::util::SCREEN_STATE_CHANGED, listener2));
tsaichristine10978642019-09-10 14:12:49 -0700182 EXPECT_EQ(1, mgr.getStateTrackersCount());
183 EXPECT_EQ(2, mgr.getListenersCount(android::util::SCREEN_STATE_CHANGED));
184
185 // Register listener to non-state atom
tsaichristined21aacf2019-10-07 14:47:38 -0700186 EXPECT_FALSE(mgr.registerListener(android::util::BATTERY_LEVEL_CHANGED, listener2));
tsaichristine10978642019-09-10 14:12:49 -0700187 EXPECT_EQ(1, mgr.getStateTrackersCount());
188}
189
190/**
191 * Test unregistering listeners from StateTrackers
192 *
193 * - StateManager will unregister listeners from a StateTracker only if the
194 * StateTracker exists and the listener is registered to the StateTracker.
195 * - Once all listeners are removed from a StateTracker, the StateTracker
196 * is also removed.
197 */
198TEST(StateTrackerTest, TestUnregisterListener) {
199 sp<TestStateListener> listener1 = new TestStateListener();
200 sp<TestStateListener> listener2 = new TestStateListener();
201 StateManager mgr;
202
203 // Unregister listener from non-existing StateTracker
204 EXPECT_EQ(0, mgr.getStateTrackersCount());
205 mgr.unregisterListener(android::util::SCREEN_STATE_CHANGED, listener1);
206 EXPECT_EQ(0, mgr.getStateTrackersCount());
207 EXPECT_EQ(-1, mgr.getListenersCount(android::util::SCREEN_STATE_CHANGED));
208
209 // Unregister non-registered listener from existing StateTracker
210 mgr.registerListener(android::util::SCREEN_STATE_CHANGED, listener1);
211 EXPECT_EQ(1, mgr.getStateTrackersCount());
212 EXPECT_EQ(1, mgr.getListenersCount(android::util::SCREEN_STATE_CHANGED));
213 mgr.unregisterListener(android::util::SCREEN_STATE_CHANGED, listener2);
214 EXPECT_EQ(1, mgr.getStateTrackersCount());
215 EXPECT_EQ(1, mgr.getListenersCount(android::util::SCREEN_STATE_CHANGED));
216
217 // Unregister second-to-last listener from StateTracker
218 mgr.registerListener(android::util::SCREEN_STATE_CHANGED, listener2);
219 mgr.unregisterListener(android::util::SCREEN_STATE_CHANGED, listener1);
220 EXPECT_EQ(1, mgr.getStateTrackersCount());
221 EXPECT_EQ(1, mgr.getListenersCount(android::util::SCREEN_STATE_CHANGED));
222
223 // Unregister last listener from StateTracker
224 mgr.unregisterListener(android::util::SCREEN_STATE_CHANGED, listener2);
225 EXPECT_EQ(0, mgr.getStateTrackersCount());
226 EXPECT_EQ(-1, mgr.getListenersCount(android::util::SCREEN_STATE_CHANGED));
227}
228
229/**
230 * Test StateManager's onLogEvent and StateListener's onStateChanged correctly
231 * updates listener for states without primary keys.
232 */
233TEST(StateTrackerTest, TestStateChangeNoPrimaryFields) {
234 sp<TestStateListener> listener1 = new TestStateListener();
235 StateManager mgr;
236 mgr.registerListener(android::util::SCREEN_STATE_CHANGED, listener1);
237
238 // log event
239 std::shared_ptr<LogEvent> event =
240 buildScreenEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON);
241 mgr.onLogEvent(*event);
242
243 // check listener was updated
244 EXPECT_EQ(1, listener1->updates.size());
245 EXPECT_EQ(DEFAULT_DIMENSION_KEY, listener1->updates[0].mKey);
246 EXPECT_EQ(2, listener1->updates[0].mState);
247
248 // check StateTracker was updated by querying for state
249 HashableDimensionKey queryKey = DEFAULT_DIMENSION_KEY;
tsaichristine69000e62019-10-18 17:34:52 -0700250 EXPECT_EQ(2, getStateInt(mgr, android::util::SCREEN_STATE_CHANGED, queryKey));
tsaichristine10978642019-09-10 14:12:49 -0700251}
252
253/**
254 * Test StateManager's onLogEvent and StateListener's onStateChanged correctly
tsaichristined21aacf2019-10-07 14:47:38 -0700255 * updates listener for states with one primary key.
tsaichristine10978642019-09-10 14:12:49 -0700256 */
257TEST(StateTrackerTest, TestStateChangeOnePrimaryField) {
258 sp<TestStateListener> listener1 = new TestStateListener();
259 StateManager mgr;
260 mgr.registerListener(android::util::UID_PROCESS_STATE_CHANGED, listener1);
261
262 // log event
tsaichristined21aacf2019-10-07 14:47:38 -0700263 std::shared_ptr<LogEvent> event =
264 buildUidProcessEvent(1000 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_TOP);
tsaichristine10978642019-09-10 14:12:49 -0700265 mgr.onLogEvent(*event);
266
267 // check listener was updated
268 EXPECT_EQ(1, listener1->updates.size());
269 EXPECT_EQ(1000, listener1->updates[0].mKey.getValues()[0].mValue.int_value);
270 EXPECT_EQ(1002, listener1->updates[0].mState);
271
272 // check StateTracker was updated by querying for state
273 HashableDimensionKey queryKey;
tsaichristined21aacf2019-10-07 14:47:38 -0700274 getUidProcessKey(1000 /* uid */, &queryKey);
tsaichristine69000e62019-10-18 17:34:52 -0700275 EXPECT_EQ(1002, getStateInt(mgr, android::util::UID_PROCESS_STATE_CHANGED, queryKey));
tsaichristine10978642019-09-10 14:12:49 -0700276}
277
tsaichristined21aacf2019-10-07 14:47:38 -0700278/**
279 * Test StateManager's onLogEvent and StateListener's onStateChanged correctly
280 * updates listener for states with multiple primary keys.
281 */
tsaichristine10978642019-09-10 14:12:49 -0700282TEST(StateTrackerTest, TestStateChangeMultiplePrimaryFields) {
283 sp<TestStateListener> listener1 = new TestStateListener();
284 StateManager mgr;
285 mgr.registerListener(android::util::OVERLAY_STATE_CHANGED, listener1);
286
287 // log event
tsaichristined21aacf2019-10-07 14:47:38 -0700288 std::shared_ptr<LogEvent> event =
289 buildOverlayEvent(1000 /* uid */, "package1", 1); // state: ENTERED
tsaichristine10978642019-09-10 14:12:49 -0700290 mgr.onLogEvent(*event);
291
tsaichristined21aacf2019-10-07 14:47:38 -0700292 // check listener was updated
tsaichristine10978642019-09-10 14:12:49 -0700293 EXPECT_EQ(1, listener1->updates.size());
294 EXPECT_EQ(1000, listener1->updates[0].mKey.getValues()[0].mValue.int_value);
295 EXPECT_EQ(1, listener1->updates[0].mState);
tsaichristined21aacf2019-10-07 14:47:38 -0700296
297 // check StateTracker was updated by querying for state
298 HashableDimensionKey queryKey;
299 getOverlayKey(1000 /* uid */, "package1", &queryKey);
tsaichristine69000e62019-10-18 17:34:52 -0700300 EXPECT_EQ(1, getStateInt(mgr, android::util::OVERLAY_STATE_CHANGED, queryKey));
tsaichristine10978642019-09-10 14:12:49 -0700301}
302
303/**
304 * Test StateManager's onLogEvent and StateListener's onStateChanged
305 * when there is an error extracting state from log event. Listener is not
306 * updated of state change.
307 */
308TEST(StateTrackerTest, TestStateChangeEventError) {
309 sp<TestStateListener> listener1 = new TestStateListener();
310 StateManager mgr;
311 mgr.registerListener(android::util::OVERLAY_STATE_CHANGED, listener1);
312
313 // log event
tsaichristined21aacf2019-10-07 14:47:38 -0700314 std::shared_ptr<LogEvent> event1 =
315 buildIncorrectOverlayEvent(1000 /* uid */, "package1", 1 /* state */);
316 std::shared_ptr<LogEvent> event2 = buildOverlayEventBadStateType(1001 /* uid */, "package2");
tsaichristine10978642019-09-10 14:12:49 -0700317
tsaichristined21aacf2019-10-07 14:47:38 -0700318 // check listener was updated
319 mgr.onLogEvent(*event1);
320 EXPECT_EQ(0, listener1->updates.size());
321 mgr.onLogEvent(*event2);
tsaichristine10978642019-09-10 14:12:49 -0700322 EXPECT_EQ(0, listener1->updates.size());
323}
324
325TEST(StateTrackerTest, TestStateQuery) {
326 sp<TestStateListener> listener1 = new TestStateListener();
327 sp<TestStateListener> listener2 = new TestStateListener();
328 sp<TestStateListener> listener3 = new TestStateListener();
329 StateManager mgr;
330 mgr.registerListener(android::util::SCREEN_STATE_CHANGED, listener1);
331 mgr.registerListener(android::util::UID_PROCESS_STATE_CHANGED, listener2);
332 mgr.registerListener(android::util::OVERLAY_STATE_CHANGED, listener3);
333
334 std::shared_ptr<LogEvent> event1 = buildUidProcessEvent(
335 1000,
tsaichristined21aacf2019-10-07 14:47:38 -0700336 android::app::ProcessStateEnum::PROCESS_STATE_TOP); // state value: 1002
tsaichristine10978642019-09-10 14:12:49 -0700337 std::shared_ptr<LogEvent> event2 = buildUidProcessEvent(
338 1001,
tsaichristined21aacf2019-10-07 14:47:38 -0700339 android::app::ProcessStateEnum::PROCESS_STATE_FOREGROUND_SERVICE); // state value:
340 // 1003
tsaichristine10978642019-09-10 14:12:49 -0700341 std::shared_ptr<LogEvent> event3 = buildUidProcessEvent(
342 1002,
tsaichristined21aacf2019-10-07 14:47:38 -0700343 android::app::ProcessStateEnum::PROCESS_STATE_PERSISTENT); // state value: 1000
tsaichristine10978642019-09-10 14:12:49 -0700344 std::shared_ptr<LogEvent> event4 = buildUidProcessEvent(
345 1001,
tsaichristined21aacf2019-10-07 14:47:38 -0700346 android::app::ProcessStateEnum::PROCESS_STATE_TOP); // state value: 1002
tsaichristine10978642019-09-10 14:12:49 -0700347 std::shared_ptr<LogEvent> event5 =
tsaichristined21aacf2019-10-07 14:47:38 -0700348 buildScreenEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON);
tsaichristine10978642019-09-10 14:12:49 -0700349 std::shared_ptr<LogEvent> event6 = buildOverlayEvent(1000, "package1", 1);
350 std::shared_ptr<LogEvent> event7 = buildOverlayEvent(1000, "package2", 2);
351
352 mgr.onLogEvent(*event1);
353 mgr.onLogEvent(*event2);
354 mgr.onLogEvent(*event3);
355 mgr.onLogEvent(*event5);
356 mgr.onLogEvent(*event5);
357 mgr.onLogEvent(*event6);
358 mgr.onLogEvent(*event7);
359
360 // Query for UidProcessState of uid 1001
361 HashableDimensionKey queryKey1;
362 getUidProcessKey(1001, &queryKey1);
tsaichristine69000e62019-10-18 17:34:52 -0700363 EXPECT_EQ(1003, getStateInt(mgr, android::util::UID_PROCESS_STATE_CHANGED, queryKey1));
tsaichristine10978642019-09-10 14:12:49 -0700364
365 // Query for UidProcessState of uid 1004 - not in state map
366 HashableDimensionKey queryKey2;
367 getUidProcessKey(1004, &queryKey2);
tsaichristine69000e62019-10-18 17:34:52 -0700368 EXPECT_EQ(-1, getStateInt(mgr, android::util::UID_PROCESS_STATE_CHANGED,
369 queryKey2)); // default state
tsaichristine10978642019-09-10 14:12:49 -0700370
371 // Query for UidProcessState of uid 1001 - after change in state
372 mgr.onLogEvent(*event4);
tsaichristine69000e62019-10-18 17:34:52 -0700373 EXPECT_EQ(1002, getStateInt(mgr, android::util::UID_PROCESS_STATE_CHANGED, queryKey1));
tsaichristine10978642019-09-10 14:12:49 -0700374
375 // Query for ScreenState
tsaichristine69000e62019-10-18 17:34:52 -0700376 EXPECT_EQ(2, getStateInt(mgr, android::util::SCREEN_STATE_CHANGED, DEFAULT_DIMENSION_KEY));
tsaichristine10978642019-09-10 14:12:49 -0700377
378 // Query for OverlayState of uid 1000, package name "package2"
379 HashableDimensionKey queryKey3;
380 getOverlayKey(1000, "package2", &queryKey3);
tsaichristine69000e62019-10-18 17:34:52 -0700381 EXPECT_EQ(2, getStateInt(mgr, android::util::OVERLAY_STATE_CHANGED, queryKey3));
tsaichristine10978642019-09-10 14:12:49 -0700382}
383
384} // namespace statsd
385} // namespace os
386} // namespace android
387#else
388GTEST_LOG_(INFO) << "This test does nothing.\n";
389#endif