diff --git a/src/com/android/settings/deviceinfo/UsbBackend.java b/src/com/android/settings/deviceinfo/UsbBackend.java index e648b393822..20116389b6c 100644 --- a/src/com/android/settings/deviceinfo/UsbBackend.java +++ b/src/com/android/settings/deviceinfo/UsbBackend.java @@ -24,6 +24,7 @@ import android.hardware.usb.UsbPort; import android.hardware.usb.UsbPortStatus; import android.os.UserHandle; import android.os.UserManager; +import android.support.annotation.VisibleForTesting; public class UsbBackend { @@ -41,7 +42,6 @@ public class UsbBackend { private final boolean mRestrictedBySystem; private final boolean mMidi; - private UserManager mUserManager; private UsbManager mUsbManager; private UsbPort mPort; private UsbPortStatus mPortStatus; @@ -49,20 +49,26 @@ public class UsbBackend { private boolean mIsUnlocked; public UsbBackend(Context context) { + this(context, new UserRestrictionUtil(context)); + } + + @VisibleForTesting + UsbBackend(Context context, UserRestrictionUtil userRestrictionUtil) { Intent intent = context.registerReceiver(null, new IntentFilter(UsbManager.ACTION_USB_STATE)); mIsUnlocked = intent == null ? false : intent.getBooleanExtra(UsbManager.USB_DATA_UNLOCKED, false); - mUserManager = UserManager.get(context); mUsbManager = context.getSystemService(UsbManager.class); - mRestricted = mUserManager.hasUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER); - mRestrictedBySystem = mUserManager.hasBaseUserRestriction( - UserManager.DISALLOW_USB_FILE_TRANSFER, UserHandle.of(UserHandle.myUserId())); + mRestricted = userRestrictionUtil.isUsbFileTransferRestricted(); + mRestrictedBySystem = userRestrictionUtil.isUsbFileTransferRestrictedBySystem(); mMidi = context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_MIDI); UsbPort[] ports = mUsbManager.getPorts(); + if (ports == null) { + return; + } // For now look for a connected port, in the future we should identify port in the // notification and pick based on that. final int N = ports.length; @@ -172,4 +178,22 @@ public class UsbBackend { // No port, support sink modes only. return (mode & MODE_POWER_MASK) != MODE_POWER_SOURCE; } + + // Wrapper class to enable testing with UserManager APIs + public static class UserRestrictionUtil { + private UserManager mUserManager; + + public UserRestrictionUtil(Context context) { + mUserManager = UserManager.get(context); + } + + public boolean isUsbFileTransferRestricted() { + return mUserManager.hasUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER); + } + + public boolean isUsbFileTransferRestrictedBySystem() { + return mUserManager.hasBaseUserRestriction( + UserManager.DISALLOW_USB_FILE_TRANSFER, UserHandle.of(UserHandle.myUserId())); + } + } } diff --git a/tests/robotests/src/com/android/settings/deviceinfo/UsbBackendTest.java b/tests/robotests/src/com/android/settings/deviceinfo/UsbBackendTest.java new file mode 100644 index 00000000000..99c37ef6cfa --- /dev/null +++ b/tests/robotests/src/com/android/settings/deviceinfo/UsbBackendTest.java @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.deviceinfo; + +import android.content.Context; +import android.content.pm.PackageManager; +import android.hardware.usb.UsbManager; + +import com.android.settings.SettingsRobolectricTestRunner; +import com.android.settings.TestConfig; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.annotation.Config; + +import static org.mockito.Answers.RETURNS_DEEP_STUBS; +import static org.mockito.Mockito.when; + +@RunWith(SettingsRobolectricTestRunner.class) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) +public class UsbBackendTest { + + @Mock(answer = RETURNS_DEEP_STUBS) + private Context mContext; + @Mock + private UsbManager mUsbManager; + @Mock + private UsbBackend.UserRestrictionUtil mUserRestrictionUtil; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + when(mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_MIDI)) + .thenReturn(true); + when((Object)mContext.getSystemService(UsbManager.class)).thenReturn(mUsbManager); + } + + @Test + public void constructor_noUsbPort_shouldNotCrash() { + UsbBackend usbBackend = new UsbBackend(mContext, mUserRestrictionUtil); + // Should not crash + } +}