blob: 77520140b1a3b74fcc94e1255db70adbd6db4cfb [file] [log] [blame]
Fabian Kozynski7f370dd2018-12-05 10:41:07 -05001/*
2 * Copyright (C) 2018 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
17package com.android.systemui.qs;
18
19
Fabian Kozynski00d494d2019-04-04 09:53:50 -040020import static junit.framework.Assert.assertEquals;
Fabian Kozynski6ff5c182019-06-20 14:57:47 -040021import static junit.framework.Assert.assertTrue;
Fabian Kozynski7f370dd2018-12-05 10:41:07 -050022import static junit.framework.TestCase.assertFalse;
23
Fabian Kozynski00d494d2019-04-04 09:53:50 -040024import static org.mockito.ArgumentMatchers.anyString;
25import static org.mockito.Mockito.mock;
26import static org.mockito.Mockito.when;
27
Fabian Kozynski6ff5c182019-06-20 14:57:47 -040028import android.app.ActivityManager;
Fabian Kozynski00d494d2019-04-04 09:53:50 -040029import android.content.Context;
30import android.content.Intent;
31import android.os.Handler;
32import android.os.Looper;
Fabian Kozynski6ff5c182019-06-20 14:57:47 -040033import android.provider.Settings;
Fabian Kozynski7f370dd2018-12-05 10:41:07 -050034import android.testing.AndroidTestingRunner;
Fabian Kozynski00d494d2019-04-04 09:53:50 -040035import android.testing.TestableLooper;
36import android.testing.TestableLooper.RunWithLooper;
Fabian Kozynski7f370dd2018-12-05 10:41:07 -050037
Brett Chabot84151d92019-02-27 15:37:59 -080038import androidx.test.filters.SmallTest;
39
Fabian Kozynski6ff5c182019-06-20 14:57:47 -040040import com.android.internal.util.CollectionUtils;
Fabian Kozynski00d494d2019-04-04 09:53:50 -040041import com.android.systemui.DumpController;
Fabian Kozynski6ff5c182019-06-20 14:57:47 -040042import com.android.systemui.R;
Fabian Kozynski7f370dd2018-12-05 10:41:07 -050043import com.android.systemui.SysuiTestCase;
Fabian Kozynski00d494d2019-04-04 09:53:50 -040044import com.android.systemui.plugins.qs.QSFactory;
45import com.android.systemui.plugins.qs.QSTile;
46import com.android.systemui.qs.tileimpl.QSFactoryImpl;
47import com.android.systemui.qs.tileimpl.QSTileImpl;
48import com.android.systemui.shared.plugins.PluginManager;
49import com.android.systemui.statusbar.phone.AutoTileManager;
50import com.android.systemui.statusbar.phone.StatusBarIconController;
51import com.android.systemui.tuner.TunerService;
Fabian Kozynski7f370dd2018-12-05 10:41:07 -050052
Fabian Kozynski00d494d2019-04-04 09:53:50 -040053import org.junit.Before;
Fabian Kozynski7f370dd2018-12-05 10:41:07 -050054import org.junit.Test;
55import org.junit.runner.RunWith;
Fabian Kozynski00d494d2019-04-04 09:53:50 -040056import org.mockito.Mock;
57import org.mockito.MockitoAnnotations;
Fabian Kozynski7f370dd2018-12-05 10:41:07 -050058
Fabian Kozynski00d494d2019-04-04 09:53:50 -040059import java.io.FileDescriptor;
60import java.io.PrintWriter;
61import java.io.StringWriter;
Fabian Kozynski7f370dd2018-12-05 10:41:07 -050062import java.util.List;
Tadashi G. Takaoka38bb49b2019-10-08 15:00:42 +090063import java.util.Objects;
Fabian Kozynski7f370dd2018-12-05 10:41:07 -050064
Fabian Kozynski00d494d2019-04-04 09:53:50 -040065import javax.inject.Provider;
66
Fabian Kozynski7f370dd2018-12-05 10:41:07 -050067@RunWith(AndroidTestingRunner.class)
68@SmallTest
Fabian Kozynski00d494d2019-04-04 09:53:50 -040069@RunWithLooper
Fabian Kozynski7f370dd2018-12-05 10:41:07 -050070public class QSTileHostTest extends SysuiTestCase {
71
Fabian Kozynski00d494d2019-04-04 09:53:50 -040072 private static String MOCK_STATE_STRING = "MockState";
73
74 @Mock
75 private StatusBarIconController mIconController;
76 @Mock
77 private QSFactoryImpl mDefaultFactory;
78 @Mock
79 private PluginManager mPluginManager;
80 @Mock
81 private TunerService mTunerService;
82 @Mock
83 private Provider<AutoTileManager> mAutoTiles;
84 @Mock
85 private DumpController mDumpController;
86 @Mock
87 private QSTile.State mMockState;
88 private Handler mHandler;
89 private TestableLooper mLooper;
90 private QSTileHost mQSTileHost;
91
92 @Before
93 public void setUp() {
94 MockitoAnnotations.initMocks(this);
95 mLooper = TestableLooper.get(this);
96 mHandler = new Handler(mLooper.getLooper());
97 mQSTileHost = new TestQSTileHost(mContext, mIconController, mDefaultFactory, mHandler,
98 mLooper.getLooper(),
99 mPluginManager, mTunerService, mAutoTiles, mDumpController);
100 setUpTileFactory();
Fabian Kozynski837c1ab2019-09-04 10:35:09 -0400101 Settings.Secure.putStringForUser(mContext.getContentResolver(), QSTileHost.TILES_SETTING,
102 "", ActivityManager.getCurrentUser());
Fabian Kozynski00d494d2019-04-04 09:53:50 -0400103 }
104
105 private void setUpTileFactory() {
106 when(mMockState.toString()).thenReturn(MOCK_STATE_STRING);
107 when(mDefaultFactory.createTile(anyString())).thenAnswer(
108 invocation -> {
109 String spec = invocation.getArgument(0);
110 switch (spec) {
111 case "spec1":
112 return new TestTile1(mQSTileHost);
113 case "spec2":
114 return new TestTile2(mQSTileHost);
115 default:
116 return null;
117 }
118 });
Fabian Kozynski00d494d2019-04-04 09:53:50 -0400119 }
120
Fabian Kozynski7f370dd2018-12-05 10:41:07 -0500121 @Test
122 public void testLoadTileSpecs_emptySetting() {
123 List<String> tiles = QSTileHost.loadTileSpecs(mContext, "");
124 assertFalse(tiles.isEmpty());
125 }
126
127 @Test
128 public void testLoadTileSpecs_nullSetting() {
129 List<String> tiles = QSTileHost.loadTileSpecs(mContext, null);
130 assertFalse(tiles.isEmpty());
131 }
Fabian Kozynski00d494d2019-04-04 09:53:50 -0400132
133 @Test
Fabian Kozynski6ff5c182019-06-20 14:57:47 -0400134 public void testInvalidSpecUsesDefault() {
135 mContext.getOrCreateTestableResources()
136 .addOverride(R.string.quick_settings_tiles, "spec1,spec2");
137 mQSTileHost.onTuningChanged(QSTileHost.TILES_SETTING, "not-valid");
138
139 assertEquals(2, mQSTileHost.getTiles().size());
140 }
141
142 @Test
143 public void testSpecWithInvalidDoesNotUseDefault() {
144 mContext.getOrCreateTestableResources()
145 .addOverride(R.string.quick_settings_tiles, "spec1,spec2");
146 mQSTileHost.onTuningChanged(QSTileHost.TILES_SETTING, "spec2,not-valid");
147
148 assertEquals(1, mQSTileHost.getTiles().size());
149 QSTile element = CollectionUtils.firstOrNull(mQSTileHost.getTiles());
150 assertTrue(element instanceof TestTile2);
151 }
152
153 @Test
Fabian Kozynski00d494d2019-04-04 09:53:50 -0400154 public void testDump() {
155 mQSTileHost.onTuningChanged(QSTileHost.TILES_SETTING, "spec1,spec2");
156 StringWriter w = new StringWriter();
157 PrintWriter pw = new PrintWriter(w);
158 mQSTileHost.dump(mock(FileDescriptor.class), pw, new String[]{});
159 String output = "QSTileHost:\n"
160 + TestTile1.class.getSimpleName() + ":\n"
161 + " " + MOCK_STATE_STRING + "\n"
162 + TestTile2.class.getSimpleName() + ":\n"
163 + " " + MOCK_STATE_STRING + "\n";
164 assertEquals(output, w.getBuffer().toString());
165 }
166
167 private static class TestQSTileHost extends QSTileHost {
168 TestQSTileHost(Context context, StatusBarIconController iconController,
169 QSFactoryImpl defaultFactory, Handler mainHandler, Looper bgLooper,
170 PluginManager pluginManager, TunerService tunerService,
171 Provider<AutoTileManager> autoTiles, DumpController dumpController) {
172 super(context, iconController, defaultFactory, mainHandler, bgLooper, pluginManager,
173 tunerService, autoTiles, dumpController);
174 }
175
176 @Override
177 public void onPluginConnected(QSFactory plugin, Context pluginContext) {
178 }
179
180 @Override
181 public void onPluginDisconnected(QSFactory plugin) {
182 }
Fabian Kozynski6ff5c182019-06-20 14:57:47 -0400183
184 @Override
185 public void changeTiles(List<String> previousTiles, List<String> newTiles) {
186 String previousSetting = Settings.Secure.getStringForUser(
187 getContext().getContentResolver(), TILES_SETTING,
188 ActivityManager.getCurrentUser());
189 super.changeTiles(previousTiles, newTiles);
190 // After tiles are changed, make sure to call onTuningChanged with the new setting if it
191 // changed
192 String newSetting = Settings.Secure.getStringForUser(getContext().getContentResolver(),
193 TILES_SETTING, ActivityManager.getCurrentUser());
Tadashi G. Takaoka38bb49b2019-10-08 15:00:42 +0900194 if (!Objects.equals(newSetting, previousSetting)) {
Fabian Kozynski6ff5c182019-06-20 14:57:47 -0400195 onTuningChanged(TILES_SETTING, newSetting);
196 }
197 }
Fabian Kozynski00d494d2019-04-04 09:53:50 -0400198 }
199
200 private class TestTile extends QSTileImpl<QSTile.State> {
201
202 protected TestTile(QSHost host) {
203 super(host);
204 }
205
206 @Override
207 public State newTileState() {
208 return mMockState;
209 }
210
211 @Override
212 public State getState() {
213 return mMockState;
214 }
215
216 @Override
217 protected void handleClick() {}
218
219 @Override
220 protected void handleUpdateState(State state, Object arg) {}
221
222 @Override
223 public int getMetricsCategory() {
224 return 0;
225 }
226
227 @Override
228 public Intent getLongClickIntent() {
229 return null;
230 }
231
232 @Override
233 protected void handleSetListening(boolean listening) {}
234
235 @Override
236 public CharSequence getTileLabel() {
237 return null;
238 }
239 }
240
241 private class TestTile1 extends TestTile {
242
243 protected TestTile1(QSHost host) {
244 super(host);
245 }
246 }
247
248 private class TestTile2 extends TestTile {
249
250 protected TestTile2(QSHost host) {
251 super(host);
252 }
253 }
Fabian Kozynski7f370dd2018-12-05 10:41:07 -0500254}