blob: 9e226f69362234a362b42c719753c0910503ce14 [file] [log] [blame]
Evan Laird6b284732017-02-28 17:27:04 -05001/*
2 * Copyright (C) 2016 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.customize;
16
Fabian Kozynski7753f3e2019-03-01 13:56:26 -050017import static junit.framework.Assert.assertEquals;
Amin Shaikhc5b1bc82018-03-21 08:13:47 -040018import static junit.framework.Assert.assertTrue;
Evan Laird6b284732017-02-28 17:27:04 -050019
Fabian Kozynskibb3ff872018-11-16 14:51:44 -050020import static org.hamcrest.Matchers.equalTo;
21import static org.hamcrest.Matchers.is;
Amin Shaikhc5b1bc82018-03-21 08:13:47 -040022import static org.junit.Assert.assertFalse;
Fabian Kozynskibb3ff872018-11-16 14:51:44 -050023import static org.junit.Assert.assertThat;
Fabian Kozynski7753f3e2019-03-01 13:56:26 -050024import static org.mockito.ArgumentMatchers.anyInt;
Fabian Kozynskibb3ff872018-11-16 14:51:44 -050025import static org.mockito.ArgumentMatchers.anyString;
Amin Shaikhc5b1bc82018-03-21 08:13:47 -040026import static org.mockito.Mockito.any;
Fabian Kozynskibb3ff872018-11-16 14:51:44 -050027import static org.mockito.Mockito.atLeastOnce;
Amin Shaikhc5b1bc82018-03-21 08:13:47 -040028import static org.mockito.Mockito.doAnswer;
Fabian Kozynskibb3ff872018-11-16 14:51:44 -050029import static org.mockito.Mockito.mock;
Amin Shaikhc5b1bc82018-03-21 08:13:47 -040030import static org.mockito.Mockito.times;
31import static org.mockito.Mockito.verify;
Fabian Kozynskibb3ff872018-11-16 14:51:44 -050032import static org.mockito.Mockito.when;
Amin Shaikhc5b1bc82018-03-21 08:13:47 -040033
Fabian Kozynski7753f3e2019-03-01 13:56:26 -050034import android.Manifest;
35import android.content.pm.ApplicationInfo;
Fabian Kozynskibb3ff872018-11-16 14:51:44 -050036import android.content.pm.PackageManager;
Fabian Kozynski7753f3e2019-03-01 13:56:26 -050037import android.content.pm.ResolveInfo;
38import android.content.pm.ServiceInfo;
Fabian Kozynskibb3ff872018-11-16 14:51:44 -050039import android.provider.Settings;
Fabian Kozynski7753f3e2019-03-01 13:56:26 -050040import android.service.quicksettings.Tile;
Jason Monk340b0e52017-03-08 14:57:56 -050041import android.testing.AndroidTestingRunner;
Jason Monk340b0e52017-03-08 14:57:56 -050042import android.testing.TestableLooper;
43import android.testing.TestableLooper.RunWithLooper;
Fabian Kozynskibb3ff872018-11-16 14:51:44 -050044import android.text.TextUtils;
45import android.util.ArraySet;
Jason Monke5b770e2017-03-03 21:49:29 -050046
Brett Chabot84151d92019-02-27 15:37:59 -080047import androidx.test.filters.SmallTest;
48
Amin Shaikhc5b1bc82018-03-21 08:13:47 -040049import com.android.systemui.Dependency;
Fabian Kozynskibb3ff872018-11-16 14:51:44 -050050import com.android.systemui.R;
Amin Shaikhc5b1bc82018-03-21 08:13:47 -040051import com.android.systemui.SysuiTestCase;
Fabian Kozynskibb3ff872018-11-16 14:51:44 -050052import com.android.systemui.plugins.qs.QSTile;
Amin Shaikhc5b1bc82018-03-21 08:13:47 -040053import com.android.systemui.qs.QSTileHost;
54
Evan Laird6b284732017-02-28 17:27:04 -050055import org.junit.Before;
56import org.junit.Test;
57import org.junit.runner.RunWith;
Fabian Kozynski7753f3e2019-03-01 13:56:26 -050058import org.mockito.Answers;
Fabian Kozynskibb3ff872018-11-16 14:51:44 -050059import org.mockito.ArgumentCaptor;
Fabian Kozynski7753f3e2019-03-01 13:56:26 -050060import org.mockito.Captor;
Amin Shaikhc5b1bc82018-03-21 08:13:47 -040061import org.mockito.Mock;
62import org.mockito.MockitoAnnotations;
Evan Laird6b284732017-02-28 17:27:04 -050063
Amin Shaikhc5b1bc82018-03-21 08:13:47 -040064import java.util.ArrayList;
Fabian Kozynskibb3ff872018-11-16 14:51:44 -050065import java.util.Arrays;
66import java.util.List;
67import java.util.Set;
Jason Monke5b770e2017-03-03 21:49:29 -050068
Evan Laird6b284732017-02-28 17:27:04 -050069@SmallTest
Jason Monk340b0e52017-03-08 14:57:56 -050070@RunWith(AndroidTestingRunner.class)
Evan Laird6b284732017-02-28 17:27:04 -050071@RunWithLooper
72public class TileQueryHelperTest extends SysuiTestCase {
Fabian Kozynskibb3ff872018-11-16 14:51:44 -050073 private static final String CURRENT_TILES = "wifi,dnd,nfc";
74 private static final String ONLY_STOCK_TILES = "wifi,dnd";
75 private static final String WITH_OTHER_TILES = "wifi,dnd,other";
76 // Note no nfc in stock tiles
77 private static final String STOCK_TILES = "wifi,dnd,cell,battery";
78 private static final String ALL_TILES = "wifi,dnd,nfc,cell,battery";
79 private static final Set<String> FACTORY_TILES = new ArraySet<>();
Fabian Kozynski7753f3e2019-03-01 13:56:26 -050080 private static final String TEST_PKG = "test_pkg";
81 private static final String TEST_CLS = "test_cls";
Amin Shaikhc5b1bc82018-03-21 08:13:47 -040082
Fabian Kozynskibb3ff872018-11-16 14:51:44 -050083 static {
84 FACTORY_TILES.addAll(Arrays.asList(
85 new String[]{"wifi", "bt", "cell", "dnd", "inversion", "airplane", "work",
86 "rotation", "flashlight", "location", "cast", "hotspot", "user", "battery",
87 "saver", "night", "nfc"}));
88 }
89
90 @Mock
91 private TileQueryHelper.TileStateListener mListener;
92 @Mock
93 private QSTileHost mQSTileHost;
94 @Mock
95 private PackageManager mPackageManager;
Fabian Kozynski7753f3e2019-03-01 13:56:26 -050096 @Captor
97 private ArgumentCaptor<List<TileQueryHelper.TileInfo>> mCaptor;
Fabian Kozynskibb3ff872018-11-16 14:51:44 -050098
99 private QSTile.State mState;
Evan Laird6b284732017-02-28 17:27:04 -0500100 private TestableLooper mBGLooper;
Amin Shaikhc5b1bc82018-03-21 08:13:47 -0400101 private TileQueryHelper mTileQueryHelper;
Evan Laird6b284732017-02-28 17:27:04 -0500102
103 @Before
104 public void setup() {
Amin Shaikhc5b1bc82018-03-21 08:13:47 -0400105 MockitoAnnotations.initMocks(this);
Evan Laird6b284732017-02-28 17:27:04 -0500106 mBGLooper = TestableLooper.get(this);
Jason Monk340b0e52017-03-08 14:57:56 -0500107 mDependency.injectTestDependency(Dependency.BG_LOOPER, mBGLooper.getLooper());
Fabian Kozynskibb3ff872018-11-16 14:51:44 -0500108 mContext.setMockPackageManager(mPackageManager);
109
110 mState = new QSTile.State();
111 doAnswer(invocation -> {
112 String spec = (String) invocation.getArguments()[0];
113 if (FACTORY_TILES.contains(spec)) {
114 QSTile m = mock(QSTile.class);
115 when(m.isAvailable()).thenReturn(true);
116 when(m.getTileSpec()).thenReturn(spec);
117 when(m.getState()).thenReturn(mState);
118 return m;
119 } else {
120 return null;
121 }
122 }
123 ).when(mQSTileHost).createTile(anyString());
124
Amin Shaikhc5b1bc82018-03-21 08:13:47 -0400125 mTileQueryHelper = new TileQueryHelper(mContext, mListener);
Evan Laird6b284732017-02-28 17:27:04 -0500126 }
127
128 @Test
Amin Shaikhc5b1bc82018-03-21 08:13:47 -0400129 public void testIsFinished_falseBeforeQuerying() {
130 assertFalse(mTileQueryHelper.isFinished());
Evan Laird6b284732017-02-28 17:27:04 -0500131 }
132
133 @Test
Amin Shaikhc5b1bc82018-03-21 08:13:47 -0400134 public void testIsFinished_trueAfterQuerying() {
135 mTileQueryHelper.queryTiles(mQSTileHost);
Evan Laird6b284732017-02-28 17:27:04 -0500136
Evan Laird6b284732017-02-28 17:27:04 -0500137 mBGLooper.processAllMessages();
Amin Shaikhc5b1bc82018-03-21 08:13:47 -0400138 waitForIdleSync(Dependency.get(Dependency.MAIN_HANDLER));
139
140 assertTrue(mTileQueryHelper.isFinished());
141 }
142
143 @Test
144 public void testQueryTiles_callsListenerTwice() {
145 mTileQueryHelper.queryTiles(mQSTileHost);
146
147 mBGLooper.processAllMessages();
148 waitForIdleSync(Dependency.get(Dependency.MAIN_HANDLER));
149
150 verify(mListener, times(2)).onTilesChanged(any());
151 }
152
153 @Test
154 public void testQueryTiles_isFinishedFalseOnListenerCalls_thenTrueAfterCompletion() {
155 doAnswer(invocation -> {
156 assertFalse(mTileQueryHelper.isFinished());
157 return null;
158 }).when(mListener).onTilesChanged(any());
159
160 mTileQueryHelper.queryTiles(mQSTileHost);
161
162 mBGLooper.processAllMessages();
163 waitForIdleSync(Dependency.get(Dependency.MAIN_HANDLER));
164
165 assertTrue(mTileQueryHelper.isFinished());
Evan Laird6b284732017-02-28 17:27:04 -0500166 }
Fabian Kozynskibb3ff872018-11-16 14:51:44 -0500167
168 @Test
169 public void testQueryTiles_correctTilesAndOrderOnlyStockTiles() {
Fabian Kozynskibb3ff872018-11-16 14:51:44 -0500170 Settings.Secure.putString(mContext.getContentResolver(), Settings.Secure.QS_TILES,
171 ONLY_STOCK_TILES);
172 mContext.getOrCreateTestableResources().addOverride(R.string.quick_settings_tiles_stock,
173 STOCK_TILES);
174
175 mTileQueryHelper.queryTiles(mQSTileHost);
176
177 mBGLooper.processAllMessages();
178 waitForIdleSync(Dependency.get(Dependency.MAIN_HANDLER));
179
Fabian Kozynski7753f3e2019-03-01 13:56:26 -0500180 verify(mListener, atLeastOnce()).onTilesChanged(mCaptor.capture());
Fabian Kozynskibb3ff872018-11-16 14:51:44 -0500181 List<String> specs = new ArrayList<>();
Fabian Kozynski7753f3e2019-03-01 13:56:26 -0500182 for (TileQueryHelper.TileInfo t : mCaptor.getValue()) {
Fabian Kozynskibb3ff872018-11-16 14:51:44 -0500183 specs.add(t.spec);
184 }
185 String tiles = TextUtils.join(",", specs);
186 assertThat(tiles, is(equalTo(STOCK_TILES)));
187 }
188
189 @Test
190 public void testQueryTiles_correctTilesAndOrderOtherFactoryTiles() {
Fabian Kozynskibb3ff872018-11-16 14:51:44 -0500191 Settings.Secure.putString(mContext.getContentResolver(), Settings.Secure.QS_TILES,
192 CURRENT_TILES);
193 mContext.getOrCreateTestableResources().addOverride(R.string.quick_settings_tiles_stock,
194 STOCK_TILES);
195
196 mTileQueryHelper.queryTiles(mQSTileHost);
197
198 mBGLooper.processAllMessages();
199 waitForIdleSync(Dependency.get(Dependency.MAIN_HANDLER));
200
Fabian Kozynski7753f3e2019-03-01 13:56:26 -0500201 verify(mListener, atLeastOnce()).onTilesChanged(mCaptor.capture());
Fabian Kozynskibb3ff872018-11-16 14:51:44 -0500202 List<String> specs = new ArrayList<>();
Fabian Kozynski7753f3e2019-03-01 13:56:26 -0500203 for (TileQueryHelper.TileInfo t : mCaptor.getValue()) {
Fabian Kozynskibb3ff872018-11-16 14:51:44 -0500204 specs.add(t.spec);
205 }
206 String tiles = TextUtils.join(",", specs);
207 assertThat(tiles, is(equalTo(ALL_TILES)));
208 }
209
210 @Test
211 public void testQueryTiles_otherTileNotIncluded() {
Fabian Kozynskibb3ff872018-11-16 14:51:44 -0500212 Settings.Secure.putString(mContext.getContentResolver(), Settings.Secure.QS_TILES,
213 WITH_OTHER_TILES);
214 mContext.getOrCreateTestableResources().addOverride(R.string.quick_settings_tiles_stock,
215 STOCK_TILES);
216
217 mTileQueryHelper.queryTiles(mQSTileHost);
218
219 mBGLooper.processAllMessages();
220 waitForIdleSync(Dependency.get(Dependency.MAIN_HANDLER));
221
Fabian Kozynski7753f3e2019-03-01 13:56:26 -0500222 verify(mListener, atLeastOnce()).onTilesChanged(mCaptor.capture());
Fabian Kozynskibb3ff872018-11-16 14:51:44 -0500223 List<String> specs = new ArrayList<>();
Fabian Kozynski7753f3e2019-03-01 13:56:26 -0500224 for (TileQueryHelper.TileInfo t : mCaptor.getValue()) {
Fabian Kozynskibb3ff872018-11-16 14:51:44 -0500225 specs.add(t.spec);
226 }
227 assertFalse(specs.contains("other"));
228 }
Fabian Kozynski565f2582018-12-19 17:39:53 -0500229
230 @Test
Fabian Kozynski7753f3e2019-03-01 13:56:26 -0500231 public void testThirdPartyTilesInactive() {
232 ResolveInfo resolveInfo = new ResolveInfo();
233 ServiceInfo serviceInfo = mock(ServiceInfo.class, Answers.RETURNS_MOCKS);
234 resolveInfo.serviceInfo = serviceInfo;
235 serviceInfo.packageName = TEST_PKG;
236 serviceInfo.name = TEST_CLS;
237 serviceInfo.icon = R.drawable.android;
238 serviceInfo.permission = Manifest.permission.BIND_QUICK_SETTINGS_TILE;
239 serviceInfo.applicationInfo = mock(ApplicationInfo.class, Answers.RETURNS_MOCKS);
240 serviceInfo.applicationInfo.icon = R.drawable.android;
241 List<ResolveInfo> list = new ArrayList<>();
242 list.add(resolveInfo);
243 when(mPackageManager.queryIntentServicesAsUser(any(), anyInt(), anyInt())).thenReturn(list);
244
245 Settings.Secure.putString(mContext.getContentResolver(), Settings.Secure.QS_TILES, "");
246 mContext.getOrCreateTestableResources().addOverride(R.string.quick_settings_tiles_stock,
247 "");
248
249 mTileQueryHelper.queryTiles(mQSTileHost);
250 mBGLooper.processAllMessages();
251 waitForIdleSync(Dependency.get(Dependency.MAIN_HANDLER));
252
253 verify(mListener, atLeastOnce()).onTilesChanged(mCaptor.capture());
254 List<TileQueryHelper.TileInfo> tileInfos = mCaptor.getValue();
255 assertEquals(1, tileInfos.size());
256 assertEquals(Tile.STATE_INACTIVE, tileInfos.get(0).state.state);
257 }
258
259 @Test
Fabian Kozynski565f2582018-12-19 17:39:53 -0500260 public void testQueryTiles_nullSetting() {
261 Settings.Secure.putString(mContext.getContentResolver(), Settings.Secure.QS_TILES, null);
262 mContext.getOrCreateTestableResources().addOverride(R.string.quick_settings_tiles_stock,
263 STOCK_TILES);
264 mTileQueryHelper.queryTiles(mQSTileHost);
265 }
Evan Laird6b284732017-02-28 17:27:04 -0500266}