blob: 86f6cd331fc96b2a0d44348b5bee852254af1ee2 [file] [log] [blame]
Jason Monk8c09ac72017-03-16 11:53:40 -04001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
5 * except in compliance with the License. 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 distributed under the
10 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
11 * KIND, either express or implied. See the License for the specific language governing
12 * permissions and limitations under the License.
13 */
14
15package com.android.systemui.qs.tileimpl;
16
17import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION_QS_CLICK;
18import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION_QS_LONG_PRESS;
19import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION_QS_SECONDARY_CLICK;
20import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_QS_POSITION;
21import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_QS_VALUE;
Susi Kharraz-Post9b033672018-11-28 08:14:07 -050022import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_STATUS_BAR_STATE;
Jason Monk8c09ac72017-03-16 11:53:40 -040023import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_ACTION;
24
Susi Kharraz-Post9b033672018-11-28 08:14:07 -050025import static org.junit.Assert.assertEquals;
Jason Monk2ef8ed62017-09-07 14:51:41 -040026import static org.mockito.ArgumentMatchers.any;
Jason Monk8c09ac72017-03-16 11:53:40 -040027import static org.mockito.ArgumentMatchers.anyInt;
28import static org.mockito.ArgumentMatchers.eq;
29import static org.mockito.Matchers.argThat;
Jason Monk1c6116c2017-09-06 17:33:01 -040030import static org.mockito.Mockito.clearInvocations;
Jason Monk8c09ac72017-03-16 11:53:40 -040031import static org.mockito.Mockito.mock;
Jason Monk1c6116c2017-09-06 17:33:01 -040032import static org.mockito.Mockito.never;
33import static org.mockito.Mockito.spy;
Jason Monk8c09ac72017-03-16 11:53:40 -040034import static org.mockito.Mockito.verify;
35import static org.mockito.Mockito.when;
36
Jason Monk1c6116c2017-09-06 17:33:01 -040037import static java.lang.Thread.sleep;
38
Jason Monk8c09ac72017-03-16 11:53:40 -040039import android.content.Intent;
40import android.metrics.LogMaker;
Jason Monkfba8faf2017-05-23 10:42:59 -040041import android.support.test.filters.SmallTest;
Jason Monk8c09ac72017-03-16 11:53:40 -040042import android.testing.AndroidTestingRunner;
43import android.testing.TestableLooper;
44import android.testing.TestableLooper.RunWithLooper;
45
46import com.android.internal.logging.MetricsLogger;
47import com.android.systemui.Dependency;
48import com.android.systemui.SysuiTestCase;
49import com.android.systemui.plugins.qs.QSTile;
Beverly8fdb5332019-02-04 14:29:49 -050050import com.android.systemui.plugins.statusbar.StatusBarStateController;
Jason Monk8c09ac72017-03-16 11:53:40 -040051import com.android.systemui.qs.QSHost;
52import com.android.systemui.qs.QSTileHost;
Susi Kharraz-Post9b033672018-11-28 08:14:07 -050053import com.android.systemui.statusbar.StatusBarState;
Jason Monk8c09ac72017-03-16 11:53:40 -040054
55import org.junit.Before;
Geoffrey Pitsch659a91b2017-11-28 13:33:13 -050056import org.junit.Ignore;
Jason Monk8c09ac72017-03-16 11:53:40 -040057import org.junit.Test;
58import org.junit.runner.RunWith;
Susi Kharraz-Post9b033672018-11-28 08:14:07 -050059import org.mockito.ArgumentCaptor;
Jason Monk8c09ac72017-03-16 11:53:40 -040060import org.mockito.ArgumentMatcher;
Susi Kharraz-Post9b033672018-11-28 08:14:07 -050061import org.mockito.Captor;
62import org.mockito.MockitoAnnotations;
Jason Monk8c09ac72017-03-16 11:53:40 -040063
64@RunWith(AndroidTestingRunner.class)
65@RunWithLooper
Jason Monkfba8faf2017-05-23 10:42:59 -040066@SmallTest
Jason Monk8c09ac72017-03-16 11:53:40 -040067public class QSTileImplTest extends SysuiTestCase {
68
69 public static final int POSITION = 14;
70 private TestableLooper mTestableLooper;
71 private TileImpl mTile;
72 private QSTileHost mHost;
73 private MetricsLogger mMetricsLogger;
Susi Kharraz-Post9b033672018-11-28 08:14:07 -050074 private StatusBarStateController mStatusBarStateController;
75
76 @Captor
77 private ArgumentCaptor<LogMaker> mLogCaptor;
Jason Monk8c09ac72017-03-16 11:53:40 -040078
79 @Before
80 public void setup() throws Exception {
Susi Kharraz-Post9b033672018-11-28 08:14:07 -050081 MockitoAnnotations.initMocks(this);
Jason Monk8c09ac72017-03-16 11:53:40 -040082 String spec = "spec";
83 mTestableLooper = TestableLooper.get(this);
84 mDependency.injectTestDependency(Dependency.BG_LOOPER, mTestableLooper.getLooper());
85 mMetricsLogger = mDependency.injectMockDependency(MetricsLogger.class);
Susi Kharraz-Post9b033672018-11-28 08:14:07 -050086 mStatusBarStateController =
87 mDependency.injectMockDependency(StatusBarStateController.class);
Jason Monk8c09ac72017-03-16 11:53:40 -040088 mHost = mock(QSTileHost.class);
89 when(mHost.indexOf(spec)).thenReturn(POSITION);
Rohan Shahdb2cfa32018-02-20 11:27:22 -080090 when(mHost.getContext()).thenReturn(mContext.getBaseContext());
Jason Monk1c6116c2017-09-06 17:33:01 -040091
92 mTile = spy(new TileImpl(mHost));
93 mTile.mHandler = mTile.new H(mTestableLooper.getLooper());
94 mTile.setTileSpec(spec);
Jason Monk8c09ac72017-03-16 11:53:40 -040095 }
96
97 @Test
98 public void testClick_Metrics() {
99 mTile.click();
100 verify(mMetricsLogger).write(argThat(new TileLogMatcher(ACTION_QS_CLICK)));
101 }
102
103 @Test
Susi Kharraz-Post9b033672018-11-28 08:14:07 -0500104 public void testClick_Metrics_Status_Bar_Status() {
105 when(mStatusBarStateController.getState()).thenReturn(StatusBarState.SHADE);
106 mTile.click();
107 verify(mMetricsLogger).write(mLogCaptor.capture());
108 assertEquals(StatusBarState.SHADE, mLogCaptor.getValue()
109 .getTaggedData(FIELD_STATUS_BAR_STATE));
110 }
111
112 @Test
Jason Monk8c09ac72017-03-16 11:53:40 -0400113 public void testSecondaryClick_Metrics() {
114 mTile.secondaryClick();
115 verify(mMetricsLogger).write(argThat(new TileLogMatcher(ACTION_QS_SECONDARY_CLICK)));
116 }
117
118 @Test
Susi Kharraz-Post9b033672018-11-28 08:14:07 -0500119 public void testSecondaryClick_Metrics_Status_Bar_Status() {
120 when(mStatusBarStateController.getState()).thenReturn(StatusBarState.KEYGUARD);
121 mTile.secondaryClick();
122 verify(mMetricsLogger).write(mLogCaptor.capture());
123 assertEquals(StatusBarState.KEYGUARD, mLogCaptor.getValue()
124 .getTaggedData(FIELD_STATUS_BAR_STATE));
125 }
126
127 @Test
Jason Monk8c09ac72017-03-16 11:53:40 -0400128 public void testLongClick_Metrics() {
129 mTile.longClick();
130 verify(mMetricsLogger).write(argThat(new TileLogMatcher(ACTION_QS_LONG_PRESS)));
131 }
132
133 @Test
Susi Kharraz-Post9b033672018-11-28 08:14:07 -0500134 public void testLongClick_Metrics_Status_Bar_Status() {
135 when(mStatusBarStateController.getState()).thenReturn(StatusBarState.SHADE_LOCKED);
136 mTile.click();
137 verify(mMetricsLogger).write(mLogCaptor.capture());
138 assertEquals(StatusBarState.SHADE_LOCKED, mLogCaptor.getValue()
139 .getTaggedData(FIELD_STATUS_BAR_STATE));
140 }
141
142 @Test
143 public void testPopulateWithLockedScreen() {
144 LogMaker maker = mock(LogMaker.class);
145 when(maker.setSubtype(anyInt())).thenReturn(maker);
146 when(maker.addTaggedData(anyInt(), any())).thenReturn(maker);
147 mTile.getState().value = true;
148 mTile.populate(maker);
149 verify(maker).addTaggedData(eq(FIELD_QS_VALUE), eq(1));
150 verify(maker).addTaggedData(eq(FIELD_QS_POSITION), eq(POSITION));
151 }
152
153 @Test
154 public void testPopulateWithUnlockedScreen() {
Jason Monk8c09ac72017-03-16 11:53:40 -0400155 LogMaker maker = mock(LogMaker.class);
156 when(maker.setSubtype(anyInt())).thenReturn(maker);
Jason Monk2ef8ed62017-09-07 14:51:41 -0400157 when(maker.addTaggedData(anyInt(), any())).thenReturn(maker);
Jason Monk8c09ac72017-03-16 11:53:40 -0400158 mTile.getState().value = true;
159 mTile.populate(maker);
160 verify(maker).addTaggedData(eq(FIELD_QS_VALUE), eq(1));
161 verify(maker).addTaggedData(eq(FIELD_QS_POSITION), eq(POSITION));
162 }
163
Jason Monk1c6116c2017-09-06 17:33:01 -0400164 @Test
Geoffrey Pitsch659a91b2017-11-28 13:33:13 -0500165 @Ignore("flaky")
Jason Monk1c6116c2017-09-06 17:33:01 -0400166 public void testStaleTimeout() throws InterruptedException {
167 when(mTile.getStaleTimeout()).thenReturn(5l);
168 clearInvocations(mTile);
169
170 mTile.handleRefreshState(null);
171 mTestableLooper.processAllMessages();
172 verify(mTile, never()).handleStale();
173
174 sleep(10);
175 mTestableLooper.processAllMessages();
176 verify(mTile).handleStale();
177 }
178
179 @Test
180 public void testStaleListening() {
181 mTile.handleStale();
182 mTestableLooper.processAllMessages();
183 verify(mTile).handleSetListening(eq(true));
184
185 mTile.handleRefreshState(null);
186 mTestableLooper.processAllMessages();
187 verify(mTile).handleSetListening(eq(false));
188 }
189
Jason Monk8c09ac72017-03-16 11:53:40 -0400190 private class TileLogMatcher implements ArgumentMatcher<LogMaker> {
191
192 private final int mCategory;
193 public String mInvalid;
194
195 public TileLogMatcher(int category) {
196 mCategory = category;
197 }
198
199 @Override
200 public boolean matches(LogMaker arg) {
201 if (arg.getCategory() != mCategory) {
202 mInvalid = "Expected category " + mCategory + " but was " + arg.getCategory();
203 return false;
204 }
205 if (arg.getType() != TYPE_ACTION) {
206 mInvalid = "Expected type " + TYPE_ACTION + " but was " + arg.getType();
207 return false;
208 }
209 if (arg.getSubtype() != mTile.getMetricsCategory()) {
210 mInvalid = "Expected subtype " + mTile.getMetricsCategory() + " but was "
211 + arg.getSubtype();
212 return false;
213 }
214 return true;
215 }
216
217 @Override
218 public String toString() {
219 return mInvalid;
220 }
221 }
222
223 private static class TileImpl extends QSTileImpl<QSTile.BooleanState> {
224 protected TileImpl(QSHost host) {
225 super(host);
226 }
227
228 @Override
229 public BooleanState newTileState() {
230 return new BooleanState();
231 }
232
233 @Override
234 protected void handleClick() {
235
236 }
237
238 @Override
239 protected void handleUpdateState(BooleanState state, Object arg) {
240
241 }
242
243 @Override
244 public int getMetricsCategory() {
245 return 42;
246 }
247
248 @Override
249 public Intent getLongClickIntent() {
250 return null;
251 }
252
253 @Override
Jason Monk1c6116c2017-09-06 17:33:01 -0400254 protected void handleSetListening(boolean listening) {
Jason Monk8c09ac72017-03-16 11:53:40 -0400255
256 }
257
258 @Override
259 public CharSequence getTileLabel() {
260 return null;
261 }
262 }
263}