Fabian Kozynski | 7f370dd | 2018-12-05 10:41:07 -0500 | [diff] [blame] | 1 | /* |
| 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 | |
| 17 | package com.android.systemui.qs; |
| 18 | |
| 19 | |
Fabian Kozynski | 00d494d | 2019-04-04 09:53:50 -0400 | [diff] [blame] | 20 | import static junit.framework.Assert.assertEquals; |
Fabian Kozynski | 6ff5c18 | 2019-06-20 14:57:47 -0400 | [diff] [blame] | 21 | import static junit.framework.Assert.assertTrue; |
Fabian Kozynski | 7f370dd | 2018-12-05 10:41:07 -0500 | [diff] [blame] | 22 | import static junit.framework.TestCase.assertFalse; |
| 23 | |
Fabian Kozynski | 00d494d | 2019-04-04 09:53:50 -0400 | [diff] [blame] | 24 | import static org.mockito.ArgumentMatchers.anyString; |
| 25 | import static org.mockito.Mockito.mock; |
| 26 | import static org.mockito.Mockito.when; |
| 27 | |
Fabian Kozynski | 6ff5c18 | 2019-06-20 14:57:47 -0400 | [diff] [blame] | 28 | import android.app.ActivityManager; |
Fabian Kozynski | 00d494d | 2019-04-04 09:53:50 -0400 | [diff] [blame] | 29 | import android.content.Context; |
| 30 | import android.content.Intent; |
| 31 | import android.os.Handler; |
| 32 | import android.os.Looper; |
Fabian Kozynski | 6ff5c18 | 2019-06-20 14:57:47 -0400 | [diff] [blame] | 33 | import android.provider.Settings; |
Fabian Kozynski | 7f370dd | 2018-12-05 10:41:07 -0500 | [diff] [blame] | 34 | import android.testing.AndroidTestingRunner; |
Fabian Kozynski | 00d494d | 2019-04-04 09:53:50 -0400 | [diff] [blame] | 35 | import android.testing.TestableLooper; |
| 36 | import android.testing.TestableLooper.RunWithLooper; |
Fabian Kozynski | 7f370dd | 2018-12-05 10:41:07 -0500 | [diff] [blame] | 37 | |
Brett Chabot | 84151d9 | 2019-02-27 15:37:59 -0800 | [diff] [blame] | 38 | import androidx.test.filters.SmallTest; |
| 39 | |
Fabian Kozynski | 6ff5c18 | 2019-06-20 14:57:47 -0400 | [diff] [blame] | 40 | import com.android.internal.util.CollectionUtils; |
Fabian Kozynski | 00d494d | 2019-04-04 09:53:50 -0400 | [diff] [blame] | 41 | import com.android.systemui.DumpController; |
Fabian Kozynski | 6ff5c18 | 2019-06-20 14:57:47 -0400 | [diff] [blame] | 42 | import com.android.systemui.R; |
Fabian Kozynski | 7f370dd | 2018-12-05 10:41:07 -0500 | [diff] [blame] | 43 | import com.android.systemui.SysuiTestCase; |
Fabian Kozynski | 00d494d | 2019-04-04 09:53:50 -0400 | [diff] [blame] | 44 | import com.android.systemui.plugins.qs.QSFactory; |
| 45 | import com.android.systemui.plugins.qs.QSTile; |
| 46 | import com.android.systemui.qs.tileimpl.QSFactoryImpl; |
| 47 | import com.android.systemui.qs.tileimpl.QSTileImpl; |
| 48 | import com.android.systemui.shared.plugins.PluginManager; |
| 49 | import com.android.systemui.statusbar.phone.AutoTileManager; |
| 50 | import com.android.systemui.statusbar.phone.StatusBarIconController; |
| 51 | import com.android.systemui.tuner.TunerService; |
Fabian Kozynski | 7f370dd | 2018-12-05 10:41:07 -0500 | [diff] [blame] | 52 | |
Fabian Kozynski | 00d494d | 2019-04-04 09:53:50 -0400 | [diff] [blame] | 53 | import org.junit.Before; |
Fabian Kozynski | 7f370dd | 2018-12-05 10:41:07 -0500 | [diff] [blame] | 54 | import org.junit.Test; |
| 55 | import org.junit.runner.RunWith; |
Fabian Kozynski | 00d494d | 2019-04-04 09:53:50 -0400 | [diff] [blame] | 56 | import org.mockito.Mock; |
| 57 | import org.mockito.MockitoAnnotations; |
Fabian Kozynski | 7f370dd | 2018-12-05 10:41:07 -0500 | [diff] [blame] | 58 | |
Fabian Kozynski | 00d494d | 2019-04-04 09:53:50 -0400 | [diff] [blame] | 59 | import java.io.FileDescriptor; |
| 60 | import java.io.PrintWriter; |
| 61 | import java.io.StringWriter; |
Fabian Kozynski | 7f370dd | 2018-12-05 10:41:07 -0500 | [diff] [blame] | 62 | import java.util.List; |
Tadashi G. Takaoka | 38bb49b | 2019-10-08 15:00:42 +0900 | [diff] [blame] | 63 | import java.util.Objects; |
Fabian Kozynski | 7f370dd | 2018-12-05 10:41:07 -0500 | [diff] [blame] | 64 | |
Fabian Kozynski | 00d494d | 2019-04-04 09:53:50 -0400 | [diff] [blame] | 65 | import javax.inject.Provider; |
| 66 | |
Fabian Kozynski | 7f370dd | 2018-12-05 10:41:07 -0500 | [diff] [blame] | 67 | @RunWith(AndroidTestingRunner.class) |
| 68 | @SmallTest |
Fabian Kozynski | 00d494d | 2019-04-04 09:53:50 -0400 | [diff] [blame] | 69 | @RunWithLooper |
Fabian Kozynski | 7f370dd | 2018-12-05 10:41:07 -0500 | [diff] [blame] | 70 | public class QSTileHostTest extends SysuiTestCase { |
| 71 | |
Fabian Kozynski | 00d494d | 2019-04-04 09:53:50 -0400 | [diff] [blame] | 72 | 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 Kozynski | 837c1ab | 2019-09-04 10:35:09 -0400 | [diff] [blame] | 101 | Settings.Secure.putStringForUser(mContext.getContentResolver(), QSTileHost.TILES_SETTING, |
| 102 | "", ActivityManager.getCurrentUser()); |
Fabian Kozynski | 00d494d | 2019-04-04 09:53:50 -0400 | [diff] [blame] | 103 | } |
| 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 Kozynski | 00d494d | 2019-04-04 09:53:50 -0400 | [diff] [blame] | 119 | } |
| 120 | |
Fabian Kozynski | 7f370dd | 2018-12-05 10:41:07 -0500 | [diff] [blame] | 121 | @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 Kozynski | 00d494d | 2019-04-04 09:53:50 -0400 | [diff] [blame] | 132 | |
| 133 | @Test |
Fabian Kozynski | 6ff5c18 | 2019-06-20 14:57:47 -0400 | [diff] [blame] | 134 | 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 Kozynski | 00d494d | 2019-04-04 09:53:50 -0400 | [diff] [blame] | 154 | 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 Kozynski | 6ff5c18 | 2019-06-20 14:57:47 -0400 | [diff] [blame] | 183 | |
| 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. Takaoka | 38bb49b | 2019-10-08 15:00:42 +0900 | [diff] [blame] | 194 | if (!Objects.equals(newSetting, previousSetting)) { |
Fabian Kozynski | 6ff5c18 | 2019-06-20 14:57:47 -0400 | [diff] [blame] | 195 | onTuningChanged(TILES_SETTING, newSetting); |
| 196 | } |
| 197 | } |
Fabian Kozynski | 00d494d | 2019-04-04 09:53:50 -0400 | [diff] [blame] | 198 | } |
| 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 Kozynski | 7f370dd | 2018-12-05 10:41:07 -0500 | [diff] [blame] | 254 | } |