| /* |
| * Copyright (C) 2016 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.server.wifi.util; |
| |
| import static org.junit.Assert.assertFalse; |
| import static org.junit.Assert.assertTrue; |
| import static org.junit.Assert.fail; |
| import static org.mockito.ArgumentMatchers.any; |
| import static org.mockito.ArgumentMatchers.eq; |
| import static org.mockito.ArgumentMatchers.nullable; |
| import static org.mockito.Matchers.anyInt; |
| import static org.mockito.Matchers.anyString; |
| import static org.mockito.Mockito.doAnswer; |
| import static org.mockito.Mockito.doThrow; |
| import static org.mockito.Mockito.never; |
| import static org.mockito.Mockito.times; |
| import static org.mockito.Mockito.verify; |
| import static org.mockito.Mockito.when; |
| |
| import android.Manifest; |
| import android.app.AppOpsManager; |
| import android.app.admin.DevicePolicyManager; |
| import android.content.ComponentName; |
| import android.content.ContentResolver; |
| import android.content.Context; |
| import android.content.pm.ApplicationInfo; |
| import android.content.pm.PackageManager; |
| import android.location.LocationManager; |
| import android.net.NetworkStack; |
| import android.os.Build; |
| import android.os.UserHandle; |
| import android.os.UserManager; |
| import android.provider.Settings; |
| |
| import androidx.test.filters.SmallTest; |
| |
| import com.android.modules.utils.build.SdkLevel; |
| import com.android.server.wifi.BinderUtil; |
| import com.android.server.wifi.FakeWifiLog; |
| import com.android.server.wifi.FrameworkFacade; |
| import com.android.server.wifi.WifiBaseTest; |
| import com.android.server.wifi.WifiInjector; |
| |
| import org.junit.Before; |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| import org.junit.runners.JUnit4; |
| import org.mockito.Mock; |
| import org.mockito.MockitoAnnotations; |
| import org.mockito.Spy; |
| import org.mockito.invocation.InvocationOnMock; |
| import org.mockito.stubbing.Answer; |
| |
| import java.util.HashMap; |
| |
| /** Unit tests for {@link WifiPermissionsUtil}. */ |
| @RunWith(JUnit4.class) |
| @SmallTest |
| public class WifiPermissionsUtilTest extends WifiBaseTest { |
| public static final String TAG = "WifiPermissionsUtilTest"; |
| |
| // Mock objects for testing |
| @Mock private WifiPermissionsWrapper mMockPermissionsWrapper; |
| @Mock private Context mMockContext; |
| @Mock private FrameworkFacade mMockFrameworkFacade; |
| @Mock private PackageManager mMockPkgMgr; |
| @Mock private ApplicationInfo mMockApplInfo; |
| @Mock private AppOpsManager mMockAppOps; |
| @Mock private UserManager mMockUserManager; |
| @Mock private ContentResolver mMockContentResolver; |
| @Mock private WifiInjector mWifiInjector; |
| @Mock private LocationManager mLocationManager; |
| @Mock private DevicePolicyManager mDevicePolicyManager; |
| @Mock private PackageManager mPackageManager; |
| @Spy private FakeWifiLog mWifiLog; |
| |
| private static final String TEST_WIFI_STACK_APK_NAME = "com.android.wifi"; |
| private static final String TEST_PACKAGE_NAME = "com.google.somePackage"; |
| private static final String TEST_FEATURE_ID = "com.google.someFeature"; |
| private static final String INVALID_PACKAGE = "BAD_PACKAGE"; |
| private static final int MANAGED_PROFILE_UID = 1100000; |
| private static final int OTHER_USER_UID = 1200000; |
| private static final boolean CHECK_LOCATION_SETTINGS = false; |
| private static final boolean IGNORE_LOCATION_SETTINGS = true; |
| private static final boolean DONT_HIDE_FROM_APP_OPS = false; |
| private static final boolean HIDE_FROM_APP_OPS = true; |
| |
| private final String mMacAddressPermission = "android.permission.PEERS_MAC_ADDRESS"; |
| private final String mInteractAcrossUsersFullPermission = |
| "android.permission.INTERACT_ACROSS_USERS_FULL"; |
| private final String mManifestStringCoarse = |
| Manifest.permission.ACCESS_COARSE_LOCATION; |
| private final String mManifestStringFine = |
| Manifest.permission.ACCESS_FINE_LOCATION; |
| private final String mManifestStringHardware = |
| Manifest.permission.LOCATION_HARDWARE; |
| |
| // Test variables |
| private int mWifiScanAllowApps; |
| private int mUid; |
| private int mCoarseLocationPermission; |
| private int mAllowCoarseLocationApps; |
| private int mFineLocationPermission; |
| private int mAllowFineLocationApps; |
| private int mHardwareLocationPermission; |
| private int mCurrentUser; |
| private boolean mIsLocationEnabled; |
| private boolean mThrowSecurityException; |
| private Answer<Integer> mReturnPermission; |
| private HashMap<String, Integer> mPermissionsList = new HashMap<String, Integer>(); |
| |
| /** |
| * Set up Mockito tests |
| */ |
| @Before |
| public void setUp() { |
| MockitoAnnotations.initMocks(this); |
| initTestVars(); |
| } |
| |
| private void setupTestCase() throws Exception { |
| setupMocks(); |
| setupMockInterface(); |
| } |
| |
| /** |
| * Verify we return true when the UID does have the override config permission |
| */ |
| @Test |
| public void testCheckConfigOverridePermissionApproved() throws Exception { |
| mUid = MANAGED_PROFILE_UID; // do not really care about this value |
| setupTestCase(); |
| WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, |
| mMockContext, mMockUserManager, mWifiInjector); |
| when(mMockPermissionsWrapper.getOverrideWifiConfigPermission(anyInt())) |
| .thenReturn(PackageManager.PERMISSION_GRANTED); |
| assertTrue(codeUnderTest.checkConfigOverridePermission(mUid)); |
| } |
| |
| /** |
| * Verify we return false when the UID does not have the override config permission. |
| */ |
| @Test |
| public void testCheckConfigOverridePermissionDenied() throws Exception { |
| mUid = OTHER_USER_UID; // do not really care about this value |
| setupTestCase(); |
| WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, |
| mMockContext, mMockUserManager, mWifiInjector); |
| when(mMockPermissionsWrapper.getOverrideWifiConfigPermission(anyInt())) |
| .thenReturn(PackageManager.PERMISSION_DENIED); |
| assertFalse(codeUnderTest.checkConfigOverridePermission(mUid)); |
| } |
| |
| /** |
| * Test case setting: Package is valid |
| * Location mode is enabled |
| * Caller can read peers mac address |
| * This App has permission to request WIFI_SCAN |
| * User is current |
| * Validate no Exceptions are thrown |
| * - User has all the permissions |
| */ |
| @Test |
| public void testCanReadPeersMacAddressCurrentUserAndAllPermissions() throws Exception { |
| mThrowSecurityException = false; |
| mUid = MANAGED_PROFILE_UID; |
| mPermissionsList.put(mMacAddressPermission, mUid); |
| mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; |
| mCurrentUser = UserHandle.USER_SYSTEM; |
| mIsLocationEnabled = true; |
| setupTestCase(); |
| WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, |
| mMockContext, mMockUserManager, mWifiInjector); |
| codeUnderTest.enforceCanAccessScanResults(TEST_PACKAGE_NAME, TEST_FEATURE_ID, mUid, null); |
| } |
| |
| /** |
| * Test case setting: Package is valid |
| * Location mode is enabled |
| * Caller can read peers mac address |
| * This App has permission to request WIFI_SCAN |
| * User profile is current |
| * Validate no Exceptions are thrown |
| * - User has all the permissions |
| */ |
| @Test |
| public void testCanReadPeersMacAddressCurrentProfileAndAllPermissions() throws Exception { |
| mThrowSecurityException = false; |
| mUid = MANAGED_PROFILE_UID; |
| mPermissionsList.put(mMacAddressPermission, mUid); |
| mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; |
| mIsLocationEnabled = true; |
| setupTestCase(); |
| WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, |
| mMockContext, mMockUserManager, mWifiInjector); |
| codeUnderTest.enforceCanAccessScanResults(TEST_PACKAGE_NAME, TEST_FEATURE_ID, mUid, null); |
| } |
| |
| /** |
| * Test case setting: Package is valid |
| * Caller can read peers mac address |
| * Validate that a SecurityException is thrown |
| * - This App doesn't have permission to request Wifi Scan |
| */ |
| @Test |
| public void testCannotAccessScanResult_AppNotAllowed() throws Exception { |
| mThrowSecurityException = false; |
| mPermissionsList.put(mMacAddressPermission, mUid); |
| setupTestCase(); |
| WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, |
| mMockContext, mMockUserManager, mWifiInjector); |
| try { |
| codeUnderTest.enforceCanAccessScanResults(TEST_PACKAGE_NAME, TEST_FEATURE_ID, mUid, |
| null); |
| fail("Expected SecurityException is not thrown"); |
| } catch (SecurityException e) { |
| } |
| } |
| |
| /** |
| * Test case setting: Package is valid |
| * Location mode is enabled |
| * Caller can read peers mac address |
| * This App has permission to request WIFI_SCAN |
| * User or profile is not current but the uid has |
| * permission to INTERACT_ACROSS_USERS_FULL |
| * Validate no Exceptions are thrown |
| * - User has all the permissions |
| */ |
| @Test |
| public void testenforceCanAccessScanResults_UserOrProfileNotCurrent() throws Exception { |
| mThrowSecurityException = false; |
| mUid = MANAGED_PROFILE_UID; |
| mPermissionsList.put(mMacAddressPermission, mUid); |
| mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; |
| mPermissionsList.put(mInteractAcrossUsersFullPermission, mUid); |
| mIsLocationEnabled = true; |
| setupTestCase(); |
| WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, |
| mMockContext, mMockUserManager, mWifiInjector); |
| codeUnderTest.enforceCanAccessScanResults(TEST_PACKAGE_NAME, TEST_FEATURE_ID, mUid, null); |
| } |
| |
| /** |
| * Test case setting: Package is valid |
| * Caller can read peers mac address |
| * This App has permission to request WIFI_SCAN |
| * User or profile is not Current |
| * Validate that a SecurityException is thrown |
| * - Calling uid doesn't have INTERACT_ACROSS_USERS_FULL permission |
| */ |
| @Test |
| public void testCannotAccessScanResults_NoInteractAcrossUsersFullPermission() throws Exception { |
| mThrowSecurityException = false; |
| mUid = MANAGED_PROFILE_UID; |
| mPermissionsList.put(mMacAddressPermission, mUid); |
| mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; |
| setupTestCase(); |
| WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, |
| mMockContext, mMockUserManager, mWifiInjector); |
| try { |
| codeUnderTest.enforceCanAccessScanResults(TEST_PACKAGE_NAME, TEST_FEATURE_ID, mUid, |
| null); |
| fail("Expected SecurityException is not thrown"); |
| } catch (SecurityException e) { |
| } |
| } |
| |
| /** |
| * Test case Setting: Package is valid |
| * Foreground |
| * This App has permission to request WIFI_SCAN |
| * User is current |
| * Validate that a SecurityException is thrown - app does not have location permission |
| */ |
| @Test |
| public void testLegacyForegroundAppWithOtherPermissionsDenied() throws Exception { |
| mThrowSecurityException = false; |
| mMockApplInfo.targetSdkVersion = Build.VERSION_CODES.GINGERBREAD; |
| mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; |
| mUid = MANAGED_PROFILE_UID; |
| mCurrentUser = UserHandle.USER_SYSTEM; |
| setupTestCase(); |
| WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, |
| mMockContext, mMockUserManager, mWifiInjector); |
| try { |
| codeUnderTest.enforceCanAccessScanResults(TEST_PACKAGE_NAME, TEST_FEATURE_ID, mUid, |
| null); |
| fail("Expected SecurityException is not thrown"); |
| } catch (SecurityException e) { |
| } |
| } |
| |
| /** |
| * Test case Setting: Package is valid |
| * Location Mode Enabled |
| * Coarse Location Access |
| * This App has permission to request WIFI_SCAN |
| * User profile is current |
| * Validate no Exceptions are thrown - has all permissions |
| */ |
| @Test |
| public void testLegacyAppHasLocationAndAllPermissions() throws Exception { |
| mThrowSecurityException = false; |
| mMockApplInfo.targetSdkVersion = Build.VERSION_CODES.GINGERBREAD; |
| mIsLocationEnabled = true; |
| mCoarseLocationPermission = PackageManager.PERMISSION_GRANTED; |
| mAllowCoarseLocationApps = AppOpsManager.MODE_ALLOWED; |
| mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; |
| mUid = MANAGED_PROFILE_UID; |
| setupTestCase(); |
| WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, |
| mMockContext, mMockUserManager, mWifiInjector); |
| codeUnderTest.enforceCanAccessScanResults(TEST_PACKAGE_NAME, TEST_FEATURE_ID, mUid, null); |
| } |
| |
| /** |
| * Test case setting: Package is valid |
| * Location Mode Enabled |
| * Validate that a SecurityException is thrown |
| * - Doesn't have Peer Mac Address read permission |
| * - Uid is not an active network scorer |
| * - Location Mode is enabled but the uid |
| * - doesn't have Coarse Location Access |
| * - which implies No Location Permission |
| */ |
| @Test |
| public void testCannotAccessScanResults_NoCoarseLocationPermission() throws Exception { |
| mThrowSecurityException = false; |
| mIsLocationEnabled = true; |
| setupTestCase(); |
| WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, |
| mMockContext, mMockUserManager, mWifiInjector); |
| try { |
| codeUnderTest.enforceCanAccessScanResults(TEST_PACKAGE_NAME, TEST_FEATURE_ID, mUid, |
| null); |
| fail("Expected SecurityException is not thrown"); |
| } catch (SecurityException e) { |
| } |
| } |
| |
| /** |
| * Test case setting: Package is valid |
| * Location Mode Disabled |
| * Caller has location permission |
| * Validate an Exception is thrown |
| * - Uid is not an active network scorer |
| * - Uid doesn't have Coarse Location Access |
| * - which implies No Location Permission |
| */ |
| @Test |
| public void testCannotAccessScanResults_LocationModeDisabled() throws Exception { |
| mThrowSecurityException = false; |
| mUid = MANAGED_PROFILE_UID; |
| mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; |
| mPermissionsList.put(mInteractAcrossUsersFullPermission, mUid); |
| mIsLocationEnabled = false; |
| |
| setupTestCase(); |
| |
| WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, |
| mMockContext, mMockUserManager, mWifiInjector); |
| try { |
| codeUnderTest.enforceCanAccessScanResults(TEST_PACKAGE_NAME, TEST_FEATURE_ID, mUid, |
| null); |
| fail("Expected SecurityException is not thrown"); |
| } catch (SecurityException e) { |
| } |
| } |
| |
| /** |
| * Test case setting: Package is valid |
| * Location Mode Disabled |
| * Caller has location permisson |
| * Caller has CHANGE_WIFI_STATE |
| * Validate SecurityException is thrown |
| * - Doesn't have Peer Mac Address read permission |
| * - Uid is not an active network scorer |
| * - Location Mode is disabled |
| * - which implies no scan result access |
| */ |
| @Test |
| public void testEnforceCannotAccessScanResults_LocationModeDisabledHasChangeWifiState() |
| throws Exception { |
| mThrowSecurityException = false; |
| mUid = MANAGED_PROFILE_UID; |
| mPermissionsList.put(mMacAddressPermission, mUid); |
| mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; |
| mPermissionsList.put(mInteractAcrossUsersFullPermission, mUid); |
| mIsLocationEnabled = false; |
| |
| setupTestCase(); |
| |
| WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, |
| mMockContext, mMockUserManager, mWifiInjector); |
| try { |
| codeUnderTest.enforceCanAccessScanResults(TEST_PACKAGE_NAME, TEST_FEATURE_ID, mUid, |
| null); |
| fail("Expected SecurityException is not thrown"); |
| } catch (SecurityException e) { |
| } |
| } |
| |
| /** |
| * Test case setting: Package is valid |
| * Location Mode Disabled |
| * Caller has location permisson |
| * Caller has ACCESS_WIFI_STATE |
| * Validate Exception is thrown |
| * - Doesn't have Peer Mac Address read permission |
| * - Uid is not an active network scorer |
| * - Location Mode is disabled |
| * - doesn't have Coarse Location Access |
| * - which implies no scan result access |
| */ |
| @Test |
| public void testEnforceCannotAccessScanResults_LocationModeDisabledHasAccessWifiState() |
| throws Exception { |
| mThrowSecurityException = false; |
| mUid = MANAGED_PROFILE_UID; |
| mPermissionsList.put(mMacAddressPermission, mUid); |
| mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; |
| mPermissionsList.put(mInteractAcrossUsersFullPermission, mUid); |
| mIsLocationEnabled = false; |
| |
| setupTestCase(); |
| |
| WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, |
| mMockContext, mMockUserManager, mWifiInjector); |
| try { |
| codeUnderTest.enforceCanAccessScanResults(TEST_PACKAGE_NAME, TEST_FEATURE_ID, mUid, |
| null); |
| fail("Expected SecurityException is not thrown"); |
| } catch (SecurityException e) { |
| } |
| } |
| |
| /** |
| * Test case setting: Package is valid |
| * Location Mode Disabled |
| * Caller has location permisson |
| * Caller does not have NETWORK_SETTINGS |
| * Validate Exception is thrown |
| * - Doesn't have Peer Mac Address read permission |
| * - Uid is not an active network scorer |
| * - Location Mode is disabled |
| * - doesn't have Coarse Location Access |
| * - which implies no scan result access |
| */ |
| @Test |
| public void testEnforceCannotAccessScanResults_LocationModeDisabledHasNoNetworkSettings() |
| throws Exception { |
| mThrowSecurityException = false; |
| mUid = MANAGED_PROFILE_UID; |
| mPermissionsList.put(mMacAddressPermission, mUid); |
| mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; |
| mPermissionsList.put(mInteractAcrossUsersFullPermission, mUid); |
| mIsLocationEnabled = false; |
| |
| setupTestCase(); |
| when(mMockPermissionsWrapper.getUidPermission( |
| Manifest.permission.NETWORK_SETTINGS, MANAGED_PROFILE_UID)) |
| .thenReturn(PackageManager.PERMISSION_DENIED); |
| |
| WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, |
| mMockContext, mMockUserManager, mWifiInjector); |
| try { |
| codeUnderTest.enforceCanAccessScanResults(TEST_PACKAGE_NAME, TEST_FEATURE_ID, mUid, |
| null); |
| fail("Expected SecurityException is not thrown"); |
| } catch (SecurityException e) { |
| } |
| } |
| |
| /** |
| * Test case setting: Package is valid |
| * Location Mode Disabled |
| * Caller has location permisson |
| * Caller has NETWORK_SETTINGS |
| * Validate Exception is thrown |
| * - Doesn't have Peer Mac Address read permission |
| * - Uid is not an active network scorer |
| * - Location Mode is disabled |
| * - doesn't have Coarse Location Access |
| * - which implies no scan result access |
| */ |
| @Test |
| public void testEnforceCanAccessScanResults_LocationModeDisabledHasNetworkSettings() |
| throws Exception { |
| mThrowSecurityException = false; |
| mUid = MANAGED_PROFILE_UID; |
| mPermissionsList.put(mMacAddressPermission, mUid); |
| mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; |
| mPermissionsList.put(mInteractAcrossUsersFullPermission, mUid); |
| mIsLocationEnabled = false; |
| |
| setupTestCase(); |
| when(mMockPermissionsWrapper.getUidPermission( |
| Manifest.permission.NETWORK_SETTINGS, MANAGED_PROFILE_UID)) |
| .thenReturn(PackageManager.PERMISSION_GRANTED); |
| |
| WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, |
| mMockContext, mMockUserManager, mWifiInjector); |
| codeUnderTest.enforceCanAccessScanResults(TEST_PACKAGE_NAME, TEST_FEATURE_ID, mUid, null); |
| } |
| |
| /** |
| * Test case setting: Package is valid |
| * Location Mode Disabled |
| * Caller has location permisson |
| * Caller does not have NETWORK_SETUP_WIZARD |
| * Validate Exception is thrown |
| * - Doesn't have Peer Mac Address read permission |
| * - Uid is not an active network scorer |
| * - Location Mode is disabled |
| * - doesn't have Coarse Location Access |
| * - which implies no scan result access |
| */ |
| @Test |
| public void testEnforceCannotAccessScanResults_LocationModeDisabledHasNoNetworkSetupWizard() |
| throws Exception { |
| mThrowSecurityException = false; |
| mUid = MANAGED_PROFILE_UID; |
| mPermissionsList.put(mMacAddressPermission, mUid); |
| mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; |
| mPermissionsList.put(mInteractAcrossUsersFullPermission, mUid); |
| mIsLocationEnabled = false; |
| |
| setupTestCase(); |
| when(mMockPermissionsWrapper.getUidPermission( |
| android.Manifest.permission.NETWORK_SETUP_WIZARD, MANAGED_PROFILE_UID)) |
| .thenReturn(PackageManager.PERMISSION_DENIED); |
| |
| WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, |
| mMockContext, mMockUserManager, mWifiInjector); |
| try { |
| codeUnderTest.enforceCanAccessScanResults(TEST_PACKAGE_NAME, TEST_FEATURE_ID, mUid, |
| null); |
| fail("Expected SecurityException is not thrown"); |
| } catch (SecurityException e) { |
| } |
| } |
| |
| /** |
| * Test case setting: Package is valid |
| * Location Mode Disabled |
| * Caller has no location permisson |
| * Caller has NETWORK_SETUP_WIZARD |
| * Validate Exception is thrown |
| * - Doesn't have Peer Mac Address read permission |
| * - Uid is not an active network scorer |
| * - Location Mode is disabled |
| * - doesn't have Coarse Location Access |
| * - which implies no scan result access |
| */ |
| @Test |
| public void testEnforceCanAccessScanResults_LocationModeDisabledHasNetworkSetupWizard() |
| throws Exception { |
| mThrowSecurityException = false; |
| mUid = MANAGED_PROFILE_UID; |
| mPermissionsList.put(mMacAddressPermission, mUid); |
| mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; |
| mPermissionsList.put(mInteractAcrossUsersFullPermission, mUid); |
| mIsLocationEnabled = false; |
| |
| setupTestCase(); |
| when(mMockPermissionsWrapper.getUidPermission( |
| android.Manifest.permission.NETWORK_SETUP_WIZARD, MANAGED_PROFILE_UID)) |
| .thenReturn(PackageManager.PERMISSION_GRANTED); |
| |
| WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, |
| mMockContext, mMockUserManager, mWifiInjector); |
| codeUnderTest.enforceCanAccessScanResults(TEST_PACKAGE_NAME, TEST_FEATURE_ID, mUid, null); |
| } |
| |
| /** |
| * Test case setting: Package is valid |
| * Location Mode Disabled |
| * Caller has no location permisson |
| * Caller has NETWORK_MANAGED_PROVISIONING |
| * Validate Exception is thrown |
| * - Doesn't have Peer Mac Address read permission |
| * - Uid is not an active network scorer |
| * - Location Mode is disabled |
| * - doesn't have Coarse Location Access |
| * - which implies no scan result access |
| */ |
| @Test |
| public void testEnforceCanAccessScanResults_LocationModeDisabledHasNetworkManagedProvisioning() |
| throws Exception { |
| mThrowSecurityException = false; |
| mUid = MANAGED_PROFILE_UID; |
| mPermissionsList.put(mMacAddressPermission, mUid); |
| mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; |
| mPermissionsList.put(mInteractAcrossUsersFullPermission, mUid); |
| mIsLocationEnabled = false; |
| |
| setupTestCase(); |
| when(mMockPermissionsWrapper.getUidPermission( |
| android.Manifest.permission.NETWORK_MANAGED_PROVISIONING, MANAGED_PROFILE_UID)) |
| .thenReturn(PackageManager.PERMISSION_GRANTED); |
| |
| WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, |
| mMockContext, mMockUserManager, mWifiInjector); |
| codeUnderTest.enforceCanAccessScanResults(TEST_PACKAGE_NAME, TEST_FEATURE_ID, mUid, null); |
| } |
| |
| /** |
| * Test case setting: Package is valid |
| * Location Mode Disabled |
| * Caller has no location permisson |
| * Caller has NETWORK_STACK |
| * Validate Exception is thrown |
| * - Doesn't have Peer Mac Address read permission |
| * - Uid is not an active network scorer |
| * - Location Mode is disabled |
| * - doesn't have Coarse Location Access |
| * - which implies no scan result access |
| */ |
| @Test |
| public void testEnforceCanAccessScanResults_LocationModeDisabledHasNetworkStack() |
| throws Exception { |
| mThrowSecurityException = false; |
| mUid = MANAGED_PROFILE_UID; |
| mPermissionsList.put(mMacAddressPermission, mUid); |
| mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; |
| mPermissionsList.put(mInteractAcrossUsersFullPermission, mUid); |
| mIsLocationEnabled = false; |
| |
| setupTestCase(); |
| when(mMockPermissionsWrapper.getUidPermission( |
| android.Manifest.permission.NETWORK_STACK, MANAGED_PROFILE_UID)) |
| .thenReturn(PackageManager.PERMISSION_GRANTED); |
| |
| WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, |
| mMockContext, mMockUserManager, mWifiInjector); |
| codeUnderTest.enforceCanAccessScanResults(TEST_PACKAGE_NAME, TEST_FEATURE_ID, mUid, null); |
| } |
| |
| /** |
| * Test case setting: Package is valid |
| * Location Mode Disabled |
| * Caller has no location permisson |
| * Caller has MAINLINE_NETWORK_STACK |
| * Validate Exception is thrown |
| * - Doesn't have Peer Mac Address read permission |
| * - Uid is not an active network scorer |
| * - Location Mode is disabled |
| * - doesn't have Coarse Location Access |
| * - which implies no scan result access |
| */ |
| @Test |
| public void testEnforceCanAccessScanResults_LocationModeDisabledHasMainlineNetworkStack() |
| throws Exception { |
| mThrowSecurityException = false; |
| mUid = MANAGED_PROFILE_UID; |
| mPermissionsList.put(mMacAddressPermission, mUid); |
| mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; |
| mPermissionsList.put(mInteractAcrossUsersFullPermission, mUid); |
| mIsLocationEnabled = false; |
| |
| setupTestCase(); |
| when(mMockPermissionsWrapper.getUidPermission( |
| NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, MANAGED_PROFILE_UID)) |
| .thenReturn(PackageManager.PERMISSION_GRANTED); |
| |
| WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, |
| mMockContext, mMockUserManager, mWifiInjector); |
| codeUnderTest.enforceCanAccessScanResults(TEST_PACKAGE_NAME, TEST_FEATURE_ID, mUid, null); |
| } |
| |
| /** |
| * Test case setting: Invalid Package |
| * Expect a securityException |
| */ |
| @Test |
| public void testInvalidPackage() throws Exception { |
| setupTestCase(); |
| WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, |
| mMockContext, mMockUserManager, mWifiInjector); |
| try { |
| codeUnderTest.enforceCanAccessScanResults(TEST_PACKAGE_NAME, TEST_FEATURE_ID, mUid, |
| null); |
| fail("Expected SecurityException is not thrown"); |
| } catch (SecurityException e) { |
| } |
| } |
| |
| /** |
| * Test case setting: legacy caller does have Coarse Location permission. |
| * A SecurityException should not be thrown. |
| */ |
| @Test |
| public void testEnforceCoarseLocationPermissionLegacyApp() throws Exception { |
| mThrowSecurityException = false; |
| mMockApplInfo.targetSdkVersion = Build.VERSION_CODES.GINGERBREAD; |
| mIsLocationEnabled = true; |
| mCoarseLocationPermission = PackageManager.PERMISSION_GRANTED; |
| mAllowCoarseLocationApps = AppOpsManager.MODE_ALLOWED; |
| mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; |
| mUid = MANAGED_PROFILE_UID; |
| setupTestCase(); |
| WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, |
| mMockContext, mMockUserManager, mWifiInjector); |
| codeUnderTest.enforceLocationPermission(TEST_PACKAGE_NAME, TEST_FEATURE_ID, mUid); |
| |
| // verify that checking FINE for legacy apps! |
| verify(mMockAppOps).noteOp(eq(AppOpsManager.OPSTR_FINE_LOCATION), anyInt(), anyString(), |
| any(), any()); |
| } |
| |
| /** |
| * Test case setting: legacy caller does have Coarse Location permission. |
| * A SecurityException should not be thrown. |
| */ |
| @Test |
| public void testEnforceFineLocationPermissionNewQApp() throws Exception { |
| mThrowSecurityException = false; |
| mMockApplInfo.targetSdkVersion = Build.VERSION_CODES.Q; |
| mIsLocationEnabled = true; |
| mFineLocationPermission = PackageManager.PERMISSION_GRANTED; |
| mAllowFineLocationApps = AppOpsManager.MODE_ALLOWED; |
| mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; |
| mUid = MANAGED_PROFILE_UID; |
| setupTestCase(); |
| WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, |
| mMockContext, mMockUserManager, mWifiInjector); |
| codeUnderTest.enforceLocationPermission(TEST_PACKAGE_NAME, TEST_FEATURE_ID, mUid); |
| verify(mMockAppOps) |
| .noteOp(eq(AppOpsManager.OPSTR_FINE_LOCATION), anyInt(), anyString(), any(), any()); |
| } |
| |
| /** |
| * Test case setting: legacy caller does have Coarse Location permission. |
| * A SecurityException should not be thrown. |
| */ |
| @Test |
| public void testEnforceFailureFineLocationPermissionNewQApp() throws Exception { |
| mThrowSecurityException = false; |
| mMockApplInfo.targetSdkVersion = Build.VERSION_CODES.Q; |
| mIsLocationEnabled = true; |
| mCoarseLocationPermission = PackageManager.PERMISSION_GRANTED; |
| mFineLocationPermission = PackageManager.PERMISSION_DENIED; |
| mAllowCoarseLocationApps = AppOpsManager.MODE_ALLOWED; |
| mAllowFineLocationApps = AppOpsManager.MODE_ERRORED; |
| mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; |
| mUid = MANAGED_PROFILE_UID; |
| setupTestCase(); |
| WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, |
| mMockContext, mMockUserManager, mWifiInjector); |
| try { |
| codeUnderTest.enforceLocationPermission(TEST_PACKAGE_NAME, TEST_FEATURE_ID, mUid); |
| fail("Expected SecurityException not thrown"); |
| } catch (SecurityException e) { |
| // empty |
| } |
| verify(mMockAppOps, never()).noteOp(anyInt(), anyInt(), anyString()); |
| } |
| |
| /** |
| * Verifies the helper method exposed for checking NETWORK_SETUP_WIZARD permission. |
| */ |
| @Test |
| public void testCheckNetworkSetupWizard() throws Exception { |
| setupMocks(); |
| WifiPermissionsUtil wifiPermissionsUtil = new WifiPermissionsUtil(mMockPermissionsWrapper, |
| mMockContext, mMockUserManager, mWifiInjector); |
| |
| when(mMockPermissionsWrapper.getUidPermission( |
| android.Manifest.permission.NETWORK_SETUP_WIZARD, MANAGED_PROFILE_UID)) |
| .thenReturn(PackageManager.PERMISSION_DENIED); |
| assertFalse(wifiPermissionsUtil.checkNetworkSetupWizardPermission(MANAGED_PROFILE_UID)); |
| |
| when(mMockPermissionsWrapper.getUidPermission( |
| android.Manifest.permission.NETWORK_SETUP_WIZARD, MANAGED_PROFILE_UID)) |
| .thenReturn(PackageManager.PERMISSION_GRANTED); |
| assertTrue(wifiPermissionsUtil.checkNetworkSetupWizardPermission(MANAGED_PROFILE_UID)); |
| } |
| |
| /** |
| * Verifies the helper method exposed for checking NETWORK_MANAGED_PROVISIONING permission. |
| */ |
| @Test |
| public void testCheckNetworkManagedProvisioning() throws Exception { |
| setupMocks(); |
| WifiPermissionsUtil wifiPermissionsUtil = new WifiPermissionsUtil(mMockPermissionsWrapper, |
| mMockContext, mMockUserManager, mWifiInjector); |
| |
| when(mMockPermissionsWrapper.getUidPermission( |
| android.Manifest.permission.NETWORK_MANAGED_PROVISIONING, MANAGED_PROFILE_UID)) |
| .thenReturn(PackageManager.PERMISSION_DENIED); |
| assertFalse(wifiPermissionsUtil.checkNetworkManagedProvisioningPermission( |
| MANAGED_PROFILE_UID)); |
| |
| when(mMockPermissionsWrapper.getUidPermission( |
| android.Manifest.permission.NETWORK_MANAGED_PROVISIONING, MANAGED_PROFILE_UID)) |
| .thenReturn(PackageManager.PERMISSION_GRANTED); |
| assertTrue(wifiPermissionsUtil.checkNetworkManagedProvisioningPermission( |
| MANAGED_PROFILE_UID)); |
| } |
| |
| /** |
| * Verifies the helper method exposed for checking SYSTERM_ALERT_WINDOW permission. |
| */ |
| @Test |
| public void testCheckSystemAlertWindowPermissionWithModeDefaultAppOps() throws Exception { |
| setupMocks(); |
| WifiPermissionsUtil wifiPermissionsUtil = new WifiPermissionsUtil(mMockPermissionsWrapper, |
| mMockContext, mMockUserManager, mWifiInjector); |
| |
| when(mMockAppOps.noteOp(AppOpsManager.OPSTR_SYSTEM_ALERT_WINDOW, MANAGED_PROFILE_UID, |
| TEST_PACKAGE_NAME, null, null)) |
| .thenReturn(AppOpsManager.MODE_DEFAULT); |
| when(mMockPermissionsWrapper.getUidPermission( |
| Manifest.permission.SYSTEM_ALERT_WINDOW, MANAGED_PROFILE_UID)) |
| .thenReturn(PackageManager.PERMISSION_DENIED); |
| assertFalse(wifiPermissionsUtil.checkSystemAlertWindowPermission( |
| MANAGED_PROFILE_UID, TEST_PACKAGE_NAME)); |
| |
| when(mMockAppOps.noteOp(AppOpsManager.OPSTR_SYSTEM_ALERT_WINDOW, MANAGED_PROFILE_UID, |
| TEST_PACKAGE_NAME, null, null)) |
| .thenReturn(AppOpsManager.MODE_DEFAULT); |
| when(mMockPermissionsWrapper.getUidPermission( |
| Manifest.permission.SYSTEM_ALERT_WINDOW, MANAGED_PROFILE_UID)) |
| .thenReturn(PackageManager.PERMISSION_GRANTED); |
| assertTrue(wifiPermissionsUtil.checkSystemAlertWindowPermission( |
| MANAGED_PROFILE_UID, TEST_PACKAGE_NAME)); |
| } |
| |
| /** |
| * Verifies the helper method exposed for checking SYSTERM_ALERT_WINDOW permission. |
| */ |
| @Test |
| public void testCheckSystemAlertWindowPermissionWithModeAllowedAppOps() throws Exception { |
| setupMocks(); |
| WifiPermissionsUtil wifiPermissionsUtil = new WifiPermissionsUtil(mMockPermissionsWrapper, |
| mMockContext, mMockUserManager, mWifiInjector); |
| |
| when(mMockAppOps.noteOp( |
| AppOpsManager.OP_SYSTEM_ALERT_WINDOW, MANAGED_PROFILE_UID, TEST_PACKAGE_NAME)) |
| .thenReturn(AppOpsManager.MODE_ALLOWED); |
| assertTrue(wifiPermissionsUtil.checkSystemAlertWindowPermission( |
| MANAGED_PROFILE_UID, TEST_PACKAGE_NAME)); |
| } |
| |
| /** |
| * Verifies the helper method exposed for checking if the app is a DeviceOwner. |
| */ |
| @Test |
| public void testIsDeviceOwnerByPackageName() throws Exception { |
| setupMocks(); |
| WifiPermissionsUtil wifiPermissionsUtil = new WifiPermissionsUtil(mMockPermissionsWrapper, |
| mMockContext, mMockUserManager, mWifiInjector); |
| |
| when(mMockContext.getSystemService(DevicePolicyManager.class)) |
| .thenReturn(mDevicePolicyManager); |
| |
| when(mDevicePolicyManager.getDeviceOwnerComponentOnAnyUser()) |
| .thenReturn(new ComponentName(TEST_PACKAGE_NAME, new String())); |
| when(mDevicePolicyManager.getDeviceOwnerUser()) |
| .thenReturn(UserHandle.getUserHandleForUid(MANAGED_PROFILE_UID)); |
| assertTrue(wifiPermissionsUtil.isDeviceOwner( |
| MANAGED_PROFILE_UID, TEST_PACKAGE_NAME)); |
| |
| |
| // userId does not match |
| when(mDevicePolicyManager.getDeviceOwnerComponentOnAnyUser()) |
| .thenReturn(new ComponentName(TEST_PACKAGE_NAME, new String())); |
| when(mDevicePolicyManager.getDeviceOwnerUser()) |
| .thenReturn(UserHandle.getUserHandleForUid(OTHER_USER_UID)); |
| assertFalse(wifiPermissionsUtil.isDeviceOwner( |
| MANAGED_PROFILE_UID, TEST_PACKAGE_NAME)); |
| |
| // Package Name does not match |
| when(mDevicePolicyManager.getDeviceOwnerComponentOnAnyUser()) |
| .thenReturn(new ComponentName(INVALID_PACKAGE, new String())); |
| when(mDevicePolicyManager.getDeviceOwnerUser()) |
| .thenReturn(UserHandle.getUserHandleForUid(MANAGED_PROFILE_UID)); |
| assertFalse(wifiPermissionsUtil.isDeviceOwner( |
| MANAGED_PROFILE_UID, TEST_PACKAGE_NAME)); |
| |
| // No device owner. |
| when(mDevicePolicyManager.getDeviceOwnerComponentOnAnyUser()) |
| .thenReturn(null); |
| assertFalse(wifiPermissionsUtil.isDeviceOwner( |
| MANAGED_PROFILE_UID, TEST_PACKAGE_NAME)); |
| |
| // DevicePolicyManager does not exist. |
| when(mMockContext.getSystemService(Context.DEVICE_POLICY_SERVICE)) |
| .thenReturn(null); |
| assertFalse(wifiPermissionsUtil.isDeviceOwner( |
| MANAGED_PROFILE_UID, TEST_PACKAGE_NAME)); |
| } |
| |
| /** |
| * Verifies the helper method exposed for checking if UID is a DeviceOwner. |
| */ |
| @Test |
| public void testIsDeviceOwnerByUid() throws Exception { |
| setupMocks(); |
| WifiPermissionsUtil wifiPermissionsUtil = new WifiPermissionsUtil(mMockPermissionsWrapper, |
| mMockContext, mMockUserManager, mWifiInjector); |
| |
| when(mMockContext.getSystemService(DevicePolicyManager.class)) |
| .thenReturn(mDevicePolicyManager); |
| when(mMockContext.getPackageManager()).thenReturn(mPackageManager); |
| |
| when(mDevicePolicyManager.getDeviceOwnerComponentOnAnyUser()) |
| .thenReturn(new ComponentName(TEST_PACKAGE_NAME, new String())); |
| when(mDevicePolicyManager.getDeviceOwnerUser()) |
| .thenReturn(UserHandle.getUserHandleForUid(MANAGED_PROFILE_UID)); |
| when(mPackageManager.getPackagesForUid(MANAGED_PROFILE_UID)).thenReturn( |
| new String[] { TEST_PACKAGE_NAME }); |
| assertTrue(wifiPermissionsUtil.isDeviceOwner(MANAGED_PROFILE_UID)); |
| |
| // userId does not match |
| when(mDevicePolicyManager.getDeviceOwnerComponentOnAnyUser()) |
| .thenReturn(new ComponentName(TEST_PACKAGE_NAME, new String())); |
| when(mDevicePolicyManager.getDeviceOwnerUser()) |
| .thenReturn(UserHandle.getUserHandleForUid(OTHER_USER_UID)); |
| assertFalse(wifiPermissionsUtil.isDeviceOwner(MANAGED_PROFILE_UID)); |
| |
| // uid does not match |
| when(mDevicePolicyManager.getDeviceOwnerComponentOnAnyUser()) |
| .thenReturn(new ComponentName(TEST_PACKAGE_NAME, new String())); |
| when(mDevicePolicyManager.getDeviceOwnerUser()) |
| .thenReturn(UserHandle.getUserHandleForUid(MANAGED_PROFILE_UID)); |
| when(mPackageManager.getPackagesForUid(MANAGED_PROFILE_UID)).thenReturn( |
| new String[] { TEST_FEATURE_ID }); |
| assertFalse(wifiPermissionsUtil.isDeviceOwner(MANAGED_PROFILE_UID)); |
| |
| // no packages for uid |
| when(mDevicePolicyManager.getDeviceOwnerComponentOnAnyUser()) |
| .thenReturn(new ComponentName(TEST_PACKAGE_NAME, new String())); |
| when(mDevicePolicyManager.getDeviceOwnerUser()) |
| .thenReturn(UserHandle.getUserHandleForUid(MANAGED_PROFILE_UID)); |
| when(mPackageManager.getPackagesForUid(MANAGED_PROFILE_UID)).thenReturn(null); |
| assertFalse(wifiPermissionsUtil.isDeviceOwner(MANAGED_PROFILE_UID)); |
| |
| // No device owner. |
| when(mDevicePolicyManager.getDeviceOwnerComponentOnAnyUser()) |
| .thenReturn(null); |
| assertFalse(wifiPermissionsUtil.isDeviceOwner(MANAGED_PROFILE_UID)); |
| |
| // DevicePolicyManager does not exist. |
| when(mMockContext.getSystemService(Context.DEVICE_POLICY_SERVICE)) |
| .thenReturn(null); |
| assertFalse(wifiPermissionsUtil.isDeviceOwner(MANAGED_PROFILE_UID)); |
| } |
| |
| /** |
| * Verifies the helper method exposed for checking if the app is a ProfileOwner. |
| */ |
| @Test |
| public void testIsProfileOwnerApp() throws Exception { |
| setupMocks(); |
| WifiPermissionsUtil wifiPermissionsUtil = new WifiPermissionsUtil(mMockPermissionsWrapper, |
| mMockContext, mMockUserManager, mWifiInjector); |
| |
| when(mMockContext.createPackageContextAsUser( |
| TEST_WIFI_STACK_APK_NAME, 0, UserHandle.getUserHandleForUid(MANAGED_PROFILE_UID))) |
| .thenReturn(mMockContext); |
| when(mMockContext.getSystemService(DevicePolicyManager.class)) |
| .thenReturn(mDevicePolicyManager); |
| |
| when(mDevicePolicyManager.isProfileOwnerApp(TEST_PACKAGE_NAME)) |
| .thenReturn(true); |
| assertTrue(wifiPermissionsUtil.isProfileOwner( |
| MANAGED_PROFILE_UID, TEST_PACKAGE_NAME)); |
| |
| when(mDevicePolicyManager.isProfileOwnerApp(TEST_PACKAGE_NAME)) |
| .thenReturn(false); |
| assertFalse(wifiPermissionsUtil.isProfileOwner( |
| MANAGED_PROFILE_UID, TEST_PACKAGE_NAME)); |
| |
| // DevicePolicyManager does not exist. |
| when(mMockContext.getSystemService(Context.DEVICE_POLICY_SERVICE)) |
| .thenReturn(null); |
| assertFalse(wifiPermissionsUtil.isProfileOwner( |
| MANAGED_PROFILE_UID, TEST_PACKAGE_NAME)); |
| |
| // Invalid package name. |
| doThrow(new PackageManager.NameNotFoundException()) |
| .when(mMockContext).createPackageContextAsUser( |
| TEST_WIFI_STACK_APK_NAME, 0, |
| UserHandle.getUserHandleForUid(MANAGED_PROFILE_UID)); |
| assertFalse(wifiPermissionsUtil.isProfileOwner( |
| MANAGED_PROFILE_UID, TEST_PACKAGE_NAME)); |
| } |
| |
| /** |
| * Test case setting: caller does not have Location permission. |
| * Expect a SecurityException |
| */ |
| @Test(expected = SecurityException.class) |
| public void testEnforceLocationPermissionExpectSecurityException() throws Exception { |
| setupTestCase(); |
| WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, |
| mMockContext, mMockUserManager, mWifiInjector); |
| codeUnderTest.enforceLocationPermission(TEST_PACKAGE_NAME, TEST_FEATURE_ID, mUid); |
| } |
| |
| /** |
| * Test case setting: Package is valid |
| * Location Mode Enabled |
| * Fine Location Access |
| * Location hardware Access |
| * This App has permission to request WIFI_SCAN |
| * Validate no Exceptions are thrown - has all permissions |
| */ |
| @Test |
| public void testCanAccessScanResultsForWifiScanner() throws Exception { |
| mThrowSecurityException = false; |
| mIsLocationEnabled = true; |
| mFineLocationPermission = PackageManager.PERMISSION_GRANTED; |
| mHardwareLocationPermission = PackageManager.PERMISSION_GRANTED; |
| mAllowFineLocationApps = AppOpsManager.MODE_ALLOWED; |
| mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; |
| mUid = MANAGED_PROFILE_UID; |
| setupTestCase(); |
| WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, |
| mMockContext, mMockUserManager, mWifiInjector); |
| codeUnderTest.enforceCanAccessScanResultsForWifiScanner(TEST_PACKAGE_NAME, TEST_FEATURE_ID, |
| mUid, CHECK_LOCATION_SETTINGS, DONT_HIDE_FROM_APP_OPS); |
| |
| verify(mMockAppOps, never()) |
| .unsafeCheckOp(AppOpsManager.OPSTR_FINE_LOCATION, mUid, TEST_PACKAGE_NAME); |
| verify(mMockAppOps).noteOp(AppOpsManager.OPSTR_FINE_LOCATION, mUid, TEST_PACKAGE_NAME, |
| TEST_FEATURE_ID, null); |
| } |
| |
| /** |
| * Test case setting: Package is valid |
| * Location Mode Enabled |
| * Fine Location Access |
| * Location hardware Access |
| * This App has permission to request WIFI_SCAN |
| * Validate no Exceptions are thrown - has all permissions & don't note in app-ops. |
| */ |
| @Test |
| public void testCannotAccessScanResultsForWifiScanner_HideFromAppOps() |
| throws Exception { |
| mThrowSecurityException = false; |
| mIsLocationEnabled = true; |
| mFineLocationPermission = PackageManager.PERMISSION_GRANTED; |
| mHardwareLocationPermission = PackageManager.PERMISSION_GRANTED; |
| mAllowFineLocationApps = AppOpsManager.MODE_ALLOWED; |
| mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; |
| mUid = MANAGED_PROFILE_UID; |
| setupTestCase(); |
| WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, |
| mMockContext, mMockUserManager, mWifiInjector); |
| codeUnderTest.enforceCanAccessScanResultsForWifiScanner(TEST_PACKAGE_NAME, TEST_FEATURE_ID, |
| mUid, IGNORE_LOCATION_SETTINGS, HIDE_FROM_APP_OPS); |
| |
| verify(mMockAppOps).unsafeCheckOp(AppOpsManager.OPSTR_FINE_LOCATION, mUid, |
| TEST_PACKAGE_NAME); |
| verify(mMockAppOps, never()).noteOp( |
| AppOpsManager.OPSTR_FINE_LOCATION, mUid, TEST_PACKAGE_NAME, null, null); |
| } |
| |
| |
| /** |
| * Test case setting: Package is valid |
| * Location Mode Enabled |
| * Location hardware Access |
| * This App has permission to request WIFI_SCAN |
| * Validate that a SecurityException is thrown |
| * - Doesn't have fine location permission. |
| */ |
| @Test |
| public void testCannotAccessScanResultsForWifiScanner_NoFineLocationPermission() |
| throws Exception { |
| mThrowSecurityException = false; |
| mIsLocationEnabled = true; |
| mFineLocationPermission = PackageManager.PERMISSION_DENIED; |
| mHardwareLocationPermission = PackageManager.PERMISSION_GRANTED; |
| mAllowFineLocationApps = AppOpsManager.MODE_ALLOWED; |
| mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; |
| mUid = MANAGED_PROFILE_UID; |
| setupTestCase(); |
| WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, |
| mMockContext, mMockUserManager, mWifiInjector); |
| try { |
| codeUnderTest.enforceCanAccessScanResultsForWifiScanner(TEST_PACKAGE_NAME, |
| TEST_FEATURE_ID, mUid, CHECK_LOCATION_SETTINGS, DONT_HIDE_FROM_APP_OPS); |
| fail("Expected SecurityException is not thrown"); |
| } catch (SecurityException e) { |
| } |
| } |
| |
| /** |
| * Test case setting: Package is valid |
| * Location Mode Enabled |
| * Fine Location Access |
| * This App has permission to request WIFI_SCAN |
| * Validate that a SecurityException is thrown |
| * - Doesn't have fine location app-ops. |
| */ |
| @Test |
| public void testCannotAccessScanResultsForWifiScanner_NoFineLocationAppOps() throws Exception { |
| mThrowSecurityException = false; |
| mIsLocationEnabled = true; |
| mFineLocationPermission = PackageManager.PERMISSION_GRANTED; |
| mHardwareLocationPermission = PackageManager.PERMISSION_GRANTED; |
| mAllowFineLocationApps = AppOpsManager.MODE_IGNORED; |
| mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; |
| mUid = MANAGED_PROFILE_UID; |
| setupTestCase(); |
| WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, |
| mMockContext, mMockUserManager, mWifiInjector); |
| try { |
| codeUnderTest.enforceCanAccessScanResultsForWifiScanner(TEST_PACKAGE_NAME, |
| TEST_FEATURE_ID, mUid, CHECK_LOCATION_SETTINGS, DONT_HIDE_FROM_APP_OPS); |
| fail("Expected SecurityException is not thrown"); |
| } catch (SecurityException e) { |
| } |
| } |
| |
| /** |
| * Test case setting: Package is valid |
| * Location Mode Enabled |
| * Location hardware Access |
| * This App has permission to request WIFI_SCAN |
| * Validate that a SecurityException is thrown |
| * - Doesn't have hardware location permission. |
| */ |
| @Test |
| public void testCannotAccessScanResultsForWifiScanner_NoHardwareLocationPermission() |
| throws Exception { |
| mThrowSecurityException = false; |
| mIsLocationEnabled = true; |
| mFineLocationPermission = PackageManager.PERMISSION_GRANTED; |
| mHardwareLocationPermission = PackageManager.PERMISSION_DENIED; |
| mAllowFineLocationApps = AppOpsManager.MODE_ALLOWED; |
| mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; |
| mUid = MANAGED_PROFILE_UID; |
| setupTestCase(); |
| WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, |
| mMockContext, mMockUserManager, mWifiInjector); |
| try { |
| codeUnderTest.enforceCanAccessScanResultsForWifiScanner(TEST_PACKAGE_NAME, |
| TEST_FEATURE_ID, mUid, CHECK_LOCATION_SETTINGS, DONT_HIDE_FROM_APP_OPS); |
| fail("Expected SecurityException is not thrown"); |
| } catch (SecurityException e) { |
| } |
| } |
| |
| /** |
| * Test case setting: Package is valid |
| * Location Mode Enabled |
| * Fine Location Access |
| * Location hardware Access |
| * Validate that a SecurityException is thrown |
| * - This App does not have permission to request WIFI_SCAN. |
| */ |
| @Test |
| public void testCannotAccessScanResultsForWifiScanner_NoWifiScanAppOps() throws Exception { |
| mThrowSecurityException = false; |
| mIsLocationEnabled = true; |
| mFineLocationPermission = PackageManager.PERMISSION_GRANTED; |
| mHardwareLocationPermission = PackageManager.PERMISSION_GRANTED; |
| mAllowFineLocationApps = AppOpsManager.MODE_ALLOWED; |
| mWifiScanAllowApps = AppOpsManager.MODE_IGNORED; |
| mUid = MANAGED_PROFILE_UID; |
| setupTestCase(); |
| WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, |
| mMockContext, mMockUserManager, mWifiInjector); |
| try { |
| codeUnderTest.enforceCanAccessScanResultsForWifiScanner(TEST_PACKAGE_NAME, |
| TEST_FEATURE_ID, mUid, CHECK_LOCATION_SETTINGS, DONT_HIDE_FROM_APP_OPS); |
| fail("Expected SecurityException is not thrown"); |
| } catch (SecurityException e) { |
| } |
| } |
| |
| /** |
| * Test case setting: Package is valid |
| * Fine Location Access |
| * Location hardware Access |
| * This App has permission to request WIFI_SCAN |
| * Validate an Exception is thrown |
| * - Location is not enabled. |
| */ |
| @Test |
| public void testCannotAccessScanResultsForWifiScanner_LocationModeDisabled() throws Exception { |
| mThrowSecurityException = false; |
| mIsLocationEnabled = false; |
| mFineLocationPermission = PackageManager.PERMISSION_GRANTED; |
| mHardwareLocationPermission = PackageManager.PERMISSION_GRANTED; |
| mAllowFineLocationApps = AppOpsManager.MODE_ALLOWED; |
| mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; |
| mUid = MANAGED_PROFILE_UID; |
| setupTestCase(); |
| WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, |
| mMockContext, mMockUserManager, mWifiInjector); |
| try { |
| codeUnderTest.enforceCanAccessScanResultsForWifiScanner(TEST_PACKAGE_NAME, |
| TEST_FEATURE_ID, mUid, CHECK_LOCATION_SETTINGS, DONT_HIDE_FROM_APP_OPS); |
| fail("Expected SecurityException is not thrown"); |
| } catch (SecurityException e) { |
| } |
| } |
| |
| /** |
| * Test case setting: Package is valid |
| * Location Mode Disabled |
| * Fine Location Access |
| * Location hardware Access |
| * This App has permission to request WIFI_SCAN |
| * Validate no Exceptions are thrown - has all permissions & ignores location settings. |
| */ |
| @Test |
| public void testCannotAccessScanResultsForWifiScanner_IgnoreLocationSettings() |
| throws Exception { |
| mThrowSecurityException = false; |
| mIsLocationEnabled = false; |
| mFineLocationPermission = PackageManager.PERMISSION_GRANTED; |
| mHardwareLocationPermission = PackageManager.PERMISSION_GRANTED; |
| mAllowFineLocationApps = AppOpsManager.MODE_ALLOWED; |
| mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; |
| mUid = MANAGED_PROFILE_UID; |
| setupTestCase(); |
| WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, |
| mMockContext, mMockUserManager, mWifiInjector); |
| codeUnderTest.enforceCanAccessScanResultsForWifiScanner(TEST_PACKAGE_NAME, TEST_FEATURE_ID, |
| mUid, IGNORE_LOCATION_SETTINGS, DONT_HIDE_FROM_APP_OPS); |
| } |
| |
| /** |
| * Test case setting: Location Mode Enabled |
| * Fine Location Access |
| * Location hardware Access |
| * This App has permission to request WIFI_SCAN |
| * Validate an Exception is thrown |
| * - Invalid package name. |
| */ |
| @Test |
| public void testCannotAccessScanResultsForWifiScanner_InvalidPackage() throws Exception { |
| mThrowSecurityException = true; |
| mIsLocationEnabled = true; |
| mFineLocationPermission = PackageManager.PERMISSION_GRANTED; |
| mHardwareLocationPermission = PackageManager.PERMISSION_GRANTED; |
| mAllowFineLocationApps = AppOpsManager.MODE_ALLOWED; |
| mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED; |
| mUid = MANAGED_PROFILE_UID; |
| setupTestCase(); |
| WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, |
| mMockContext, mMockUserManager, mWifiInjector); |
| try { |
| codeUnderTest.enforceCanAccessScanResultsForWifiScanner(TEST_PACKAGE_NAME, |
| TEST_FEATURE_ID, mUid, CHECK_LOCATION_SETTINGS, DONT_HIDE_FROM_APP_OPS); |
| fail("Expected SecurityException is not thrown"); |
| } catch (SecurityException e) { |
| } |
| } |
| |
| /** |
| * Verify that we handle failures when trying to fetch location mode using LocationManager API. |
| * We should use the legacy setting to read the value if we encounter any failure. |
| */ |
| @Test |
| public void testIsLocationEnabledFallbackToLegacySetting() throws Exception { |
| mUid = OTHER_USER_UID; // do not really care about this value |
| setupTestCase(); |
| WifiPermissionsUtil codeUnderTest = new WifiPermissionsUtil(mMockPermissionsWrapper, |
| mMockContext, mMockUserManager, mWifiInjector); |
| doThrow(new RuntimeException()).when(mLocationManager).isLocationEnabledForUser(any()); |
| |
| when(mMockFrameworkFacade.getIntegerSetting( |
| any(Context.class), eq(Settings.Secure.LOCATION_MODE), anyInt())) |
| .thenReturn(Settings.Secure.LOCATION_MODE_OFF); |
| assertFalse(codeUnderTest.isLocationModeEnabled()); |
| |
| when(mMockFrameworkFacade.getIntegerSetting( |
| any(Context.class), eq(Settings.Secure.LOCATION_MODE), anyInt())) |
| .thenReturn(Settings.Secure.LOCATION_MODE_ON); |
| assertTrue(codeUnderTest.isLocationModeEnabled()); |
| |
| verify(mMockFrameworkFacade, times(2)).getIntegerSetting( |
| any(Context.class), eq(Settings.Secure.LOCATION_MODE), anyInt()); |
| } |
| |
| private Answer<Integer> createPermissionAnswer() { |
| return new Answer<Integer>() { |
| @Override |
| public Integer answer(InvocationOnMock invocation) { |
| int myUid = (int) invocation.getArguments()[1]; |
| String myPermission = (String) invocation.getArguments()[0]; |
| mPermissionsList.get(myPermission); |
| if (mPermissionsList.containsKey(myPermission)) { |
| int uid = mPermissionsList.get(myPermission); |
| if (myUid == uid) { |
| return PackageManager.PERMISSION_GRANTED; |
| } |
| } |
| return PackageManager.PERMISSION_DENIED; |
| } |
| }; |
| } |
| |
| private void setupMocks() throws Exception { |
| when(mMockPkgMgr.getApplicationInfoAsUser(eq(TEST_PACKAGE_NAME), eq(0), any())) |
| .thenReturn(mMockApplInfo); |
| when(mMockContext.createPackageContextAsUser(any(), anyInt(), any())) |
| .thenReturn(mMockContext); |
| if (SdkLevel.isAtLeastS()) { |
| when(mMockPkgMgr.getTargetSdkVersion(TEST_PACKAGE_NAME)) |
| .thenReturn(mMockApplInfo.targetSdkVersion); |
| } |
| when(mMockPkgMgr.getApplicationInfoAsUser(eq(TEST_PACKAGE_NAME), eq(0), any())) |
| .thenReturn(mMockApplInfo); |
| when(mMockContext.getPackageManager()).thenReturn(mMockPkgMgr); |
| when(mMockAppOps.noteOp(AppOpsManager.OPSTR_WIFI_SCAN, mUid, TEST_PACKAGE_NAME, |
| TEST_FEATURE_ID, null)).thenReturn(mWifiScanAllowApps); |
| when(mMockAppOps.noteOp(eq(AppOpsManager.OPSTR_COARSE_LOCATION), eq(mUid), |
| eq(TEST_PACKAGE_NAME), eq(TEST_FEATURE_ID), nullable(String.class))) |
| .thenReturn(mAllowCoarseLocationApps); |
| when(mMockAppOps.noteOp(eq(AppOpsManager.OPSTR_FINE_LOCATION), eq(mUid), |
| eq(TEST_PACKAGE_NAME), eq(TEST_FEATURE_ID), nullable(String.class))) |
| .thenReturn(mAllowFineLocationApps); |
| when(mMockAppOps.unsafeCheckOp(AppOpsManager.OPSTR_FINE_LOCATION, mUid, TEST_PACKAGE_NAME)) |
| .thenReturn(mAllowFineLocationApps); |
| if (mThrowSecurityException) { |
| doThrow(new SecurityException("Package " + TEST_PACKAGE_NAME + " doesn't belong" |
| + " to application bound to user " + mUid)) |
| .when(mMockAppOps).checkPackage(mUid, TEST_PACKAGE_NAME); |
| } |
| when(mMockContext.getSystemService(Context.APP_OPS_SERVICE)) |
| .thenReturn(mMockAppOps); |
| when(mMockContext.getContentResolver()).thenReturn(mMockContentResolver); |
| when(mMockContext.getSystemService(Context.USER_SERVICE)) |
| .thenReturn(mMockUserManager); |
| when(mWifiInjector.makeLog(anyString())).thenReturn(mWifiLog); |
| when(mWifiInjector.getFrameworkFacade()).thenReturn(mMockFrameworkFacade); |
| when(mMockContext.getSystemService(Context.LOCATION_SERVICE)).thenReturn(mLocationManager); |
| when(mMockContext.getPackageName()).thenReturn(TEST_WIFI_STACK_APK_NAME); |
| } |
| |
| private void initTestVars() { |
| mPermissionsList.clear(); |
| mReturnPermission = createPermissionAnswer(); |
| mWifiScanAllowApps = AppOpsManager.MODE_ERRORED; |
| mUid = OTHER_USER_UID; |
| mThrowSecurityException = true; |
| mMockApplInfo.targetSdkVersion = Build.VERSION_CODES.M; |
| mIsLocationEnabled = false; |
| mCurrentUser = UserHandle.USER_SYSTEM; |
| mCoarseLocationPermission = PackageManager.PERMISSION_DENIED; |
| mFineLocationPermission = PackageManager.PERMISSION_DENIED; |
| mAllowCoarseLocationApps = AppOpsManager.MODE_ERRORED; |
| mAllowFineLocationApps = AppOpsManager.MODE_ERRORED; |
| } |
| |
| private void setupMockInterface() { |
| BinderUtil.setUid(mUid); |
| doAnswer(mReturnPermission).when(mMockPermissionsWrapper).getUidPermission( |
| anyString(), anyInt()); |
| doAnswer(mReturnPermission).when(mMockPermissionsWrapper).getUidPermission( |
| anyString(), anyInt()); |
| when(mMockUserManager.isSameProfileGroup(UserHandle.SYSTEM, |
| UserHandle.getUserHandleForUid(MANAGED_PROFILE_UID))) |
| .thenReturn(true); |
| when(mMockPermissionsWrapper.getCurrentUser()).thenReturn(mCurrentUser); |
| when(mMockPermissionsWrapper.getUidPermission(mManifestStringCoarse, mUid)) |
| .thenReturn(mCoarseLocationPermission); |
| when(mMockPermissionsWrapper.getUidPermission(mManifestStringFine, mUid)) |
| .thenReturn(mFineLocationPermission); |
| when(mMockPermissionsWrapper.getUidPermission(mManifestStringHardware, mUid)) |
| .thenReturn(mHardwareLocationPermission); |
| when(mLocationManager.isLocationEnabledForUser(any())).thenReturn(mIsLocationEnabled); |
| } |
| } |