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 package com.android.server.usb; 17 18 import static org.junit.Assert.assertEquals; 19 import static org.junit.Assert.assertFalse; 20 import static org.junit.Assert.assertNotEquals; 21 import static org.junit.Assert.assertTrue; 22 import static org.mockito.ArgumentMatchers.eq; 23 import static org.mockito.Mockito.verify; 24 import static org.mockito.Mockito.when; 25 26 import android.app.ActivityManager; 27 import android.content.ContentResolver; 28 import android.content.Context; 29 import android.content.Intent; 30 import android.content.SharedPreferences; 31 import android.debug.AdbManagerInternal; 32 import android.debug.AdbTransportType; 33 import android.hardware.usb.UsbManager; 34 import android.os.Handler; 35 import android.os.Looper; 36 import android.os.Message; 37 38 import androidx.test.InstrumentationRegistry; 39 import androidx.test.filters.SmallTest; 40 import androidx.test.runner.AndroidJUnit4; 41 42 import com.android.dx.mockito.inline.extended.ExtendedMockito; 43 import com.android.server.FgThread; 44 import com.android.server.LocalServices; 45 46 import org.junit.After; 47 import org.junit.Before; 48 import org.junit.Test; 49 import org.junit.runner.RunWith; 50 import org.mockito.Mock; 51 import org.mockito.MockitoAnnotations; 52 import org.mockito.MockitoSession; 53 import org.mockito.quality.Strictness; 54 55 import java.util.HashMap; 56 import java.util.Locale; 57 import java.util.Map; 58 59 /** 60 * Tests for UsbHandler state changes. 61 */ 62 @RunWith(AndroidJUnit4.class) 63 public class UsbHandlerTest { 64 private static final String TAG = UsbHandlerTest.class.getSimpleName(); 65 66 @Mock 67 private UsbDeviceManager mUsbDeviceManager; 68 @Mock 69 private UsbAlsaManager mUsbAlsaManager; 70 @Mock 71 private UsbSettingsManager mUsbSettingsManager; 72 @Mock 73 private UsbPermissionManager mUsbPermissionManager; 74 @Mock 75 private SharedPreferences mSharedPreferences; 76 @Mock 77 private SharedPreferences.Editor mEditor; 78 @Mock 79 private AdbManagerInternal mAdbManagerInternal; 80 81 private MockUsbHandler mUsbHandler; 82 83 private static final int MSG_UPDATE_STATE = 0; 84 private static final int MSG_ENABLE_ADB = 1; 85 private static final int MSG_SET_CURRENT_FUNCTIONS = 2; 86 private static final int MSG_SYSTEM_READY = 3; 87 private static final int MSG_BOOT_COMPLETED = 4; 88 private static final int MSG_USER_SWITCHED = 5; 89 private static final int MSG_UPDATE_USER_RESTRICTIONS = 6; 90 private static final int MSG_SET_SCREEN_UNLOCKED_FUNCTIONS = 12; 91 private static final int MSG_UPDATE_SCREEN_LOCK = 13; 92 93 private Map<String, String> mMockProperties; 94 private Map<String, Integer> mMockGlobalSettings; 95 private MockitoSession mStaticMockSession; 96 97 private class MockUsbHandler extends UsbDeviceManager.UsbHandler { 98 boolean mIsUsbTransferAllowed; 99 Intent mBroadcastedIntent; 100 MockUsbHandler(Looper looper, Context context, UsbDeviceManager deviceManager, UsbAlsaManager alsaManager, UsbSettingsManager settingsManager, UsbPermissionManager permissionManager)101 MockUsbHandler(Looper looper, Context context, UsbDeviceManager deviceManager, 102 UsbAlsaManager alsaManager, UsbSettingsManager settingsManager, 103 UsbPermissionManager permissionManager) { 104 super(looper, context, deviceManager, alsaManager, permissionManager); 105 mUseUsbNotification = false; 106 mIsUsbTransferAllowed = true; 107 mCurrentUsbFunctionsReceived = true; 108 } 109 110 @Override setEnabledFunctions(long functions, boolean force, int operationId)111 protected void setEnabledFunctions(long functions, boolean force, int operationId) { 112 mCurrentFunctions = functions; 113 } 114 115 @Override setSystemProperty(String property, String value)116 protected void setSystemProperty(String property, String value) { 117 mMockProperties.put(property, value); 118 } 119 120 @Override putGlobalSettings(ContentResolver resolver, String setting, int val)121 protected void putGlobalSettings(ContentResolver resolver, String setting, int val) { 122 mMockGlobalSettings.put(setting, val); 123 } 124 125 @Override getSystemProperty(String property, String def)126 protected String getSystemProperty(String property, String def) { 127 if (mMockProperties.containsKey(property)) { 128 return mMockProperties.get(property); 129 } 130 return def; 131 } 132 133 @Override isUsbTransferAllowed()134 protected boolean isUsbTransferAllowed() { 135 return mIsUsbTransferAllowed; 136 } 137 138 @Override getPinnedSharedPrefs(Context context)139 protected SharedPreferences getPinnedSharedPrefs(Context context) { 140 return mSharedPreferences; 141 } 142 143 @Override sendStickyBroadcast(Intent intent)144 protected void sendStickyBroadcast(Intent intent) { 145 mBroadcastedIntent = intent; 146 } 147 148 @Override handlerInitDone(int operationId)149 public void handlerInitDone(int operationId) { 150 } 151 152 @Override setCurrentUsbFunctionsCb(long functions, int status, int mRequest, long mFunctions, boolean mChargingFunctions)153 public void setCurrentUsbFunctionsCb(long functions, 154 int status, int mRequest, long mFunctions, boolean mChargingFunctions){ 155 } 156 157 @Override getUsbSpeedCb(int speed)158 public void getUsbSpeedCb(int speed){ 159 } 160 161 @Override resetCb(int status)162 public void resetCb(int status){ 163 } 164 165 } 166 167 @Before before()168 public void before() { 169 MockitoAnnotations.initMocks(this); 170 mStaticMockSession = ExtendedMockito.mockitoSession() 171 .mockStatic(LocalServices.class) 172 .strictness(Strictness.WARN) 173 .startMocking(); 174 mMockProperties = new HashMap<>(); 175 mMockGlobalSettings = new HashMap<>(); 176 when(mSharedPreferences.edit()).thenReturn(mEditor); 177 178 mUsbHandler = new MockUsbHandler(FgThread.get().getLooper(), 179 InstrumentationRegistry.getContext(), mUsbDeviceManager, mUsbAlsaManager, 180 mUsbSettingsManager, mUsbPermissionManager); 181 182 when(LocalServices.getService(eq(AdbManagerInternal.class))) 183 .thenReturn(mAdbManagerInternal); 184 } 185 186 @After tearDown()187 public void tearDown() throws Exception { 188 if (mStaticMockSession != null) { 189 mStaticMockSession.finishMocking(); 190 } 191 } 192 193 @SmallTest 194 @Test setFunctionsMtp()195 public void setFunctionsMtp() { 196 mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_SET_CURRENT_FUNCTIONS, 197 UsbManager.FUNCTION_MTP)); 198 assertNotEquals(mUsbHandler.getEnabledFunctions() & UsbManager.FUNCTION_MTP, 0); 199 } 200 201 @SmallTest 202 @Test setFunctionsPtp()203 public void setFunctionsPtp() { 204 mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_SET_CURRENT_FUNCTIONS, 205 UsbManager.FUNCTION_PTP)); 206 assertNotEquals(mUsbHandler.getEnabledFunctions() & UsbManager.FUNCTION_PTP, 0); 207 } 208 209 @SmallTest 210 @Test setFunctionsMidi()211 public void setFunctionsMidi() { 212 mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_SET_CURRENT_FUNCTIONS, 213 UsbManager.FUNCTION_MIDI)); 214 assertNotEquals(mUsbHandler.getEnabledFunctions() & UsbManager.FUNCTION_MIDI, 0); 215 } 216 217 @SmallTest 218 @Test setFunctionsRndis()219 public void setFunctionsRndis() { 220 mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_SET_CURRENT_FUNCTIONS, 221 UsbManager.FUNCTION_RNDIS)); 222 assertNotEquals(mUsbHandler.getEnabledFunctions() & UsbManager.FUNCTION_RNDIS, 0); 223 } 224 225 @SmallTest 226 @Test setFunctionsNcm()227 public void setFunctionsNcm() { 228 mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_SET_CURRENT_FUNCTIONS, 229 UsbManager.FUNCTION_NCM)); 230 assertNotEquals(mUsbHandler.getEnabledFunctions() & UsbManager.FUNCTION_NCM, 0); 231 } 232 233 @SmallTest 234 @Test setFunctionsNcmAndRndis()235 public void setFunctionsNcmAndRndis() { 236 final long rndisPlusNcm = UsbManager.FUNCTION_RNDIS | UsbManager.FUNCTION_NCM; 237 238 mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_SET_CURRENT_FUNCTIONS, 239 UsbManager.FUNCTION_NCM)); 240 assertEquals(UsbManager.FUNCTION_NCM, mUsbHandler.getEnabledFunctions() & rndisPlusNcm); 241 242 mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_SET_CURRENT_FUNCTIONS, 243 rndisPlusNcm)); 244 assertEquals(rndisPlusNcm, mUsbHandler.getEnabledFunctions() & rndisPlusNcm); 245 246 mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_SET_CURRENT_FUNCTIONS, 247 UsbManager.FUNCTION_NCM)); 248 assertEquals(UsbManager.FUNCTION_NCM, mUsbHandler.getEnabledFunctions() & rndisPlusNcm); 249 } 250 251 @SmallTest 252 @Test enableAdb()253 public void enableAdb() { 254 sendBootCompleteMessages(mUsbHandler); 255 Message msg = mUsbHandler.obtainMessage(MSG_ENABLE_ADB); 256 msg.arg1 = 1; 257 mUsbHandler.handleMessage(msg); 258 assertEquals(mUsbHandler.getEnabledFunctions(), UsbManager.FUNCTION_NONE); 259 assertEquals(mMockProperties.get(UsbDeviceManager.UsbHandler 260 .USB_PERSISTENT_CONFIG_PROPERTY), UsbManager.USB_FUNCTION_ADB); 261 262 when(mAdbManagerInternal.isAdbEnabled(eq(AdbTransportType.USB))).thenReturn(true); 263 mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_UPDATE_STATE, 1, 1)); 264 265 assertTrue(mUsbHandler.mBroadcastedIntent.getBooleanExtra(UsbManager.USB_CONNECTED, false)); 266 assertTrue(mUsbHandler.mBroadcastedIntent 267 .getBooleanExtra(UsbManager.USB_CONFIGURED, false)); 268 assertTrue(mUsbHandler.mBroadcastedIntent 269 .getBooleanExtra(UsbManager.USB_FUNCTION_ADB, false)); 270 } 271 272 @SmallTest 273 @Test disableAdb()274 public void disableAdb() { 275 mMockProperties.put(UsbDeviceManager.UsbHandler.USB_PERSISTENT_CONFIG_PROPERTY, 276 UsbManager.USB_FUNCTION_ADB); 277 mUsbHandler = new MockUsbHandler(FgThread.get().getLooper(), 278 InstrumentationRegistry.getContext(), mUsbDeviceManager, mUsbAlsaManager, 279 mUsbSettingsManager, mUsbPermissionManager); 280 281 sendBootCompleteMessages(mUsbHandler); 282 mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_ENABLE_ADB, 0)); 283 assertEquals(mUsbHandler.getEnabledFunctions(), UsbManager.FUNCTION_NONE); 284 assertFalse(mUsbHandler.isAdbEnabled()); 285 assertEquals(mMockProperties.get(UsbDeviceManager.UsbHandler 286 .USB_PERSISTENT_CONFIG_PROPERTY), ""); 287 } 288 289 @SmallTest 290 @Test bootCompletedCharging()291 public void bootCompletedCharging() { 292 sendBootCompleteMessages(mUsbHandler); 293 assertEquals(mUsbHandler.getEnabledFunctions(), UsbManager.FUNCTION_NONE); 294 } 295 296 @SmallTest 297 @Test userSwitchedDisablesMtp()298 public void userSwitchedDisablesMtp() { 299 mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_SET_CURRENT_FUNCTIONS, 300 UsbManager.FUNCTION_MTP)); 301 assertNotEquals(mUsbHandler.getEnabledFunctions() & UsbManager.FUNCTION_MTP, 0); 302 303 Message msg = mUsbHandler.obtainMessage(MSG_USER_SWITCHED); 304 msg.arg1 = ActivityManager.getCurrentUser() + 1; 305 mUsbHandler.handleMessage(msg); 306 assertEquals(mUsbHandler.getEnabledFunctions(), UsbManager.FUNCTION_NONE); 307 } 308 309 @SmallTest 310 @Test changedRestrictionsDisablesMtp()311 public void changedRestrictionsDisablesMtp() { 312 mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_SET_CURRENT_FUNCTIONS, 313 UsbManager.FUNCTION_MTP)); 314 assertNotEquals(mUsbHandler.getEnabledFunctions() & UsbManager.FUNCTION_MTP, 0); 315 316 mUsbHandler.mIsUsbTransferAllowed = false; 317 mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_UPDATE_USER_RESTRICTIONS)); 318 assertEquals(mUsbHandler.getEnabledFunctions(), UsbManager.FUNCTION_NONE); 319 } 320 321 @SmallTest 322 @Test disconnectResetsCharging()323 public void disconnectResetsCharging() { 324 sendBootCompleteMessages(mUsbHandler); 325 326 mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_SET_CURRENT_FUNCTIONS, 327 UsbManager.FUNCTION_MTP)); 328 assertNotEquals(mUsbHandler.getEnabledFunctions() & UsbManager.FUNCTION_MTP, 0); 329 330 mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_UPDATE_STATE, 0, 0)); 331 332 assertEquals(mUsbHandler.getEnabledFunctions(), UsbManager.FUNCTION_NONE); 333 } 334 335 @SmallTest 336 @Test configuredSendsBroadcast()337 public void configuredSendsBroadcast() { 338 sendBootCompleteMessages(mUsbHandler); 339 mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_SET_CURRENT_FUNCTIONS, 340 UsbManager.FUNCTION_MTP)); 341 assertNotEquals(mUsbHandler.getEnabledFunctions() & UsbManager.FUNCTION_MTP, 0); 342 343 mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_UPDATE_STATE, 1, 1)); 344 345 assertNotEquals(mUsbHandler.getEnabledFunctions() & UsbManager.FUNCTION_MTP, 0); 346 assertTrue(mUsbHandler.mBroadcastedIntent.getBooleanExtra(UsbManager.USB_CONNECTED, false)); 347 assertTrue(mUsbHandler.mBroadcastedIntent 348 .getBooleanExtra(UsbManager.USB_CONFIGURED, false)); 349 assertTrue(mUsbHandler.mBroadcastedIntent 350 .getBooleanExtra(UsbManager.USB_FUNCTION_MTP, false)); 351 } 352 353 @SmallTest 354 @Test setScreenUnlockedFunctions()355 public void setScreenUnlockedFunctions() { 356 sendBootCompleteMessages(mUsbHandler); 357 mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_UPDATE_SCREEN_LOCK, 0)); 358 359 mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_SET_SCREEN_UNLOCKED_FUNCTIONS, 360 UsbManager.FUNCTION_MTP)); 361 assertNotEquals(mUsbHandler.getScreenUnlockedFunctions() & UsbManager.FUNCTION_MTP, 0); 362 assertNotEquals(mUsbHandler.getEnabledFunctions() & UsbManager.FUNCTION_MTP, 0); 363 verify(mEditor).putString(String.format(Locale.ENGLISH, 364 UsbDeviceManager.UNLOCKED_CONFIG_PREF, mUsbHandler.mCurrentUser), 365 UsbManager.USB_FUNCTION_MTP); 366 } 367 368 @SmallTest 369 @Test unlockScreen()370 public void unlockScreen() { 371 when(mSharedPreferences.getString(String.format(Locale.ENGLISH, 372 UsbDeviceManager.UNLOCKED_CONFIG_PREF, mUsbHandler.mCurrentUser), "")) 373 .thenReturn(UsbManager.USB_FUNCTION_MTP); 374 mUsbHandler = new MockUsbHandler(FgThread.get().getLooper(), 375 InstrumentationRegistry.getContext(), mUsbDeviceManager, mUsbAlsaManager, 376 mUsbSettingsManager, mUsbPermissionManager); 377 sendBootCompleteMessages(mUsbHandler); 378 mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_UPDATE_SCREEN_LOCK, 1)); 379 mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_UPDATE_SCREEN_LOCK, 0)); 380 381 assertNotEquals(mUsbHandler.getScreenUnlockedFunctions() & UsbManager.FUNCTION_MTP, 0); 382 assertNotEquals(mUsbHandler.getEnabledFunctions() & UsbManager.FUNCTION_MTP, 0); 383 } 384 sendBootCompleteMessages(Handler handler)385 private static void sendBootCompleteMessages(Handler handler) { 386 handler.handleMessage(handler.obtainMessage(MSG_BOOT_COMPLETED)); 387 handler.handleMessage(handler.obtainMessage(MSG_SYSTEM_READY)); 388 } 389 } 390