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 SharedPreferences mSharedPreferences;
67     @Mock
68     private SharedPreferences.Editor mEditor;
69 
70     private MockUsbHandler mUsbHandler;
71 
72     private static final int MSG_UPDATE_STATE = 0;
73     private static final int MSG_ENABLE_ADB = 1;
74     private static final int MSG_SET_CURRENT_FUNCTIONS = 2;
75     private static final int MSG_SYSTEM_READY = 3;
76     private static final int MSG_BOOT_COMPLETED = 4;
77     private static final int MSG_USER_SWITCHED = 5;
78     private static final int MSG_UPDATE_USER_RESTRICTIONS = 6;
79     private static final int MSG_SET_SCREEN_UNLOCKED_FUNCTIONS = 12;
80     private static final int MSG_UPDATE_SCREEN_LOCK = 13;
81 
82     private Map<String, String> mMockProperties;
83     private Map<String, Integer> mMockGlobalSettings;
84 
85     private class MockUsbHandler extends UsbDeviceManager.UsbHandler {
86         boolean mIsUsbTransferAllowed;
87         Intent mBroadcastedIntent;
88 
MockUsbHandler(Looper looper, Context context, UsbDeviceManager deviceManager, UsbAlsaManager alsaManager, UsbSettingsManager settingsManager)89         MockUsbHandler(Looper looper, Context context, UsbDeviceManager deviceManager,
90                 UsbAlsaManager alsaManager, UsbSettingsManager settingsManager) {
91             super(looper, context, deviceManager, alsaManager, settingsManager);
92             mUseUsbNotification = false;
93             mIsUsbTransferAllowed = true;
94             mCurrentUsbFunctionsReceived = true;
95         }
96 
97         @Override
setEnabledFunctions(long functions, boolean force)98         protected void setEnabledFunctions(long functions, boolean force) {
99             mCurrentFunctions = functions;
100         }
101 
102         @Override
setSystemProperty(String property, String value)103         protected void setSystemProperty(String property, String value) {
104             mMockProperties.put(property, value);
105         }
106 
107         @Override
putGlobalSettings(ContentResolver resolver, String setting, int val)108         protected void putGlobalSettings(ContentResolver resolver, String setting, int val) {
109             mMockGlobalSettings.put(setting, val);
110         }
111 
112         @Override
getSystemProperty(String property, String def)113         protected String getSystemProperty(String property, String def) {
114             if (mMockProperties.containsKey(property)) {
115                 return mMockProperties.get(property);
116             }
117             return def;
118         }
119 
120         @Override
isUsbTransferAllowed()121         protected boolean isUsbTransferAllowed() {
122             return mIsUsbTransferAllowed;
123         }
124 
125         @Override
getPinnedSharedPrefs(Context context)126         protected SharedPreferences getPinnedSharedPrefs(Context context) {
127             return mSharedPreferences;
128         }
129 
130         @Override
sendStickyBroadcast(Intent intent)131         protected void sendStickyBroadcast(Intent intent) {
132             mBroadcastedIntent = intent;
133         }
134     }
135 
136     @Before
before()137     public void before() {
138         MockitoAnnotations.initMocks(this);
139         mMockProperties = new HashMap<>();
140         mMockGlobalSettings = new HashMap<>();
141         when(mSharedPreferences.edit()).thenReturn(mEditor);
142 
143         mUsbHandler = new MockUsbHandler(FgThread.get().getLooper(),
144                 InstrumentationRegistry.getContext(), mUsbDeviceManager, mUsbAlsaManager,
145                 mUsbSettingsManager);
146     }
147 
148     @SmallTest
149     @Test
setFunctionsMtp()150     public void setFunctionsMtp() {
151         mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_SET_CURRENT_FUNCTIONS,
152                 UsbManager.FUNCTION_MTP));
153         assertNotEquals(mUsbHandler.getEnabledFunctions() & UsbManager.FUNCTION_MTP, 0);
154     }
155 
156     @SmallTest
157     @Test
setFunctionsPtp()158     public void setFunctionsPtp() {
159         mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_SET_CURRENT_FUNCTIONS,
160                 UsbManager.FUNCTION_PTP));
161         assertNotEquals(mUsbHandler.getEnabledFunctions() & UsbManager.FUNCTION_PTP, 0);
162     }
163 
164     @SmallTest
165     @Test
setFunctionsMidi()166     public void setFunctionsMidi() {
167         mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_SET_CURRENT_FUNCTIONS,
168                 UsbManager.FUNCTION_MIDI));
169         assertNotEquals(mUsbHandler.getEnabledFunctions() & UsbManager.FUNCTION_MIDI, 0);
170     }
171 
172     @SmallTest
173     @Test
setFunctionsRndis()174     public void setFunctionsRndis() {
175         mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_SET_CURRENT_FUNCTIONS,
176                 UsbManager.FUNCTION_RNDIS));
177         assertNotEquals(mUsbHandler.getEnabledFunctions() & UsbManager.FUNCTION_RNDIS, 0);
178     }
179 
180     @SmallTest
181     @Test
enableAdb()182     public void enableAdb() {
183         sendBootCompleteMessages(mUsbHandler);
184         Message msg = mUsbHandler.obtainMessage(MSG_ENABLE_ADB);
185         msg.arg1 = 1;
186         mUsbHandler.handleMessage(msg);
187         assertEquals(mUsbHandler.getEnabledFunctions(), UsbManager.FUNCTION_NONE);
188         assertEquals(mMockProperties.get(UsbDeviceManager.UsbHandler
189                 .USB_PERSISTENT_CONFIG_PROPERTY), UsbManager.USB_FUNCTION_ADB);
190         assertTrue(mUsbHandler.isAdbEnabled());
191 
192         mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_UPDATE_STATE, 1, 1));
193 
194         assertTrue(mUsbHandler.mBroadcastedIntent.getBooleanExtra(UsbManager.USB_CONNECTED, false));
195         assertTrue(mUsbHandler.mBroadcastedIntent
196                 .getBooleanExtra(UsbManager.USB_CONFIGURED, false));
197         assertTrue(mUsbHandler.mBroadcastedIntent
198                 .getBooleanExtra(UsbManager.USB_FUNCTION_ADB, false));
199     }
200 
201     @SmallTest
202     @Test
disableAdb()203     public void disableAdb() {
204         mMockProperties.put(UsbDeviceManager.UsbHandler.USB_PERSISTENT_CONFIG_PROPERTY,
205                 UsbManager.USB_FUNCTION_ADB);
206         mUsbHandler = new MockUsbHandler(FgThread.get().getLooper(),
207                 InstrumentationRegistry.getContext(), mUsbDeviceManager, mUsbAlsaManager,
208                 mUsbSettingsManager);
209 
210         sendBootCompleteMessages(mUsbHandler);
211         mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_ENABLE_ADB, 0));
212         assertEquals(mUsbHandler.getEnabledFunctions(), UsbManager.FUNCTION_NONE);
213         assertFalse(mUsbHandler.isAdbEnabled());
214         assertEquals(mMockProperties.get(UsbDeviceManager.UsbHandler
215                 .USB_PERSISTENT_CONFIG_PROPERTY), "");
216     }
217 
218     @SmallTest
219     @Test
bootCompletedCharging()220     public void bootCompletedCharging() {
221         sendBootCompleteMessages(mUsbHandler);
222         assertEquals(mUsbHandler.getEnabledFunctions(), UsbManager.FUNCTION_NONE);
223     }
224 
225     @SmallTest
226     @Test
bootCompletedAdbEnabled()227     public void bootCompletedAdbEnabled() {
228         mMockProperties.put(UsbDeviceManager.UsbHandler.USB_PERSISTENT_CONFIG_PROPERTY, "adb");
229         mUsbHandler = new MockUsbHandler(FgThread.get().getLooper(),
230                 InstrumentationRegistry.getContext(), mUsbDeviceManager, mUsbAlsaManager,
231                 mUsbSettingsManager);
232 
233         sendBootCompleteMessages(mUsbHandler);
234         assertEquals(mUsbHandler.getEnabledFunctions(), UsbManager.FUNCTION_NONE);
235         assertEquals(mMockGlobalSettings.get(Settings.Global.ADB_ENABLED).intValue(), 1);
236         assertTrue(mUsbHandler.isAdbEnabled());
237     }
238 
239     @SmallTest
240     @Test
userSwitchedDisablesMtp()241     public void userSwitchedDisablesMtp() {
242         mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_SET_CURRENT_FUNCTIONS,
243                 UsbManager.FUNCTION_MTP));
244         assertNotEquals(mUsbHandler.getEnabledFunctions() & UsbManager.FUNCTION_MTP, 0);
245 
246         Message msg = mUsbHandler.obtainMessage(MSG_USER_SWITCHED);
247         msg.arg1 = ActivityManager.getCurrentUser() + 1;
248         mUsbHandler.handleMessage(msg);
249         assertEquals(mUsbHandler.getEnabledFunctions(), UsbManager.FUNCTION_NONE);
250     }
251 
252     @SmallTest
253     @Test
changedRestrictionsDisablesMtp()254     public void changedRestrictionsDisablesMtp() {
255         mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_SET_CURRENT_FUNCTIONS,
256                 UsbManager.FUNCTION_MTP));
257         assertNotEquals(mUsbHandler.getEnabledFunctions() & UsbManager.FUNCTION_MTP, 0);
258 
259         mUsbHandler.mIsUsbTransferAllowed = false;
260         mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_UPDATE_USER_RESTRICTIONS));
261         assertEquals(mUsbHandler.getEnabledFunctions(), UsbManager.FUNCTION_NONE);
262     }
263 
264     @SmallTest
265     @Test
disconnectResetsCharging()266     public void disconnectResetsCharging() {
267         sendBootCompleteMessages(mUsbHandler);
268 
269         mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_SET_CURRENT_FUNCTIONS,
270                 UsbManager.FUNCTION_MTP));
271         assertNotEquals(mUsbHandler.getEnabledFunctions() & UsbManager.FUNCTION_MTP, 0);
272 
273         mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_UPDATE_STATE, 0, 0));
274 
275         assertEquals(mUsbHandler.getEnabledFunctions(), UsbManager.FUNCTION_NONE);
276     }
277 
278     @SmallTest
279     @Test
configuredSendsBroadcast()280     public void configuredSendsBroadcast() {
281         sendBootCompleteMessages(mUsbHandler);
282         mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_SET_CURRENT_FUNCTIONS,
283                 UsbManager.FUNCTION_MTP));
284         assertNotEquals(mUsbHandler.getEnabledFunctions() & UsbManager.FUNCTION_MTP, 0);
285 
286         mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_UPDATE_STATE, 1, 1));
287 
288         assertNotEquals(mUsbHandler.getEnabledFunctions() & UsbManager.FUNCTION_MTP, 0);
289         assertTrue(mUsbHandler.mBroadcastedIntent.getBooleanExtra(UsbManager.USB_CONNECTED, false));
290         assertTrue(mUsbHandler.mBroadcastedIntent
291                 .getBooleanExtra(UsbManager.USB_CONFIGURED, false));
292         assertTrue(mUsbHandler.mBroadcastedIntent
293                 .getBooleanExtra(UsbManager.USB_FUNCTION_MTP, false));
294     }
295 
296     @SmallTest
297     @Test
setScreenUnlockedFunctions()298     public void setScreenUnlockedFunctions() {
299         sendBootCompleteMessages(mUsbHandler);
300         mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_UPDATE_SCREEN_LOCK, 0));
301 
302         mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_SET_SCREEN_UNLOCKED_FUNCTIONS,
303                 UsbManager.FUNCTION_MTP));
304         assertNotEquals(mUsbHandler.getScreenUnlockedFunctions() & UsbManager.FUNCTION_MTP, 0);
305         assertNotEquals(mUsbHandler.getEnabledFunctions() & UsbManager.FUNCTION_MTP, 0);
306         verify(mEditor).putString(String.format(Locale.ENGLISH,
307                 UsbDeviceManager.UNLOCKED_CONFIG_PREF, mUsbHandler.mCurrentUser),
308                 UsbManager.USB_FUNCTION_MTP);
309     }
310 
311     @SmallTest
312     @Test
unlockScreen()313     public void unlockScreen() {
314         when(mSharedPreferences.getString(String.format(Locale.ENGLISH,
315                 UsbDeviceManager.UNLOCKED_CONFIG_PREF, mUsbHandler.mCurrentUser), ""))
316                 .thenReturn(UsbManager.USB_FUNCTION_MTP);
317         mUsbHandler = new MockUsbHandler(FgThread.get().getLooper(),
318                 InstrumentationRegistry.getContext(), mUsbDeviceManager, mUsbAlsaManager,
319                 mUsbSettingsManager);
320         sendBootCompleteMessages(mUsbHandler);
321         mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_UPDATE_SCREEN_LOCK, 1));
322         mUsbHandler.handleMessage(mUsbHandler.obtainMessage(MSG_UPDATE_SCREEN_LOCK, 0));
323 
324         assertNotEquals(mUsbHandler.getScreenUnlockedFunctions() & UsbManager.FUNCTION_MTP, 0);
325         assertNotEquals(mUsbHandler.getEnabledFunctions() & UsbManager.FUNCTION_MTP, 0);
326     }
327 
sendBootCompleteMessages(Handler handler)328     private static void sendBootCompleteMessages(Handler handler) {
329         handler.handleMessage(handler.obtainMessage(MSG_BOOT_COMPLETED));
330         handler.handleMessage(handler.obtainMessage(MSG_SYSTEM_READY));
331     }
332 }
333