blob: 3df8a8aadda25d7e7961a212b9a4dde06b51ad19 [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
37import android.content.Intent;
38import android.metrics.LogMaker;
39import android.testing.AndroidTestingRunner;
40import android.testing.TestableLooper;
41import android.testing.TestableLooper.RunWithLooper;
42
Brett Chabot84151d92019-02-27 15:37:59 -080043import androidx.test.filters.SmallTest;
44
Jason Monk8c09ac72017-03-16 11:53:40 -040045import com.android.internal.logging.MetricsLogger;
46import com.android.systemui.Dependency;
47import com.android.systemui.SysuiTestCase;
48import com.android.systemui.plugins.qs.QSTile;
Beverly8fdb5332019-02-04 14:29:49 -050049import com.android.systemui.plugins.statusbar.StatusBarStateController;
Jason Monk8c09ac72017-03-16 11:53:40 -040050import com.android.systemui.qs.QSHost;
51import com.android.systemui.qs.QSTileHost;
Susi Kharraz-Post9b033672018-11-28 08:14:07 -050052import com.android.systemui.statusbar.StatusBarState;
Jason Monk8c09ac72017-03-16 11:53:40 -040053
54import org.junit.Before;
Geoffrey Pitsch659a91b2017-11-28 13:33:13 -050055import org.junit.Ignore;
Jason Monk8c09ac72017-03-16 11:53:40 -040056import org.junit.Test;
57import org.junit.runner.RunWith;
Susi Kharraz-Post9b033672018-11-28 08:14:07 -050058import org.mockito.ArgumentCaptor;
Jason Monk8c09ac72017-03-16 11:53:40 -040059import org.mockito.ArgumentMatcher;
Susi Kharraz-Post9b033672018-11-28 08:14:07 -050060import org.mockito.Captor;
61import org.mockito.MockitoAnnotations;
Jason Monk8c09ac72017-03-16 11:53:40 -040062
Brett Chabot84151d92019-02-27 15:37:59 -080063import static java.lang.Thread.sleep;
64
Jason Monk8c09ac72017-03-16 11:53:40 -040065@RunWith(AndroidTestingRunner.class)
66@RunWithLooper
Jason Monkfba8faf2017-05-23 10:42:59 -040067@SmallTest
Jason Monk8c09ac72017-03-16 11:53:40 -040068public class QSTileImplTest extends SysuiTestCase {
69
70 public static final int POSITION = 14;
71 private TestableLooper mTestableLooper;
72 private TileImpl mTile;
73 private QSTileHost mHost;
74 private MetricsLogger mMetricsLogger;
Susi Kharraz-Post9b033672018-11-28 08:14:07 -050075 private StatusBarStateController mStatusBarStateController;
76
77 @Captor
78 private ArgumentCaptor<LogMaker> mLogCaptor;
Jason Monk8c09ac72017-03-16 11:53:40 -040079
80 @Before
81 public void setup() throws Exception {
Susi Kharraz-Post9b033672018-11-28 08:14:07 -050082 MockitoAnnotations.initMocks(this);
Jason Monk8c09ac72017-03-16 11:53:40 -040083 String spec = "spec";
84 mTestableLooper = TestableLooper.get(this);
85 mDependency.injectTestDependency(Dependency.BG_LOOPER, mTestableLooper.getLooper());
86 mMetricsLogger = mDependency.injectMockDependency(MetricsLogger.class);
Susi Kharraz-Post9b033672018-11-28 08:14:07 -050087 mStatusBarStateController =
88 mDependency.injectMockDependency(StatusBarStateController.class);
Jason Monk8c09ac72017-03-16 11:53:40 -040089 mHost = mock(QSTileHost.class);
90 when(mHost.indexOf(spec)).thenReturn(POSITION);
Rohan Shahdb2cfa32018-02-20 11:27:22 -080091 when(mHost.getContext()).thenReturn(mContext.getBaseContext());
Jason Monk1c6116c2017-09-06 17:33:01 -040092
93 mTile = spy(new TileImpl(mHost));
94 mTile.mHandler = mTile.new H(mTestableLooper.getLooper());
95 mTile.setTileSpec(spec);
Jason Monk8c09ac72017-03-16 11:53:40 -040096 }
97
98 @Test
99 public void testClick_Metrics() {
100 mTile.click();
101 verify(mMetricsLogger).write(argThat(new TileLogMatcher(ACTION_QS_CLICK)));
102 }
103
104 @Test
Susi Kharraz-Post9b033672018-11-28 08:14:07 -0500105 public void testClick_Metrics_Status_Bar_Status() {
106 when(mStatusBarStateController.getState()).thenReturn(StatusBarState.SHADE);
107 mTile.click();
108 verify(mMetricsLogger).write(mLogCaptor.capture());
109 assertEquals(StatusBarState.SHADE, mLogCaptor.getValue()
110 .getTaggedData(FIELD_STATUS_BAR_STATE));
111 }
112
113 @Test
Jason Monk8c09ac72017-03-16 11:53:40 -0400114 public void testSecondaryClick_Metrics() {
115 mTile.secondaryClick();
116 verify(mMetricsLogger).write(argThat(new TileLogMatcher(ACTION_QS_SECONDARY_CLICK)));
117 }
118
119 @Test
Susi Kharraz-Post9b033672018-11-28 08:14:07 -0500120 public void testSecondaryClick_Metrics_Status_Bar_Status() {
121 when(mStatusBarStateController.getState()).thenReturn(StatusBarState.KEYGUARD);
122 mTile.secondaryClick();
123 verify(mMetricsLogger).write(mLogCaptor.capture());
124 assertEquals(StatusBarState.KEYGUARD, mLogCaptor.getValue()
125 .getTaggedData(FIELD_STATUS_BAR_STATE));
126 }
127
128 @Test
Jason Monk8c09ac72017-03-16 11:53:40 -0400129 public void testLongClick_Metrics() {
130 mTile.longClick();
131 verify(mMetricsLogger).write(argThat(new TileLogMatcher(ACTION_QS_LONG_PRESS)));
132 }
133
134 @Test
Susi Kharraz-Post9b033672018-11-28 08:14:07 -0500135 public void testLongClick_Metrics_Status_Bar_Status() {
136 when(mStatusBarStateController.getState()).thenReturn(StatusBarState.SHADE_LOCKED);
137 mTile.click();
138 verify(mMetricsLogger).write(mLogCaptor.capture());
139 assertEquals(StatusBarState.SHADE_LOCKED, mLogCaptor.getValue()
140 .getTaggedData(FIELD_STATUS_BAR_STATE));
141 }
142
143 @Test
144 public void testPopulateWithLockedScreen() {
145 LogMaker maker = mock(LogMaker.class);
146 when(maker.setSubtype(anyInt())).thenReturn(maker);
147 when(maker.addTaggedData(anyInt(), any())).thenReturn(maker);
148 mTile.getState().value = true;
149 mTile.populate(maker);
150 verify(maker).addTaggedData(eq(FIELD_QS_VALUE), eq(1));
151 verify(maker).addTaggedData(eq(FIELD_QS_POSITION), eq(POSITION));
152 }
153
154 @Test
155 public void testPopulateWithUnlockedScreen() {
Jason Monk8c09ac72017-03-16 11:53:40 -0400156 LogMaker maker = mock(LogMaker.class);
157 when(maker.setSubtype(anyInt())).thenReturn(maker);
Jason Monk2ef8ed62017-09-07 14:51:41 -0400158 when(maker.addTaggedData(anyInt(), any())).thenReturn(maker);
Jason Monk8c09ac72017-03-16 11:53:40 -0400159 mTile.getState().value = true;
160 mTile.populate(maker);
161 verify(maker).addTaggedData(eq(FIELD_QS_VALUE), eq(1));
162 verify(maker).addTaggedData(eq(FIELD_QS_POSITION), eq(POSITION));
163 }
164
Jason Monk1c6116c2017-09-06 17:33:01 -0400165 @Test
Geoffrey Pitsch659a91b2017-11-28 13:33:13 -0500166 @Ignore("flaky")
Jason Monk1c6116c2017-09-06 17:33:01 -0400167 public void testStaleTimeout() throws InterruptedException {
168 when(mTile.getStaleTimeout()).thenReturn(5l);
169 clearInvocations(mTile);
170
171 mTile.handleRefreshState(null);
172 mTestableLooper.processAllMessages();
173 verify(mTile, never()).handleStale();
174
175 sleep(10);
176 mTestableLooper.processAllMessages();
177 verify(mTile).handleStale();
178 }
179
180 @Test
181 public void testStaleListening() {
182 mTile.handleStale();
183 mTestableLooper.processAllMessages();
184 verify(mTile).handleSetListening(eq(true));
185
186 mTile.handleRefreshState(null);
187 mTestableLooper.processAllMessages();
188 verify(mTile).handleSetListening(eq(false));
189 }
190
Jason Monk8c09ac72017-03-16 11:53:40 -0400191 private class TileLogMatcher implements ArgumentMatcher<LogMaker> {
192
193 private final int mCategory;
194 public String mInvalid;
195
196 public TileLogMatcher(int category) {
197 mCategory = category;
198 }
199
200 @Override
201 public boolean matches(LogMaker arg) {
202 if (arg.getCategory() != mCategory) {
203 mInvalid = "Expected category " + mCategory + " but was " + arg.getCategory();
204 return false;
205 }
206 if (arg.getType() != TYPE_ACTION) {
207 mInvalid = "Expected type " + TYPE_ACTION + " but was " + arg.getType();
208 return false;
209 }
210 if (arg.getSubtype() != mTile.getMetricsCategory()) {
211 mInvalid = "Expected subtype " + mTile.getMetricsCategory() + " but was "
212 + arg.getSubtype();
213 return false;
214 }
215 return true;
216 }
217
218 @Override
219 public String toString() {
220 return mInvalid;
221 }
222 }
223
224 private static class TileImpl extends QSTileImpl<QSTile.BooleanState> {
225 protected TileImpl(QSHost host) {
226 super(host);
227 }
228
229 @Override
230 public BooleanState newTileState() {
231 return new BooleanState();
232 }
233
234 @Override
235 protected void handleClick() {
236
237 }
238
239 @Override
240 protected void handleUpdateState(BooleanState state, Object arg) {
241
242 }
243
244 @Override
245 public int getMetricsCategory() {
246 return 42;
247 }
248
249 @Override
250 public Intent getLongClickIntent() {
251 return null;
252 }
253
254 @Override
Jason Monk1c6116c2017-09-06 17:33:01 -0400255 protected void handleSetListening(boolean listening) {
Jason Monk8c09ac72017-03-16 11:53:40 -0400256
257 }
258
259 @Override
260 public CharSequence getTileLabel() {
261 return null;
262 }
263 }
264}