blob: 4208fef3860ee832cbdbc6114914a370bff14ad6 [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
tsaichristined21aacf2019-10-07 14:47:38 -070047 void onStateChanged(int atomId, const HashableDimensionKey& primaryKey, int oldState,
tsaichristine10978642019-09-10 14:12:49 -070048 int newState) {
49 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();
149
150 mgr.registerListener(android::util::SCREEN_STATE_CHANGED, listener1);
151 EXPECT_EQ(1, mgr.getStateTrackersCount());
152 EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
153}
154
155/**
156 * Test registering listeners to StateTrackers
157 *
158 * - StateManager will create a new StateTracker if it doesn't already exist
159 * and then register the listener to the StateTracker.
160 * - If a listener is already registered to a StateTracker, it is not added again.
161 * - StateTrackers are only created for atoms that are state atoms.
162 */
163TEST(StateTrackerTest, TestRegisterListener) {
164 sp<TestStateListener> listener1 = new TestStateListener();
165 sp<TestStateListener> listener2 = new TestStateListener();
166 StateManager mgr;
167
168 // Register listener to non-existing StateTracker
169 EXPECT_EQ(0, mgr.getStateTrackersCount());
tsaichristined21aacf2019-10-07 14:47:38 -0700170 EXPECT_TRUE(mgr.registerListener(android::util::SCREEN_STATE_CHANGED, listener1));
tsaichristine10978642019-09-10 14:12:49 -0700171 EXPECT_EQ(1, mgr.getStateTrackersCount());
172 EXPECT_EQ(1, mgr.getListenersCount(android::util::SCREEN_STATE_CHANGED));
173
174 // Register listener to existing StateTracker
tsaichristined21aacf2019-10-07 14:47:38 -0700175 EXPECT_TRUE(mgr.registerListener(android::util::SCREEN_STATE_CHANGED, listener2));
tsaichristine10978642019-09-10 14:12:49 -0700176 EXPECT_EQ(1, mgr.getStateTrackersCount());
177 EXPECT_EQ(2, mgr.getListenersCount(android::util::SCREEN_STATE_CHANGED));
178
179 // Register already registered listener to existing StateTracker
tsaichristined21aacf2019-10-07 14:47:38 -0700180 EXPECT_TRUE(mgr.registerListener(android::util::SCREEN_STATE_CHANGED, listener2));
tsaichristine10978642019-09-10 14:12:49 -0700181 EXPECT_EQ(1, mgr.getStateTrackersCount());
182 EXPECT_EQ(2, mgr.getListenersCount(android::util::SCREEN_STATE_CHANGED));
183
184 // Register listener to non-state atom
tsaichristined21aacf2019-10-07 14:47:38 -0700185 EXPECT_FALSE(mgr.registerListener(android::util::BATTERY_LEVEL_CHANGED, listener2));
tsaichristine10978642019-09-10 14:12:49 -0700186 EXPECT_EQ(1, mgr.getStateTrackersCount());
187}
188
189/**
190 * Test unregistering listeners from StateTrackers
191 *
192 * - StateManager will unregister listeners from a StateTracker only if the
193 * StateTracker exists and the listener is registered to the StateTracker.
194 * - Once all listeners are removed from a StateTracker, the StateTracker
195 * is also removed.
196 */
197TEST(StateTrackerTest, TestUnregisterListener) {
198 sp<TestStateListener> listener1 = new TestStateListener();
199 sp<TestStateListener> listener2 = new TestStateListener();
200 StateManager mgr;
201
202 // Unregister listener from non-existing StateTracker
203 EXPECT_EQ(0, mgr.getStateTrackersCount());
204 mgr.unregisterListener(android::util::SCREEN_STATE_CHANGED, listener1);
205 EXPECT_EQ(0, mgr.getStateTrackersCount());
206 EXPECT_EQ(-1, mgr.getListenersCount(android::util::SCREEN_STATE_CHANGED));
207
208 // Unregister non-registered listener from existing StateTracker
209 mgr.registerListener(android::util::SCREEN_STATE_CHANGED, listener1);
210 EXPECT_EQ(1, mgr.getStateTrackersCount());
211 EXPECT_EQ(1, mgr.getListenersCount(android::util::SCREEN_STATE_CHANGED));
212 mgr.unregisterListener(android::util::SCREEN_STATE_CHANGED, listener2);
213 EXPECT_EQ(1, mgr.getStateTrackersCount());
214 EXPECT_EQ(1, mgr.getListenersCount(android::util::SCREEN_STATE_CHANGED));
215
216 // Unregister second-to-last listener from StateTracker
217 mgr.registerListener(android::util::SCREEN_STATE_CHANGED, listener2);
218 mgr.unregisterListener(android::util::SCREEN_STATE_CHANGED, listener1);
219 EXPECT_EQ(1, mgr.getStateTrackersCount());
220 EXPECT_EQ(1, mgr.getListenersCount(android::util::SCREEN_STATE_CHANGED));
221
222 // Unregister last listener from StateTracker
223 mgr.unregisterListener(android::util::SCREEN_STATE_CHANGED, listener2);
224 EXPECT_EQ(0, mgr.getStateTrackersCount());
225 EXPECT_EQ(-1, mgr.getListenersCount(android::util::SCREEN_STATE_CHANGED));
226}
227
228/**
229 * Test StateManager's onLogEvent and StateListener's onStateChanged correctly
230 * updates listener for states without primary keys.
231 */
232TEST(StateTrackerTest, TestStateChangeNoPrimaryFields) {
233 sp<TestStateListener> listener1 = new TestStateListener();
234 StateManager mgr;
235 mgr.registerListener(android::util::SCREEN_STATE_CHANGED, listener1);
236
237 // log event
238 std::shared_ptr<LogEvent> event =
239 buildScreenEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON);
240 mgr.onLogEvent(*event);
241
242 // check listener was updated
243 EXPECT_EQ(1, listener1->updates.size());
244 EXPECT_EQ(DEFAULT_DIMENSION_KEY, listener1->updates[0].mKey);
245 EXPECT_EQ(2, listener1->updates[0].mState);
246
247 // check StateTracker was updated by querying for state
248 HashableDimensionKey queryKey = DEFAULT_DIMENSION_KEY;
tsaichristine69000e62019-10-18 17:34:52 -0700249 EXPECT_EQ(2, getStateInt(mgr, android::util::SCREEN_STATE_CHANGED, queryKey));
tsaichristine10978642019-09-10 14:12:49 -0700250}
251
252/**
253 * Test StateManager's onLogEvent and StateListener's onStateChanged correctly
tsaichristined21aacf2019-10-07 14:47:38 -0700254 * updates listener for states with one primary key.
tsaichristine10978642019-09-10 14:12:49 -0700255 */
256TEST(StateTrackerTest, TestStateChangeOnePrimaryField) {
257 sp<TestStateListener> listener1 = new TestStateListener();
258 StateManager mgr;
259 mgr.registerListener(android::util::UID_PROCESS_STATE_CHANGED, listener1);
260
261 // log event
tsaichristined21aacf2019-10-07 14:47:38 -0700262 std::shared_ptr<LogEvent> event =
263 buildUidProcessEvent(1000 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_TOP);
tsaichristine10978642019-09-10 14:12:49 -0700264 mgr.onLogEvent(*event);
265
266 // check listener was updated
267 EXPECT_EQ(1, listener1->updates.size());
268 EXPECT_EQ(1000, listener1->updates[0].mKey.getValues()[0].mValue.int_value);
269 EXPECT_EQ(1002, listener1->updates[0].mState);
270
271 // check StateTracker was updated by querying for state
272 HashableDimensionKey queryKey;
tsaichristined21aacf2019-10-07 14:47:38 -0700273 getUidProcessKey(1000 /* uid */, &queryKey);
tsaichristine69000e62019-10-18 17:34:52 -0700274 EXPECT_EQ(1002, getStateInt(mgr, android::util::UID_PROCESS_STATE_CHANGED, queryKey));
tsaichristine10978642019-09-10 14:12:49 -0700275}
276
tsaichristined21aacf2019-10-07 14:47:38 -0700277/**
278 * Test StateManager's onLogEvent and StateListener's onStateChanged correctly
279 * updates listener for states with multiple primary keys.
280 */
tsaichristine10978642019-09-10 14:12:49 -0700281TEST(StateTrackerTest, TestStateChangeMultiplePrimaryFields) {
282 sp<TestStateListener> listener1 = new TestStateListener();
283 StateManager mgr;
284 mgr.registerListener(android::util::OVERLAY_STATE_CHANGED, listener1);
285
286 // log event
tsaichristined21aacf2019-10-07 14:47:38 -0700287 std::shared_ptr<LogEvent> event =
288 buildOverlayEvent(1000 /* uid */, "package1", 1); // state: ENTERED
tsaichristine10978642019-09-10 14:12:49 -0700289 mgr.onLogEvent(*event);
290
tsaichristined21aacf2019-10-07 14:47:38 -0700291 // check listener was updated
tsaichristine10978642019-09-10 14:12:49 -0700292 EXPECT_EQ(1, listener1->updates.size());
293 EXPECT_EQ(1000, listener1->updates[0].mKey.getValues()[0].mValue.int_value);
294 EXPECT_EQ(1, listener1->updates[0].mState);
tsaichristined21aacf2019-10-07 14:47:38 -0700295
296 // check StateTracker was updated by querying for state
297 HashableDimensionKey queryKey;
298 getOverlayKey(1000 /* uid */, "package1", &queryKey);
tsaichristine69000e62019-10-18 17:34:52 -0700299 EXPECT_EQ(1, getStateInt(mgr, android::util::OVERLAY_STATE_CHANGED, queryKey));
tsaichristine10978642019-09-10 14:12:49 -0700300}
301
302/**
303 * Test StateManager's onLogEvent and StateListener's onStateChanged
304 * when there is an error extracting state from log event. Listener is not
305 * updated of state change.
306 */
307TEST(StateTrackerTest, TestStateChangeEventError) {
308 sp<TestStateListener> listener1 = new TestStateListener();
309 StateManager mgr;
310 mgr.registerListener(android::util::OVERLAY_STATE_CHANGED, listener1);
311
312 // log event
tsaichristined21aacf2019-10-07 14:47:38 -0700313 std::shared_ptr<LogEvent> event1 =
314 buildIncorrectOverlayEvent(1000 /* uid */, "package1", 1 /* state */);
315 std::shared_ptr<LogEvent> event2 = buildOverlayEventBadStateType(1001 /* uid */, "package2");
tsaichristine10978642019-09-10 14:12:49 -0700316
tsaichristined21aacf2019-10-07 14:47:38 -0700317 // check listener was updated
318 mgr.onLogEvent(*event1);
319 EXPECT_EQ(0, listener1->updates.size());
320 mgr.onLogEvent(*event2);
tsaichristine10978642019-09-10 14:12:49 -0700321 EXPECT_EQ(0, listener1->updates.size());
322}
323
324TEST(StateTrackerTest, TestStateQuery) {
325 sp<TestStateListener> listener1 = new TestStateListener();
326 sp<TestStateListener> listener2 = new TestStateListener();
327 sp<TestStateListener> listener3 = new TestStateListener();
328 StateManager mgr;
329 mgr.registerListener(android::util::SCREEN_STATE_CHANGED, listener1);
330 mgr.registerListener(android::util::UID_PROCESS_STATE_CHANGED, listener2);
331 mgr.registerListener(android::util::OVERLAY_STATE_CHANGED, listener3);
332
333 std::shared_ptr<LogEvent> event1 = buildUidProcessEvent(
334 1000,
tsaichristined21aacf2019-10-07 14:47:38 -0700335 android::app::ProcessStateEnum::PROCESS_STATE_TOP); // state value: 1002
tsaichristine10978642019-09-10 14:12:49 -0700336 std::shared_ptr<LogEvent> event2 = buildUidProcessEvent(
337 1001,
tsaichristined21aacf2019-10-07 14:47:38 -0700338 android::app::ProcessStateEnum::PROCESS_STATE_FOREGROUND_SERVICE); // state value:
339 // 1003
tsaichristine10978642019-09-10 14:12:49 -0700340 std::shared_ptr<LogEvent> event3 = buildUidProcessEvent(
341 1002,
tsaichristined21aacf2019-10-07 14:47:38 -0700342 android::app::ProcessStateEnum::PROCESS_STATE_PERSISTENT); // state value: 1000
tsaichristine10978642019-09-10 14:12:49 -0700343 std::shared_ptr<LogEvent> event4 = buildUidProcessEvent(
344 1001,
tsaichristined21aacf2019-10-07 14:47:38 -0700345 android::app::ProcessStateEnum::PROCESS_STATE_TOP); // state value: 1002
tsaichristine10978642019-09-10 14:12:49 -0700346 std::shared_ptr<LogEvent> event5 =
tsaichristined21aacf2019-10-07 14:47:38 -0700347 buildScreenEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON);
tsaichristine10978642019-09-10 14:12:49 -0700348 std::shared_ptr<LogEvent> event6 = buildOverlayEvent(1000, "package1", 1);
349 std::shared_ptr<LogEvent> event7 = buildOverlayEvent(1000, "package2", 2);
350
351 mgr.onLogEvent(*event1);
352 mgr.onLogEvent(*event2);
353 mgr.onLogEvent(*event3);
354 mgr.onLogEvent(*event5);
355 mgr.onLogEvent(*event5);
356 mgr.onLogEvent(*event6);
357 mgr.onLogEvent(*event7);
358
359 // Query for UidProcessState of uid 1001
360 HashableDimensionKey queryKey1;
361 getUidProcessKey(1001, &queryKey1);
tsaichristine69000e62019-10-18 17:34:52 -0700362 EXPECT_EQ(1003, getStateInt(mgr, android::util::UID_PROCESS_STATE_CHANGED, queryKey1));
tsaichristine10978642019-09-10 14:12:49 -0700363
364 // Query for UidProcessState of uid 1004 - not in state map
365 HashableDimensionKey queryKey2;
366 getUidProcessKey(1004, &queryKey2);
tsaichristine69000e62019-10-18 17:34:52 -0700367 EXPECT_EQ(-1, getStateInt(mgr, android::util::UID_PROCESS_STATE_CHANGED,
368 queryKey2)); // default state
tsaichristine10978642019-09-10 14:12:49 -0700369
370 // Query for UidProcessState of uid 1001 - after change in state
371 mgr.onLogEvent(*event4);
tsaichristine69000e62019-10-18 17:34:52 -0700372 EXPECT_EQ(1002, getStateInt(mgr, android::util::UID_PROCESS_STATE_CHANGED, queryKey1));
tsaichristine10978642019-09-10 14:12:49 -0700373
374 // Query for ScreenState
tsaichristine69000e62019-10-18 17:34:52 -0700375 EXPECT_EQ(2, getStateInt(mgr, android::util::SCREEN_STATE_CHANGED, DEFAULT_DIMENSION_KEY));
tsaichristine10978642019-09-10 14:12:49 -0700376
377 // Query for OverlayState of uid 1000, package name "package2"
378 HashableDimensionKey queryKey3;
379 getOverlayKey(1000, "package2", &queryKey3);
tsaichristine69000e62019-10-18 17:34:52 -0700380 EXPECT_EQ(2, getStateInt(mgr, android::util::OVERLAY_STATE_CHANGED, queryKey3));
tsaichristine10978642019-09-10 14:12:49 -0700381}
382
383} // namespace statsd
384} // namespace os
385} // namespace android
386#else
387GTEST_LOG_(INFO) << "This test does nothing.\n";
388#endif