Jason Monk | 0b80c4e | 2017-05-01 15:38:34 -0400 | [diff] [blame] | 1 | /* |
| 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 | |
| 15 | package com.android.systemui.statusbar.policy; |
| 16 | |
| 17 | import static org.junit.Assert.assertEquals; |
| 18 | import static org.junit.Assert.assertNull; |
| 19 | import static org.mockito.ArgumentMatchers.any; |
| 20 | import static org.mockito.ArgumentMatchers.eq; |
| 21 | import static org.mockito.Mockito.mock; |
| 22 | import static org.mockito.Mockito.verify; |
| 23 | import static org.mockito.Mockito.when; |
| 24 | |
| 25 | import android.content.res.Configuration; |
| 26 | import android.testing.AndroidTestingRunner; |
| 27 | import android.testing.TestableLooper; |
| 28 | import android.testing.TestableLooper.RunWithLooper; |
Jason Monk | 0b80c4e | 2017-05-01 15:38:34 -0400 | [diff] [blame] | 29 | |
Brett Chabot | 84151d9 | 2019-02-27 15:37:59 -0800 | [diff] [blame] | 30 | import androidx.test.filters.SmallTest; |
| 31 | |
Jason Monk | 0b80c4e | 2017-05-01 15:38:34 -0400 | [diff] [blame] | 32 | import com.android.systemui.SysuiTestCase; |
| 33 | import com.android.systemui.plugins.OverlayPlugin; |
| 34 | import com.android.systemui.plugins.Plugin; |
| 35 | import com.android.systemui.plugins.PluginListener; |
Tony Wickham | 023cb19 | 2018-09-13 15:23:04 -0700 | [diff] [blame] | 36 | import com.android.systemui.shared.plugins.PluginManager; |
Jason Monk | 0b80c4e | 2017-05-01 15:38:34 -0400 | [diff] [blame] | 37 | import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener; |
| 38 | import com.android.systemui.statusbar.policy.ExtensionController.Extension; |
| 39 | import com.android.systemui.statusbar.policy.ExtensionController.TunerFactory; |
| 40 | import com.android.systemui.tuner.TunerService; |
| 41 | import com.android.systemui.tuner.TunerService.Tunable; |
Jason Monk | 7fc1f9b | 2018-12-20 15:12:17 -0500 | [diff] [blame] | 42 | import com.android.systemui.util.leak.LeakDetector; |
Jason Monk | 0b80c4e | 2017-05-01 15:38:34 -0400 | [diff] [blame] | 43 | |
| 44 | import org.junit.Before; |
| 45 | import org.junit.Test; |
| 46 | import org.junit.runner.RunWith; |
| 47 | import org.mockito.ArgumentCaptor; |
| 48 | |
| 49 | import java.util.Map; |
| 50 | import java.util.function.Consumer; |
| 51 | |
| 52 | @RunWith(AndroidTestingRunner.class) |
Jason Monk | fba8faf | 2017-05-23 10:42:59 -0400 | [diff] [blame] | 53 | @SmallTest |
Jason Monk | 0b80c4e | 2017-05-01 15:38:34 -0400 | [diff] [blame] | 54 | public class ExtensionControllerImplTest extends SysuiTestCase { |
| 55 | |
| 56 | private PluginManager mPluginManager; |
| 57 | private TunerService mTunerService; |
| 58 | private ExtensionController mExtensionController; |
| 59 | private ConfigurationController mConfigurationController; |
| 60 | |
| 61 | @Before |
| 62 | public void setup() { |
| 63 | mPluginManager = mDependency.injectMockDependency(PluginManager.class); |
| 64 | mTunerService = mDependency.injectMockDependency(TunerService.class); |
| 65 | mConfigurationController = mDependency.injectMockDependency(ConfigurationController.class); |
Jason Monk | 7fc1f9b | 2018-12-20 15:12:17 -0500 | [diff] [blame] | 66 | mExtensionController = new ExtensionControllerImpl(mContext, |
| 67 | mock(LeakDetector.class), mPluginManager, mTunerService, mConfigurationController); |
Jason Monk | 0b80c4e | 2017-05-01 15:38:34 -0400 | [diff] [blame] | 68 | } |
| 69 | |
| 70 | @Test |
| 71 | public void testPlugin() { |
| 72 | OverlayPlugin plugin = mock(OverlayPlugin.class); |
| 73 | |
| 74 | Extension ext = mExtensionController.newExtension(OverlayPlugin.class) |
| 75 | .withPlugin(OverlayPlugin.class) |
| 76 | .build(); |
| 77 | ArgumentCaptor<PluginListener> listener = ArgumentCaptor.forClass(PluginListener.class); |
| 78 | verify(mPluginManager).addPluginListener(eq(OverlayPlugin.ACTION), listener.capture(), |
| 79 | eq(OverlayPlugin.class)); |
| 80 | |
| 81 | listener.getValue().onPluginConnected(plugin, null); |
| 82 | assertEquals(plugin, ext.get()); |
| 83 | |
| 84 | ext.destroy(); |
| 85 | verify(mPluginManager).removePluginListener(any()); |
| 86 | } |
| 87 | |
| 88 | @Test |
| 89 | public void testTuner() { |
| 90 | String[] keys = new String[] { "key1", "key2" }; |
| 91 | TunerFactory<Object> factory = new ExtensionController.TunerFactory() { |
| 92 | @Override |
| 93 | public String[] keys() { |
| 94 | return keys; |
| 95 | } |
| 96 | |
| 97 | @Override |
| 98 | public Object create(Map settings) { |
| 99 | return null; |
| 100 | } |
| 101 | }; |
| 102 | Extension ext = mExtensionController.newExtension(Object.class) |
| 103 | .withTunerFactory(factory) |
| 104 | .build(); |
| 105 | verify(mTunerService).addTunable(any(), eq(keys[0]), eq(keys[1])); |
| 106 | |
| 107 | ext.destroy(); |
| 108 | verify(mTunerService).removeTunable(any()); |
| 109 | } |
| 110 | |
| 111 | @Test |
| 112 | @RunWithLooper |
| 113 | public void testUiMode() { |
| 114 | Object o = new Object(); |
| 115 | Extension ext = mExtensionController.newExtension(Object.class) |
| 116 | .withUiMode(Configuration.UI_MODE_TYPE_CAR, () -> o) |
| 117 | .build(); |
| 118 | ArgumentCaptor<ConfigurationListener> captor = ArgumentCaptor.forClass( |
| 119 | ConfigurationListener.class); |
| 120 | verify(mConfigurationController).addCallback(captor.capture()); |
| 121 | |
| 122 | Configuration c = new Configuration(mContext.getResources().getConfiguration()); |
| 123 | c.uiMode = 0; |
| 124 | captor.getValue().onConfigChanged(c); |
| 125 | TestableLooper.get(this).processAllMessages(); |
| 126 | assertNull(ext.get()); |
| 127 | |
| 128 | c.uiMode = Configuration.UI_MODE_TYPE_CAR; |
| 129 | captor.getValue().onConfigChanged(c); |
| 130 | TestableLooper.get(this).processAllMessages(); |
| 131 | assertEquals(o, ext.get()); |
| 132 | |
| 133 | ext.destroy(); |
| 134 | verify(mConfigurationController).removeCallback(eq(captor.getValue())); |
| 135 | } |
| 136 | |
| 137 | @Test |
| 138 | public void testDefault() { |
| 139 | Object o = new Object(); |
| 140 | Extension ext = mExtensionController.newExtension(Object.class) |
| 141 | .withDefault(() -> o) |
| 142 | .build(); |
| 143 | assertEquals(o, ext.get()); |
| 144 | } |
| 145 | |
| 146 | @Test |
| 147 | @RunWithLooper |
| 148 | public void testSortOrder() { |
Jason Monk | 0b80c4e | 2017-05-01 15:38:34 -0400 | [diff] [blame] | 149 | Object def = new Object(); |
| 150 | Object uiMode = new Object(); |
| 151 | Object tuner = new Object(); |
| 152 | Plugin plugin = mock(Plugin.class); |
| 153 | TunerFactory<Object> factory = mock(TunerFactory.class); |
| 154 | Extension ext = mExtensionController.newExtension(Object.class) |
| 155 | .withDefault(() -> def) |
| 156 | .withUiMode(Configuration.UI_MODE_TYPE_CAR, () -> uiMode) |
| 157 | .withTunerFactory(factory) |
| 158 | .withPlugin(Object.class, "some_action") |
| 159 | .build(); |
| 160 | |
| 161 | // Test default first. |
| 162 | assertEquals(def, ext.get()); |
| 163 | |
| 164 | // Enable a UI mode and check that. |
| 165 | ArgumentCaptor<ConfigurationListener> captor = ArgumentCaptor.forClass( |
| 166 | ConfigurationListener.class); |
| 167 | verify(mConfigurationController).addCallback(captor.capture()); |
| 168 | Configuration c = new Configuration(mContext.getResources().getConfiguration()); |
| 169 | c.uiMode |= Configuration.UI_MODE_TYPE_CAR; |
| 170 | captor.getValue().onConfigChanged(c); |
| 171 | TestableLooper.get(this).processAllMessages(); |
| 172 | assertEquals(uiMode, ext.get()); |
| 173 | |
| 174 | // Turn on tuner item and check that. |
| 175 | when(factory.create(any())).thenReturn(tuner); |
| 176 | ArgumentCaptor<Tunable> tunable = ArgumentCaptor.forClass(Tunable.class); |
| 177 | verify(mTunerService).addTunable(tunable.capture(), any()); |
| 178 | tunable.getValue().onTuningChanged(null, null); |
| 179 | assertEquals(tuner, ext.get()); |
| 180 | |
| 181 | // Lastly, check a plugin. |
| 182 | ArgumentCaptor<PluginListener> listener = ArgumentCaptor.forClass(PluginListener.class); |
| 183 | verify(mPluginManager).addPluginListener(any(), listener.capture(), any()); |
| 184 | listener.getValue().onPluginConnected(plugin, null); |
| 185 | assertEquals(plugin, ext.get()); |
| 186 | } |
| 187 | |
| 188 | @Test |
| 189 | public void testCallback() { |
| 190 | Consumer<Object> callback = mock(Consumer.class); |
| 191 | final Object o = new Object(); |
| 192 | mExtensionController.newExtension(Object.class) |
| 193 | .withDefault(() -> o) |
| 194 | .withCallback(callback) |
| 195 | .build(); |
| 196 | verify(callback).accept(eq(o)); |
| 197 | } |
| 198 | |
| 199 | } |