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